aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-11-14 22:10:50 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-14 22:10:50 -0500
commit702ed3c1a9dfe4dfe112f13542d0c9d689f5008b (patch)
tree389a18e751299babb9cb8f6085b5e30631378c8b
parent1a39a65cba08f8a76f00fea9023d336e0858941b (diff)
parent170173bf37342dab486daaa2a0381d802c10fb21 (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.c59
-rw-r--r--net/batman-adv/hard-interface.c41
-rw-r--r--net/batman-adv/hash.h22
-rw-r--r--net/batman-adv/main.h1
-rw-r--r--net/batman-adv/originator.c1
-rw-r--r--net/batman-adv/routing.c173
-rw-r--r--net/batman-adv/soft-interface.c1
-rw-r--r--net/batman-adv/sysfs.c2
-rw-r--r--net/batman-adv/translation-table.c276
-rw-r--r--net/batman-adv/translation-table.h2
-rw-r--r--net/batman-adv/types.h11
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 */
41static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) 41static 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)
61static inline uint32_t batadv_choose_backbone_gw(const void *data, 57static 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 */
363static struct batadv_backbone_gw * 355static struct batadv_backbone_gw *
364batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, 356batadv_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 */
75static 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
62static int batadv_is_valid_iface(const struct net_device *net_dev) 101static 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 */
92static 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);
721out: 715out:
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 */
908static bool
909batadv_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;
941out:
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
902static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, 950static 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
241static 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
241void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 255void 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); 335add_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! */ 338check_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
322out: 364out:
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
329static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, 371static 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
520out: 580out:
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 }
877add_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
803out_remove: 886out_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
811out: 900out:
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
931static void
932batadv_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
1593batadv_send_other_tt_response(struct batadv_priv *bat_priv, 1670batadv_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
1728batadv_send_my_tt_response(struct batadv_priv *bat_priv, 1805batadv_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,
1894static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 1971static 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
1937bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) 2014bool 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;
1951out: 2029out:
@@ -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;
2003out: 2077out:
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 */
2525bool 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);
2537out:
2538 return ret;
2539
2540}
2541
2448bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 2542bool 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);
60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 60bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
61 uint8_t *addr); 61 uint8_t *addr);
62bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
63 uint8_t *addr);
62bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 64bool 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;