Commit 058d0e26989e3da2fa031f551235f6ff1e0bc27c
Committed by
Marek Lindner
1 parent
c8c991bf20
Exists in
master
and in
4 other branches
batman-adv: keep local table consistency for further TT_RESPONSE
To keep transtable consistency among all the nodes, an originator must not send not yet announced clients within a full table TT_RESPONSE. Instead, deleted client have to be kept in the table in order to be sent within an immediate TT_RESPONSE. In this way all the nodes in the network will always provide the same response for the same request. All the modification are committed at the next ttvn increment event. Signed-off-by: Antonio Quartulli <ordex@autistici.org> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Showing 4 changed files with 125 additions and 30 deletions Side-by-side Diff
net/batman-adv/packet.h
net/batman-adv/send.c
... | ... | @@ -309,10 +309,8 @@ |
309 | 309 | if (hard_iface == primary_if) { |
310 | 310 | /* if at least one change happened */ |
311 | 311 | if (atomic_read(&bat_priv->tt_local_changes) > 0) { |
312 | + tt_commit_changes(bat_priv); | |
312 | 313 | prepare_packet_buffer(bat_priv, hard_iface); |
313 | - /* Increment the TTVN only once per OGM interval */ | |
314 | - atomic_inc(&bat_priv->ttvn); | |
315 | - bat_priv->tt_poss_change = false; | |
316 | 314 | } |
317 | 315 | |
318 | 316 | /* if the changes have been sent enough times */ |
net/batman-adv/translation-table.c
... | ... | @@ -215,11 +215,14 @@ |
215 | 215 | |
216 | 216 | tt_local_event(bat_priv, addr, tt_local_entry->flags); |
217 | 217 | |
218 | + /* The local entry has to be marked as NEW to avoid to send it in | |
219 | + * a full table response going out before the next ttvn increment | |
220 | + * (consistency check) */ | |
221 | + tt_local_entry->flags |= TT_CLIENT_NEW; | |
222 | + | |
218 | 223 | hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, |
219 | 224 | tt_local_entry, &tt_local_entry->hash_entry); |
220 | 225 | |
221 | - atomic_inc(&bat_priv->num_local_tt); | |
222 | - | |
223 | 226 | /* remove address from global hash if present */ |
224 | 227 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
225 | 228 | |
226 | 229 | |
227 | 230 | |
... | ... | @@ -358,19 +361,17 @@ |
358 | 361 | return ret; |
359 | 362 | } |
360 | 363 | |
361 | -static void tt_local_del(struct bat_priv *bat_priv, | |
362 | - struct tt_local_entry *tt_local_entry, | |
363 | - const char *message) | |
364 | +static void tt_local_set_pending(struct bat_priv *bat_priv, | |
365 | + struct tt_local_entry *tt_local_entry, | |
366 | + uint16_t flags) | |
364 | 367 | { |
365 | - bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry (%pM): %s\n", | |
366 | - tt_local_entry->addr, message); | |
368 | + tt_local_event(bat_priv, tt_local_entry->addr, | |
369 | + tt_local_entry->flags | flags); | |
367 | 370 | |
368 | - atomic_dec(&bat_priv->num_local_tt); | |
369 | - | |
370 | - hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig, | |
371 | - tt_local_entry->addr); | |
372 | - | |
373 | - tt_local_entry_free_ref(tt_local_entry); | |
371 | + /* The local client has to be merked as "pending to be removed" but has | |
372 | + * to be kept in the table in order to send it in an full tables | |
373 | + * response issued before the net ttvn increment (consistency check) */ | |
374 | + tt_local_entry->flags |= TT_CLIENT_PENDING; | |
374 | 375 | } |
375 | 376 | |
376 | 377 | void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, |
377 | 378 | |
... | ... | @@ -379,14 +380,14 @@ |
379 | 380 | struct tt_local_entry *tt_local_entry = NULL; |
380 | 381 | |
381 | 382 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
382 | - | |
383 | 383 | if (!tt_local_entry) |
384 | 384 | goto out; |
385 | 385 | |
386 | - tt_local_event(bat_priv, tt_local_entry->addr, | |
387 | - tt_local_entry->flags | TT_CLIENT_DEL | | |
388 | - (roaming ? TT_CLIENT_ROAM : NO_FLAGS)); | |
389 | - tt_local_del(bat_priv, tt_local_entry, message); | |
386 | + tt_local_set_pending(bat_priv, tt_local_entry, TT_CLIENT_DEL | | |
387 | + (roaming ? TT_CLIENT_ROAM : NO_FLAGS)); | |
388 | + | |
389 | + bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: " | |
390 | + "%s\n", tt_local_entry->addr, message); | |
390 | 391 | out: |
391 | 392 | if (tt_local_entry) |
392 | 393 | tt_local_entry_free_ref(tt_local_entry); |
393 | 394 | |
394 | 395 | |
... | ... | @@ -411,18 +412,19 @@ |
411 | 412 | if (tt_local_entry->flags & TT_CLIENT_NOPURGE) |
412 | 413 | continue; |
413 | 414 | |
415 | + /* entry already marked for deletion */ | |
416 | + if (tt_local_entry->flags & TT_CLIENT_PENDING) | |
417 | + continue; | |
418 | + | |
414 | 419 | if (!is_out_of_time(tt_local_entry->last_seen, |
415 | 420 | TT_LOCAL_TIMEOUT * 1000)) |
416 | 421 | continue; |
417 | 422 | |
418 | - tt_local_event(bat_priv, tt_local_entry->addr, | |
419 | - tt_local_entry->flags | TT_CLIENT_DEL); | |
420 | - atomic_dec(&bat_priv->num_local_tt); | |
421 | - bat_dbg(DBG_TT, bat_priv, "Deleting local " | |
422 | - "tt entry (%pM): timed out\n", | |
423 | + tt_local_set_pending(bat_priv, tt_local_entry, | |
424 | + TT_CLIENT_DEL); | |
425 | + bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) " | |
426 | + "pending to be removed: timed out\n", | |
423 | 427 | tt_local_entry->addr); |
424 | - hlist_del_rcu(node); | |
425 | - tt_local_entry_free_ref(tt_local_entry); | |
426 | 428 | } |
427 | 429 | spin_unlock_bh(list_lock); |
428 | 430 | } |
... | ... | @@ -846,6 +848,10 @@ |
846 | 848 | rcu_read_lock(); |
847 | 849 | hlist_for_each_entry_rcu(tt_local_entry, node, |
848 | 850 | head, hash_entry) { |
851 | + /* not yet committed clients have not to be taken into | |
852 | + * account while computing the CRC */ | |
853 | + if (tt_local_entry->flags & TT_CLIENT_NEW) | |
854 | + continue; | |
849 | 855 | total_one = 0; |
850 | 856 | for (j = 0; j < ETH_ALEN; j++) |
851 | 857 | total_one = crc16_byte(total_one, |
... | ... | @@ -935,6 +941,16 @@ |
935 | 941 | return tt_req_node; |
936 | 942 | } |
937 | 943 | |
944 | +/* data_ptr is useless here, but has to be kept to respect the prototype */ | |
945 | +static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) | |
946 | +{ | |
947 | + const struct tt_local_entry *tt_local_entry = entry_ptr; | |
948 | + | |
949 | + if (tt_local_entry->flags & TT_CLIENT_NEW) | |
950 | + return 0; | |
951 | + return 1; | |
952 | +} | |
953 | + | |
938 | 954 | static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) |
939 | 955 | { |
940 | 956 | const struct tt_global_entry *tt_global_entry = entry_ptr; |
... | ... | @@ -1275,7 +1291,8 @@ |
1275 | 1291 | |
1276 | 1292 | skb = tt_response_fill_table(tt_len, ttvn, |
1277 | 1293 | bat_priv->tt_local_hash, |
1278 | - primary_if, NULL, NULL); | |
1294 | + primary_if, tt_local_valid_entry, | |
1295 | + NULL); | |
1279 | 1296 | if (!skb) |
1280 | 1297 | goto out; |
1281 | 1298 | |
... | ... | @@ -1400,6 +1417,10 @@ |
1400 | 1417 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
1401 | 1418 | if (!tt_local_entry) |
1402 | 1419 | goto out; |
1420 | + /* Check if the client has been logically deleted (but is kept for | |
1421 | + * consistency purpose) */ | |
1422 | + if (tt_local_entry->flags & TT_CLIENT_PENDING) | |
1423 | + goto out; | |
1403 | 1424 | ret = true; |
1404 | 1425 | out: |
1405 | 1426 | if (tt_local_entry) |
... | ... | @@ -1619,5 +1640,78 @@ |
1619 | 1640 | tt_roam_list_free(bat_priv); |
1620 | 1641 | |
1621 | 1642 | kfree(bat_priv->tt_buff); |
1643 | +} | |
1644 | + | |
1645 | +/* This function will reset the specified flags from all the entries in | |
1646 | + * the given hash table and will increment num_local_tt for each involved | |
1647 | + * entry */ | |
1648 | +static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags) | |
1649 | +{ | |
1650 | + int i; | |
1651 | + struct hashtable_t *hash = bat_priv->tt_local_hash; | |
1652 | + struct hlist_head *head; | |
1653 | + struct hlist_node *node; | |
1654 | + struct tt_local_entry *tt_local_entry; | |
1655 | + | |
1656 | + if (!hash) | |
1657 | + return; | |
1658 | + | |
1659 | + for (i = 0; i < hash->size; i++) { | |
1660 | + head = &hash->table[i]; | |
1661 | + | |
1662 | + rcu_read_lock(); | |
1663 | + hlist_for_each_entry_rcu(tt_local_entry, node, | |
1664 | + head, hash_entry) { | |
1665 | + tt_local_entry->flags &= ~flags; | |
1666 | + atomic_inc(&bat_priv->num_local_tt); | |
1667 | + } | |
1668 | + rcu_read_unlock(); | |
1669 | + } | |
1670 | + | |
1671 | +} | |
1672 | + | |
1673 | +/* Purge out all the tt local entries marked with TT_CLIENT_PENDING */ | |
1674 | +static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) | |
1675 | +{ | |
1676 | + struct hashtable_t *hash = bat_priv->tt_local_hash; | |
1677 | + struct tt_local_entry *tt_local_entry; | |
1678 | + struct hlist_node *node, *node_tmp; | |
1679 | + struct hlist_head *head; | |
1680 | + spinlock_t *list_lock; /* protects write access to the hash lists */ | |
1681 | + int i; | |
1682 | + | |
1683 | + if (!hash) | |
1684 | + return; | |
1685 | + | |
1686 | + for (i = 0; i < hash->size; i++) { | |
1687 | + head = &hash->table[i]; | |
1688 | + list_lock = &hash->list_locks[i]; | |
1689 | + | |
1690 | + spin_lock_bh(list_lock); | |
1691 | + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, | |
1692 | + head, hash_entry) { | |
1693 | + if (!(tt_local_entry->flags & TT_CLIENT_PENDING)) | |
1694 | + continue; | |
1695 | + | |
1696 | + bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry " | |
1697 | + "(%pM): pending\n", tt_local_entry->addr); | |
1698 | + | |
1699 | + atomic_dec(&bat_priv->num_local_tt); | |
1700 | + hlist_del_rcu(node); | |
1701 | + tt_local_entry_free_ref(tt_local_entry); | |
1702 | + } | |
1703 | + spin_unlock_bh(list_lock); | |
1704 | + } | |
1705 | + | |
1706 | +} | |
1707 | + | |
1708 | +void tt_commit_changes(struct bat_priv *bat_priv) | |
1709 | +{ | |
1710 | + tt_local_reset_flags(bat_priv, TT_CLIENT_NEW); | |
1711 | + tt_local_purge_pending_clients(bat_priv); | |
1712 | + | |
1713 | + /* Increment the TTVN only once per OGM interval */ | |
1714 | + atomic_inc(&bat_priv->ttvn); | |
1715 | + bat_priv->tt_poss_change = false; | |
1622 | 1716 | } |
net/batman-adv/translation-table.h