X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=net%2Fbatman-adv%2Ftranslation-table.c;h=d2d85a6cabccdc03484fce88625e74f122edf37e;hp=c7aafc7c5ed4854b2a46f6e37b5386ef937fee8e;hb=16e7b8c95fa6f8e57d9ab73597e31e3396f0c00d;hpb=3c00303206c3a1ccd86579efdc90bc35f140962e diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c7aafc7c5ed4..d2d85a6cabcc 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -245,9 +245,11 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, if (tt_global_entry) { /* This node is probably going to update its tt table */ tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as PENDING and has to be + /* The global entry has to be marked as ROAMING and has to be * kept for consistency purpose */ - tt_global_entry->flags |= TT_CLIENT_PENDING; + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + send_roam_adv(bat_priv, tt_global_entry->addr, tt_global_entry->orig_node); } @@ -694,6 +696,7 @@ void tt_global_del(struct bat_priv *bat_priv, const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; + struct tt_local_entry *tt_local_entry = NULL; tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) @@ -701,15 +704,29 @@ void tt_global_del(struct bat_priv *bat_priv, if (tt_global_entry->orig_node == orig_node) { if (roaming) { - tt_global_entry->flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; + /* if we are deleting a global entry due to a roam + * event, there are two possibilities: + * 1) the client roamed from node A to node B => we mark + * it with TT_CLIENT_ROAM, we start a timer and we + * wait for node B to claim it. In case of timeout + * the entry is purged. + * 2) the client roamed to us => we can directly delete + * the global entry, since it is useless now. */ + tt_local_entry = tt_local_hash_find(bat_priv, + tt_global_entry->addr); + if (!tt_local_entry) { + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + goto out; + } } _tt_global_del(bat_priv, tt_global_entry, message); } out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); } void tt_global_del_orig(struct bat_priv *bat_priv, @@ -935,6 +952,29 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv) return total; } +/** + * batadv_tt_req_node_release - free tt_req node entry + * @ref: kref pointer of the tt req_node entry + */ +static void batadv_tt_req_node_release(struct kref *ref) +{ + struct tt_req_node *tt_req_node; + + tt_req_node = container_of(ref, struct tt_req_node, refcount); + + kfree(tt_req_node); +} + +/** + * batadv_tt_req_node_put - decrement the tt_req_node refcounter and + * possibly release it + * @tt_req_node: tt_req_node to be free'd + */ +static void batadv_tt_req_node_put(struct tt_req_node *tt_req_node) +{ + kref_put(&tt_req_node->refcount, batadv_tt_req_node_release); +} + static void tt_req_list_free(struct bat_priv *bat_priv) { struct tt_req_node *node, *safe; @@ -943,7 +983,7 @@ static void tt_req_list_free(struct bat_priv *bat_priv) list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { list_del(&node->list); - kfree(node); + batadv_tt_req_node_put(node); } spin_unlock_bh(&bat_priv->tt_req_list_lock); @@ -978,7 +1018,7 @@ static void tt_req_purge(struct bat_priv *bat_priv) if (is_out_of_time(node->issued_at, TT_REQUEST_TIMEOUT * 1000)) { list_del(&node->list); - kfree(node); + batadv_tt_req_node_put(node); } } spin_unlock_bh(&bat_priv->tt_req_list_lock); @@ -1003,9 +1043,11 @@ static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv, if (!tt_req_node) goto unlock; + kref_init(&tt_req_node->refcount); memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); tt_req_node->issued_at = jiffies; + kref_get(&tt_req_node->refcount); list_add(&tt_req_node->list, &bat_priv->tt_req_list); unlock: spin_unlock_bh(&bat_priv->tt_req_list_lock); @@ -1157,12 +1199,19 @@ out: hardif_free_ref(primary_if); if (ret) kfree_skb(skb); + if (ret && tt_req_node) { spin_lock_bh(&bat_priv->tt_req_list_lock); - list_del(&tt_req_node->list); + if (!list_empty(&tt_req_node->list)) { + list_del(&tt_req_node->list); + batadv_tt_req_node_put(tt_req_node); + } spin_unlock_bh(&bat_priv->tt_req_list_lock); - kfree(tt_req_node); } + + if (tt_req_node) + batadv_tt_req_node_put(tt_req_node); + return ret; } @@ -1535,7 +1584,7 @@ void handle_tt_response(struct bat_priv *bat_priv, if (!compare_eth(node->addr, tt_response->src)) continue; list_del(&node->list); - kfree(node); + batadv_tt_req_node_put(node); } spin_unlock_bh(&bat_priv->tt_req_list_lock); @@ -1799,10 +1848,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) { struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; - bool ret = true; + bool ret = false; if (!atomic_read(&bat_priv->ap_isolation)) - return false; + goto out; tt_local_entry = tt_local_hash_find(bat_priv, dst); if (!tt_local_entry) @@ -1812,10 +1861,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) if (!tt_global_entry) goto out; - if (_is_ap_isolated(tt_local_entry, tt_global_entry)) + if (!_is_ap_isolated(tt_local_entry, tt_global_entry)) goto out; - ret = false; + ret = true; out: if (tt_global_entry)