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