aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAntonio Quartulli <antonio@open-mesh.com>2013-07-30 16:16:25 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-19 17:25:12 -0400
commit7ea7b4a142758deaf46c1af0ca9ceca6dd55138b (patch)
tree02803d96cc171936e7c973f389ec19f7e0295a97 /net
parenta70a9aa990bdf24039cb4167993bcc5a0f9cbb18 (diff)
batman-adv: make the TT CRC logic VLAN specific
This change allows nodes to handle the TT table on a per-VLAN basis. This is needed because nodes may have to store only some of the global entries advertised by another node. In this scenario such nodes would re-create only a partial global table and would not be able to compute a correct CRC anymore. This patch splits the logic and introduces one CRC per VLAN. In this way a node fetching only some entries belonging to some VLANs is still able to compute the needed CRCs and still check the table correctness. With this patch the shape of the TVLV-TT is changed too because now a node needs to advertise all the CRCs of all the VLANs that it is wired to. The debug output of the local Translation Table now shows the CRC along with each entry since there is not a common value for the entire table anymore. Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/originator.c101
-rw-r--r--net/batman-adv/originator.h7
-rw-r--r--net/batman-adv/packet.h18
-rw-r--r--net/batman-adv/translation-table.c720
-rw-r--r--net/batman-adv/types.h41
5 files changed, 730 insertions, 157 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 867778e8184d..7a499dad53d3 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -44,6 +44,88 @@ static int batadv_compare_orig(const struct hlist_node *node, const void *data2)
44 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); 44 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
45} 45}
46 46
47/**
48 * batadv_orig_node_vlan_get - get an orig_node_vlan object
49 * @orig_node: the originator serving the VLAN
50 * @vid: the VLAN identifier
51 *
52 * Returns the vlan object identified by vid and belonging to orig_node or NULL
53 * if it does not exist.
54 */
55struct batadv_orig_node_vlan *
56batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
57 unsigned short vid)
58{
59 struct batadv_orig_node_vlan *vlan = NULL, *tmp;
60
61 rcu_read_lock();
62 list_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
63 if (tmp->vid != vid)
64 continue;
65
66 if (!atomic_inc_not_zero(&tmp->refcount))
67 continue;
68
69 vlan = tmp;
70
71 break;
72 }
73 rcu_read_unlock();
74
75 return vlan;
76}
77
78/**
79 * batadv_orig_node_vlan_new - search and possibly create an orig_node_vlan
80 * object
81 * @orig_node: the originator serving the VLAN
82 * @vid: the VLAN identifier
83 *
84 * Returns NULL in case of failure or the vlan object identified by vid and
85 * belonging to orig_node otherwise. The object is created and added to the list
86 * if it does not exist.
87 *
88 * The object is returned with refcounter increased by 1.
89 */
90struct batadv_orig_node_vlan *
91batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
92 unsigned short vid)
93{
94 struct batadv_orig_node_vlan *vlan;
95
96 spin_lock_bh(&orig_node->vlan_list_lock);
97
98 /* first look if an object for this vid already exists */
99 vlan = batadv_orig_node_vlan_get(orig_node, vid);
100 if (vlan)
101 goto out;
102
103 vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
104 if (!vlan)
105 goto out;
106
107 atomic_set(&vlan->refcount, 2);
108 vlan->vid = vid;
109
110 list_add_rcu(&vlan->list, &orig_node->vlan_list);
111
112out:
113 spin_unlock_bh(&orig_node->vlan_list_lock);
114
115 return vlan;
116}
117
118/**
119 * batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly free
120 * the originator-vlan object
121 * @orig_vlan: the originator-vlan object to release
122 */
123void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan)
124{
125 if (atomic_dec_and_test(&orig_vlan->refcount))
126 kfree_rcu(orig_vlan, rcu);
127}
128
47int batadv_originator_init(struct batadv_priv *bat_priv) 129int batadv_originator_init(struct batadv_priv *bat_priv)
48{ 130{
49 if (bat_priv->orig_hash) 131 if (bat_priv->orig_hash)
@@ -218,6 +300,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
218 const uint8_t *addr) 300 const uint8_t *addr)
219{ 301{
220 struct batadv_orig_node *orig_node; 302 struct batadv_orig_node *orig_node;
303 struct batadv_orig_node_vlan *vlan;
221 int size, i; 304 int size, i;
222 int hash_added; 305 int hash_added;
223 unsigned long reset_time; 306 unsigned long reset_time;
@@ -235,11 +318,13 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
235 318
236 INIT_HLIST_HEAD(&orig_node->neigh_list); 319 INIT_HLIST_HEAD(&orig_node->neigh_list);
237 INIT_LIST_HEAD(&orig_node->bond_list); 320 INIT_LIST_HEAD(&orig_node->bond_list);
321 INIT_LIST_HEAD(&orig_node->vlan_list);
238 spin_lock_init(&orig_node->ogm_cnt_lock); 322 spin_lock_init(&orig_node->ogm_cnt_lock);
239 spin_lock_init(&orig_node->bcast_seqno_lock); 323 spin_lock_init(&orig_node->bcast_seqno_lock);
240 spin_lock_init(&orig_node->neigh_list_lock); 324 spin_lock_init(&orig_node->neigh_list_lock);
241 spin_lock_init(&orig_node->tt_buff_lock); 325 spin_lock_init(&orig_node->tt_buff_lock);
242 spin_lock_init(&orig_node->tt_lock); 326 spin_lock_init(&orig_node->tt_lock);
327 spin_lock_init(&orig_node->vlan_list_lock);
243 328
244 batadv_nc_init_orig(orig_node); 329 batadv_nc_init_orig(orig_node);
245 330
@@ -251,22 +336,30 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
251 memcpy(orig_node->orig, addr, ETH_ALEN); 336 memcpy(orig_node->orig, addr, ETH_ALEN);
252 batadv_dat_init_orig_node_addr(orig_node); 337 batadv_dat_init_orig_node_addr(orig_node);
253 orig_node->router = NULL; 338 orig_node->router = NULL;
254 orig_node->tt_crc = 0;
255 atomic_set(&orig_node->last_ttvn, 0); 339 atomic_set(&orig_node->last_ttvn, 0);
256 orig_node->tt_buff = NULL; 340 orig_node->tt_buff = NULL;
257 orig_node->tt_buff_len = 0; 341 orig_node->tt_buff_len = 0;
258 atomic_set(&orig_node->tt_size, 0);
259 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 342 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
260 orig_node->bcast_seqno_reset = reset_time; 343 orig_node->bcast_seqno_reset = reset_time;
261 orig_node->batman_seqno_reset = reset_time; 344 orig_node->batman_seqno_reset = reset_time;
262 345
263 atomic_set(&orig_node->bond_candidates, 0); 346 atomic_set(&orig_node->bond_candidates, 0);
264 347
348 /* create a vlan object for the "untagged" LAN */
349 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
350 if (!vlan)
351 goto free_orig_node;
352 /* batadv_orig_node_vlan_new() increases the refcounter.
353 * Immediately release vlan since it is not needed anymore in this
354 * context
355 */
356 batadv_orig_node_vlan_free_ref(vlan);
357
265 size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS; 358 size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
266 359
267 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); 360 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
268 if (!orig_node->bcast_own) 361 if (!orig_node->bcast_own)
269 goto free_orig_node; 362 goto free_vlan;
270 363
271 size = bat_priv->num_ifaces * sizeof(uint8_t); 364 size = bat_priv->num_ifaces * sizeof(uint8_t);
272 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); 365 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
@@ -291,6 +384,8 @@ free_bcast_own_sum:
291 kfree(orig_node->bcast_own_sum); 384 kfree(orig_node->bcast_own_sum);
292free_bcast_own: 385free_bcast_own:
293 kfree(orig_node->bcast_own); 386 kfree(orig_node->bcast_own);
387free_vlan:
388 batadv_orig_node_vlan_free_ref(vlan);
294free_orig_node: 389free_orig_node:
295 kfree(orig_node); 390 kfree(orig_node);
296 return NULL; 391 return NULL;
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 7887b84a9af4..cc6d686cfe6d 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -40,6 +40,13 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
40 int max_if_num); 40 int max_if_num);
41int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, 41int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
42 int max_if_num); 42 int max_if_num);
43struct batadv_orig_node_vlan *
44batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
45 unsigned short vid);
46struct batadv_orig_node_vlan *
47batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
48 unsigned short vid);
49void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan);
43 50
44 51
45/* hashfunction to choose an entry in a hash table of given size 52/* hashfunction to choose an entry in a hash table of given size
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 6311642f3ee8..9fbcaacc345a 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -391,14 +391,26 @@ struct batadv_tvlv_gateway_data {
391 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container 391 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
392 * @flags: translation table flags (see batadv_tt_data_flags) 392 * @flags: translation table flags (see batadv_tt_data_flags)
393 * @ttvn: translation table version number 393 * @ttvn: translation table version number
394 * @reserved: field reserved for future use 394 * @vlan_num: number of announced VLANs. In the TVLV this struct is followed by
395 * @crc: crc32 checksum of the local translation table 395 * one batadv_tvlv_tt_vlan_data object per announced vlan
396 */ 396 */
397struct batadv_tvlv_tt_data { 397struct batadv_tvlv_tt_data {
398 uint8_t flags; 398 uint8_t flags;
399 uint8_t ttvn; 399 uint8_t ttvn;
400 __be16 num_vlan;
401};
402
403/**
404 * struct batadv_tvlv_tt_vlan_data - vlan specific tt data propagated through
405 * the tt tvlv container
406 * @crc: crc32 checksum of the entries belonging to this vlan
407 * @vid: vlan identifier
408 * @reserved: unused, useful for alignment purposes
409 */
410struct batadv_tvlv_tt_vlan_data {
411 __be32 crc;
412 __be16 vid;
400 uint16_t reserved; 413 uint16_t reserved;
401 __be32 crc;
402}; 414};
403 415
404/** 416/**
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 00f4faa69c07..41a8387c5ef8 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -208,13 +208,107 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
208 kfree(orig_entry); 208 kfree(orig_entry);
209} 209}
210 210
211/**
212 * batadv_tt_local_size_mod - change the size by v of the local table identified
213 * by vid
214 * @bat_priv: the bat priv with all the soft interface information
215 * @vid: the VLAN identifier of the sub-table to change
216 * @v: the amount to sum to the local table size
217 */
218static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
219 unsigned short vid, int v)
220{
221 struct batadv_softif_vlan *vlan;
222
223 vlan = batadv_softif_vlan_get(bat_priv, vid);
224 if (!vlan)
225 return;
226
227 atomic_add(v, &vlan->tt.num_entries);
228
229 batadv_softif_vlan_free_ref(vlan);
230}
231
232/**
233 * batadv_tt_local_size_inc - increase by one the local table size for the given
234 * vid
235 * @bat_priv: the bat priv with all the soft interface information
236 * @vid: the VLAN identifier
237 */
238static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
239 unsigned short vid)
240{
241 batadv_tt_local_size_mod(bat_priv, vid, 1);
242}
243
244/**
245 * batadv_tt_local_size_dec - decrease by one the local table size for the given
246 * vid
247 * @bat_priv: the bat priv with all the soft interface information
248 * @vid: the VLAN identifier
249 */
250static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
251 unsigned short vid)
252{
253 batadv_tt_local_size_mod(bat_priv, vid, -1);
254}
255
256/**
257 * batadv_tt_global_size_mod - change the size by v of the local table
258 * identified by vid
259 * @bat_priv: the bat priv with all the soft interface information
260 * @vid: the VLAN identifier
261 * @v: the amount to sum to the global table size
262 */
263static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
264 unsigned short vid, int v)
265{
266 struct batadv_orig_node_vlan *vlan;
267
268 vlan = batadv_orig_node_vlan_new(orig_node, vid);
269 if (!vlan)
270 return;
271
272 if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
273 spin_lock_bh(&orig_node->vlan_list_lock);
274 list_del_rcu(&vlan->list);
275 spin_unlock_bh(&orig_node->vlan_list_lock);
276 batadv_orig_node_vlan_free_ref(vlan);
277 }
278
279 batadv_orig_node_vlan_free_ref(vlan);
280}
281
282/**
283 * batadv_tt_global_size_inc - increase by one the global table size for the
284 * given vid
285 * @orig_node: the originator which global table size has to be decreased
286 * @vid: the vlan identifier
287 */
288static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
289 unsigned short vid)
290{
291 batadv_tt_global_size_mod(orig_node, vid, 1);
292}
293
294/**
295 * batadv_tt_global_size_dec - decrease by one the global table size for the
296 * given vid
297 * @orig_node: the originator which global table size has to be decreased
298 * @vid: the vlan identifier
299 */
300static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
301 unsigned short vid)
302{
303 batadv_tt_global_size_mod(orig_node, vid, -1);
304}
305
211static void 306static void
212batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) 307batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
213{ 308{
214 if (!atomic_dec_and_test(&orig_entry->refcount)) 309 if (!atomic_dec_and_test(&orig_entry->refcount))
215 return; 310 return;
216 /* to avoid race conditions, immediately decrease the tt counter */ 311
217 atomic_dec(&orig_entry->orig_node->tt_size);
218 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); 312 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
219} 313}
220 314
@@ -464,6 +558,149 @@ out:
464} 558}
465 559
466/** 560/**
561 * batadv_tt_prepare_tvlv_global_data - prepare the TVLV TT header to send
562 * within a TT Response directed to another node
563 * @orig_node: originator for which the TT data has to be prepared
564 * @tt_data: uninitialised pointer to the address of the TVLV buffer
565 * @tt_change: uninitialised pointer to the address of the area where the TT
566 * changed can be stored
567 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
568 * function reserves the amount of space needed to send the entire global TT
569 * table. In case of success the value is updated with the real amount of
570 * reserved bytes
571
572 * Allocate the needed amount of memory for the entire TT TVLV and write its
573 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
574 * objects, one per active VLAN served by the originator node.
575 *
576 * Return the size of the allocated buffer or 0 in case of failure.
577 */
578static uint16_t
579batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
580 struct batadv_tvlv_tt_data **tt_data,
581 struct batadv_tvlv_tt_change **tt_change,
582 int32_t *tt_len)
583{
584 uint16_t num_vlan = 0, num_entries = 0, change_offset, tvlv_len;
585 struct batadv_tvlv_tt_vlan_data *tt_vlan;
586 struct batadv_orig_node_vlan *vlan;
587 uint8_t *tt_change_ptr;
588
589 rcu_read_lock();
590 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
591 num_vlan++;
592 num_entries += atomic_read(&vlan->tt.num_entries);
593 }
594
595 change_offset = sizeof(**tt_data);
596 change_offset += num_vlan * sizeof(*tt_vlan);
597
598 /* if tt_len is negative, allocate the space needed by the full table */
599 if (*tt_len < 0)
600 *tt_len = batadv_tt_len(num_entries);
601
602 tvlv_len = *tt_len;
603 tvlv_len += change_offset;
604
605 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
606 if (!*tt_data) {
607 *tt_len = 0;
608 goto out;
609 }
610
611 (*tt_data)->flags = BATADV_NO_FLAGS;
612 (*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
613 (*tt_data)->num_vlan = htons(num_vlan);
614
615 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
616 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
617 tt_vlan->vid = htons(vlan->vid);
618 tt_vlan->crc = htonl(vlan->tt.crc);
619
620 tt_vlan++;
621 }
622
623 tt_change_ptr = (uint8_t *)*tt_data + change_offset;
624 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
625
626out:
627 rcu_read_unlock();
628 return tvlv_len;
629}
630
631/**
632 * batadv_tt_prepare_tvlv_local_data - allocate and prepare the TT TVLV for this
633 * node
634 * @bat_priv: the bat priv with all the soft interface information
635 * @tt_data: uninitialised pointer to the address of the TVLV buffer
636 * @tt_change: uninitialised pointer to the address of the area where the TT
637 * changes can be stored
638 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
639 * function reserves the amount of space needed to send the entire local TT
640 * table. In case of success the value is updated with the real amount of
641 * reserved bytes
642 *
643 * Allocate the needed amount of memory for the entire TT TVLV and write its
644 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
645 * objects, one per active VLAN.
646 *
647 * Return the size of the allocated buffer or 0 in case of failure.
648 */
649static uint16_t
650batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
651 struct batadv_tvlv_tt_data **tt_data,
652 struct batadv_tvlv_tt_change **tt_change,
653 int32_t *tt_len)
654{
655 struct batadv_tvlv_tt_vlan_data *tt_vlan;
656 struct batadv_softif_vlan *vlan;
657 uint16_t num_vlan = 0, num_entries = 0, tvlv_len;
658 uint8_t *tt_change_ptr;
659 int change_offset;
660
661 rcu_read_lock();
662 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
663 num_vlan++;
664 num_entries += atomic_read(&vlan->tt.num_entries);
665 }
666
667 change_offset = sizeof(**tt_data);
668 change_offset += num_vlan * sizeof(*tt_vlan);
669
670 /* if tt_len is negative, allocate the space needed by the full table */
671 if (*tt_len < 0)
672 *tt_len = batadv_tt_len(num_entries);
673
674 tvlv_len = *tt_len;
675 tvlv_len += change_offset;
676
677 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
678 if (!*tt_data) {
679 tvlv_len = 0;
680 goto out;
681 }
682
683 (*tt_data)->flags = BATADV_NO_FLAGS;
684 (*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
685 (*tt_data)->num_vlan = htons(num_vlan);
686
687 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
688 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
689 tt_vlan->vid = htons(vlan->vid);
690 tt_vlan->crc = htonl(vlan->tt.crc);
691
692 tt_vlan++;
693 }
694
695 tt_change_ptr = (uint8_t *)*tt_data + change_offset;
696 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
697
698out:
699 rcu_read_unlock();
700 return tvlv_len;
701}
702
703/**
467 * batadv_tt_tvlv_container_update - update the translation table tvlv container 704 * batadv_tt_tvlv_container_update - update the translation table tvlv container
468 * after local tt changes have been committed 705 * after local tt changes have been committed
469 * @bat_priv: the bat priv with all the soft interface information 706 * @bat_priv: the bat priv with all the soft interface information
@@ -473,10 +710,12 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
473 struct batadv_tt_change_node *entry, *safe; 710 struct batadv_tt_change_node *entry, *safe;
474 struct batadv_tvlv_tt_data *tt_data; 711 struct batadv_tvlv_tt_data *tt_data;
475 struct batadv_tvlv_tt_change *tt_change; 712 struct batadv_tvlv_tt_change *tt_change;
476 int tt_diff_len = 0, tt_change_len = 0; 713 int tt_diff_len, tt_change_len = 0;
477 int tt_diff_entries_num = 0, tt_diff_entries_count = 0; 714 int tt_diff_entries_num = 0, tt_diff_entries_count = 0;
715 uint16_t tvlv_len;
478 716
479 tt_diff_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); 717 tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
718 tt_diff_len = batadv_tt_len(tt_diff_entries_num);
480 719
481 /* if we have too many changes for one packet don't send any 720 /* if we have too many changes for one packet don't send any
482 * and wait for the tt table request which will be fragmented 721 * and wait for the tt table request which will be fragmented
@@ -484,24 +723,19 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
484 if (tt_diff_len > bat_priv->soft_iface->mtu) 723 if (tt_diff_len > bat_priv->soft_iface->mtu)
485 tt_diff_len = 0; 724 tt_diff_len = 0;
486 725
487 tt_data = kzalloc(sizeof(*tt_data) + tt_diff_len, GFP_ATOMIC); 726 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
488 if (!tt_data) 727 &tt_change, &tt_diff_len);
728 if (!tvlv_len)
489 return; 729 return;
490 730
491 tt_data->flags = BATADV_TT_OGM_DIFF; 731 tt_data->flags = BATADV_TT_OGM_DIFF;
492 tt_data->ttvn = atomic_read(&bat_priv->tt.vn);
493 tt_data->crc = htonl(bat_priv->tt.local_crc);
494 732
495 if (tt_diff_len == 0) 733 if (tt_diff_len == 0)
496 goto container_register; 734 goto container_register;
497 735
498 tt_diff_entries_num = batadv_tt_entries(tt_diff_len);
499
500 spin_lock_bh(&bat_priv->tt.changes_list_lock); 736 spin_lock_bh(&bat_priv->tt.changes_list_lock);
501 atomic_set(&bat_priv->tt.local_changes, 0); 737 atomic_set(&bat_priv->tt.local_changes, 0);
502 738
503 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
504
505 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, 739 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
506 list) { 740 list) {
507 if (tt_diff_entries_count < tt_diff_entries_num) { 741 if (tt_diff_entries_count < tt_diff_entries_num) {
@@ -537,7 +771,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
537 771
538container_register: 772container_register:
539 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data, 773 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
540 sizeof(*tt_data) + tt_change_len); 774 tvlv_len);
541 kfree(tt_data); 775 kfree(tt_data);
542} 776}
543 777
@@ -549,7 +783,9 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
549 struct batadv_tt_common_entry *tt_common_entry; 783 struct batadv_tt_common_entry *tt_common_entry;
550 struct batadv_tt_local_entry *tt_local; 784 struct batadv_tt_local_entry *tt_local;
551 struct batadv_hard_iface *primary_if; 785 struct batadv_hard_iface *primary_if;
786 struct batadv_softif_vlan *vlan;
552 struct hlist_head *head; 787 struct hlist_head *head;
788 unsigned short vid;
553 uint32_t i; 789 uint32_t i;
554 int last_seen_secs; 790 int last_seen_secs;
555 int last_seen_msecs; 791 int last_seen_msecs;
@@ -562,11 +798,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
562 goto out; 798 goto out;
563 799
564 seq_printf(seq, 800 seq_printf(seq,
565 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.8x):\n", 801 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
566 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn), 802 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
567 bat_priv->tt.local_crc); 803 seq_printf(seq, " %-13s %s %-7s %-9s (%-10s)\n", "Client", "VID",
568 seq_printf(seq, " %-13s %s %-7s %-10s\n", "Client", "VID", 804 "Flags", "Last seen", "CRC");
569 "Flags", "Last seen");
570 805
571 for (i = 0; i < hash->size; i++) { 806 for (i = 0; i < hash->size; i++) {
572 head = &hash->table[i]; 807 head = &hash->table[i];
@@ -577,6 +812,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
577 tt_local = container_of(tt_common_entry, 812 tt_local = container_of(tt_common_entry,
578 struct batadv_tt_local_entry, 813 struct batadv_tt_local_entry,
579 common); 814 common);
815 vid = tt_common_entry->vid;
580 last_seen_jiffies = jiffies - tt_local->last_seen; 816 last_seen_jiffies = jiffies - tt_local->last_seen;
581 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); 817 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
582 last_seen_secs = last_seen_msecs / 1000; 818 last_seen_secs = last_seen_msecs / 1000;
@@ -584,7 +820,15 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
584 820
585 no_purge = tt_common_entry->flags & np_flag; 821 no_purge = tt_common_entry->flags & np_flag;
586 822
587 seq_printf(seq, " * %pM %4i [%c%c%c%c%c] %3u.%03u\n", 823 vlan = batadv_softif_vlan_get(bat_priv, vid);
824 if (!vlan) {
825 seq_printf(seq, "Cannot retrieve VLAN %d\n",
826 BATADV_PRINT_VID(vid));
827 continue;
828 }
829
830 seq_printf(seq,
831 " * %pM %4i [%c%c%c%c%c] %3u.%03u (%#.8x)\n",
588 tt_common_entry->addr, 832 tt_common_entry->addr,
589 BATADV_PRINT_VID(tt_common_entry->vid), 833 BATADV_PRINT_VID(tt_common_entry->vid),
590 (tt_common_entry->flags & 834 (tt_common_entry->flags &
@@ -597,7 +841,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
597 (tt_common_entry->flags & 841 (tt_common_entry->flags &
598 BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 842 BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
599 no_purge ? 0 : last_seen_secs, 843 no_purge ? 0 : last_seen_secs,
600 no_purge ? 0 : last_seen_msecs); 844 no_purge ? 0 : last_seen_msecs,
845 vlan->tt.crc);
846
847 batadv_softif_vlan_free_ref(vlan);
601 } 848 }
602 rcu_read_unlock(); 849 rcu_read_unlock();
603 } 850 }
@@ -860,7 +1107,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
860 1107
861 INIT_HLIST_NODE(&orig_entry->list); 1108 INIT_HLIST_NODE(&orig_entry->list);
862 atomic_inc(&orig_node->refcount); 1109 atomic_inc(&orig_node->refcount);
863 atomic_inc(&orig_node->tt_size); 1110 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
864 orig_entry->orig_node = orig_node; 1111 orig_entry->orig_node = orig_node;
865 orig_entry->ttvn = ttvn; 1112 orig_entry->ttvn = ttvn;
866 atomic_set(&orig_entry->refcount, 2); 1113 atomic_set(&orig_entry->refcount, 2);
@@ -1070,45 +1317,71 @@ static void
1070batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, 1317batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
1071 struct seq_file *seq) 1318 struct seq_file *seq)
1072{ 1319{
1073 struct hlist_head *head;
1074 struct batadv_tt_orig_list_entry *orig_entry, *best_entry; 1320 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
1075 struct batadv_tt_common_entry *tt_common_entry; 1321 struct batadv_tt_common_entry *tt_common_entry;
1076 uint16_t flags; 1322 struct batadv_orig_node_vlan *vlan;
1323 struct hlist_head *head;
1077 uint8_t last_ttvn; 1324 uint8_t last_ttvn;
1325 uint16_t flags;
1078 1326
1079 tt_common_entry = &tt_global_entry->common; 1327 tt_common_entry = &tt_global_entry->common;
1080 flags = tt_common_entry->flags; 1328 flags = tt_common_entry->flags;
1081 1329
1082 best_entry = batadv_transtable_best_orig(tt_global_entry); 1330 best_entry = batadv_transtable_best_orig(tt_global_entry);
1083 if (best_entry) { 1331 if (best_entry) {
1332 vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
1333 tt_common_entry->vid);
1334 if (!vlan) {
1335 seq_printf(seq,
1336 " * Cannot retrieve VLAN %d for originator %pM\n",
1337 BATADV_PRINT_VID(tt_common_entry->vid),
1338 best_entry->orig_node->orig);
1339 goto print_list;
1340 }
1341
1084 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn); 1342 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
1085 seq_printf(seq, 1343 seq_printf(seq,
1086 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n", 1344 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
1087 '*', tt_global_entry->common.addr, 1345 '*', tt_global_entry->common.addr,
1088 BATADV_PRINT_VID(tt_global_entry->common.vid), 1346 BATADV_PRINT_VID(tt_global_entry->common.vid),
1089 best_entry->ttvn, best_entry->orig_node->orig, 1347 best_entry->ttvn, best_entry->orig_node->orig,
1090 last_ttvn, best_entry->orig_node->tt_crc, 1348 last_ttvn, vlan->tt.crc,
1091 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 1349 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1092 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 1350 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
1093 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); 1351 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1352
1353 batadv_orig_node_vlan_free_ref(vlan);
1094 } 1354 }
1095 1355
1356print_list:
1096 head = &tt_global_entry->orig_list; 1357 head = &tt_global_entry->orig_list;
1097 1358
1098 hlist_for_each_entry_rcu(orig_entry, head, list) { 1359 hlist_for_each_entry_rcu(orig_entry, head, list) {
1099 if (best_entry == orig_entry) 1360 if (best_entry == orig_entry)
1100 continue; 1361 continue;
1101 1362
1363 vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
1364 tt_common_entry->vid);
1365 if (!vlan) {
1366 seq_printf(seq,
1367 " + Cannot retrieve VLAN %d for originator %pM\n",
1368 BATADV_PRINT_VID(tt_common_entry->vid),
1369 orig_entry->orig_node->orig);
1370 continue;
1371 }
1372
1102 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); 1373 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
1103 seq_printf(seq, 1374 seq_printf(seq,
1104 " %c %pM %4d (%3u) via %pM (%3u) [%c%c%c]\n", 1375 " %c %pM %4d (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
1105 '+', tt_global_entry->common.addr, 1376 '+', tt_global_entry->common.addr,
1106 BATADV_PRINT_VID(tt_global_entry->common.vid), 1377 BATADV_PRINT_VID(tt_global_entry->common.vid),
1107 orig_entry->ttvn, orig_entry->orig_node->orig, 1378 orig_entry->ttvn, orig_entry->orig_node->orig,
1108 last_ttvn, 1379 last_ttvn, vlan->tt.crc,
1109 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 1380 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1110 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 1381 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
1111 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); 1382 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1383
1384 batadv_orig_node_vlan_free_ref(vlan);
1112 } 1385 }
1113} 1386}
1114 1387
@@ -1165,6 +1438,8 @@ batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1165 head = &tt_global_entry->orig_list; 1438 head = &tt_global_entry->orig_list;
1166 hlist_for_each_entry_safe(orig_entry, safe, head, list) { 1439 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
1167 hlist_del_rcu(&orig_entry->list); 1440 hlist_del_rcu(&orig_entry->list);
1441 batadv_tt_global_size_dec(orig_entry->orig_node,
1442 tt_global_entry->common.vid);
1168 batadv_tt_orig_list_entry_free_ref(orig_entry); 1443 batadv_tt_orig_list_entry_free_ref(orig_entry);
1169 } 1444 }
1170 spin_unlock_bh(&tt_global_entry->list_lock); 1445 spin_unlock_bh(&tt_global_entry->list_lock);
@@ -1192,6 +1467,8 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
1192 tt_global_entry->common.addr, 1467 tt_global_entry->common.addr,
1193 BATADV_PRINT_VID(vid), message); 1468 BATADV_PRINT_VID(vid), message);
1194 hlist_del_rcu(&orig_entry->list); 1469 hlist_del_rcu(&orig_entry->list);
1470 batadv_tt_global_size_dec(orig_node,
1471 tt_global_entry->common.vid);
1195 batadv_tt_orig_list_entry_free_ref(orig_entry); 1472 batadv_tt_orig_list_entry_free_ref(orig_entry);
1196 } 1473 }
1197 } 1474 }
@@ -1535,6 +1812,7 @@ out:
1535 * to the given orig_node 1812 * to the given orig_node
1536 * @bat_priv: the bat priv with all the soft interface information 1813 * @bat_priv: the bat priv with all the soft interface information
1537 * @orig_node: originator for which the CRC should be computed 1814 * @orig_node: originator for which the CRC should be computed
1815 * @vid: VLAN identifier for which the CRC32 has to be computed
1538 * 1816 *
1539 * This function computes the checksum for the global table corresponding to a 1817 * This function computes the checksum for the global table corresponding to a
1540 * specific originator. In particular, the checksum is computed as follows: For 1818 * specific originator. In particular, the checksum is computed as follows: For
@@ -1554,7 +1832,8 @@ out:
1554 * Returns the checksum of the global table of a given originator. 1832 * Returns the checksum of the global table of a given originator.
1555 */ 1833 */
1556static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, 1834static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1557 struct batadv_orig_node *orig_node) 1835 struct batadv_orig_node *orig_node,
1836 unsigned short vid)
1558{ 1837{
1559 struct batadv_hashtable *hash = bat_priv->tt.global_hash; 1838 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1560 struct batadv_tt_common_entry *tt_common; 1839 struct batadv_tt_common_entry *tt_common;
@@ -1570,6 +1849,12 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1570 tt_global = container_of(tt_common, 1849 tt_global = container_of(tt_common,
1571 struct batadv_tt_global_entry, 1850 struct batadv_tt_global_entry,
1572 common); 1851 common);
1852 /* compute the CRC only for entries belonging to the
1853 * VLAN identified by the vid passed as parameter
1854 */
1855 if (tt_common->vid != vid)
1856 continue;
1857
1573 /* Roaming clients are in the global table for 1858 /* Roaming clients are in the global table for
1574 * consistency only. They don't have to be 1859 * consistency only. They don't have to be
1575 * taken into account while computing the 1860 * taken into account while computing the
@@ -1604,13 +1889,15 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1604/** 1889/**
1605 * batadv_tt_local_crc - calculates the checksum of the local table 1890 * batadv_tt_local_crc - calculates the checksum of the local table
1606 * @bat_priv: the bat priv with all the soft interface information 1891 * @bat_priv: the bat priv with all the soft interface information
1892 * @vid: VLAN identifier for which the CRC32 has to be computed
1607 * 1893 *
1608 * For details about the computation, please refer to the documentation for 1894 * For details about the computation, please refer to the documentation for
1609 * batadv_tt_global_crc(). 1895 * batadv_tt_global_crc().
1610 * 1896 *
1611 * Returns the checksum of the local table 1897 * Returns the checksum of the local table
1612 */ 1898 */
1613static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv) 1899static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
1900 unsigned short vid)
1614{ 1901{
1615 struct batadv_hashtable *hash = bat_priv->tt.local_hash; 1902 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1616 struct batadv_tt_common_entry *tt_common; 1903 struct batadv_tt_common_entry *tt_common;
@@ -1622,6 +1909,12 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1622 1909
1623 rcu_read_lock(); 1910 rcu_read_lock();
1624 hlist_for_each_entry_rcu(tt_common, head, hash_entry) { 1911 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
1912 /* compute the CRC only for entries belonging to the
1913 * VLAN identified by vid
1914 */
1915 if (tt_common->vid != vid)
1916 continue;
1917
1625 /* not yet committed clients have not to be taken into 1918 /* not yet committed clients have not to be taken into
1626 * account while computing the CRC 1919 * account while computing the CRC
1627 */ 1920 */
@@ -1753,44 +2046,29 @@ static int batadv_tt_global_valid(const void *entry_ptr,
1753} 2046}
1754 2047
1755/** 2048/**
1756 * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the 2049 * batadv_tt_tvlv_generate - fill the tvlv buff with the tt entries from the
1757 * tt entries from the specified tt hash 2050 * specified tt hash
1758 * @bat_priv: the bat priv with all the soft interface information 2051 * @bat_priv: the bat priv with all the soft interface information
1759 * @hash: hash table containing the tt entries 2052 * @hash: hash table containing the tt entries
1760 * @tt_len: expected tvlv tt data buffer length in number of bytes 2053 * @tt_len: expected tvlv tt data buffer length in number of bytes
2054 * @tvlv_buff: pointer to the buffer to fill with the TT data
1761 * @valid_cb: function to filter tt change entries 2055 * @valid_cb: function to filter tt change entries
1762 * @cb_data: data passed to the filter function as argument 2056 * @cb_data: data passed to the filter function as argument
1763 *
1764 * Returns pointer to allocated tvlv tt data buffer if operation was
1765 * successful or NULL otherwise.
1766 */ 2057 */
1767static struct batadv_tvlv_tt_data * 2058static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1768batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, 2059 struct batadv_hashtable *hash,
1769 struct batadv_hashtable *hash, uint16_t tt_len, 2060 void *tvlv_buff, uint16_t tt_len,
1770 int (*valid_cb)(const void *, const void *), 2061 int (*valid_cb)(const void *, const void *),
1771 void *cb_data) 2062 void *cb_data)
1772{ 2063{
1773 struct batadv_tt_common_entry *tt_common_entry; 2064 struct batadv_tt_common_entry *tt_common_entry;
1774 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1775 struct batadv_tvlv_tt_change *tt_change; 2065 struct batadv_tvlv_tt_change *tt_change;
1776 struct hlist_head *head; 2066 struct hlist_head *head;
1777 uint16_t tt_tot, tt_num_entries = 0; 2067 uint16_t tt_tot, tt_num_entries = 0;
1778 ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data);
1779 uint32_t i; 2068 uint32_t i;
1780 2069
1781 if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) {
1782 tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size;
1783 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
1784 }
1785
1786 tt_tot = batadv_tt_entries(tt_len); 2070 tt_tot = batadv_tt_entries(tt_len);
1787 2071 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
1788 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1789 GFP_ATOMIC);
1790 if (!tvlv_tt_data)
1791 goto out;
1792
1793 tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1);
1794 2072
1795 rcu_read_lock(); 2073 rcu_read_lock();
1796 for (i = 0; i < hash->size; i++) { 2074 for (i = 0; i < hash->size; i++) {
@@ -1815,9 +2093,89 @@ batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1815 } 2093 }
1816 } 2094 }
1817 rcu_read_unlock(); 2095 rcu_read_unlock();
2096}
1818 2097
1819out: 2098/**
1820 return tvlv_tt_data; 2099 * batadv_tt_global_check_crc - check if all the CRCs are correct
2100 * @orig_node: originator for which the CRCs have to be checked
2101 * @tt_vlan: pointer to the first tvlv VLAN entry
2102 * @num_vlan: number of tvlv VLAN entries
2103 * @create: if true, create VLAN objects if not found
2104 *
2105 * Return true if all the received CRCs match the locally stored ones, false
2106 * otherwise
2107 */
2108static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
2109 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2110 uint16_t num_vlan)
2111{
2112 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
2113 struct batadv_orig_node_vlan *vlan;
2114 int i;
2115
2116 /* check if each received CRC matches the locally stored one */
2117 for (i = 0; i < num_vlan; i++) {
2118 tt_vlan_tmp = tt_vlan + i;
2119
2120 /* if orig_node is a backbone node for this VLAN, don't check
2121 * the CRC as we ignore all the global entries over it
2122 */
2123 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
2124 orig_node->orig))
2125 continue;
2126
2127 vlan = batadv_orig_node_vlan_get(orig_node,
2128 ntohs(tt_vlan_tmp->vid));
2129 if (!vlan)
2130 return false;
2131
2132 if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc))
2133 return false;
2134 }
2135
2136 return true;
2137}
2138
2139/**
2140 * batadv_tt_local_update_crc - update all the local CRCs
2141 * @bat_priv: the bat priv with all the soft interface information
2142 */
2143static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
2144{
2145 struct batadv_softif_vlan *vlan;
2146
2147 /* recompute the global CRC for each VLAN */
2148 rcu_read_lock();
2149 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
2150 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
2151 }
2152 rcu_read_unlock();
2153}
2154
2155/**
2156 * batadv_tt_global_update_crc - update all the global CRCs for this orig_node
2157 * @bat_priv: the bat priv with all the soft interface information
2158 * @orig_node: the orig_node for which the CRCs have to be updated
2159 */
2160static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
2161 struct batadv_orig_node *orig_node)
2162{
2163 struct batadv_orig_node_vlan *vlan;
2164 uint32_t crc;
2165
2166 /* recompute the global CRC for each VLAN */
2167 rcu_read_lock();
2168 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
2169 /* if orig_node is a backbone node for this VLAN, don't compute
2170 * the CRC as we ignore all the global entries over it
2171 */
2172 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2173 continue;
2174
2175 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
2176 vlan->tt.crc = crc;
2177 }
2178 rcu_read_unlock();
1821} 2179}
1822 2180
1823/** 2181/**
@@ -1825,19 +2183,23 @@ out:
1825 * @bat_priv: the bat priv with all the soft interface information 2183 * @bat_priv: the bat priv with all the soft interface information
1826 * @dst_orig_node: the destination of the message 2184 * @dst_orig_node: the destination of the message
1827 * @ttvn: the version number that the source of the message is looking for 2185 * @ttvn: the version number that the source of the message is looking for
1828 * @tt_crc: the CRC associated with the version number 2186 * @tt_vlan: pointer to the first tvlv VLAN object to request
2187 * @num_vlan: number of tvlv VLAN entries
1829 * @full_table: ask for the entire translation table if true, while only for the 2188 * @full_table: ask for the entire translation table if true, while only for the
1830 * last TT diff otherwise 2189 * last TT diff otherwise
1831 */ 2190 */
1832static int batadv_send_tt_request(struct batadv_priv *bat_priv, 2191static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1833 struct batadv_orig_node *dst_orig_node, 2192 struct batadv_orig_node *dst_orig_node,
1834 uint8_t ttvn, uint32_t tt_crc, 2193 uint8_t ttvn,
1835 bool full_table) 2194 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2195 uint16_t num_vlan, bool full_table)
1836{ 2196{
1837 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2197 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1838 struct batadv_hard_iface *primary_if;
1839 struct batadv_tt_req_node *tt_req_node = NULL; 2198 struct batadv_tt_req_node *tt_req_node = NULL;
2199 struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
2200 struct batadv_hard_iface *primary_if;
1840 bool ret = false; 2201 bool ret = false;
2202 int i, size;
1841 2203
1842 primary_if = batadv_primary_if_get_selected(bat_priv); 2204 primary_if = batadv_primary_if_get_selected(bat_priv);
1843 if (!primary_if) 2205 if (!primary_if)
@@ -1850,13 +2212,26 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1850 if (!tt_req_node) 2212 if (!tt_req_node)
1851 goto out; 2213 goto out;
1852 2214
1853 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC); 2215 size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
2216 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
1854 if (!tvlv_tt_data) 2217 if (!tvlv_tt_data)
1855 goto out; 2218 goto out;
1856 2219
1857 tvlv_tt_data->flags = BATADV_TT_REQUEST; 2220 tvlv_tt_data->flags = BATADV_TT_REQUEST;
1858 tvlv_tt_data->ttvn = ttvn; 2221 tvlv_tt_data->ttvn = ttvn;
1859 tvlv_tt_data->crc = htonl(tt_crc); 2222 tvlv_tt_data->num_vlan = htons(num_vlan);
2223
2224 /* send all the CRCs within the request. This is needed by intermediate
2225 * nodes to ensure they have the correct table before replying
2226 */
2227 tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
2228 for (i = 0; i < num_vlan; i++) {
2229 tt_vlan_req->vid = tt_vlan->vid;
2230 tt_vlan_req->crc = tt_vlan->crc;
2231
2232 tt_vlan_req++;
2233 tt_vlan++;
2234 }
1860 2235
1861 if (full_table) 2236 if (full_table)
1862 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE; 2237 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
@@ -1867,7 +2242,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1867 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); 2242 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1868 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2243 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1869 dst_orig_node->orig, BATADV_TVLV_TT, 1, 2244 dst_orig_node->orig, BATADV_TVLV_TT, 1,
1870 tvlv_tt_data, sizeof(*tvlv_tt_data)); 2245 tvlv_tt_data, size);
1871 ret = true; 2246 ret = true;
1872 2247
1873out: 2248out:
@@ -1899,10 +2274,13 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1899{ 2274{
1900 struct batadv_orig_node *req_dst_orig_node; 2275 struct batadv_orig_node *req_dst_orig_node;
1901 struct batadv_orig_node *res_dst_orig_node = NULL; 2276 struct batadv_orig_node *res_dst_orig_node = NULL;
2277 struct batadv_tvlv_tt_change *tt_change;
1902 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2278 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1903 uint8_t orig_ttvn, req_ttvn; 2279 struct batadv_tvlv_tt_vlan_data *tt_vlan;
1904 uint16_t tt_len;
1905 bool ret = false, full_table; 2280 bool ret = false, full_table;
2281 uint8_t orig_ttvn, req_ttvn;
2282 uint16_t tvlv_len;
2283 int32_t tt_len;
1906 2284
1907 batadv_dbg(BATADV_DBG_TT, bat_priv, 2285 batadv_dbg(BATADV_DBG_TT, bat_priv,
1908 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n", 2286 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
@@ -1921,9 +2299,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1921 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 2299 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1922 req_ttvn = tt_data->ttvn; 2300 req_ttvn = tt_data->ttvn;
1923 2301
2302 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
1924 /* this node doesn't have the requested data */ 2303 /* this node doesn't have the requested data */
1925 if (orig_ttvn != req_ttvn || 2304 if (orig_ttvn != req_ttvn ||
1926 tt_data->crc != htonl(req_dst_orig_node->tt_crc)) 2305 !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
2306 ntohs(tt_data->num_vlan)))
1927 goto out; 2307 goto out;
1928 2308
1929 /* If the full table has been explicitly requested */ 2309 /* If the full table has been explicitly requested */
@@ -1940,26 +2320,34 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1940 spin_lock_bh(&req_dst_orig_node->tt_buff_lock); 2320 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1941 tt_len = req_dst_orig_node->tt_buff_len; 2321 tt_len = req_dst_orig_node->tt_buff_len;
1942 2322
1943 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 2323 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
1944 GFP_ATOMIC); 2324 &tvlv_tt_data,
1945 if (!tvlv_tt_data) 2325 &tt_change,
2326 &tt_len);
2327 if (!tt_len)
1946 goto unlock; 2328 goto unlock;
1947 2329
1948 /* Copy the last orig_node's OGM buffer */ 2330 /* Copy the last orig_node's OGM buffer */
1949 memcpy(tvlv_tt_data + 1, req_dst_orig_node->tt_buff, 2331 memcpy(tt_change, req_dst_orig_node->tt_buff,
1950 req_dst_orig_node->tt_buff_len); 2332 req_dst_orig_node->tt_buff_len);
1951 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); 2333 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1952 } else { 2334 } else {
1953 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); 2335 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
1954 tt_len = batadv_tt_len(tt_len); 2336 * in the initial part
1955 2337 */
1956 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 2338 tt_len = -1;
1957 bat_priv->tt.global_hash, 2339 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
1958 tt_len, 2340 &tvlv_tt_data,
1959 batadv_tt_global_valid, 2341 &tt_change,
1960 req_dst_orig_node); 2342 &tt_len);
1961 if (!tvlv_tt_data) 2343 if (!tt_len)
1962 goto out; 2344 goto out;
2345
2346 /* fill the rest of the tvlv with the real TT entries */
2347 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
2348 tt_change, tt_len,
2349 batadv_tt_global_valid,
2350 req_dst_orig_node);
1963 } 2351 }
1964 2352
1965 tvlv_tt_data->flags = BATADV_TT_RESPONSE; 2353 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
@@ -1976,8 +2364,8 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1976 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 2364 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1977 2365
1978 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig, 2366 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
1979 req_src, BATADV_TVLV_TT, 1, 2367 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
1980 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 2368 tvlv_len);
1981 2369
1982 ret = true; 2370 ret = true;
1983 goto out; 2371 goto out;
@@ -2008,11 +2396,13 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
2008 uint8_t *req_src) 2396 uint8_t *req_src)
2009{ 2397{
2010 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2398 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
2011 struct batadv_orig_node *orig_node;
2012 struct batadv_hard_iface *primary_if = NULL; 2399 struct batadv_hard_iface *primary_if = NULL;
2400 struct batadv_tvlv_tt_change *tt_change;
2401 struct batadv_orig_node *orig_node;
2013 uint8_t my_ttvn, req_ttvn; 2402 uint8_t my_ttvn, req_ttvn;
2403 uint16_t tvlv_len;
2014 bool full_table; 2404 bool full_table;
2015 uint16_t tt_len; 2405 int32_t tt_len;
2016 2406
2017 batadv_dbg(BATADV_DBG_TT, bat_priv, 2407 batadv_dbg(BATADV_DBG_TT, bat_priv,
2018 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n", 2408 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
@@ -2046,29 +2436,37 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
2046 */ 2436 */
2047 if (!full_table) { 2437 if (!full_table) {
2048 spin_lock_bh(&bat_priv->tt.last_changeset_lock); 2438 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
2049 tt_len = bat_priv->tt.last_changeset_len;
2050 2439
2051 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 2440 tt_len = bat_priv->tt.last_changeset_len;
2052 GFP_ATOMIC); 2441 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
2053 if (!tvlv_tt_data) 2442 &tvlv_tt_data,
2443 &tt_change,
2444 &tt_len);
2445 if (!tt_len)
2054 goto unlock; 2446 goto unlock;
2055 2447
2056 /* Copy the last orig_node's OGM buffer */ 2448 /* Copy the last orig_node's OGM buffer */
2057 memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset, 2449 memcpy(tt_change, bat_priv->tt.last_changeset,
2058 bat_priv->tt.last_changeset_len); 2450 bat_priv->tt.last_changeset_len);
2059 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 2451 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
2060 } else { 2452 } else {
2061 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
2062 tt_len = batadv_tt_len(tt_len);
2063 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 2453 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
2064 2454
2065 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 2455 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
2066 bat_priv->tt.local_hash, 2456 * in the initial part
2067 tt_len, 2457 */
2068 batadv_tt_local_valid, 2458 tt_len = -1;
2069 NULL); 2459 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
2070 if (!tvlv_tt_data) 2460 &tvlv_tt_data,
2461 &tt_change,
2462 &tt_len);
2463 if (!tt_len)
2071 goto out; 2464 goto out;
2465
2466 /* fill the rest of the tvlv with the real TT entries */
2467 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
2468 tt_change, tt_len,
2469 batadv_tt_local_valid, NULL);
2072 } 2470 }
2073 2471
2074 tvlv_tt_data->flags = BATADV_TT_RESPONSE; 2472 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
@@ -2084,8 +2482,8 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
2084 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 2482 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
2085 2483
2086 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2484 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
2087 req_src, BATADV_TVLV_TT, 1, 2485 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
2088 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 2486 tvlv_len);
2089 2487
2090 goto out; 2488 goto out;
2091 2489
@@ -2161,8 +2559,9 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
2161} 2559}
2162 2560
2163static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 2561static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2164 struct batadv_tvlv_tt_data *tt_data, 2562 struct batadv_tvlv_tt_change *tt_change,
2165 uint8_t *resp_src, uint16_t num_entries) 2563 uint8_t ttvn, uint8_t *resp_src,
2564 uint16_t num_entries)
2166{ 2565{
2167 struct batadv_orig_node *orig_node; 2566 struct batadv_orig_node *orig_node;
2168 2567
@@ -2173,9 +2572,8 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2173 /* Purge the old table first.. */ 2572 /* Purge the old table first.. */
2174 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); 2573 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
2175 2574
2176 _batadv_tt_update_changes(bat_priv, orig_node, 2575 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
2177 (struct batadv_tvlv_tt_change *)(tt_data + 1), 2576 ttvn);
2178 num_entries, tt_data->ttvn);
2179 2577
2180 spin_lock_bh(&orig_node->tt_buff_lock); 2578 spin_lock_bh(&orig_node->tt_buff_lock);
2181 kfree(orig_node->tt_buff); 2579 kfree(orig_node->tt_buff);
@@ -2183,7 +2581,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2183 orig_node->tt_buff = NULL; 2581 orig_node->tt_buff = NULL;
2184 spin_unlock_bh(&orig_node->tt_buff_lock); 2582 spin_unlock_bh(&orig_node->tt_buff_lock);
2185 2583
2186 atomic_set(&orig_node->last_ttvn, tt_data->ttvn); 2584 atomic_set(&orig_node->last_ttvn, ttvn);
2187 2585
2188out: 2586out:
2189 if (orig_node) 2587 if (orig_node)
@@ -2247,6 +2645,8 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2247 struct batadv_tt_req_node *node, *safe; 2645 struct batadv_tt_req_node *node, *safe;
2248 struct batadv_orig_node *orig_node = NULL; 2646 struct batadv_orig_node *orig_node = NULL;
2249 struct batadv_tvlv_tt_change *tt_change; 2647 struct batadv_tvlv_tt_change *tt_change;
2648 uint8_t *tvlv_ptr = (uint8_t *)tt_data;
2649 uint16_t change_offset;
2250 2650
2251 batadv_dbg(BATADV_DBG_TT, bat_priv, 2651 batadv_dbg(BATADV_DBG_TT, bat_priv,
2252 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", 2652 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
@@ -2263,16 +2663,22 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2263 2663
2264 spin_lock_bh(&orig_node->tt_lock); 2664 spin_lock_bh(&orig_node->tt_lock);
2265 2665
2666 change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
2667 change_offset *= ntohs(tt_data->num_vlan);
2668 change_offset += sizeof(*tt_data);
2669 tvlv_ptr += change_offset;
2670
2671 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
2266 if (tt_data->flags & BATADV_TT_FULL_TABLE) { 2672 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
2267 batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries); 2673 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
2674 resp_src, num_entries);
2268 } else { 2675 } else {
2269 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
2270 batadv_tt_update_changes(bat_priv, orig_node, num_entries, 2676 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
2271 tt_data->ttvn, tt_change); 2677 tt_data->ttvn, tt_change);
2272 } 2678 }
2273 2679
2274 /* Recalculate the CRC for this orig_node and store it */ 2680 /* Recalculate the CRC for this orig_node and store it */
2275 orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); 2681 batadv_tt_global_update_crc(bat_priv, orig_node);
2276 2682
2277 spin_unlock_bh(&orig_node->tt_lock); 2683 spin_unlock_bh(&orig_node->tt_lock);
2278 2684
@@ -2284,6 +2690,7 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2284 list_del(&node->list); 2690 list_del(&node->list);
2285 kfree(node); 2691 kfree(node);
2286 } 2692 }
2693
2287 spin_unlock_bh(&bat_priv->tt.req_list_lock); 2694 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2288out: 2695out:
2289 if (orig_node) 2696 if (orig_node)
@@ -2452,19 +2859,25 @@ void batadv_tt_free(struct batadv_priv *bat_priv)
2452 kfree(bat_priv->tt.last_changeset); 2859 kfree(bat_priv->tt.last_changeset);
2453} 2860}
2454 2861
2455/* This function will enable or disable the specified flags for all the entries 2862/**
2456 * in the given hash table and returns the number of modified entries 2863 * batadv_tt_local_set_flags - set or unset the specified flags on the local
2864 * table and possibly count them in the TT size
2865 * @bat_priv: the bat priv with all the soft interface information
2866 * @flags: the flag to switch
2867 * @enable: whether to set or unset the flag
2868 * @count: whether to increase the TT size by the number of changed entries
2457 */ 2869 */
2458static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash, 2870static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv,
2459 uint16_t flags, bool enable) 2871 uint16_t flags, bool enable, bool count)
2460{ 2872{
2461 uint32_t i; 2873 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
2874 struct batadv_tt_common_entry *tt_common_entry;
2462 uint16_t changed_num = 0; 2875 uint16_t changed_num = 0;
2463 struct hlist_head *head; 2876 struct hlist_head *head;
2464 struct batadv_tt_common_entry *tt_common_entry; 2877 uint32_t i;
2465 2878
2466 if (!hash) 2879 if (!hash)
2467 goto out; 2880 return;
2468 2881
2469 for (i = 0; i < hash->size; i++) { 2882 for (i = 0; i < hash->size; i++) {
2470 head = &hash->table[i]; 2883 head = &hash->table[i];
@@ -2482,11 +2895,15 @@ static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash,
2482 tt_common_entry->flags &= ~flags; 2895 tt_common_entry->flags &= ~flags;
2483 } 2896 }
2484 changed_num++; 2897 changed_num++;
2898
2899 if (!count)
2900 continue;
2901
2902 batadv_tt_local_size_inc(bat_priv,
2903 tt_common_entry->vid);
2485 } 2904 }
2486 rcu_read_unlock(); 2905 rcu_read_unlock();
2487 } 2906 }
2488out:
2489 return changed_num;
2490} 2907}
2491 2908
2492/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ 2909/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
@@ -2518,7 +2935,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2518 tt_common->addr, 2935 tt_common->addr,
2519 BATADV_PRINT_VID(tt_common->vid)); 2936 BATADV_PRINT_VID(tt_common->vid));
2520 2937
2521 atomic_dec(&bat_priv->tt.local_entry_num); 2938 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
2522 hlist_del_rcu(&tt_common->hash_entry); 2939 hlist_del_rcu(&tt_common->hash_entry);
2523 tt_local = container_of(tt_common, 2940 tt_local = container_of(tt_common,
2524 struct batadv_tt_local_entry, 2941 struct batadv_tt_local_entry,
@@ -2536,8 +2953,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2536 */ 2953 */
2537void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv) 2954void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2538{ 2955{
2539 uint16_t changed_num = 0;
2540
2541 spin_lock_bh(&bat_priv->tt.commit_lock); 2956 spin_lock_bh(&bat_priv->tt.commit_lock);
2542 2957
2543 if (atomic_read(&bat_priv->tt.local_changes) < 1) { 2958 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
@@ -2546,13 +2961,10 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2546 goto out; 2961 goto out;
2547 } 2962 }
2548 2963
2549 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, 2964 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
2550 BATADV_TT_CLIENT_NEW, false);
2551 2965
2552 /* all reset entries have to be counted as local entries */
2553 atomic_add(changed_num, &bat_priv->tt.local_entry_num);
2554 batadv_tt_local_purge_pending_clients(bat_priv); 2966 batadv_tt_local_purge_pending_clients(bat_priv);
2555 bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv); 2967 batadv_tt_local_update_crc(bat_priv);
2556 2968
2557 /* Increment the TTVN only once per OGM interval */ 2969 /* Increment the TTVN only once per OGM interval */
2558 atomic_inc(&bat_priv->tt.vn); 2970 atomic_inc(&bat_priv->tt.vn);
@@ -2608,25 +3020,28 @@ out:
2608 * information received via ogms 3020 * information received via ogms
2609 * @bat_priv: the bat priv with all the soft interface information 3021 * @bat_priv: the bat priv with all the soft interface information
2610 * @orig: the orig_node of the ogm 3022 * @orig: the orig_node of the ogm
2611 * @tt_buff: buffer holding the tt information 3023 * @tt_vlan: pointer to the first tvlv VLAN entry
3024 * @tt_num_vlan: number of tvlv VLAN entries
3025 * @tt_change: pointer to the first entry in the TT buffer
2612 * @tt_num_changes: number of tt changes inside the tt buffer 3026 * @tt_num_changes: number of tt changes inside the tt buffer
2613 * @ttvn: translation table version number of this changeset 3027 * @ttvn: translation table version number of this changeset
2614 * @tt_crc: crc32 checksum of orig node's translation table 3028 * @tt_crc: crc32 checksum of orig node's translation table
2615 */ 3029 */
2616static void batadv_tt_update_orig(struct batadv_priv *bat_priv, 3030static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2617 struct batadv_orig_node *orig_node, 3031 struct batadv_orig_node *orig_node,
2618 const unsigned char *tt_buff, 3032 const void *tt_buff, uint16_t tt_num_vlan,
2619 uint16_t tt_num_changes, uint8_t ttvn, 3033 struct batadv_tvlv_tt_change *tt_change,
2620 uint32_t tt_crc) 3034 uint16_t tt_num_changes, uint8_t ttvn)
2621{ 3035{
2622 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 3036 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
3037 struct batadv_tvlv_tt_vlan_data *tt_vlan;
2623 bool full_table = true; 3038 bool full_table = true;
2624 struct batadv_tvlv_tt_change *tt_change;
2625 3039
2626 /* don't care about a backbone gateways updates. */ 3040 /* don't care about a backbone gateways updates. */
2627 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) 3041 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2628 return; 3042 return;
2629 3043
3044 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
2630 /* orig table not initialised AND first diff is in the OGM OR the ttvn 3045 /* orig table not initialised AND first diff is in the OGM OR the ttvn
2631 * increased by one -> we can apply the attached changes 3046 * increased by one -> we can apply the attached changes
2632 */ 3047 */
@@ -2652,7 +3067,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2652 * prefer to recompute it to spot any possible inconsistency 3067 * prefer to recompute it to spot any possible inconsistency
2653 * in the global table 3068 * in the global table
2654 */ 3069 */
2655 orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); 3070 batadv_tt_global_update_crc(bat_priv, orig_node);
2656 3071
2657 spin_unlock_bh(&orig_node->tt_lock); 3072 spin_unlock_bh(&orig_node->tt_lock);
2658 3073
@@ -2665,21 +3080,24 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2665 * checking the CRC value is mandatory to detect the 3080 * checking the CRC value is mandatory to detect the
2666 * inconsistency 3081 * inconsistency
2667 */ 3082 */
2668 if (orig_node->tt_crc != tt_crc) 3083 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
3084 tt_num_vlan))
2669 goto request_table; 3085 goto request_table;
2670 } else { 3086 } else {
2671 /* if we missed more than one change or our tables are not 3087 /* if we missed more than one change or our tables are not
2672 * in sync anymore -> request fresh tt data 3088 * in sync anymore -> request fresh tt data
2673 */ 3089 */
2674 if (!orig_node->tt_initialised || ttvn != orig_ttvn || 3090 if (!orig_node->tt_initialised || ttvn != orig_ttvn ||
2675 orig_node->tt_crc != tt_crc) { 3091 !batadv_tt_global_check_crc(orig_node, tt_vlan,
3092 tt_num_vlan)) {
2676request_table: 3093request_table:
2677 batadv_dbg(BATADV_DBG_TT, bat_priv, 3094 batadv_dbg(BATADV_DBG_TT, bat_priv,
2678 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.8x last_crc: %#.8x num_changes: %u)\n", 3095 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
2679 orig_node->orig, ttvn, orig_ttvn, tt_crc, 3096 orig_node->orig, ttvn, orig_ttvn,
2680 orig_node->tt_crc, tt_num_changes); 3097 tt_num_changes);
2681 batadv_send_tt_request(bat_priv, orig_node, ttvn, 3098 batadv_send_tt_request(bat_priv, orig_node, ttvn,
2682 tt_crc, full_table); 3099 tt_vlan, tt_num_vlan,
3100 full_table);
2683 return; 3101 return;
2684 } 3102 }
2685 } 3103 }
@@ -2774,12 +3192,13 @@ out:
2774 */ 3192 */
2775static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 3193static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2776 struct batadv_orig_node *orig, 3194 struct batadv_orig_node *orig,
2777 uint8_t flags, 3195 uint8_t flags, void *tvlv_value,
2778 void *tvlv_value,
2779 uint16_t tvlv_value_len) 3196 uint16_t tvlv_value_len)
2780{ 3197{
3198 struct batadv_tvlv_tt_vlan_data *tt_vlan;
3199 struct batadv_tvlv_tt_change *tt_change;
2781 struct batadv_tvlv_tt_data *tt_data; 3200 struct batadv_tvlv_tt_data *tt_data;
2782 uint16_t num_entries; 3201 uint16_t num_entries, num_vlan;
2783 3202
2784 if (tvlv_value_len < sizeof(*tt_data)) 3203 if (tvlv_value_len < sizeof(*tt_data))
2785 return; 3204 return;
@@ -2787,11 +3206,19 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2787 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 3206 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2788 tvlv_value_len -= sizeof(*tt_data); 3207 tvlv_value_len -= sizeof(*tt_data);
2789 3208
3209 num_vlan = ntohs(tt_data->num_vlan);
3210
3211 if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
3212 return;
3213
3214 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
3215 tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
3216 tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
3217
2790 num_entries = batadv_tt_entries(tvlv_value_len); 3218 num_entries = batadv_tt_entries(tvlv_value_len);
2791 3219
2792 batadv_tt_update_orig(bat_priv, orig, 3220 batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
2793 (unsigned char *)(tt_data + 1), 3221 num_entries, tt_data->ttvn);
2794 num_entries, tt_data->ttvn, ntohl(tt_data->crc));
2795} 3222}
2796 3223
2797/** 3224/**
@@ -2812,7 +3239,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2812 uint16_t tvlv_value_len) 3239 uint16_t tvlv_value_len)
2813{ 3240{
2814 struct batadv_tvlv_tt_data *tt_data; 3241 struct batadv_tvlv_tt_data *tt_data;
2815 uint16_t num_entries; 3242 uint16_t tt_vlan_len, tt_num_entries;
2816 char tt_flag; 3243 char tt_flag;
2817 bool ret; 3244 bool ret;
2818 3245
@@ -2822,7 +3249,14 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2822 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 3249 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2823 tvlv_value_len -= sizeof(*tt_data); 3250 tvlv_value_len -= sizeof(*tt_data);
2824 3251
2825 num_entries = batadv_tt_entries(tvlv_value_len); 3252 tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
3253 tt_vlan_len *= ntohs(tt_data->num_vlan);
3254
3255 if (tvlv_value_len < tt_vlan_len)
3256 return NET_RX_SUCCESS;
3257
3258 tvlv_value_len -= tt_vlan_len;
3259 tt_num_entries = batadv_tt_entries(tvlv_value_len);
2826 3260
2827 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) { 3261 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
2828 case BATADV_TT_REQUEST: 3262 case BATADV_TT_REQUEST:
@@ -2850,7 +3284,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2850 3284
2851 if (batadv_is_my_mac(bat_priv, dst)) { 3285 if (batadv_is_my_mac(bat_priv, dst)) {
2852 batadv_handle_tt_response(bat_priv, tt_data, 3286 batadv_handle_tt_response(bat_priv, tt_data,
2853 src, num_entries); 3287 src, tt_num_entries);
2854 return NET_RX_SUCCESS; 3288 return NET_RX_SUCCESS;
2855 } 3289 }
2856 3290
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index bd95d612260c..ff53933b5a59 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -107,6 +107,32 @@ struct batadv_frag_list_entry {
107}; 107};
108 108
109/** 109/**
110 * struct batadv_vlan_tt - VLAN specific TT attributes
111 * @crc: CRC32 checksum of the entries belonging to this vlan
112 * @num_entries: number of TT entries for this VLAN
113 */
114struct batadv_vlan_tt {
115 uint32_t crc;
116 atomic_t num_entries;
117};
118
119/**
120 * batadv_orig_node_vlan - VLAN specific data per orig_node
121 * @vid: the VLAN identifier
122 * @tt: VLAN specific TT attributes
123 * @list: list node for orig_node::vlan_list
124 * @refcount: number of context where this object is currently in use
125 * @rcu: struct used for freeing in a RCU-safe manner
126 */
127struct batadv_orig_node_vlan {
128 unsigned short vid;
129 struct batadv_vlan_tt tt;
130 struct list_head list;
131 atomic_t refcount;
132 struct rcu_head rcu;
133};
134
135/**
110 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh 136 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
111 * @orig: originator ethernet address 137 * @orig: originator ethernet address
112 * @primary_addr: hosts primary interface address 138 * @primary_addr: hosts primary interface address
@@ -120,12 +146,10 @@ struct batadv_frag_list_entry {
120 * @batman_seqno_reset: time when the batman seqno window was reset 146 * @batman_seqno_reset: time when the batman seqno window was reset
121 * @capabilities: announced capabilities of this originator 147 * @capabilities: announced capabilities of this originator
122 * @last_ttvn: last seen translation table version number 148 * @last_ttvn: last seen translation table version number
123 * @tt_crc: CRC of the translation table
124 * @tt_buff: last tt changeset this node received from the orig node 149 * @tt_buff: last tt changeset this node received from the orig node
125 * @tt_buff_len: length of the last tt changeset this node received from the 150 * @tt_buff_len: length of the last tt changeset this node received from the
126 * orig node 151 * orig node
127 * @tt_buff_lock: lock that protects tt_buff and tt_buff_len 152 * @tt_buff_lock: lock that protects tt_buff and tt_buff_len
128 * @tt_size: number of global TT entries announced by the orig node
129 * @tt_initialised: bool keeping track of whether or not this node have received 153 * @tt_initialised: bool keeping track of whether or not this node have received
130 * any translation table information from the orig node yet 154 * any translation table information from the orig node yet
131 * @tt_lock: prevents from updating the table while reading it. Table update is 155 * @tt_lock: prevents from updating the table while reading it. Table update is
@@ -154,6 +178,9 @@ struct batadv_frag_list_entry {
154 * @in_coding_list_lock: protects in_coding_list 178 * @in_coding_list_lock: protects in_coding_list
155 * @out_coding_list_lock: protects out_coding_list 179 * @out_coding_list_lock: protects out_coding_list
156 * @fragments: array with heads for fragment chains 180 * @fragments: array with heads for fragment chains
181 * @vlan_list: a list of orig_node_vlan structs, one per VLAN served by the
182 * originator represented by this object
183 * @vlan_list_lock: lock protecting vlan_list
157 */ 184 */
158struct batadv_orig_node { 185struct batadv_orig_node {
159 uint8_t orig[ETH_ALEN]; 186 uint8_t orig[ETH_ALEN];
@@ -169,11 +196,9 @@ struct batadv_orig_node {
169 unsigned long batman_seqno_reset; 196 unsigned long batman_seqno_reset;
170 uint8_t capabilities; 197 uint8_t capabilities;
171 atomic_t last_ttvn; 198 atomic_t last_ttvn;
172 uint32_t tt_crc;
173 unsigned char *tt_buff; 199 unsigned char *tt_buff;
174 int16_t tt_buff_len; 200 int16_t tt_buff_len;
175 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ 201 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */
176 atomic_t tt_size;
177 bool tt_initialised; 202 bool tt_initialised;
178 /* prevents from changing the table while reading it */ 203 /* prevents from changing the table while reading it */
179 spinlock_t tt_lock; 204 spinlock_t tt_lock;
@@ -203,6 +228,8 @@ struct batadv_orig_node {
203 spinlock_t out_coding_list_lock; /* Protects out_coding_list */ 228 spinlock_t out_coding_list_lock; /* Protects out_coding_list */
204#endif 229#endif
205 struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT]; 230 struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT];
231 struct list_head vlan_list;
232 spinlock_t vlan_list_lock; /* protects vlan_list */
206}; 233};
207 234
208/** 235/**
@@ -389,8 +416,6 @@ enum batadv_counters {
389 * @changes_list_lock: lock protecting changes_list 416 * @changes_list_lock: lock protecting changes_list
390 * @req_list_lock: lock protecting req_list 417 * @req_list_lock: lock protecting req_list
391 * @roam_list_lock: lock protecting roam_list 418 * @roam_list_lock: lock protecting roam_list
392 * @local_entry_num: number of entries in the local hash table
393 * @local_crc: Checksum of the local table, recomputed before sending a new OGM
394 * @last_changeset: last tt changeset this host has generated 419 * @last_changeset: last tt changeset this host has generated
395 * @last_changeset_len: length of last tt changeset this host has generated 420 * @last_changeset_len: length of last tt changeset this host has generated
396 * @last_changeset_lock: lock protecting last_changeset & last_changeset_len 421 * @last_changeset_lock: lock protecting last_changeset & last_changeset_len
@@ -413,8 +438,6 @@ struct batadv_priv_tt {
413 spinlock_t changes_list_lock; /* protects changes */ 438 spinlock_t changes_list_lock; /* protects changes */
414 spinlock_t req_list_lock; /* protects req_list */ 439 spinlock_t req_list_lock; /* protects req_list */
415 spinlock_t roam_list_lock; /* protects roam_list */ 440 spinlock_t roam_list_lock; /* protects roam_list */
416 atomic_t local_entry_num;
417 uint32_t local_crc;
418 unsigned char *last_changeset; 441 unsigned char *last_changeset;
419 int16_t last_changeset_len; 442 int16_t last_changeset_len;
420 /* protects last_changeset & last_changeset_len */ 443 /* protects last_changeset & last_changeset_len */
@@ -548,6 +571,7 @@ struct batadv_priv_nc {
548 * @vid: VLAN identifier 571 * @vid: VLAN identifier
549 * @kobj: kobject for sysfs vlan subdirectory 572 * @kobj: kobject for sysfs vlan subdirectory
550 * @ap_isolation: AP isolation state 573 * @ap_isolation: AP isolation state
574 * @tt: TT private attributes (VLAN specific)
551 * @list: list node for bat_priv::softif_vlan_list 575 * @list: list node for bat_priv::softif_vlan_list
552 * @refcount: number of context where this object is currently in use 576 * @refcount: number of context where this object is currently in use
553 * @rcu: struct used for freeing in a RCU-safe manner 577 * @rcu: struct used for freeing in a RCU-safe manner
@@ -556,6 +580,7 @@ struct batadv_softif_vlan {
556 unsigned short vid; 580 unsigned short vid;
557 struct kobject *kobj; 581 struct kobject *kobj;
558 atomic_t ap_isolation; /* boolean */ 582 atomic_t ap_isolation; /* boolean */
583 struct batadv_vlan_tt tt;
559 struct hlist_node list; 584 struct hlist_node list;
560 atomic_t refcount; 585 atomic_t refcount;
561 struct rcu_head rcu; 586 struct rcu_head rcu;