diff options
Diffstat (limited to 'net/batman-adv/translation-table.c')
| -rw-r--r-- | net/batman-adv/translation-table.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index feaf492b01ca..7e6df7a4964a 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
| @@ -47,10 +47,12 @@ | |||
| 47 | #include "bridge_loop_avoidance.h" | 47 | #include "bridge_loop_avoidance.h" |
| 48 | #include "hard-interface.h" | 48 | #include "hard-interface.h" |
| 49 | #include "hash.h" | 49 | #include "hash.h" |
| 50 | #include "log.h" | ||
| 50 | #include "multicast.h" | 51 | #include "multicast.h" |
| 51 | #include "originator.h" | 52 | #include "originator.h" |
| 52 | #include "packet.h" | 53 | #include "packet.h" |
| 53 | #include "soft-interface.h" | 54 | #include "soft-interface.h" |
| 55 | #include "tvlv.h" | ||
| 54 | 56 | ||
| 55 | /* hash class keys */ | 57 | /* hash class keys */ |
| 56 | static struct lock_class_key batadv_tt_local_hash_lock_class_key; | 58 | static struct lock_class_key batadv_tt_local_hash_lock_class_key; |
| @@ -650,8 +652,10 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, | |||
| 650 | 652 | ||
| 651 | /* increase the refcounter of the related vlan */ | 653 | /* increase the refcounter of the related vlan */ |
| 652 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 654 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
| 653 | if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d", | 655 | if (!vlan) { |
| 654 | addr, BATADV_PRINT_VID(vid))) { | 656 | net_ratelimited_function(batadv_info, soft_iface, |
| 657 | "adding TT local entry %pM to non-existent VLAN %d\n", | ||
| 658 | addr, BATADV_PRINT_VID(vid)); | ||
| 655 | kfree(tt_local); | 659 | kfree(tt_local); |
| 656 | tt_local = NULL; | 660 | tt_local = NULL; |
| 657 | goto out; | 661 | goto out; |
| @@ -691,7 +695,6 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, | |||
| 691 | if (unlikely(hash_added != 0)) { | 695 | if (unlikely(hash_added != 0)) { |
| 692 | /* remove the reference for the hash */ | 696 | /* remove the reference for the hash */ |
| 693 | batadv_tt_local_entry_put(tt_local); | 697 | batadv_tt_local_entry_put(tt_local); |
| 694 | batadv_softif_vlan_put(vlan); | ||
| 695 | goto out; | 698 | goto out; |
| 696 | } | 699 | } |
| 697 | 700 | ||
| @@ -995,7 +998,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
| 995 | struct batadv_tt_local_entry *tt_local; | 998 | struct batadv_tt_local_entry *tt_local; |
| 996 | struct batadv_hard_iface *primary_if; | 999 | struct batadv_hard_iface *primary_if; |
| 997 | struct hlist_head *head; | 1000 | struct hlist_head *head; |
| 998 | unsigned short vid; | ||
| 999 | u32 i; | 1001 | u32 i; |
| 1000 | int last_seen_secs; | 1002 | int last_seen_secs; |
| 1001 | int last_seen_msecs; | 1003 | int last_seen_msecs; |
| @@ -1022,7 +1024,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
| 1022 | tt_local = container_of(tt_common_entry, | 1024 | tt_local = container_of(tt_common_entry, |
| 1023 | struct batadv_tt_local_entry, | 1025 | struct batadv_tt_local_entry, |
| 1024 | common); | 1026 | common); |
| 1025 | vid = tt_common_entry->vid; | ||
| 1026 | last_seen_jiffies = jiffies - tt_local->last_seen; | 1027 | last_seen_jiffies = jiffies - tt_local->last_seen; |
| 1027 | last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); | 1028 | last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); |
| 1028 | last_seen_secs = last_seen_msecs / 1000; | 1029 | last_seen_secs = last_seen_msecs / 1000; |
| @@ -1546,7 +1547,7 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv, | |||
| 1546 | struct batadv_tt_global_entry *tt_global_entry) | 1547 | struct batadv_tt_global_entry *tt_global_entry) |
| 1547 | { | 1548 | { |
| 1548 | struct batadv_neigh_node *router, *best_router = NULL; | 1549 | struct batadv_neigh_node *router, *best_router = NULL; |
| 1549 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; | 1550 | struct batadv_algo_ops *bao = bat_priv->algo_ops; |
| 1550 | struct hlist_head *head; | 1551 | struct hlist_head *head; |
| 1551 | struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL; | 1552 | struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL; |
| 1552 | 1553 | ||
| @@ -1558,8 +1559,8 @@ batadv_transtable_best_orig(struct batadv_priv *bat_priv, | |||
| 1558 | continue; | 1559 | continue; |
| 1559 | 1560 | ||
| 1560 | if (best_router && | 1561 | if (best_router && |
| 1561 | bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT, | 1562 | bao->neigh.cmp(router, BATADV_IF_DEFAULT, best_router, |
| 1562 | best_router, BATADV_IF_DEFAULT) <= 0) { | 1563 | BATADV_IF_DEFAULT) <= 0) { |
| 1563 | batadv_neigh_node_put(router); | 1564 | batadv_neigh_node_put(router); |
| 1564 | continue; | 1565 | continue; |
| 1565 | } | 1566 | } |
| @@ -2269,6 +2270,29 @@ static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv, | |||
| 2269 | return crc; | 2270 | return crc; |
| 2270 | } | 2271 | } |
| 2271 | 2272 | ||
| 2273 | /** | ||
| 2274 | * batadv_tt_req_node_release - free tt_req node entry | ||
| 2275 | * @ref: kref pointer of the tt req_node entry | ||
| 2276 | */ | ||
| 2277 | static void batadv_tt_req_node_release(struct kref *ref) | ||
| 2278 | { | ||
| 2279 | struct batadv_tt_req_node *tt_req_node; | ||
| 2280 | |||
| 2281 | tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount); | ||
| 2282 | |||
| 2283 | kfree(tt_req_node); | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | /** | ||
| 2287 | * batadv_tt_req_node_put - decrement the tt_req_node refcounter and | ||
| 2288 | * possibly release it | ||
| 2289 | * @tt_req_node: tt_req_node to be free'd | ||
| 2290 | */ | ||
| 2291 | static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node) | ||
| 2292 | { | ||
| 2293 | kref_put(&tt_req_node->refcount, batadv_tt_req_node_release); | ||
| 2294 | } | ||
| 2295 | |||
| 2272 | static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | 2296 | static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) |
| 2273 | { | 2297 | { |
| 2274 | struct batadv_tt_req_node *node; | 2298 | struct batadv_tt_req_node *node; |
| @@ -2278,7 +2302,7 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | |||
| 2278 | 2302 | ||
| 2279 | hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { | 2303 | hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
| 2280 | hlist_del_init(&node->list); | 2304 | hlist_del_init(&node->list); |
| 2281 | kfree(node); | 2305 | batadv_tt_req_node_put(node); |
| 2282 | } | 2306 | } |
| 2283 | 2307 | ||
| 2284 | spin_unlock_bh(&bat_priv->tt.req_list_lock); | 2308 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
| @@ -2315,7 +2339,7 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv) | |||
| 2315 | if (batadv_has_timed_out(node->issued_at, | 2339 | if (batadv_has_timed_out(node->issued_at, |
| 2316 | BATADV_TT_REQUEST_TIMEOUT)) { | 2340 | BATADV_TT_REQUEST_TIMEOUT)) { |
| 2317 | hlist_del_init(&node->list); | 2341 | hlist_del_init(&node->list); |
| 2318 | kfree(node); | 2342 | batadv_tt_req_node_put(node); |
| 2319 | } | 2343 | } |
| 2320 | } | 2344 | } |
| 2321 | spin_unlock_bh(&bat_priv->tt.req_list_lock); | 2345 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
| @@ -2347,9 +2371,11 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv, | |||
| 2347 | if (!tt_req_node) | 2371 | if (!tt_req_node) |
| 2348 | goto unlock; | 2372 | goto unlock; |
| 2349 | 2373 | ||
| 2374 | kref_init(&tt_req_node->refcount); | ||
| 2350 | ether_addr_copy(tt_req_node->addr, orig_node->orig); | 2375 | ether_addr_copy(tt_req_node->addr, orig_node->orig); |
| 2351 | tt_req_node->issued_at = jiffies; | 2376 | tt_req_node->issued_at = jiffies; |
| 2352 | 2377 | ||
| 2378 | kref_get(&tt_req_node->refcount); | ||
| 2353 | hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list); | 2379 | hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list); |
| 2354 | unlock: | 2380 | unlock: |
| 2355 | spin_unlock_bh(&bat_priv->tt.req_list_lock); | 2381 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
| @@ -2613,13 +2639,19 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv, | |||
| 2613 | out: | 2639 | out: |
| 2614 | if (primary_if) | 2640 | if (primary_if) |
| 2615 | batadv_hardif_put(primary_if); | 2641 | batadv_hardif_put(primary_if); |
| 2642 | |||
| 2616 | if (ret && tt_req_node) { | 2643 | if (ret && tt_req_node) { |
| 2617 | spin_lock_bh(&bat_priv->tt.req_list_lock); | 2644 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
| 2618 | /* hlist_del_init() verifies tt_req_node still is in the list */ | 2645 | if (!hlist_unhashed(&tt_req_node->list)) { |
| 2619 | hlist_del_init(&tt_req_node->list); | 2646 | hlist_del_init(&tt_req_node->list); |
| 2647 | batadv_tt_req_node_put(tt_req_node); | ||
| 2648 | } | ||
| 2620 | spin_unlock_bh(&bat_priv->tt.req_list_lock); | 2649 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
| 2621 | kfree(tt_req_node); | ||
| 2622 | } | 2650 | } |
| 2651 | |||
| 2652 | if (tt_req_node) | ||
| 2653 | batadv_tt_req_node_put(tt_req_node); | ||
| 2654 | |||
| 2623 | kfree(tvlv_tt_data); | 2655 | kfree(tvlv_tt_data); |
| 2624 | return ret; | 2656 | return ret; |
| 2625 | } | 2657 | } |
| @@ -3055,7 +3087,7 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv, | |||
| 3055 | if (!batadv_compare_eth(node->addr, resp_src)) | 3087 | if (!batadv_compare_eth(node->addr, resp_src)) |
| 3056 | continue; | 3088 | continue; |
| 3057 | hlist_del_init(&node->list); | 3089 | hlist_del_init(&node->list); |
| 3058 | kfree(node); | 3090 | batadv_tt_req_node_put(node); |
| 3059 | } | 3091 | } |
| 3060 | 3092 | ||
| 3061 | spin_unlock_bh(&bat_priv->tt.req_list_lock); | 3093 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
