aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-13 04:26:54 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-13 04:26:54 -0400
commite86c986137ee410190093d9ba86b86854861b9d5 (patch)
tree02a3830ddfb3d9994647a2750a3f69045769d7b0
parent94f950c4060cd9b1989c565284beb159b9705a50 (diff)
parentd5b4c93e67b0b1291aa8e2aaf694e40afc3412d0 (diff)
Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge
Included change: - fix "rtnl locked" concurrent executions by using rtnl_lock instead of rtnl_trylock. This fix enables batman-adv initialisation to do not fail just because somewhere else in the system another code path is holding the rtnl lock. It is easy to see the problem when batman-adv is trying to start together with other networking components. - fix the routing protocol forwarding policy by enhancing the duplicate control packet detection. When the right circumstances trigger the issue, some nodes in the network become totally unreachable, so breaking the mesh connectivity. - fix the Bridge Loop Avoidance component by not running the originator address change handling routine when the component is disabled. The routine was generating useless packets that were sent over the network. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/batman-adv/bat_iv_ogm.c86
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c4
-rw-r--r--net/batman-adv/sysfs.c5
3 files changed, 60 insertions, 35 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 */
40enum batadv_dup_status {
41 BATADV_NO_DUP = 0,
42 BATADV_ORIG_DUP,
43 BATADV_NEIGH_DUP,
44 BATADV_PROTECTED,
45};
46
32static struct batadv_neigh_node * 47static struct batadv_neigh_node *
33batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, 48batadv_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 */
913static int 929static enum batadv_dup_status
914batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, 930batadv_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
976out: 998out:
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;
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 379061c72549..de27b3175cfd 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1067,6 +1067,10 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1067 group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); 1067 group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
1068 bat_priv->bla.claim_dest.group = group; 1068 bat_priv->bla.claim_dest.group = group;
1069 1069
1070 /* purge everything when bridge loop avoidance is turned off */
1071 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1072 oldif = NULL;
1073
1070 if (!oldif) { 1074 if (!oldif) {
1071 batadv_bla_purge_claims(bat_priv, NULL, 1); 1075 batadv_bla_purge_claims(bat_priv, NULL, 1);
1072 batadv_bla_purge_backbone_gw(bat_priv, 1); 1076 batadv_bla_purge_backbone_gw(bat_priv, 1);
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 15a22efa9a67..929e304dacb2 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -582,10 +582,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
582 (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) 582 (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
583 goto out; 583 goto out;
584 584
585 if (!rtnl_trylock()) { 585 rtnl_lock();
586 ret = -ERESTARTSYS;
587 goto out;
588 }
589 586
590 if (status_tmp == BATADV_IF_NOT_IN_USE) { 587 if (status_tmp == BATADV_IF_NOT_IN_USE) {
591 batadv_hardif_disable_interface(hard_iface, 588 batadv_hardif_disable_interface(hard_iface,