diff options
author | Simon Wunderlich <simon@open-mesh.com> | 2013-05-23 07:07:42 -0400 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2013-06-10 02:42:17 -0400 |
commit | 7c24bbbeab4159f924b65b1e94878e597b762714 (patch) | |
tree | 599e4e13220b5cbd25992923b375bd3b31300505 /net/batman-adv | |
parent | ac16d1484efd5d2d9077c55453b1f8abff49fc18 (diff) |
batman-adv: forward late OGMs from best next hop
When a packet is received from another node first and later from the
best next hop, this packet is dropped. However the first OGM was sent
with the BATADV_NOT_BEST_NEXT_HOP flag and thus dropped by neighbors.
The late OGM from the best neighbor is then dropped because it is a
duplicate.
If this situation happens constantly, a node might end up not forwarding
the "valid" OGMs anymore, and nodes behind will starve from not getting
valid OGMs.
Fix this by refining the duplicate checking behaviour: The actions
should depend on whether it was a duplicate for a neighbor only or for
the originator. OGMs which are not duplicates for a specific neighbor
will now be considered in batadv_iv_ogm_forward(), but only actually
forwarded for the best next hop. Therefore, late OGMs from the best
next hop are forwarded now and not dropped as duplicates anymore.
Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 071f288b77a8..f680ee101878 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -29,6 +29,21 @@ | |||
29 | #include "bat_algo.h" | 29 | #include "bat_algo.h" |
30 | #include "network-coding.h" | 30 | #include "network-coding.h" |
31 | 31 | ||
32 | /** | ||
33 | * batadv_dup_status - duplicate status | ||
34 | * @BATADV_NO_DUP: the packet is a duplicate | ||
35 | * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the | ||
36 | * neighbor) | ||
37 | * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor | ||
38 | * @BATADV_PROTECTED: originator is currently protected (after reboot) | ||
39 | */ | ||
40 | enum batadv_dup_status { | ||
41 | BATADV_NO_DUP = 0, | ||
42 | BATADV_ORIG_DUP, | ||
43 | BATADV_NEIGH_DUP, | ||
44 | BATADV_PROTECTED, | ||
45 | }; | ||
46 | |||
32 | static struct batadv_neigh_node * | 47 | static struct batadv_neigh_node * |
33 | batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | 48 | batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, |
34 | const uint8_t *neigh_addr, | 49 | const uint8_t *neigh_addr, |
@@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
650 | const struct batadv_ogm_packet *batadv_ogm_packet, | 665 | const struct batadv_ogm_packet *batadv_ogm_packet, |
651 | struct batadv_hard_iface *if_incoming, | 666 | struct batadv_hard_iface *if_incoming, |
652 | const unsigned char *tt_buff, | 667 | const unsigned char *tt_buff, |
653 | int is_duplicate) | 668 | enum batadv_dup_status dup_status) |
654 | { | 669 | { |
655 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 670 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
656 | struct batadv_neigh_node *router = NULL; | 671 | struct batadv_neigh_node *router = NULL; |
@@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
676 | continue; | 691 | continue; |
677 | } | 692 | } |
678 | 693 | ||
679 | if (is_duplicate) | 694 | if (dup_status != BATADV_NO_DUP) |
680 | continue; | 695 | continue; |
681 | 696 | ||
682 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); | 697 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); |
@@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
718 | neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); | 733 | neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); |
719 | spin_unlock_bh(&neigh_node->lq_update_lock); | 734 | spin_unlock_bh(&neigh_node->lq_update_lock); |
720 | 735 | ||
721 | if (!is_duplicate) { | 736 | if (dup_status == BATADV_NO_DUP) { |
722 | orig_node->last_ttl = batadv_ogm_packet->header.ttl; | 737 | orig_node->last_ttl = batadv_ogm_packet->header.ttl; |
723 | neigh_node->last_ttl = batadv_ogm_packet->header.ttl; | 738 | neigh_node->last_ttl = batadv_ogm_packet->header.ttl; |
724 | } | 739 | } |
@@ -902,15 +917,16 @@ out: | |||
902 | return ret; | 917 | return ret; |
903 | } | 918 | } |
904 | 919 | ||
905 | /* processes a batman packet for all interfaces, adjusts the sequence number and | 920 | /** |
906 | * finds out whether it is a duplicate. | 921 | * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces, |
907 | * returns: | 922 | * adjust the sequence number and find out whether it is a duplicate |
908 | * 1 the packet is a duplicate | 923 | * @ethhdr: ethernet header of the packet |
909 | * 0 the packet has not yet been received | 924 | * @batadv_ogm_packet: OGM packet to be considered |
910 | * -1 the packet is old and has been received while the seqno window | 925 | * @if_incoming: interface on which the OGM packet was received |
911 | * was protected. Caller should drop it. | 926 | * |
927 | * Returns duplicate status as enum batadv_dup_status | ||
912 | */ | 928 | */ |
913 | static int | 929 | static enum batadv_dup_status |
914 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | 930 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, |
915 | const struct batadv_ogm_packet *batadv_ogm_packet, | 931 | const struct batadv_ogm_packet *batadv_ogm_packet, |
916 | const struct batadv_hard_iface *if_incoming) | 932 | const struct batadv_hard_iface *if_incoming) |
@@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
918 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 934 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
919 | struct batadv_orig_node *orig_node; | 935 | struct batadv_orig_node *orig_node; |
920 | struct batadv_neigh_node *tmp_neigh_node; | 936 | struct batadv_neigh_node *tmp_neigh_node; |
921 | int is_duplicate = 0; | 937 | int is_dup; |
922 | int32_t seq_diff; | 938 | int32_t seq_diff; |
923 | int need_update = 0; | 939 | int need_update = 0; |
924 | int set_mark, ret = -1; | 940 | int set_mark; |
941 | enum batadv_dup_status ret = BATADV_NO_DUP; | ||
925 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); | 942 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); |
926 | uint8_t *neigh_addr; | 943 | uint8_t *neigh_addr; |
927 | uint8_t packet_count; | 944 | uint8_t packet_count; |
928 | 945 | ||
929 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); | 946 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); |
930 | if (!orig_node) | 947 | if (!orig_node) |
931 | return 0; | 948 | return BATADV_NO_DUP; |
932 | 949 | ||
933 | spin_lock_bh(&orig_node->ogm_cnt_lock); | 950 | spin_lock_bh(&orig_node->ogm_cnt_lock); |
934 | seq_diff = seqno - orig_node->last_real_seqno; | 951 | seq_diff = seqno - orig_node->last_real_seqno; |
@@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
936 | /* signalize caller that the packet is to be dropped. */ | 953 | /* signalize caller that the packet is to be dropped. */ |
937 | if (!hlist_empty(&orig_node->neigh_list) && | 954 | if (!hlist_empty(&orig_node->neigh_list) && |
938 | batadv_window_protected(bat_priv, seq_diff, | 955 | batadv_window_protected(bat_priv, seq_diff, |
939 | &orig_node->batman_seqno_reset)) | 956 | &orig_node->batman_seqno_reset)) { |
957 | ret = BATADV_PROTECTED; | ||
940 | goto out; | 958 | goto out; |
959 | } | ||
941 | 960 | ||
942 | rcu_read_lock(); | 961 | rcu_read_lock(); |
943 | hlist_for_each_entry_rcu(tmp_neigh_node, | 962 | hlist_for_each_entry_rcu(tmp_neigh_node, |
944 | &orig_node->neigh_list, list) { | 963 | &orig_node->neigh_list, list) { |
945 | is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits, | ||
946 | orig_node->last_real_seqno, | ||
947 | seqno); | ||
948 | |||
949 | neigh_addr = tmp_neigh_node->addr; | 964 | neigh_addr = tmp_neigh_node->addr; |
965 | is_dup = batadv_test_bit(tmp_neigh_node->real_bits, | ||
966 | orig_node->last_real_seqno, | ||
967 | seqno); | ||
968 | |||
950 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && | 969 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && |
951 | tmp_neigh_node->if_incoming == if_incoming) | 970 | tmp_neigh_node->if_incoming == if_incoming) { |
952 | set_mark = 1; | 971 | set_mark = 1; |
953 | else | 972 | if (is_dup) |
973 | ret = BATADV_NEIGH_DUP; | ||
974 | } else { | ||
954 | set_mark = 0; | 975 | set_mark = 0; |
976 | if (is_dup && (ret != BATADV_NEIGH_DUP)) | ||
977 | ret = BATADV_ORIG_DUP; | ||
978 | } | ||
955 | 979 | ||
956 | /* if the window moved, set the update flag. */ | 980 | /* if the window moved, set the update flag. */ |
957 | need_update |= batadv_bit_get_packet(bat_priv, | 981 | need_update |= batadv_bit_get_packet(bat_priv, |
@@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
971 | orig_node->last_real_seqno = seqno; | 995 | orig_node->last_real_seqno = seqno; |
972 | } | 996 | } |
973 | 997 | ||
974 | ret = is_duplicate; | ||
975 | |||
976 | out: | 998 | out: |
977 | spin_unlock_bh(&orig_node->ogm_cnt_lock); | 999 | spin_unlock_bh(&orig_node->ogm_cnt_lock); |
978 | batadv_orig_node_free_ref(orig_node); | 1000 | batadv_orig_node_free_ref(orig_node); |
@@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
994 | int is_broadcast = 0, is_bidirect; | 1016 | int is_broadcast = 0, is_bidirect; |
995 | bool is_single_hop_neigh = false; | 1017 | bool is_single_hop_neigh = false; |
996 | bool is_from_best_next_hop = false; | 1018 | bool is_from_best_next_hop = false; |
997 | int is_duplicate, sameseq, simlar_ttl; | 1019 | int sameseq, similar_ttl; |
1020 | enum batadv_dup_status dup_status; | ||
998 | uint32_t if_incoming_seqno; | 1021 | uint32_t if_incoming_seqno; |
999 | uint8_t *prev_sender; | 1022 | uint8_t *prev_sender; |
1000 | 1023 | ||
@@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
1138 | if (!orig_node) | 1161 | if (!orig_node) |
1139 | return; | 1162 | return; |
1140 | 1163 | ||
1141 | is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, | 1164 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, |
1142 | if_incoming); | 1165 | if_incoming); |
1143 | 1166 | ||
1144 | if (is_duplicate == -1) { | 1167 | if (dup_status == BATADV_PROTECTED) { |
1145 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1168 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1146 | "Drop packet: packet within seqno protection time (sender: %pM)\n", | 1169 | "Drop packet: packet within seqno protection time (sender: %pM)\n", |
1147 | ethhdr->h_source); | 1170 | ethhdr->h_source); |
@@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
1211 | * seqno and similar ttl as the non-duplicate | 1234 | * seqno and similar ttl as the non-duplicate |
1212 | */ | 1235 | */ |
1213 | sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); | 1236 | sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); |
1214 | simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; | 1237 | similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; |
1215 | if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl))) | 1238 | if (is_bidirect && ((dup_status == BATADV_NO_DUP) || |
1239 | (sameseq && similar_ttl))) | ||
1216 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, | 1240 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, |
1217 | batadv_ogm_packet, if_incoming, | 1241 | batadv_ogm_packet, if_incoming, |
1218 | tt_buff, is_duplicate); | 1242 | tt_buff, dup_status); |
1219 | 1243 | ||
1220 | /* is single hop (direct) neighbor */ | 1244 | /* is single hop (direct) neighbor */ |
1221 | if (is_single_hop_neigh) { | 1245 | if (is_single_hop_neigh) { |
@@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
1236 | goto out_neigh; | 1260 | goto out_neigh; |
1237 | } | 1261 | } |
1238 | 1262 | ||
1239 | if (is_duplicate) { | 1263 | if (dup_status == BATADV_NEIGH_DUP) { |
1240 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1264 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1241 | "Drop packet: duplicate packet received\n"); | 1265 | "Drop packet: duplicate packet received\n"); |
1242 | goto out_neigh; | 1266 | goto out_neigh; |