diff options
author | David S. Miller <davem@davemloft.net> | 2012-11-14 22:10:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-14 22:10:50 -0500 |
commit | 702ed3c1a9dfe4dfe112f13542d0c9d689f5008b (patch) | |
tree | 389a18e751299babb9cb8f6085b5e30631378c8b | |
parent | 1a39a65cba08f8a76f00fea9023d336e0858941b (diff) | |
parent | 170173bf37342dab486daaa2a0381d802c10fb21 (diff) |
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Included changes:
- hash computation improvements
- Bridge Loop Avoidance set-up phase optimisations
- Roaming handling code redesign
- some code cleanups
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 59 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 41 | ||||
-rw-r--r-- | net/batman-adv/hash.h | 22 | ||||
-rw-r--r-- | net/batman-adv/main.h | 1 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 1 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 173 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 1 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 2 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 276 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 2 | ||||
-rw-r--r-- | net/batman-adv/types.h | 11 |
11 files changed, 416 insertions, 173 deletions
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 29a5542aac75..bda8b1710806 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, | |||
40 | /* return the index of the claim */ | 40 | /* return the index of the claim */ |
41 | static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) | 41 | static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) |
42 | { | 42 | { |
43 | const unsigned char *key = data; | 43 | struct batadv_claim *claim = (struct batadv_claim *)data; |
44 | uint32_t hash = 0; | 44 | uint32_t hash = 0; |
45 | size_t i; | ||
46 | 45 | ||
47 | for (i = 0; i < ETH_ALEN + sizeof(short); i++) { | 46 | hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); |
48 | hash += key[i]; | 47 | hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); |
49 | hash += (hash << 10); | ||
50 | hash ^= (hash >> 6); | ||
51 | } | ||
52 | 48 | ||
53 | hash += (hash << 3); | 49 | hash += (hash << 3); |
54 | hash ^= (hash >> 11); | 50 | hash ^= (hash >> 11); |
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) | |||
61 | static inline uint32_t batadv_choose_backbone_gw(const void *data, | 57 | static inline uint32_t batadv_choose_backbone_gw(const void *data, |
62 | uint32_t size) | 58 | uint32_t size) |
63 | { | 59 | { |
64 | const unsigned char *key = data; | 60 | struct batadv_claim *claim = (struct batadv_claim *)data; |
65 | uint32_t hash = 0; | 61 | uint32_t hash = 0; |
66 | size_t i; | ||
67 | 62 | ||
68 | for (i = 0; i < ETH_ALEN + sizeof(short); i++) { | 63 | hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); |
69 | hash += key[i]; | 64 | hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); |
70 | hash += (hash << 10); | ||
71 | hash ^= (hash >> 6); | ||
72 | } | ||
73 | 65 | ||
74 | hash += (hash << 3); | 66 | hash += (hash << 3); |
75 | hash ^= (hash >> 11); | 67 | hash ^= (hash >> 11); |
@@ -362,7 +354,7 @@ out: | |||
362 | */ | 354 | */ |
363 | static struct batadv_backbone_gw * | 355 | static struct batadv_backbone_gw * |
364 | batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | 356 | batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, |
365 | short vid) | 357 | short vid, bool own_backbone) |
366 | { | 358 | { |
367 | struct batadv_backbone_gw *entry; | 359 | struct batadv_backbone_gw *entry; |
368 | struct batadv_orig_node *orig_node; | 360 | struct batadv_orig_node *orig_node; |
@@ -386,6 +378,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
386 | entry->crc = BATADV_BLA_CRC_INIT; | 378 | entry->crc = BATADV_BLA_CRC_INIT; |
387 | entry->bat_priv = bat_priv; | 379 | entry->bat_priv = bat_priv; |
388 | atomic_set(&entry->request_sent, 0); | 380 | atomic_set(&entry->request_sent, 0); |
381 | atomic_set(&entry->wait_periods, 0); | ||
389 | memcpy(entry->orig, orig, ETH_ALEN); | 382 | memcpy(entry->orig, orig, ETH_ALEN); |
390 | 383 | ||
391 | /* one for the hash, one for returning */ | 384 | /* one for the hash, one for returning */ |
@@ -409,6 +402,16 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
409 | "became a backbone gateway"); | 402 | "became a backbone gateway"); |
410 | batadv_orig_node_free_ref(orig_node); | 403 | batadv_orig_node_free_ref(orig_node); |
411 | } | 404 | } |
405 | |||
406 | if (own_backbone) { | ||
407 | batadv_bla_send_announce(bat_priv, entry); | ||
408 | |||
409 | /* this will be decreased in the worker thread */ | ||
410 | atomic_inc(&entry->request_sent); | ||
411 | atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS); | ||
412 | atomic_inc(&bat_priv->bla.num_requests); | ||
413 | } | ||
414 | |||
412 | return entry; | 415 | return entry; |
413 | } | 416 | } |
414 | 417 | ||
@@ -424,7 +427,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv, | |||
424 | 427 | ||
425 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, | 428 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, |
426 | primary_if->net_dev->dev_addr, | 429 | primary_if->net_dev->dev_addr, |
427 | vid); | 430 | vid, true); |
428 | if (unlikely(!backbone_gw)) | 431 | if (unlikely(!backbone_gw)) |
429 | return; | 432 | return; |
430 | 433 | ||
@@ -632,7 +635,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, | |||
632 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) | 635 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) |
633 | return 0; | 636 | return 0; |
634 | 637 | ||
635 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); | 638 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, |
639 | false); | ||
636 | 640 | ||
637 | if (unlikely(!backbone_gw)) | 641 | if (unlikely(!backbone_gw)) |
638 | return 1; | 642 | return 1; |
@@ -730,7 +734,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, | |||
730 | 734 | ||
731 | /* register the gateway if not yet available, and add the claim. */ | 735 | /* register the gateway if not yet available, and add the claim. */ |
732 | 736 | ||
733 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); | 737 | backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, |
738 | false); | ||
734 | 739 | ||
735 | if (unlikely(!backbone_gw)) | 740 | if (unlikely(!backbone_gw)) |
736 | return 1; | 741 | return 1; |
@@ -1140,6 +1145,24 @@ static void batadv_bla_periodic_work(struct work_struct *work) | |||
1140 | backbone_gw->lasttime = jiffies; | 1145 | backbone_gw->lasttime = jiffies; |
1141 | 1146 | ||
1142 | batadv_bla_send_announce(bat_priv, backbone_gw); | 1147 | batadv_bla_send_announce(bat_priv, backbone_gw); |
1148 | |||
1149 | /* request_sent is only set after creation to avoid | ||
1150 | * problems when we are not yet known as backbone gw | ||
1151 | * in the backbone. | ||
1152 | * | ||
1153 | * We can reset this now after we waited some periods | ||
1154 | * to give bridge forward delays and bla group forming | ||
1155 | * some grace time. | ||
1156 | */ | ||
1157 | |||
1158 | if (atomic_read(&backbone_gw->request_sent) == 0) | ||
1159 | continue; | ||
1160 | |||
1161 | if (!atomic_dec_and_test(&backbone_gw->wait_periods)) | ||
1162 | continue; | ||
1163 | |||
1164 | atomic_dec(&backbone_gw->bat_priv->bla.num_requests); | ||
1165 | atomic_set(&backbone_gw->request_sent, 0); | ||
1143 | } | 1166 | } |
1144 | rcu_read_unlock(); | 1167 | rcu_read_unlock(); |
1145 | } | 1168 | } |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 6b7a5d3eeb77..365ed74f3946 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -59,6 +59,45 @@ out: | |||
59 | return hard_iface; | 59 | return hard_iface; |
60 | } | 60 | } |
61 | 61 | ||
62 | /** | ||
63 | * batadv_is_on_batman_iface - check if a device is a batman iface descendant | ||
64 | * @net_dev: the device to check | ||
65 | * | ||
66 | * If the user creates any virtual device on top of a batman-adv interface, it | ||
67 | * is important to prevent this new interface to be used to create a new mesh | ||
68 | * network (this behaviour would lead to a batman-over-batman configuration). | ||
69 | * This function recursively checks all the fathers of the device passed as | ||
70 | * argument looking for a batman-adv soft interface. | ||
71 | * | ||
72 | * Returns true if the device is descendant of a batman-adv mesh interface (or | ||
73 | * if it is a batman-adv interface itself), false otherwise | ||
74 | */ | ||
75 | static bool batadv_is_on_batman_iface(const struct net_device *net_dev) | ||
76 | { | ||
77 | struct net_device *parent_dev; | ||
78 | bool ret; | ||
79 | |||
80 | /* check if this is a batman-adv mesh interface */ | ||
81 | if (batadv_softif_is_valid(net_dev)) | ||
82 | return true; | ||
83 | |||
84 | /* no more parents..stop recursion */ | ||
85 | if (net_dev->iflink == net_dev->ifindex) | ||
86 | return false; | ||
87 | |||
88 | /* recurse over the parent device */ | ||
89 | parent_dev = dev_get_by_index(&init_net, net_dev->iflink); | ||
90 | /* if we got a NULL parent_dev there is something broken.. */ | ||
91 | if (WARN(!parent_dev, "Cannot find parent device")) | ||
92 | return false; | ||
93 | |||
94 | ret = batadv_is_on_batman_iface(parent_dev); | ||
95 | |||
96 | if (parent_dev) | ||
97 | dev_put(parent_dev); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
62 | static int batadv_is_valid_iface(const struct net_device *net_dev) | 101 | static int batadv_is_valid_iface(const struct net_device *net_dev) |
63 | { | 102 | { |
64 | if (net_dev->flags & IFF_LOOPBACK) | 103 | if (net_dev->flags & IFF_LOOPBACK) |
@@ -71,7 +110,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev) | |||
71 | return 0; | 110 | return 0; |
72 | 111 | ||
73 | /* no batman over batman */ | 112 | /* no batman over batman */ |
74 | if (batadv_softif_is_valid(net_dev)) | 113 | if (batadv_is_on_batman_iface(net_dev)) |
75 | return 0; | 114 | return 0; |
76 | 115 | ||
77 | return 1; | 116 | return 1; |
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index 977de9c75fc2..e05333905afd 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h | |||
@@ -82,6 +82,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash, | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * batadv_hash_bytes - hash some bytes and add them to the previous hash | ||
86 | * @hash: previous hash value | ||
87 | * @data: data to be hashed | ||
88 | * @size: number of bytes to be hashed | ||
89 | * | ||
90 | * Returns the new hash value. | ||
91 | */ | ||
92 | static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data, | ||
93 | uint32_t size) | ||
94 | { | ||
95 | const unsigned char *key = data; | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < size; i++) { | ||
99 | hash += key[i]; | ||
100 | hash += (hash << 10); | ||
101 | hash ^= (hash >> 6); | ||
102 | } | ||
103 | return hash; | ||
104 | } | ||
105 | |||
106 | /** | ||
85 | * batadv_hash_add - adds data to the hashtable | 107 | * batadv_hash_add - adds data to the hashtable |
86 | * @hash: storage hash table | 108 | * @hash: storage hash table |
87 | * @compare: callback to determine if 2 hash elements are identical | 109 | * @compare: callback to determine if 2 hash elements are identical |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 240c74ffeb93..8f149bb66817 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -95,6 +95,7 @@ | |||
95 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ | 95 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ |
96 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) | 96 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) |
97 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) | 97 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) |
98 | #define BATADV_BLA_WAIT_PERIODS 3 | ||
98 | 99 | ||
99 | #define BATADV_DUPLIST_SIZE 16 | 100 | #define BATADV_DUPLIST_SIZE 16 |
100 | #define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ | 101 | #define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 84930a4f5369..8c32cf1c2dec 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -221,7 +221,6 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, | |||
221 | atomic_set(&orig_node->refcount, 2); | 221 | atomic_set(&orig_node->refcount, 2); |
222 | 222 | ||
223 | orig_node->tt_initialised = false; | 223 | orig_node->tt_initialised = false; |
224 | orig_node->tt_poss_change = false; | ||
225 | orig_node->bat_priv = bat_priv; | 224 | orig_node->bat_priv = bat_priv; |
226 | memcpy(orig_node->orig, addr, ETH_ALEN); | 225 | memcpy(orig_node->orig, addr, ETH_ALEN); |
227 | batadv_dat_init_orig_node_addr(orig_node); | 226 | batadv_dat_init_orig_node_addr(orig_node); |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 32aa4d460e1f..78d657264cbf 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -711,12 +711,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | |||
711 | BATADV_TT_CLIENT_ROAM, | 711 | BATADV_TT_CLIENT_ROAM, |
712 | atomic_read(&orig_node->last_ttvn) + 1); | 712 | atomic_read(&orig_node->last_ttvn) + 1); |
713 | 713 | ||
714 | /* Roaming phase starts: I have new information but the ttvn has not | ||
715 | * been incremented yet. This flag will make me check all the incoming | ||
716 | * packets for the correct destination. | ||
717 | */ | ||
718 | bat_priv->tt.poss_change = true; | ||
719 | |||
720 | batadv_orig_node_free_ref(orig_node); | 714 | batadv_orig_node_free_ref(orig_node); |
721 | out: | 715 | out: |
722 | /* returning NET_RX_DROP will make the caller function kfree the skb */ | 716 | /* returning NET_RX_DROP will make the caller function kfree the skb */ |
@@ -899,14 +893,67 @@ out: | |||
899 | return ret; | 893 | return ret; |
900 | } | 894 | } |
901 | 895 | ||
896 | /** | ||
897 | * batadv_reroute_unicast_packet - update the unicast header for re-routing | ||
898 | * @bat_priv: the bat priv with all the soft interface information | ||
899 | * @unicast_packet: the unicast header to be updated | ||
900 | * @dst_addr: the payload destination | ||
901 | * | ||
902 | * Search the translation table for dst_addr and update the unicast header with | ||
903 | * the new corresponding information (originator address where the destination | ||
904 | * client currently is and its known TTVN) | ||
905 | * | ||
906 | * Returns true if the packet header has been updated, false otherwise | ||
907 | */ | ||
908 | static bool | ||
909 | batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, | ||
910 | struct batadv_unicast_packet *unicast_packet, | ||
911 | uint8_t *dst_addr) | ||
912 | { | ||
913 | struct batadv_orig_node *orig_node = NULL; | ||
914 | struct batadv_hard_iface *primary_if = NULL; | ||
915 | bool ret = false; | ||
916 | uint8_t *orig_addr, orig_ttvn; | ||
917 | |||
918 | if (batadv_is_my_client(bat_priv, dst_addr)) { | ||
919 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
920 | if (!primary_if) | ||
921 | goto out; | ||
922 | orig_addr = primary_if->net_dev->dev_addr; | ||
923 | orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | ||
924 | } else { | ||
925 | orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr); | ||
926 | if (!orig_node) | ||
927 | goto out; | ||
928 | |||
929 | if (batadv_compare_eth(orig_node->orig, unicast_packet->dest)) | ||
930 | goto out; | ||
931 | |||
932 | orig_addr = orig_node->orig; | ||
933 | orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
934 | } | ||
935 | |||
936 | /* update the packet header */ | ||
937 | memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); | ||
938 | unicast_packet->ttvn = orig_ttvn; | ||
939 | |||
940 | ret = true; | ||
941 | out: | ||
942 | if (primary_if) | ||
943 | batadv_hardif_free_ref(primary_if); | ||
944 | if (orig_node) | ||
945 | batadv_orig_node_free_ref(orig_node); | ||
946 | |||
947 | return ret; | ||
948 | } | ||
949 | |||
902 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | 950 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, |
903 | struct sk_buff *skb) { | 951 | struct sk_buff *skb) { |
904 | uint8_t curr_ttvn; | 952 | uint8_t curr_ttvn, old_ttvn; |
905 | struct batadv_orig_node *orig_node; | 953 | struct batadv_orig_node *orig_node; |
906 | struct ethhdr *ethhdr; | 954 | struct ethhdr *ethhdr; |
907 | struct batadv_hard_iface *primary_if; | 955 | struct batadv_hard_iface *primary_if; |
908 | struct batadv_unicast_packet *unicast_packet; | 956 | struct batadv_unicast_packet *unicast_packet; |
909 | bool tt_poss_change; | ||
910 | int is_old_ttvn; | 957 | int is_old_ttvn; |
911 | 958 | ||
912 | /* check if there is enough data before accessing it */ | 959 | /* check if there is enough data before accessing it */ |
@@ -918,65 +965,89 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
918 | return 0; | 965 | return 0; |
919 | 966 | ||
920 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 967 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
968 | ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | ||
921 | 969 | ||
922 | if (batadv_is_my_mac(unicast_packet->dest)) { | 970 | /* check if the destination client was served by this node and it is now |
923 | tt_poss_change = bat_priv->tt.poss_change; | 971 | * roaming. In this case, it means that the node has got a ROAM_ADV |
924 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | 972 | * message and that it knows the new destination in the mesh to re-route |
925 | } else { | 973 | * the packet to |
974 | */ | ||
975 | if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) { | ||
976 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | ||
977 | ethhdr->h_dest)) | ||
978 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, | ||
979 | bat_priv, | ||
980 | "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", | ||
981 | unicast_packet->dest, | ||
982 | ethhdr->h_dest); | ||
983 | /* at this point the mesh destination should have been | ||
984 | * substituted with the originator address found in the global | ||
985 | * table. If not, let the packet go untouched anyway because | ||
986 | * there is nothing the node can do | ||
987 | */ | ||
988 | return 1; | ||
989 | } | ||
990 | |||
991 | /* retrieve the TTVN known by this node for the packet destination. This | ||
992 | * value is used later to check if the node which sent (or re-routed | ||
993 | * last time) the packet had an updated information or not | ||
994 | */ | ||
995 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | ||
996 | if (!batadv_is_my_mac(unicast_packet->dest)) { | ||
926 | orig_node = batadv_orig_hash_find(bat_priv, | 997 | orig_node = batadv_orig_hash_find(bat_priv, |
927 | unicast_packet->dest); | 998 | unicast_packet->dest); |
928 | 999 | /* if it is not possible to find the orig_node representing the | |
1000 | * destination, the packet can immediately be dropped as it will | ||
1001 | * not be possible to deliver it | ||
1002 | */ | ||
929 | if (!orig_node) | 1003 | if (!orig_node) |
930 | return 0; | 1004 | return 0; |
931 | 1005 | ||
932 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | 1006 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
933 | tt_poss_change = orig_node->tt_poss_change; | ||
934 | batadv_orig_node_free_ref(orig_node); | 1007 | batadv_orig_node_free_ref(orig_node); |
935 | } | 1008 | } |
936 | 1009 | ||
937 | /* Check whether I have to reroute the packet */ | 1010 | /* check if the TTVN contained in the packet is fresher than what the |
1011 | * node knows | ||
1012 | */ | ||
938 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); | 1013 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); |
939 | if (is_old_ttvn || tt_poss_change) { | 1014 | if (!is_old_ttvn) |
940 | /* check if there is enough data before accessing it */ | 1015 | return 1; |
941 | if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) + | ||
942 | ETH_HLEN) < 0) | ||
943 | return 0; | ||
944 | 1016 | ||
945 | ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | 1017 | old_ttvn = unicast_packet->ttvn; |
1018 | /* the packet was forged based on outdated network information. Its | ||
1019 | * destination can possibly be updated and forwarded towards the new | ||
1020 | * target host | ||
1021 | */ | ||
1022 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | ||
1023 | ethhdr->h_dest)) { | ||
1024 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | ||
1025 | "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", | ||
1026 | unicast_packet->dest, ethhdr->h_dest, | ||
1027 | old_ttvn, curr_ttvn); | ||
1028 | return 1; | ||
1029 | } | ||
946 | 1030 | ||
947 | /* we don't have an updated route for this client, so we should | 1031 | /* the packet has not been re-routed: either the destination is |
948 | * not try to reroute the packet!! | 1032 | * currently served by this node or there is no destination at all and |
949 | */ | 1033 | * it is possible to drop the packet |
950 | if (batadv_tt_global_client_is_roaming(bat_priv, | 1034 | */ |
951 | ethhdr->h_dest)) | 1035 | if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) |
952 | return 1; | 1036 | return 0; |
953 | 1037 | ||
954 | orig_node = batadv_transtable_search(bat_priv, NULL, | 1038 | /* update the header in order to let the packet be delivered to this |
955 | ethhdr->h_dest); | 1039 | * node's soft interface |
956 | 1040 | */ | |
957 | if (!orig_node) { | 1041 | primary_if = batadv_primary_if_get_selected(bat_priv); |
958 | if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) | 1042 | if (!primary_if) |
959 | return 0; | 1043 | return 0; |
960 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
961 | if (!primary_if) | ||
962 | return 0; | ||
963 | memcpy(unicast_packet->dest, | ||
964 | primary_if->net_dev->dev_addr, ETH_ALEN); | ||
965 | batadv_hardif_free_ref(primary_if); | ||
966 | } else { | ||
967 | memcpy(unicast_packet->dest, orig_node->orig, | ||
968 | ETH_ALEN); | ||
969 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
970 | batadv_orig_node_free_ref(orig_node); | ||
971 | } | ||
972 | 1044 | ||
973 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | 1045 | memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); |
974 | "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", | 1046 | |
975 | unicast_packet->ttvn, curr_ttvn, | 1047 | batadv_hardif_free_ref(primary_if); |
976 | ethhdr->h_dest, unicast_packet->dest); | 1048 | |
1049 | unicast_packet->ttvn = curr_ttvn; | ||
977 | 1050 | ||
978 | unicast_packet->ttvn = curr_ttvn; | ||
979 | } | ||
980 | return 1; | 1051 | return 1; |
981 | } | 1052 | } |
982 | 1053 | ||
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c283d87c4cce..2d1f89517d99 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -505,7 +505,6 @@ struct net_device *batadv_softif_create(const char *name) | |||
505 | #endif | 505 | #endif |
506 | bat_priv->tt.last_changeset = NULL; | 506 | bat_priv->tt.last_changeset = NULL; |
507 | bat_priv->tt.last_changeset_len = 0; | 507 | bat_priv->tt.last_changeset_len = 0; |
508 | bat_priv->tt.poss_change = false; | ||
509 | 508 | ||
510 | bat_priv->primary_if = NULL; | 509 | bat_priv->primary_if = NULL; |
511 | bat_priv->num_ifaces = 0; | 510 | bat_priv->num_ifaces = 0; |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index fa3cc1af0918..84a55cb19b0b 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -688,7 +688,7 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, | |||
688 | enum batadv_uev_action action, const char *data) | 688 | enum batadv_uev_action action, const char *data) |
689 | { | 689 | { |
690 | int ret = -ENOMEM; | 690 | int ret = -ENOMEM; |
691 | struct batadv_hard_iface *primary_if = NULL; | 691 | struct batadv_hard_iface *primary_if; |
692 | struct kobject *bat_kobj; | 692 | struct kobject *bat_kobj; |
693 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; | 693 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; |
694 | 694 | ||
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f8b9c32c29a5..9f5705fcf426 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -238,92 +238,134 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static void batadv_tt_global_free(struct batadv_priv *bat_priv, | ||
242 | struct batadv_tt_global_entry *tt_global, | ||
243 | const char *message) | ||
244 | { | ||
245 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
246 | "Deleting global tt entry %pM: %s\n", | ||
247 | tt_global->common.addr, message); | ||
248 | |||
249 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, | ||
250 | batadv_choose_orig, tt_global->common.addr); | ||
251 | batadv_tt_global_entry_free_ref(tt_global); | ||
252 | |||
253 | } | ||
254 | |||
241 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | 255 | void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, |
242 | int ifindex) | 256 | int ifindex) |
243 | { | 257 | { |
244 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 258 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
245 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 259 | struct batadv_tt_local_entry *tt_local; |
246 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 260 | struct batadv_tt_global_entry *tt_global; |
247 | struct hlist_head *head; | 261 | struct hlist_head *head; |
248 | struct hlist_node *node; | 262 | struct hlist_node *node; |
249 | struct batadv_tt_orig_list_entry *orig_entry; | 263 | struct batadv_tt_orig_list_entry *orig_entry; |
250 | int hash_added; | 264 | int hash_added; |
265 | bool roamed_back = false; | ||
251 | 266 | ||
252 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 267 | tt_local = batadv_tt_local_hash_find(bat_priv, addr); |
268 | tt_global = batadv_tt_global_hash_find(bat_priv, addr); | ||
253 | 269 | ||
254 | if (tt_local_entry) { | 270 | if (tt_local) { |
255 | tt_local_entry->last_seen = jiffies; | 271 | tt_local->last_seen = jiffies; |
256 | /* possibly unset the BATADV_TT_CLIENT_PENDING flag */ | 272 | if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) { |
257 | tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING; | 273 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
258 | goto out; | 274 | "Re-adding pending client %pM\n", addr); |
275 | /* whatever the reason why the PENDING flag was set, | ||
276 | * this is a client which was enqueued to be removed in | ||
277 | * this orig_interval. Since it popped up again, the | ||
278 | * flag can be reset like it was never enqueued | ||
279 | */ | ||
280 | tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; | ||
281 | goto add_event; | ||
282 | } | ||
283 | |||
284 | if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) { | ||
285 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
286 | "Roaming client %pM came back to its original location\n", | ||
287 | addr); | ||
288 | /* the ROAM flag is set because this client roamed away | ||
289 | * and the node got a roaming_advertisement message. Now | ||
290 | * that the client popped up again at its original | ||
291 | * location such flag can be unset | ||
292 | */ | ||
293 | tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM; | ||
294 | roamed_back = true; | ||
295 | } | ||
296 | goto check_roaming; | ||
259 | } | 297 | } |
260 | 298 | ||
261 | tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC); | 299 | tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); |
262 | if (!tt_local_entry) | 300 | if (!tt_local) |
263 | goto out; | 301 | goto out; |
264 | 302 | ||
265 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 303 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
266 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 304 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
267 | (uint8_t)atomic_read(&bat_priv->tt.vn)); | 305 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
268 | 306 | ||
269 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); | 307 | memcpy(tt_local->common.addr, addr, ETH_ALEN); |
270 | tt_local_entry->common.flags = BATADV_NO_FLAGS; | 308 | tt_local->common.flags = BATADV_NO_FLAGS; |
271 | if (batadv_is_wifi_iface(ifindex)) | 309 | if (batadv_is_wifi_iface(ifindex)) |
272 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; | 310 | tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; |
273 | atomic_set(&tt_local_entry->common.refcount, 2); | 311 | atomic_set(&tt_local->common.refcount, 2); |
274 | tt_local_entry->last_seen = jiffies; | 312 | tt_local->last_seen = jiffies; |
275 | tt_local_entry->common.added_at = tt_local_entry->last_seen; | 313 | tt_local->common.added_at = tt_local->last_seen; |
276 | 314 | ||
277 | /* the batman interface mac address should never be purged */ | 315 | /* the batman interface mac address should never be purged */ |
278 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) | 316 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) |
279 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE; | 317 | tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; |
280 | 318 | ||
281 | /* The local entry has to be marked as NEW to avoid to send it in | 319 | /* The local entry has to be marked as NEW to avoid to send it in |
282 | * a full table response going out before the next ttvn increment | 320 | * a full table response going out before the next ttvn increment |
283 | * (consistency check) | 321 | * (consistency check) |
284 | */ | 322 | */ |
285 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; | 323 | tt_local->common.flags |= BATADV_TT_CLIENT_NEW; |
286 | 324 | ||
287 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, | 325 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
288 | batadv_choose_orig, | 326 | batadv_choose_orig, &tt_local->common, |
289 | &tt_local_entry->common, | 327 | &tt_local->common.hash_entry); |
290 | &tt_local_entry->common.hash_entry); | ||
291 | 328 | ||
292 | if (unlikely(hash_added != 0)) { | 329 | if (unlikely(hash_added != 0)) { |
293 | /* remove the reference for the hash */ | 330 | /* remove the reference for the hash */ |
294 | batadv_tt_local_entry_free_ref(tt_local_entry); | 331 | batadv_tt_local_entry_free_ref(tt_local); |
295 | goto out; | 332 | goto out; |
296 | } | 333 | } |
297 | 334 | ||
298 | batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags); | 335 | add_event: |
299 | 336 | batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); | |
300 | /* remove address from global hash if present */ | ||
301 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); | ||
302 | 337 | ||
303 | /* Check whether it is a roaming! */ | 338 | check_roaming: |
304 | if (tt_global_entry) { | 339 | /* Check whether it is a roaming, but don't do anything if the roaming |
340 | * process has already been handled | ||
341 | */ | ||
342 | if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) { | ||
305 | /* These node are probably going to update their tt table */ | 343 | /* These node are probably going to update their tt table */ |
306 | head = &tt_global_entry->orig_list; | 344 | head = &tt_global->orig_list; |
307 | rcu_read_lock(); | 345 | rcu_read_lock(); |
308 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { | 346 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { |
309 | orig_entry->orig_node->tt_poss_change = true; | 347 | batadv_send_roam_adv(bat_priv, tt_global->common.addr, |
310 | |||
311 | batadv_send_roam_adv(bat_priv, | ||
312 | tt_global_entry->common.addr, | ||
313 | orig_entry->orig_node); | 348 | orig_entry->orig_node); |
314 | } | 349 | } |
315 | rcu_read_unlock(); | 350 | rcu_read_unlock(); |
316 | /* The global entry has to be marked as ROAMING and | 351 | if (roamed_back) { |
317 | * has to be kept for consistency purpose | 352 | batadv_tt_global_free(bat_priv, tt_global, |
318 | */ | 353 | "Roaming canceled"); |
319 | tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM; | 354 | tt_global = NULL; |
320 | tt_global_entry->roam_at = jiffies; | 355 | } else { |
356 | /* The global entry has to be marked as ROAMING and | ||
357 | * has to be kept for consistency purpose | ||
358 | */ | ||
359 | tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; | ||
360 | tt_global->roam_at = jiffies; | ||
361 | } | ||
321 | } | 362 | } |
363 | |||
322 | out: | 364 | out: |
323 | if (tt_local_entry) | 365 | if (tt_local) |
324 | batadv_tt_local_entry_free_ref(tt_local_entry); | 366 | batadv_tt_local_entry_free_ref(tt_local); |
325 | if (tt_global_entry) | 367 | if (tt_global) |
326 | batadv_tt_global_entry_free_ref(tt_global_entry); | 368 | batadv_tt_global_entry_free_ref(tt_global); |
327 | } | 369 | } |
328 | 370 | ||
329 | static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, | 371 | static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, |
@@ -502,7 +544,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | |||
502 | const uint8_t *addr, const char *message, | 544 | const uint8_t *addr, const char *message, |
503 | bool roaming) | 545 | bool roaming) |
504 | { | 546 | { |
505 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 547 | struct batadv_tt_local_entry *tt_local_entry; |
506 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; | 548 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; |
507 | 549 | ||
508 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 550 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
@@ -512,10 +554,28 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | |||
512 | curr_flags = tt_local_entry->common.flags; | 554 | curr_flags = tt_local_entry->common.flags; |
513 | 555 | ||
514 | flags = BATADV_TT_CLIENT_DEL; | 556 | flags = BATADV_TT_CLIENT_DEL; |
515 | if (roaming) | 557 | /* if this global entry addition is due to a roaming, the node has to |
558 | * mark the local entry as "roamed" in order to correctly reroute | ||
559 | * packets later | ||
560 | */ | ||
561 | if (roaming) { | ||
516 | flags |= BATADV_TT_CLIENT_ROAM; | 562 | flags |= BATADV_TT_CLIENT_ROAM; |
563 | /* mark the local client as ROAMed */ | ||
564 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; | ||
565 | } | ||
517 | 566 | ||
518 | batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); | 567 | if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) { |
568 | batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, | ||
569 | message); | ||
570 | goto out; | ||
571 | } | ||
572 | /* if this client has been added right now, it is possible to | ||
573 | * immediately purge it | ||
574 | */ | ||
575 | batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, | ||
576 | curr_flags | BATADV_TT_CLIENT_DEL); | ||
577 | hlist_del_rcu(&tt_local_entry->common.hash_entry); | ||
578 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
519 | 579 | ||
520 | out: | 580 | out: |
521 | if (tt_local_entry) | 581 | if (tt_local_entry) |
@@ -724,13 +784,23 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
724 | const unsigned char *tt_addr, uint8_t flags, | 784 | const unsigned char *tt_addr, uint8_t flags, |
725 | uint8_t ttvn) | 785 | uint8_t ttvn) |
726 | { | 786 | { |
727 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 787 | struct batadv_tt_global_entry *tt_global_entry; |
788 | struct batadv_tt_local_entry *tt_local_entry; | ||
728 | int ret = 0; | 789 | int ret = 0; |
729 | int hash_added; | 790 | int hash_added; |
730 | struct batadv_tt_common_entry *common; | 791 | struct batadv_tt_common_entry *common; |
731 | uint16_t local_flags; | 792 | uint16_t local_flags; |
732 | 793 | ||
733 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); | 794 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); |
795 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr); | ||
796 | |||
797 | /* if the node already has a local client for this entry, it has to wait | ||
798 | * for a roaming advertisement instead of manually messing up the global | ||
799 | * table | ||
800 | */ | ||
801 | if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry && | ||
802 | !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) | ||
803 | goto out; | ||
734 | 804 | ||
735 | if (!tt_global_entry) { | 805 | if (!tt_global_entry) { |
736 | tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); | 806 | tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); |
@@ -765,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
765 | goto out_remove; | 835 | goto out_remove; |
766 | } | 836 | } |
767 | } else { | 837 | } else { |
838 | common = &tt_global_entry->common; | ||
768 | /* If there is already a global entry, we can use this one for | 839 | /* If there is already a global entry, we can use this one for |
769 | * our processing. | 840 | * our processing. |
770 | * But if we are trying to add a temporary client we can exit | 841 | * But if we are trying to add a temporary client then here are |
771 | * directly because the temporary information should never | 842 | * two options at this point: |
772 | * override any already known client state (whatever it is) | 843 | * 1) the global client is not a temporary client: the global |
844 | * client has to be left as it is, temporary information | ||
845 | * should never override any already known client state | ||
846 | * 2) the global client is a temporary client: purge the | ||
847 | * originator list and add the new one orig_entry | ||
773 | */ | 848 | */ |
774 | if (flags & BATADV_TT_CLIENT_TEMP) | 849 | if (flags & BATADV_TT_CLIENT_TEMP) { |
775 | goto out; | 850 | if (!(common->flags & BATADV_TT_CLIENT_TEMP)) |
851 | goto out; | ||
852 | if (batadv_tt_global_entry_has_orig(tt_global_entry, | ||
853 | orig_node)) | ||
854 | goto out_remove; | ||
855 | batadv_tt_global_del_orig_list(tt_global_entry); | ||
856 | goto add_orig_entry; | ||
857 | } | ||
776 | 858 | ||
777 | /* if the client was temporary added before receiving the first | 859 | /* if the client was temporary added before receiving the first |
778 | * OGM announcing it, we have to clear the TEMP flag | 860 | * OGM announcing it, we have to clear the TEMP flag |
779 | */ | 861 | */ |
780 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; | 862 | common->flags &= ~BATADV_TT_CLIENT_TEMP; |
781 | 863 | ||
782 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only | 864 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only |
783 | * one originator left in the list and we previously received a | 865 | * one originator left in the list and we previously received a |
@@ -786,18 +868,19 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
786 | * We should first delete the old originator before adding the | 868 | * We should first delete the old originator before adding the |
787 | * new one. | 869 | * new one. |
788 | */ | 870 | */ |
789 | if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) { | 871 | if (common->flags & BATADV_TT_CLIENT_ROAM) { |
790 | batadv_tt_global_del_orig_list(tt_global_entry); | 872 | batadv_tt_global_del_orig_list(tt_global_entry); |
791 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | 873 | common->flags &= ~BATADV_TT_CLIENT_ROAM; |
792 | tt_global_entry->roam_at = 0; | 874 | tt_global_entry->roam_at = 0; |
793 | } | 875 | } |
794 | } | 876 | } |
877 | add_orig_entry: | ||
795 | /* add the new orig_entry (if needed) or update it */ | 878 | /* add the new orig_entry (if needed) or update it */ |
796 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); | 879 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); |
797 | 880 | ||
798 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 881 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
799 | "Creating new global tt entry: %pM (via %pM)\n", | 882 | "Creating new global tt entry: %pM (via %pM)\n", |
800 | tt_global_entry->common.addr, orig_node->orig); | 883 | common->addr, orig_node->orig); |
801 | ret = 1; | 884 | ret = 1; |
802 | 885 | ||
803 | out_remove: | 886 | out_remove: |
@@ -805,12 +888,20 @@ out_remove: | |||
805 | /* remove address from local hash if present */ | 888 | /* remove address from local hash if present */ |
806 | local_flags = batadv_tt_local_remove(bat_priv, tt_addr, | 889 | local_flags = batadv_tt_local_remove(bat_priv, tt_addr, |
807 | "global tt received", | 890 | "global tt received", |
808 | flags & BATADV_TT_CLIENT_ROAM); | 891 | !!(flags & BATADV_TT_CLIENT_ROAM)); |
809 | tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; | 892 | tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; |
810 | 893 | ||
894 | if (!(flags & BATADV_TT_CLIENT_ROAM)) | ||
895 | /* this is a normal global add. Therefore the client is not in a | ||
896 | * roaming state anymore. | ||
897 | */ | ||
898 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | ||
899 | |||
811 | out: | 900 | out: |
812 | if (tt_global_entry) | 901 | if (tt_global_entry) |
813 | batadv_tt_global_entry_free_ref(tt_global_entry); | 902 | batadv_tt_global_entry_free_ref(tt_global_entry); |
903 | if (tt_local_entry) | ||
904 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
814 | return ret; | 905 | return ret; |
815 | } | 906 | } |
816 | 907 | ||
@@ -928,21 +1019,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, | |||
928 | spin_unlock_bh(&tt_global_entry->list_lock); | 1019 | spin_unlock_bh(&tt_global_entry->list_lock); |
929 | } | 1020 | } |
930 | 1021 | ||
931 | static void | ||
932 | batadv_tt_global_del_struct(struct batadv_priv *bat_priv, | ||
933 | struct batadv_tt_global_entry *tt_global_entry, | ||
934 | const char *message) | ||
935 | { | ||
936 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
937 | "Deleting global tt entry %pM: %s\n", | ||
938 | tt_global_entry->common.addr, message); | ||
939 | |||
940 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, | ||
941 | batadv_choose_orig, tt_global_entry->common.addr); | ||
942 | batadv_tt_global_entry_free_ref(tt_global_entry); | ||
943 | |||
944 | } | ||
945 | |||
946 | /* If the client is to be deleted, we check if it is the last origantor entry | 1022 | /* If the client is to be deleted, we check if it is the last origantor entry |
947 | * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the | 1023 | * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the |
948 | * timer, otherwise we simply remove the originator scheduled for deletion. | 1024 | * timer, otherwise we simply remove the originator scheduled for deletion. |
@@ -991,7 +1067,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
991 | const unsigned char *addr, | 1067 | const unsigned char *addr, |
992 | const char *message, bool roaming) | 1068 | const char *message, bool roaming) |
993 | { | 1069 | { |
994 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 1070 | struct batadv_tt_global_entry *tt_global_entry; |
995 | struct batadv_tt_local_entry *local_entry = NULL; | 1071 | struct batadv_tt_local_entry *local_entry = NULL; |
996 | 1072 | ||
997 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); | 1073 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); |
@@ -1003,8 +1079,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
1003 | orig_node, message); | 1079 | orig_node, message); |
1004 | 1080 | ||
1005 | if (hlist_empty(&tt_global_entry->orig_list)) | 1081 | if (hlist_empty(&tt_global_entry->orig_list)) |
1006 | batadv_tt_global_del_struct(bat_priv, tt_global_entry, | 1082 | batadv_tt_global_free(bat_priv, tt_global_entry, |
1007 | message); | 1083 | message); |
1008 | 1084 | ||
1009 | goto out; | 1085 | goto out; |
1010 | } | 1086 | } |
@@ -1027,7 +1103,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
1027 | if (local_entry) { | 1103 | if (local_entry) { |
1028 | /* local entry exists, case 2: client roamed to us. */ | 1104 | /* local entry exists, case 2: client roamed to us. */ |
1029 | batadv_tt_global_del_orig_list(tt_global_entry); | 1105 | batadv_tt_global_del_orig_list(tt_global_entry); |
1030 | batadv_tt_global_del_struct(bat_priv, tt_global_entry, message); | 1106 | batadv_tt_global_free(bat_priv, tt_global_entry, message); |
1031 | } else | 1107 | } else |
1032 | /* no local entry exists, case 1: check for roaming */ | 1108 | /* no local entry exists, case 1: check for roaming */ |
1033 | batadv_tt_global_del_roaming(bat_priv, tt_global_entry, | 1109 | batadv_tt_global_del_roaming(bat_priv, tt_global_entry, |
@@ -1206,7 +1282,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, | |||
1206 | 1282 | ||
1207 | if (src && atomic_read(&bat_priv->ap_isolation)) { | 1283 | if (src && atomic_read(&bat_priv->ap_isolation)) { |
1208 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); | 1284 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); |
1209 | if (!tt_local_entry) | 1285 | if (!tt_local_entry || |
1286 | (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)) | ||
1210 | goto out; | 1287 | goto out; |
1211 | } | 1288 | } |
1212 | 1289 | ||
@@ -1593,7 +1670,7 @@ static bool | |||
1593 | batadv_send_other_tt_response(struct batadv_priv *bat_priv, | 1670 | batadv_send_other_tt_response(struct batadv_priv *bat_priv, |
1594 | struct batadv_tt_query_packet *tt_request) | 1671 | struct batadv_tt_query_packet *tt_request) |
1595 | { | 1672 | { |
1596 | struct batadv_orig_node *req_dst_orig_node = NULL; | 1673 | struct batadv_orig_node *req_dst_orig_node; |
1597 | struct batadv_orig_node *res_dst_orig_node = NULL; | 1674 | struct batadv_orig_node *res_dst_orig_node = NULL; |
1598 | struct batadv_neigh_node *neigh_node = NULL; | 1675 | struct batadv_neigh_node *neigh_node = NULL; |
1599 | struct batadv_hard_iface *primary_if = NULL; | 1676 | struct batadv_hard_iface *primary_if = NULL; |
@@ -1728,7 +1805,7 @@ static bool | |||
1728 | batadv_send_my_tt_response(struct batadv_priv *bat_priv, | 1805 | batadv_send_my_tt_response(struct batadv_priv *bat_priv, |
1729 | struct batadv_tt_query_packet *tt_request) | 1806 | struct batadv_tt_query_packet *tt_request) |
1730 | { | 1807 | { |
1731 | struct batadv_orig_node *orig_node = NULL; | 1808 | struct batadv_orig_node *orig_node; |
1732 | struct batadv_neigh_node *neigh_node = NULL; | 1809 | struct batadv_neigh_node *neigh_node = NULL; |
1733 | struct batadv_hard_iface *primary_if = NULL; | 1810 | struct batadv_hard_iface *primary_if = NULL; |
1734 | uint8_t my_ttvn, req_ttvn, ttvn; | 1811 | uint8_t my_ttvn, req_ttvn, ttvn; |
@@ -1894,7 +1971,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, | |||
1894 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, | 1971 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, |
1895 | struct batadv_tt_query_packet *tt_response) | 1972 | struct batadv_tt_query_packet *tt_response) |
1896 | { | 1973 | { |
1897 | struct batadv_orig_node *orig_node = NULL; | 1974 | struct batadv_orig_node *orig_node; |
1898 | 1975 | ||
1899 | orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); | 1976 | orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); |
1900 | if (!orig_node) | 1977 | if (!orig_node) |
@@ -1936,7 +2013,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv, | |||
1936 | 2013 | ||
1937 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) | 2014 | bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) |
1938 | { | 2015 | { |
1939 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 2016 | struct batadv_tt_local_entry *tt_local_entry; |
1940 | bool ret = false; | 2017 | bool ret = false; |
1941 | 2018 | ||
1942 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | 2019 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
@@ -1945,7 +2022,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) | |||
1945 | /* Check if the client has been logically deleted (but is kept for | 2022 | /* Check if the client has been logically deleted (but is kept for |
1946 | * consistency purpose) | 2023 | * consistency purpose) |
1947 | */ | 2024 | */ |
1948 | if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) | 2025 | if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) || |
2026 | (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM)) | ||
1949 | goto out; | 2027 | goto out; |
1950 | ret = true; | 2028 | ret = true; |
1951 | out: | 2029 | out: |
@@ -1996,10 +2074,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv, | |||
1996 | 2074 | ||
1997 | /* Recalculate the CRC for this orig_node and store it */ | 2075 | /* Recalculate the CRC for this orig_node and store it */ |
1998 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); | 2076 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
1999 | /* Roaming phase is over: tables are in sync again. I can | ||
2000 | * unset the flag | ||
2001 | */ | ||
2002 | orig_node->tt_poss_change = false; | ||
2003 | out: | 2077 | out: |
2004 | if (orig_node) | 2078 | if (orig_node) |
2005 | batadv_orig_node_free_ref(orig_node); | 2079 | batadv_orig_node_free_ref(orig_node); |
@@ -2290,7 +2364,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, | |||
2290 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 2364 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
2291 | "Local changes committed, updating to ttvn %u\n", | 2365 | "Local changes committed, updating to ttvn %u\n", |
2292 | (uint8_t)atomic_read(&bat_priv->tt.vn)); | 2366 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
2293 | bat_priv->tt.poss_change = false; | ||
2294 | 2367 | ||
2295 | /* reset the sending counter */ | 2368 | /* reset the sending counter */ |
2296 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); | 2369 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
@@ -2402,11 +2475,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv, | |||
2402 | */ | 2475 | */ |
2403 | if (orig_node->tt_crc != tt_crc) | 2476 | if (orig_node->tt_crc != tt_crc) |
2404 | goto request_table; | 2477 | goto request_table; |
2405 | |||
2406 | /* Roaming phase is over: tables are in sync again. I can | ||
2407 | * unset the flag | ||
2408 | */ | ||
2409 | orig_node->tt_poss_change = false; | ||
2410 | } else { | 2478 | } else { |
2411 | /* if we missed more than one change or our tables are not | 2479 | /* if we missed more than one change or our tables are not |
2412 | * in sync anymore -> request fresh tt data | 2480 | * in sync anymore -> request fresh tt data |
@@ -2445,6 +2513,32 @@ out: | |||
2445 | return ret; | 2513 | return ret; |
2446 | } | 2514 | } |
2447 | 2515 | ||
2516 | /** | ||
2517 | * batadv_tt_local_client_is_roaming - tells whether the client is roaming | ||
2518 | * @bat_priv: the bat priv with all the soft interface information | ||
2519 | * @addr: the MAC address of the local client to query | ||
2520 | * | ||
2521 | * Returns true if the local client is known to be roaming (it is not served by | ||
2522 | * this node anymore) or not. If yes, the client is still present in the table | ||
2523 | * to keep the latter consistent with the node TTVN | ||
2524 | */ | ||
2525 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | ||
2526 | uint8_t *addr) | ||
2527 | { | ||
2528 | struct batadv_tt_local_entry *tt_local_entry; | ||
2529 | bool ret = false; | ||
2530 | |||
2531 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); | ||
2532 | if (!tt_local_entry) | ||
2533 | goto out; | ||
2534 | |||
2535 | ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM; | ||
2536 | batadv_tt_local_entry_free_ref(tt_local_entry); | ||
2537 | out: | ||
2538 | return ret; | ||
2539 | |||
2540 | } | ||
2541 | |||
2448 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | 2542 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
2449 | struct batadv_orig_node *orig_node, | 2543 | struct batadv_orig_node *orig_node, |
2450 | const unsigned char *addr) | 2544 | const unsigned char *addr) |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 9fa4fe41c868..46d4451a59ee 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv, | |||
59 | int packet_min_len); | 59 | int packet_min_len); |
60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | 60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | uint8_t *addr); | 61 | uint8_t *addr); |
62 | bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, | ||
63 | uint8_t *addr); | ||
62 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | 64 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, |
63 | struct batadv_orig_node *orig_node, | 65 | struct batadv_orig_node *orig_node, |
64 | const unsigned char *addr); | 66 | const unsigned char *addr); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 8ce16c1cbafb..7b3d0d7ef06a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -101,13 +101,6 @@ struct batadv_orig_node { | |||
101 | spinlock_t tt_buff_lock; /* protects tt_buff */ | 101 | spinlock_t tt_buff_lock; /* protects tt_buff */ |
102 | atomic_t tt_size; | 102 | atomic_t tt_size; |
103 | bool tt_initialised; | 103 | bool tt_initialised; |
104 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | ||
105 | * If true, then I sent a Roaming_adv to this orig_node and I have to | ||
106 | * inspect every packet directed to it to check whether it is still | ||
107 | * the true destination or not. This flag will be reset to false as | ||
108 | * soon as I receive a new TTVN from this orig_node | ||
109 | */ | ||
110 | bool tt_poss_change; | ||
111 | uint32_t last_real_seqno; | 104 | uint32_t last_real_seqno; |
112 | uint8_t last_ttl; | 105 | uint8_t last_ttl; |
113 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 106 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
@@ -212,7 +205,6 @@ struct batadv_priv_tt { | |||
212 | atomic_t vn; | 205 | atomic_t vn; |
213 | atomic_t ogm_append_cnt; | 206 | atomic_t ogm_append_cnt; |
214 | atomic_t local_changes; | 207 | atomic_t local_changes; |
215 | bool poss_change; | ||
216 | struct list_head changes_list; | 208 | struct list_head changes_list; |
217 | struct batadv_hashtable *local_hash; | 209 | struct batadv_hashtable *local_hash; |
218 | struct batadv_hashtable *global_hash; | 210 | struct batadv_hashtable *global_hash; |
@@ -303,7 +295,7 @@ struct batadv_priv { | |||
303 | struct hlist_head forw_bcast_list; | 295 | struct hlist_head forw_bcast_list; |
304 | struct batadv_hashtable *orig_hash; | 296 | struct batadv_hashtable *orig_hash; |
305 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 297 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
306 | spinlock_t forw_bcast_list_lock; /* protects */ | 298 | spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ |
307 | struct delayed_work orig_work; | 299 | struct delayed_work orig_work; |
308 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ | 300 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ |
309 | struct batadv_algo_ops *bat_algo_ops; | 301 | struct batadv_algo_ops *bat_algo_ops; |
@@ -369,6 +361,7 @@ struct batadv_backbone_gw { | |||
369 | struct hlist_node hash_entry; | 361 | struct hlist_node hash_entry; |
370 | struct batadv_priv *bat_priv; | 362 | struct batadv_priv *bat_priv; |
371 | unsigned long lasttime; /* last time we heard of this backbone gw */ | 363 | unsigned long lasttime; /* last time we heard of this backbone gw */ |
364 | atomic_t wait_periods; | ||
372 | atomic_t request_sent; | 365 | atomic_t request_sent; |
373 | atomic_t refcount; | 366 | atomic_t refcount; |
374 | struct rcu_head rcu; | 367 | struct rcu_head rcu; |