From 07568d0369f93cd54d2e5ca6f5c64f5b55557857 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 30 Aug 2012 18:22:27 +0200 Subject: [PATCH 01/11] batman-adv: don't rely on positions in struct for hashing The hash functions in the bridge loop avoidance code expects the VLAN vid to be right after the mac address, but this is not guaranteed. Fix this by explicitly hashing over the right fields of the struct. Reported-by: Marek Lindner Signed-off-by: Simon Wunderlich Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 20 ++++++-------------- net/batman-adv/hash.h | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 29a5542aac75..49c35a60195a 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, /* return the index of the claim */ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) { - const unsigned char *key = data; + struct batadv_claim *claim = (struct batadv_claim *)data; uint32_t hash = 0; - size_t i; - for (i = 0; i < ETH_ALEN + sizeof(short); i++) { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } + hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); + hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); hash += (hash << 3); hash ^= (hash >> 11); @@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size) static inline uint32_t batadv_choose_backbone_gw(const void *data, uint32_t size) { - const unsigned char *key = data; + struct batadv_claim *claim = (struct batadv_claim *)data; uint32_t hash = 0; - size_t i; - for (i = 0; i < ETH_ALEN + sizeof(short); i++) { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } + hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr)); + hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid)); hash += (hash << 3); hash ^= (hash >> 11); 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 @@ -81,6 +81,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash, batadv_hash_destroy(hash); } +/** + * batadv_hash_bytes - hash some bytes and add them to the previous hash + * @hash: previous hash value + * @data: data to be hashed + * @size: number of bytes to be hashed + * + * Returns the new hash value. + */ +static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data, + uint32_t size) +{ + const unsigned char *key = data; + int i; + + for (i = 0; i < size; i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + return hash; +} + /** * batadv_hash_add - adds data to the hashtable * @hash: storage hash table From a7528f8ddda9fba061148e18e71761b50b1c6d26 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 2 Sep 2012 19:00:38 +0200 Subject: [PATCH 02/11] batman-adv: fix wrong spinlock inline comment Signed-off-by: Antonio Quartulli --- net/batman-adv/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 8ce16c1cbafb..e8a1b18ae546 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -303,7 +303,7 @@ struct batadv_priv { struct hlist_head forw_bcast_list; struct batadv_hashtable *orig_hash; spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ - spinlock_t forw_bcast_list_lock; /* protects */ + spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ struct delayed_work orig_work; struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ struct batadv_algo_ops *bat_algo_ops; From b7eddd0b3950ea9dc863f1cbfa30d172dbf772f4 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 9 Sep 2012 10:46:46 +0200 Subject: [PATCH 03/11] batman-adv: prevent using any virtual device created on batman-adv as hard-interface Any virtual device created on top of a batman-adv mesh interface must be prevented to be used to create a new mesh network (this would lead to an unwanted batman-over-batman configuration) Signed-off-by: Antonio Quartulli --- net/batman-adv/hard-interface.c | 41 ++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) 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: return hard_iface; } +/** + * batadv_is_on_batman_iface - check if a device is a batman iface descendant + * @net_dev: the device to check + * + * If the user creates any virtual device on top of a batman-adv interface, it + * is important to prevent this new interface to be used to create a new mesh + * network (this behaviour would lead to a batman-over-batman configuration). + * This function recursively checks all the fathers of the device passed as + * argument looking for a batman-adv soft interface. + * + * Returns true if the device is descendant of a batman-adv mesh interface (or + * if it is a batman-adv interface itself), false otherwise + */ +static bool batadv_is_on_batman_iface(const struct net_device *net_dev) +{ + struct net_device *parent_dev; + bool ret; + + /* check if this is a batman-adv mesh interface */ + if (batadv_softif_is_valid(net_dev)) + return true; + + /* no more parents..stop recursion */ + if (net_dev->iflink == net_dev->ifindex) + return false; + + /* recurse over the parent device */ + parent_dev = dev_get_by_index(&init_net, net_dev->iflink); + /* if we got a NULL parent_dev there is something broken.. */ + if (WARN(!parent_dev, "Cannot find parent device")) + return false; + + ret = batadv_is_on_batman_iface(parent_dev); + + if (parent_dev) + dev_put(parent_dev); + return ret; +} + static int batadv_is_valid_iface(const struct net_device *net_dev) { if (net_dev->flags & IFF_LOOPBACK) @@ -71,7 +110,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev) return 0; /* no batman over batman */ - if (batadv_softif_is_valid(net_dev)) + if (batadv_is_on_batman_iface(net_dev)) return 0; return 1; From 52aebd6a9fe4ad0245a00ef4457425ad83661c90 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sat, 8 Sep 2012 18:02:53 +0200 Subject: [PATCH 04/11] batman-adv: send announcement when backbone gw is registered To avoid loops in the startup phase until the first announcement is sent, send an announcement immediately as soon as a backbone gw is added. This may happen due to various reasons, e.g. a packet passes the rx or tx path. Signed-off-by: Simon Wunderlich Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 49c35a60195a..c49cf24ab33d 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -354,7 +354,7 @@ out: */ static struct batadv_backbone_gw * batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, - short vid) + short vid, bool own_backbone) { struct batadv_backbone_gw *entry; struct batadv_orig_node *orig_node; @@ -401,6 +401,10 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, "became a backbone gateway"); batadv_orig_node_free_ref(orig_node); } + + if (own_backbone) + batadv_bla_send_announce(bat_priv, entry); + return entry; } @@ -416,7 +420,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv, backbone_gw = batadv_bla_get_backbone_gw(bat_priv, primary_if->net_dev->dev_addr, - vid); + vid, true); if (unlikely(!backbone_gw)) return; @@ -624,7 +628,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, if (memcmp(an_addr, batadv_announce_mac, 4) != 0) return 0; - backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); + backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, + false); if (unlikely(!backbone_gw)) return 1; @@ -722,7 +727,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, /* register the gateway if not yet available, and add the claim. */ - backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid); + backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid, + false); if (unlikely(!backbone_gw)) return 1; From d807f2728708c54a1ac1ce04d4549d8eb2b996d2 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sun, 9 Sep 2012 22:27:57 +0200 Subject: [PATCH 05/11] batman-adv: allow bla traffic only after first worker period When adding a backbone gateway for the first time, it might not yet be known in the backbone, and therefore we should not forward broadcasts yet. This behaviour is the same as when sending a request to another backbone gw because of a CRC mismatch. The backbone gw will operate normal after the next periodic bla work. Signed-off-by: Simon Wunderlich Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index c49cf24ab33d..8cd97d59ee61 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -402,9 +402,14 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, batadv_orig_node_free_ref(orig_node); } - if (own_backbone) + if (own_backbone) { batadv_bla_send_announce(bat_priv, entry); + /* this will be decreased in the worker thread */ + atomic_inc(&entry->request_sent); + atomic_inc(&bat_priv->bla.num_requests); + } + return entry; } @@ -1138,6 +1143,19 @@ static void batadv_bla_periodic_work(struct work_struct *work) backbone_gw->lasttime = jiffies; batadv_bla_send_announce(bat_priv, backbone_gw); + + /* request_sent is only set after creation to avoid + * problems when we are not yet known as backbone gw + * in the backbone. + * + * We can reset this now and allow traffic again. + */ + + if (atomic_read(&backbone_gw->request_sent) == 0) + continue; + + atomic_dec(&backbone_gw->bat_priv->bla.num_requests); + atomic_set(&backbone_gw->request_sent, 0); } rcu_read_unlock(); } From 28709878b6a7d15362ba63bde01d42c38f88be9d Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 13 Sep 2012 18:18:46 +0200 Subject: [PATCH 06/11] batman-adv: wait multiple periods before activating bla For some reasons (bridge forward delay, network device setup order, etc) the initial bridge loop avoidance announcement packets may be lost. This may lead to problems in finding other backbone gws, and therfore create loops in the startup time. Fix this by extending the waiting periods to 3 (define can be changed) before allowing broadcast traffic. Signed-off-by: Simon Wunderlich Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 9 ++++++++- net/batman-adv/main.h | 1 + net/batman-adv/types.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 8cd97d59ee61..bda8b1710806 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -378,6 +378,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, entry->crc = BATADV_BLA_CRC_INIT; entry->bat_priv = bat_priv; atomic_set(&entry->request_sent, 0); + atomic_set(&entry->wait_periods, 0); memcpy(entry->orig, orig, ETH_ALEN); /* one for the hash, one for returning */ @@ -407,6 +408,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, /* this will be decreased in the worker thread */ atomic_inc(&entry->request_sent); + atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS); atomic_inc(&bat_priv->bla.num_requests); } @@ -1148,12 +1150,17 @@ static void batadv_bla_periodic_work(struct work_struct *work) * problems when we are not yet known as backbone gw * in the backbone. * - * We can reset this now and allow traffic again. + * We can reset this now after we waited some periods + * to give bridge forward delays and bla group forming + * some grace time. */ if (atomic_read(&backbone_gw->request_sent) == 0) continue; + if (!atomic_dec_and_test(&backbone_gw->wait_periods)) + continue; + atomic_dec(&backbone_gw->bat_priv->bla.num_requests); atomic_set(&backbone_gw->request_sent, 0); } 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 @@ #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) +#define BATADV_BLA_WAIT_PERIODS 3 #define BATADV_DUPLIST_SIZE 16 #define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index e8a1b18ae546..fa09961652a1 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -369,6 +369,7 @@ struct batadv_backbone_gw { struct hlist_node hash_entry; struct batadv_priv *bat_priv; unsigned long lasttime; /* last time we heard of this backbone gw */ + atomic_t wait_periods; atomic_t request_sent; atomic_t refcount; struct rcu_head rcu; From 7c1fd91da5a5eecc91674991199940c05f87cb3a Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 23 Sep 2012 22:38:34 +0200 Subject: [PATCH 07/11] batman-adv: substitute tt_poss_change with a per-tt_entry flag tt_poss_change is a node-wide flag which tells whether the node is in a roaming state (a client recently moved to/away from it) in order to let it apply special re-routing rules. However this flag does not give a clear idea of the current state because it is not possible to understand *which client* is actually involved in the roaming. For this reason a better approach has been chosen: instead of using a node-wide variable, the roaming state is now given by a per-tt_entry ROAM flag which, in case of packet coming through the node, tells the node whether the real destination is in roaming state or not. With this flag change, batadv_check_unicast_ttvn() has also been rearranged in order to better fit the new re-routing logic and to be much more readable. Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 1 - net/batman-adv/routing.c | 177 ++++++++++++++++++++--------- net/batman-adv/soft-interface.c | 1 - net/batman-adv/translation-table.c | 46 +++++--- net/batman-adv/translation-table.h | 2 + net/batman-adv/types.h | 8 -- 6 files changed, 158 insertions(+), 77 deletions(-) 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, atomic_set(&orig_node->refcount, 2); orig_node->tt_initialised = false; - orig_node->tt_poss_change = false; orig_node->bat_priv = bat_priv; memcpy(orig_node->orig, addr, ETH_ALEN); 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) BATADV_TT_CLIENT_ROAM, atomic_read(&orig_node->last_ttvn) + 1); - /* Roaming phase starts: I have new information but the ttvn has not - * been incremented yet. This flag will make me check all the incoming - * packets for the correct destination. - */ - bat_priv->tt.poss_change = true; - batadv_orig_node_free_ref(orig_node); out: /* returning NET_RX_DROP will make the caller function kfree the skb */ @@ -899,14 +893,67 @@ out: return ret; } +/** + * batadv_reroute_unicast_packet - update the unicast header for re-routing + * @bat_priv: the bat priv with all the soft interface information + * @unicast_packet: the unicast header to be updated + * @dst_addr: the payload destination + * + * Search the translation table for dst_addr and update the unicast header with + * the new corresponding information (originator address where the destination + * client currently is and its known TTVN) + * + * Returns true if the packet header has been updated, false otherwise + */ +static bool +batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, + struct batadv_unicast_packet *unicast_packet, + uint8_t *dst_addr) +{ + struct batadv_orig_node *orig_node = NULL; + struct batadv_hard_iface *primary_if = NULL; + bool ret = false; + uint8_t *orig_addr, orig_ttvn; + + if (batadv_is_my_client(bat_priv, dst_addr)) { + primary_if = batadv_primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + orig_addr = primary_if->net_dev->dev_addr; + orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); + } else { + orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr); + if (!orig_node) + goto out; + + if (batadv_compare_eth(orig_node->orig, unicast_packet->dest)) + goto out; + + orig_addr = orig_node->orig; + orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); + } + + /* update the packet header */ + memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); + unicast_packet->ttvn = orig_ttvn; + + ret = true; +out: + if (primary_if) + batadv_hardif_free_ref(primary_if); + if (orig_node) + batadv_orig_node_free_ref(orig_node); + + return ret; +} + static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, struct sk_buff *skb) { - uint8_t curr_ttvn; + uint8_t curr_ttvn, old_ttvn; struct batadv_orig_node *orig_node; struct ethhdr *ethhdr; struct batadv_hard_iface *primary_if; struct batadv_unicast_packet *unicast_packet; - bool tt_poss_change; int is_old_ttvn; /* check if there is enough data before accessing it */ @@ -918,65 +965,89 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, return 0; unicast_packet = (struct batadv_unicast_packet *)skb->data; + ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); - if (batadv_is_my_mac(unicast_packet->dest)) { - tt_poss_change = bat_priv->tt.poss_change; - curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); - } else { + /* check if the destination client was served by this node and it is now + * roaming. In this case, it means that the node has got a ROAM_ADV + * message and that it knows the new destination in the mesh to re-route + * the packet to + */ + if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) { + if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, + ethhdr->h_dest)) + net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, + bat_priv, + "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", + unicast_packet->dest, + ethhdr->h_dest); + /* at this point the mesh destination should have been + * substituted with the originator address found in the global + * table. If not, let the packet go untouched anyway because + * there is nothing the node can do + */ + return 1; + } + + /* retrieve the TTVN known by this node for the packet destination. This + * value is used later to check if the node which sent (or re-routed + * last time) the packet had an updated information or not + */ + curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); + if (!batadv_is_my_mac(unicast_packet->dest)) { orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest); - + /* if it is not possible to find the orig_node representing the + * destination, the packet can immediately be dropped as it will + * not be possible to deliver it + */ if (!orig_node) return 0; curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); - tt_poss_change = orig_node->tt_poss_change; batadv_orig_node_free_ref(orig_node); } - /* Check whether I have to reroute the packet */ + /* check if the TTVN contained in the packet is fresher than what the + * node knows + */ is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); - if (is_old_ttvn || tt_poss_change) { - /* check if there is enough data before accessing it */ - if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) + - ETH_HLEN) < 0) - return 0; - - ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); - - /* we don't have an updated route for this client, so we should - * not try to reroute the packet!! - */ - if (batadv_tt_global_client_is_roaming(bat_priv, - ethhdr->h_dest)) - return 1; - - orig_node = batadv_transtable_search(bat_priv, NULL, - ethhdr->h_dest); - - if (!orig_node) { - if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) - return 0; - primary_if = batadv_primary_if_get_selected(bat_priv); - if (!primary_if) - return 0; - memcpy(unicast_packet->dest, - primary_if->net_dev->dev_addr, ETH_ALEN); - batadv_hardif_free_ref(primary_if); - } else { - memcpy(unicast_packet->dest, orig_node->orig, - ETH_ALEN); - curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); - batadv_orig_node_free_ref(orig_node); - } + if (!is_old_ttvn) + return 1; + old_ttvn = unicast_packet->ttvn; + /* the packet was forged based on outdated network information. Its + * destination can possibly be updated and forwarded towards the new + * target host + */ + if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, + ethhdr->h_dest)) { net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, - "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", - unicast_packet->ttvn, curr_ttvn, - ethhdr->h_dest, unicast_packet->dest); - - unicast_packet->ttvn = curr_ttvn; + "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", + unicast_packet->dest, ethhdr->h_dest, + old_ttvn, curr_ttvn); + return 1; } + + /* the packet has not been re-routed: either the destination is + * currently served by this node or there is no destination at all and + * it is possible to drop the packet + */ + if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) + return 0; + + /* update the header in order to let the packet be delivered to this + * node's soft interface + */ + primary_if = batadv_primary_if_get_selected(bat_priv); + if (!primary_if) + return 0; + + memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); + + batadv_hardif_free_ref(primary_if); + + unicast_packet->ttvn = curr_ttvn; + return 1; } 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) #endif bat_priv->tt.last_changeset = NULL; bat_priv->tt.last_changeset_len = 0; - bat_priv->tt.poss_change = false; bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f8b9c32c29a5..d7418511448d 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -306,8 +306,6 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, head = &tt_global_entry->orig_list; rcu_read_lock(); hlist_for_each_entry_rcu(orig_entry, node, head, list) { - orig_entry->orig_node->tt_poss_change = true; - batadv_send_roam_adv(bat_priv, tt_global_entry->common.addr, orig_entry->orig_node); @@ -512,8 +510,11 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, curr_flags = tt_local_entry->common.flags; flags = BATADV_TT_CLIENT_DEL; - if (roaming) + if (roaming) { flags |= BATADV_TT_CLIENT_ROAM; + /* mark the local client as ROAMed */ + tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; + } batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); @@ -1945,7 +1946,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) /* Check if the client has been logically deleted (but is kept for * consistency purpose) */ - if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) + if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) || + (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM)) goto out; ret = true; out: @@ -1996,10 +1998,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv, /* Recalculate the CRC for this orig_node and store it */ orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); - /* Roaming phase is over: tables are in sync again. I can - * unset the flag - */ - orig_node->tt_poss_change = false; out: if (orig_node) batadv_orig_node_free_ref(orig_node); @@ -2290,7 +2288,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n", (uint8_t)atomic_read(&bat_priv->tt.vn)); - bat_priv->tt.poss_change = false; /* reset the sending counter */ atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); @@ -2402,11 +2399,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv, */ if (orig_node->tt_crc != tt_crc) goto request_table; - - /* Roaming phase is over: tables are in sync again. I can - * unset the flag - */ - orig_node->tt_poss_change = false; } else { /* if we missed more than one change or our tables are not * in sync anymore -> request fresh tt data @@ -2445,6 +2437,32 @@ out: return ret; } +/** + * batadv_tt_local_client_is_roaming - tells whether the client is roaming + * @bat_priv: the bat priv with all the soft interface information + * @addr: the MAC address of the local client to query + * + * Returns true if the local client is known to be roaming (it is not served by + * this node anymore) or not. If yes, the client is still present in the table + * to keep the latter consistent with the node TTVN + */ +bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, + uint8_t *addr) +{ + struct batadv_tt_local_entry *tt_local_entry; + bool ret = false; + + tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); + if (!tt_local_entry) + goto out; + + ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM; + batadv_tt_local_entry_free_ref(tt_local_entry); +out: + return ret; + +} + bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, 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, int packet_min_len); bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, uint8_t *addr); +bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, + uint8_t *addr); bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, const unsigned char *addr); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index fa09961652a1..7b3d0d7ef06a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -101,13 +101,6 @@ struct batadv_orig_node { spinlock_t tt_buff_lock; /* protects tt_buff */ atomic_t tt_size; bool tt_initialised; - /* The tt_poss_change flag is used to detect an ongoing roaming phase. - * If true, then I sent a Roaming_adv to this orig_node and I have to - * inspect every packet directed to it to check whether it is still - * the true destination or not. This flag will be reset to false as - * soon as I receive a new TTVN from this orig_node - */ - bool tt_poss_change; uint32_t last_real_seqno; uint8_t last_ttl; DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); @@ -212,7 +205,6 @@ struct batadv_priv_tt { atomic_t vn; atomic_t ogm_append_cnt; atomic_t local_changes; - bool poss_change; struct list_head changes_list; struct batadv_hashtable *local_hash; struct batadv_hashtable *global_hash; From 47c94655c3d8086d92825760e1f1d9b12a5976e4 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 23 Sep 2012 22:38:35 +0200 Subject: [PATCH 08/11] batman-adv: refactor code to simplify long lines Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 62 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index d7418511448d..c24e60425289 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -242,86 +242,84 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, int ifindex) { struct batadv_priv *bat_priv = netdev_priv(soft_iface); - struct batadv_tt_local_entry *tt_local_entry = NULL; - struct batadv_tt_global_entry *tt_global_entry = NULL; + struct batadv_tt_local_entry *tt_local = NULL; + struct batadv_tt_global_entry *tt_global = NULL; struct hlist_head *head; struct hlist_node *node; struct batadv_tt_orig_list_entry *orig_entry; int hash_added; - tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); + tt_local = batadv_tt_local_hash_find(bat_priv, addr); - if (tt_local_entry) { - tt_local_entry->last_seen = jiffies; + if (tt_local) { + tt_local->last_seen = jiffies; /* possibly unset the BATADV_TT_CLIENT_PENDING flag */ - tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING; + tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; goto out; } - tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC); - if (!tt_local_entry) + tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); + if (!tt_local) goto out; batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, (uint8_t)atomic_read(&bat_priv->tt.vn)); - memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); - tt_local_entry->common.flags = BATADV_NO_FLAGS; + memcpy(tt_local->common.addr, addr, ETH_ALEN); + tt_local->common.flags = BATADV_NO_FLAGS; if (batadv_is_wifi_iface(ifindex)) - tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; - atomic_set(&tt_local_entry->common.refcount, 2); - tt_local_entry->last_seen = jiffies; - tt_local_entry->common.added_at = tt_local_entry->last_seen; + tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; + atomic_set(&tt_local->common.refcount, 2); + tt_local->last_seen = jiffies; + tt_local->common.added_at = tt_local->last_seen; /* the batman interface mac address should never be purged */ if (batadv_compare_eth(addr, soft_iface->dev_addr)) - tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE; + tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; /* The local entry has to be marked as NEW to avoid to send it in * a full table response going out before the next ttvn increment * (consistency check) */ - tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; + tt_local->common.flags |= BATADV_TT_CLIENT_NEW; hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, - batadv_choose_orig, - &tt_local_entry->common, - &tt_local_entry->common.hash_entry); + batadv_choose_orig, &tt_local->common, + &tt_local->common.hash_entry); if (unlikely(hash_added != 0)) { /* remove the reference for the hash */ - batadv_tt_local_entry_free_ref(tt_local_entry); + batadv_tt_local_entry_free_ref(tt_local); goto out; } - batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags); + batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); /* remove address from global hash if present */ - tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); + tt_global = batadv_tt_global_hash_find(bat_priv, addr); /* Check whether it is a roaming! */ - if (tt_global_entry) { + if (tt_global) { /* These node are probably going to update their tt table */ - head = &tt_global_entry->orig_list; + head = &tt_global->orig_list; rcu_read_lock(); hlist_for_each_entry_rcu(orig_entry, node, head, list) { - batadv_send_roam_adv(bat_priv, - tt_global_entry->common.addr, + batadv_send_roam_adv(bat_priv, tt_global->common.addr, orig_entry->orig_node); } rcu_read_unlock(); /* The global entry has to be marked as ROAMING and * has to be kept for consistency purpose */ - tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; + tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; + tt_global->roam_at = jiffies; } out: - if (tt_local_entry) - batadv_tt_local_entry_free_ref(tt_local_entry); - if (tt_global_entry) - batadv_tt_global_entry_free_ref(tt_global_entry); + if (tt_local) + batadv_tt_local_entry_free_ref(tt_local); + if (tt_global) + batadv_tt_global_entry_free_ref(tt_global); } static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, From be73b488d1e2993fe92b5ec02347c3f7c08307b8 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 23 Sep 2012 22:38:36 +0200 Subject: [PATCH 09/11] batman-adv: refactor tt_global_del_struct() batadv_tt_global_del_struct() function is not properly named. Having a more meaningful name which reflects the current behavior helps other developers to easily understand what it does. A parameter has also been renamed in order to let the function header better fit the 80-chars line-width Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c24e60425289..cb8433aceed8 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -927,18 +927,17 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, spin_unlock_bh(&tt_global_entry->list_lock); } -static void -batadv_tt_global_del_struct(struct batadv_priv *bat_priv, - struct batadv_tt_global_entry *tt_global_entry, - const char *message) +static void batadv_tt_global_free(struct batadv_priv *bat_priv, + struct batadv_tt_global_entry *tt_global, + const char *message) { batadv_dbg(BATADV_DBG_TT, bat_priv, "Deleting global tt entry %pM: %s\n", - tt_global_entry->common.addr, message); + tt_global->common.addr, message); batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, - batadv_choose_orig, tt_global_entry->common.addr); - batadv_tt_global_entry_free_ref(tt_global_entry); + batadv_choose_orig, tt_global->common.addr); + batadv_tt_global_entry_free_ref(tt_global); } @@ -1002,8 +1001,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, orig_node, message); if (hlist_empty(&tt_global_entry->orig_list)) - batadv_tt_global_del_struct(bat_priv, tt_global_entry, - message); + batadv_tt_global_free(bat_priv, tt_global_entry, + message); goto out; } @@ -1026,7 +1025,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, if (local_entry) { /* local entry exists, case 2: client roamed to us. */ batadv_tt_global_del_orig_list(tt_global_entry); - batadv_tt_global_del_struct(bat_priv, tt_global_entry, message); + batadv_tt_global_free(bat_priv, tt_global_entry, message); } else /* no local entry exists, case 1: check for roaming */ batadv_tt_global_del_roaming(bat_priv, tt_global_entry, From 068ee6e204e1f48ba24ec91ce40f5ca833a57a81 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 23 Sep 2012 22:38:37 +0200 Subject: [PATCH 10/11] batman-adv: roaming handling mechanism redesign This patch allows clients to roam multiple times within the same originator-interval. To enable this new feature two key aspects that have been introduced: 1) packets are always directed to the node that was originally serving the roamed client which will then re-route the data to the correct destination at any point in time; 2) the client flags handling mechanism has been properly modified in order to allow multiple roamings withinin the same orig-int. Therefore flags are now set properly even in this scenario. Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 157 ++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 39 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index cb8433aceed8..dd2c2545cfef 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -238,6 +238,20 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv) return 0; } +static void batadv_tt_global_free(struct batadv_priv *bat_priv, + struct batadv_tt_global_entry *tt_global, + const char *message) +{ + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Deleting global tt entry %pM: %s\n", + tt_global->common.addr, message); + + batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, + batadv_choose_orig, tt_global->common.addr); + batadv_tt_global_entry_free_ref(tt_global); + +} + void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, int ifindex) { @@ -248,14 +262,38 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, struct hlist_node *node; struct batadv_tt_orig_list_entry *orig_entry; int hash_added; + bool roamed_back = false; tt_local = batadv_tt_local_hash_find(bat_priv, addr); + tt_global = batadv_tt_global_hash_find(bat_priv, addr); if (tt_local) { tt_local->last_seen = jiffies; - /* possibly unset the BATADV_TT_CLIENT_PENDING flag */ - tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; - goto out; + if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) { + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Re-adding pending client %pM\n", addr); + /* whatever the reason why the PENDING flag was set, + * this is a client which was enqueued to be removed in + * this orig_interval. Since it popped up again, the + * flag can be reset like it was never enqueued + */ + tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; + goto add_event; + } + + if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) { + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Roaming client %pM came back to its original location\n", + addr); + /* the ROAM flag is set because this client roamed away + * and the node got a roaming_advertisement message. Now + * that the client popped up again at its original + * location such flag can be unset + */ + tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM; + roamed_back = true; + } + goto check_roaming; } tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); @@ -294,13 +332,14 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, goto out; } +add_event: batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); - /* remove address from global hash if present */ - tt_global = batadv_tt_global_hash_find(bat_priv, addr); - - /* Check whether it is a roaming! */ - if (tt_global) { +check_roaming: + /* Check whether it is a roaming, but don't do anything if the roaming + * process has already been handled + */ + if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) { /* These node are probably going to update their tt table */ head = &tt_global->orig_list; rcu_read_lock(); @@ -309,12 +348,19 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, orig_entry->orig_node); } rcu_read_unlock(); - /* The global entry has to be marked as ROAMING and - * has to be kept for consistency purpose - */ - tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; - tt_global->roam_at = jiffies; + if (roamed_back) { + batadv_tt_global_free(bat_priv, tt_global, + "Roaming canceled"); + tt_global = NULL; + } else { + /* The global entry has to be marked as ROAMING and + * has to be kept for consistency purpose + */ + tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; + tt_global->roam_at = jiffies; + } } + out: if (tt_local) batadv_tt_local_entry_free_ref(tt_local); @@ -508,13 +554,28 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, curr_flags = tt_local_entry->common.flags; flags = BATADV_TT_CLIENT_DEL; + /* if this global entry addition is due to a roaming, the node has to + * mark the local entry as "roamed" in order to correctly reroute + * packets later + */ if (roaming) { flags |= BATADV_TT_CLIENT_ROAM; /* mark the local client as ROAMed */ tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; } - batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); + if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) { + batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, + message); + goto out; + } + /* if this client has been added right now, it is possible to + * immediately purge it + */ + batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, + curr_flags | BATADV_TT_CLIENT_DEL); + hlist_del_rcu(&tt_local_entry->common.hash_entry); + batadv_tt_local_entry_free_ref(tt_local_entry); out: if (tt_local_entry) @@ -724,12 +785,22 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, uint8_t ttvn) { struct batadv_tt_global_entry *tt_global_entry = NULL; + struct batadv_tt_local_entry *tt_local_entry = NULL; int ret = 0; int hash_added; struct batadv_tt_common_entry *common; uint16_t local_flags; tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); + tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr); + + /* if the node already has a local client for this entry, it has to wait + * for a roaming advertisement instead of manually messing up the global + * table + */ + if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry && + !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) + goto out; if (!tt_global_entry) { tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); @@ -764,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, goto out_remove; } } else { + common = &tt_global_entry->common; /* If there is already a global entry, we can use this one for * our processing. - * But if we are trying to add a temporary client we can exit - * directly because the temporary information should never - * override any already known client state (whatever it is) + * But if we are trying to add a temporary client then here are + * two options at this point: + * 1) the global client is not a temporary client: the global + * client has to be left as it is, temporary information + * should never override any already known client state + * 2) the global client is a temporary client: purge the + * originator list and add the new one orig_entry */ - if (flags & BATADV_TT_CLIENT_TEMP) - goto out; + if (flags & BATADV_TT_CLIENT_TEMP) { + if (!(common->flags & BATADV_TT_CLIENT_TEMP)) + goto out; + if (batadv_tt_global_entry_has_orig(tt_global_entry, + orig_node)) + goto out_remove; + batadv_tt_global_del_orig_list(tt_global_entry); + goto add_orig_entry; + } /* if the client was temporary added before receiving the first * OGM announcing it, we have to clear the TEMP flag */ - tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; + common->flags &= ~BATADV_TT_CLIENT_TEMP; /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only * one originator left in the list and we previously received a @@ -785,18 +868,19 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, * We should first delete the old originator before adding the * new one. */ - if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) { + if (common->flags & BATADV_TT_CLIENT_ROAM) { batadv_tt_global_del_orig_list(tt_global_entry); - tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; + common->flags &= ~BATADV_TT_CLIENT_ROAM; tt_global_entry->roam_at = 0; } } +add_orig_entry: /* add the new orig_entry (if needed) or update it */ batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new global tt entry: %pM (via %pM)\n", - tt_global_entry->common.addr, orig_node->orig); + common->addr, orig_node->orig); ret = 1; out_remove: @@ -804,12 +888,20 @@ out_remove: /* remove address from local hash if present */ local_flags = batadv_tt_local_remove(bat_priv, tt_addr, "global tt received", - flags & BATADV_TT_CLIENT_ROAM); + !!(flags & BATADV_TT_CLIENT_ROAM)); tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; + if (!(flags & BATADV_TT_CLIENT_ROAM)) + /* this is a normal global add. Therefore the client is not in a + * roaming state anymore. + */ + tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; + out: if (tt_global_entry) batadv_tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + batadv_tt_local_entry_free_ref(tt_local_entry); return ret; } @@ -927,20 +1019,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, spin_unlock_bh(&tt_global_entry->list_lock); } -static void batadv_tt_global_free(struct batadv_priv *bat_priv, - struct batadv_tt_global_entry *tt_global, - const char *message) -{ - batadv_dbg(BATADV_DBG_TT, bat_priv, - "Deleting global tt entry %pM: %s\n", - tt_global->common.addr, message); - - batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, - batadv_choose_orig, tt_global->common.addr); - batadv_tt_global_entry_free_ref(tt_global); - -} - /* If the client is to be deleted, we check if it is the last origantor entry * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the * timer, otherwise we simply remove the originator scheduled for deletion. @@ -1204,7 +1282,8 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, if (src && atomic_read(&bat_priv->ap_isolation)) { tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); - if (!tt_local_entry) + if (!tt_local_entry || + (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)) goto out; } From 170173bf37342dab486daaa2a0381d802c10fb21 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 7 Oct 2012 12:02:22 +0200 Subject: [PATCH 11/11] batman-adv: Remove instant overwritten variable initialization Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/sysfs.c | 2 +- net/batman-adv/translation-table.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) 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, enum batadv_uev_action action, const char *data) { int ret = -ENOMEM; - struct batadv_hard_iface *primary_if = NULL; + struct batadv_hard_iface *primary_if; struct kobject *bat_kobj; char *uevent_env[4] = { NULL, NULL, NULL, NULL }; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index dd2c2545cfef..9f5705fcf426 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -256,8 +256,8 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, int ifindex) { struct batadv_priv *bat_priv = netdev_priv(soft_iface); - struct batadv_tt_local_entry *tt_local = NULL; - struct batadv_tt_global_entry *tt_global = NULL; + struct batadv_tt_local_entry *tt_local; + struct batadv_tt_global_entry *tt_global; struct hlist_head *head; struct hlist_node *node; struct batadv_tt_orig_list_entry *orig_entry; @@ -544,7 +544,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr, const char *message, bool roaming) { - struct batadv_tt_local_entry *tt_local_entry = NULL; + struct batadv_tt_local_entry *tt_local_entry; uint16_t flags, curr_flags = BATADV_NO_FLAGS; tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); @@ -784,8 +784,8 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, const unsigned char *tt_addr, uint8_t flags, uint8_t ttvn) { - struct batadv_tt_global_entry *tt_global_entry = NULL; - struct batadv_tt_local_entry *tt_local_entry = NULL; + struct batadv_tt_global_entry *tt_global_entry; + struct batadv_tt_local_entry *tt_local_entry; int ret = 0; int hash_added; struct batadv_tt_common_entry *common; @@ -1067,7 +1067,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, const unsigned char *addr, const char *message, bool roaming) { - struct batadv_tt_global_entry *tt_global_entry = NULL; + struct batadv_tt_global_entry *tt_global_entry; struct batadv_tt_local_entry *local_entry = NULL; tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); @@ -1670,7 +1670,7 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv, struct batadv_tt_query_packet *tt_request) { - struct batadv_orig_node *req_dst_orig_node = NULL; + struct batadv_orig_node *req_dst_orig_node; struct batadv_orig_node *res_dst_orig_node = NULL; struct batadv_neigh_node *neigh_node = NULL; struct batadv_hard_iface *primary_if = NULL; @@ -1805,7 +1805,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv, struct batadv_tt_query_packet *tt_request) { - struct batadv_orig_node *orig_node = NULL; + struct batadv_orig_node *orig_node; struct batadv_neigh_node *neigh_node = NULL; struct batadv_hard_iface *primary_if = NULL; uint8_t my_ttvn, req_ttvn, ttvn; @@ -1971,7 +1971,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, struct batadv_tt_query_packet *tt_response) { - struct batadv_orig_node *orig_node = NULL; + struct batadv_orig_node *orig_node; orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); if (!orig_node) @@ -2013,7 +2013,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv, bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) { - struct batadv_tt_local_entry *tt_local_entry = NULL; + struct batadv_tt_local_entry *tt_local_entry; bool ret = false; tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);