diff options
43 files changed, 1652 insertions, 768 deletions
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt index 89490beb3c0b..58e49042fc20 100644 --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt | |||
| @@ -66,11 +66,10 @@ All mesh wide settings can be found in batman's own interface | |||
| 66 | folder: | 66 | folder: |
| 67 | 67 | ||
| 68 | # ls /sys/class/net/bat0/mesh/ | 68 | # ls /sys/class/net/bat0/mesh/ |
| 69 | # aggregated_ogms gw_bandwidth log_level | 69 | #aggregated_ogms distributed_arp_table gw_sel_class orig_interval |
| 70 | # ap_isolation gw_mode orig_interval | 70 | #ap_isolation fragmentation hop_penalty routing_algo |
| 71 | # bonding gw_sel_class routing_algo | 71 | #bonding gw_bandwidth isolation_mark vlan0 |
| 72 | # bridge_loop_avoidance hop_penalty fragmentation | 72 | #bridge_loop_avoidance gw_mode log_level |
| 73 | |||
| 74 | 73 | ||
| 75 | There is a special folder for debugging information: | 74 | There is a special folder for debugging information: |
| 76 | 75 | ||
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index fa780b76630e..2b2dc473e1f7 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | config BATMAN_ADV | 5 | config BATMAN_ADV |
| 6 | tristate "B.A.T.M.A.N. Advanced Meshing Protocol" | 6 | tristate "B.A.T.M.A.N. Advanced Meshing Protocol" |
| 7 | depends on NET | 7 | depends on NET |
| 8 | select CRC16 | ||
| 9 | select LIBCRC32C | 8 | select LIBCRC32C |
| 10 | default n | 9 | default n |
| 11 | help | 10 | help |
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index e5954152cfe0..42df18f877e9 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # | 1 | # |
| 2 | # Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 2 | # Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 3 | # | 3 | # |
| 4 | # Marek Lindner, Simon Wunderlich | 4 | # Marek Lindner, Simon Wunderlich |
| 5 | # | 5 | # |
diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h index 92435bfc7471..4e49666f8c65 100644 --- a/net/batman-adv/bat_algo.h +++ b/net/batman-adv/bat_algo.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 278d78bd7735..921ac20cf690 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -272,7 +272,14 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | |||
| 272 | if (!neigh_node) | 272 | if (!neigh_node) |
| 273 | goto out; | 273 | goto out; |
| 274 | 274 | ||
| 275 | spin_lock_init(&neigh_node->bat_iv.lq_update_lock); | 275 | if (!atomic_inc_not_zero(&hard_iface->refcount)) { |
| 276 | kfree(neigh_node); | ||
| 277 | neigh_node = NULL; | ||
| 278 | goto out; | ||
| 279 | } | ||
| 280 | |||
| 281 | neigh_node->orig_node = orig_neigh; | ||
| 282 | neigh_node->if_incoming = hard_iface; | ||
| 276 | 283 | ||
| 277 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 284 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 278 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | 285 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", |
| @@ -459,17 +466,9 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
| 459 | /* send a batman ogm packet */ | 466 | /* send a batman ogm packet */ |
| 460 | static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet) | 467 | static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet) |
| 461 | { | 468 | { |
| 462 | struct batadv_hard_iface *hard_iface; | ||
| 463 | struct net_device *soft_iface; | 469 | struct net_device *soft_iface; |
| 464 | struct batadv_priv *bat_priv; | 470 | struct batadv_priv *bat_priv; |
| 465 | struct batadv_hard_iface *primary_if = NULL; | 471 | struct batadv_hard_iface *primary_if = NULL; |
| 466 | struct batadv_ogm_packet *batadv_ogm_packet; | ||
| 467 | unsigned char directlink; | ||
| 468 | uint8_t *packet_pos; | ||
| 469 | |||
| 470 | packet_pos = forw_packet->skb->data; | ||
| 471 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; | ||
| 472 | directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0); | ||
| 473 | 472 | ||
| 474 | if (!forw_packet->if_incoming) { | 473 | if (!forw_packet->if_incoming) { |
| 475 | pr_err("Error - can't forward packet: incoming iface not specified\n"); | 474 | pr_err("Error - can't forward packet: incoming iface not specified\n"); |
| @@ -479,59 +478,48 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet) | |||
| 479 | soft_iface = forw_packet->if_incoming->soft_iface; | 478 | soft_iface = forw_packet->if_incoming->soft_iface; |
| 480 | bat_priv = netdev_priv(soft_iface); | 479 | bat_priv = netdev_priv(soft_iface); |
| 481 | 480 | ||
| 482 | if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE) | 481 | if (WARN_ON(!forw_packet->if_outgoing)) |
| 483 | goto out; | 482 | goto out; |
| 484 | 483 | ||
| 485 | primary_if = batadv_primary_if_get_selected(bat_priv); | 484 | if (WARN_ON(forw_packet->if_outgoing->soft_iface != soft_iface)) |
| 486 | if (!primary_if) | ||
| 487 | goto out; | 485 | goto out; |
| 488 | 486 | ||
| 489 | /* multihomed peer assumed | 487 | if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE) |
| 490 | * non-primary OGMs are only broadcasted on their interface | ||
| 491 | */ | ||
| 492 | if ((directlink && (batadv_ogm_packet->ttl == 1)) || | ||
| 493 | (forw_packet->own && (forw_packet->if_incoming != primary_if))) { | ||
| 494 | /* FIXME: what about aggregated packets ? */ | ||
| 495 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 496 | "%s packet (originator %pM, seqno %u, TTL %d) on interface %s [%pM]\n", | ||
| 497 | (forw_packet->own ? "Sending own" : "Forwarding"), | ||
| 498 | batadv_ogm_packet->orig, | ||
| 499 | ntohl(batadv_ogm_packet->seqno), | ||
| 500 | batadv_ogm_packet->ttl, | ||
| 501 | forw_packet->if_incoming->net_dev->name, | ||
| 502 | forw_packet->if_incoming->net_dev->dev_addr); | ||
| 503 | |||
| 504 | /* skb is only used once and than forw_packet is free'd */ | ||
| 505 | batadv_send_skb_packet(forw_packet->skb, | ||
| 506 | forw_packet->if_incoming, | ||
| 507 | batadv_broadcast_addr); | ||
| 508 | forw_packet->skb = NULL; | ||
| 509 | |||
| 510 | goto out; | 488 | goto out; |
| 511 | } | ||
| 512 | 489 | ||
| 513 | /* broadcast on every interface */ | 490 | primary_if = batadv_primary_if_get_selected(bat_priv); |
| 514 | rcu_read_lock(); | 491 | if (!primary_if) |
| 515 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 492 | goto out; |
| 516 | if (hard_iface->soft_iface != soft_iface) | ||
| 517 | continue; | ||
| 518 | 493 | ||
| 519 | batadv_iv_ogm_send_to_if(forw_packet, hard_iface); | 494 | /* only for one specific outgoing interface */ |
| 520 | } | 495 | batadv_iv_ogm_send_to_if(forw_packet, forw_packet->if_outgoing); |
| 521 | rcu_read_unlock(); | ||
| 522 | 496 | ||
| 523 | out: | 497 | out: |
| 524 | if (primary_if) | 498 | if (primary_if) |
| 525 | batadv_hardif_free_ref(primary_if); | 499 | batadv_hardif_free_ref(primary_if); |
| 526 | } | 500 | } |
| 527 | 501 | ||
| 528 | /* return true if new_packet can be aggregated with forw_packet */ | 502 | /** |
| 503 | * batadv_iv_ogm_can_aggregate - find out if an OGM can be aggregated on an | ||
| 504 | * existing forward packet | ||
| 505 | * @new_bat_ogm_packet: OGM packet to be aggregated | ||
| 506 | * @bat_priv: the bat priv with all the soft interface information | ||
| 507 | * @packet_len: (total) length of the OGM | ||
| 508 | * @send_time: timestamp (jiffies) when the packet is to be sent | ||
| 509 | * @direktlink: true if this is a direct link packet | ||
| 510 | * @if_incoming: interface where the packet was received | ||
| 511 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 512 | * @forw_packet: the forwarded packet which should be checked | ||
| 513 | * | ||
| 514 | * Returns true if new_packet can be aggregated with forw_packet | ||
| 515 | */ | ||
| 529 | static bool | 516 | static bool |
| 530 | batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, | 517 | batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, |
| 531 | struct batadv_priv *bat_priv, | 518 | struct batadv_priv *bat_priv, |
| 532 | int packet_len, unsigned long send_time, | 519 | int packet_len, unsigned long send_time, |
| 533 | bool directlink, | 520 | bool directlink, |
| 534 | const struct batadv_hard_iface *if_incoming, | 521 | const struct batadv_hard_iface *if_incoming, |
| 522 | const struct batadv_hard_iface *if_outgoing, | ||
| 535 | const struct batadv_forw_packet *forw_packet) | 523 | const struct batadv_forw_packet *forw_packet) |
| 536 | { | 524 | { |
| 537 | struct batadv_ogm_packet *batadv_ogm_packet; | 525 | struct batadv_ogm_packet *batadv_ogm_packet; |
| @@ -565,6 +553,10 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, | |||
| 565 | if (!primary_if) | 553 | if (!primary_if) |
| 566 | goto out; | 554 | goto out; |
| 567 | 555 | ||
| 556 | /* packet is not leaving on the same interface. */ | ||
| 557 | if (forw_packet->if_outgoing != if_outgoing) | ||
| 558 | goto out; | ||
| 559 | |||
| 568 | /* packets without direct link flag and high TTL | 560 | /* packets without direct link flag and high TTL |
| 569 | * are flooded through the net | 561 | * are flooded through the net |
| 570 | */ | 562 | */ |
| @@ -606,11 +598,21 @@ out: | |||
| 606 | return res; | 598 | return res; |
| 607 | } | 599 | } |
| 608 | 600 | ||
| 609 | /* create a new aggregated packet and add this packet to it */ | 601 | /* batadv_iv_ogm_aggregate_new - create a new aggregated packet and add this |
| 602 | * packet to it. | ||
| 603 | * @packet_buff: pointer to the OGM | ||
| 604 | * @packet_len: (total) length of the OGM | ||
| 605 | * @send_time: timestamp (jiffies) when the packet is to be sent | ||
| 606 | * @direct_link: whether this OGM has direct link status | ||
| 607 | * @if_incoming: interface where the packet was received | ||
| 608 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 609 | * @own_packet: true if it is a self-generated ogm | ||
| 610 | */ | ||
| 610 | static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | 611 | static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, |
| 611 | int packet_len, unsigned long send_time, | 612 | int packet_len, unsigned long send_time, |
| 612 | bool direct_link, | 613 | bool direct_link, |
| 613 | struct batadv_hard_iface *if_incoming, | 614 | struct batadv_hard_iface *if_incoming, |
| 615 | struct batadv_hard_iface *if_outgoing, | ||
| 614 | int own_packet) | 616 | int own_packet) |
| 615 | { | 617 | { |
| 616 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 618 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| @@ -621,6 +623,9 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
| 621 | if (!atomic_inc_not_zero(&if_incoming->refcount)) | 623 | if (!atomic_inc_not_zero(&if_incoming->refcount)) |
| 622 | return; | 624 | return; |
| 623 | 625 | ||
| 626 | if (!atomic_inc_not_zero(&if_outgoing->refcount)) | ||
| 627 | goto out_free_incoming; | ||
| 628 | |||
| 624 | /* own packet should always be scheduled */ | 629 | /* own packet should always be scheduled */ |
| 625 | if (!own_packet) { | 630 | if (!own_packet) { |
| 626 | if (!batadv_atomic_dec_not_zero(&bat_priv->batman_queue_left)) { | 631 | if (!batadv_atomic_dec_not_zero(&bat_priv->batman_queue_left)) { |
| @@ -661,6 +666,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
| 661 | 666 | ||
| 662 | forw_packet_aggr->own = own_packet; | 667 | forw_packet_aggr->own = own_packet; |
| 663 | forw_packet_aggr->if_incoming = if_incoming; | 668 | forw_packet_aggr->if_incoming = if_incoming; |
| 669 | forw_packet_aggr->if_outgoing = if_outgoing; | ||
| 664 | forw_packet_aggr->num_packets = 0; | 670 | forw_packet_aggr->num_packets = 0; |
| 665 | forw_packet_aggr->direct_link_flags = BATADV_NO_FLAGS; | 671 | forw_packet_aggr->direct_link_flags = BATADV_NO_FLAGS; |
| 666 | forw_packet_aggr->send_time = send_time; | 672 | forw_packet_aggr->send_time = send_time; |
| @@ -683,6 +689,8 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, | |||
| 683 | 689 | ||
| 684 | return; | 690 | return; |
| 685 | out: | 691 | out: |
| 692 | batadv_hardif_free_ref(if_outgoing); | ||
| 693 | out_free_incoming: | ||
| 686 | batadv_hardif_free_ref(if_incoming); | 694 | batadv_hardif_free_ref(if_incoming); |
| 687 | } | 695 | } |
| 688 | 696 | ||
| @@ -706,10 +714,21 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr, | |||
| 706 | } | 714 | } |
| 707 | } | 715 | } |
| 708 | 716 | ||
| 717 | /** | ||
| 718 | * batadv_iv_ogm_queue_add - queue up an OGM for transmission | ||
| 719 | * @bat_priv: the bat priv with all the soft interface information | ||
| 720 | * @packet_buff: pointer to the OGM | ||
| 721 | * @packet_len: (total) length of the OGM | ||
| 722 | * @if_incoming: interface where the packet was received | ||
| 723 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 724 | * @own_packet: true if it is a self-generated ogm | ||
| 725 | * @send_time: timestamp (jiffies) when the packet is to be sent | ||
| 726 | */ | ||
| 709 | static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, | 727 | static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, |
| 710 | unsigned char *packet_buff, | 728 | unsigned char *packet_buff, |
| 711 | int packet_len, | 729 | int packet_len, |
| 712 | struct batadv_hard_iface *if_incoming, | 730 | struct batadv_hard_iface *if_incoming, |
| 731 | struct batadv_hard_iface *if_outgoing, | ||
| 713 | int own_packet, unsigned long send_time) | 732 | int own_packet, unsigned long send_time) |
| 714 | { | 733 | { |
| 715 | /* _aggr -> pointer to the packet we want to aggregate with | 734 | /* _aggr -> pointer to the packet we want to aggregate with |
| @@ -735,6 +754,7 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, | |||
| 735 | bat_priv, packet_len, | 754 | bat_priv, packet_len, |
| 736 | send_time, direct_link, | 755 | send_time, direct_link, |
| 737 | if_incoming, | 756 | if_incoming, |
| 757 | if_outgoing, | ||
| 738 | forw_packet_pos)) { | 758 | forw_packet_pos)) { |
| 739 | forw_packet_aggr = forw_packet_pos; | 759 | forw_packet_aggr = forw_packet_pos; |
| 740 | break; | 760 | break; |
| @@ -758,7 +778,8 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, | |||
| 758 | 778 | ||
| 759 | batadv_iv_ogm_aggregate_new(packet_buff, packet_len, | 779 | batadv_iv_ogm_aggregate_new(packet_buff, packet_len, |
| 760 | send_time, direct_link, | 780 | send_time, direct_link, |
| 761 | if_incoming, own_packet); | 781 | if_incoming, if_outgoing, |
| 782 | own_packet); | ||
| 762 | } else { | 783 | } else { |
| 763 | batadv_iv_ogm_aggregate(forw_packet_aggr, packet_buff, | 784 | batadv_iv_ogm_aggregate(forw_packet_aggr, packet_buff, |
| 764 | packet_len, direct_link); | 785 | packet_len, direct_link); |
| @@ -771,7 +792,8 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, | |||
| 771 | struct batadv_ogm_packet *batadv_ogm_packet, | 792 | struct batadv_ogm_packet *batadv_ogm_packet, |
| 772 | bool is_single_hop_neigh, | 793 | bool is_single_hop_neigh, |
| 773 | bool is_from_best_next_hop, | 794 | bool is_from_best_next_hop, |
| 774 | struct batadv_hard_iface *if_incoming) | 795 | struct batadv_hard_iface *if_incoming, |
| 796 | struct batadv_hard_iface *if_outgoing) | ||
| 775 | { | 797 | { |
| 776 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 798 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 777 | uint16_t tvlv_len; | 799 | uint16_t tvlv_len; |
| @@ -816,7 +838,8 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, | |||
| 816 | 838 | ||
| 817 | batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, | 839 | batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, |
| 818 | BATADV_OGM_HLEN + tvlv_len, | 840 | BATADV_OGM_HLEN + tvlv_len, |
| 819 | if_incoming, 0, batadv_iv_ogm_fwd_send_time()); | 841 | if_incoming, if_outgoing, 0, |
| 842 | batadv_iv_ogm_fwd_send_time()); | ||
| 820 | } | 843 | } |
| 821 | 844 | ||
| 822 | /** | 845 | /** |
| @@ -861,10 +884,11 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
| 861 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 884 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
| 862 | unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; | 885 | unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; |
| 863 | struct batadv_ogm_packet *batadv_ogm_packet; | 886 | struct batadv_ogm_packet *batadv_ogm_packet; |
| 864 | struct batadv_hard_iface *primary_if; | 887 | struct batadv_hard_iface *primary_if, *tmp_hard_iface; |
| 865 | int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; | 888 | int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; |
| 866 | uint32_t seqno; | 889 | uint32_t seqno; |
| 867 | uint16_t tvlv_len = 0; | 890 | uint16_t tvlv_len = 0; |
| 891 | unsigned long send_time; | ||
| 868 | 892 | ||
| 869 | primary_if = batadv_primary_if_get_selected(bat_priv); | 893 | primary_if = batadv_primary_if_get_selected(bat_priv); |
| 870 | 894 | ||
| @@ -887,23 +911,60 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
| 887 | atomic_inc(&hard_iface->bat_iv.ogm_seqno); | 911 | atomic_inc(&hard_iface->bat_iv.ogm_seqno); |
| 888 | 912 | ||
| 889 | batadv_iv_ogm_slide_own_bcast_window(hard_iface); | 913 | batadv_iv_ogm_slide_own_bcast_window(hard_iface); |
| 890 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, | ||
| 891 | hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, | ||
| 892 | batadv_iv_ogm_emit_send_time(bat_priv)); | ||
| 893 | 914 | ||
| 915 | send_time = batadv_iv_ogm_emit_send_time(bat_priv); | ||
| 916 | |||
| 917 | if (hard_iface != primary_if) { | ||
| 918 | /* OGMs from secondary interfaces are only scheduled on their | ||
| 919 | * respective interfaces. | ||
| 920 | */ | ||
| 921 | batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len, | ||
| 922 | hard_iface, hard_iface, 1, send_time); | ||
| 923 | goto out; | ||
| 924 | } | ||
| 925 | |||
| 926 | /* OGMs from primary interfaces are scheduled on all | ||
| 927 | * interfaces. | ||
| 928 | */ | ||
| 929 | rcu_read_lock(); | ||
| 930 | list_for_each_entry_rcu(tmp_hard_iface, &batadv_hardif_list, list) { | ||
| 931 | if (tmp_hard_iface->soft_iface != hard_iface->soft_iface) | ||
| 932 | continue; | ||
| 933 | batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, | ||
| 934 | *ogm_buff_len, hard_iface, | ||
| 935 | tmp_hard_iface, 1, send_time); | ||
| 936 | } | ||
| 937 | rcu_read_unlock(); | ||
| 938 | |||
| 939 | out: | ||
| 894 | if (primary_if) | 940 | if (primary_if) |
| 895 | batadv_hardif_free_ref(primary_if); | 941 | batadv_hardif_free_ref(primary_if); |
| 896 | } | 942 | } |
| 897 | 943 | ||
| 944 | /** | ||
| 945 | * batadv_iv_ogm_orig_update - use OGM to update corresponding data in an | ||
| 946 | * originator | ||
| 947 | * @bat_priv: the bat priv with all the soft interface information | ||
| 948 | * @orig_node: the orig node who originally emitted the ogm packet | ||
| 949 | * @orig_ifinfo: ifinfo for the outgoing interface of the orig_node | ||
| 950 | * @ethhdr: Ethernet header of the OGM | ||
| 951 | * @batadv_ogm_packet: the ogm packet | ||
| 952 | * @if_incoming: interface where the packet was received | ||
| 953 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 954 | * @dup_status: the duplicate status of this ogm packet. | ||
| 955 | */ | ||
| 898 | static void | 956 | static void |
| 899 | batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | 957 | batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, |
| 900 | struct batadv_orig_node *orig_node, | 958 | struct batadv_orig_node *orig_node, |
| 959 | struct batadv_orig_ifinfo *orig_ifinfo, | ||
| 901 | const struct ethhdr *ethhdr, | 960 | const struct ethhdr *ethhdr, |
| 902 | const struct batadv_ogm_packet *batadv_ogm_packet, | 961 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 903 | struct batadv_hard_iface *if_incoming, | 962 | struct batadv_hard_iface *if_incoming, |
| 904 | const unsigned char *tt_buff, | 963 | struct batadv_hard_iface *if_outgoing, |
| 905 | enum batadv_dup_status dup_status) | 964 | enum batadv_dup_status dup_status) |
| 906 | { | 965 | { |
| 966 | struct batadv_neigh_ifinfo *neigh_ifinfo = NULL; | ||
| 967 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 907 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 968 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
| 908 | struct batadv_neigh_node *router = NULL; | 969 | struct batadv_neigh_node *router = NULL; |
| 909 | struct batadv_orig_node *orig_node_tmp; | 970 | struct batadv_orig_node *orig_node_tmp; |
| @@ -931,12 +992,21 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 931 | if (dup_status != BATADV_NO_DUP) | 992 | if (dup_status != BATADV_NO_DUP) |
| 932 | continue; | 993 | continue; |
| 933 | 994 | ||
| 934 | spin_lock_bh(&tmp_neigh_node->bat_iv.lq_update_lock); | 995 | /* only update the entry for this outgoing interface */ |
| 935 | batadv_ring_buffer_set(tmp_neigh_node->bat_iv.tq_recv, | 996 | neigh_ifinfo = batadv_neigh_ifinfo_get(tmp_neigh_node, |
| 936 | &tmp_neigh_node->bat_iv.tq_index, 0); | 997 | if_outgoing); |
| 937 | tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->bat_iv.tq_recv); | 998 | if (!neigh_ifinfo) |
| 938 | tmp_neigh_node->bat_iv.tq_avg = tq_avg; | 999 | continue; |
| 939 | spin_unlock_bh(&tmp_neigh_node->bat_iv.lq_update_lock); | 1000 | |
| 1001 | spin_lock_bh(&tmp_neigh_node->ifinfo_lock); | ||
| 1002 | batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv, | ||
| 1003 | &neigh_ifinfo->bat_iv.tq_index, 0); | ||
| 1004 | tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv); | ||
| 1005 | neigh_ifinfo->bat_iv.tq_avg = tq_avg; | ||
| 1006 | spin_unlock_bh(&tmp_neigh_node->ifinfo_lock); | ||
| 1007 | |||
| 1008 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1009 | neigh_ifinfo = NULL; | ||
| 940 | } | 1010 | } |
| 941 | 1011 | ||
| 942 | if (!neigh_node) { | 1012 | if (!neigh_node) { |
| @@ -958,39 +1028,49 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 958 | "Updating existing last-hop neighbor of originator\n"); | 1028 | "Updating existing last-hop neighbor of originator\n"); |
| 959 | 1029 | ||
| 960 | rcu_read_unlock(); | 1030 | rcu_read_unlock(); |
| 1031 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); | ||
| 1032 | if (!neigh_ifinfo) | ||
| 1033 | goto out; | ||
| 961 | 1034 | ||
| 962 | neigh_node->last_seen = jiffies; | 1035 | neigh_node->last_seen = jiffies; |
| 963 | 1036 | ||
| 964 | spin_lock_bh(&neigh_node->bat_iv.lq_update_lock); | 1037 | spin_lock_bh(&neigh_node->ifinfo_lock); |
| 965 | batadv_ring_buffer_set(neigh_node->bat_iv.tq_recv, | 1038 | batadv_ring_buffer_set(neigh_ifinfo->bat_iv.tq_recv, |
| 966 | &neigh_node->bat_iv.tq_index, | 1039 | &neigh_ifinfo->bat_iv.tq_index, |
| 967 | batadv_ogm_packet->tq); | 1040 | batadv_ogm_packet->tq); |
| 968 | tq_avg = batadv_ring_buffer_avg(neigh_node->bat_iv.tq_recv); | 1041 | tq_avg = batadv_ring_buffer_avg(neigh_ifinfo->bat_iv.tq_recv); |
| 969 | neigh_node->bat_iv.tq_avg = tq_avg; | 1042 | neigh_ifinfo->bat_iv.tq_avg = tq_avg; |
| 970 | spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock); | 1043 | spin_unlock_bh(&neigh_node->ifinfo_lock); |
| 971 | 1044 | ||
| 972 | if (dup_status == BATADV_NO_DUP) { | 1045 | if (dup_status == BATADV_NO_DUP) { |
| 973 | orig_node->last_ttl = batadv_ogm_packet->ttl; | 1046 | orig_ifinfo->last_ttl = batadv_ogm_packet->ttl; |
| 974 | neigh_node->last_ttl = batadv_ogm_packet->ttl; | 1047 | neigh_ifinfo->last_ttl = batadv_ogm_packet->ttl; |
| 975 | } | 1048 | } |
| 976 | 1049 | ||
| 977 | batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node); | ||
| 978 | |||
| 979 | /* if this neighbor already is our next hop there is nothing | 1050 | /* if this neighbor already is our next hop there is nothing |
| 980 | * to change | 1051 | * to change |
| 981 | */ | 1052 | */ |
| 982 | router = batadv_orig_node_get_router(orig_node); | 1053 | router = batadv_orig_router_get(orig_node, if_outgoing); |
| 983 | if (router == neigh_node) | 1054 | if (router == neigh_node) |
| 984 | goto out; | 1055 | goto out; |
| 985 | 1056 | ||
| 986 | /* if this neighbor does not offer a better TQ we won't consider it */ | 1057 | if (router) { |
| 987 | if (router && (router->bat_iv.tq_avg > neigh_node->bat_iv.tq_avg)) | 1058 | router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing); |
| 988 | goto out; | 1059 | if (!router_ifinfo) |
| 1060 | goto out; | ||
| 1061 | |||
| 1062 | /* if this neighbor does not offer a better TQ we won't | ||
| 1063 | * consider it | ||
| 1064 | */ | ||
| 1065 | if (router_ifinfo->bat_iv.tq_avg > neigh_ifinfo->bat_iv.tq_avg) | ||
| 1066 | goto out; | ||
| 1067 | } | ||
| 989 | 1068 | ||
| 990 | /* if the TQ is the same and the link not more symmetric we | 1069 | /* if the TQ is the same and the link not more symmetric we |
| 991 | * won't consider it either | 1070 | * won't consider it either |
| 992 | */ | 1071 | */ |
| 993 | if (router && (neigh_node->bat_iv.tq_avg == router->bat_iv.tq_avg)) { | 1072 | if (router_ifinfo && |
| 1073 | (neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg)) { | ||
| 994 | orig_node_tmp = router->orig_node; | 1074 | orig_node_tmp = router->orig_node; |
| 995 | spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock); | 1075 | spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock); |
| 996 | if_num = router->if_incoming->if_num; | 1076 | if_num = router->if_incoming->if_num; |
| @@ -1007,7 +1087,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 1007 | goto out; | 1087 | goto out; |
| 1008 | } | 1088 | } |
| 1009 | 1089 | ||
| 1010 | batadv_update_route(bat_priv, orig_node, neigh_node); | 1090 | batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node); |
| 1011 | goto out; | 1091 | goto out; |
| 1012 | 1092 | ||
| 1013 | unlock: | 1093 | unlock: |
| @@ -1017,20 +1097,37 @@ out: | |||
| 1017 | batadv_neigh_node_free_ref(neigh_node); | 1097 | batadv_neigh_node_free_ref(neigh_node); |
| 1018 | if (router) | 1098 | if (router) |
| 1019 | batadv_neigh_node_free_ref(router); | 1099 | batadv_neigh_node_free_ref(router); |
| 1100 | if (neigh_ifinfo) | ||
| 1101 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1102 | if (router_ifinfo) | ||
| 1103 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 1020 | } | 1104 | } |
| 1021 | 1105 | ||
| 1106 | /** | ||
| 1107 | * batadv_iv_ogm_calc_tq - calculate tq for current received ogm packet | ||
| 1108 | * @orig_node: the orig node who originally emitted the ogm packet | ||
| 1109 | * @orig_neigh_node: the orig node struct of the neighbor who sent the packet | ||
| 1110 | * @batadv_ogm_packet: the ogm packet | ||
| 1111 | * @if_incoming: interface where the packet was received | ||
| 1112 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 1113 | * | ||
| 1114 | * Returns 1 if the link can be considered bidirectional, 0 otherwise | ||
| 1115 | */ | ||
| 1022 | static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | 1116 | static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, |
| 1023 | struct batadv_orig_node *orig_neigh_node, | 1117 | struct batadv_orig_node *orig_neigh_node, |
| 1024 | struct batadv_ogm_packet *batadv_ogm_packet, | 1118 | struct batadv_ogm_packet *batadv_ogm_packet, |
| 1025 | struct batadv_hard_iface *if_incoming) | 1119 | struct batadv_hard_iface *if_incoming, |
| 1120 | struct batadv_hard_iface *if_outgoing) | ||
| 1026 | { | 1121 | { |
| 1027 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1122 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1028 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node; | 1123 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node; |
| 1124 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 1029 | uint8_t total_count; | 1125 | uint8_t total_count; |
| 1030 | uint8_t orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; | 1126 | uint8_t orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; |
| 1031 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; | 1127 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; |
| 1032 | int tq_asym_penalty, inv_asym_penalty, if_num, ret = 0; | 1128 | int tq_asym_penalty, inv_asym_penalty, if_num, ret = 0; |
| 1033 | unsigned int combined_tq; | 1129 | unsigned int combined_tq; |
| 1130 | int tq_iface_penalty; | ||
| 1034 | 1131 | ||
| 1035 | /* find corresponding one hop neighbor */ | 1132 | /* find corresponding one hop neighbor */ |
| 1036 | rcu_read_lock(); | 1133 | rcu_read_lock(); |
| @@ -1070,7 +1167,13 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | |||
| 1070 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1167 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1071 | if_num = if_incoming->if_num; | 1168 | if_num = if_incoming->if_num; |
| 1072 | orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num]; | 1169 | orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num]; |
| 1073 | neigh_rq_count = neigh_node->bat_iv.real_packet_count; | 1170 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); |
| 1171 | if (neigh_ifinfo) { | ||
| 1172 | neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count; | ||
| 1173 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1174 | } else { | ||
| 1175 | neigh_rq_count = 0; | ||
| 1176 | } | ||
| 1074 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1177 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1075 | 1178 | ||
| 1076 | /* pay attention to not get a value bigger than 100 % */ | 1179 | /* pay attention to not get a value bigger than 100 % */ |
| @@ -1106,15 +1209,31 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | |||
| 1106 | inv_asym_penalty /= neigh_rq_max_cube; | 1209 | inv_asym_penalty /= neigh_rq_max_cube; |
| 1107 | tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; | 1210 | tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; |
| 1108 | 1211 | ||
| 1109 | combined_tq = batadv_ogm_packet->tq * tq_own * tq_asym_penalty; | 1212 | /* penalize if the OGM is forwarded on the same interface. WiFi |
| 1110 | combined_tq /= BATADV_TQ_MAX_VALUE * BATADV_TQ_MAX_VALUE; | 1213 | * interfaces and other half duplex devices suffer from throughput |
| 1214 | * drops as they can't send and receive at the same time. | ||
| 1215 | */ | ||
| 1216 | tq_iface_penalty = BATADV_TQ_MAX_VALUE; | ||
| 1217 | if (if_outgoing && (if_incoming == if_outgoing) && | ||
| 1218 | batadv_is_wifi_netdev(if_outgoing->net_dev)) | ||
| 1219 | tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE, | ||
| 1220 | bat_priv); | ||
| 1221 | |||
| 1222 | combined_tq = batadv_ogm_packet->tq * | ||
| 1223 | tq_own * | ||
| 1224 | tq_asym_penalty * | ||
| 1225 | tq_iface_penalty; | ||
| 1226 | combined_tq /= BATADV_TQ_MAX_VALUE * | ||
| 1227 | BATADV_TQ_MAX_VALUE * | ||
| 1228 | BATADV_TQ_MAX_VALUE; | ||
| 1111 | batadv_ogm_packet->tq = combined_tq; | 1229 | batadv_ogm_packet->tq = combined_tq; |
| 1112 | 1230 | ||
| 1113 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1231 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1114 | "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i\n", | 1232 | "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n", |
| 1115 | orig_node->orig, orig_neigh_node->orig, total_count, | 1233 | orig_node->orig, orig_neigh_node->orig, total_count, |
| 1116 | neigh_rq_count, tq_own, | 1234 | neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty, |
| 1117 | tq_asym_penalty, batadv_ogm_packet->tq); | 1235 | batadv_ogm_packet->tq, if_incoming->net_dev->name, |
| 1236 | if_outgoing ? if_outgoing->net_dev->name : "DEFAULT"); | ||
| 1118 | 1237 | ||
| 1119 | /* if link has the minimum required transmission quality | 1238 | /* if link has the minimum required transmission quality |
| 1120 | * consider it bidirectional | 1239 | * consider it bidirectional |
| @@ -1134,17 +1253,21 @@ out: | |||
| 1134 | * @ethhdr: ethernet header of the packet | 1253 | * @ethhdr: ethernet header of the packet |
| 1135 | * @batadv_ogm_packet: OGM packet to be considered | 1254 | * @batadv_ogm_packet: OGM packet to be considered |
| 1136 | * @if_incoming: interface on which the OGM packet was received | 1255 | * @if_incoming: interface on which the OGM packet was received |
| 1256 | * @if_outgoing: interface for which the retransmission should be considered | ||
| 1137 | * | 1257 | * |
| 1138 | * Returns duplicate status as enum batadv_dup_status | 1258 | * Returns duplicate status as enum batadv_dup_status |
| 1139 | */ | 1259 | */ |
| 1140 | static enum batadv_dup_status | 1260 | static enum batadv_dup_status |
| 1141 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | 1261 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, |
| 1142 | const struct batadv_ogm_packet *batadv_ogm_packet, | 1262 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 1143 | const struct batadv_hard_iface *if_incoming) | 1263 | const struct batadv_hard_iface *if_incoming, |
| 1264 | struct batadv_hard_iface *if_outgoing) | ||
| 1144 | { | 1265 | { |
| 1145 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1266 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1146 | struct batadv_orig_node *orig_node; | 1267 | struct batadv_orig_node *orig_node; |
| 1147 | struct batadv_neigh_node *tmp_neigh_node; | 1268 | struct batadv_orig_ifinfo *orig_ifinfo = NULL; |
| 1269 | struct batadv_neigh_node *neigh_node; | ||
| 1270 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 1148 | int is_dup; | 1271 | int is_dup; |
| 1149 | int32_t seq_diff; | 1272 | int32_t seq_diff; |
| 1150 | int need_update = 0; | 1273 | int need_update = 0; |
| @@ -1159,27 +1282,37 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 1159 | if (!orig_node) | 1282 | if (!orig_node) |
| 1160 | return BATADV_NO_DUP; | 1283 | return BATADV_NO_DUP; |
| 1161 | 1284 | ||
| 1285 | orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing); | ||
| 1286 | if (WARN_ON(!orig_ifinfo)) { | ||
| 1287 | batadv_orig_node_free_ref(orig_node); | ||
| 1288 | return 0; | ||
| 1289 | } | ||
| 1290 | |||
| 1162 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1291 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1163 | seq_diff = seqno - orig_node->last_real_seqno; | 1292 | seq_diff = seqno - orig_ifinfo->last_real_seqno; |
| 1164 | 1293 | ||
| 1165 | /* signalize caller that the packet is to be dropped. */ | 1294 | /* signalize caller that the packet is to be dropped. */ |
| 1166 | if (!hlist_empty(&orig_node->neigh_list) && | 1295 | if (!hlist_empty(&orig_node->neigh_list) && |
| 1167 | batadv_window_protected(bat_priv, seq_diff, | 1296 | batadv_window_protected(bat_priv, seq_diff, |
| 1168 | &orig_node->batman_seqno_reset)) { | 1297 | &orig_ifinfo->batman_seqno_reset)) { |
| 1169 | ret = BATADV_PROTECTED; | 1298 | ret = BATADV_PROTECTED; |
| 1170 | goto out; | 1299 | goto out; |
| 1171 | } | 1300 | } |
| 1172 | 1301 | ||
| 1173 | rcu_read_lock(); | 1302 | rcu_read_lock(); |
| 1174 | hlist_for_each_entry_rcu(tmp_neigh_node, | 1303 | hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) { |
| 1175 | &orig_node->neigh_list, list) { | 1304 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, |
| 1176 | neigh_addr = tmp_neigh_node->addr; | 1305 | if_outgoing); |
| 1177 | is_dup = batadv_test_bit(tmp_neigh_node->bat_iv.real_bits, | 1306 | if (!neigh_ifinfo) |
| 1178 | orig_node->last_real_seqno, | 1307 | continue; |
| 1308 | |||
| 1309 | neigh_addr = neigh_node->addr; | ||
| 1310 | is_dup = batadv_test_bit(neigh_ifinfo->bat_iv.real_bits, | ||
| 1311 | orig_ifinfo->last_real_seqno, | ||
| 1179 | seqno); | 1312 | seqno); |
| 1180 | 1313 | ||
| 1181 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && | 1314 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && |
| 1182 | tmp_neigh_node->if_incoming == if_incoming) { | 1315 | neigh_node->if_incoming == if_incoming) { |
| 1183 | set_mark = 1; | 1316 | set_mark = 1; |
| 1184 | if (is_dup) | 1317 | if (is_dup) |
| 1185 | ret = BATADV_NEIGH_DUP; | 1318 | ret = BATADV_NEIGH_DUP; |
| @@ -1190,173 +1323,78 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 1190 | } | 1323 | } |
| 1191 | 1324 | ||
| 1192 | /* if the window moved, set the update flag. */ | 1325 | /* if the window moved, set the update flag. */ |
| 1193 | bitmap = tmp_neigh_node->bat_iv.real_bits; | 1326 | bitmap = neigh_ifinfo->bat_iv.real_bits; |
| 1194 | need_update |= batadv_bit_get_packet(bat_priv, bitmap, | 1327 | need_update |= batadv_bit_get_packet(bat_priv, bitmap, |
| 1195 | seq_diff, set_mark); | 1328 | seq_diff, set_mark); |
| 1196 | 1329 | ||
| 1197 | packet_count = bitmap_weight(tmp_neigh_node->bat_iv.real_bits, | 1330 | packet_count = bitmap_weight(bitmap, |
| 1198 | BATADV_TQ_LOCAL_WINDOW_SIZE); | 1331 | BATADV_TQ_LOCAL_WINDOW_SIZE); |
| 1199 | tmp_neigh_node->bat_iv.real_packet_count = packet_count; | 1332 | neigh_ifinfo->bat_iv.real_packet_count = packet_count; |
| 1333 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
| 1200 | } | 1334 | } |
| 1201 | rcu_read_unlock(); | 1335 | rcu_read_unlock(); |
| 1202 | 1336 | ||
| 1203 | if (need_update) { | 1337 | if (need_update) { |
| 1204 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1338 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1205 | "updating last_seqno: old %u, new %u\n", | 1339 | "%s updating last_seqno: old %u, new %u\n", |
| 1206 | orig_node->last_real_seqno, seqno); | 1340 | if_outgoing ? if_outgoing->net_dev->name : "DEFAULT", |
| 1207 | orig_node->last_real_seqno = seqno; | 1341 | orig_ifinfo->last_real_seqno, seqno); |
| 1342 | orig_ifinfo->last_real_seqno = seqno; | ||
| 1208 | } | 1343 | } |
| 1209 | 1344 | ||
| 1210 | out: | 1345 | out: |
| 1211 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 1346 | spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
| 1212 | batadv_orig_node_free_ref(orig_node); | 1347 | batadv_orig_node_free_ref(orig_node); |
| 1348 | if (orig_ifinfo) | ||
| 1349 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 1213 | return ret; | 1350 | return ret; |
| 1214 | } | 1351 | } |
| 1215 | 1352 | ||
| 1216 | static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | 1353 | |
| 1217 | struct batadv_ogm_packet *batadv_ogm_packet, | 1354 | /** |
| 1218 | const unsigned char *tt_buff, | 1355 | * batadv_iv_ogm_process_per_outif - process a batman iv OGM for an outgoing if |
| 1219 | struct batadv_hard_iface *if_incoming) | 1356 | * @skb: the skb containing the OGM |
| 1357 | * @orig_node: the (cached) orig node for the originator of this OGM | ||
| 1358 | * @if_incoming: the interface where this packet was received | ||
| 1359 | * @if_outgoing: the interface for which the packet should be considered | ||
| 1360 | */ | ||
| 1361 | static void | ||
| 1362 | batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset, | ||
| 1363 | struct batadv_orig_node *orig_node, | ||
| 1364 | struct batadv_hard_iface *if_incoming, | ||
| 1365 | struct batadv_hard_iface *if_outgoing) | ||
| 1220 | { | 1366 | { |
| 1221 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1367 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1222 | struct batadv_hard_iface *hard_iface; | ||
| 1223 | struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp; | ||
| 1224 | struct batadv_neigh_node *router = NULL, *router_router = NULL; | 1368 | struct batadv_neigh_node *router = NULL, *router_router = NULL; |
| 1369 | struct batadv_orig_node *orig_neigh_node; | ||
| 1370 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
| 1225 | struct batadv_neigh_node *orig_neigh_router = NULL; | 1371 | struct batadv_neigh_node *orig_neigh_router = NULL; |
| 1226 | int has_directlink_flag; | 1372 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; |
| 1227 | int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 1373 | struct batadv_ogm_packet *ogm_packet; |
| 1228 | int is_bidirect; | ||
| 1229 | bool is_single_hop_neigh = false; | ||
| 1230 | bool is_from_best_next_hop = false; | ||
| 1231 | int sameseq, similar_ttl; | ||
| 1232 | enum batadv_dup_status dup_status; | 1374 | enum batadv_dup_status dup_status; |
| 1233 | uint32_t if_incoming_seqno; | 1375 | bool is_from_best_next_hop = false; |
| 1376 | bool is_single_hop_neigh = false; | ||
| 1377 | bool sameseq, similar_ttl; | ||
| 1378 | struct sk_buff *skb_priv; | ||
| 1379 | struct ethhdr *ethhdr; | ||
| 1234 | uint8_t *prev_sender; | 1380 | uint8_t *prev_sender; |
| 1381 | int is_bidirect; | ||
| 1235 | 1382 | ||
| 1236 | /* Silently drop when the batman packet is actually not a | 1383 | /* create a private copy of the skb, as some functions change tq value |
| 1237 | * correct packet. | 1384 | * and/or flags. |
| 1238 | * | ||
| 1239 | * This might happen if a packet is padded (e.g. Ethernet has a | ||
| 1240 | * minimum frame length of 64 byte) and the aggregation interprets | ||
| 1241 | * it as an additional length. | ||
| 1242 | * | ||
| 1243 | * TODO: A more sane solution would be to have a bit in the | ||
| 1244 | * batadv_ogm_packet to detect whether the packet is the last | ||
| 1245 | * packet in an aggregation. Here we expect that the padding | ||
| 1246 | * is always zero (or not 0x01) | ||
| 1247 | */ | 1385 | */ |
| 1248 | if (batadv_ogm_packet->packet_type != BATADV_IV_OGM) | 1386 | skb_priv = skb_copy(skb, GFP_ATOMIC); |
| 1387 | if (!skb_priv) | ||
| 1249 | return; | 1388 | return; |
| 1250 | 1389 | ||
| 1251 | /* could be changed by schedule_own_packet() */ | 1390 | ethhdr = eth_hdr(skb_priv); |
| 1252 | if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno); | 1391 | ogm_packet = (struct batadv_ogm_packet *)(skb_priv->data + ogm_offset); |
| 1253 | |||
| 1254 | if (batadv_ogm_packet->flags & BATADV_DIRECTLINK) | ||
| 1255 | has_directlink_flag = 1; | ||
| 1256 | else | ||
| 1257 | has_directlink_flag = 0; | ||
| 1258 | 1392 | ||
| 1259 | if (batadv_compare_eth(ethhdr->h_source, batadv_ogm_packet->orig)) | 1393 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, ogm_packet, |
| 1394 | if_incoming, if_outgoing); | ||
| 1395 | if (batadv_compare_eth(ethhdr->h_source, ogm_packet->orig)) | ||
| 1260 | is_single_hop_neigh = true; | 1396 | is_single_hop_neigh = true; |
| 1261 | 1397 | ||
| 1262 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1263 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n", | ||
| 1264 | ethhdr->h_source, if_incoming->net_dev->name, | ||
| 1265 | if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig, | ||
| 1266 | batadv_ogm_packet->prev_sender, | ||
| 1267 | ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq, | ||
| 1268 | batadv_ogm_packet->ttl, | ||
| 1269 | batadv_ogm_packet->version, has_directlink_flag); | ||
| 1270 | |||
| 1271 | rcu_read_lock(); | ||
| 1272 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | ||
| 1273 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | ||
| 1274 | continue; | ||
| 1275 | |||
| 1276 | if (hard_iface->soft_iface != if_incoming->soft_iface) | ||
| 1277 | continue; | ||
| 1278 | |||
| 1279 | if (batadv_compare_eth(ethhdr->h_source, | ||
| 1280 | hard_iface->net_dev->dev_addr)) | ||
| 1281 | is_my_addr = 1; | ||
| 1282 | |||
| 1283 | if (batadv_compare_eth(batadv_ogm_packet->orig, | ||
| 1284 | hard_iface->net_dev->dev_addr)) | ||
| 1285 | is_my_orig = 1; | ||
| 1286 | |||
| 1287 | if (batadv_compare_eth(batadv_ogm_packet->prev_sender, | ||
| 1288 | hard_iface->net_dev->dev_addr)) | ||
| 1289 | is_my_oldorig = 1; | ||
| 1290 | } | ||
| 1291 | rcu_read_unlock(); | ||
| 1292 | |||
| 1293 | if (is_my_addr) { | ||
| 1294 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1295 | "Drop packet: received my own broadcast (sender: %pM)\n", | ||
| 1296 | ethhdr->h_source); | ||
| 1297 | return; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | if (is_my_orig) { | ||
| 1301 | unsigned long *word; | ||
| 1302 | int offset; | ||
| 1303 | int32_t bit_pos; | ||
| 1304 | int16_t if_num; | ||
| 1305 | uint8_t *weight; | ||
| 1306 | |||
| 1307 | orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv, | ||
| 1308 | ethhdr->h_source); | ||
| 1309 | if (!orig_neigh_node) | ||
| 1310 | return; | ||
| 1311 | |||
| 1312 | /* neighbor has to indicate direct link and it has to | ||
| 1313 | * come via the corresponding interface | ||
| 1314 | * save packet seqno for bidirectional check | ||
| 1315 | */ | ||
| 1316 | if (has_directlink_flag && | ||
| 1317 | batadv_compare_eth(if_incoming->net_dev->dev_addr, | ||
| 1318 | batadv_ogm_packet->orig)) { | ||
| 1319 | if_num = if_incoming->if_num; | ||
| 1320 | offset = if_num * BATADV_NUM_WORDS; | ||
| 1321 | |||
| 1322 | spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); | ||
| 1323 | word = &(orig_neigh_node->bat_iv.bcast_own[offset]); | ||
| 1324 | bit_pos = if_incoming_seqno - 2; | ||
| 1325 | bit_pos -= ntohl(batadv_ogm_packet->seqno); | ||
| 1326 | batadv_set_bit(word, bit_pos); | ||
| 1327 | weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num]; | ||
| 1328 | *weight = bitmap_weight(word, | ||
| 1329 | BATADV_TQ_LOCAL_WINDOW_SIZE); | ||
| 1330 | spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1334 | "Drop packet: originator packet from myself (via neighbor)\n"); | ||
| 1335 | batadv_orig_node_free_ref(orig_neigh_node); | ||
| 1336 | return; | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | if (is_my_oldorig) { | ||
| 1340 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1341 | "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n", | ||
| 1342 | ethhdr->h_source); | ||
| 1343 | return; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | if (batadv_ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) { | ||
| 1347 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1348 | "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n", | ||
| 1349 | ethhdr->h_source); | ||
| 1350 | return; | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | orig_node = batadv_iv_ogm_orig_get(bat_priv, batadv_ogm_packet->orig); | ||
| 1354 | if (!orig_node) | ||
| 1355 | return; | ||
| 1356 | |||
| 1357 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, | ||
| 1358 | if_incoming); | ||
| 1359 | |||
| 1360 | if (dup_status == BATADV_PROTECTED) { | 1398 | if (dup_status == BATADV_PROTECTED) { |
| 1361 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1399 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1362 | "Drop packet: packet within seqno protection time (sender: %pM)\n", | 1400 | "Drop packet: packet within seqno protection time (sender: %pM)\n", |
| @@ -1364,27 +1402,28 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1364 | goto out; | 1402 | goto out; |
| 1365 | } | 1403 | } |
| 1366 | 1404 | ||
| 1367 | if (batadv_ogm_packet->tq == 0) { | 1405 | if (ogm_packet->tq == 0) { |
| 1368 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1406 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1369 | "Drop packet: originator packet with tq equal 0\n"); | 1407 | "Drop packet: originator packet with tq equal 0\n"); |
| 1370 | goto out; | 1408 | goto out; |
| 1371 | } | 1409 | } |
| 1372 | 1410 | ||
| 1373 | router = batadv_orig_node_get_router(orig_node); | 1411 | router = batadv_orig_router_get(orig_node, if_outgoing); |
| 1374 | if (router) { | 1412 | if (router) { |
| 1375 | orig_node_tmp = router->orig_node; | 1413 | router_router = batadv_orig_router_get(router->orig_node, |
| 1376 | router_router = batadv_orig_node_get_router(orig_node_tmp); | 1414 | if_outgoing); |
| 1415 | router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing); | ||
| 1377 | } | 1416 | } |
| 1378 | 1417 | ||
| 1379 | if ((router && router->bat_iv.tq_avg != 0) && | 1418 | if ((router_ifinfo && router_ifinfo->bat_iv.tq_avg != 0) && |
| 1380 | (batadv_compare_eth(router->addr, ethhdr->h_source))) | 1419 | (batadv_compare_eth(router->addr, ethhdr->h_source))) |
| 1381 | is_from_best_next_hop = true; | 1420 | is_from_best_next_hop = true; |
| 1382 | 1421 | ||
| 1383 | prev_sender = batadv_ogm_packet->prev_sender; | 1422 | prev_sender = ogm_packet->prev_sender; |
| 1384 | /* avoid temporary routing loops */ | 1423 | /* avoid temporary routing loops */ |
| 1385 | if (router && router_router && | 1424 | if (router && router_router && |
| 1386 | (batadv_compare_eth(router->addr, prev_sender)) && | 1425 | (batadv_compare_eth(router->addr, prev_sender)) && |
| 1387 | !(batadv_compare_eth(batadv_ogm_packet->orig, prev_sender)) && | 1426 | !(batadv_compare_eth(ogm_packet->orig, prev_sender)) && |
| 1388 | (batadv_compare_eth(router->addr, router_router->addr))) { | 1427 | (batadv_compare_eth(router->addr, router_router->addr))) { |
| 1389 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1428 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1390 | "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM)\n", | 1429 | "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM)\n", |
| @@ -1392,7 +1431,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1392 | goto out; | 1431 | goto out; |
| 1393 | } | 1432 | } |
| 1394 | 1433 | ||
| 1395 | batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node); | 1434 | if (if_outgoing == BATADV_IF_DEFAULT) |
| 1435 | batadv_tvlv_ogm_receive(bat_priv, ogm_packet, orig_node); | ||
| 1396 | 1436 | ||
| 1397 | /* if sender is a direct neighbor the sender mac equals | 1437 | /* if sender is a direct neighbor the sender mac equals |
| 1398 | * originator mac | 1438 | * originator mac |
| @@ -1408,9 +1448,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1408 | 1448 | ||
| 1409 | /* Update nc_nodes of the originator */ | 1449 | /* Update nc_nodes of the originator */ |
| 1410 | batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node, | 1450 | batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node, |
| 1411 | batadv_ogm_packet, is_single_hop_neigh); | 1451 | ogm_packet, is_single_hop_neigh); |
| 1412 | 1452 | ||
| 1413 | orig_neigh_router = batadv_orig_node_get_router(orig_neigh_node); | 1453 | orig_neigh_router = batadv_orig_router_get(orig_neigh_node, |
| 1454 | if_outgoing); | ||
| 1414 | 1455 | ||
| 1415 | /* drop packet if sender is not a direct neighbor and if we | 1456 | /* drop packet if sender is not a direct neighbor and if we |
| 1416 | * don't route towards it | 1457 | * don't route towards it |
| @@ -1422,28 +1463,48 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1422 | } | 1463 | } |
| 1423 | 1464 | ||
| 1424 | is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node, | 1465 | is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node, |
| 1425 | batadv_ogm_packet, if_incoming); | 1466 | ogm_packet, if_incoming, |
| 1426 | 1467 | if_outgoing); | |
| 1427 | batadv_bonding_save_primary(orig_node, orig_neigh_node, | ||
| 1428 | batadv_ogm_packet); | ||
| 1429 | 1468 | ||
| 1430 | /* update ranking if it is not a duplicate or has the same | 1469 | /* update ranking if it is not a duplicate or has the same |
| 1431 | * seqno and similar ttl as the non-duplicate | 1470 | * seqno and similar ttl as the non-duplicate |
| 1432 | */ | 1471 | */ |
| 1433 | sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); | 1472 | orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing); |
| 1434 | similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl; | 1473 | if (!orig_ifinfo) |
| 1474 | goto out_neigh; | ||
| 1475 | |||
| 1476 | sameseq = orig_ifinfo->last_real_seqno == ntohl(ogm_packet->seqno); | ||
| 1477 | similar_ttl = (orig_ifinfo->last_ttl - 3) <= ogm_packet->ttl; | ||
| 1478 | |||
| 1435 | if (is_bidirect && ((dup_status == BATADV_NO_DUP) || | 1479 | if (is_bidirect && ((dup_status == BATADV_NO_DUP) || |
| 1436 | (sameseq && similar_ttl))) | 1480 | (sameseq && similar_ttl))) { |
| 1437 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, | 1481 | batadv_iv_ogm_orig_update(bat_priv, orig_node, |
| 1438 | batadv_ogm_packet, if_incoming, | 1482 | orig_ifinfo, ethhdr, |
| 1439 | tt_buff, dup_status); | 1483 | ogm_packet, if_incoming, |
| 1484 | if_outgoing, dup_status); | ||
| 1485 | } | ||
| 1486 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 1487 | |||
| 1488 | /* only forward for specific interface, not for the default one. */ | ||
| 1489 | if (if_outgoing == BATADV_IF_DEFAULT) | ||
| 1490 | goto out_neigh; | ||
| 1440 | 1491 | ||
| 1441 | /* is single hop (direct) neighbor */ | 1492 | /* is single hop (direct) neighbor */ |
| 1442 | if (is_single_hop_neigh) { | 1493 | if (is_single_hop_neigh) { |
| 1494 | /* OGMs from secondary interfaces should only scheduled once | ||
| 1495 | * per interface where it has been received, not multiple times | ||
| 1496 | */ | ||
| 1497 | if ((ogm_packet->ttl <= 2) && | ||
| 1498 | (if_incoming != if_outgoing)) { | ||
| 1499 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1500 | "Drop packet: OGM from secondary interface and wrong outgoing interface\n"); | ||
| 1501 | goto out_neigh; | ||
| 1502 | } | ||
| 1443 | /* mark direct link on incoming interface */ | 1503 | /* mark direct link on incoming interface */ |
| 1444 | batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet, | 1504 | batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet, |
| 1445 | is_single_hop_neigh, | 1505 | is_single_hop_neigh, |
| 1446 | is_from_best_next_hop, if_incoming); | 1506 | is_from_best_next_hop, if_incoming, |
| 1507 | if_outgoing); | ||
| 1447 | 1508 | ||
| 1448 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1509 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1449 | "Forwarding packet: rebroadcast neighbor packet with direct link flag\n"); | 1510 | "Forwarding packet: rebroadcast neighbor packet with direct link flag\n"); |
| @@ -1465,9 +1526,9 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1465 | 1526 | ||
| 1466 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1527 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1467 | "Forwarding packet: rebroadcast originator packet\n"); | 1528 | "Forwarding packet: rebroadcast originator packet\n"); |
| 1468 | batadv_iv_ogm_forward(orig_node, ethhdr, batadv_ogm_packet, | 1529 | batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet, |
| 1469 | is_single_hop_neigh, is_from_best_next_hop, | 1530 | is_single_hop_neigh, is_from_best_next_hop, |
| 1470 | if_incoming); | 1531 | if_incoming, if_outgoing); |
| 1471 | 1532 | ||
| 1472 | out_neigh: | 1533 | out_neigh: |
| 1473 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 1534 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
| @@ -1480,6 +1541,165 @@ out: | |||
| 1480 | if (orig_neigh_router) | 1541 | if (orig_neigh_router) |
| 1481 | batadv_neigh_node_free_ref(orig_neigh_router); | 1542 | batadv_neigh_node_free_ref(orig_neigh_router); |
| 1482 | 1543 | ||
| 1544 | kfree_skb(skb_priv); | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | /** | ||
| 1548 | * batadv_iv_ogm_process - process an incoming batman iv OGM | ||
| 1549 | * @skb: the skb containing the OGM | ||
| 1550 | * @ogm_offset: offset to the OGM which should be processed (for aggregates) | ||
| 1551 | * @if_incoming: the interface where this packet was receved | ||
| 1552 | */ | ||
| 1553 | static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, | ||
| 1554 | struct batadv_hard_iface *if_incoming) | ||
| 1555 | { | ||
| 1556 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | ||
| 1557 | struct batadv_orig_node *orig_neigh_node, *orig_node; | ||
| 1558 | struct batadv_hard_iface *hard_iface; | ||
| 1559 | struct batadv_ogm_packet *ogm_packet; | ||
| 1560 | uint32_t if_incoming_seqno; | ||
| 1561 | bool has_directlink_flag; | ||
| 1562 | struct ethhdr *ethhdr; | ||
| 1563 | bool is_my_oldorig = false; | ||
| 1564 | bool is_my_addr = false; | ||
| 1565 | bool is_my_orig = false; | ||
| 1566 | |||
| 1567 | ogm_packet = (struct batadv_ogm_packet *)(skb->data + ogm_offset); | ||
| 1568 | ethhdr = eth_hdr(skb); | ||
| 1569 | |||
| 1570 | /* Silently drop when the batman packet is actually not a | ||
| 1571 | * correct packet. | ||
| 1572 | * | ||
| 1573 | * This might happen if a packet is padded (e.g. Ethernet has a | ||
| 1574 | * minimum frame length of 64 byte) and the aggregation interprets | ||
| 1575 | * it as an additional length. | ||
| 1576 | * | ||
| 1577 | * TODO: A more sane solution would be to have a bit in the | ||
| 1578 | * batadv_ogm_packet to detect whether the packet is the last | ||
| 1579 | * packet in an aggregation. Here we expect that the padding | ||
| 1580 | * is always zero (or not 0x01) | ||
| 1581 | */ | ||
| 1582 | if (ogm_packet->packet_type != BATADV_IV_OGM) | ||
| 1583 | return; | ||
| 1584 | |||
| 1585 | /* could be changed by schedule_own_packet() */ | ||
| 1586 | if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno); | ||
| 1587 | |||
| 1588 | if (ogm_packet->flags & BATADV_DIRECTLINK) | ||
| 1589 | has_directlink_flag = true; | ||
| 1590 | else | ||
| 1591 | has_directlink_flag = false; | ||
| 1592 | |||
| 1593 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1594 | "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n", | ||
| 1595 | ethhdr->h_source, if_incoming->net_dev->name, | ||
| 1596 | if_incoming->net_dev->dev_addr, ogm_packet->orig, | ||
| 1597 | ogm_packet->prev_sender, ntohl(ogm_packet->seqno), | ||
| 1598 | ogm_packet->tq, ogm_packet->ttl, | ||
| 1599 | ogm_packet->version, has_directlink_flag); | ||
| 1600 | |||
| 1601 | rcu_read_lock(); | ||
| 1602 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | ||
| 1603 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | ||
| 1604 | continue; | ||
| 1605 | |||
| 1606 | if (hard_iface->soft_iface != if_incoming->soft_iface) | ||
| 1607 | continue; | ||
| 1608 | |||
| 1609 | if (batadv_compare_eth(ethhdr->h_source, | ||
| 1610 | hard_iface->net_dev->dev_addr)) | ||
| 1611 | is_my_addr = true; | ||
| 1612 | |||
| 1613 | if (batadv_compare_eth(ogm_packet->orig, | ||
| 1614 | hard_iface->net_dev->dev_addr)) | ||
| 1615 | is_my_orig = true; | ||
| 1616 | |||
| 1617 | if (batadv_compare_eth(ogm_packet->prev_sender, | ||
| 1618 | hard_iface->net_dev->dev_addr)) | ||
| 1619 | is_my_oldorig = true; | ||
| 1620 | } | ||
| 1621 | rcu_read_unlock(); | ||
| 1622 | |||
| 1623 | if (is_my_addr) { | ||
| 1624 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1625 | "Drop packet: received my own broadcast (sender: %pM)\n", | ||
| 1626 | ethhdr->h_source); | ||
| 1627 | return; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | if (is_my_orig) { | ||
| 1631 | unsigned long *word; | ||
| 1632 | int offset; | ||
| 1633 | int32_t bit_pos; | ||
| 1634 | int16_t if_num; | ||
| 1635 | uint8_t *weight; | ||
| 1636 | |||
| 1637 | orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv, | ||
| 1638 | ethhdr->h_source); | ||
| 1639 | if (!orig_neigh_node) | ||
| 1640 | return; | ||
| 1641 | |||
| 1642 | /* neighbor has to indicate direct link and it has to | ||
| 1643 | * come via the corresponding interface | ||
| 1644 | * save packet seqno for bidirectional check | ||
| 1645 | */ | ||
| 1646 | if (has_directlink_flag && | ||
| 1647 | batadv_compare_eth(if_incoming->net_dev->dev_addr, | ||
| 1648 | ogm_packet->orig)) { | ||
| 1649 | if_num = if_incoming->if_num; | ||
| 1650 | offset = if_num * BATADV_NUM_WORDS; | ||
| 1651 | |||
| 1652 | spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); | ||
| 1653 | word = &(orig_neigh_node->bat_iv.bcast_own[offset]); | ||
| 1654 | bit_pos = if_incoming_seqno - 2; | ||
| 1655 | bit_pos -= ntohl(ogm_packet->seqno); | ||
| 1656 | batadv_set_bit(word, bit_pos); | ||
| 1657 | weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num]; | ||
| 1658 | *weight = bitmap_weight(word, | ||
| 1659 | BATADV_TQ_LOCAL_WINDOW_SIZE); | ||
| 1660 | spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1664 | "Drop packet: originator packet from myself (via neighbor)\n"); | ||
| 1665 | batadv_orig_node_free_ref(orig_neigh_node); | ||
| 1666 | return; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | if (is_my_oldorig) { | ||
| 1670 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1671 | "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n", | ||
| 1672 | ethhdr->h_source); | ||
| 1673 | return; | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | if (ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) { | ||
| 1677 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 1678 | "Drop packet: ignoring all packets not forwarded from the best next hop (sender: %pM)\n", | ||
| 1679 | ethhdr->h_source); | ||
| 1680 | return; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | orig_node = batadv_iv_ogm_orig_get(bat_priv, ogm_packet->orig); | ||
| 1684 | if (!orig_node) | ||
| 1685 | return; | ||
| 1686 | |||
| 1687 | batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node, | ||
| 1688 | if_incoming, BATADV_IF_DEFAULT); | ||
| 1689 | |||
| 1690 | rcu_read_lock(); | ||
| 1691 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | ||
| 1692 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | ||
| 1693 | continue; | ||
| 1694 | |||
| 1695 | if (hard_iface->soft_iface != bat_priv->soft_iface) | ||
| 1696 | continue; | ||
| 1697 | |||
| 1698 | batadv_iv_ogm_process_per_outif(skb, ogm_offset, orig_node, | ||
| 1699 | if_incoming, hard_iface); | ||
| 1700 | } | ||
| 1701 | rcu_read_unlock(); | ||
| 1702 | |||
| 1483 | batadv_orig_node_free_ref(orig_node); | 1703 | batadv_orig_node_free_ref(orig_node); |
| 1484 | } | 1704 | } |
| 1485 | 1705 | ||
| @@ -1487,11 +1707,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
| 1487 | struct batadv_hard_iface *if_incoming) | 1707 | struct batadv_hard_iface *if_incoming) |
| 1488 | { | 1708 | { |
| 1489 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1709 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 1490 | struct batadv_ogm_packet *batadv_ogm_packet; | 1710 | struct batadv_ogm_packet *ogm_packet; |
| 1491 | struct ethhdr *ethhdr; | ||
| 1492 | int buff_pos = 0, packet_len; | ||
| 1493 | unsigned char *tvlv_buff, *packet_buff; | ||
| 1494 | uint8_t *packet_pos; | 1711 | uint8_t *packet_pos; |
| 1712 | int ogm_offset; | ||
| 1495 | bool ret; | 1713 | bool ret; |
| 1496 | 1714 | ||
| 1497 | ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); | 1715 | ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); |
| @@ -1508,42 +1726,68 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
| 1508 | batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES, | 1726 | batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES, |
| 1509 | skb->len + ETH_HLEN); | 1727 | skb->len + ETH_HLEN); |
| 1510 | 1728 | ||
| 1511 | packet_len = skb_headlen(skb); | 1729 | ogm_offset = 0; |
| 1512 | ethhdr = eth_hdr(skb); | 1730 | ogm_packet = (struct batadv_ogm_packet *)skb->data; |
| 1513 | packet_buff = skb->data; | ||
| 1514 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff; | ||
| 1515 | 1731 | ||
| 1516 | /* unpack the aggregated packets and process them one by one */ | 1732 | /* unpack the aggregated packets and process them one by one */ |
| 1517 | while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, | 1733 | while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), |
| 1518 | batadv_ogm_packet->tvlv_len)) { | 1734 | ogm_packet->tvlv_len)) { |
| 1519 | tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; | 1735 | batadv_iv_ogm_process(skb, ogm_offset, if_incoming); |
| 1520 | 1736 | ||
| 1521 | batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, | 1737 | ogm_offset += BATADV_OGM_HLEN; |
| 1522 | tvlv_buff, if_incoming); | 1738 | ogm_offset += ntohs(ogm_packet->tvlv_len); |
| 1523 | 1739 | ||
| 1524 | buff_pos += BATADV_OGM_HLEN; | 1740 | packet_pos = skb->data + ogm_offset; |
| 1525 | buff_pos += ntohs(batadv_ogm_packet->tvlv_len); | 1741 | ogm_packet = (struct batadv_ogm_packet *)packet_pos; |
| 1526 | |||
| 1527 | packet_pos = packet_buff + buff_pos; | ||
| 1528 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; | ||
| 1529 | } | 1742 | } |
| 1530 | 1743 | ||
| 1531 | kfree_skb(skb); | 1744 | kfree_skb(skb); |
| 1532 | return NET_RX_SUCCESS; | 1745 | return NET_RX_SUCCESS; |
| 1533 | } | 1746 | } |
| 1534 | 1747 | ||
| 1748 | /* batadv_iv_ogm_orig_print_neigh - print neighbors for the originator table | ||
| 1749 | * @orig_node: the orig_node for which the neighbors are printed | ||
| 1750 | * @if_outgoing: outgoing interface for these entries | ||
| 1751 | * @seq: debugfs table seq_file struct | ||
| 1752 | * | ||
| 1753 | * Must be called while holding an rcu lock. | ||
| 1754 | */ | ||
| 1755 | static void | ||
| 1756 | batadv_iv_ogm_orig_print_neigh(struct batadv_orig_node *orig_node, | ||
| 1757 | struct batadv_hard_iface *if_outgoing, | ||
| 1758 | struct seq_file *seq) | ||
| 1759 | { | ||
| 1760 | struct batadv_neigh_node *neigh_node; | ||
| 1761 | struct batadv_neigh_ifinfo *n_ifinfo; | ||
| 1762 | |||
| 1763 | hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) { | ||
| 1764 | n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing); | ||
| 1765 | if (!n_ifinfo) | ||
| 1766 | continue; | ||
| 1767 | |||
| 1768 | seq_printf(seq, " %pM (%3i)", | ||
| 1769 | neigh_node->addr, | ||
| 1770 | n_ifinfo->bat_iv.tq_avg); | ||
| 1771 | |||
| 1772 | batadv_neigh_ifinfo_free_ref(n_ifinfo); | ||
| 1773 | } | ||
| 1774 | } | ||
| 1775 | |||
| 1535 | /** | 1776 | /** |
| 1536 | * batadv_iv_ogm_orig_print - print the originator table | 1777 | * batadv_iv_ogm_orig_print - print the originator table |
| 1537 | * @bat_priv: the bat priv with all the soft interface information | 1778 | * @bat_priv: the bat priv with all the soft interface information |
| 1538 | * @seq: debugfs table seq_file struct | 1779 | * @seq: debugfs table seq_file struct |
| 1780 | * @if_outgoing: the outgoing interface for which this should be printed | ||
| 1539 | */ | 1781 | */ |
| 1540 | static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | 1782 | static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, |
| 1541 | struct seq_file *seq) | 1783 | struct seq_file *seq, |
| 1784 | struct batadv_hard_iface *if_outgoing) | ||
| 1542 | { | 1785 | { |
| 1543 | struct batadv_neigh_node *neigh_node, *neigh_node_tmp; | 1786 | struct batadv_neigh_node *neigh_node; |
| 1544 | struct batadv_hashtable *hash = bat_priv->orig_hash; | 1787 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
| 1545 | int last_seen_msecs, last_seen_secs; | 1788 | int last_seen_msecs, last_seen_secs; |
| 1546 | struct batadv_orig_node *orig_node; | 1789 | struct batadv_orig_node *orig_node; |
| 1790 | struct batadv_neigh_ifinfo *n_ifinfo; | ||
| 1547 | unsigned long last_seen_jiffies; | 1791 | unsigned long last_seen_jiffies; |
| 1548 | struct hlist_head *head; | 1792 | struct hlist_head *head; |
| 1549 | int batman_count = 0; | 1793 | int batman_count = 0; |
| @@ -1558,11 +1802,17 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | |||
| 1558 | 1802 | ||
| 1559 | rcu_read_lock(); | 1803 | rcu_read_lock(); |
| 1560 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { | 1804 | hlist_for_each_entry_rcu(orig_node, head, hash_entry) { |
| 1561 | neigh_node = batadv_orig_node_get_router(orig_node); | 1805 | neigh_node = batadv_orig_router_get(orig_node, |
| 1806 | if_outgoing); | ||
| 1562 | if (!neigh_node) | 1807 | if (!neigh_node) |
| 1563 | continue; | 1808 | continue; |
| 1564 | 1809 | ||
| 1565 | if (neigh_node->bat_iv.tq_avg == 0) | 1810 | n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, |
| 1811 | if_outgoing); | ||
| 1812 | if (!n_ifinfo) | ||
| 1813 | goto next; | ||
| 1814 | |||
| 1815 | if (n_ifinfo->bat_iv.tq_avg == 0) | ||
| 1566 | goto next; | 1816 | goto next; |
| 1567 | 1817 | ||
| 1568 | last_seen_jiffies = jiffies - orig_node->last_seen; | 1818 | last_seen_jiffies = jiffies - orig_node->last_seen; |
| @@ -1572,22 +1822,19 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, | |||
| 1572 | 1822 | ||
| 1573 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", | 1823 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", |
| 1574 | orig_node->orig, last_seen_secs, | 1824 | orig_node->orig, last_seen_secs, |
| 1575 | last_seen_msecs, neigh_node->bat_iv.tq_avg, | 1825 | last_seen_msecs, n_ifinfo->bat_iv.tq_avg, |
| 1576 | neigh_node->addr, | 1826 | neigh_node->addr, |
| 1577 | neigh_node->if_incoming->net_dev->name); | 1827 | neigh_node->if_incoming->net_dev->name); |
| 1578 | 1828 | ||
| 1579 | hlist_for_each_entry_rcu(neigh_node_tmp, | 1829 | batadv_iv_ogm_orig_print_neigh(orig_node, if_outgoing, |
| 1580 | &orig_node->neigh_list, list) { | 1830 | seq); |
| 1581 | seq_printf(seq, " %pM (%3i)", | ||
| 1582 | neigh_node_tmp->addr, | ||
| 1583 | neigh_node_tmp->bat_iv.tq_avg); | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | seq_puts(seq, "\n"); | 1831 | seq_puts(seq, "\n"); |
| 1587 | batman_count++; | 1832 | batman_count++; |
| 1588 | 1833 | ||
| 1589 | next: | 1834 | next: |
| 1590 | batadv_neigh_node_free_ref(neigh_node); | 1835 | batadv_neigh_node_free_ref(neigh_node); |
| 1836 | if (n_ifinfo) | ||
| 1837 | batadv_neigh_ifinfo_free_ref(n_ifinfo); | ||
| 1591 | } | 1838 | } |
| 1592 | rcu_read_unlock(); | 1839 | rcu_read_unlock(); |
| 1593 | } | 1840 | } |
| @@ -1599,37 +1846,84 @@ next: | |||
| 1599 | /** | 1846 | /** |
| 1600 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors | 1847 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors |
| 1601 | * @neigh1: the first neighbor object of the comparison | 1848 | * @neigh1: the first neighbor object of the comparison |
| 1849 | * @if_outgoing1: outgoing interface for the first neighbor | ||
| 1602 | * @neigh2: the second neighbor object of the comparison | 1850 | * @neigh2: the second neighbor object of the comparison |
| 1851 | * @if_outgoing2: outgoing interface for the second neighbor | ||
| 1603 | * | 1852 | * |
| 1604 | * Returns a value less, equal to or greater than 0 if the metric via neigh1 is | 1853 | * Returns a value less, equal to or greater than 0 if the metric via neigh1 is |
| 1605 | * lower, the same as or higher than the metric via neigh2 | 1854 | * lower, the same as or higher than the metric via neigh2 |
| 1606 | */ | 1855 | */ |
| 1607 | static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, | 1856 | static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, |
| 1608 | struct batadv_neigh_node *neigh2) | 1857 | struct batadv_hard_iface *if_outgoing1, |
| 1858 | struct batadv_neigh_node *neigh2, | ||
| 1859 | struct batadv_hard_iface *if_outgoing2) | ||
| 1609 | { | 1860 | { |
| 1861 | struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo; | ||
| 1610 | uint8_t tq1, tq2; | 1862 | uint8_t tq1, tq2; |
| 1863 | int diff; | ||
| 1864 | |||
| 1865 | neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); | ||
| 1866 | neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | ||
| 1867 | |||
| 1868 | if (!neigh1_ifinfo || !neigh2_ifinfo) { | ||
| 1869 | diff = 0; | ||
| 1870 | goto out; | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | tq1 = neigh1_ifinfo->bat_iv.tq_avg; | ||
| 1874 | tq2 = neigh2_ifinfo->bat_iv.tq_avg; | ||
| 1875 | diff = tq1 - tq2; | ||
| 1611 | 1876 | ||
| 1612 | tq1 = neigh1->bat_iv.tq_avg; | 1877 | out: |
| 1613 | tq2 = neigh2->bat_iv.tq_avg; | 1878 | if (neigh1_ifinfo) |
| 1879 | batadv_neigh_ifinfo_free_ref(neigh1_ifinfo); | ||
| 1880 | if (neigh2_ifinfo) | ||
| 1881 | batadv_neigh_ifinfo_free_ref(neigh2_ifinfo); | ||
| 1614 | 1882 | ||
| 1615 | return tq1 - tq2; | 1883 | return diff; |
| 1616 | } | 1884 | } |
| 1617 | 1885 | ||
| 1618 | /** | 1886 | /** |
| 1619 | * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than | 1887 | * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than |
| 1620 | * neigh2 from the metric prospective | 1888 | * neigh2 from the metric prospective |
| 1621 | * @neigh1: the first neighbor object of the comparison | 1889 | * @neigh1: the first neighbor object of the comparison |
| 1890 | * @if_outgoing: outgoing interface for the first neighbor | ||
| 1622 | * @neigh2: the second neighbor object of the comparison | 1891 | * @neigh2: the second neighbor object of the comparison |
| 1623 | * | 1892 | * @if_outgoing2: outgoing interface for the second neighbor |
| 1624 | * Returns true if the metric via neigh1 is equally good or better than the | 1893 | |
| 1625 | * metric via neigh2, false otherwise. | 1894 | * Returns true if the metric via neigh1 is equally good or better than |
| 1895 | * the metric via neigh2, false otherwise. | ||
| 1626 | */ | 1896 | */ |
| 1627 | static bool batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, | 1897 | static bool |
| 1628 | struct batadv_neigh_node *neigh2) | 1898 | batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, |
| 1899 | struct batadv_hard_iface *if_outgoing1, | ||
| 1900 | struct batadv_neigh_node *neigh2, | ||
| 1901 | struct batadv_hard_iface *if_outgoing2) | ||
| 1629 | { | 1902 | { |
| 1630 | int diff = batadv_iv_ogm_neigh_cmp(neigh1, neigh2); | 1903 | struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo; |
| 1904 | uint8_t tq1, tq2; | ||
| 1905 | bool ret; | ||
| 1631 | 1906 | ||
| 1632 | return diff > -BATADV_TQ_SIMILARITY_THRESHOLD; | 1907 | neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); |
| 1908 | neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); | ||
| 1909 | |||
| 1910 | /* we can't say that the metric is better */ | ||
| 1911 | if (!neigh1_ifinfo || !neigh2_ifinfo) { | ||
| 1912 | ret = false; | ||
| 1913 | goto out; | ||
| 1914 | } | ||
| 1915 | |||
| 1916 | tq1 = neigh1_ifinfo->bat_iv.tq_avg; | ||
| 1917 | tq2 = neigh2_ifinfo->bat_iv.tq_avg; | ||
| 1918 | ret = (tq1 - tq2) > -BATADV_TQ_SIMILARITY_THRESHOLD; | ||
| 1919 | |||
| 1920 | out: | ||
| 1921 | if (neigh1_ifinfo) | ||
| 1922 | batadv_neigh_ifinfo_free_ref(neigh1_ifinfo); | ||
| 1923 | if (neigh2_ifinfo) | ||
| 1924 | batadv_neigh_ifinfo_free_ref(neigh2_ifinfo); | ||
| 1925 | |||
| 1926 | return ret; | ||
| 1633 | } | 1927 | } |
| 1634 | 1928 | ||
| 1635 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { | 1929 | static struct batadv_algo_ops batadv_batman_iv __read_mostly = { |
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 89d3a5bcacc1..9586750022f5 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich, Marek Lindner | 3 | * Simon Wunderlich, Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index 685e0af1fef2..cc2407351d36 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich, Marek Lindner | 3 | * Simon Wunderlich, Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index b164a073a215..5c0eda48d7a2 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich | 3 | * Simon Wunderlich |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index 377dae069177..43c985d92c3e 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich | 3 | * Simon Wunderlich |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 0adbcee80d24..b758881be108 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
| @@ -248,6 +248,19 @@ static int batadv_originators_open(struct inode *inode, struct file *file) | |||
| 248 | return single_open(file, batadv_orig_seq_print_text, net_dev); | 248 | return single_open(file, batadv_orig_seq_print_text, net_dev); |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | /** | ||
| 252 | * batadv_originators_hardif_open - handles debugfs output for the | ||
| 253 | * originator table of an hard interface | ||
| 254 | * @inode: inode pointer to debugfs file | ||
| 255 | * @file: pointer to the seq_file | ||
| 256 | */ | ||
| 257 | static int batadv_originators_hardif_open(struct inode *inode, | ||
| 258 | struct file *file) | ||
| 259 | { | ||
| 260 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
| 261 | return single_open(file, batadv_orig_hardif_seq_print_text, net_dev); | ||
| 262 | } | ||
| 263 | |||
| 251 | static int batadv_gateways_open(struct inode *inode, struct file *file) | 264 | static int batadv_gateways_open(struct inode *inode, struct file *file) |
| 252 | { | 265 | { |
| 253 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 266 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
| @@ -369,6 +382,28 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | |||
| 369 | NULL, | 382 | NULL, |
| 370 | }; | 383 | }; |
| 371 | 384 | ||
| 385 | #define BATADV_HARDIF_DEBUGINFO(_name, _mode, _open) \ | ||
| 386 | struct batadv_debuginfo batadv_hardif_debuginfo_##_name = { \ | ||
| 387 | .attr = { \ | ||
| 388 | .name = __stringify(_name), \ | ||
| 389 | .mode = _mode, \ | ||
| 390 | }, \ | ||
| 391 | .fops = { \ | ||
| 392 | .owner = THIS_MODULE, \ | ||
| 393 | .open = _open, \ | ||
| 394 | .read = seq_read, \ | ||
| 395 | .llseek = seq_lseek, \ | ||
| 396 | .release = single_release, \ | ||
| 397 | }, \ | ||
| 398 | }; | ||
| 399 | static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO, | ||
| 400 | batadv_originators_hardif_open); | ||
| 401 | |||
| 402 | static struct batadv_debuginfo *batadv_hardif_debuginfos[] = { | ||
| 403 | &batadv_hardif_debuginfo_originators, | ||
| 404 | NULL, | ||
| 405 | }; | ||
| 406 | |||
| 372 | void batadv_debugfs_init(void) | 407 | void batadv_debugfs_init(void) |
| 373 | { | 408 | { |
| 374 | struct batadv_debuginfo **bat_debug; | 409 | struct batadv_debuginfo **bat_debug; |
| @@ -396,6 +431,7 @@ void batadv_debugfs_init(void) | |||
| 396 | return; | 431 | return; |
| 397 | err: | 432 | err: |
| 398 | debugfs_remove_recursive(batadv_debugfs); | 433 | debugfs_remove_recursive(batadv_debugfs); |
| 434 | batadv_debugfs = NULL; | ||
| 399 | } | 435 | } |
| 400 | 436 | ||
| 401 | void batadv_debugfs_destroy(void) | 437 | void batadv_debugfs_destroy(void) |
| @@ -404,6 +440,59 @@ void batadv_debugfs_destroy(void) | |||
| 404 | batadv_debugfs = NULL; | 440 | batadv_debugfs = NULL; |
| 405 | } | 441 | } |
| 406 | 442 | ||
| 443 | /** | ||
| 444 | * batadv_debugfs_add_hardif - creates the base directory for a hard interface | ||
| 445 | * in debugfs. | ||
| 446 | * @hard_iface: hard interface which should be added. | ||
| 447 | */ | ||
| 448 | int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface) | ||
| 449 | { | ||
| 450 | struct batadv_debuginfo **bat_debug; | ||
| 451 | struct dentry *file; | ||
| 452 | |||
| 453 | if (!batadv_debugfs) | ||
| 454 | goto out; | ||
| 455 | |||
| 456 | hard_iface->debug_dir = debugfs_create_dir(hard_iface->net_dev->name, | ||
| 457 | batadv_debugfs); | ||
| 458 | if (!hard_iface->debug_dir) | ||
| 459 | goto out; | ||
| 460 | |||
| 461 | for (bat_debug = batadv_hardif_debuginfos; *bat_debug; ++bat_debug) { | ||
| 462 | file = debugfs_create_file(((*bat_debug)->attr).name, | ||
| 463 | S_IFREG | ((*bat_debug)->attr).mode, | ||
| 464 | hard_iface->debug_dir, | ||
| 465 | hard_iface->net_dev, | ||
| 466 | &(*bat_debug)->fops); | ||
| 467 | if (!file) | ||
| 468 | goto rem_attr; | ||
| 469 | } | ||
| 470 | |||
| 471 | return 0; | ||
| 472 | rem_attr: | ||
| 473 | debugfs_remove_recursive(hard_iface->debug_dir); | ||
| 474 | hard_iface->debug_dir = NULL; | ||
| 475 | out: | ||
| 476 | #ifdef CONFIG_DEBUG_FS | ||
| 477 | return -ENOMEM; | ||
| 478 | #else | ||
| 479 | return 0; | ||
| 480 | #endif /* CONFIG_DEBUG_FS */ | ||
| 481 | } | ||
| 482 | |||
| 483 | /** | ||
| 484 | * batadv_debugfs_del_hardif - delete the base directory for a hard interface | ||
| 485 | * in debugfs. | ||
| 486 | * @hard_iface: hard interface which is deleted. | ||
| 487 | */ | ||
| 488 | void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface) | ||
| 489 | { | ||
| 490 | if (batadv_debugfs) { | ||
| 491 | debugfs_remove_recursive(hard_iface->debug_dir); | ||
| 492 | hard_iface->debug_dir = NULL; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 407 | int batadv_debugfs_add_meshif(struct net_device *dev) | 496 | int batadv_debugfs_add_meshif(struct net_device *dev) |
| 408 | { | 497 | { |
| 409 | struct batadv_priv *bat_priv = netdev_priv(dev); | 498 | struct batadv_priv *bat_priv = netdev_priv(dev); |
diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h index 0861b629e1a8..37c4d6ddd04d 100644 --- a/net/batman-adv/debugfs.h +++ b/net/batman-adv/debugfs.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
| @@ -24,5 +24,7 @@ void batadv_debugfs_init(void); | |||
| 24 | void batadv_debugfs_destroy(void); | 24 | void batadv_debugfs_destroy(void); |
| 25 | int batadv_debugfs_add_meshif(struct net_device *dev); | 25 | int batadv_debugfs_add_meshif(struct net_device *dev); |
| 26 | void batadv_debugfs_del_meshif(struct net_device *dev); | 26 | void batadv_debugfs_del_meshif(struct net_device *dev); |
| 27 | int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface); | ||
| 28 | void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface); | ||
| 27 | 29 | ||
| 28 | #endif /* _NET_BATMAN_ADV_DEBUGFS_H_ */ | 30 | #endif /* _NET_BATMAN_ADV_DEBUGFS_H_ */ |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 997ae6ac51ff..edee50411892 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Antonio Quartulli | 3 | * Antonio Quartulli |
| 4 | * | 4 | * |
| @@ -589,7 +589,8 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, | |||
| 589 | if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND) | 589 | if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND) |
| 590 | continue; | 590 | continue; |
| 591 | 591 | ||
| 592 | neigh_node = batadv_orig_node_get_router(cand[i].orig_node); | 592 | neigh_node = batadv_orig_router_get(cand[i].orig_node, |
| 593 | BATADV_IF_DEFAULT); | ||
| 593 | if (!neigh_node) | 594 | if (!neigh_node) |
| 594 | goto free_orig; | 595 | goto free_orig; |
| 595 | 596 | ||
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index afa13ca2371a..ac9be9b67a25 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2011-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Antonio Quartulli | 3 | * Antonio Quartulli |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 43185ca9da17..88df9b1d552d 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2013-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Martin Hundebøll <martin@hundeboll.net> | 3 | * Martin Hundebøll <martin@hundeboll.net> |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h index 0347f0ce0f61..5d7a0e66a22b 100644 --- a/net/batman-adv/fragmentation.h +++ b/net/batman-adv/fragmentation.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2013-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Martin Hundebøll <martin@hundeboll.net> | 3 | * Martin Hundebøll <martin@hundeboll.net> |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 4150a641c52e..55cf2260d295 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
| @@ -129,6 +129,7 @@ static struct batadv_gw_node * | |||
| 129 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | 129 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) |
| 130 | { | 130 | { |
| 131 | struct batadv_neigh_node *router; | 131 | struct batadv_neigh_node *router; |
| 132 | struct batadv_neigh_ifinfo *router_ifinfo; | ||
| 132 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | 133 | struct batadv_gw_node *gw_node, *curr_gw = NULL; |
| 133 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 134 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
| 134 | uint32_t gw_divisor; | 135 | uint32_t gw_divisor; |
| @@ -145,14 +146,19 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
| 145 | continue; | 146 | continue; |
| 146 | 147 | ||
| 147 | orig_node = gw_node->orig_node; | 148 | orig_node = gw_node->orig_node; |
| 148 | router = batadv_orig_node_get_router(orig_node); | 149 | router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); |
| 149 | if (!router) | 150 | if (!router) |
| 150 | continue; | 151 | continue; |
| 151 | 152 | ||
| 153 | router_ifinfo = batadv_neigh_ifinfo_get(router, | ||
| 154 | BATADV_IF_DEFAULT); | ||
| 155 | if (!router_ifinfo) | ||
| 156 | goto next; | ||
| 157 | |||
| 152 | if (!atomic_inc_not_zero(&gw_node->refcount)) | 158 | if (!atomic_inc_not_zero(&gw_node->refcount)) |
| 153 | goto next; | 159 | goto next; |
| 154 | 160 | ||
| 155 | tq_avg = router->bat_iv.tq_avg; | 161 | tq_avg = router_ifinfo->bat_iv.tq_avg; |
| 156 | 162 | ||
| 157 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 163 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
| 158 | case 1: /* fast connection */ | 164 | case 1: /* fast connection */ |
| @@ -197,6 +203,8 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
| 197 | 203 | ||
| 198 | next: | 204 | next: |
| 199 | batadv_neigh_node_free_ref(router); | 205 | batadv_neigh_node_free_ref(router); |
| 206 | if (router_ifinfo) | ||
| 207 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 200 | } | 208 | } |
| 201 | rcu_read_unlock(); | 209 | rcu_read_unlock(); |
| 202 | 210 | ||
| @@ -239,6 +247,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 239 | { | 247 | { |
| 240 | struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL; | 248 | struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL; |
| 241 | struct batadv_neigh_node *router = NULL; | 249 | struct batadv_neigh_node *router = NULL; |
| 250 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 242 | char gw_addr[18] = { '\0' }; | 251 | char gw_addr[18] = { '\0' }; |
| 243 | 252 | ||
| 244 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 253 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) |
| @@ -257,11 +266,19 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 257 | if (next_gw) { | 266 | if (next_gw) { |
| 258 | sprintf(gw_addr, "%pM", next_gw->orig_node->orig); | 267 | sprintf(gw_addr, "%pM", next_gw->orig_node->orig); |
| 259 | 268 | ||
| 260 | router = batadv_orig_node_get_router(next_gw->orig_node); | 269 | router = batadv_orig_router_get(next_gw->orig_node, |
| 270 | BATADV_IF_DEFAULT); | ||
| 261 | if (!router) { | 271 | if (!router) { |
| 262 | batadv_gw_reselect(bat_priv); | 272 | batadv_gw_reselect(bat_priv); |
| 263 | goto out; | 273 | goto out; |
| 264 | } | 274 | } |
| 275 | |||
| 276 | router_ifinfo = batadv_neigh_ifinfo_get(router, | ||
| 277 | BATADV_IF_DEFAULT); | ||
| 278 | if (!router_ifinfo) { | ||
| 279 | batadv_gw_reselect(bat_priv); | ||
| 280 | goto out; | ||
| 281 | } | ||
| 265 | } | 282 | } |
| 266 | 283 | ||
| 267 | if ((curr_gw) && (!next_gw)) { | 284 | if ((curr_gw) && (!next_gw)) { |
| @@ -276,7 +293,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 276 | next_gw->bandwidth_down / 10, | 293 | next_gw->bandwidth_down / 10, |
| 277 | next_gw->bandwidth_down % 10, | 294 | next_gw->bandwidth_down % 10, |
| 278 | next_gw->bandwidth_up / 10, | 295 | next_gw->bandwidth_up / 10, |
| 279 | next_gw->bandwidth_up % 10, router->bat_iv.tq_avg); | 296 | next_gw->bandwidth_up % 10, |
| 297 | router_ifinfo->bat_iv.tq_avg); | ||
| 280 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, | 298 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, |
| 281 | gw_addr); | 299 | gw_addr); |
| 282 | } else { | 300 | } else { |
| @@ -286,7 +304,8 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
| 286 | next_gw->bandwidth_down / 10, | 304 | next_gw->bandwidth_down / 10, |
| 287 | next_gw->bandwidth_down % 10, | 305 | next_gw->bandwidth_down % 10, |
| 288 | next_gw->bandwidth_up / 10, | 306 | next_gw->bandwidth_up / 10, |
| 289 | next_gw->bandwidth_up % 10, router->bat_iv.tq_avg); | 307 | next_gw->bandwidth_up % 10, |
| 308 | router_ifinfo->bat_iv.tq_avg); | ||
| 290 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, | 309 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, |
| 291 | gw_addr); | 310 | gw_addr); |
| 292 | } | 311 | } |
| @@ -300,11 +319,15 @@ out: | |||
| 300 | batadv_gw_node_free_ref(next_gw); | 319 | batadv_gw_node_free_ref(next_gw); |
| 301 | if (router) | 320 | if (router) |
| 302 | batadv_neigh_node_free_ref(router); | 321 | batadv_neigh_node_free_ref(router); |
| 322 | if (router_ifinfo) | ||
| 323 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 303 | } | 324 | } |
| 304 | 325 | ||
| 305 | void batadv_gw_check_election(struct batadv_priv *bat_priv, | 326 | void batadv_gw_check_election(struct batadv_priv *bat_priv, |
| 306 | struct batadv_orig_node *orig_node) | 327 | struct batadv_orig_node *orig_node) |
| 307 | { | 328 | { |
| 329 | struct batadv_neigh_ifinfo *router_orig_tq = NULL; | ||
| 330 | struct batadv_neigh_ifinfo *router_gw_tq = NULL; | ||
| 308 | struct batadv_orig_node *curr_gw_orig; | 331 | struct batadv_orig_node *curr_gw_orig; |
| 309 | struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL; | 332 | struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL; |
| 310 | uint8_t gw_tq_avg, orig_tq_avg; | 333 | uint8_t gw_tq_avg, orig_tq_avg; |
| @@ -313,20 +336,30 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, | |||
| 313 | if (!curr_gw_orig) | 336 | if (!curr_gw_orig) |
| 314 | goto reselect; | 337 | goto reselect; |
| 315 | 338 | ||
| 316 | router_gw = batadv_orig_node_get_router(curr_gw_orig); | 339 | router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT); |
| 317 | if (!router_gw) | 340 | if (!router_gw) |
| 318 | goto reselect; | 341 | goto reselect; |
| 319 | 342 | ||
| 343 | router_gw_tq = batadv_neigh_ifinfo_get(router_gw, | ||
| 344 | BATADV_IF_DEFAULT); | ||
| 345 | if (!router_gw_tq) | ||
| 346 | goto reselect; | ||
| 347 | |||
| 320 | /* this node already is the gateway */ | 348 | /* this node already is the gateway */ |
| 321 | if (curr_gw_orig == orig_node) | 349 | if (curr_gw_orig == orig_node) |
| 322 | goto out; | 350 | goto out; |
| 323 | 351 | ||
| 324 | router_orig = batadv_orig_node_get_router(orig_node); | 352 | router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); |
| 325 | if (!router_orig) | 353 | if (!router_orig) |
| 326 | goto out; | 354 | goto out; |
| 327 | 355 | ||
| 328 | gw_tq_avg = router_gw->bat_iv.tq_avg; | 356 | router_orig_tq = batadv_neigh_ifinfo_get(router_orig, |
| 329 | orig_tq_avg = router_orig->bat_iv.tq_avg; | 357 | BATADV_IF_DEFAULT); |
| 358 | if (!router_orig_tq) | ||
| 359 | goto out; | ||
| 360 | |||
| 361 | gw_tq_avg = router_gw_tq->bat_iv.tq_avg; | ||
| 362 | orig_tq_avg = router_orig_tq->bat_iv.tq_avg; | ||
| 330 | 363 | ||
| 331 | /* the TQ value has to be better */ | 364 | /* the TQ value has to be better */ |
| 332 | if (orig_tq_avg < gw_tq_avg) | 365 | if (orig_tq_avg < gw_tq_avg) |
| @@ -352,6 +385,10 @@ out: | |||
| 352 | batadv_neigh_node_free_ref(router_gw); | 385 | batadv_neigh_node_free_ref(router_gw); |
| 353 | if (router_orig) | 386 | if (router_orig) |
| 354 | batadv_neigh_node_free_ref(router_orig); | 387 | batadv_neigh_node_free_ref(router_orig); |
| 388 | if (router_gw_tq) | ||
| 389 | batadv_neigh_ifinfo_free_ref(router_gw_tq); | ||
| 390 | if (router_orig_tq) | ||
| 391 | batadv_neigh_ifinfo_free_ref(router_orig_tq); | ||
| 355 | 392 | ||
| 356 | return; | 393 | return; |
| 357 | } | 394 | } |
| @@ -537,28 +574,36 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, | |||
| 537 | { | 574 | { |
| 538 | struct batadv_gw_node *curr_gw; | 575 | struct batadv_gw_node *curr_gw; |
| 539 | struct batadv_neigh_node *router; | 576 | struct batadv_neigh_node *router; |
| 577 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | ||
| 540 | int ret = -1; | 578 | int ret = -1; |
| 541 | 579 | ||
| 542 | router = batadv_orig_node_get_router(gw_node->orig_node); | 580 | router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT); |
| 543 | if (!router) | 581 | if (!router) |
| 544 | goto out; | 582 | goto out; |
| 545 | 583 | ||
| 584 | router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT); | ||
| 585 | if (!router_ifinfo) | ||
| 586 | goto out; | ||
| 587 | |||
| 546 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 588 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
| 547 | 589 | ||
| 548 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", | 590 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", |
| 549 | (curr_gw == gw_node ? "=>" : " "), | 591 | (curr_gw == gw_node ? "=>" : " "), |
| 550 | gw_node->orig_node->orig, | 592 | gw_node->orig_node->orig, |
| 551 | router->bat_iv.tq_avg, router->addr, | 593 | router_ifinfo->bat_iv.tq_avg, router->addr, |
| 552 | router->if_incoming->net_dev->name, | 594 | router->if_incoming->net_dev->name, |
| 553 | gw_node->bandwidth_down / 10, | 595 | gw_node->bandwidth_down / 10, |
| 554 | gw_node->bandwidth_down % 10, | 596 | gw_node->bandwidth_down % 10, |
| 555 | gw_node->bandwidth_up / 10, | 597 | gw_node->bandwidth_up / 10, |
| 556 | gw_node->bandwidth_up % 10); | 598 | gw_node->bandwidth_up % 10); |
| 557 | 599 | ||
| 558 | batadv_neigh_node_free_ref(router); | ||
| 559 | if (curr_gw) | 600 | if (curr_gw) |
| 560 | batadv_gw_node_free_ref(curr_gw); | 601 | batadv_gw_node_free_ref(curr_gw); |
| 561 | out: | 602 | out: |
| 603 | if (router_ifinfo) | ||
| 604 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
| 605 | if (router) | ||
| 606 | batadv_neigh_node_free_ref(router); | ||
| 562 | return ret; | 607 | return ret; |
| 563 | } | 608 | } |
| 564 | 609 | ||
| @@ -746,6 +791,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 746 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; | 791 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; |
| 747 | struct batadv_orig_node *orig_dst_node = NULL; | 792 | struct batadv_orig_node *orig_dst_node = NULL; |
| 748 | struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; | 793 | struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; |
| 794 | struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; | ||
| 749 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 795 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
| 750 | bool out_of_range = false; | 796 | bool out_of_range = false; |
| 751 | uint8_t curr_tq_avg; | 797 | uint8_t curr_tq_avg; |
| @@ -787,7 +833,14 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 787 | if (!neigh_curr) | 833 | if (!neigh_curr) |
| 788 | goto out; | 834 | goto out; |
| 789 | 835 | ||
| 790 | curr_tq_avg = neigh_curr->bat_iv.tq_avg; | 836 | curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr, |
| 837 | BATADV_IF_DEFAULT); | ||
| 838 | if (!curr_ifinfo) | ||
| 839 | goto out; | ||
| 840 | |||
| 841 | curr_tq_avg = curr_ifinfo->bat_iv.tq_avg; | ||
| 842 | batadv_neigh_ifinfo_free_ref(curr_ifinfo); | ||
| 843 | |||
| 791 | break; | 844 | break; |
| 792 | case BATADV_GW_MODE_OFF: | 845 | case BATADV_GW_MODE_OFF: |
| 793 | default: | 846 | default: |
| @@ -798,8 +851,13 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 798 | if (!neigh_old) | 851 | if (!neigh_old) |
| 799 | goto out; | 852 | goto out; |
| 800 | 853 | ||
| 801 | if (curr_tq_avg - neigh_old->bat_iv.tq_avg > BATADV_GW_THRESHOLD) | 854 | old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT); |
| 855 | if (!old_ifinfo) | ||
| 856 | goto out; | ||
| 857 | |||
| 858 | if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD) | ||
| 802 | out_of_range = true; | 859 | out_of_range = true; |
| 860 | batadv_neigh_ifinfo_free_ref(old_ifinfo); | ||
| 803 | 861 | ||
| 804 | out: | 862 | out: |
| 805 | if (orig_dst_node) | 863 | if (orig_dst_node) |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 006befb8c7b8..7ee53bb7d50f 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index f76816ce9faf..6f5e621f220a 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h index c47b17a0a6b6..aa5116561947 100644 --- a/net/batman-adv/gateway_common.h +++ b/net/batman-adv/gateway_common.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index bebd46ce0ebd..1b12573bcf83 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "translation-table.h" | 23 | #include "translation-table.h" |
| 24 | #include "routing.h" | 24 | #include "routing.h" |
| 25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
| 26 | #include "debugfs.h" | ||
| 26 | #include "originator.h" | 27 | #include "originator.h" |
| 27 | #include "hash.h" | 28 | #include "hash.h" |
| 28 | #include "bridge_loop_avoidance.h" | 29 | #include "bridge_loop_avoidance.h" |
| @@ -539,6 +540,7 @@ static void batadv_hardif_remove_interface_finish(struct work_struct *work) | |||
| 539 | hard_iface = container_of(work, struct batadv_hard_iface, | 540 | hard_iface = container_of(work, struct batadv_hard_iface, |
| 540 | cleanup_work); | 541 | cleanup_work); |
| 541 | 542 | ||
| 543 | batadv_debugfs_del_hardif(hard_iface); | ||
| 542 | batadv_sysfs_del_hardif(&hard_iface->hardif_obj); | 544 | batadv_sysfs_del_hardif(&hard_iface->hardif_obj); |
| 543 | batadv_hardif_free_ref(hard_iface); | 545 | batadv_hardif_free_ref(hard_iface); |
| 544 | } | 546 | } |
| @@ -569,6 +571,11 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
| 569 | hard_iface->net_dev = net_dev; | 571 | hard_iface->net_dev = net_dev; |
| 570 | hard_iface->soft_iface = NULL; | 572 | hard_iface->soft_iface = NULL; |
| 571 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; | 573 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; |
| 574 | |||
| 575 | ret = batadv_debugfs_add_hardif(hard_iface); | ||
| 576 | if (ret) | ||
| 577 | goto free_sysfs; | ||
| 578 | |||
| 572 | INIT_LIST_HEAD(&hard_iface->list); | 579 | INIT_LIST_HEAD(&hard_iface->list); |
| 573 | INIT_WORK(&hard_iface->cleanup_work, | 580 | INIT_WORK(&hard_iface->cleanup_work, |
| 574 | batadv_hardif_remove_interface_finish); | 581 | batadv_hardif_remove_interface_finish); |
| @@ -585,6 +592,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
| 585 | 592 | ||
| 586 | return hard_iface; | 593 | return hard_iface; |
| 587 | 594 | ||
| 595 | free_sysfs: | ||
| 596 | batadv_sysfs_del_hardif(&hard_iface->hardif_obj); | ||
| 588 | free_if: | 597 | free_if: |
| 589 | kfree(hard_iface); | 598 | kfree(hard_iface); |
| 590 | release_dev: | 599 | release_dev: |
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index d8ca8ac829c1..1918cd50b62e 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -40,6 +40,7 @@ enum batadv_hard_if_cleanup { | |||
| 40 | extern struct notifier_block batadv_hard_if_notifier; | 40 | extern struct notifier_block batadv_hard_if_notifier; |
| 41 | 41 | ||
| 42 | bool batadv_is_wifi_netdev(struct net_device *net_device); | 42 | bool batadv_is_wifi_netdev(struct net_device *net_device); |
| 43 | bool batadv_is_wifi_iface(int ifindex); | ||
| 43 | struct batadv_hard_iface* | 44 | struct batadv_hard_iface* |
| 44 | batadv_hardif_get_by_netdev(const struct net_device *net_dev); | 45 | batadv_hardif_get_by_netdev(const struct net_device *net_dev); |
| 45 | int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | 46 | int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, |
| @@ -51,6 +52,11 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface); | |||
| 51 | void batadv_update_min_mtu(struct net_device *soft_iface); | 52 | void batadv_update_min_mtu(struct net_device *soft_iface); |
| 52 | void batadv_hardif_free_rcu(struct rcu_head *rcu); | 53 | void batadv_hardif_free_rcu(struct rcu_head *rcu); |
| 53 | 54 | ||
| 55 | /** | ||
| 56 | * batadv_hardif_free_ref - decrement the hard interface refcounter and | ||
| 57 | * possibly free it | ||
| 58 | * @hard_iface: the hard interface to free | ||
| 59 | */ | ||
| 54 | static inline void | 60 | static inline void |
| 55 | batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) | 61 | batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) |
| 56 | { | 62 | { |
| @@ -58,6 +64,18 @@ batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) | |||
| 58 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); | 64 | call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); |
| 59 | } | 65 | } |
| 60 | 66 | ||
| 67 | /** | ||
| 68 | * batadv_hardif_free_ref_now - decrement the hard interface refcounter and | ||
| 69 | * possibly free it (without rcu callback) | ||
| 70 | * @hard_iface: the hard interface to free | ||
| 71 | */ | ||
| 72 | static inline void | ||
| 73 | batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface) | ||
| 74 | { | ||
| 75 | if (atomic_dec_and_test(&hard_iface->refcount)) | ||
| 76 | batadv_hardif_free_rcu(&hard_iface->rcu); | ||
| 77 | } | ||
| 78 | |||
| 61 | static inline struct batadv_hard_iface * | 79 | static inline struct batadv_hard_iface * |
| 62 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) | 80 | batadv_primary_if_get_selected(struct batadv_priv *bat_priv) |
| 63 | { | 81 | { |
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index d9cfa03b9e12..63bdf7e94f1e 100644 --- a/net/batman-adv/hash.c +++ b/net/batman-adv/hash.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich, Marek Lindner | 3 | * Simon Wunderlich, Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index df5ece96ac12..539fc1266793 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2006-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Simon Wunderlich, Marek Lindner | 3 | * Simon Wunderlich, Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 3c08eee1b920..abb9d6e0388b 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
| @@ -215,7 +215,8 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, | |||
| 215 | if (!orig_node) | 215 | if (!orig_node) |
| 216 | goto dst_unreach; | 216 | goto dst_unreach; |
| 217 | 217 | ||
| 218 | neigh_node = batadv_orig_node_get_router(orig_node); | 218 | neigh_node = batadv_orig_router_get(orig_node, |
| 219 | BATADV_IF_DEFAULT); | ||
| 219 | if (!neigh_node) | 220 | if (!neigh_node) |
| 220 | goto dst_unreach; | 221 | goto dst_unreach; |
| 221 | 222 | ||
diff --git a/net/batman-adv/icmp_socket.h b/net/batman-adv/icmp_socket.h index 559e54ad64a2..0c33950aa4aa 100644 --- a/net/batman-adv/icmp_socket.h +++ b/net/batman-adv/icmp_socket.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 945e441b579d..e56b4d6a43b6 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -419,13 +419,23 @@ static void batadv_recv_handler_init(void) | |||
| 419 | for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++) | 419 | for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++) |
| 420 | batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet; | 420 | batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet; |
| 421 | 421 | ||
| 422 | /* compile time checks for struct member offsets */ | 422 | /* compile time checks for sizes */ |
| 423 | BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10); | 423 | BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6); |
| 424 | BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4); | 424 | BUILD_BUG_ON(sizeof(struct batadv_ogm_packet) != 24); |
| 425 | BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4); | 425 | BUILD_BUG_ON(sizeof(struct batadv_icmp_header) != 20); |
| 426 | BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4); | 426 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet) != 20); |
| 427 | BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4); | 427 | BUILD_BUG_ON(sizeof(struct batadv_icmp_packet_rr) != 116); |
| 428 | BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4); | 428 | BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10); |
| 429 | BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18); | ||
| 430 | BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20); | ||
| 431 | BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14); | ||
| 432 | BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46); | ||
| 433 | BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20); | ||
| 434 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_hdr) != 4); | ||
| 435 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_gateway_data) != 8); | ||
| 436 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_vlan_data) != 8); | ||
| 437 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12); | ||
| 438 | BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8); | ||
| 429 | 439 | ||
| 430 | /* broadcast packet */ | 440 | /* broadcast packet */ |
| 431 | batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; | 441 | batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index a468760b11ea..9374f1a51348 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -24,7 +24,7 @@ | |||
| 24 | #define BATADV_DRIVER_DEVICE "batman-adv" | 24 | #define BATADV_DRIVER_DEVICE "batman-adv" |
| 25 | 25 | ||
| 26 | #ifndef BATADV_SOURCE_VERSION | 26 | #ifndef BATADV_SOURCE_VERSION |
| 27 | #define BATADV_SOURCE_VERSION "2013.5.0" | 27 | #define BATADV_SOURCE_VERSION "2014.1.0" |
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | /* B.A.T.M.A.N. parameters */ | 30 | /* B.A.T.M.A.N. parameters */ |
| @@ -72,6 +72,12 @@ | |||
| 72 | 72 | ||
| 73 | #define BATADV_NO_MARK 0 | 73 | #define BATADV_NO_MARK 0 |
| 74 | 74 | ||
| 75 | /* default interface for multi interface operation. The default interface is | ||
| 76 | * used for communication which originated locally (i.e. is not forwarded) | ||
| 77 | * or where special forwarding is not desired/necessary. | ||
| 78 | */ | ||
| 79 | #define BATADV_IF_DEFAULT ((struct batadv_hard_iface *)NULL) | ||
| 80 | |||
| 75 | #define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) | 81 | #define BATADV_NUM_WORDS BITS_TO_LONGS(BATADV_TQ_LOCAL_WINDOW_SIZE) |
| 76 | 82 | ||
| 77 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ | 83 | #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index d6f0be346a3d..f1b604d88dc3 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2012-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Martin Hundebøll, Jeppe Ledet-Pedersen | 3 | * Martin Hundebøll, Jeppe Ledet-Pedersen |
| 4 | * | 4 | * |
| @@ -718,9 +718,21 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv, | |||
| 718 | struct batadv_orig_node *orig_node, | 718 | struct batadv_orig_node *orig_node, |
| 719 | struct batadv_ogm_packet *ogm_packet) | 719 | struct batadv_ogm_packet *ogm_packet) |
| 720 | { | 720 | { |
| 721 | if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno)) | 721 | struct batadv_orig_ifinfo *orig_ifinfo; |
| 722 | uint32_t last_real_seqno; | ||
| 723 | uint8_t last_ttl; | ||
| 724 | |||
| 725 | orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT); | ||
| 726 | if (!orig_ifinfo) | ||
| 722 | return false; | 727 | return false; |
| 723 | if (orig_node->last_ttl != ogm_packet->ttl + 1) | 728 | |
| 729 | last_ttl = orig_ifinfo->last_ttl; | ||
| 730 | last_real_seqno = orig_ifinfo->last_real_seqno; | ||
| 731 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 732 | |||
| 733 | if (last_real_seqno != ntohl(ogm_packet->seqno)) | ||
| 734 | return false; | ||
| 735 | if (last_ttl != ogm_packet->ttl + 1) | ||
| 724 | return false; | 736 | return false; |
| 725 | if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender)) | 737 | if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender)) |
| 726 | return false; | 738 | return false; |
| @@ -1008,6 +1020,8 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | |||
| 1008 | struct batadv_coded_packet *coded_packet; | 1020 | struct batadv_coded_packet *coded_packet; |
| 1009 | struct batadv_neigh_node *neigh_tmp, *router_neigh; | 1021 | struct batadv_neigh_node *neigh_tmp, *router_neigh; |
| 1010 | struct batadv_neigh_node *router_coding = NULL; | 1022 | struct batadv_neigh_node *router_coding = NULL; |
| 1023 | struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; | ||
| 1024 | struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; | ||
| 1011 | uint8_t *first_source, *first_dest, *second_source, *second_dest; | 1025 | uint8_t *first_source, *first_dest, *second_source, *second_dest; |
| 1012 | __be32 packet_id1, packet_id2; | 1026 | __be32 packet_id1, packet_id2; |
| 1013 | size_t count; | 1027 | size_t count; |
| @@ -1017,19 +1031,34 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | |||
| 1017 | int coded_size = sizeof(*coded_packet); | 1031 | int coded_size = sizeof(*coded_packet); |
| 1018 | int header_add = coded_size - unicast_size; | 1032 | int header_add = coded_size - unicast_size; |
| 1019 | 1033 | ||
| 1020 | router_neigh = batadv_orig_node_get_router(neigh_node->orig_node); | 1034 | /* TODO: do we need to consider the outgoing interface for |
| 1035 | * coded packets? | ||
| 1036 | */ | ||
| 1037 | router_neigh = batadv_orig_router_get(neigh_node->orig_node, | ||
| 1038 | BATADV_IF_DEFAULT); | ||
| 1021 | if (!router_neigh) | 1039 | if (!router_neigh) |
| 1022 | goto out; | 1040 | goto out; |
| 1023 | 1041 | ||
| 1042 | router_neigh_ifinfo = batadv_neigh_ifinfo_get(router_neigh, | ||
| 1043 | BATADV_IF_DEFAULT); | ||
| 1044 | if (!router_neigh_ifinfo) | ||
| 1045 | goto out; | ||
| 1046 | |||
| 1024 | neigh_tmp = nc_packet->neigh_node; | 1047 | neigh_tmp = nc_packet->neigh_node; |
| 1025 | router_coding = batadv_orig_node_get_router(neigh_tmp->orig_node); | 1048 | router_coding = batadv_orig_router_get(neigh_tmp->orig_node, |
| 1049 | BATADV_IF_DEFAULT); | ||
| 1026 | if (!router_coding) | 1050 | if (!router_coding) |
| 1027 | goto out; | 1051 | goto out; |
| 1028 | 1052 | ||
| 1029 | tq_tmp = batadv_nc_random_weight_tq(router_neigh->bat_iv.tq_avg); | 1053 | router_coding_ifinfo = batadv_neigh_ifinfo_get(router_coding, |
| 1030 | tq_weighted_neigh = tq_tmp; | 1054 | BATADV_IF_DEFAULT); |
| 1031 | tq_tmp = batadv_nc_random_weight_tq(router_coding->bat_iv.tq_avg); | 1055 | if (!router_coding_ifinfo) |
| 1032 | tq_weighted_coding = tq_tmp; | 1056 | goto out; |
| 1057 | |||
| 1058 | tq_tmp = router_neigh_ifinfo->bat_iv.tq_avg; | ||
| 1059 | tq_weighted_neigh = batadv_nc_random_weight_tq(tq_tmp); | ||
| 1060 | tq_tmp = router_coding_ifinfo->bat_iv.tq_avg; | ||
| 1061 | tq_weighted_coding = batadv_nc_random_weight_tq(tq_tmp); | ||
| 1033 | 1062 | ||
| 1034 | /* Select one destination for the MAC-header dst-field based on | 1063 | /* Select one destination for the MAC-header dst-field based on |
| 1035 | * weighted TQ-values. | 1064 | * weighted TQ-values. |
| @@ -1153,6 +1182,10 @@ out: | |||
| 1153 | batadv_neigh_node_free_ref(router_neigh); | 1182 | batadv_neigh_node_free_ref(router_neigh); |
| 1154 | if (router_coding) | 1183 | if (router_coding) |
| 1155 | batadv_neigh_node_free_ref(router_coding); | 1184 | batadv_neigh_node_free_ref(router_coding); |
| 1185 | if (router_neigh_ifinfo) | ||
| 1186 | batadv_neigh_ifinfo_free_ref(router_neigh_ifinfo); | ||
| 1187 | if (router_coding_ifinfo) | ||
| 1188 | batadv_neigh_ifinfo_free_ref(router_coding_ifinfo); | ||
| 1156 | return res; | 1189 | return res; |
| 1157 | } | 1190 | } |
| 1158 | 1191 | ||
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index ab59b3d7cf0f..358c0d686ab0 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2012-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2012-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Martin Hundebøll, Jeppe Ledet-Pedersen | 3 | * Martin Hundebøll, Jeppe Ledet-Pedersen |
| 4 | * | 4 | * |
| @@ -62,7 +62,6 @@ static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv) | |||
| 62 | 62 | ||
| 63 | static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) | 63 | static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) |
| 64 | { | 64 | { |
| 65 | return; | ||
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | static inline void | 67 | static inline void |
| @@ -72,7 +71,6 @@ batadv_nc_update_nc_node(struct batadv_priv *bat_priv, | |||
| 72 | struct batadv_ogm_packet *ogm_packet, | 71 | struct batadv_ogm_packet *ogm_packet, |
| 73 | int is_single_hop_neigh) | 72 | int is_single_hop_neigh) |
| 74 | { | 73 | { |
| 75 | return; | ||
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | static inline void | 76 | static inline void |
| @@ -81,17 +79,14 @@ batadv_nc_purge_orig(struct batadv_priv *bat_priv, | |||
| 81 | bool (*to_purge)(struct batadv_priv *, | 79 | bool (*to_purge)(struct batadv_priv *, |
| 82 | struct batadv_nc_node *)) | 80 | struct batadv_nc_node *)) |
| 83 | { | 81 | { |
| 84 | return; | ||
| 85 | } | 82 | } |
| 86 | 83 | ||
| 87 | static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) | 84 | static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) |
| 88 | { | 85 | { |
| 89 | return; | ||
| 90 | } | 86 | } |
| 91 | 87 | ||
| 92 | static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node) | 88 | static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node) |
| 93 | { | 89 | { |
| 94 | return; | ||
| 95 | } | 90 | } |
| 96 | 91 | ||
| 97 | static inline bool batadv_nc_skb_forward(struct sk_buff *skb, | 92 | static inline bool batadv_nc_skb_forward(struct sk_buff *skb, |
| @@ -104,14 +99,12 @@ static inline void | |||
| 104 | batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, | 99 | batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, |
| 105 | struct sk_buff *skb) | 100 | struct sk_buff *skb) |
| 106 | { | 101 | { |
| 107 | return; | ||
| 108 | } | 102 | } |
| 109 | 103 | ||
| 110 | static inline void | 104 | static inline void |
| 111 | batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, | 105 | batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, |
| 112 | struct sk_buff *skb) | 106 | struct sk_buff *skb) |
| 113 | { | 107 | { |
| 114 | return; | ||
| 115 | } | 108 | } |
| 116 | 109 | ||
| 117 | static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq, | 110 | static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq, |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 04a6d51f1d58..6df12a2e3605 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -148,20 +148,114 @@ err: | |||
| 148 | return -ENOMEM; | 148 | return -ENOMEM; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | /** | ||
| 152 | * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object | ||
| 153 | * @rcu: rcu pointer of the neigh_ifinfo object | ||
| 154 | */ | ||
| 155 | static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu) | ||
| 156 | { | ||
| 157 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 158 | |||
| 159 | neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu); | ||
| 160 | |||
| 161 | if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | ||
| 162 | batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing); | ||
| 163 | |||
| 164 | kfree(neigh_ifinfo); | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 168 | * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free | ||
| 169 | * the neigh_ifinfo (without rcu callback) | ||
| 170 | * @neigh_ifinfo: the neigh_ifinfo object to release | ||
| 171 | */ | ||
| 172 | static void | ||
| 173 | batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo) | ||
| 174 | { | ||
| 175 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | ||
| 176 | batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu); | ||
| 177 | } | ||
| 178 | |||
| 179 | /** | ||
| 180 | * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free | ||
| 181 | * the neigh_ifinfo | ||
| 182 | * @neigh_ifinfo: the neigh_ifinfo object to release | ||
| 183 | */ | ||
| 184 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) | ||
| 185 | { | ||
| 186 | if (atomic_dec_and_test(&neigh_ifinfo->refcount)) | ||
| 187 | call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu); | ||
| 188 | } | ||
| 189 | |||
| 190 | /** | ||
| 191 | * batadv_neigh_node_free_rcu - free the neigh_node | ||
| 192 | * @rcu: rcu pointer of the neigh_node | ||
| 193 | */ | ||
| 194 | static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) | ||
| 195 | { | ||
| 196 | struct hlist_node *node_tmp; | ||
| 197 | struct batadv_neigh_node *neigh_node; | ||
| 198 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 199 | |||
| 200 | neigh_node = container_of(rcu, struct batadv_neigh_node, rcu); | ||
| 201 | |||
| 202 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, | ||
| 203 | &neigh_node->ifinfo_list, list) { | ||
| 204 | batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); | ||
| 205 | } | ||
| 206 | batadv_hardif_free_ref_now(neigh_node->if_incoming); | ||
| 207 | |||
| 208 | kfree(neigh_node); | ||
| 209 | } | ||
| 210 | |||
| 211 | /** | ||
| 212 | * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter | ||
| 213 | * and possibly free it (without rcu callback) | ||
| 214 | * @neigh_node: neigh neighbor to free | ||
| 215 | */ | ||
| 216 | static void | ||
| 217 | batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node) | ||
| 218 | { | ||
| 219 | if (atomic_dec_and_test(&neigh_node->refcount)) | ||
| 220 | batadv_neigh_node_free_rcu(&neigh_node->rcu); | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * batadv_neigh_node_free_ref - decrement the neighbors refcounter | ||
| 225 | * and possibly free it | ||
| 226 | * @neigh_node: neigh neighbor to free | ||
| 227 | */ | ||
| 151 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) | 228 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) |
| 152 | { | 229 | { |
| 153 | if (atomic_dec_and_test(&neigh_node->refcount)) | 230 | if (atomic_dec_and_test(&neigh_node->refcount)) |
| 154 | kfree_rcu(neigh_node, rcu); | 231 | call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); |
| 155 | } | 232 | } |
| 156 | 233 | ||
| 157 | /* increases the refcounter of a found router */ | 234 | /** |
| 235 | * batadv_orig_node_get_router - router to the originator depending on iface | ||
| 236 | * @orig_node: the orig node for the router | ||
| 237 | * @if_outgoing: the interface where the payload packet has been received or | ||
| 238 | * the OGM should be sent to | ||
| 239 | * | ||
| 240 | * Returns the neighbor which should be router for this orig_node/iface. | ||
| 241 | * | ||
| 242 | * The object is returned with refcounter increased by 1. | ||
| 243 | */ | ||
| 158 | struct batadv_neigh_node * | 244 | struct batadv_neigh_node * |
| 159 | batadv_orig_node_get_router(struct batadv_orig_node *orig_node) | 245 | batadv_orig_router_get(struct batadv_orig_node *orig_node, |
| 246 | const struct batadv_hard_iface *if_outgoing) | ||
| 160 | { | 247 | { |
| 161 | struct batadv_neigh_node *router; | 248 | struct batadv_orig_ifinfo *orig_ifinfo; |
| 249 | struct batadv_neigh_node *router = NULL; | ||
| 162 | 250 | ||
| 163 | rcu_read_lock(); | 251 | rcu_read_lock(); |
| 164 | router = rcu_dereference(orig_node->router); | 252 | hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) { |
| 253 | if (orig_ifinfo->if_outgoing != if_outgoing) | ||
| 254 | continue; | ||
| 255 | |||
| 256 | router = rcu_dereference(orig_ifinfo->router); | ||
| 257 | break; | ||
| 258 | } | ||
| 165 | 259 | ||
| 166 | if (router && !atomic_inc_not_zero(&router->refcount)) | 260 | if (router && !atomic_inc_not_zero(&router->refcount)) |
| 167 | router = NULL; | 261 | router = NULL; |
| @@ -171,6 +265,164 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node) | |||
| 171 | } | 265 | } |
| 172 | 266 | ||
| 173 | /** | 267 | /** |
| 268 | * batadv_orig_ifinfo_get - find the ifinfo from an orig_node | ||
| 269 | * @orig_node: the orig node to be queried | ||
| 270 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 271 | * | ||
| 272 | * Returns the requested orig_ifinfo or NULL if not found. | ||
| 273 | * | ||
| 274 | * The object is returned with refcounter increased by 1. | ||
| 275 | */ | ||
| 276 | struct batadv_orig_ifinfo * | ||
| 277 | batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, | ||
| 278 | struct batadv_hard_iface *if_outgoing) | ||
| 279 | { | ||
| 280 | struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL; | ||
| 281 | |||
| 282 | rcu_read_lock(); | ||
| 283 | hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list, | ||
| 284 | list) { | ||
| 285 | if (tmp->if_outgoing != if_outgoing) | ||
| 286 | continue; | ||
| 287 | |||
| 288 | if (!atomic_inc_not_zero(&tmp->refcount)) | ||
| 289 | continue; | ||
| 290 | |||
| 291 | orig_ifinfo = tmp; | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | rcu_read_unlock(); | ||
| 295 | |||
| 296 | return orig_ifinfo; | ||
| 297 | } | ||
| 298 | |||
| 299 | /** | ||
| 300 | * batadv_orig_ifinfo_new - search and possibly create an orig_ifinfo object | ||
| 301 | * @orig_node: the orig node to be queried | ||
| 302 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 303 | * | ||
| 304 | * Returns NULL in case of failure or the orig_ifinfo object for the if_outgoing | ||
| 305 | * interface otherwise. The object is created and added to the list | ||
| 306 | * if it does not exist. | ||
| 307 | * | ||
| 308 | * The object is returned with refcounter increased by 1. | ||
| 309 | */ | ||
| 310 | struct batadv_orig_ifinfo * | ||
| 311 | batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, | ||
| 312 | struct batadv_hard_iface *if_outgoing) | ||
| 313 | { | ||
| 314 | struct batadv_orig_ifinfo *orig_ifinfo = NULL; | ||
| 315 | unsigned long reset_time; | ||
| 316 | |||
| 317 | spin_lock_bh(&orig_node->neigh_list_lock); | ||
| 318 | |||
| 319 | orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing); | ||
| 320 | if (orig_ifinfo) | ||
| 321 | goto out; | ||
| 322 | |||
| 323 | orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC); | ||
| 324 | if (!orig_ifinfo) | ||
| 325 | goto out; | ||
| 326 | |||
| 327 | if (if_outgoing != BATADV_IF_DEFAULT && | ||
| 328 | !atomic_inc_not_zero(&if_outgoing->refcount)) { | ||
| 329 | kfree(orig_ifinfo); | ||
| 330 | orig_ifinfo = NULL; | ||
| 331 | goto out; | ||
| 332 | } | ||
| 333 | |||
| 334 | reset_time = jiffies - 1; | ||
| 335 | reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); | ||
| 336 | orig_ifinfo->batman_seqno_reset = reset_time; | ||
| 337 | orig_ifinfo->if_outgoing = if_outgoing; | ||
| 338 | INIT_HLIST_NODE(&orig_ifinfo->list); | ||
| 339 | atomic_set(&orig_ifinfo->refcount, 2); | ||
| 340 | hlist_add_head_rcu(&orig_ifinfo->list, | ||
| 341 | &orig_node->ifinfo_list); | ||
| 342 | out: | ||
| 343 | spin_unlock_bh(&orig_node->neigh_list_lock); | ||
| 344 | return orig_ifinfo; | ||
| 345 | } | ||
| 346 | |||
| 347 | /** | ||
| 348 | * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node | ||
| 349 | * @neigh_node: the neigh node to be queried | ||
| 350 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 351 | * | ||
| 352 | * The object is returned with refcounter increased by 1. | ||
| 353 | * | ||
| 354 | * Returns the requested neigh_ifinfo or NULL if not found | ||
| 355 | */ | ||
| 356 | struct batadv_neigh_ifinfo * | ||
| 357 | batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, | ||
| 358 | struct batadv_hard_iface *if_outgoing) | ||
| 359 | { | ||
| 360 | struct batadv_neigh_ifinfo *neigh_ifinfo = NULL, | ||
| 361 | *tmp_neigh_ifinfo; | ||
| 362 | |||
| 363 | rcu_read_lock(); | ||
| 364 | hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list, | ||
| 365 | list) { | ||
| 366 | if (tmp_neigh_ifinfo->if_outgoing != if_outgoing) | ||
| 367 | continue; | ||
| 368 | |||
| 369 | if (!atomic_inc_not_zero(&tmp_neigh_ifinfo->refcount)) | ||
| 370 | continue; | ||
| 371 | |||
| 372 | neigh_ifinfo = tmp_neigh_ifinfo; | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | rcu_read_unlock(); | ||
| 376 | |||
| 377 | return neigh_ifinfo; | ||
| 378 | } | ||
| 379 | |||
| 380 | /** | ||
| 381 | * batadv_neigh_ifinfo_new - search and possibly create an neigh_ifinfo object | ||
| 382 | * @neigh_node: the neigh node to be queried | ||
| 383 | * @if_outgoing: the interface for which the ifinfo should be acquired | ||
| 384 | * | ||
| 385 | * Returns NULL in case of failure or the neigh_ifinfo object for the | ||
| 386 | * if_outgoing interface otherwise. The object is created and added to the list | ||
| 387 | * if it does not exist. | ||
| 388 | * | ||
| 389 | * The object is returned with refcounter increased by 1. | ||
| 390 | */ | ||
| 391 | struct batadv_neigh_ifinfo * | ||
| 392 | batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, | ||
| 393 | struct batadv_hard_iface *if_outgoing) | ||
| 394 | { | ||
| 395 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
| 396 | |||
| 397 | spin_lock_bh(&neigh->ifinfo_lock); | ||
| 398 | |||
| 399 | neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing); | ||
| 400 | if (neigh_ifinfo) | ||
| 401 | goto out; | ||
| 402 | |||
| 403 | neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC); | ||
| 404 | if (!neigh_ifinfo) | ||
| 405 | goto out; | ||
| 406 | |||
| 407 | if (if_outgoing && !atomic_inc_not_zero(&if_outgoing->refcount)) { | ||
| 408 | kfree(neigh_ifinfo); | ||
| 409 | neigh_ifinfo = NULL; | ||
| 410 | goto out; | ||
| 411 | } | ||
| 412 | |||
| 413 | INIT_HLIST_NODE(&neigh_ifinfo->list); | ||
| 414 | atomic_set(&neigh_ifinfo->refcount, 2); | ||
| 415 | neigh_ifinfo->if_outgoing = if_outgoing; | ||
| 416 | |||
| 417 | hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list); | ||
| 418 | |||
| 419 | out: | ||
| 420 | spin_unlock_bh(&neigh->ifinfo_lock); | ||
| 421 | |||
| 422 | return neigh_ifinfo; | ||
| 423 | } | ||
| 424 | |||
| 425 | /** | ||
| 174 | * batadv_neigh_node_new - create and init a new neigh_node object | 426 | * batadv_neigh_node_new - create and init a new neigh_node object |
| 175 | * @hard_iface: the interface where the neighbour is connected to | 427 | * @hard_iface: the interface where the neighbour is connected to |
| 176 | * @neigh_addr: the mac address of the neighbour interface | 428 | * @neigh_addr: the mac address of the neighbour interface |
| @@ -191,13 +443,13 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | |||
| 191 | goto out; | 443 | goto out; |
| 192 | 444 | ||
| 193 | INIT_HLIST_NODE(&neigh_node->list); | 445 | INIT_HLIST_NODE(&neigh_node->list); |
| 446 | INIT_HLIST_HEAD(&neigh_node->ifinfo_list); | ||
| 447 | spin_lock_init(&neigh_node->ifinfo_lock); | ||
| 194 | 448 | ||
| 195 | memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); | 449 | memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); |
| 196 | neigh_node->if_incoming = hard_iface; | 450 | neigh_node->if_incoming = hard_iface; |
| 197 | neigh_node->orig_node = orig_node; | 451 | neigh_node->orig_node = orig_node; |
| 198 | 452 | ||
| 199 | INIT_LIST_HEAD(&neigh_node->bonding_list); | ||
| 200 | |||
| 201 | /* extra reference for return */ | 453 | /* extra reference for return */ |
| 202 | atomic_set(&neigh_node->refcount, 2); | 454 | atomic_set(&neigh_node->refcount, 2); |
| 203 | 455 | ||
| @@ -205,30 +457,68 @@ out: | |||
| 205 | return neigh_node; | 457 | return neigh_node; |
| 206 | } | 458 | } |
| 207 | 459 | ||
| 460 | /** | ||
| 461 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object | ||
| 462 | * @rcu: rcu pointer of the orig_ifinfo object | ||
| 463 | */ | ||
| 464 | static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) | ||
| 465 | { | ||
| 466 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
| 467 | |||
| 468 | orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); | ||
| 469 | |||
| 470 | if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | ||
| 471 | batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); | ||
| 472 | |||
| 473 | kfree(orig_ifinfo); | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free | ||
| 478 | * the orig_ifinfo (without rcu callback) | ||
| 479 | * @orig_ifinfo: the orig_ifinfo object to release | ||
| 480 | */ | ||
| 481 | static void | ||
| 482 | batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo) | ||
| 483 | { | ||
| 484 | if (atomic_dec_and_test(&orig_ifinfo->refcount)) | ||
| 485 | batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu); | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free | ||
| 490 | * the orig_ifinfo | ||
| 491 | * @orig_ifinfo: the orig_ifinfo object to release | ||
| 492 | */ | ||
| 493 | void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) | ||
| 494 | { | ||
| 495 | if (atomic_dec_and_test(&orig_ifinfo->refcount)) | ||
| 496 | call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu); | ||
| 497 | } | ||
| 498 | |||
| 208 | static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | 499 | static void batadv_orig_node_free_rcu(struct rcu_head *rcu) |
| 209 | { | 500 | { |
| 210 | struct hlist_node *node_tmp; | 501 | struct hlist_node *node_tmp; |
| 211 | struct batadv_neigh_node *neigh_node, *tmp_neigh_node; | 502 | struct batadv_neigh_node *neigh_node; |
| 212 | struct batadv_orig_node *orig_node; | 503 | struct batadv_orig_node *orig_node; |
| 504 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
| 213 | 505 | ||
| 214 | orig_node = container_of(rcu, struct batadv_orig_node, rcu); | 506 | orig_node = container_of(rcu, struct batadv_orig_node, rcu); |
| 215 | 507 | ||
| 216 | spin_lock_bh(&orig_node->neigh_list_lock); | 508 | spin_lock_bh(&orig_node->neigh_list_lock); |
| 217 | 509 | ||
| 218 | /* for all bonding members ... */ | ||
| 219 | list_for_each_entry_safe(neigh_node, tmp_neigh_node, | ||
| 220 | &orig_node->bond_list, bonding_list) { | ||
| 221 | list_del_rcu(&neigh_node->bonding_list); | ||
| 222 | batadv_neigh_node_free_ref(neigh_node); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* for all neighbors towards this originator ... */ | 510 | /* for all neighbors towards this originator ... */ |
| 226 | hlist_for_each_entry_safe(neigh_node, node_tmp, | 511 | hlist_for_each_entry_safe(neigh_node, node_tmp, |
| 227 | &orig_node->neigh_list, list) { | 512 | &orig_node->neigh_list, list) { |
| 228 | hlist_del_rcu(&neigh_node->list); | 513 | hlist_del_rcu(&neigh_node->list); |
| 229 | batadv_neigh_node_free_ref(neigh_node); | 514 | batadv_neigh_node_free_ref_now(neigh_node); |
| 230 | } | 515 | } |
| 231 | 516 | ||
| 517 | hlist_for_each_entry_safe(orig_ifinfo, node_tmp, | ||
| 518 | &orig_node->ifinfo_list, list) { | ||
| 519 | hlist_del_rcu(&orig_ifinfo->list); | ||
| 520 | batadv_orig_ifinfo_free_ref_now(orig_ifinfo); | ||
| 521 | } | ||
| 232 | spin_unlock_bh(&orig_node->neigh_list_lock); | 522 | spin_unlock_bh(&orig_node->neigh_list_lock); |
| 233 | 523 | ||
| 234 | /* Free nc_nodes */ | 524 | /* Free nc_nodes */ |
| @@ -325,8 +615,8 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | |||
| 325 | return NULL; | 615 | return NULL; |
| 326 | 616 | ||
| 327 | INIT_HLIST_HEAD(&orig_node->neigh_list); | 617 | INIT_HLIST_HEAD(&orig_node->neigh_list); |
| 328 | INIT_LIST_HEAD(&orig_node->bond_list); | ||
| 329 | INIT_LIST_HEAD(&orig_node->vlan_list); | 618 | INIT_LIST_HEAD(&orig_node->vlan_list); |
| 619 | INIT_HLIST_HEAD(&orig_node->ifinfo_list); | ||
| 330 | spin_lock_init(&orig_node->bcast_seqno_lock); | 620 | spin_lock_init(&orig_node->bcast_seqno_lock); |
| 331 | spin_lock_init(&orig_node->neigh_list_lock); | 621 | spin_lock_init(&orig_node->neigh_list_lock); |
| 332 | spin_lock_init(&orig_node->tt_buff_lock); | 622 | spin_lock_init(&orig_node->tt_buff_lock); |
| @@ -342,15 +632,11 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | |||
| 342 | orig_node->bat_priv = bat_priv; | 632 | orig_node->bat_priv = bat_priv; |
| 343 | memcpy(orig_node->orig, addr, ETH_ALEN); | 633 | memcpy(orig_node->orig, addr, ETH_ALEN); |
| 344 | batadv_dat_init_orig_node_addr(orig_node); | 634 | batadv_dat_init_orig_node_addr(orig_node); |
| 345 | orig_node->router = NULL; | ||
| 346 | atomic_set(&orig_node->last_ttvn, 0); | 635 | atomic_set(&orig_node->last_ttvn, 0); |
| 347 | orig_node->tt_buff = NULL; | 636 | orig_node->tt_buff = NULL; |
| 348 | orig_node->tt_buff_len = 0; | 637 | orig_node->tt_buff_len = 0; |
| 349 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); | 638 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); |
| 350 | orig_node->bcast_seqno_reset = reset_time; | 639 | orig_node->bcast_seqno_reset = reset_time; |
| 351 | orig_node->batman_seqno_reset = reset_time; | ||
| 352 | |||
| 353 | atomic_set(&orig_node->bond_candidates, 0); | ||
| 354 | 640 | ||
| 355 | /* create a vlan object for the "untagged" LAN */ | 641 | /* create a vlan object for the "untagged" LAN */ |
| 356 | vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); | 642 | vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); |
| @@ -374,20 +660,76 @@ free_orig_node: | |||
| 374 | return NULL; | 660 | return NULL; |
| 375 | } | 661 | } |
| 376 | 662 | ||
| 663 | /** | ||
| 664 | * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator | ||
| 665 | * @bat_priv: the bat priv with all the soft interface information | ||
| 666 | * @orig_node: orig node which is to be checked | ||
| 667 | * | ||
| 668 | * Returns true if any ifinfo entry was purged, false otherwise. | ||
| 669 | */ | ||
| 670 | static bool | ||
| 671 | batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv, | ||
| 672 | struct batadv_orig_node *orig_node) | ||
| 673 | { | ||
| 674 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
| 675 | struct batadv_hard_iface *if_outgoing; | ||
| 676 | struct hlist_node *node_tmp; | ||
| 677 | bool ifinfo_purged = false; | ||
| 678 | |||
| 679 | spin_lock_bh(&orig_node->neigh_list_lock); | ||
| 680 | |||
| 681 | /* for all ifinfo objects for this originator */ | ||
| 682 | hlist_for_each_entry_safe(orig_ifinfo, node_tmp, | ||
| 683 | &orig_node->ifinfo_list, list) { | ||
| 684 | if_outgoing = orig_ifinfo->if_outgoing; | ||
| 685 | |||
| 686 | /* always keep the default interface */ | ||
| 687 | if (if_outgoing == BATADV_IF_DEFAULT) | ||
| 688 | continue; | ||
| 689 | |||
| 690 | /* don't purge if the interface is not (going) down */ | ||
| 691 | if ((if_outgoing->if_status != BATADV_IF_INACTIVE) && | ||
| 692 | (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) && | ||
| 693 | (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)) | ||
| 694 | continue; | ||
| 695 | |||
| 696 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
| 697 | "router/ifinfo purge: originator %pM, iface: %s\n", | ||
| 698 | orig_node->orig, if_outgoing->net_dev->name); | ||
| 699 | |||
| 700 | ifinfo_purged = true; | ||
| 701 | |||
| 702 | hlist_del_rcu(&orig_ifinfo->list); | ||
| 703 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 704 | if (orig_node->last_bonding_candidate == orig_ifinfo) { | ||
| 705 | orig_node->last_bonding_candidate = NULL; | ||
| 706 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | spin_unlock_bh(&orig_node->neigh_list_lock); | ||
| 711 | |||
| 712 | return ifinfo_purged; | ||
| 713 | } | ||
| 714 | |||
| 715 | |||
| 716 | /** | ||
| 717 | * batadv_purge_orig_neighbors - purges neighbors from originator | ||
| 718 | * @bat_priv: the bat priv with all the soft interface information | ||
| 719 | * @orig_node: orig node which is to be checked | ||
| 720 | * | ||
| 721 | * Returns true if any neighbor was purged, false otherwise | ||
| 722 | */ | ||
| 377 | static bool | 723 | static bool |
| 378 | batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | 724 | batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, |
| 379 | struct batadv_orig_node *orig_node, | 725 | struct batadv_orig_node *orig_node) |
| 380 | struct batadv_neigh_node **best_neigh) | ||
| 381 | { | 726 | { |
| 382 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 383 | struct hlist_node *node_tmp; | 727 | struct hlist_node *node_tmp; |
| 384 | struct batadv_neigh_node *neigh_node; | 728 | struct batadv_neigh_node *neigh_node; |
| 385 | bool neigh_purged = false; | 729 | bool neigh_purged = false; |
| 386 | unsigned long last_seen; | 730 | unsigned long last_seen; |
| 387 | struct batadv_hard_iface *if_incoming; | 731 | struct batadv_hard_iface *if_incoming; |
| 388 | 732 | ||
| 389 | *best_neigh = NULL; | ||
| 390 | |||
| 391 | spin_lock_bh(&orig_node->neigh_list_lock); | 733 | spin_lock_bh(&orig_node->neigh_list_lock); |
| 392 | 734 | ||
| 393 | /* for all neighbors towards this originator ... */ | 735 | /* for all neighbors towards this originator ... */ |
| @@ -416,15 +758,7 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | |||
| 416 | neigh_purged = true; | 758 | neigh_purged = true; |
| 417 | 759 | ||
| 418 | hlist_del_rcu(&neigh_node->list); | 760 | hlist_del_rcu(&neigh_node->list); |
| 419 | batadv_bonding_candidate_del(orig_node, neigh_node); | ||
| 420 | batadv_neigh_node_free_ref(neigh_node); | 761 | batadv_neigh_node_free_ref(neigh_node); |
| 421 | } else { | ||
| 422 | /* store the best_neighbour if this is the first | ||
| 423 | * iteration or if a better neighbor has been found | ||
| 424 | */ | ||
| 425 | if (!*best_neigh || | ||
| 426 | bao->bat_neigh_cmp(neigh_node, *best_neigh) > 0) | ||
| 427 | *best_neigh = neigh_node; | ||
| 428 | } | 762 | } |
| 429 | } | 763 | } |
| 430 | 764 | ||
| @@ -432,10 +766,57 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | |||
| 432 | return neigh_purged; | 766 | return neigh_purged; |
| 433 | } | 767 | } |
| 434 | 768 | ||
| 769 | /** | ||
| 770 | * batadv_find_best_neighbor - finds the best neighbor after purging | ||
| 771 | * @bat_priv: the bat priv with all the soft interface information | ||
| 772 | * @orig_node: orig node which is to be checked | ||
| 773 | * @if_outgoing: the interface for which the metric should be compared | ||
| 774 | * | ||
| 775 | * Returns the current best neighbor, with refcount increased. | ||
| 776 | */ | ||
| 777 | static struct batadv_neigh_node * | ||
| 778 | batadv_find_best_neighbor(struct batadv_priv *bat_priv, | ||
| 779 | struct batadv_orig_node *orig_node, | ||
| 780 | struct batadv_hard_iface *if_outgoing) | ||
| 781 | { | ||
| 782 | struct batadv_neigh_node *best = NULL, *neigh; | ||
| 783 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 784 | |||
| 785 | rcu_read_lock(); | ||
| 786 | hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) { | ||
| 787 | if (best && (bao->bat_neigh_cmp(neigh, if_outgoing, | ||
| 788 | best, if_outgoing) <= 0)) | ||
| 789 | continue; | ||
| 790 | |||
| 791 | if (!atomic_inc_not_zero(&neigh->refcount)) | ||
| 792 | continue; | ||
| 793 | |||
| 794 | if (best) | ||
| 795 | batadv_neigh_node_free_ref(best); | ||
| 796 | |||
| 797 | best = neigh; | ||
| 798 | } | ||
| 799 | rcu_read_unlock(); | ||
| 800 | |||
| 801 | return best; | ||
| 802 | } | ||
| 803 | |||
| 804 | /** | ||
| 805 | * batadv_purge_orig_node - purges obsolete information from an orig_node | ||
| 806 | * @bat_priv: the bat priv with all the soft interface information | ||
| 807 | * @orig_node: orig node which is to be checked | ||
| 808 | * | ||
| 809 | * This function checks if the orig_node or substructures of it have become | ||
| 810 | * obsolete, and purges this information if that's the case. | ||
| 811 | * | ||
| 812 | * Returns true if the orig_node is to be removed, false otherwise. | ||
| 813 | */ | ||
| 435 | static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | 814 | static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, |
| 436 | struct batadv_orig_node *orig_node) | 815 | struct batadv_orig_node *orig_node) |
| 437 | { | 816 | { |
| 438 | struct batadv_neigh_node *best_neigh_node; | 817 | struct batadv_neigh_node *best_neigh_node; |
| 818 | struct batadv_hard_iface *hard_iface; | ||
| 819 | bool changed; | ||
| 439 | 820 | ||
| 440 | if (batadv_has_timed_out(orig_node->last_seen, | 821 | if (batadv_has_timed_out(orig_node->last_seen, |
| 441 | 2 * BATADV_PURGE_TIMEOUT)) { | 822 | 2 * BATADV_PURGE_TIMEOUT)) { |
| @@ -444,12 +825,39 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | |||
| 444 | orig_node->orig, | 825 | orig_node->orig, |
| 445 | jiffies_to_msecs(orig_node->last_seen)); | 826 | jiffies_to_msecs(orig_node->last_seen)); |
| 446 | return true; | 827 | return true; |
| 447 | } else { | ||
| 448 | if (batadv_purge_orig_neighbors(bat_priv, orig_node, | ||
| 449 | &best_neigh_node)) | ||
| 450 | batadv_update_route(bat_priv, orig_node, | ||
| 451 | best_neigh_node); | ||
| 452 | } | 828 | } |
| 829 | changed = batadv_purge_orig_ifinfo(bat_priv, orig_node); | ||
| 830 | changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node); | ||
| 831 | |||
| 832 | if (!changed) | ||
| 833 | return false; | ||
| 834 | |||
| 835 | /* first for NULL ... */ | ||
| 836 | best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, | ||
| 837 | BATADV_IF_DEFAULT); | ||
| 838 | batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT, | ||
| 839 | best_neigh_node); | ||
| 840 | if (best_neigh_node) | ||
| 841 | batadv_neigh_node_free_ref(best_neigh_node); | ||
| 842 | |||
| 843 | /* ... then for all other interfaces. */ | ||
| 844 | rcu_read_lock(); | ||
| 845 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | ||
| 846 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | ||
| 847 | continue; | ||
| 848 | |||
| 849 | if (hard_iface->soft_iface != bat_priv->soft_iface) | ||
| 850 | continue; | ||
| 851 | |||
| 852 | best_neigh_node = batadv_find_best_neighbor(bat_priv, | ||
| 853 | orig_node, | ||
| 854 | hard_iface); | ||
| 855 | batadv_update_route(bat_priv, orig_node, hard_iface, | ||
| 856 | best_neigh_node); | ||
| 857 | if (best_neigh_node) | ||
| 858 | batadv_neigh_node_free_ref(best_neigh_node); | ||
| 859 | } | ||
| 860 | rcu_read_unlock(); | ||
| 453 | 861 | ||
| 454 | return false; | 862 | return false; |
| 455 | } | 863 | } |
| @@ -532,8 +940,54 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) | |||
| 532 | return 0; | 940 | return 0; |
| 533 | } | 941 | } |
| 534 | 942 | ||
| 535 | bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq); | 943 | bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, |
| 944 | BATADV_IF_DEFAULT); | ||
| 945 | |||
| 946 | return 0; | ||
| 947 | } | ||
| 948 | |||
| 949 | /** | ||
| 950 | * batadv_orig_hardif_seq_print_text - writes originator infos for a specific | ||
| 951 | * outgoing interface | ||
| 952 | * @seq: debugfs table seq_file struct | ||
| 953 | * @offset: not used | ||
| 954 | * | ||
| 955 | * Returns 0 | ||
| 956 | */ | ||
| 957 | int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) | ||
| 958 | { | ||
| 959 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
| 960 | struct batadv_hard_iface *hard_iface; | ||
| 961 | struct batadv_priv *bat_priv; | ||
| 962 | |||
| 963 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | ||
| 964 | |||
| 965 | if (!hard_iface || !hard_iface->soft_iface) { | ||
| 966 | seq_puts(seq, "Interface not known to B.A.T.M.A.N.\n"); | ||
| 967 | goto out; | ||
| 968 | } | ||
| 969 | |||
| 970 | bat_priv = netdev_priv(hard_iface->soft_iface); | ||
| 971 | if (!bat_priv->bat_algo_ops->bat_orig_print) { | ||
| 972 | seq_puts(seq, | ||
| 973 | "No printing function for this routing protocol\n"); | ||
| 974 | goto out; | ||
| 975 | } | ||
| 976 | |||
| 977 | if (hard_iface->if_status != BATADV_IF_ACTIVE) { | ||
| 978 | seq_puts(seq, "Interface not active\n"); | ||
| 979 | goto out; | ||
| 980 | } | ||
| 536 | 981 | ||
| 982 | seq_printf(seq, "[B.A.T.M.A.N. adv %s, IF/MAC: %s/%pM (%s %s)]\n", | ||
| 983 | BATADV_SOURCE_VERSION, hard_iface->net_dev->name, | ||
| 984 | hard_iface->net_dev->dev_addr, | ||
| 985 | hard_iface->soft_iface->name, bat_priv->bat_algo_ops->name); | ||
| 986 | |||
| 987 | bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); | ||
| 988 | |||
| 989 | out: | ||
| 990 | batadv_hardif_free_ref(hard_iface); | ||
| 537 | return 0; | 991 | return 0; |
| 538 | } | 992 | } |
| 539 | 993 | ||
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 99ed3c61e4f9..37be290f63f6 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -34,8 +34,26 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | |||
| 34 | struct batadv_orig_node *orig_node); | 34 | struct batadv_orig_node *orig_node); |
| 35 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); | 35 | void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); |
| 36 | struct batadv_neigh_node * | 36 | struct batadv_neigh_node * |
| 37 | batadv_orig_node_get_router(struct batadv_orig_node *orig_node); | 37 | batadv_orig_router_get(struct batadv_orig_node *orig_node, |
| 38 | const struct batadv_hard_iface *if_outgoing); | ||
| 39 | struct batadv_neigh_ifinfo * | ||
| 40 | batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, | ||
| 41 | struct batadv_hard_iface *if_outgoing); | ||
| 42 | struct batadv_neigh_ifinfo * | ||
| 43 | batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, | ||
| 44 | struct batadv_hard_iface *if_outgoing); | ||
| 45 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); | ||
| 46 | |||
| 47 | struct batadv_orig_ifinfo * | ||
| 48 | batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, | ||
| 49 | struct batadv_hard_iface *if_outgoing); | ||
| 50 | struct batadv_orig_ifinfo * | ||
| 51 | batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, | ||
| 52 | struct batadv_hard_iface *if_outgoing); | ||
| 53 | void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo); | ||
| 54 | |||
| 38 | int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); | 55 | int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); |
| 56 | int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset); | ||
| 39 | int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, | 57 | int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, |
| 40 | int max_if_num); | 58 | int max_if_num); |
| 41 | int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, | 59 | int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index ef2010c27146..0a381d1174c1 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7e8aa177eb1d..1ed9f7c9ecea 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -33,13 +33,32 @@ | |||
| 33 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 33 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
| 34 | struct batadv_hard_iface *recv_if); | 34 | struct batadv_hard_iface *recv_if); |
| 35 | 35 | ||
| 36 | /** | ||
| 37 | * _batadv_update_route - set the router for this originator | ||
| 38 | * @bat_priv: the bat priv with all the soft interface information | ||
| 39 | * @orig_node: orig node which is to be configured | ||
| 40 | * @recv_if: the receive interface for which this route is set | ||
| 41 | * @neigh_node: neighbor which should be the next router | ||
| 42 | * | ||
| 43 | * This function does not perform any error checks | ||
| 44 | */ | ||
| 36 | static void _batadv_update_route(struct batadv_priv *bat_priv, | 45 | static void _batadv_update_route(struct batadv_priv *bat_priv, |
| 37 | struct batadv_orig_node *orig_node, | 46 | struct batadv_orig_node *orig_node, |
| 47 | struct batadv_hard_iface *recv_if, | ||
| 38 | struct batadv_neigh_node *neigh_node) | 48 | struct batadv_neigh_node *neigh_node) |
| 39 | { | 49 | { |
| 50 | struct batadv_orig_ifinfo *orig_ifinfo; | ||
| 40 | struct batadv_neigh_node *curr_router; | 51 | struct batadv_neigh_node *curr_router; |
| 41 | 52 | ||
| 42 | curr_router = batadv_orig_node_get_router(orig_node); | 53 | orig_ifinfo = batadv_orig_ifinfo_get(orig_node, recv_if); |
| 54 | if (!orig_ifinfo) | ||
| 55 | return; | ||
| 56 | |||
| 57 | rcu_read_lock(); | ||
| 58 | curr_router = rcu_dereference(orig_ifinfo->router); | ||
| 59 | if (curr_router && !atomic_inc_not_zero(&curr_router->refcount)) | ||
| 60 | curr_router = NULL; | ||
| 61 | rcu_read_unlock(); | ||
| 43 | 62 | ||
| 44 | /* route deleted */ | 63 | /* route deleted */ |
| 45 | if ((curr_router) && (!neigh_node)) { | 64 | if ((curr_router) && (!neigh_node)) { |
| @@ -69,16 +88,25 @@ static void _batadv_update_route(struct batadv_priv *bat_priv, | |||
| 69 | neigh_node = NULL; | 88 | neigh_node = NULL; |
| 70 | 89 | ||
| 71 | spin_lock_bh(&orig_node->neigh_list_lock); | 90 | spin_lock_bh(&orig_node->neigh_list_lock); |
| 72 | rcu_assign_pointer(orig_node->router, neigh_node); | 91 | rcu_assign_pointer(orig_ifinfo->router, neigh_node); |
| 73 | spin_unlock_bh(&orig_node->neigh_list_lock); | 92 | spin_unlock_bh(&orig_node->neigh_list_lock); |
| 93 | batadv_orig_ifinfo_free_ref(orig_ifinfo); | ||
| 74 | 94 | ||
| 75 | /* decrease refcount of previous best neighbor */ | 95 | /* decrease refcount of previous best neighbor */ |
| 76 | if (curr_router) | 96 | if (curr_router) |
| 77 | batadv_neigh_node_free_ref(curr_router); | 97 | batadv_neigh_node_free_ref(curr_router); |
| 78 | } | 98 | } |
| 79 | 99 | ||
| 100 | /** | ||
| 101 | * batadv_update_route - set the router for this originator | ||
| 102 | * @bat_priv: the bat priv with all the soft interface information | ||
| 103 | * @orig_node: orig node which is to be configured | ||
| 104 | * @recv_if: the receive interface for which this route is set | ||
| 105 | * @neigh_node: neighbor which should be the next router | ||
| 106 | */ | ||
| 80 | void batadv_update_route(struct batadv_priv *bat_priv, | 107 | void batadv_update_route(struct batadv_priv *bat_priv, |
| 81 | struct batadv_orig_node *orig_node, | 108 | struct batadv_orig_node *orig_node, |
| 109 | struct batadv_hard_iface *recv_if, | ||
| 82 | struct batadv_neigh_node *neigh_node) | 110 | struct batadv_neigh_node *neigh_node) |
| 83 | { | 111 | { |
| 84 | struct batadv_neigh_node *router = NULL; | 112 | struct batadv_neigh_node *router = NULL; |
| @@ -86,125 +114,16 @@ void batadv_update_route(struct batadv_priv *bat_priv, | |||
| 86 | if (!orig_node) | 114 | if (!orig_node) |
| 87 | goto out; | 115 | goto out; |
| 88 | 116 | ||
| 89 | router = batadv_orig_node_get_router(orig_node); | 117 | router = batadv_orig_router_get(orig_node, recv_if); |
| 90 | 118 | ||
| 91 | if (router != neigh_node) | 119 | if (router != neigh_node) |
| 92 | _batadv_update_route(bat_priv, orig_node, neigh_node); | 120 | _batadv_update_route(bat_priv, orig_node, recv_if, neigh_node); |
| 93 | 121 | ||
| 94 | out: | 122 | out: |
| 95 | if (router) | 123 | if (router) |
| 96 | batadv_neigh_node_free_ref(router); | 124 | batadv_neigh_node_free_ref(router); |
| 97 | } | 125 | } |
| 98 | 126 | ||
| 99 | /* caller must hold the neigh_list_lock */ | ||
| 100 | void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node, | ||
| 101 | struct batadv_neigh_node *neigh_node) | ||
| 102 | { | ||
| 103 | /* this neighbor is not part of our candidate list */ | ||
| 104 | if (list_empty(&neigh_node->bonding_list)) | ||
| 105 | goto out; | ||
| 106 | |||
| 107 | list_del_rcu(&neigh_node->bonding_list); | ||
| 108 | INIT_LIST_HEAD(&neigh_node->bonding_list); | ||
| 109 | batadv_neigh_node_free_ref(neigh_node); | ||
| 110 | atomic_dec(&orig_node->bond_candidates); | ||
| 111 | |||
| 112 | out: | ||
| 113 | return; | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * batadv_bonding_candidate_add - consider a new link for bonding mode towards | ||
| 118 | * the given originator | ||
| 119 | * @bat_priv: the bat priv with all the soft interface information | ||
| 120 | * @orig_node: the target node | ||
| 121 | * @neigh_node: the neighbor representing the new link to consider for bonding | ||
| 122 | * mode | ||
| 123 | */ | ||
| 124 | void batadv_bonding_candidate_add(struct batadv_priv *bat_priv, | ||
| 125 | struct batadv_orig_node *orig_node, | ||
| 126 | struct batadv_neigh_node *neigh_node) | ||
| 127 | { | ||
| 128 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 129 | struct batadv_neigh_node *tmp_neigh_node, *router = NULL; | ||
| 130 | uint8_t interference_candidate = 0; | ||
| 131 | |||
| 132 | spin_lock_bh(&orig_node->neigh_list_lock); | ||
| 133 | |||
| 134 | /* only consider if it has the same primary address ... */ | ||
| 135 | if (!batadv_compare_eth(orig_node->orig, | ||
| 136 | neigh_node->orig_node->primary_addr)) | ||
| 137 | goto candidate_del; | ||
| 138 | |||
| 139 | router = batadv_orig_node_get_router(orig_node); | ||
| 140 | if (!router) | ||
| 141 | goto candidate_del; | ||
| 142 | |||
| 143 | |||
| 144 | /* ... and is good enough to be considered */ | ||
| 145 | if (bao->bat_neigh_is_equiv_or_better(neigh_node, router)) | ||
| 146 | goto candidate_del; | ||
| 147 | |||
| 148 | /* check if we have another candidate with the same mac address or | ||
| 149 | * interface. If we do, we won't select this candidate because of | ||
| 150 | * possible interference. | ||
| 151 | */ | ||
| 152 | hlist_for_each_entry_rcu(tmp_neigh_node, | ||
| 153 | &orig_node->neigh_list, list) { | ||
| 154 | if (tmp_neigh_node == neigh_node) | ||
| 155 | continue; | ||
| 156 | |||
| 157 | /* we only care if the other candidate is even | ||
| 158 | * considered as candidate. | ||
| 159 | */ | ||
| 160 | if (list_empty(&tmp_neigh_node->bonding_list)) | ||
| 161 | continue; | ||
| 162 | |||
| 163 | if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) || | ||
| 164 | (batadv_compare_eth(neigh_node->addr, | ||
| 165 | tmp_neigh_node->addr))) { | ||
| 166 | interference_candidate = 1; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | /* don't care further if it is an interference candidate */ | ||
| 172 | if (interference_candidate) | ||
| 173 | goto candidate_del; | ||
| 174 | |||
| 175 | /* this neighbor already is part of our candidate list */ | ||
| 176 | if (!list_empty(&neigh_node->bonding_list)) | ||
| 177 | goto out; | ||
| 178 | |||
| 179 | if (!atomic_inc_not_zero(&neigh_node->refcount)) | ||
| 180 | goto out; | ||
| 181 | |||
| 182 | list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list); | ||
| 183 | atomic_inc(&orig_node->bond_candidates); | ||
| 184 | goto out; | ||
| 185 | |||
| 186 | candidate_del: | ||
| 187 | batadv_bonding_candidate_del(orig_node, neigh_node); | ||
| 188 | |||
| 189 | out: | ||
| 190 | spin_unlock_bh(&orig_node->neigh_list_lock); | ||
| 191 | |||
| 192 | if (router) | ||
| 193 | batadv_neigh_node_free_ref(router); | ||
| 194 | } | ||
| 195 | |||
| 196 | /* copy primary address for bonding */ | ||
| 197 | void | ||
| 198 | batadv_bonding_save_primary(const struct batadv_orig_node *orig_node, | ||
| 199 | struct batadv_orig_node *orig_neigh_node, | ||
| 200 | const struct batadv_ogm_packet *batman_ogm_packet) | ||
| 201 | { | ||
| 202 | if (!(batman_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP)) | ||
| 203 | return; | ||
| 204 | |||
| 205 | memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* checks whether the host restarted and is in the protection time. | 127 | /* checks whether the host restarted and is in the protection time. |
| 209 | * returns: | 128 | * returns: |
| 210 | * 0 if the packet is to be accepted | 129 | * 0 if the packet is to be accepted |
| @@ -459,114 +378,6 @@ out: | |||
| 459 | return ret; | 378 | return ret; |
| 460 | } | 379 | } |
| 461 | 380 | ||
| 462 | /* In the bonding case, send the packets in a round | ||
| 463 | * robin fashion over the remaining interfaces. | ||
| 464 | * | ||
| 465 | * This method rotates the bonding list and increases the | ||
| 466 | * returned router's refcount. | ||
| 467 | */ | ||
| 468 | static struct batadv_neigh_node * | ||
| 469 | batadv_find_bond_router(struct batadv_orig_node *primary_orig, | ||
| 470 | const struct batadv_hard_iface *recv_if) | ||
| 471 | { | ||
| 472 | struct batadv_neigh_node *tmp_neigh_node; | ||
| 473 | struct batadv_neigh_node *router = NULL, *first_candidate = NULL; | ||
| 474 | |||
| 475 | rcu_read_lock(); | ||
| 476 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
| 477 | bonding_list) { | ||
| 478 | if (!first_candidate) | ||
| 479 | first_candidate = tmp_neigh_node; | ||
| 480 | |||
| 481 | /* recv_if == NULL on the first node. */ | ||
| 482 | if (tmp_neigh_node->if_incoming == recv_if) | ||
| 483 | continue; | ||
| 484 | |||
| 485 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
| 486 | continue; | ||
| 487 | |||
| 488 | router = tmp_neigh_node; | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | |||
| 492 | /* use the first candidate if nothing was found. */ | ||
| 493 | if (!router && first_candidate && | ||
| 494 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
| 495 | router = first_candidate; | ||
| 496 | |||
| 497 | if (!router) | ||
| 498 | goto out; | ||
| 499 | |||
| 500 | /* selected should point to the next element | ||
| 501 | * after the current router | ||
| 502 | */ | ||
| 503 | spin_lock_bh(&primary_orig->neigh_list_lock); | ||
| 504 | /* this is a list_move(), which unfortunately | ||
| 505 | * does not exist as rcu version | ||
| 506 | */ | ||
| 507 | list_del_rcu(&primary_orig->bond_list); | ||
| 508 | list_add_rcu(&primary_orig->bond_list, | ||
| 509 | &router->bonding_list); | ||
| 510 | spin_unlock_bh(&primary_orig->neigh_list_lock); | ||
| 511 | |||
| 512 | out: | ||
| 513 | rcu_read_unlock(); | ||
| 514 | return router; | ||
| 515 | } | ||
| 516 | |||
| 517 | /** | ||
| 518 | * batadv_find_ifalter_router - find the best of the remaining candidates which | ||
| 519 | * are not using this interface | ||
| 520 | * @bat_priv: the bat priv with all the soft interface information | ||
| 521 | * @primary_orig: the destination | ||
| 522 | * @recv_if: the interface that the router returned by this function has to not | ||
| 523 | * use | ||
| 524 | * | ||
| 525 | * Returns the best candidate towards primary_orig that is not using recv_if. | ||
| 526 | * Increases the returned neighbor's refcount | ||
| 527 | */ | ||
| 528 | static struct batadv_neigh_node * | ||
| 529 | batadv_find_ifalter_router(struct batadv_priv *bat_priv, | ||
| 530 | struct batadv_orig_node *primary_orig, | ||
| 531 | const struct batadv_hard_iface *recv_if) | ||
| 532 | { | ||
| 533 | struct batadv_neigh_node *router = NULL, *first_candidate = NULL; | ||
| 534 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | ||
| 535 | struct batadv_neigh_node *tmp_neigh_node; | ||
| 536 | |||
| 537 | rcu_read_lock(); | ||
| 538 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
| 539 | bonding_list) { | ||
| 540 | if (!first_candidate) | ||
| 541 | first_candidate = tmp_neigh_node; | ||
| 542 | |||
| 543 | /* recv_if == NULL on the first node. */ | ||
| 544 | if (tmp_neigh_node->if_incoming == recv_if) | ||
| 545 | continue; | ||
| 546 | |||
| 547 | if (router && bao->bat_neigh_cmp(tmp_neigh_node, router)) | ||
| 548 | continue; | ||
| 549 | |||
| 550 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
| 551 | continue; | ||
| 552 | |||
| 553 | /* decrement refcount of previously selected router */ | ||
| 554 | if (router) | ||
| 555 | batadv_neigh_node_free_ref(router); | ||
| 556 | |||
| 557 | /* we found a better router (or at least one valid router) */ | ||
| 558 | router = tmp_neigh_node; | ||
| 559 | } | ||
| 560 | |||
| 561 | /* use the first candidate if nothing was found. */ | ||
| 562 | if (!router && first_candidate && | ||
| 563 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
| 564 | router = first_candidate; | ||
| 565 | |||
| 566 | rcu_read_unlock(); | ||
| 567 | return router; | ||
| 568 | } | ||
| 569 | |||
| 570 | /** | 381 | /** |
| 571 | * batadv_check_unicast_packet - Check for malformed unicast packets | 382 | * batadv_check_unicast_packet - Check for malformed unicast packets |
| 572 | * @bat_priv: the bat priv with all the soft interface information | 383 | * @bat_priv: the bat priv with all the soft interface information |
| @@ -604,95 +415,141 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, | |||
| 604 | return 0; | 415 | return 0; |
| 605 | } | 416 | } |
| 606 | 417 | ||
| 607 | /* find a suitable router for this originator, and use | 418 | /** |
| 608 | * bonding if possible. increases the found neighbors | 419 | * batadv_find_router - find a suitable router for this originator |
| 609 | * refcount. | 420 | * @bat_priv: the bat priv with all the soft interface information |
| 421 | * @orig_node: the destination node | ||
| 422 | * @recv_if: pointer to interface this packet was received on | ||
| 423 | * | ||
| 424 | * Returns the router which should be used for this orig_node on | ||
| 425 | * this interface, or NULL if not available. | ||
| 610 | */ | 426 | */ |
| 611 | struct batadv_neigh_node * | 427 | struct batadv_neigh_node * |
| 612 | batadv_find_router(struct batadv_priv *bat_priv, | 428 | batadv_find_router(struct batadv_priv *bat_priv, |
| 613 | struct batadv_orig_node *orig_node, | 429 | struct batadv_orig_node *orig_node, |
| 614 | const struct batadv_hard_iface *recv_if) | 430 | struct batadv_hard_iface *recv_if) |
| 615 | { | 431 | { |
| 616 | struct batadv_orig_node *primary_orig_node; | 432 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; |
| 617 | struct batadv_orig_node *router_orig; | 433 | struct batadv_neigh_node *first_candidate_router = NULL; |
| 618 | struct batadv_neigh_node *router; | 434 | struct batadv_neigh_node *next_candidate_router = NULL; |
| 619 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 435 | struct batadv_neigh_node *router, *cand_router = NULL; |
| 620 | int bonding_enabled; | 436 | struct batadv_neigh_node *last_cand_router = NULL; |
| 621 | uint8_t *primary_addr; | 437 | struct batadv_orig_ifinfo *cand, *first_candidate = NULL; |
| 438 | struct batadv_orig_ifinfo *next_candidate = NULL; | ||
| 439 | struct batadv_orig_ifinfo *last_candidate; | ||
| 440 | bool last_candidate_found = false; | ||
| 622 | 441 | ||
| 623 | if (!orig_node) | 442 | if (!orig_node) |
| 624 | return NULL; | 443 | return NULL; |
| 625 | 444 | ||
| 626 | router = batadv_orig_node_get_router(orig_node); | 445 | router = batadv_orig_router_get(orig_node, recv_if); |
| 627 | if (!router) | ||
| 628 | goto err; | ||
| 629 | 446 | ||
| 630 | /* without bonding, the first node should | 447 | /* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop) |
| 631 | * always choose the default router. | 448 | * and if activated. |
| 449 | */ | ||
| 450 | if (recv_if == BATADV_IF_DEFAULT || !atomic_read(&bat_priv->bonding) || | ||
| 451 | !router) | ||
| 452 | return router; | ||
| 453 | |||
| 454 | /* bonding: loop through the list of possible routers found | ||
| 455 | * for the various outgoing interfaces and find a candidate after | ||
| 456 | * the last chosen bonding candidate (next_candidate). If no such | ||
| 457 | * router is found, use the first candidate found (the previously | ||
| 458 | * chosen bonding candidate might have been the last one in the list). | ||
| 459 | * If this can't be found either, return the previously choosen | ||
| 460 | * router - obviously there are no other candidates. | ||
| 632 | */ | 461 | */ |
| 633 | bonding_enabled = atomic_read(&bat_priv->bonding); | ||
| 634 | |||
| 635 | rcu_read_lock(); | 462 | rcu_read_lock(); |
| 636 | /* select default router to output */ | 463 | last_candidate = orig_node->last_bonding_candidate; |
| 637 | router_orig = router->orig_node; | 464 | if (last_candidate) |
| 638 | if (!router_orig) | 465 | last_cand_router = rcu_dereference(last_candidate->router); |
| 639 | goto err_unlock; | ||
| 640 | 466 | ||
| 641 | if ((!recv_if) && (!bonding_enabled)) | 467 | hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) { |
| 642 | goto return_router; | 468 | /* acquire some structures and references ... */ |
| 469 | if (!atomic_inc_not_zero(&cand->refcount)) | ||
| 470 | continue; | ||
| 643 | 471 | ||
| 644 | primary_addr = router_orig->primary_addr; | 472 | cand_router = rcu_dereference(cand->router); |
| 473 | if (!cand_router) | ||
| 474 | goto next; | ||
| 645 | 475 | ||
| 646 | /* if we have something in the primary_addr, we can search | 476 | if (!atomic_inc_not_zero(&cand_router->refcount)) { |
| 647 | * for a potential bonding candidate. | 477 | cand_router = NULL; |
| 648 | */ | 478 | goto next; |
| 649 | if (batadv_compare_eth(primary_addr, zero_mac)) | 479 | } |
| 650 | goto return_router; | ||
| 651 | 480 | ||
| 652 | /* find the orig_node which has the primary interface. might | 481 | /* alternative candidate should be good enough to be |
| 653 | * even be the same as our router_orig in many cases | 482 | * considered |
| 654 | */ | 483 | */ |
| 655 | if (batadv_compare_eth(primary_addr, router_orig->orig)) { | 484 | if (!bao->bat_neigh_is_equiv_or_better(cand_router, |
| 656 | primary_orig_node = router_orig; | 485 | cand->if_outgoing, |
| 657 | } else { | 486 | router, recv_if)) |
| 658 | primary_orig_node = batadv_orig_hash_find(bat_priv, | 487 | goto next; |
| 659 | primary_addr); | 488 | |
| 660 | if (!primary_orig_node) | 489 | /* don't use the same router twice */ |
| 661 | goto return_router; | 490 | if (last_cand_router == cand_router) |
| 491 | goto next; | ||
| 492 | |||
| 493 | /* mark the first possible candidate */ | ||
| 494 | if (!first_candidate) { | ||
| 495 | atomic_inc(&cand_router->refcount); | ||
| 496 | atomic_inc(&cand->refcount); | ||
| 497 | first_candidate = cand; | ||
| 498 | first_candidate_router = cand_router; | ||
| 499 | } | ||
| 500 | |||
| 501 | /* check if the loop has already passed the previously selected | ||
| 502 | * candidate ... this function should select the next candidate | ||
| 503 | * AFTER the previously used bonding candidate. | ||
| 504 | */ | ||
| 505 | if (!last_candidate || last_candidate_found) { | ||
| 506 | next_candidate = cand; | ||
| 507 | next_candidate_router = cand_router; | ||
| 508 | break; | ||
| 509 | } | ||
| 662 | 510 | ||
| 663 | batadv_orig_node_free_ref(primary_orig_node); | 511 | if (last_candidate == cand) |
| 512 | last_candidate_found = true; | ||
| 513 | next: | ||
| 514 | /* free references */ | ||
| 515 | if (cand_router) { | ||
| 516 | batadv_neigh_node_free_ref(cand_router); | ||
| 517 | cand_router = NULL; | ||
| 518 | } | ||
| 519 | batadv_orig_ifinfo_free_ref(cand); | ||
| 664 | } | 520 | } |
| 521 | rcu_read_unlock(); | ||
| 665 | 522 | ||
| 666 | /* with less than 2 candidates, we can't do any | 523 | /* last_bonding_candidate is reset below, remove the old reference. */ |
| 667 | * bonding and prefer the original router. | 524 | if (orig_node->last_bonding_candidate) |
| 668 | */ | 525 | batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate); |
| 669 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) | ||
| 670 | goto return_router; | ||
| 671 | 526 | ||
| 672 | /* all nodes between should choose a candidate which | 527 | /* After finding candidates, handle the three cases: |
| 673 | * is is not on the interface where the packet came | 528 | * 1) there is a next candidate, use that |
| 674 | * in. | 529 | * 2) there is no next candidate, use the first of the list |
| 530 | * 3) there is no candidate at all, return the default router | ||
| 675 | */ | 531 | */ |
| 676 | batadv_neigh_node_free_ref(router); | 532 | if (next_candidate) { |
| 533 | batadv_neigh_node_free_ref(router); | ||
| 677 | 534 | ||
| 678 | if (bonding_enabled) | 535 | /* remove references to first candidate, we don't need it. */ |
| 679 | router = batadv_find_bond_router(primary_orig_node, recv_if); | 536 | if (first_candidate) { |
| 680 | else | 537 | batadv_neigh_node_free_ref(first_candidate_router); |
| 681 | router = batadv_find_ifalter_router(bat_priv, primary_orig_node, | 538 | batadv_orig_ifinfo_free_ref(first_candidate); |
| 682 | recv_if); | 539 | } |
| 540 | router = next_candidate_router; | ||
| 541 | orig_node->last_bonding_candidate = next_candidate; | ||
| 542 | } else if (first_candidate) { | ||
| 543 | batadv_neigh_node_free_ref(router); | ||
| 683 | 544 | ||
| 684 | return_router: | 545 | /* refcounting has already been done in the loop above. */ |
| 685 | if (router && router->if_incoming->if_status != BATADV_IF_ACTIVE) | 546 | router = first_candidate_router; |
| 686 | goto err_unlock; | 547 | orig_node->last_bonding_candidate = first_candidate; |
| 548 | } else { | ||
| 549 | orig_node->last_bonding_candidate = NULL; | ||
| 550 | } | ||
| 687 | 551 | ||
| 688 | rcu_read_unlock(); | ||
| 689 | return router; | 552 | return router; |
| 690 | err_unlock: | ||
| 691 | rcu_read_unlock(); | ||
| 692 | err: | ||
| 693 | if (router) | ||
| 694 | batadv_neigh_node_free_ref(router); | ||
| 695 | return NULL; | ||
| 696 | } | 553 | } |
| 697 | 554 | ||
| 698 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 555 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index c1eadfa67945..557d3d12a9ab 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -23,6 +23,7 @@ bool batadv_check_management_packet(struct sk_buff *skb, | |||
| 23 | int header_len); | 23 | int header_len); |
| 24 | void batadv_update_route(struct batadv_priv *bat_priv, | 24 | void batadv_update_route(struct batadv_priv *bat_priv, |
| 25 | struct batadv_orig_node *orig_node, | 25 | struct batadv_orig_node *orig_node, |
| 26 | struct batadv_hard_iface *recv_if, | ||
| 26 | struct batadv_neigh_node *neigh_node); | 27 | struct batadv_neigh_node *neigh_node); |
| 27 | int batadv_recv_icmp_packet(struct sk_buff *skb, | 28 | int batadv_recv_icmp_packet(struct sk_buff *skb, |
| 28 | struct batadv_hard_iface *recv_if); | 29 | struct batadv_hard_iface *recv_if); |
| @@ -43,16 +44,7 @@ int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, | |||
| 43 | struct batadv_neigh_node * | 44 | struct batadv_neigh_node * |
| 44 | batadv_find_router(struct batadv_priv *bat_priv, | 45 | batadv_find_router(struct batadv_priv *bat_priv, |
| 45 | struct batadv_orig_node *orig_node, | 46 | struct batadv_orig_node *orig_node, |
| 46 | const struct batadv_hard_iface *recv_if); | 47 | struct batadv_hard_iface *recv_if); |
| 47 | void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node, | ||
| 48 | struct batadv_neigh_node *neigh_node); | ||
| 49 | void batadv_bonding_candidate_add(struct batadv_priv *bat_priv, | ||
| 50 | struct batadv_orig_node *orig_node, | ||
| 51 | struct batadv_neigh_node *neigh_node); | ||
| 52 | void batadv_bonding_save_primary(const struct batadv_orig_node *orig_node, | ||
| 53 | struct batadv_orig_node *orig_neigh_node, | ||
| 54 | const struct batadv_ogm_packet | ||
| 55 | *batman_ogm_packet); | ||
| 56 | int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff, | 48 | int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff, |
| 57 | unsigned long *last_reset); | 49 | unsigned long *last_reset); |
| 58 | 50 | ||
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 30d12c445ea3..579f5f00a385 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -387,6 +387,8 @@ static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) | |||
| 387 | kfree_skb(forw_packet->skb); | 387 | kfree_skb(forw_packet->skb); |
| 388 | if (forw_packet->if_incoming) | 388 | if (forw_packet->if_incoming) |
| 389 | batadv_hardif_free_ref(forw_packet->if_incoming); | 389 | batadv_hardif_free_ref(forw_packet->if_incoming); |
| 390 | if (forw_packet->if_outgoing) | ||
| 391 | batadv_hardif_free_ref(forw_packet->if_outgoing); | ||
| 390 | kfree(forw_packet); | 392 | kfree(forw_packet); |
| 391 | } | 393 | } |
| 392 | 394 | ||
| @@ -450,6 +452,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, | |||
| 450 | 452 | ||
| 451 | forw_packet->skb = newskb; | 453 | forw_packet->skb = newskb; |
| 452 | forw_packet->if_incoming = primary_if; | 454 | forw_packet->if_incoming = primary_if; |
| 455 | forw_packet->if_outgoing = NULL; | ||
| 453 | 456 | ||
| 454 | /* how often did we send the bcast packet ? */ | 457 | /* how often did we send the bcast packet ? */ |
| 455 | forw_packet->num_packets = 0; | 458 | forw_packet->num_packets = 0; |
| @@ -545,11 +548,16 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) | |||
| 545 | 548 | ||
| 546 | bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet); | 549 | bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet); |
| 547 | 550 | ||
| 548 | /* we have to have at least one packet in the queue | 551 | /* we have to have at least one packet in the queue to determine the |
| 549 | * to determine the queues wake up time unless we are | 552 | * queues wake up time unless we are shutting down. |
| 550 | * shutting down | 553 | * |
| 554 | * only re-schedule if this is the "original" copy, e.g. the OGM of the | ||
| 555 | * primary interface should only be rescheduled once per period, but | ||
| 556 | * this function will be called for the forw_packet instances of the | ||
| 557 | * other secondary interfaces as well. | ||
| 551 | */ | 558 | */ |
| 552 | if (forw_packet->own) | 559 | if (forw_packet->own && |
| 560 | forw_packet->if_incoming == forw_packet->if_outgoing) | ||
| 553 | batadv_schedule_bat_ogm(forw_packet->if_incoming); | 561 | batadv_schedule_bat_ogm(forw_packet->if_incoming); |
| 554 | 562 | ||
| 555 | out: | 563 | out: |
| @@ -610,7 +618,8 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | |||
| 610 | * we delete only packets belonging to the given interface | 618 | * we delete only packets belonging to the given interface |
| 611 | */ | 619 | */ |
| 612 | if ((hard_iface) && | 620 | if ((hard_iface) && |
| 613 | (forw_packet->if_incoming != hard_iface)) | 621 | (forw_packet->if_incoming != hard_iface) && |
| 622 | (forw_packet->if_outgoing != hard_iface)) | ||
| 614 | continue; | 623 | continue; |
| 615 | 624 | ||
| 616 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 625 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 0b17f8d56f2e..aaddaa9661ce 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c50f64337f55..f82c267e1886 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -697,7 +697,7 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
| 697 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 697 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
| 698 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | 698 | atomic_set(&bat_priv->gw.bandwidth_up, 20); |
| 699 | atomic_set(&bat_priv->orig_interval, 1000); | 699 | atomic_set(&bat_priv->orig_interval, 1000); |
| 700 | atomic_set(&bat_priv->hop_penalty, 30); | 700 | atomic_set(&bat_priv->hop_penalty, 15); |
| 701 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 701 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
| 702 | atomic_set(&bat_priv->log_level, 0); | 702 | atomic_set(&bat_priv->log_level, 0); |
| 703 | #endif | 703 | #endif |
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 4ab0167ac6ac..dbab22fd89a5 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index b6a4403b7007..e456bf6bb284 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h index ed80b727dfd8..b715b60db7cd 100644 --- a/net/batman-adv/sysfs.h +++ b/net/batman-adv/sysfs.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2010-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner | 3 | * Marek Lindner |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 63d25705cec6..a6fb1ff25f50 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich, Antonio Quartulli | 3 | * Marek Lindner, Simon Wunderlich, Antonio Quartulli |
| 4 | * | 4 | * |
| @@ -1400,12 +1400,14 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv, | |||
| 1400 | 1400 | ||
| 1401 | head = &tt_global_entry->orig_list; | 1401 | head = &tt_global_entry->orig_list; |
| 1402 | hlist_for_each_entry_rcu(orig_entry, head, list) { | 1402 | hlist_for_each_entry_rcu(orig_entry, head, list) { |
| 1403 | router = batadv_orig_node_get_router(orig_entry->orig_node); | 1403 | router = batadv_orig_router_get(orig_entry->orig_node, |
| 1404 | BATADV_IF_DEFAULT); | ||
| 1404 | if (!router) | 1405 | if (!router) |
| 1405 | continue; | 1406 | continue; |
| 1406 | 1407 | ||
| 1407 | if (best_router && | 1408 | if (best_router && |
| 1408 | bao->bat_neigh_cmp(router, best_router) <= 0) { | 1409 | bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT, |
| 1410 | best_router, BATADV_IF_DEFAULT) <= 0) { | ||
| 1409 | batadv_neigh_node_free_ref(router); | 1411 | batadv_neigh_node_free_ref(router); |
| 1410 | continue; | 1412 | continue; |
| 1411 | } | 1413 | } |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index daa8ab728f71..20a1d7861ded 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich, Antonio Quartulli | 3 | * Marek Lindner, Simon Wunderlich, Antonio Quartulli |
| 4 | * | 4 | * |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 0430a0474506..b53f90d85db9 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors: |
| 2 | * | 2 | * |
| 3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
| 4 | * | 4 | * |
| @@ -84,6 +84,7 @@ struct batadv_hard_iface_bat_iv { | |||
| 84 | * @rcu: struct used for freeing in an RCU-safe manner | 84 | * @rcu: struct used for freeing in an RCU-safe manner |
| 85 | * @bat_iv: BATMAN IV specific per hard interface data | 85 | * @bat_iv: BATMAN IV specific per hard interface data |
| 86 | * @cleanup_work: work queue callback item for hard interface deinit | 86 | * @cleanup_work: work queue callback item for hard interface deinit |
| 87 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs | ||
| 87 | */ | 88 | */ |
| 88 | struct batadv_hard_iface { | 89 | struct batadv_hard_iface { |
| 89 | struct list_head list; | 90 | struct list_head list; |
| @@ -98,6 +99,29 @@ struct batadv_hard_iface { | |||
| 98 | struct rcu_head rcu; | 99 | struct rcu_head rcu; |
| 99 | struct batadv_hard_iface_bat_iv bat_iv; | 100 | struct batadv_hard_iface_bat_iv bat_iv; |
| 100 | struct work_struct cleanup_work; | 101 | struct work_struct cleanup_work; |
| 102 | struct dentry *debug_dir; | ||
| 103 | }; | ||
| 104 | |||
| 105 | /** | ||
| 106 | * struct batadv_orig_ifinfo - originator info per outgoing interface | ||
| 107 | * @list: list node for orig_node::ifinfo_list | ||
| 108 | * @if_outgoing: pointer to outgoing hard interface | ||
| 109 | * @router: router that should be used to reach this originator | ||
| 110 | * @last_real_seqno: last and best known sequence number | ||
| 111 | * @last_ttl: ttl of last received packet | ||
| 112 | * @batman_seqno_reset: time when the batman seqno window was reset | ||
| 113 | * @refcount: number of contexts the object is used | ||
| 114 | * @rcu: struct used for freeing in an RCU-safe manner | ||
| 115 | */ | ||
| 116 | struct batadv_orig_ifinfo { | ||
| 117 | struct hlist_node list; | ||
| 118 | struct batadv_hard_iface *if_outgoing; | ||
| 119 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ | ||
| 120 | uint32_t last_real_seqno; | ||
| 121 | uint8_t last_ttl; | ||
| 122 | unsigned long batman_seqno_reset; | ||
| 123 | atomic_t refcount; | ||
| 124 | struct rcu_head rcu; | ||
| 101 | }; | 125 | }; |
| 102 | 126 | ||
| 103 | /** | 127 | /** |
| @@ -175,11 +199,11 @@ struct batadv_orig_bat_iv { | |||
| 175 | * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh | 199 | * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh |
| 176 | * @orig: originator ethernet address | 200 | * @orig: originator ethernet address |
| 177 | * @primary_addr: hosts primary interface address | 201 | * @primary_addr: hosts primary interface address |
| 178 | * @router: router that should be used to reach this originator | 202 | * @ifinfo_list: list for routers per outgoing interface |
| 203 | * @last_bonding_candidate: pointer to last ifinfo of last used router | ||
| 179 | * @batadv_dat_addr_t: address of the orig node in the distributed hash | 204 | * @batadv_dat_addr_t: address of the orig node in the distributed hash |
| 180 | * @last_seen: time when last packet from this node was received | 205 | * @last_seen: time when last packet from this node was received |
| 181 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 206 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
| 182 | * @batman_seqno_reset: time when the batman seqno window was reset | ||
| 183 | * @capabilities: announced capabilities of this originator | 207 | * @capabilities: announced capabilities of this originator |
| 184 | * @last_ttvn: last seen translation table version number | 208 | * @last_ttvn: last seen translation table version number |
| 185 | * @tt_buff: last tt changeset this node received from the orig node | 209 | * @tt_buff: last tt changeset this node received from the orig node |
| @@ -192,19 +216,15 @@ struct batadv_orig_bat_iv { | |||
| 192 | * made up by two operations (data structure update and metdata -CRC/TTVN- | 216 | * made up by two operations (data structure update and metdata -CRC/TTVN- |
| 193 | * recalculation) and they have to be executed atomically in order to avoid | 217 | * recalculation) and they have to be executed atomically in order to avoid |
| 194 | * another thread to read the table/metadata between those. | 218 | * another thread to read the table/metadata between those. |
| 195 | * @last_real_seqno: last and best known sequence number | ||
| 196 | * @last_ttl: ttl of last received packet | ||
| 197 | * @bcast_bits: bitfield containing the info which payload broadcast originated | 219 | * @bcast_bits: bitfield containing the info which payload broadcast originated |
| 198 | * from this orig node this host already has seen (relative to | 220 | * from this orig node this host already has seen (relative to |
| 199 | * last_bcast_seqno) | 221 | * last_bcast_seqno) |
| 200 | * @last_bcast_seqno: last broadcast sequence number received by this host | 222 | * @last_bcast_seqno: last broadcast sequence number received by this host |
| 201 | * @neigh_list: list of potential next hop neighbor towards this orig node | 223 | * @neigh_list: list of potential next hop neighbor towards this orig node |
| 202 | * @neigh_list_lock: lock protecting neigh_list, router and bonding_list | 224 | * @neigh_list_lock: lock protecting neigh_list and router |
| 203 | * @hash_entry: hlist node for batadv_priv::orig_hash | 225 | * @hash_entry: hlist node for batadv_priv::orig_hash |
| 204 | * @bat_priv: pointer to soft_iface this orig node belongs to | 226 | * @bat_priv: pointer to soft_iface this orig node belongs to |
| 205 | * @bcast_seqno_lock: lock protecting bcast_bits & last_bcast_seqno | 227 | * @bcast_seqno_lock: lock protecting bcast_bits & last_bcast_seqno |
| 206 | * @bond_candidates: how many candidates are available | ||
| 207 | * @bond_list: list of bonding candidates | ||
| 208 | * @refcount: number of contexts the object is used | 228 | * @refcount: number of contexts the object is used |
| 209 | * @rcu: struct used for freeing in an RCU-safe manner | 229 | * @rcu: struct used for freeing in an RCU-safe manner |
| 210 | * @in_coding_list: list of nodes this orig can hear | 230 | * @in_coding_list: list of nodes this orig can hear |
| @@ -220,13 +240,13 @@ struct batadv_orig_bat_iv { | |||
| 220 | struct batadv_orig_node { | 240 | struct batadv_orig_node { |
| 221 | uint8_t orig[ETH_ALEN]; | 241 | uint8_t orig[ETH_ALEN]; |
| 222 | uint8_t primary_addr[ETH_ALEN]; | 242 | uint8_t primary_addr[ETH_ALEN]; |
| 223 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ | 243 | struct hlist_head ifinfo_list; |
| 244 | struct batadv_orig_ifinfo *last_bonding_candidate; | ||
| 224 | #ifdef CONFIG_BATMAN_ADV_DAT | 245 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 225 | batadv_dat_addr_t dat_addr; | 246 | batadv_dat_addr_t dat_addr; |
| 226 | #endif | 247 | #endif |
| 227 | unsigned long last_seen; | 248 | unsigned long last_seen; |
| 228 | unsigned long bcast_seqno_reset; | 249 | unsigned long bcast_seqno_reset; |
| 229 | unsigned long batman_seqno_reset; | ||
| 230 | uint8_t capabilities; | 250 | uint8_t capabilities; |
| 231 | atomic_t last_ttvn; | 251 | atomic_t last_ttvn; |
| 232 | unsigned char *tt_buff; | 252 | unsigned char *tt_buff; |
| @@ -235,19 +255,15 @@ struct batadv_orig_node { | |||
| 235 | bool tt_initialised; | 255 | bool tt_initialised; |
| 236 | /* prevents from changing the table while reading it */ | 256 | /* prevents from changing the table while reading it */ |
| 237 | spinlock_t tt_lock; | 257 | spinlock_t tt_lock; |
| 238 | uint32_t last_real_seqno; | ||
| 239 | uint8_t last_ttl; | ||
| 240 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 258 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
| 241 | uint32_t last_bcast_seqno; | 259 | uint32_t last_bcast_seqno; |
| 242 | struct hlist_head neigh_list; | 260 | struct hlist_head neigh_list; |
| 243 | /* neigh_list_lock protects: neigh_list, router & bonding_list */ | 261 | /* neigh_list_lock protects: neigh_list and router */ |
| 244 | spinlock_t neigh_list_lock; | 262 | spinlock_t neigh_list_lock; |
| 245 | struct hlist_node hash_entry; | 263 | struct hlist_node hash_entry; |
| 246 | struct batadv_priv *bat_priv; | 264 | struct batadv_priv *bat_priv; |
| 247 | /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */ | 265 | /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */ |
| 248 | spinlock_t bcast_seqno_lock; | 266 | spinlock_t bcast_seqno_lock; |
| 249 | atomic_t bond_candidates; | ||
| 250 | struct list_head bond_list; | ||
| 251 | atomic_t refcount; | 267 | atomic_t refcount; |
| 252 | struct rcu_head rcu; | 268 | struct rcu_head rcu; |
| 253 | #ifdef CONFIG_BATMAN_ADV_NC | 269 | #ifdef CONFIG_BATMAN_ADV_NC |
| @@ -293,49 +309,62 @@ struct batadv_gw_node { | |||
| 293 | }; | 309 | }; |
| 294 | 310 | ||
| 295 | /** | 311 | /** |
| 296 | * struct batadv_neigh_bat_iv - B.A.T.M.A.N. IV specific structure for single | 312 | * struct batadv_neigh_node - structure for single hops neighbors |
| 297 | * hop neighbors | 313 | * @list: list node for batadv_orig_node::neigh_list |
| 314 | * @orig_node: pointer to corresponding orig_node | ||
| 315 | * @addr: the MAC address of the neighboring interface | ||
| 316 | * @ifinfo_list: list for routing metrics per outgoing interface | ||
| 317 | * @ifinfo_lock: lock protecting private ifinfo members and list | ||
| 318 | * @if_incoming: pointer to incoming hard interface | ||
| 319 | * @last_seen: when last packet via this neighbor was received | ||
| 320 | * @last_ttl: last received ttl from this neigh node | ||
| 321 | * @rcu: struct used for freeing in an RCU-safe manner | ||
| 322 | * @bat_iv: B.A.T.M.A.N. IV private structure | ||
| 323 | */ | ||
| 324 | struct batadv_neigh_node { | ||
| 325 | struct hlist_node list; | ||
| 326 | struct batadv_orig_node *orig_node; | ||
| 327 | uint8_t addr[ETH_ALEN]; | ||
| 328 | struct hlist_head ifinfo_list; | ||
| 329 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ | ||
| 330 | struct batadv_hard_iface *if_incoming; | ||
| 331 | unsigned long last_seen; | ||
| 332 | atomic_t refcount; | ||
| 333 | struct rcu_head rcu; | ||
| 334 | }; | ||
| 335 | |||
| 336 | /* struct batadv_neigh_node_bat_iv - neighbor information per outgoing | ||
| 337 | * interface for BATMAN IV | ||
| 298 | * @tq_recv: ring buffer of received TQ values from this neigh node | 338 | * @tq_recv: ring buffer of received TQ values from this neigh node |
| 299 | * @tq_index: ring buffer index | 339 | * @tq_index: ring buffer index |
| 300 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) | 340 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) |
| 301 | * @real_bits: bitfield containing the number of OGMs received from this neigh | 341 | * @real_bits: bitfield containing the number of OGMs received from this neigh |
| 302 | * node (relative to orig_node->last_real_seqno) | 342 | * node (relative to orig_node->last_real_seqno) |
| 303 | * @real_packet_count: counted result of real_bits | 343 | * @real_packet_count: counted result of real_bits |
| 304 | * @lq_update_lock: lock protecting tq_recv & tq_index | ||
| 305 | */ | 344 | */ |
| 306 | struct batadv_neigh_bat_iv { | 345 | struct batadv_neigh_ifinfo_bat_iv { |
| 307 | uint8_t tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; | 346 | uint8_t tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; |
| 308 | uint8_t tq_index; | 347 | uint8_t tq_index; |
| 309 | uint8_t tq_avg; | 348 | uint8_t tq_avg; |
| 310 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 349 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
| 311 | uint8_t real_packet_count; | 350 | uint8_t real_packet_count; |
| 312 | spinlock_t lq_update_lock; /* protects tq_recv & tq_index */ | ||
| 313 | }; | 351 | }; |
| 314 | 352 | ||
| 315 | /** | 353 | /* struct batadv_neigh_ifinfo - neighbor information per outgoing interface |
| 316 | * struct batadv_neigh_node - structure for single hops neighbors | 354 | * @list: list node for batadv_neigh_node::ifinfo_list |
| 317 | * @list: list node for batadv_orig_node::neigh_list | 355 | * @if_outgoing: pointer to outgoing hard interface |
| 318 | * @orig_node: pointer to corresponding orig_node | 356 | * @bat_iv: B.A.T.M.A.N. IV private structure |
| 319 | * @addr: the MAC address of the neighboring interface | ||
| 320 | * @if_incoming: pointer to incoming hard interface | ||
| 321 | * @last_seen: when last packet via this neighbor was received | ||
| 322 | * @last_ttl: last received ttl from this neigh node | 357 | * @last_ttl: last received ttl from this neigh node |
| 323 | * @bonding_list: list node for batadv_orig_node::bond_list | ||
| 324 | * @refcount: number of contexts the object is used | 358 | * @refcount: number of contexts the object is used |
| 325 | * @rcu: struct used for freeing in an RCU-safe manner | 359 | * @rcu: struct used for freeing in a RCU-safe manner |
| 326 | * @bat_iv: B.A.T.M.A.N. IV private structure | ||
| 327 | */ | 360 | */ |
| 328 | struct batadv_neigh_node { | 361 | struct batadv_neigh_ifinfo { |
| 329 | struct hlist_node list; | 362 | struct hlist_node list; |
| 330 | struct batadv_orig_node *orig_node; | 363 | struct batadv_hard_iface *if_outgoing; |
| 331 | uint8_t addr[ETH_ALEN]; | 364 | struct batadv_neigh_ifinfo_bat_iv bat_iv; |
| 332 | struct batadv_hard_iface *if_incoming; | ||
| 333 | unsigned long last_seen; | ||
| 334 | uint8_t last_ttl; | 365 | uint8_t last_ttl; |
| 335 | struct list_head bonding_list; | ||
| 336 | atomic_t refcount; | 366 | atomic_t refcount; |
| 337 | struct rcu_head rcu; | 367 | struct rcu_head rcu; |
| 338 | struct batadv_neigh_bat_iv bat_iv; | ||
| 339 | }; | 368 | }; |
| 340 | 369 | ||
| 341 | /** | 370 | /** |
| @@ -993,8 +1022,10 @@ struct batadv_skb_cb { | |||
| 993 | * @direct_link_flags: direct link flags for aggregated OGM packets | 1022 | * @direct_link_flags: direct link flags for aggregated OGM packets |
| 994 | * @num_packets: counter for bcast packet retransmission | 1023 | * @num_packets: counter for bcast packet retransmission |
| 995 | * @delayed_work: work queue callback item for packet sending | 1024 | * @delayed_work: work queue callback item for packet sending |
| 996 | * @if_incoming: pointer incoming hard-iface or primary iface if locally | 1025 | * @if_incoming: pointer to incoming hard-iface or primary iface if |
| 997 | * generated packet | 1026 | * locally generated packet |
| 1027 | * @if_outgoing: packet where the packet should be sent to, or NULL if | ||
| 1028 | * unspecified | ||
| 998 | */ | 1029 | */ |
| 999 | struct batadv_forw_packet { | 1030 | struct batadv_forw_packet { |
| 1000 | struct hlist_node list; | 1031 | struct hlist_node list; |
| @@ -1006,6 +1037,7 @@ struct batadv_forw_packet { | |||
| 1006 | uint8_t num_packets; | 1037 | uint8_t num_packets; |
| 1007 | struct delayed_work delayed_work; | 1038 | struct delayed_work delayed_work; |
| 1008 | struct batadv_hard_iface *if_incoming; | 1039 | struct batadv_hard_iface *if_incoming; |
| 1040 | struct batadv_hard_iface *if_outgoing; | ||
| 1009 | }; | 1041 | }; |
| 1010 | 1042 | ||
| 1011 | /** | 1043 | /** |
| @@ -1019,9 +1051,11 @@ struct batadv_forw_packet { | |||
| 1019 | * @bat_primary_iface_set: called when primary interface is selected / changed | 1051 | * @bat_primary_iface_set: called when primary interface is selected / changed |
| 1020 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue | 1052 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue |
| 1021 | * @bat_ogm_emit: send scheduled OGM | 1053 | * @bat_ogm_emit: send scheduled OGM |
| 1022 | * @bat_neigh_cmp: compare the metrics of two neighbors | 1054 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective |
| 1023 | * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or | 1055 | * outgoing interfaces |
| 1024 | * better than neigh2 from the metric prospective | 1056 | * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better |
| 1057 | * than neigh2 for their respective outgoing interface from the metric | ||
| 1058 | * prospective | ||
| 1025 | * @bat_orig_print: print the originator table (optional) | 1059 | * @bat_orig_print: print the originator table (optional) |
| 1026 | * @bat_orig_free: free the resources allocated by the routing algorithm for an | 1060 | * @bat_orig_free: free the resources allocated by the routing algorithm for an |
| 1027 | * orig_node object | 1061 | * orig_node object |
| @@ -1040,11 +1074,17 @@ struct batadv_algo_ops { | |||
| 1040 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); | 1074 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); |
| 1041 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); | 1075 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); |
| 1042 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, | 1076 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, |
| 1043 | struct batadv_neigh_node *neigh2); | 1077 | struct batadv_hard_iface *if_outgoing1, |
| 1044 | bool (*bat_neigh_is_equiv_or_better)(struct batadv_neigh_node *neigh1, | 1078 | struct batadv_neigh_node *neigh2, |
| 1045 | struct batadv_neigh_node *neigh2); | 1079 | struct batadv_hard_iface *if_outgoing2); |
| 1080 | bool (*bat_neigh_is_equiv_or_better) | ||
| 1081 | (struct batadv_neigh_node *neigh1, | ||
| 1082 | struct batadv_hard_iface *if_outgoing1, | ||
| 1083 | struct batadv_neigh_node *neigh2, | ||
| 1084 | struct batadv_hard_iface *if_outgoing2); | ||
| 1046 | /* orig_node handling API */ | 1085 | /* orig_node handling API */ |
| 1047 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq); | 1086 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, |
| 1087 | struct batadv_hard_iface *hard_iface); | ||
| 1048 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); | 1088 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); |
| 1049 | int (*bat_orig_add_if)(struct batadv_orig_node *orig_node, | 1089 | int (*bat_orig_add_if)(struct batadv_orig_node *orig_node, |
| 1050 | int max_if_num); | 1090 | int max_if_num); |
