aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-01-14 00:50:27 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-14 00:50:27 -0500
commit853dc21bfe15f545347b5c82aad02735d552110d (patch)
treee5881a889f67211727d0422d617d01a2c1495da6 /net
parent6806afc9aa1000db598e31164d2ef505be3b3075 (diff)
parent12afc36e38b3b6a0ec9bda71632c2285e7fdbab2 (diff)
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes: - drop dependency against CRC16 - move to new release version - add size check at compile time for packet structs - update copyright years in every file - implement new bonding/interface alternation feature Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/Kconfig1
-rw-r--r--net/batman-adv/Makefile2
-rw-r--r--net/batman-adv/bat_algo.h2
-rw-r--r--net/batman-adv/bat_iv_ogm.c882
-rw-r--r--net/batman-adv/bitarray.c2
-rw-r--r--net/batman-adv/bitarray.h2
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c2
-rw-r--r--net/batman-adv/bridge_loop_avoidance.h2
-rw-r--r--net/batman-adv/debugfs.c91
-rw-r--r--net/batman-adv/debugfs.h4
-rw-r--r--net/batman-adv/distributed-arp-table.c5
-rw-r--r--net/batman-adv/distributed-arp-table.h2
-rw-r--r--net/batman-adv/fragmentation.c2
-rw-r--r--net/batman-adv/fragmentation.h2
-rw-r--r--net/batman-adv/gateway_client.c88
-rw-r--r--net/batman-adv/gateway_client.h2
-rw-r--r--net/batman-adv/gateway_common.c2
-rw-r--r--net/batman-adv/gateway_common.h2
-rw-r--r--net/batman-adv/hard-interface.c11
-rw-r--r--net/batman-adv/hard-interface.h20
-rw-r--r--net/batman-adv/hash.c2
-rw-r--r--net/batman-adv/hash.h2
-rw-r--r--net/batman-adv/icmp_socket.c5
-rw-r--r--net/batman-adv/icmp_socket.h2
-rw-r--r--net/batman-adv/main.c26
-rw-r--r--net/batman-adv/main.h10
-rw-r--r--net/batman-adv/network-coding.c51
-rw-r--r--net/batman-adv/network-coding.h9
-rw-r--r--net/batman-adv/originator.c536
-rw-r--r--net/batman-adv/originator.h22
-rw-r--r--net/batman-adv/packet.h2
-rw-r--r--net/batman-adv/routing.c429
-rw-r--r--net/batman-adv/routing.h14
-rw-r--r--net/batman-adv/send.c21
-rw-r--r--net/batman-adv/send.h2
-rw-r--r--net/batman-adv/soft-interface.c4
-rw-r--r--net/batman-adv/soft-interface.h2
-rw-r--r--net/batman-adv/sysfs.c2
-rw-r--r--net/batman-adv/sysfs.h2
-rw-r--r--net/batman-adv/translation-table.c8
-rw-r--r--net/batman-adv/translation-table.h2
-rw-r--r--net/batman-adv/types.h132
42 files changed, 1648 insertions, 763 deletions
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 @@
5config BATMAN_ADV 5config 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 */
460static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet) 467static 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
523out: 497out:
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 */
529static bool 516static bool
530batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, 517batadv_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 */
610static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, 611static 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;
685out: 691out:
692 batadv_hardif_free_ref(if_outgoing);
693out_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 */
709static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, 727static 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
939out:
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 */
898static void 956static void
899batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, 957batadv_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
1013unlock: 1093unlock:
@@ -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 */
1022static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, 1116static 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 */
1140static enum batadv_dup_status 1260static enum batadv_dup_status
1141batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, 1261batadv_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
1210out: 1345out:
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
1216static 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 */
1361static void
1362batadv_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
1472out_neigh: 1533out_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 */
1553static 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 */
1755static void
1756batadv_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 */
1540static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv, 1782static 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
1589next: 1834next:
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 */
1607static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, 1856static 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; 1877out:
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 */
1627static bool batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, 1897static bool
1628 struct batadv_neigh_node *neigh2) 1898batadv_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
1920out:
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
1635static struct batadv_algo_ops batadv_batman_iv __read_mostly = { 1929static 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 */
257static 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
251static int batadv_gateways_open(struct inode *inode, struct file *file) 264static 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) \
386struct 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};
399static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
400 batadv_originators_hardif_open);
401
402static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
403 &batadv_hardif_debuginfo_originators,
404 NULL,
405};
406
372void batadv_debugfs_init(void) 407void 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;
397err: 432err:
398 debugfs_remove_recursive(batadv_debugfs); 433 debugfs_remove_recursive(batadv_debugfs);
434 batadv_debugfs = NULL;
399} 435}
400 436
401void batadv_debugfs_destroy(void) 437void 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 */
448int 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;
472rem_attr:
473 debugfs_remove_recursive(hard_iface->debug_dir);
474 hard_iface->debug_dir = NULL;
475out:
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 */
488void 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
407int batadv_debugfs_add_meshif(struct net_device *dev) 496int 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);
24void batadv_debugfs_destroy(void); 24void batadv_debugfs_destroy(void);
25int batadv_debugfs_add_meshif(struct net_device *dev); 25int batadv_debugfs_add_meshif(struct net_device *dev);
26void batadv_debugfs_del_meshif(struct net_device *dev); 26void batadv_debugfs_del_meshif(struct net_device *dev);
27int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
28void 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 *
129batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) 129batadv_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
198next: 204next:
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
305void batadv_gw_check_election(struct batadv_priv *bat_priv, 326void 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);
561out: 602out:
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
804out: 862out:
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
595free_sysfs:
596 batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
588free_if: 597free_if:
589 kfree(hard_iface); 598 kfree(hard_iface);
590release_dev: 599release_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 {
40extern struct notifier_block batadv_hard_if_notifier; 40extern struct notifier_block batadv_hard_if_notifier;
41 41
42bool batadv_is_wifi_netdev(struct net_device *net_device); 42bool batadv_is_wifi_netdev(struct net_device *net_device);
43bool batadv_is_wifi_iface(int ifindex);
43struct batadv_hard_iface* 44struct batadv_hard_iface*
44batadv_hardif_get_by_netdev(const struct net_device *net_dev); 45batadv_hardif_get_by_netdev(const struct net_device *net_dev);
45int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, 46int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
@@ -51,6 +52,11 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface);
51void batadv_update_min_mtu(struct net_device *soft_iface); 52void batadv_update_min_mtu(struct net_device *soft_iface);
52void batadv_hardif_free_rcu(struct rcu_head *rcu); 53void 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 */
54static inline void 60static inline void
55batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface) 61batadv_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 */
72static inline void
73batadv_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
61static inline struct batadv_hard_iface * 79static inline struct batadv_hard_iface *
62batadv_primary_if_get_selected(struct batadv_priv *bat_priv) 80batadv_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
63static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) 63static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
64{ 64{
65 return;
66} 65}
67 66
68static inline void 67static 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
78static inline void 76static 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
87static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) 84static inline void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv)
88{ 85{
89 return;
90} 86}
91 87
92static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node) 88static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
93{ 89{
94 return;
95} 90}
96 91
97static inline bool batadv_nc_skb_forward(struct sk_buff *skb, 92static inline bool batadv_nc_skb_forward(struct sk_buff *skb,
@@ -104,14 +99,12 @@ static inline void
104batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, 99batadv_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
110static inline void 104static inline void
111batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, 105batadv_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
117static inline int batadv_nc_nodes_seq_print_text(struct seq_file *seq, 110static 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 */
155static 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 */
172static void
173batadv_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 */
184void 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 */
194static 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 */
216static void
217batadv_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 */
151void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) 228void 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 */
158struct batadv_neigh_node * 244struct batadv_neigh_node *
159batadv_orig_node_get_router(struct batadv_orig_node *orig_node) 245batadv_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 */
276struct batadv_orig_ifinfo *
277batadv_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 */
310struct batadv_orig_ifinfo *
311batadv_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);
342out:
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 */
356struct batadv_neigh_ifinfo *
357batadv_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 */
391struct batadv_neigh_ifinfo *
392batadv_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
419out:
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 */
464static 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 */
481static void
482batadv_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 */
493void 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
208static void batadv_orig_node_free_rcu(struct rcu_head *rcu) 499static 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 */
670static bool
671batadv_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 */
377static bool 723static bool
378batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, 724batadv_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 */
777static struct batadv_neigh_node *
778batadv_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 */
435static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, 814static 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 */
957int 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
989out:
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);
35void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); 35void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
36struct batadv_neigh_node * 36struct batadv_neigh_node *
37batadv_orig_node_get_router(struct batadv_orig_node *orig_node); 37batadv_orig_router_get(struct batadv_orig_node *orig_node,
38 const struct batadv_hard_iface *if_outgoing);
39struct batadv_neigh_ifinfo *
40batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
41 struct batadv_hard_iface *if_outgoing);
42struct batadv_neigh_ifinfo *
43batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
44 struct batadv_hard_iface *if_outgoing);
45void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo);
46
47struct batadv_orig_ifinfo *
48batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
49 struct batadv_hard_iface *if_outgoing);
50struct batadv_orig_ifinfo *
51batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
52 struct batadv_hard_iface *if_outgoing);
53void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo);
54
38int batadv_orig_seq_print_text(struct seq_file *seq, void *offset); 55int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
56int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset);
39int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, 57int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
40 int max_if_num); 58 int max_if_num);
41int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, 59int 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 @@
33static int batadv_route_unicast_packet(struct sk_buff *skb, 33static 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 */
36static void _batadv_update_route(struct batadv_priv *bat_priv, 45static 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 */
80void batadv_update_route(struct batadv_priv *bat_priv, 107void 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
94out: 122out:
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 */
100void 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
112out:
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 */
124void 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
186candidate_del:
187 batadv_bonding_candidate_del(orig_node, neigh_node);
188
189out:
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 */
197void
198batadv_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 */
468static struct batadv_neigh_node *
469batadv_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
512out:
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 */
528static struct batadv_neigh_node *
529batadv_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 */
611struct batadv_neigh_node * 427struct batadv_neigh_node *
612batadv_find_router(struct batadv_priv *bat_priv, 428batadv_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;
513next:
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
684return_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;
690err_unlock:
691 rcu_read_unlock();
692err:
693 if (router)
694 batadv_neigh_node_free_ref(router);
695 return NULL;
696} 553}
697 554
698static int batadv_route_unicast_packet(struct sk_buff *skb, 555static 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);
24void batadv_update_route(struct batadv_priv *bat_priv, 24void 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);
27int batadv_recv_icmp_packet(struct sk_buff *skb, 28int 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,
43struct batadv_neigh_node * 44struct batadv_neigh_node *
44batadv_find_router(struct batadv_priv *bat_priv, 45batadv_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);
47void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node,
48 struct batadv_neigh_node *neigh_node);
49void batadv_bonding_candidate_add(struct batadv_priv *bat_priv,
50 struct batadv_orig_node *orig_node,
51 struct batadv_neigh_node *neigh_node);
52void 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);
56int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff, 48int 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
555out: 563out:
@@ -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 */
88struct batadv_hard_iface { 89struct 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 */
116struct 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 {
220struct batadv_orig_node { 240struct 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 */
324struct 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 */
306struct batadv_neigh_bat_iv { 345struct 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 */
328struct batadv_neigh_node { 361struct 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 */
999struct batadv_forw_packet { 1030struct 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);