diff options
Diffstat (limited to 'net/batman-adv/translation-table.c')
-rw-r--r-- | net/batman-adv/translation-table.c | 416 |
1 files changed, 256 insertions, 160 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 99dd8f75b3ff..112edd371b2f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -34,6 +34,10 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, | |||
34 | static void batadv_tt_purge(struct work_struct *work); | 34 | static void batadv_tt_purge(struct work_struct *work); |
35 | static void | 35 | static void |
36 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); | 36 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); |
37 | static void batadv_tt_global_del(struct batadv_priv *bat_priv, | ||
38 | struct batadv_orig_node *orig_node, | ||
39 | const unsigned char *addr, | ||
40 | const char *message, bool roaming); | ||
37 | 41 | ||
38 | /* returns 1 if they are the same mac addr */ | 42 | /* returns 1 if they are the same mac addr */ |
39 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) | 43 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) |
@@ -46,8 +50,8 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) | |||
46 | 50 | ||
47 | static void batadv_tt_start_timer(struct batadv_priv *bat_priv) | 51 | static void batadv_tt_start_timer(struct batadv_priv *bat_priv) |
48 | { | 52 | { |
49 | INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge); | 53 | INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); |
50 | queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work, | 54 | queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, |
51 | msecs_to_jiffies(5000)); | 55 | msecs_to_jiffies(5000)); |
52 | } | 56 | } |
53 | 57 | ||
@@ -88,7 +92,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data) | |||
88 | struct batadv_tt_common_entry *tt_common_entry; | 92 | struct batadv_tt_common_entry *tt_common_entry; |
89 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 93 | struct batadv_tt_local_entry *tt_local_entry = NULL; |
90 | 94 | ||
91 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data); | 95 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data); |
92 | if (tt_common_entry) | 96 | if (tt_common_entry) |
93 | tt_local_entry = container_of(tt_common_entry, | 97 | tt_local_entry = container_of(tt_common_entry, |
94 | struct batadv_tt_local_entry, | 98 | struct batadv_tt_local_entry, |
@@ -102,7 +106,7 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data) | |||
102 | struct batadv_tt_common_entry *tt_common_entry; | 106 | struct batadv_tt_common_entry *tt_common_entry; |
103 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 107 | struct batadv_tt_global_entry *tt_global_entry = NULL; |
104 | 108 | ||
105 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data); | 109 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data); |
106 | if (tt_common_entry) | 110 | if (tt_common_entry) |
107 | tt_global_entry = container_of(tt_common_entry, | 111 | tt_global_entry = container_of(tt_common_entry, |
108 | struct batadv_tt_global_entry, | 112 | struct batadv_tt_global_entry, |
@@ -152,6 +156,8 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | |||
152 | static void | 156 | static void |
153 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) | 157 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) |
154 | { | 158 | { |
159 | if (!atomic_dec_and_test(&orig_entry->refcount)) | ||
160 | return; | ||
155 | /* to avoid race conditions, immediately decrease the tt counter */ | 161 | /* to avoid race conditions, immediately decrease the tt counter */ |
156 | atomic_dec(&orig_entry->orig_node->tt_size); | 162 | atomic_dec(&orig_entry->orig_node->tt_size); |
157 | call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); | 163 | call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); |
@@ -175,8 +181,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, | |||
175 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; | 181 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; |
176 | 182 | ||
177 | /* check for ADD+DEL or DEL+ADD events */ | 183 | /* check for ADD+DEL or DEL+ADD events */ |
178 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 184 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
179 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 185 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
180 | list) { | 186 | list) { |
181 | if (!batadv_compare_eth(entry->change.addr, addr)) | 187 | if (!batadv_compare_eth(entry->change.addr, addr)) |
182 | continue; | 188 | continue; |
@@ -203,15 +209,15 @@ del: | |||
203 | } | 209 | } |
204 | 210 | ||
205 | /* track the change in the OGMinterval list */ | 211 | /* track the change in the OGMinterval list */ |
206 | list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list); | 212 | list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list); |
207 | 213 | ||
208 | unlock: | 214 | unlock: |
209 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 215 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
210 | 216 | ||
211 | if (event_removed) | 217 | if (event_removed) |
212 | atomic_dec(&bat_priv->tt_local_changes); | 218 | atomic_dec(&bat_priv->tt.local_changes); |
213 | else | 219 | else |
214 | atomic_inc(&bat_priv->tt_local_changes); | 220 | atomic_inc(&bat_priv->tt.local_changes); |
215 | } | 221 | } |
216 | 222 | ||
217 | int batadv_tt_len(int changes_num) | 223 | int batadv_tt_len(int changes_num) |
@@ -221,12 +227,12 @@ int batadv_tt_len(int changes_num) | |||
221 | 227 | ||
222 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) | 228 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) |
223 | { | 229 | { |
224 | if (bat_priv->tt_local_hash) | 230 | if (bat_priv->tt.local_hash) |
225 | return 0; | 231 | return 0; |
226 | 232 | ||
227 | bat_priv->tt_local_hash = batadv_hash_new(1024); | 233 | bat_priv->tt.local_hash = batadv_hash_new(1024); |
228 | 234 | ||
229 | if (!bat_priv->tt_local_hash) | 235 | if (!bat_priv->tt.local_hash) |
230 | return -ENOMEM; | 236 | return -ENOMEM; |
231 | 237 | ||
232 | return 0; | 238 | return 0; |
@@ -258,7 +264,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
258 | 264 | ||
259 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 265 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
260 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 266 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
261 | (uint8_t)atomic_read(&bat_priv->ttvn)); | 267 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
262 | 268 | ||
263 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); | 269 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); |
264 | tt_local_entry->common.flags = BATADV_NO_FLAGS; | 270 | tt_local_entry->common.flags = BATADV_NO_FLAGS; |
@@ -266,6 +272,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
266 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; | 272 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; |
267 | atomic_set(&tt_local_entry->common.refcount, 2); | 273 | atomic_set(&tt_local_entry->common.refcount, 2); |
268 | tt_local_entry->last_seen = jiffies; | 274 | tt_local_entry->last_seen = jiffies; |
275 | tt_local_entry->common.added_at = tt_local_entry->last_seen; | ||
269 | 276 | ||
270 | /* the batman interface mac address should never be purged */ | 277 | /* the batman interface mac address should never be purged */ |
271 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) | 278 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) |
@@ -277,7 +284,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
277 | */ | 284 | */ |
278 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; | 285 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; |
279 | 286 | ||
280 | hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt, | 287 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
281 | batadv_choose_orig, | 288 | batadv_choose_orig, |
282 | &tt_local_entry->common, | 289 | &tt_local_entry->common, |
283 | &tt_local_entry->common.hash_entry); | 290 | &tt_local_entry->common.hash_entry); |
@@ -348,7 +355,7 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv, | |||
348 | primary_if = batadv_primary_if_get_selected(bat_priv); | 355 | primary_if = batadv_primary_if_get_selected(bat_priv); |
349 | 356 | ||
350 | req_len = min_packet_len; | 357 | req_len = min_packet_len; |
351 | req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes)); | 358 | req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); |
352 | 359 | ||
353 | /* if we have too many changes for one packet don't send any | 360 | /* if we have too many changes for one packet don't send any |
354 | * and wait for the tt table request which will be fragmented | 361 | * and wait for the tt table request which will be fragmented |
@@ -381,10 +388,10 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, | |||
381 | if (new_len > 0) | 388 | if (new_len > 0) |
382 | tot_changes = new_len / batadv_tt_len(1); | 389 | tot_changes = new_len / batadv_tt_len(1); |
383 | 390 | ||
384 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 391 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
385 | atomic_set(&bat_priv->tt_local_changes, 0); | 392 | atomic_set(&bat_priv->tt.local_changes, 0); |
386 | 393 | ||
387 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 394 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
388 | list) { | 395 | list) { |
389 | if (count < tot_changes) { | 396 | if (count < tot_changes) { |
390 | memcpy(tt_buff + batadv_tt_len(count), | 397 | memcpy(tt_buff + batadv_tt_len(count), |
@@ -394,25 +401,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, | |||
394 | list_del(&entry->list); | 401 | list_del(&entry->list); |
395 | kfree(entry); | 402 | kfree(entry); |
396 | } | 403 | } |
397 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 404 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
398 | 405 | ||
399 | /* Keep the buffer for possible tt_request */ | 406 | /* Keep the buffer for possible tt_request */ |
400 | spin_lock_bh(&bat_priv->tt_buff_lock); | 407 | spin_lock_bh(&bat_priv->tt.last_changeset_lock); |
401 | kfree(bat_priv->tt_buff); | 408 | kfree(bat_priv->tt.last_changeset); |
402 | bat_priv->tt_buff_len = 0; | 409 | bat_priv->tt.last_changeset_len = 0; |
403 | bat_priv->tt_buff = NULL; | 410 | bat_priv->tt.last_changeset = NULL; |
404 | /* check whether this new OGM has no changes due to size problems */ | 411 | /* check whether this new OGM has no changes due to size problems */ |
405 | if (new_len > 0) { | 412 | if (new_len > 0) { |
406 | /* if kmalloc() fails we will reply with the full table | 413 | /* if kmalloc() fails we will reply with the full table |
407 | * instead of providing the diff | 414 | * instead of providing the diff |
408 | */ | 415 | */ |
409 | bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC); | 416 | bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); |
410 | if (bat_priv->tt_buff) { | 417 | if (bat_priv->tt.last_changeset) { |
411 | memcpy(bat_priv->tt_buff, tt_buff, new_len); | 418 | memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); |
412 | bat_priv->tt_buff_len = new_len; | 419 | bat_priv->tt.last_changeset_len = new_len; |
413 | } | 420 | } |
414 | } | 421 | } |
415 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 422 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
416 | 423 | ||
417 | return count; | 424 | return count; |
418 | } | 425 | } |
@@ -421,7 +428,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
421 | { | 428 | { |
422 | struct net_device *net_dev = (struct net_device *)seq->private; | 429 | struct net_device *net_dev = (struct net_device *)seq->private; |
423 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 430 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
424 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 431 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
425 | struct batadv_tt_common_entry *tt_common_entry; | 432 | struct batadv_tt_common_entry *tt_common_entry; |
426 | struct batadv_hard_iface *primary_if; | 433 | struct batadv_hard_iface *primary_if; |
427 | struct hlist_node *node; | 434 | struct hlist_node *node; |
@@ -446,7 +453,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
446 | 453 | ||
447 | seq_printf(seq, | 454 | seq_printf(seq, |
448 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", | 455 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", |
449 | net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); | 456 | net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn)); |
450 | 457 | ||
451 | for (i = 0; i < hash->size; i++) { | 458 | for (i = 0; i < hash->size; i++) { |
452 | head = &hash->table[i]; | 459 | head = &hash->table[i]; |
@@ -544,7 +551,7 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, | |||
544 | 551 | ||
545 | static void batadv_tt_local_purge(struct batadv_priv *bat_priv) | 552 | static void batadv_tt_local_purge(struct batadv_priv *bat_priv) |
546 | { | 553 | { |
547 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 554 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
548 | struct hlist_head *head; | 555 | struct hlist_head *head; |
549 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 556 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
550 | uint32_t i; | 557 | uint32_t i; |
@@ -570,10 +577,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
570 | struct hlist_head *head; | 577 | struct hlist_head *head; |
571 | uint32_t i; | 578 | uint32_t i; |
572 | 579 | ||
573 | if (!bat_priv->tt_local_hash) | 580 | if (!bat_priv->tt.local_hash) |
574 | return; | 581 | return; |
575 | 582 | ||
576 | hash = bat_priv->tt_local_hash; | 583 | hash = bat_priv->tt.local_hash; |
577 | 584 | ||
578 | for (i = 0; i < hash->size; i++) { | 585 | for (i = 0; i < hash->size; i++) { |
579 | head = &hash->table[i]; | 586 | head = &hash->table[i]; |
@@ -593,17 +600,17 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
593 | 600 | ||
594 | batadv_hash_destroy(hash); | 601 | batadv_hash_destroy(hash); |
595 | 602 | ||
596 | bat_priv->tt_local_hash = NULL; | 603 | bat_priv->tt.local_hash = NULL; |
597 | } | 604 | } |
598 | 605 | ||
599 | static int batadv_tt_global_init(struct batadv_priv *bat_priv) | 606 | static int batadv_tt_global_init(struct batadv_priv *bat_priv) |
600 | { | 607 | { |
601 | if (bat_priv->tt_global_hash) | 608 | if (bat_priv->tt.global_hash) |
602 | return 0; | 609 | return 0; |
603 | 610 | ||
604 | bat_priv->tt_global_hash = batadv_hash_new(1024); | 611 | bat_priv->tt.global_hash = batadv_hash_new(1024); |
605 | 612 | ||
606 | if (!bat_priv->tt_global_hash) | 613 | if (!bat_priv->tt.global_hash) |
607 | return -ENOMEM; | 614 | return -ENOMEM; |
608 | 615 | ||
609 | return 0; | 616 | return 0; |
@@ -613,62 +620,99 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv) | |||
613 | { | 620 | { |
614 | struct batadv_tt_change_node *entry, *safe; | 621 | struct batadv_tt_change_node *entry, *safe; |
615 | 622 | ||
616 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 623 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
617 | 624 | ||
618 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 625 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
619 | list) { | 626 | list) { |
620 | list_del(&entry->list); | 627 | list_del(&entry->list); |
621 | kfree(entry); | 628 | kfree(entry); |
622 | } | 629 | } |
623 | 630 | ||
624 | atomic_set(&bat_priv->tt_local_changes, 0); | 631 | atomic_set(&bat_priv->tt.local_changes, 0); |
625 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 632 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
626 | } | 633 | } |
627 | 634 | ||
628 | /* find out if an orig_node is already in the list of a tt_global_entry. | 635 | /* retrieves the orig_tt_list_entry belonging to orig_node from the |
629 | * returns 1 if found, 0 otherwise | 636 | * batadv_tt_global_entry list |
637 | * | ||
638 | * returns it with an increased refcounter, NULL if not found | ||
630 | */ | 639 | */ |
631 | static bool | 640 | static struct batadv_tt_orig_list_entry * |
632 | batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, | 641 | batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, |
633 | const struct batadv_orig_node *orig_node) | 642 | const struct batadv_orig_node *orig_node) |
634 | { | 643 | { |
635 | struct batadv_tt_orig_list_entry *tmp_orig_entry; | 644 | struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL; |
636 | const struct hlist_head *head; | 645 | const struct hlist_head *head; |
637 | struct hlist_node *node; | 646 | struct hlist_node *node; |
638 | bool found = false; | ||
639 | 647 | ||
640 | rcu_read_lock(); | 648 | rcu_read_lock(); |
641 | head = &entry->orig_list; | 649 | head = &entry->orig_list; |
642 | hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { | 650 | hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { |
643 | if (tmp_orig_entry->orig_node == orig_node) { | 651 | if (tmp_orig_entry->orig_node != orig_node) |
644 | found = true; | 652 | continue; |
645 | break; | 653 | if (!atomic_inc_not_zero(&tmp_orig_entry->refcount)) |
646 | } | 654 | continue; |
655 | |||
656 | orig_entry = tmp_orig_entry; | ||
657 | break; | ||
647 | } | 658 | } |
648 | rcu_read_unlock(); | 659 | rcu_read_unlock(); |
660 | |||
661 | return orig_entry; | ||
662 | } | ||
663 | |||
664 | /* find out if an orig_node is already in the list of a tt_global_entry. | ||
665 | * returns true if found, false otherwise | ||
666 | */ | ||
667 | static bool | ||
668 | batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, | ||
669 | const struct batadv_orig_node *orig_node) | ||
670 | { | ||
671 | struct batadv_tt_orig_list_entry *orig_entry; | ||
672 | bool found = false; | ||
673 | |||
674 | orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); | ||
675 | if (orig_entry) { | ||
676 | found = true; | ||
677 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
678 | } | ||
679 | |||
649 | return found; | 680 | return found; |
650 | } | 681 | } |
651 | 682 | ||
652 | static void | 683 | static void |
653 | batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry, | 684 | batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, |
654 | struct batadv_orig_node *orig_node, int ttvn) | 685 | struct batadv_orig_node *orig_node, int ttvn) |
655 | { | 686 | { |
656 | struct batadv_tt_orig_list_entry *orig_entry; | 687 | struct batadv_tt_orig_list_entry *orig_entry; |
657 | 688 | ||
689 | orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); | ||
690 | if (orig_entry) { | ||
691 | /* refresh the ttvn: the current value could be a bogus one that | ||
692 | * was added during a "temporary client detection" | ||
693 | */ | ||
694 | orig_entry->ttvn = ttvn; | ||
695 | goto out; | ||
696 | } | ||
697 | |||
658 | orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); | 698 | orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); |
659 | if (!orig_entry) | 699 | if (!orig_entry) |
660 | return; | 700 | goto out; |
661 | 701 | ||
662 | INIT_HLIST_NODE(&orig_entry->list); | 702 | INIT_HLIST_NODE(&orig_entry->list); |
663 | atomic_inc(&orig_node->refcount); | 703 | atomic_inc(&orig_node->refcount); |
664 | atomic_inc(&orig_node->tt_size); | 704 | atomic_inc(&orig_node->tt_size); |
665 | orig_entry->orig_node = orig_node; | 705 | orig_entry->orig_node = orig_node; |
666 | orig_entry->ttvn = ttvn; | 706 | orig_entry->ttvn = ttvn; |
707 | atomic_set(&orig_entry->refcount, 2); | ||
667 | 708 | ||
668 | spin_lock_bh(&tt_global_entry->list_lock); | 709 | spin_lock_bh(&tt_global->list_lock); |
669 | hlist_add_head_rcu(&orig_entry->list, | 710 | hlist_add_head_rcu(&orig_entry->list, |
670 | &tt_global_entry->orig_list); | 711 | &tt_global->orig_list); |
671 | spin_unlock_bh(&tt_global_entry->list_lock); | 712 | spin_unlock_bh(&tt_global->list_lock); |
713 | out: | ||
714 | if (orig_entry) | ||
715 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
672 | } | 716 | } |
673 | 717 | ||
674 | /* caller must hold orig_node refcount */ | 718 | /* caller must hold orig_node refcount */ |
@@ -695,11 +739,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
695 | common->flags = flags; | 739 | common->flags = flags; |
696 | tt_global_entry->roam_at = 0; | 740 | tt_global_entry->roam_at = 0; |
697 | atomic_set(&common->refcount, 2); | 741 | atomic_set(&common->refcount, 2); |
742 | common->added_at = jiffies; | ||
698 | 743 | ||
699 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); | 744 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); |
700 | spin_lock_init(&tt_global_entry->list_lock); | 745 | spin_lock_init(&tt_global_entry->list_lock); |
701 | 746 | ||
702 | hash_added = batadv_hash_add(bat_priv->tt_global_hash, | 747 | hash_added = batadv_hash_add(bat_priv->tt.global_hash, |
703 | batadv_compare_tt, | 748 | batadv_compare_tt, |
704 | batadv_choose_orig, common, | 749 | batadv_choose_orig, common, |
705 | &common->hash_entry); | 750 | &common->hash_entry); |
@@ -709,11 +754,20 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
709 | batadv_tt_global_entry_free_ref(tt_global_entry); | 754 | batadv_tt_global_entry_free_ref(tt_global_entry); |
710 | goto out_remove; | 755 | goto out_remove; |
711 | } | 756 | } |
712 | |||
713 | batadv_tt_global_add_orig_entry(tt_global_entry, orig_node, | ||
714 | ttvn); | ||
715 | } else { | 757 | } else { |
716 | /* there is already a global entry, use this one. */ | 758 | /* If there is already a global entry, we can use this one for |
759 | * our processing. | ||
760 | * But if we are trying to add a temporary client we can exit | ||
761 | * directly because the temporary information should never | ||
762 | * override any already known client state (whatever it is) | ||
763 | */ | ||
764 | if (flags & BATADV_TT_CLIENT_TEMP) | ||
765 | goto out; | ||
766 | |||
767 | /* if the client was temporary added before receiving the first | ||
768 | * OGM announcing it, we have to clear the TEMP flag | ||
769 | */ | ||
770 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; | ||
717 | 771 | ||
718 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only | 772 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only |
719 | * one originator left in the list and we previously received a | 773 | * one originator left in the list and we previously received a |
@@ -727,12 +781,9 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
727 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | 781 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; |
728 | tt_global_entry->roam_at = 0; | 782 | tt_global_entry->roam_at = 0; |
729 | } | 783 | } |
730 | |||
731 | if (!batadv_tt_global_entry_has_orig(tt_global_entry, | ||
732 | orig_node)) | ||
733 | batadv_tt_global_add_orig_entry(tt_global_entry, | ||
734 | orig_node, ttvn); | ||
735 | } | 784 | } |
785 | /* add the new orig_entry (if needed) or update it */ | ||
786 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); | ||
736 | 787 | ||
737 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 788 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
738 | "Creating new global tt entry: %pM (via %pM)\n", | 789 | "Creating new global tt entry: %pM (via %pM)\n", |
@@ -771,11 +822,12 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, | |||
771 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { | 822 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { |
772 | flags = tt_common_entry->flags; | 823 | flags = tt_common_entry->flags; |
773 | last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); | 824 | last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); |
774 | seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n", | 825 | seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n", |
775 | tt_global_entry->common.addr, orig_entry->ttvn, | 826 | tt_global_entry->common.addr, orig_entry->ttvn, |
776 | orig_entry->orig_node->orig, last_ttvn, | 827 | orig_entry->orig_node->orig, last_ttvn, |
777 | (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), | 828 | (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), |
778 | (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.')); | 829 | (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), |
830 | (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); | ||
779 | } | 831 | } |
780 | } | 832 | } |
781 | 833 | ||
@@ -783,7 +835,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
783 | { | 835 | { |
784 | struct net_device *net_dev = (struct net_device *)seq->private; | 836 | struct net_device *net_dev = (struct net_device *)seq->private; |
785 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 837 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
786 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 838 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
787 | struct batadv_tt_common_entry *tt_common_entry; | 839 | struct batadv_tt_common_entry *tt_common_entry; |
788 | struct batadv_tt_global_entry *tt_global; | 840 | struct batadv_tt_global_entry *tt_global; |
789 | struct batadv_hard_iface *primary_if; | 841 | struct batadv_hard_iface *primary_if; |
@@ -884,7 +936,7 @@ batadv_tt_global_del_struct(struct batadv_priv *bat_priv, | |||
884 | "Deleting global tt entry %pM: %s\n", | 936 | "Deleting global tt entry %pM: %s\n", |
885 | tt_global_entry->common.addr, message); | 937 | tt_global_entry->common.addr, message); |
886 | 938 | ||
887 | batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt, | 939 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, |
888 | batadv_choose_orig, tt_global_entry->common.addr); | 940 | batadv_choose_orig, tt_global_entry->common.addr); |
889 | batadv_tt_global_entry_free_ref(tt_global_entry); | 941 | batadv_tt_global_entry_free_ref(tt_global_entry); |
890 | 942 | ||
@@ -995,7 +1047,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
995 | struct batadv_tt_global_entry *tt_global; | 1047 | struct batadv_tt_global_entry *tt_global; |
996 | struct batadv_tt_common_entry *tt_common_entry; | 1048 | struct batadv_tt_common_entry *tt_common_entry; |
997 | uint32_t i; | 1049 | uint32_t i; |
998 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1050 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
999 | struct hlist_node *node, *safe; | 1051 | struct hlist_node *node, *safe; |
1000 | struct hlist_head *head; | 1052 | struct hlist_head *head; |
1001 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1053 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
@@ -1030,49 +1082,63 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
1030 | orig_node->tt_initialised = false; | 1082 | orig_node->tt_initialised = false; |
1031 | } | 1083 | } |
1032 | 1084 | ||
1033 | static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv, | 1085 | static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, |
1034 | struct hlist_head *head) | 1086 | char **msg) |
1035 | { | 1087 | { |
1036 | struct batadv_tt_common_entry *tt_common_entry; | 1088 | bool purge = false; |
1037 | struct batadv_tt_global_entry *tt_global_entry; | 1089 | unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT; |
1038 | struct hlist_node *node, *node_tmp; | 1090 | unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT; |
1039 | |||
1040 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head, | ||
1041 | hash_entry) { | ||
1042 | tt_global_entry = container_of(tt_common_entry, | ||
1043 | struct batadv_tt_global_entry, | ||
1044 | common); | ||
1045 | if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM)) | ||
1046 | continue; | ||
1047 | if (!batadv_has_timed_out(tt_global_entry->roam_at, | ||
1048 | BATADV_TT_CLIENT_ROAM_TIMEOUT)) | ||
1049 | continue; | ||
1050 | 1091 | ||
1051 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1092 | if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) && |
1052 | "Deleting global tt entry (%pM): Roaming timeout\n", | 1093 | batadv_has_timed_out(tt_global->roam_at, roam_timeout)) { |
1053 | tt_global_entry->common.addr); | 1094 | purge = true; |
1095 | *msg = "Roaming timeout\n"; | ||
1096 | } | ||
1054 | 1097 | ||
1055 | hlist_del_rcu(node); | 1098 | if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) && |
1056 | batadv_tt_global_entry_free_ref(tt_global_entry); | 1099 | batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) { |
1100 | purge = true; | ||
1101 | *msg = "Temporary client timeout\n"; | ||
1057 | } | 1102 | } |
1103 | |||
1104 | return purge; | ||
1058 | } | 1105 | } |
1059 | 1106 | ||
1060 | static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv) | 1107 | static void batadv_tt_global_purge(struct batadv_priv *bat_priv) |
1061 | { | 1108 | { |
1062 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1109 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
1063 | struct hlist_head *head; | 1110 | struct hlist_head *head; |
1111 | struct hlist_node *node, *node_tmp; | ||
1064 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1112 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
1065 | uint32_t i; | 1113 | uint32_t i; |
1114 | char *msg = NULL; | ||
1115 | struct batadv_tt_common_entry *tt_common; | ||
1116 | struct batadv_tt_global_entry *tt_global; | ||
1066 | 1117 | ||
1067 | for (i = 0; i < hash->size; i++) { | 1118 | for (i = 0; i < hash->size; i++) { |
1068 | head = &hash->table[i]; | 1119 | head = &hash->table[i]; |
1069 | list_lock = &hash->list_locks[i]; | 1120 | list_lock = &hash->list_locks[i]; |
1070 | 1121 | ||
1071 | spin_lock_bh(list_lock); | 1122 | spin_lock_bh(list_lock); |
1072 | batadv_tt_global_roam_purge_list(bat_priv, head); | 1123 | hlist_for_each_entry_safe(tt_common, node, node_tmp, head, |
1124 | hash_entry) { | ||
1125 | tt_global = container_of(tt_common, | ||
1126 | struct batadv_tt_global_entry, | ||
1127 | common); | ||
1128 | |||
1129 | if (!batadv_tt_global_to_purge(tt_global, &msg)) | ||
1130 | continue; | ||
1131 | |||
1132 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
1133 | "Deleting global tt entry (%pM): %s\n", | ||
1134 | tt_global->common.addr, msg); | ||
1135 | |||
1136 | hlist_del_rcu(node); | ||
1137 | |||
1138 | batadv_tt_global_entry_free_ref(tt_global); | ||
1139 | } | ||
1073 | spin_unlock_bh(list_lock); | 1140 | spin_unlock_bh(list_lock); |
1074 | } | 1141 | } |
1075 | |||
1076 | } | 1142 | } |
1077 | 1143 | ||
1078 | static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | 1144 | static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) |
@@ -1085,10 +1151,10 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | |||
1085 | struct hlist_head *head; | 1151 | struct hlist_head *head; |
1086 | uint32_t i; | 1152 | uint32_t i; |
1087 | 1153 | ||
1088 | if (!bat_priv->tt_global_hash) | 1154 | if (!bat_priv->tt.global_hash) |
1089 | return; | 1155 | return; |
1090 | 1156 | ||
1091 | hash = bat_priv->tt_global_hash; | 1157 | hash = bat_priv->tt.global_hash; |
1092 | 1158 | ||
1093 | for (i = 0; i < hash->size; i++) { | 1159 | for (i = 0; i < hash->size; i++) { |
1094 | head = &hash->table[i]; | 1160 | head = &hash->table[i]; |
@@ -1108,7 +1174,7 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | |||
1108 | 1174 | ||
1109 | batadv_hash_destroy(hash); | 1175 | batadv_hash_destroy(hash); |
1110 | 1176 | ||
1111 | bat_priv->tt_global_hash = NULL; | 1177 | bat_priv->tt.global_hash = NULL; |
1112 | } | 1178 | } |
1113 | 1179 | ||
1114 | static bool | 1180 | static bool |
@@ -1187,7 +1253,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1187 | struct batadv_orig_node *orig_node) | 1253 | struct batadv_orig_node *orig_node) |
1188 | { | 1254 | { |
1189 | uint16_t total = 0, total_one; | 1255 | uint16_t total = 0, total_one; |
1190 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1256 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
1191 | struct batadv_tt_common_entry *tt_common; | 1257 | struct batadv_tt_common_entry *tt_common; |
1192 | struct batadv_tt_global_entry *tt_global; | 1258 | struct batadv_tt_global_entry *tt_global; |
1193 | struct hlist_node *node; | 1259 | struct hlist_node *node; |
@@ -1210,6 +1276,12 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1210 | */ | 1276 | */ |
1211 | if (tt_common->flags & BATADV_TT_CLIENT_ROAM) | 1277 | if (tt_common->flags & BATADV_TT_CLIENT_ROAM) |
1212 | continue; | 1278 | continue; |
1279 | /* Temporary clients have not been announced yet, so | ||
1280 | * they have to be skipped while computing the global | ||
1281 | * crc | ||
1282 | */ | ||
1283 | if (tt_common->flags & BATADV_TT_CLIENT_TEMP) | ||
1284 | continue; | ||
1213 | 1285 | ||
1214 | /* find out if this global entry is announced by this | 1286 | /* find out if this global entry is announced by this |
1215 | * originator | 1287 | * originator |
@@ -1234,7 +1306,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1234 | static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) | 1306 | static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) |
1235 | { | 1307 | { |
1236 | uint16_t total = 0, total_one; | 1308 | uint16_t total = 0, total_one; |
1237 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 1309 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
1238 | struct batadv_tt_common_entry *tt_common; | 1310 | struct batadv_tt_common_entry *tt_common; |
1239 | struct hlist_node *node; | 1311 | struct hlist_node *node; |
1240 | struct hlist_head *head; | 1312 | struct hlist_head *head; |
@@ -1267,14 +1339,14 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | |||
1267 | { | 1339 | { |
1268 | struct batadv_tt_req_node *node, *safe; | 1340 | struct batadv_tt_req_node *node, *safe; |
1269 | 1341 | ||
1270 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1342 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1271 | 1343 | ||
1272 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1344 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1273 | list_del(&node->list); | 1345 | list_del(&node->list); |
1274 | kfree(node); | 1346 | kfree(node); |
1275 | } | 1347 | } |
1276 | 1348 | ||
1277 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1349 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1278 | } | 1350 | } |
1279 | 1351 | ||
1280 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, | 1352 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, |
@@ -1304,15 +1376,15 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv) | |||
1304 | { | 1376 | { |
1305 | struct batadv_tt_req_node *node, *safe; | 1377 | struct batadv_tt_req_node *node, *safe; |
1306 | 1378 | ||
1307 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1379 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1308 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1380 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1309 | if (batadv_has_timed_out(node->issued_at, | 1381 | if (batadv_has_timed_out(node->issued_at, |
1310 | BATADV_TT_REQUEST_TIMEOUT)) { | 1382 | BATADV_TT_REQUEST_TIMEOUT)) { |
1311 | list_del(&node->list); | 1383 | list_del(&node->list); |
1312 | kfree(node); | 1384 | kfree(node); |
1313 | } | 1385 | } |
1314 | } | 1386 | } |
1315 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1387 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1316 | } | 1388 | } |
1317 | 1389 | ||
1318 | /* returns the pointer to the new tt_req_node struct if no request | 1390 | /* returns the pointer to the new tt_req_node struct if no request |
@@ -1324,8 +1396,8 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv, | |||
1324 | { | 1396 | { |
1325 | struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL; | 1397 | struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL; |
1326 | 1398 | ||
1327 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1399 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1328 | list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) { | 1400 | list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) { |
1329 | if (batadv_compare_eth(tt_req_node_tmp, orig_node) && | 1401 | if (batadv_compare_eth(tt_req_node_tmp, orig_node) && |
1330 | !batadv_has_timed_out(tt_req_node_tmp->issued_at, | 1402 | !batadv_has_timed_out(tt_req_node_tmp->issued_at, |
1331 | BATADV_TT_REQUEST_TIMEOUT)) | 1403 | BATADV_TT_REQUEST_TIMEOUT)) |
@@ -1339,9 +1411,9 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv, | |||
1339 | memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); | 1411 | memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); |
1340 | tt_req_node->issued_at = jiffies; | 1412 | tt_req_node->issued_at = jiffies; |
1341 | 1413 | ||
1342 | list_add(&tt_req_node->list, &bat_priv->tt_req_list); | 1414 | list_add(&tt_req_node->list, &bat_priv->tt.req_list); |
1343 | unlock: | 1415 | unlock: |
1344 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1416 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1345 | return tt_req_node; | 1417 | return tt_req_node; |
1346 | } | 1418 | } |
1347 | 1419 | ||
@@ -1363,7 +1435,8 @@ static int batadv_tt_global_valid(const void *entry_ptr, | |||
1363 | const struct batadv_tt_global_entry *tt_global_entry; | 1435 | const struct batadv_tt_global_entry *tt_global_entry; |
1364 | const struct batadv_orig_node *orig_node = data_ptr; | 1436 | const struct batadv_orig_node *orig_node = data_ptr; |
1365 | 1437 | ||
1366 | if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM) | 1438 | if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM || |
1439 | tt_common_entry->flags & BATADV_TT_CLIENT_TEMP) | ||
1367 | return 0; | 1440 | return 0; |
1368 | 1441 | ||
1369 | tt_global_entry = container_of(tt_common_entry, | 1442 | tt_global_entry = container_of(tt_common_entry, |
@@ -1507,9 +1580,9 @@ out: | |||
1507 | if (ret) | 1580 | if (ret) |
1508 | kfree_skb(skb); | 1581 | kfree_skb(skb); |
1509 | if (ret && tt_req_node) { | 1582 | if (ret && tt_req_node) { |
1510 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1583 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1511 | list_del(&tt_req_node->list); | 1584 | list_del(&tt_req_node->list); |
1512 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1585 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1513 | kfree(tt_req_node); | 1586 | kfree(tt_req_node); |
1514 | } | 1587 | } |
1515 | return ret; | 1588 | return ret; |
@@ -1530,6 +1603,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1530 | uint16_t tt_len, tt_tot; | 1603 | uint16_t tt_len, tt_tot; |
1531 | struct sk_buff *skb = NULL; | 1604 | struct sk_buff *skb = NULL; |
1532 | struct batadv_tt_query_packet *tt_response; | 1605 | struct batadv_tt_query_packet *tt_response; |
1606 | uint8_t *packet_pos; | ||
1533 | size_t len; | 1607 | size_t len; |
1534 | 1608 | ||
1535 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1609 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
@@ -1583,8 +1657,8 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1583 | goto unlock; | 1657 | goto unlock; |
1584 | 1658 | ||
1585 | skb_reserve(skb, ETH_HLEN); | 1659 | skb_reserve(skb, ETH_HLEN); |
1586 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, | 1660 | packet_pos = skb_put(skb, len); |
1587 | len); | 1661 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1588 | tt_response->ttvn = req_ttvn; | 1662 | tt_response->ttvn = req_ttvn; |
1589 | tt_response->tt_data = htons(tt_tot); | 1663 | tt_response->tt_data = htons(tt_tot); |
1590 | 1664 | ||
@@ -1600,7 +1674,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1600 | ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); | 1674 | ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); |
1601 | 1675 | ||
1602 | skb = batadv_tt_response_fill_table(tt_len, ttvn, | 1676 | skb = batadv_tt_response_fill_table(tt_len, ttvn, |
1603 | bat_priv->tt_global_hash, | 1677 | bat_priv->tt.global_hash, |
1604 | primary_if, | 1678 | primary_if, |
1605 | batadv_tt_global_valid, | 1679 | batadv_tt_global_valid, |
1606 | req_dst_orig_node); | 1680 | req_dst_orig_node); |
@@ -1663,6 +1737,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1663 | uint16_t tt_len, tt_tot; | 1737 | uint16_t tt_len, tt_tot; |
1664 | struct sk_buff *skb = NULL; | 1738 | struct sk_buff *skb = NULL; |
1665 | struct batadv_tt_query_packet *tt_response; | 1739 | struct batadv_tt_query_packet *tt_response; |
1740 | uint8_t *packet_pos; | ||
1666 | size_t len; | 1741 | size_t len; |
1667 | 1742 | ||
1668 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1743 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
@@ -1671,7 +1746,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1671 | (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); | 1746 | (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
1672 | 1747 | ||
1673 | 1748 | ||
1674 | my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 1749 | my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
1675 | req_ttvn = tt_request->ttvn; | 1750 | req_ttvn = tt_request->ttvn; |
1676 | 1751 | ||
1677 | orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); | 1752 | orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); |
@@ -1690,7 +1765,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1690 | * is too big send the whole local translation table | 1765 | * is too big send the whole local translation table |
1691 | */ | 1766 | */ |
1692 | if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || | 1767 | if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || |
1693 | !bat_priv->tt_buff) | 1768 | !bat_priv->tt.last_changeset) |
1694 | full_table = true; | 1769 | full_table = true; |
1695 | else | 1770 | else |
1696 | full_table = false; | 1771 | full_table = false; |
@@ -1699,8 +1774,8 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1699 | * I'll send only one packet with as much TT entries as I can | 1774 | * I'll send only one packet with as much TT entries as I can |
1700 | */ | 1775 | */ |
1701 | if (!full_table) { | 1776 | if (!full_table) { |
1702 | spin_lock_bh(&bat_priv->tt_buff_lock); | 1777 | spin_lock_bh(&bat_priv->tt.last_changeset_lock); |
1703 | tt_len = bat_priv->tt_buff_len; | 1778 | tt_len = bat_priv->tt.last_changeset_len; |
1704 | tt_tot = tt_len / sizeof(struct batadv_tt_change); | 1779 | tt_tot = tt_len / sizeof(struct batadv_tt_change); |
1705 | 1780 | ||
1706 | len = sizeof(*tt_response) + tt_len; | 1781 | len = sizeof(*tt_response) + tt_len; |
@@ -1709,22 +1784,22 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1709 | goto unlock; | 1784 | goto unlock; |
1710 | 1785 | ||
1711 | skb_reserve(skb, ETH_HLEN); | 1786 | skb_reserve(skb, ETH_HLEN); |
1712 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, | 1787 | packet_pos = skb_put(skb, len); |
1713 | len); | 1788 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1714 | tt_response->ttvn = req_ttvn; | 1789 | tt_response->ttvn = req_ttvn; |
1715 | tt_response->tt_data = htons(tt_tot); | 1790 | tt_response->tt_data = htons(tt_tot); |
1716 | 1791 | ||
1717 | tt_buff = skb->data + sizeof(*tt_response); | 1792 | tt_buff = skb->data + sizeof(*tt_response); |
1718 | memcpy(tt_buff, bat_priv->tt_buff, | 1793 | memcpy(tt_buff, bat_priv->tt.last_changeset, |
1719 | bat_priv->tt_buff_len); | 1794 | bat_priv->tt.last_changeset_len); |
1720 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 1795 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
1721 | } else { | 1796 | } else { |
1722 | tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt); | 1797 | tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); |
1723 | tt_len *= sizeof(struct batadv_tt_change); | 1798 | tt_len *= sizeof(struct batadv_tt_change); |
1724 | ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 1799 | ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
1725 | 1800 | ||
1726 | skb = batadv_tt_response_fill_table(tt_len, ttvn, | 1801 | skb = batadv_tt_response_fill_table(tt_len, ttvn, |
1727 | bat_priv->tt_local_hash, | 1802 | bat_priv->tt.local_hash, |
1728 | primary_if, | 1803 | primary_if, |
1729 | batadv_tt_local_valid_entry, | 1804 | batadv_tt_local_valid_entry, |
1730 | NULL); | 1805 | NULL); |
@@ -1756,7 +1831,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1756 | goto out; | 1831 | goto out; |
1757 | 1832 | ||
1758 | unlock: | 1833 | unlock: |
1759 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 1834 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
1760 | out: | 1835 | out: |
1761 | if (orig_node) | 1836 | if (orig_node) |
1762 | batadv_orig_node_free_ref(orig_node); | 1837 | batadv_orig_node_free_ref(orig_node); |
@@ -1909,14 +1984,14 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv, | |||
1909 | } | 1984 | } |
1910 | 1985 | ||
1911 | /* Delete the tt_req_node from pending tt_requests list */ | 1986 | /* Delete the tt_req_node from pending tt_requests list */ |
1912 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1987 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1913 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1988 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1914 | if (!batadv_compare_eth(node->addr, tt_response->src)) | 1989 | if (!batadv_compare_eth(node->addr, tt_response->src)) |
1915 | continue; | 1990 | continue; |
1916 | list_del(&node->list); | 1991 | list_del(&node->list); |
1917 | kfree(node); | 1992 | kfree(node); |
1918 | } | 1993 | } |
1919 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1994 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1920 | 1995 | ||
1921 | /* Recalculate the CRC for this orig_node and store it */ | 1996 | /* Recalculate the CRC for this orig_node and store it */ |
1922 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); | 1997 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
@@ -1950,22 +2025,22 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) | |||
1950 | { | 2025 | { |
1951 | struct batadv_tt_roam_node *node, *safe; | 2026 | struct batadv_tt_roam_node *node, *safe; |
1952 | 2027 | ||
1953 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2028 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1954 | 2029 | ||
1955 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { | 2030 | list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
1956 | list_del(&node->list); | 2031 | list_del(&node->list); |
1957 | kfree(node); | 2032 | kfree(node); |
1958 | } | 2033 | } |
1959 | 2034 | ||
1960 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2035 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
1961 | } | 2036 | } |
1962 | 2037 | ||
1963 | static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) | 2038 | static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) |
1964 | { | 2039 | { |
1965 | struct batadv_tt_roam_node *node, *safe; | 2040 | struct batadv_tt_roam_node *node, *safe; |
1966 | 2041 | ||
1967 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2042 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1968 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { | 2043 | list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
1969 | if (!batadv_has_timed_out(node->first_time, | 2044 | if (!batadv_has_timed_out(node->first_time, |
1970 | BATADV_ROAMING_MAX_TIME)) | 2045 | BATADV_ROAMING_MAX_TIME)) |
1971 | continue; | 2046 | continue; |
@@ -1973,7 +2048,7 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) | |||
1973 | list_del(&node->list); | 2048 | list_del(&node->list); |
1974 | kfree(node); | 2049 | kfree(node); |
1975 | } | 2050 | } |
1976 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2051 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
1977 | } | 2052 | } |
1978 | 2053 | ||
1979 | /* This function checks whether the client already reached the | 2054 | /* This function checks whether the client already reached the |
@@ -1988,11 +2063,11 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, | |||
1988 | struct batadv_tt_roam_node *tt_roam_node; | 2063 | struct batadv_tt_roam_node *tt_roam_node; |
1989 | bool ret = false; | 2064 | bool ret = false; |
1990 | 2065 | ||
1991 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2066 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1992 | /* The new tt_req will be issued only if I'm not waiting for a | 2067 | /* The new tt_req will be issued only if I'm not waiting for a |
1993 | * reply from the same orig_node yet | 2068 | * reply from the same orig_node yet |
1994 | */ | 2069 | */ |
1995 | list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) { | 2070 | list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) { |
1996 | if (!batadv_compare_eth(tt_roam_node->addr, client)) | 2071 | if (!batadv_compare_eth(tt_roam_node->addr, client)) |
1997 | continue; | 2072 | continue; |
1998 | 2073 | ||
@@ -2017,12 +2092,12 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, | |||
2017 | BATADV_ROAMING_MAX_COUNT - 1); | 2092 | BATADV_ROAMING_MAX_COUNT - 1); |
2018 | memcpy(tt_roam_node->addr, client, ETH_ALEN); | 2093 | memcpy(tt_roam_node->addr, client, ETH_ALEN); |
2019 | 2094 | ||
2020 | list_add(&tt_roam_node->list, &bat_priv->tt_roam_list); | 2095 | list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); |
2021 | ret = true; | 2096 | ret = true; |
2022 | } | 2097 | } |
2023 | 2098 | ||
2024 | unlock: | 2099 | unlock: |
2025 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2100 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
2026 | return ret; | 2101 | return ret; |
2027 | } | 2102 | } |
2028 | 2103 | ||
@@ -2086,13 +2161,15 @@ out: | |||
2086 | static void batadv_tt_purge(struct work_struct *work) | 2161 | static void batadv_tt_purge(struct work_struct *work) |
2087 | { | 2162 | { |
2088 | struct delayed_work *delayed_work; | 2163 | struct delayed_work *delayed_work; |
2164 | struct batadv_priv_tt *priv_tt; | ||
2089 | struct batadv_priv *bat_priv; | 2165 | struct batadv_priv *bat_priv; |
2090 | 2166 | ||
2091 | delayed_work = container_of(work, struct delayed_work, work); | 2167 | delayed_work = container_of(work, struct delayed_work, work); |
2092 | bat_priv = container_of(delayed_work, struct batadv_priv, tt_work); | 2168 | priv_tt = container_of(delayed_work, struct batadv_priv_tt, work); |
2169 | bat_priv = container_of(priv_tt, struct batadv_priv, tt); | ||
2093 | 2170 | ||
2094 | batadv_tt_local_purge(bat_priv); | 2171 | batadv_tt_local_purge(bat_priv); |
2095 | batadv_tt_global_roam_purge(bat_priv); | 2172 | batadv_tt_global_purge(bat_priv); |
2096 | batadv_tt_req_purge(bat_priv); | 2173 | batadv_tt_req_purge(bat_priv); |
2097 | batadv_tt_roam_purge(bat_priv); | 2174 | batadv_tt_roam_purge(bat_priv); |
2098 | 2175 | ||
@@ -2101,7 +2178,7 @@ static void batadv_tt_purge(struct work_struct *work) | |||
2101 | 2178 | ||
2102 | void batadv_tt_free(struct batadv_priv *bat_priv) | 2179 | void batadv_tt_free(struct batadv_priv *bat_priv) |
2103 | { | 2180 | { |
2104 | cancel_delayed_work_sync(&bat_priv->tt_work); | 2181 | cancel_delayed_work_sync(&bat_priv->tt.work); |
2105 | 2182 | ||
2106 | batadv_tt_local_table_free(bat_priv); | 2183 | batadv_tt_local_table_free(bat_priv); |
2107 | batadv_tt_global_table_free(bat_priv); | 2184 | batadv_tt_global_table_free(bat_priv); |
@@ -2109,7 +2186,7 @@ void batadv_tt_free(struct batadv_priv *bat_priv) | |||
2109 | batadv_tt_changes_list_free(bat_priv); | 2186 | batadv_tt_changes_list_free(bat_priv); |
2110 | batadv_tt_roam_list_free(bat_priv); | 2187 | batadv_tt_roam_list_free(bat_priv); |
2111 | 2188 | ||
2112 | kfree(bat_priv->tt_buff); | 2189 | kfree(bat_priv->tt.last_changeset); |
2113 | } | 2190 | } |
2114 | 2191 | ||
2115 | /* This function will enable or disable the specified flags for all the entries | 2192 | /* This function will enable or disable the specified flags for all the entries |
@@ -2153,7 +2230,7 @@ out: | |||
2153 | /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ | 2230 | /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ |
2154 | static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | 2231 | static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) |
2155 | { | 2232 | { |
2156 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 2233 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
2157 | struct batadv_tt_common_entry *tt_common; | 2234 | struct batadv_tt_common_entry *tt_common; |
2158 | struct batadv_tt_local_entry *tt_local; | 2235 | struct batadv_tt_local_entry *tt_local; |
2159 | struct hlist_node *node, *node_tmp; | 2236 | struct hlist_node *node, *node_tmp; |
@@ -2178,7 +2255,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
2178 | "Deleting local tt entry (%pM): pending\n", | 2255 | "Deleting local tt entry (%pM): pending\n", |
2179 | tt_common->addr); | 2256 | tt_common->addr); |
2180 | 2257 | ||
2181 | atomic_dec(&bat_priv->num_local_tt); | 2258 | atomic_dec(&bat_priv->tt.local_entry_num); |
2182 | hlist_del_rcu(node); | 2259 | hlist_del_rcu(node); |
2183 | tt_local = container_of(tt_common, | 2260 | tt_local = container_of(tt_common, |
2184 | struct batadv_tt_local_entry, | 2261 | struct batadv_tt_local_entry, |
@@ -2196,26 +2273,26 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, | |||
2196 | { | 2273 | { |
2197 | uint16_t changed_num = 0; | 2274 | uint16_t changed_num = 0; |
2198 | 2275 | ||
2199 | if (atomic_read(&bat_priv->tt_local_changes) < 1) | 2276 | if (atomic_read(&bat_priv->tt.local_changes) < 1) |
2200 | return -ENOENT; | 2277 | return -ENOENT; |
2201 | 2278 | ||
2202 | changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash, | 2279 | changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, |
2203 | BATADV_TT_CLIENT_NEW, false); | 2280 | BATADV_TT_CLIENT_NEW, false); |
2204 | 2281 | ||
2205 | /* all reset entries have to be counted as local entries */ | 2282 | /* all reset entries have to be counted as local entries */ |
2206 | atomic_add(changed_num, &bat_priv->num_local_tt); | 2283 | atomic_add(changed_num, &bat_priv->tt.local_entry_num); |
2207 | batadv_tt_local_purge_pending_clients(bat_priv); | 2284 | batadv_tt_local_purge_pending_clients(bat_priv); |
2208 | bat_priv->tt_crc = batadv_tt_local_crc(bat_priv); | 2285 | bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv); |
2209 | 2286 | ||
2210 | /* Increment the TTVN only once per OGM interval */ | 2287 | /* Increment the TTVN only once per OGM interval */ |
2211 | atomic_inc(&bat_priv->ttvn); | 2288 | atomic_inc(&bat_priv->tt.vn); |
2212 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 2289 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
2213 | "Local changes committed, updating to ttvn %u\n", | 2290 | "Local changes committed, updating to ttvn %u\n", |
2214 | (uint8_t)atomic_read(&bat_priv->ttvn)); | 2291 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
2215 | bat_priv->tt_poss_change = false; | 2292 | bat_priv->tt.poss_change = false; |
2216 | 2293 | ||
2217 | /* reset the sending counter */ | 2294 | /* reset the sending counter */ |
2218 | atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); | 2295 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
2219 | 2296 | ||
2220 | return batadv_tt_changes_fill_buff(bat_priv, packet_buff, | 2297 | return batadv_tt_changes_fill_buff(bat_priv, packet_buff, |
2221 | packet_buff_len, packet_min_len); | 2298 | packet_buff_len, packet_min_len); |
@@ -2235,7 +2312,7 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv, | |||
2235 | 2312 | ||
2236 | /* if the changes have been sent often enough */ | 2313 | /* if the changes have been sent often enough */ |
2237 | if ((tt_num_changes < 0) && | 2314 | if ((tt_num_changes < 0) && |
2238 | (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) { | 2315 | (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { |
2239 | batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, | 2316 | batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, |
2240 | packet_min_len, packet_min_len); | 2317 | packet_min_len, packet_min_len); |
2241 | tt_num_changes = 0; | 2318 | tt_num_changes = 0; |
@@ -2366,3 +2443,22 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | |||
2366 | out: | 2443 | out: |
2367 | return ret; | 2444 | return ret; |
2368 | } | 2445 | } |
2446 | |||
2447 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | ||
2448 | struct batadv_orig_node *orig_node, | ||
2449 | const unsigned char *addr) | ||
2450 | { | ||
2451 | bool ret = false; | ||
2452 | |||
2453 | if (!batadv_tt_global_add(bat_priv, orig_node, addr, | ||
2454 | BATADV_TT_CLIENT_TEMP, | ||
2455 | atomic_read(&orig_node->last_ttvn))) | ||
2456 | goto out; | ||
2457 | |||
2458 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
2459 | "Added temporary global client (addr: %pM orig: %pM)\n", | ||
2460 | addr, orig_node->orig); | ||
2461 | ret = true; | ||
2462 | out: | ||
2463 | return ret; | ||
2464 | } | ||