batman-adv: Fix TT sync flags for intermediate TT responses
[linux-2.6-block.git] / net / batman-adv / translation-table.c
CommitLineData
7db7d9f3 1// SPDX-License-Identifier: GPL-2.0
6b1aea8c 2/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors:
c6c8fea2 3 *
35c133a0 4 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
c6c8fea2
SE
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
ebf38fb7 16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
c6c8fea2
SE
17 */
18
c6c8fea2 19#include "translation-table.h"
1e2c2a4f
SE
20#include "main.h"
21
22#include <linux/atomic.h>
ac4eebd4 23#include <linux/bitops.h>
ecc36f5e 24#include <linux/build_bug.h>
1e2c2a4f 25#include <linux/byteorder/generic.h>
86452f81 26#include <linux/cache.h>
1e2c2a4f
SE
27#include <linux/compiler.h>
28#include <linux/crc32c.h>
29#include <linux/errno.h>
30#include <linux/etherdevice.h>
b92b94ac 31#include <linux/gfp.h>
1e2c2a4f 32#include <linux/if_ether.h>
86452f81 33#include <linux/init.h>
1e2c2a4f
SE
34#include <linux/jhash.h>
35#include <linux/jiffies.h>
36#include <linux/kernel.h>
6e8ef69d 37#include <linux/kref.h>
1e2c2a4f
SE
38#include <linux/list.h>
39#include <linux/lockdep.h>
3a64469e 40#include <linux/net.h>
1e2c2a4f 41#include <linux/netdevice.h>
d34f0550 42#include <linux/netlink.h>
1e2c2a4f
SE
43#include <linux/rculist.h>
44#include <linux/rcupdate.h>
45#include <linux/seq_file.h>
d34f0550 46#include <linux/skbuff.h>
1e2c2a4f
SE
47#include <linux/slab.h>
48#include <linux/spinlock.h>
49#include <linux/stddef.h>
50#include <linux/string.h>
51#include <linux/workqueue.h>
d34f0550
MS
52#include <net/genetlink.h>
53#include <net/netlink.h>
54#include <net/sock.h>
fec149f5 55#include <uapi/linux/batadv_packet.h>
d34f0550 56#include <uapi/linux/batman_adv.h>
1e2c2a4f
SE
57
58#include "bridge_loop_avoidance.h"
32ae9b22 59#include "hard-interface.h"
c6c8fea2 60#include "hash.h"
ba412080 61#include "log.h"
d34f0550 62#include "netlink.h"
1e2c2a4f 63#include "originator.h"
1e2c2a4f 64#include "soft-interface.h"
1f8dce49 65#include "tvlv.h"
a73105b8 66
86452f81
SE
67static struct kmem_cache *batadv_tl_cache __read_mostly;
68static struct kmem_cache *batadv_tg_cache __read_mostly;
69static struct kmem_cache *batadv_tt_orig_cache __read_mostly;
70static struct kmem_cache *batadv_tt_change_cache __read_mostly;
71static struct kmem_cache *batadv_tt_req_cache __read_mostly;
72static struct kmem_cache *batadv_tt_roam_cache __read_mostly;
73
dec05074
AQ
74/* hash class keys */
75static struct lock_class_key batadv_tt_local_hash_lock_class_key;
76static struct lock_class_key batadv_tt_global_hash_lock_class_key;
77
6b5e971a 78static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
c018ad3d 79 unsigned short vid,
56303d34 80 struct batadv_orig_node *orig_node);
a513088d
SE
81static void batadv_tt_purge(struct work_struct *work);
82static void
56303d34 83batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
30cfd02b
AQ
84static void batadv_tt_global_del(struct batadv_priv *bat_priv,
85 struct batadv_orig_node *orig_node,
86 const unsigned char *addr,
c018ad3d
AQ
87 unsigned short vid, const char *message,
88 bool roaming);
c6c8fea2 89
62fe710f 90/**
7e9a8c2c 91 * batadv_compare_tt() - check if two TT entries are the same
d15cd622
AQ
92 * @node: the list element pointer of the first TT entry
93 * @data2: pointer to the tt_common_entry of the second TT entry
62fe710f 94 *
d15cd622
AQ
95 * Compare the MAC address and the VLAN ID of the two TT entries and check if
96 * they are the same TT client.
4b426b10 97 * Return: true if the two TT clients are the same, false otherwise
62fe710f 98 */
4b426b10 99static bool batadv_compare_tt(const struct hlist_node *node, const void *data2)
7aadf889 100{
56303d34 101 const void *data1 = container_of(node, struct batadv_tt_common_entry,
747e4221 102 hash_entry);
4c718958
ML
103 const struct batadv_tt_common_entry *tt1 = data1;
104 const struct batadv_tt_common_entry *tt2 = data2;
7aadf889 105
4c718958 106 return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2);
7aadf889
ML
107}
108
c018ad3d 109/**
7e9a8c2c 110 * batadv_choose_tt() - return the index of the tt entry in the hash table
c018ad3d
AQ
111 * @data: pointer to the tt_common_entry object to map
112 * @size: the size of the hash table
113 *
62fe710f 114 * Return: the hash index where the object represented by 'data' should be
c018ad3d
AQ
115 * stored at.
116 */
6b5e971a 117static inline u32 batadv_choose_tt(const void *data, u32 size)
c018ad3d
AQ
118{
119 struct batadv_tt_common_entry *tt;
6b5e971a 120 u32 hash = 0;
c018ad3d
AQ
121
122 tt = (struct batadv_tt_common_entry *)data;
36fd61cb
SE
123 hash = jhash(&tt->addr, ETH_ALEN, hash);
124 hash = jhash(&tt->vid, sizeof(tt->vid), hash);
c018ad3d
AQ
125
126 return hash % size;
127}
128
129/**
7e9a8c2c 130 * batadv_tt_hash_find() - look for a client in the given hash table
c018ad3d
AQ
131 * @hash: the hash table to search
132 * @addr: the mac address of the client to look for
133 * @vid: VLAN identifier
134 *
62fe710f 135 * Return: a pointer to the tt_common struct belonging to the searched client if
c018ad3d
AQ
136 * found, NULL otherwise.
137 */
56303d34 138static struct batadv_tt_common_entry *
6b5e971a 139batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr,
c018ad3d 140 unsigned short vid)
7aadf889 141{
7aadf889 142 struct hlist_head *head;
c018ad3d 143 struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
6b5e971a 144 u32 index;
7aadf889
ML
145
146 if (!hash)
147 return NULL;
148
8fdd0153 149 ether_addr_copy(to_search.addr, addr);
c018ad3d
AQ
150 to_search.vid = vid;
151
152 index = batadv_choose_tt(&to_search, hash->size);
7aadf889
ML
153 head = &hash->table[index];
154
155 rcu_read_lock();
c018ad3d
AQ
156 hlist_for_each_entry_rcu(tt, head, hash_entry) {
157 if (!batadv_compare_eth(tt, addr))
158 continue;
159
160 if (tt->vid != vid)
7aadf889
ML
161 continue;
162
92dcdf09 163 if (!kref_get_unless_zero(&tt->refcount))
7683fdc1
AQ
164 continue;
165
c018ad3d 166 tt_tmp = tt;
7aadf889
ML
167 break;
168 }
169 rcu_read_unlock();
170
c018ad3d 171 return tt_tmp;
7aadf889
ML
172}
173
c018ad3d 174/**
7e9a8c2c 175 * batadv_tt_local_hash_find() - search the local table for a given client
c018ad3d
AQ
176 * @bat_priv: the bat priv with all the soft interface information
177 * @addr: the mac address of the client to look for
178 * @vid: VLAN identifier
179 *
62fe710f 180 * Return: a pointer to the corresponding tt_local_entry struct if the client is
c018ad3d
AQ
181 * found, NULL otherwise.
182 */
56303d34 183static struct batadv_tt_local_entry *
6b5e971a 184batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
c018ad3d 185 unsigned short vid)
7aadf889 186{
56303d34
SE
187 struct batadv_tt_common_entry *tt_common_entry;
188 struct batadv_tt_local_entry *tt_local_entry = NULL;
7aadf889 189
c018ad3d
AQ
190 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
191 vid);
48100bac
AQ
192 if (tt_common_entry)
193 tt_local_entry = container_of(tt_common_entry,
56303d34
SE
194 struct batadv_tt_local_entry,
195 common);
48100bac
AQ
196 return tt_local_entry;
197}
7aadf889 198
c018ad3d 199/**
7e9a8c2c 200 * batadv_tt_global_hash_find() - search the global table for a given client
c018ad3d
AQ
201 * @bat_priv: the bat priv with all the soft interface information
202 * @addr: the mac address of the client to look for
203 * @vid: VLAN identifier
204 *
62fe710f 205 * Return: a pointer to the corresponding tt_global_entry struct if the client
c018ad3d
AQ
206 * is found, NULL otherwise.
207 */
56303d34 208static struct batadv_tt_global_entry *
6b5e971a 209batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
c018ad3d 210 unsigned short vid)
48100bac 211{
56303d34
SE
212 struct batadv_tt_common_entry *tt_common_entry;
213 struct batadv_tt_global_entry *tt_global_entry = NULL;
7683fdc1 214
c018ad3d
AQ
215 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
216 vid);
48100bac
AQ
217 if (tt_common_entry)
218 tt_global_entry = container_of(tt_common_entry,
56303d34
SE
219 struct batadv_tt_global_entry,
220 common);
48100bac 221 return tt_global_entry;
7aadf889
ML
222}
223
86452f81 224/**
7e9a8c2c 225 * batadv_tt_local_entry_free_rcu() - free the tt_local_entry
86452f81
SE
226 * @rcu: rcu pointer of the tt_local_entry
227 */
228static void batadv_tt_local_entry_free_rcu(struct rcu_head *rcu)
229{
230 struct batadv_tt_local_entry *tt_local_entry;
231
232 tt_local_entry = container_of(rcu, struct batadv_tt_local_entry,
233 common.rcu);
234
235 kmem_cache_free(batadv_tl_cache, tt_local_entry);
236}
237
92dcdf09 238/**
7e9a8c2c 239 * batadv_tt_local_entry_release() - release tt_local_entry from lists and queue
92dcdf09
SE
240 * for free after rcu grace period
241 * @ref: kref pointer of the nc_node
242 */
243static void batadv_tt_local_entry_release(struct kref *ref)
244{
245 struct batadv_tt_local_entry *tt_local_entry;
246
247 tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
248 common.refcount);
249
a33d970d
SE
250 batadv_softif_vlan_put(tt_local_entry->vlan);
251
86452f81 252 call_rcu(&tt_local_entry->common.rcu, batadv_tt_local_entry_free_rcu);
92dcdf09
SE
253}
254
255/**
7e9a8c2c 256 * batadv_tt_local_entry_put() - decrement the tt_local_entry refcounter and
92dcdf09
SE
257 * possibly release it
258 * @tt_local_entry: tt_local_entry to be free'd
259 */
a513088d 260static void
95c0db90 261batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry)
7683fdc1 262{
92dcdf09
SE
263 kref_put(&tt_local_entry->common.refcount,
264 batadv_tt_local_entry_release);
7683fdc1
AQ
265}
266
86452f81 267/**
7e9a8c2c 268 * batadv_tt_global_entry_free_rcu() - free the tt_global_entry
86452f81
SE
269 * @rcu: rcu pointer of the tt_global_entry
270 */
271static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
272{
273 struct batadv_tt_global_entry *tt_global_entry;
274
275 tt_global_entry = container_of(rcu, struct batadv_tt_global_entry,
276 common.rcu);
277
278 kmem_cache_free(batadv_tg_cache, tt_global_entry);
279}
280
21026059 281/**
7e9a8c2c
SE
282 * batadv_tt_global_entry_release() - release tt_global_entry from lists and
283 * queue for free after rcu grace period
92dcdf09
SE
284 * @ref: kref pointer of the nc_node
285 */
286static void batadv_tt_global_entry_release(struct kref *ref)
287{
288 struct batadv_tt_global_entry *tt_global_entry;
289
290 tt_global_entry = container_of(ref, struct batadv_tt_global_entry,
291 common.refcount);
292
293 batadv_tt_global_del_orig_list(tt_global_entry);
86452f81
SE
294
295 call_rcu(&tt_global_entry->common.rcu, batadv_tt_global_entry_free_rcu);
92dcdf09
SE
296}
297
298/**
7e9a8c2c 299 * batadv_tt_global_entry_put() - decrement the tt_global_entry refcounter and
5dafd8a6 300 * possibly release it
92dcdf09 301 * @tt_global_entry: tt_global_entry to be free'd
21026059 302 */
a513088d 303static void
5dafd8a6 304batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry)
7683fdc1 305{
92dcdf09
SE
306 kref_put(&tt_global_entry->common.refcount,
307 batadv_tt_global_entry_release);
db08e6e5
SW
308}
309
1d8ab8d3 310/**
7e9a8c2c 311 * batadv_tt_global_hash_count() - count the number of orig entries
d15cd622 312 * @bat_priv: the bat priv with all the soft interface information
1d8ab8d3
LL
313 * @addr: the mac address of the client to count entries for
314 * @vid: VLAN identifier
315 *
62fe710f 316 * Return: the number of originators advertising the given address/data
1d8ab8d3
LL
317 * (excluding ourself).
318 */
319int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
6b5e971a 320 const u8 *addr, unsigned short vid)
1d8ab8d3
LL
321{
322 struct batadv_tt_global_entry *tt_global_entry;
323 int count;
324
325 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
326 if (!tt_global_entry)
327 return 0;
328
329 count = atomic_read(&tt_global_entry->orig_list_count);
5dafd8a6 330 batadv_tt_global_entry_put(tt_global_entry);
1d8ab8d3
LL
331
332 return count;
333}
334
7ea7b4a1 335/**
7e9a8c2c
SE
336 * batadv_tt_local_size_mod() - change the size by v of the local table
337 * identified by vid
7ea7b4a1
AQ
338 * @bat_priv: the bat priv with all the soft interface information
339 * @vid: the VLAN identifier of the sub-table to change
340 * @v: the amount to sum to the local table size
341 */
342static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
343 unsigned short vid, int v)
344{
345 struct batadv_softif_vlan *vlan;
346
347 vlan = batadv_softif_vlan_get(bat_priv, vid);
348 if (!vlan)
349 return;
350
351 atomic_add(v, &vlan->tt.num_entries);
352
9c3bf081 353 batadv_softif_vlan_put(vlan);
7ea7b4a1
AQ
354}
355
356/**
7e9a8c2c
SE
357 * batadv_tt_local_size_inc() - increase by one the local table size for the
358 * given vid
7ea7b4a1
AQ
359 * @bat_priv: the bat priv with all the soft interface information
360 * @vid: the VLAN identifier
361 */
362static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
363 unsigned short vid)
364{
365 batadv_tt_local_size_mod(bat_priv, vid, 1);
366}
367
368/**
7e9a8c2c
SE
369 * batadv_tt_local_size_dec() - decrease by one the local table size for the
370 * given vid
7ea7b4a1
AQ
371 * @bat_priv: the bat priv with all the soft interface information
372 * @vid: the VLAN identifier
373 */
374static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
375 unsigned short vid)
376{
377 batadv_tt_local_size_mod(bat_priv, vid, -1);
378}
379
380/**
7e9a8c2c 381 * batadv_tt_global_size_mod() - change the size by v of the global table
d15cd622
AQ
382 * for orig_node identified by vid
383 * @orig_node: the originator for which the table has to be modified
7ea7b4a1
AQ
384 * @vid: the VLAN identifier
385 * @v: the amount to sum to the global table size
386 */
387static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
388 unsigned short vid, int v)
389{
390 struct batadv_orig_node_vlan *vlan;
391
392 vlan = batadv_orig_node_vlan_new(orig_node, vid);
393 if (!vlan)
394 return;
395
396 if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
397 spin_lock_bh(&orig_node->vlan_list_lock);
3db15209
SE
398 if (!hlist_unhashed(&vlan->list)) {
399 hlist_del_init_rcu(&vlan->list);
21754e25 400 batadv_orig_node_vlan_put(vlan);
3db15209 401 }
7ea7b4a1 402 spin_unlock_bh(&orig_node->vlan_list_lock);
7ea7b4a1
AQ
403 }
404
21754e25 405 batadv_orig_node_vlan_put(vlan);
7ea7b4a1
AQ
406}
407
408/**
7e9a8c2c 409 * batadv_tt_global_size_inc() - increase by one the global table size for the
7ea7b4a1
AQ
410 * given vid
411 * @orig_node: the originator which global table size has to be decreased
412 * @vid: the vlan identifier
413 */
414static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
415 unsigned short vid)
416{
417 batadv_tt_global_size_mod(orig_node, vid, 1);
418}
419
420/**
7e9a8c2c 421 * batadv_tt_global_size_dec() - decrease by one the global table size for the
7ea7b4a1
AQ
422 * given vid
423 * @orig_node: the originator which global table size has to be decreased
424 * @vid: the vlan identifier
425 */
426static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
427 unsigned short vid)
428{
429 batadv_tt_global_size_mod(orig_node, vid, -1);
430}
431
86452f81 432/**
7e9a8c2c 433 * batadv_tt_orig_list_entry_free_rcu() - free the orig_entry
86452f81
SE
434 * @rcu: rcu pointer of the orig_entry
435 */
436static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
437{
438 struct batadv_tt_orig_list_entry *orig_entry;
439
440 orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
441
442 kmem_cache_free(batadv_tt_orig_cache, orig_entry);
443}
444
42eff6a6 445/**
7e9a8c2c 446 * batadv_tt_orig_list_entry_release() - release tt orig entry from lists and
42eff6a6 447 * queue for free after rcu grace period
6e8ef69d 448 * @ref: kref pointer of the tt orig entry
42eff6a6 449 */
6e8ef69d 450static void batadv_tt_orig_list_entry_release(struct kref *ref)
42eff6a6 451{
6e8ef69d
SE
452 struct batadv_tt_orig_list_entry *orig_entry;
453
454 orig_entry = container_of(ref, struct batadv_tt_orig_list_entry,
455 refcount);
456
5d967310 457 batadv_orig_node_put(orig_entry->orig_node);
86452f81 458 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
42eff6a6
SE
459}
460
6e8ef69d 461/**
7e9a8c2c 462 * batadv_tt_orig_list_entry_put() - decrement the tt orig entry refcounter and
7e2366c6 463 * possibly release it
6e8ef69d
SE
464 * @orig_entry: tt orig entry to be free'd
465 */
a513088d 466static void
7e2366c6 467batadv_tt_orig_list_entry_put(struct batadv_tt_orig_list_entry *orig_entry)
db08e6e5 468{
6e8ef69d 469 kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release);
7683fdc1
AQ
470}
471
3abe4adb 472/**
7e9a8c2c 473 * batadv_tt_local_event() - store a local TT event (ADD/DEL)
3abe4adb
AQ
474 * @bat_priv: the bat priv with all the soft interface information
475 * @tt_local_entry: the TT entry involved in the event
476 * @event_flags: flags to store in the event structure
477 */
56303d34 478static void batadv_tt_local_event(struct batadv_priv *bat_priv,
3abe4adb 479 struct batadv_tt_local_entry *tt_local_entry,
6b5e971a 480 u8 event_flags)
a73105b8 481{
56303d34 482 struct batadv_tt_change_node *tt_change_node, *entry, *safe;
3abe4adb 483 struct batadv_tt_common_entry *common = &tt_local_entry->common;
6b5e971a 484 u8 flags = common->flags | event_flags;
3b643de5
AQ
485 bool event_removed = false;
486 bool del_op_requested, del_op_entry;
a73105b8 487
86452f81 488 tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC);
a73105b8
AQ
489 if (!tt_change_node)
490 return;
491
ff66c975 492 tt_change_node->change.flags = flags;
ca663046
AQ
493 memset(tt_change_node->change.reserved, 0,
494 sizeof(tt_change_node->change.reserved));
8fdd0153 495 ether_addr_copy(tt_change_node->change.addr, common->addr);
c018ad3d 496 tt_change_node->change.vid = htons(common->vid);
a73105b8 497
acd34afa 498 del_op_requested = flags & BATADV_TT_CLIENT_DEL;
3b643de5
AQ
499
500 /* check for ADD+DEL or DEL+ADD events */
807736f6
SE
501 spin_lock_bh(&bat_priv->tt.changes_list_lock);
502 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
3b643de5 503 list) {
3abe4adb 504 if (!batadv_compare_eth(entry->change.addr, common->addr))
3b643de5
AQ
505 continue;
506
507 /* DEL+ADD in the same orig interval have no effect and can be
508 * removed to avoid silly behaviour on the receiver side. The
509 * other way around (ADD+DEL) can happen in case of roaming of
510 * a client still in the NEW state. Roaming of NEW clients is
511 * now possible due to automatically recognition of "temporary"
512 * clients
513 */
acd34afa 514 del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
3b643de5
AQ
515 if (!del_op_requested && del_op_entry)
516 goto del;
517 if (del_op_requested && !del_op_entry)
518 goto del;
3c4f7ab6
AQ
519
520 /* this is a second add in the same originator interval. It
521 * means that flags have been changed: update them!
522 */
523 if (!del_op_requested && !del_op_entry)
524 entry->change.flags = flags;
525
3b643de5
AQ
526 continue;
527del:
528 list_del(&entry->list);
86452f81
SE
529 kmem_cache_free(batadv_tt_change_cache, entry);
530 kmem_cache_free(batadv_tt_change_cache, tt_change_node);
3b643de5
AQ
531 event_removed = true;
532 goto unlock;
533 }
534
a73105b8 535 /* track the change in the OGMinterval list */
807736f6 536 list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
3b643de5
AQ
537
538unlock:
807736f6 539 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8 540
3b643de5 541 if (event_removed)
807736f6 542 atomic_dec(&bat_priv->tt.local_changes);
3b643de5 543 else
807736f6 544 atomic_inc(&bat_priv->tt.local_changes);
a73105b8
AQ
545}
546
335fbe0f 547/**
7e9a8c2c 548 * batadv_tt_len() - compute length in bytes of given number of tt changes
335fbe0f
ML
549 * @changes_num: number of tt changes
550 *
62fe710f 551 * Return: computed length in bytes.
335fbe0f
ML
552 */
553static int batadv_tt_len(int changes_num)
a73105b8 554{
335fbe0f 555 return changes_num * sizeof(struct batadv_tvlv_tt_change);
a73105b8
AQ
556}
557
298e6e68 558/**
7e9a8c2c 559 * batadv_tt_entries() - compute the number of entries fitting in tt_len bytes
298e6e68
AQ
560 * @tt_len: available space
561 *
62fe710f 562 * Return: the number of entries.
298e6e68 563 */
6b5e971a 564static u16 batadv_tt_entries(u16 tt_len)
298e6e68
AQ
565{
566 return tt_len / batadv_tt_len(1);
567}
568
a19d3d85 569/**
7e9a8c2c
SE
570 * batadv_tt_local_table_transmit_size() - calculates the local translation
571 * table size when transmitted over the air
a19d3d85
ML
572 * @bat_priv: the bat priv with all the soft interface information
573 *
62fe710f 574 * Return: local translation table size in bytes.
a19d3d85
ML
575 */
576static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
577{
4f248cff
SE
578 u16 num_vlan = 0;
579 u16 tt_local_entries = 0;
a19d3d85
ML
580 struct batadv_softif_vlan *vlan;
581 int hdr_size;
582
583 rcu_read_lock();
584 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
585 num_vlan++;
586 tt_local_entries += atomic_read(&vlan->tt.num_entries);
587 }
588 rcu_read_unlock();
589
590 /* header size of tvlv encapsulated tt response payload */
591 hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
592 hdr_size += sizeof(struct batadv_tvlv_hdr);
593 hdr_size += sizeof(struct batadv_tvlv_tt_data);
594 hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
595
596 return hdr_size + batadv_tt_len(tt_local_entries);
597}
598
56303d34 599static int batadv_tt_local_init(struct batadv_priv *bat_priv)
c6c8fea2 600{
807736f6 601 if (bat_priv->tt.local_hash)
5346c35e 602 return 0;
c6c8fea2 603
807736f6 604 bat_priv->tt.local_hash = batadv_hash_new(1024);
c6c8fea2 605
807736f6 606 if (!bat_priv->tt.local_hash)
5346c35e 607 return -ENOMEM;
c6c8fea2 608
dec05074
AQ
609 batadv_hash_set_lock_class(bat_priv->tt.local_hash,
610 &batadv_tt_local_hash_lock_class_key);
611
5346c35e 612 return 0;
c6c8fea2
SE
613}
614
068ee6e2
AQ
615static void batadv_tt_global_free(struct batadv_priv *bat_priv,
616 struct batadv_tt_global_entry *tt_global,
617 const char *message)
618{
619 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
620 "Deleting global tt entry %pM (vid: %d): %s\n",
621 tt_global->common.addr,
f7a2bd65 622 batadv_print_vid(tt_global->common.vid), message);
068ee6e2
AQ
623
624 batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
c018ad3d 625 batadv_choose_tt, &tt_global->common);
5dafd8a6 626 batadv_tt_global_entry_put(tt_global);
068ee6e2
AQ
627}
628
c018ad3d 629/**
7e9a8c2c 630 * batadv_tt_local_add() - add a new client to the local table or update an
c018ad3d
AQ
631 * existing client
632 * @soft_iface: netdev struct of the mesh interface
633 * @addr: the mac address of the client to add
634 * @vid: VLAN identifier
635 * @ifindex: index of the interface where the client is connected to (useful to
636 * identify wireless clients)
9464d071
AQ
637 * @mark: the value contained in the skb->mark field of the received packet (if
638 * any)
a19d3d85 639 *
62fe710f 640 * Return: true if the client was successfully added, false otherwise.
c018ad3d 641 */
6b5e971a
SE
642bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
643 unsigned short vid, int ifindex, u32 mark)
c6c8fea2 644{
56303d34 645 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
170173bf 646 struct batadv_tt_local_entry *tt_local;
c5caf4ef 647 struct batadv_tt_global_entry *tt_global = NULL;
2cd45a06 648 struct net *net = dev_net(soft_iface);
35df3b29 649 struct batadv_softif_vlan *vlan;
0c69aecc 650 struct net_device *in_dev = NULL;
10b1bbb4 651 struct batadv_hard_iface *in_hardif = NULL;
db08e6e5 652 struct hlist_head *head;
56303d34 653 struct batadv_tt_orig_list_entry *orig_entry;
a19d3d85 654 int hash_added, table_size, packet_size_max;
4f248cff
SE
655 bool ret = false;
656 bool roamed_back = false;
6b5e971a
SE
657 u8 remote_flags;
658 u32 match_mark;
c6c8fea2 659
0c69aecc 660 if (ifindex != BATADV_NULL_IFINDEX)
2cd45a06 661 in_dev = dev_get_by_index(net, ifindex);
0c69aecc 662
10b1bbb4
SE
663 if (in_dev)
664 in_hardif = batadv_hardif_get_by_netdev(in_dev);
665
c018ad3d 666 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
c5caf4ef
LL
667
668 if (!is_multicast_ether_addr(addr))
669 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
c6c8fea2 670
47c94655
AQ
671 if (tt_local) {
672 tt_local->last_seen = jiffies;
068ee6e2
AQ
673 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
674 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 675 "Re-adding pending client %pM (vid: %d)\n",
f7a2bd65 676 addr, batadv_print_vid(vid));
068ee6e2
AQ
677 /* whatever the reason why the PENDING flag was set,
678 * this is a client which was enqueued to be removed in
679 * this orig_interval. Since it popped up again, the
680 * flag can be reset like it was never enqueued
681 */
682 tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
683 goto add_event;
684 }
685
686 if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
687 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 688 "Roaming client %pM (vid: %d) came back to its original location\n",
f7a2bd65 689 addr, batadv_print_vid(vid));
068ee6e2
AQ
690 /* the ROAM flag is set because this client roamed away
691 * and the node got a roaming_advertisement message. Now
692 * that the client popped up again at its original
693 * location such flag can be unset
694 */
695 tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
696 roamed_back = true;
697 }
698 goto check_roaming;
c6c8fea2
SE
699 }
700
a19d3d85
ML
701 /* Ignore the client if we cannot send it in a full table response. */
702 table_size = batadv_tt_local_table_transmit_size(bat_priv);
703 table_size += batadv_tt_len(1);
704 packet_size_max = atomic_read(&bat_priv->packet_size_max);
705 if (table_size > packet_size_max) {
706 net_ratelimited_function(batadv_info, soft_iface,
707 "Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
708 table_size, packet_size_max, addr);
709 goto out;
710 }
711
86452f81 712 tt_local = kmem_cache_alloc(batadv_tl_cache, GFP_ATOMIC);
47c94655 713 if (!tt_local)
7683fdc1 714 goto out;
a73105b8 715
35df3b29
AQ
716 /* increase the refcounter of the related vlan */
717 vlan = batadv_softif_vlan_get(bat_priv, vid);
0b3dd7df
SW
718 if (!vlan) {
719 net_ratelimited_function(batadv_info, soft_iface,
720 "adding TT local entry %pM to non-existent VLAN %d\n",
f7a2bd65 721 addr, batadv_print_vid(vid));
86452f81 722 kmem_cache_free(batadv_tl_cache, tt_local);
fd7dec25 723 tt_local = NULL;
354136bc 724 goto out;
fd7dec25 725 }
35df3b29 726
39c75a51 727 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 728 "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
f7a2bd65 729 addr, batadv_print_vid(vid),
6b5e971a 730 (u8)atomic_read(&bat_priv->tt.vn));
c6c8fea2 731
8fdd0153 732 ether_addr_copy(tt_local->common.addr, addr);
8425ec6a
AQ
733 /* The local entry has to be marked as NEW to avoid to send it in
734 * a full table response going out before the next ttvn increment
735 * (consistency check)
736 */
737 tt_local->common.flags = BATADV_TT_CLIENT_NEW;
c018ad3d 738 tt_local->common.vid = vid;
10b1bbb4 739 if (batadv_is_wifi_hardif(in_hardif))
47c94655 740 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
92dcdf09 741 kref_init(&tt_local->common.refcount);
47c94655
AQ
742 tt_local->last_seen = jiffies;
743 tt_local->common.added_at = tt_local->last_seen;
a33d970d 744 tt_local->vlan = vlan;
c6c8fea2 745
c5caf4ef
LL
746 /* the batman interface mac and multicast addresses should never be
747 * purged
748 */
749 if (batadv_compare_eth(addr, soft_iface->dev_addr) ||
750 is_multicast_ether_addr(addr))
47c94655 751 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
c6c8fea2 752
e3387b26 753 kref_get(&tt_local->common.refcount);
807736f6 754 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
c018ad3d 755 batadv_choose_tt, &tt_local->common,
47c94655 756 &tt_local->common.hash_entry);
80b3f58c
SW
757
758 if (unlikely(hash_added != 0)) {
759 /* remove the reference for the hash */
95c0db90 760 batadv_tt_local_entry_put(tt_local);
80b3f58c
SW
761 goto out;
762 }
763
068ee6e2 764add_event:
3abe4adb 765 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
ff66c975 766
068ee6e2
AQ
767check_roaming:
768 /* Check whether it is a roaming, but don't do anything if the roaming
769 * process has already been handled
770 */
771 if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
db08e6e5 772 /* These node are probably going to update their tt table */
47c94655 773 head = &tt_global->orig_list;
db08e6e5 774 rcu_read_lock();
b67bfe0d 775 hlist_for_each_entry_rcu(orig_entry, head, list) {
47c94655 776 batadv_send_roam_adv(bat_priv, tt_global->common.addr,
c018ad3d 777 tt_global->common.vid,
a513088d 778 orig_entry->orig_node);
db08e6e5
SW
779 }
780 rcu_read_unlock();
068ee6e2
AQ
781 if (roamed_back) {
782 batadv_tt_global_free(bat_priv, tt_global,
783 "Roaming canceled");
784 tt_global = NULL;
785 } else {
786 /* The global entry has to be marked as ROAMING and
787 * has to be kept for consistency purpose
788 */
789 tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
790 tt_global->roam_at = jiffies;
791 }
7683fdc1 792 }
068ee6e2 793
3c4f7ab6
AQ
794 /* store the current remote flags before altering them. This helps
795 * understanding is flags are changing or not
796 */
797 remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
798
10b1bbb4 799 if (batadv_is_wifi_hardif(in_hardif))
3c4f7ab6
AQ
800 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
801 else
802 tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
a19d3d85 803
9464d071
AQ
804 /* check the mark in the skb: if it's equal to the configured
805 * isolation_mark, it means the packet is coming from an isolated
806 * non-mesh client
807 */
808 match_mark = (mark & bat_priv->isolation_mark_mask);
809 if (bat_priv->isolation_mark_mask &&
810 match_mark == bat_priv->isolation_mark)
811 tt_local->common.flags |= BATADV_TT_CLIENT_ISOLA;
812 else
813 tt_local->common.flags &= ~BATADV_TT_CLIENT_ISOLA;
814
3c4f7ab6
AQ
815 /* if any "dynamic" flag has been modified, resend an ADD event for this
816 * entry so that all the nodes can get the new flags
817 */
818 if (remote_flags ^ (tt_local->common.flags & BATADV_TT_REMOTE_MASK))
819 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
820
821 ret = true;
7683fdc1 822out:
10b1bbb4
SE
823 if (in_hardif)
824 batadv_hardif_put(in_hardif);
0c69aecc
AQ
825 if (in_dev)
826 dev_put(in_dev);
47c94655 827 if (tt_local)
95c0db90 828 batadv_tt_local_entry_put(tt_local);
47c94655 829 if (tt_global)
5dafd8a6 830 batadv_tt_global_entry_put(tt_global);
a19d3d85 831 return ret;
c6c8fea2
SE
832}
833
7ea7b4a1 834/**
7e9a8c2c 835 * batadv_tt_prepare_tvlv_global_data() - prepare the TVLV TT header to send
7ea7b4a1
AQ
836 * within a TT Response directed to another node
837 * @orig_node: originator for which the TT data has to be prepared
838 * @tt_data: uninitialised pointer to the address of the TVLV buffer
839 * @tt_change: uninitialised pointer to the address of the area where the TT
840 * changed can be stored
841 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
842 * function reserves the amount of space needed to send the entire global TT
843 * table. In case of success the value is updated with the real amount of
844 * reserved bytes
7ea7b4a1
AQ
845 * Allocate the needed amount of memory for the entire TT TVLV and write its
846 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
847 * objects, one per active VLAN served by the originator node.
848 *
62fe710f 849 * Return: the size of the allocated buffer or 0 in case of failure.
7ea7b4a1 850 */
6b5e971a 851static u16
7ea7b4a1
AQ
852batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
853 struct batadv_tvlv_tt_data **tt_data,
854 struct batadv_tvlv_tt_change **tt_change,
6b5e971a 855 s32 *tt_len)
7ea7b4a1 856{
4f248cff
SE
857 u16 num_vlan = 0;
858 u16 num_entries = 0;
859 u16 change_offset;
860 u16 tvlv_len;
7ea7b4a1
AQ
861 struct batadv_tvlv_tt_vlan_data *tt_vlan;
862 struct batadv_orig_node_vlan *vlan;
6b5e971a 863 u8 *tt_change_ptr;
7ea7b4a1 864
8ba0f9bd 865 spin_lock_bh(&orig_node->vlan_list_lock);
d0fa4f3f 866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
7ea7b4a1
AQ
867 num_vlan++;
868 num_entries += atomic_read(&vlan->tt.num_entries);
869 }
870
871 change_offset = sizeof(**tt_data);
872 change_offset += num_vlan * sizeof(*tt_vlan);
873
874 /* if tt_len is negative, allocate the space needed by the full table */
875 if (*tt_len < 0)
876 *tt_len = batadv_tt_len(num_entries);
877
878 tvlv_len = *tt_len;
879 tvlv_len += change_offset;
880
881 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
882 if (!*tt_data) {
883 *tt_len = 0;
884 goto out;
885 }
886
887 (*tt_data)->flags = BATADV_NO_FLAGS;
888 (*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
889 (*tt_data)->num_vlan = htons(num_vlan);
890
891 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
d0fa4f3f 892 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
7ea7b4a1
AQ
893 tt_vlan->vid = htons(vlan->vid);
894 tt_vlan->crc = htonl(vlan->tt.crc);
895
896 tt_vlan++;
897 }
898
6b5e971a 899 tt_change_ptr = (u8 *)*tt_data + change_offset;
7ea7b4a1
AQ
900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
901
902out:
8ba0f9bd 903 spin_unlock_bh(&orig_node->vlan_list_lock);
7ea7b4a1
AQ
904 return tvlv_len;
905}
906
907/**
7e9a8c2c
SE
908 * batadv_tt_prepare_tvlv_local_data() - allocate and prepare the TT TVLV for
909 * this node
7ea7b4a1
AQ
910 * @bat_priv: the bat priv with all the soft interface information
911 * @tt_data: uninitialised pointer to the address of the TVLV buffer
912 * @tt_change: uninitialised pointer to the address of the area where the TT
913 * changes can be stored
914 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
915 * function reserves the amount of space needed to send the entire local TT
916 * table. In case of success the value is updated with the real amount of
917 * reserved bytes
918 *
919 * Allocate the needed amount of memory for the entire TT TVLV and write its
920 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
921 * objects, one per active VLAN.
922 *
62fe710f 923 * Return: the size of the allocated buffer or 0 in case of failure.
7ea7b4a1 924 */
6b5e971a 925static u16
7ea7b4a1
AQ
926batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
927 struct batadv_tvlv_tt_data **tt_data,
928 struct batadv_tvlv_tt_change **tt_change,
6b5e971a 929 s32 *tt_len)
7ea7b4a1
AQ
930{
931 struct batadv_tvlv_tt_vlan_data *tt_vlan;
932 struct batadv_softif_vlan *vlan;
4f248cff
SE
933 u16 num_vlan = 0;
934 u16 num_entries = 0;
935 u16 tvlv_len;
6b5e971a 936 u8 *tt_change_ptr;
7ea7b4a1
AQ
937 int change_offset;
938
8ba0f9bd 939 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
7ea7b4a1
AQ
940 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
941 num_vlan++;
942 num_entries += atomic_read(&vlan->tt.num_entries);
943 }
944
945 change_offset = sizeof(**tt_data);
946 change_offset += num_vlan * sizeof(*tt_vlan);
947
948 /* if tt_len is negative, allocate the space needed by the full table */
949 if (*tt_len < 0)
950 *tt_len = batadv_tt_len(num_entries);
951
952 tvlv_len = *tt_len;
953 tvlv_len += change_offset;
954
955 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
956 if (!*tt_data) {
957 tvlv_len = 0;
958 goto out;
959 }
960
961 (*tt_data)->flags = BATADV_NO_FLAGS;
962 (*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
963 (*tt_data)->num_vlan = htons(num_vlan);
964
965 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
966 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
967 tt_vlan->vid = htons(vlan->vid);
968 tt_vlan->crc = htonl(vlan->tt.crc);
969
970 tt_vlan++;
971 }
972
6b5e971a 973 tt_change_ptr = (u8 *)*tt_data + change_offset;
7ea7b4a1
AQ
974 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
975
976out:
8ba0f9bd 977 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
7ea7b4a1
AQ
978 return tvlv_len;
979}
980
e1bf0c14 981/**
7e9a8c2c
SE
982 * batadv_tt_tvlv_container_update() - update the translation table tvlv
983 * container after local tt changes have been committed
e1bf0c14
ML
984 * @bat_priv: the bat priv with all the soft interface information
985 */
986static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
be9aa4c1 987{
e1bf0c14
ML
988 struct batadv_tt_change_node *entry, *safe;
989 struct batadv_tvlv_tt_data *tt_data;
990 struct batadv_tvlv_tt_change *tt_change;
7ea7b4a1 991 int tt_diff_len, tt_change_len = 0;
4f248cff
SE
992 int tt_diff_entries_num = 0;
993 int tt_diff_entries_count = 0;
6b5e971a 994 u16 tvlv_len;
be9aa4c1 995
7ea7b4a1
AQ
996 tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
997 tt_diff_len = batadv_tt_len(tt_diff_entries_num);
be9aa4c1
ML
998
999 /* if we have too many changes for one packet don't send any
1000 * and wait for the tt table request which will be fragmented
1001 */
e1bf0c14
ML
1002 if (tt_diff_len > bat_priv->soft_iface->mtu)
1003 tt_diff_len = 0;
be9aa4c1 1004
7ea7b4a1
AQ
1005 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
1006 &tt_change, &tt_diff_len);
1007 if (!tvlv_len)
e1bf0c14 1008 return;
be9aa4c1 1009
e1bf0c14 1010 tt_data->flags = BATADV_TT_OGM_DIFF;
c6c8fea2 1011
e1bf0c14
ML
1012 if (tt_diff_len == 0)
1013 goto container_register;
be9aa4c1 1014
807736f6
SE
1015 spin_lock_bh(&bat_priv->tt.changes_list_lock);
1016 atomic_set(&bat_priv->tt.local_changes, 0);
c6c8fea2 1017
807736f6 1018 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
7c64fd98 1019 list) {
e1bf0c14
ML
1020 if (tt_diff_entries_count < tt_diff_entries_num) {
1021 memcpy(tt_change + tt_diff_entries_count,
1022 &entry->change,
1023 sizeof(struct batadv_tvlv_tt_change));
1024 tt_diff_entries_count++;
c6c8fea2 1025 }
a73105b8 1026 list_del(&entry->list);
86452f81 1027 kmem_cache_free(batadv_tt_change_cache, entry);
c6c8fea2 1028 }
807736f6 1029 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8
AQ
1030
1031 /* Keep the buffer for possible tt_request */
807736f6
SE
1032 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1033 kfree(bat_priv->tt.last_changeset);
1034 bat_priv->tt.last_changeset_len = 0;
1035 bat_priv->tt.last_changeset = NULL;
e1bf0c14 1036 tt_change_len = batadv_tt_len(tt_diff_entries_count);
be9aa4c1 1037 /* check whether this new OGM has no changes due to size problems */
e1bf0c14 1038 if (tt_diff_entries_count > 0) {
be9aa4c1 1039 /* if kmalloc() fails we will reply with the full table
a73105b8
AQ
1040 * instead of providing the diff
1041 */
e1bf0c14 1042 bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
807736f6 1043 if (bat_priv->tt.last_changeset) {
e1bf0c14
ML
1044 memcpy(bat_priv->tt.last_changeset,
1045 tt_change, tt_change_len);
1046 bat_priv->tt.last_changeset_len = tt_diff_len;
a73105b8
AQ
1047 }
1048 }
807736f6 1049 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
c6c8fea2 1050
e1bf0c14
ML
1051container_register:
1052 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
7ea7b4a1 1053 tvlv_len);
e1bf0c14 1054 kfree(tt_data);
c6c8fea2
SE
1055}
1056
dc1cbd14 1057#ifdef CONFIG_BATMAN_ADV_DEBUGFS
ff15c27c
SE
1058
1059/**
1060 * batadv_tt_local_seq_print_text() - Print the local tt table in a seq file
1061 * @seq: seq file to print on
1062 * @offset: not used
1063 *
1064 * Return: always 0
1065 */
08c36d3e 1066int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea2
SE
1067{
1068 struct net_device *net_dev = (struct net_device *)seq->private;
56303d34 1069 struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6 1070 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34 1071 struct batadv_tt_common_entry *tt_common_entry;
85766a82 1072 struct batadv_tt_local_entry *tt_local;
56303d34 1073 struct batadv_hard_iface *primary_if;
c6c8fea2 1074 struct hlist_head *head;
6b5e971a 1075 u32 i;
85766a82
AQ
1076 int last_seen_secs;
1077 int last_seen_msecs;
1078 unsigned long last_seen_jiffies;
1079 bool no_purge;
6b5e971a 1080 u16 np_flag = BATADV_TT_CLIENT_NOPURGE;
c6c8fea2 1081
30da63a6
ML
1082 primary_if = batadv_seq_print_text_primary_if_get(seq);
1083 if (!primary_if)
32ae9b22 1084 goto out;
c6c8fea2 1085
86ceb360 1086 seq_printf(seq,
7ea7b4a1 1087 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
6b5e971a 1088 net_dev->name, (u8)atomic_read(&bat_priv->tt.vn));
925a6f37
AQ
1089 seq_puts(seq,
1090 " Client VID Flags Last seen (CRC )\n");
c6c8fea2 1091
c6c8fea2
SE
1092 for (i = 0; i < hash->size; i++) {
1093 head = &hash->table[i];
1094
7aadf889 1095 rcu_read_lock();
b67bfe0d 1096 hlist_for_each_entry_rcu(tt_common_entry,
7aadf889 1097 head, hash_entry) {
85766a82
AQ
1098 tt_local = container_of(tt_common_entry,
1099 struct batadv_tt_local_entry,
1100 common);
1101 last_seen_jiffies = jiffies - tt_local->last_seen;
1102 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
1103 last_seen_secs = last_seen_msecs / 1000;
1104 last_seen_msecs = last_seen_msecs % 1000;
1105
1106 no_purge = tt_common_entry->flags & np_flag;
7ea7b4a1 1107 seq_printf(seq,
dd24ddb2 1108 " * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
7c64fd98 1109 tt_common_entry->addr,
f7a2bd65 1110 batadv_print_vid(tt_common_entry->vid),
a2f2b6cd
SE
1111 ((tt_common_entry->flags &
1112 BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
85766a82 1113 no_purge ? 'P' : '.',
a2f2b6cd
SE
1114 ((tt_common_entry->flags &
1115 BATADV_TT_CLIENT_NEW) ? 'N' : '.'),
1116 ((tt_common_entry->flags &
1117 BATADV_TT_CLIENT_PENDING) ? 'X' : '.'),
1118 ((tt_common_entry->flags &
1119 BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1120 ((tt_common_entry->flags &
1121 BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
a7966d90 1122 no_purge ? 0 : last_seen_secs,
7ea7b4a1 1123 no_purge ? 0 : last_seen_msecs,
a33d970d 1124 tt_local->vlan->tt.crc);
c6c8fea2 1125 }
7aadf889 1126 rcu_read_unlock();
c6c8fea2 1127 }
32ae9b22
ML
1128out:
1129 if (primary_if)
82047ad7 1130 batadv_hardif_put(primary_if);
30da63a6 1131 return 0;
c6c8fea2 1132}
dc1cbd14 1133#endif
c6c8fea2 1134
d34f0550 1135/**
7e9a8c2c 1136 * batadv_tt_local_dump_entry() - Dump one TT local entry into a message
d34f0550
MS
1137 * @msg :Netlink message to dump into
1138 * @portid: Port making netlink request
1139 * @seq: Sequence number of netlink message
1140 * @bat_priv: The bat priv with all the soft interface information
1141 * @common: tt local & tt global common data
1142 *
1143 * Return: Error code, or 0 on success
1144 */
1145static int
1146batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1147 struct batadv_priv *bat_priv,
1148 struct batadv_tt_common_entry *common)
1149{
1150 void *hdr;
1151 struct batadv_softif_vlan *vlan;
1152 struct batadv_tt_local_entry *local;
1153 unsigned int last_seen_msecs;
1154 u32 crc;
1155
1156 local = container_of(common, struct batadv_tt_local_entry, common);
1157 last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
1158
1159 vlan = batadv_softif_vlan_get(bat_priv, common->vid);
1160 if (!vlan)
1161 return 0;
1162
1163 crc = vlan->tt.crc;
1164
1165 batadv_softif_vlan_put(vlan);
1166
1167 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1168 NLM_F_MULTI,
1169 BATADV_CMD_GET_TRANSTABLE_LOCAL);
1170 if (!hdr)
1171 return -ENOBUFS;
1172
1173 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1174 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1175 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1176 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1177 goto nla_put_failure;
1178
1179 if (!(common->flags & BATADV_TT_CLIENT_NOPURGE) &&
1180 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, last_seen_msecs))
1181 goto nla_put_failure;
1182
1183 genlmsg_end(msg, hdr);
1184 return 0;
1185
1186 nla_put_failure:
1187 genlmsg_cancel(msg, hdr);
1188 return -EMSGSIZE;
1189}
1190
1191/**
7e9a8c2c 1192 * batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message
d34f0550
MS
1193 * @msg: Netlink message to dump into
1194 * @portid: Port making netlink request
1195 * @seq: Sequence number of netlink message
1196 * @bat_priv: The bat priv with all the soft interface information
1197 * @head: Pointer to the list containing the local tt entries
1198 * @idx_s: Number of entries to skip
1199 *
1200 * Return: Error code, or 0 on success
1201 */
1202static int
1203batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1204 struct batadv_priv *bat_priv,
1205 struct hlist_head *head, int *idx_s)
1206{
1207 struct batadv_tt_common_entry *common;
1208 int idx = 0;
1209
1210 rcu_read_lock();
1211 hlist_for_each_entry_rcu(common, head, hash_entry) {
1212 if (idx++ < *idx_s)
1213 continue;
1214
1215 if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
1216 common)) {
1217 rcu_read_unlock();
1218 *idx_s = idx - 1;
1219 return -EMSGSIZE;
1220 }
1221 }
1222 rcu_read_unlock();
1223
1224 *idx_s = 0;
1225 return 0;
1226}
1227
1228/**
7e9a8c2c 1229 * batadv_tt_local_dump() - Dump TT local entries into a message
d34f0550
MS
1230 * @msg: Netlink message to dump into
1231 * @cb: Parameters from query
1232 *
1233 * Return: Error code, or 0 on success
1234 */
1235int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
1236{
1237 struct net *net = sock_net(cb->skb->sk);
1238 struct net_device *soft_iface;
1239 struct batadv_priv *bat_priv;
1240 struct batadv_hard_iface *primary_if = NULL;
1241 struct batadv_hashtable *hash;
1242 struct hlist_head *head;
1243 int ret;
1244 int ifindex;
1245 int bucket = cb->args[0];
1246 int idx = cb->args[1];
1247 int portid = NETLINK_CB(cb->skb).portid;
1248
1249 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1250 if (!ifindex)
1251 return -EINVAL;
1252
1253 soft_iface = dev_get_by_index(net, ifindex);
1254 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1255 ret = -ENODEV;
1256 goto out;
1257 }
1258
1259 bat_priv = netdev_priv(soft_iface);
1260
1261 primary_if = batadv_primary_if_get_selected(bat_priv);
1262 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1263 ret = -ENOENT;
1264 goto out;
1265 }
1266
1267 hash = bat_priv->tt.local_hash;
1268
1269 while (bucket < hash->size) {
1270 head = &hash->table[bucket];
1271
1272 if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
1273 bat_priv, head, &idx))
1274 break;
1275
1276 bucket++;
1277 }
1278
1279 ret = msg->len;
1280
1281 out:
1282 if (primary_if)
1283 batadv_hardif_put(primary_if);
1284 if (soft_iface)
1285 dev_put(soft_iface);
1286
1287 cb->args[0] = bucket;
1288 cb->args[1] = idx;
1289
1290 return ret;
1291}
1292
56303d34
SE
1293static void
1294batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
1295 struct batadv_tt_local_entry *tt_local_entry,
6b5e971a 1296 u16 flags, const char *message)
c6c8fea2 1297{
3abe4adb 1298 batadv_tt_local_event(bat_priv, tt_local_entry, flags);
a73105b8 1299
015758d0
AQ
1300 /* The local client has to be marked as "pending to be removed" but has
1301 * to be kept in the table in order to send it in a full table
9cfc7bd6
SE
1302 * response issued before the net ttvn increment (consistency check)
1303 */
acd34afa 1304 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
c566dbbe 1305
39c75a51 1306 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
1307 "Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
1308 tt_local_entry->common.addr,
f7a2bd65 1309 batadv_print_vid(tt_local_entry->common.vid), message);
c6c8fea2
SE
1310}
1311
7f91d06c 1312/**
7e9a8c2c 1313 * batadv_tt_local_remove() - logically remove an entry from the local table
7f91d06c
AQ
1314 * @bat_priv: the bat priv with all the soft interface information
1315 * @addr: the MAC address of the client to remove
c018ad3d 1316 * @vid: VLAN identifier
7f91d06c
AQ
1317 * @message: message to append to the log on deletion
1318 * @roaming: true if the deletion is due to a roaming event
1319 *
62fe710f 1320 * Return: the flags assigned to the local entry before being deleted
7f91d06c 1321 */
6b5e971a
SE
1322u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
1323 unsigned short vid, const char *message,
1324 bool roaming)
c6c8fea2 1325{
170173bf 1326 struct batadv_tt_local_entry *tt_local_entry;
6b5e971a 1327 u16 flags, curr_flags = BATADV_NO_FLAGS;
ef72706a 1328 void *tt_entry_exists;
c6c8fea2 1329
c018ad3d 1330 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1
AQ
1331 if (!tt_local_entry)
1332 goto out;
1333
7f91d06c
AQ
1334 curr_flags = tt_local_entry->common.flags;
1335
acd34afa 1336 flags = BATADV_TT_CLIENT_DEL;
068ee6e2
AQ
1337 /* if this global entry addition is due to a roaming, the node has to
1338 * mark the local entry as "roamed" in order to correctly reroute
1339 * packets later
1340 */
7c1fd91d 1341 if (roaming) {
acd34afa 1342 flags |= BATADV_TT_CLIENT_ROAM;
7c1fd91d
AQ
1343 /* mark the local client as ROAMed */
1344 tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1345 }
42d0b044 1346
068ee6e2
AQ
1347 if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
1348 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
1349 message);
1350 goto out;
1351 }
1352 /* if this client has been added right now, it is possible to
1353 * immediately purge it
1354 */
3abe4adb 1355 batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
ef72706a
ML
1356
1357 tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
1358 batadv_compare_tt,
1359 batadv_choose_tt,
1360 &tt_local_entry->common);
1361 if (!tt_entry_exists)
1362 goto out;
1363
1364 /* extra call to free the local tt entry */
95c0db90 1365 batadv_tt_local_entry_put(tt_local_entry);
7f91d06c 1366
7683fdc1
AQ
1367out:
1368 if (tt_local_entry)
95c0db90 1369 batadv_tt_local_entry_put(tt_local_entry);
7f91d06c
AQ
1370
1371 return curr_flags;
c6c8fea2
SE
1372}
1373
a19d3d85 1374/**
7e9a8c2c 1375 * batadv_tt_local_purge_list() - purge inactive tt local entries
a19d3d85
ML
1376 * @bat_priv: the bat priv with all the soft interface information
1377 * @head: pointer to the list containing the local tt entries
1378 * @timeout: parameter deciding whether a given tt local entry is considered
1379 * inactive or not
1380 */
56303d34 1381static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
a19d3d85
ML
1382 struct hlist_head *head,
1383 int timeout)
c6c8fea2 1384{
56303d34
SE
1385 struct batadv_tt_local_entry *tt_local_entry;
1386 struct batadv_tt_common_entry *tt_common_entry;
b67bfe0d 1387 struct hlist_node *node_tmp;
acd34afa 1388
b67bfe0d 1389 hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
acd34afa
SE
1390 hash_entry) {
1391 tt_local_entry = container_of(tt_common_entry,
56303d34
SE
1392 struct batadv_tt_local_entry,
1393 common);
acd34afa
SE
1394 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
1395 continue;
1396
1397 /* entry already marked for deletion */
1398 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
1399 continue;
1400
a19d3d85 1401 if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
acd34afa
SE
1402 continue;
1403
1404 batadv_tt_local_set_pending(bat_priv, tt_local_entry,
1405 BATADV_TT_CLIENT_DEL, "timed out");
1406 }
1407}
1408
a19d3d85 1409/**
7e9a8c2c 1410 * batadv_tt_local_purge() - purge inactive tt local entries
a19d3d85
ML
1411 * @bat_priv: the bat priv with all the soft interface information
1412 * @timeout: parameter deciding whether a given tt local entry is considered
1413 * inactive or not
1414 */
1415static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
1416 int timeout)
acd34afa 1417{
807736f6 1418 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
c6c8fea2 1419 struct hlist_head *head;
7683fdc1 1420 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 1421 u32 i;
c6c8fea2 1422
c6c8fea2
SE
1423 for (i = 0; i < hash->size; i++) {
1424 head = &hash->table[i];
7683fdc1 1425 list_lock = &hash->list_locks[i];
c6c8fea2 1426
7683fdc1 1427 spin_lock_bh(list_lock);
a19d3d85 1428 batadv_tt_local_purge_list(bat_priv, head, timeout);
7683fdc1 1429 spin_unlock_bh(list_lock);
c6c8fea2 1430 }
c6c8fea2
SE
1431}
1432
56303d34 1433static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
c6c8fea2 1434{
5bf74e9c 1435 struct batadv_hashtable *hash;
a73105b8 1436 spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34
SE
1437 struct batadv_tt_common_entry *tt_common_entry;
1438 struct batadv_tt_local_entry *tt_local;
b67bfe0d 1439 struct hlist_node *node_tmp;
7683fdc1 1440 struct hlist_head *head;
6b5e971a 1441 u32 i;
a73105b8 1442
807736f6 1443 if (!bat_priv->tt.local_hash)
c6c8fea2
SE
1444 return;
1445
807736f6 1446 hash = bat_priv->tt.local_hash;
a73105b8
AQ
1447
1448 for (i = 0; i < hash->size; i++) {
1449 head = &hash->table[i];
1450 list_lock = &hash->list_locks[i];
1451
1452 spin_lock_bh(list_lock);
b67bfe0d 1453 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
a73105b8 1454 head, hash_entry) {
b67bfe0d 1455 hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34
SE
1456 tt_local = container_of(tt_common_entry,
1457 struct batadv_tt_local_entry,
1458 common);
35df3b29 1459
95c0db90 1460 batadv_tt_local_entry_put(tt_local);
a73105b8
AQ
1461 }
1462 spin_unlock_bh(list_lock);
1463 }
1464
1a8eaf07 1465 batadv_hash_destroy(hash);
a73105b8 1466
807736f6 1467 bat_priv->tt.local_hash = NULL;
c6c8fea2
SE
1468}
1469
56303d34 1470static int batadv_tt_global_init(struct batadv_priv *bat_priv)
c6c8fea2 1471{
807736f6 1472 if (bat_priv->tt.global_hash)
5346c35e 1473 return 0;
c6c8fea2 1474
807736f6 1475 bat_priv->tt.global_hash = batadv_hash_new(1024);
c6c8fea2 1476
807736f6 1477 if (!bat_priv->tt.global_hash)
5346c35e 1478 return -ENOMEM;
c6c8fea2 1479
dec05074
AQ
1480 batadv_hash_set_lock_class(bat_priv->tt.global_hash,
1481 &batadv_tt_global_hash_lock_class_key);
1482
5346c35e 1483 return 0;
c6c8fea2
SE
1484}
1485
56303d34 1486static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
c6c8fea2 1487{
56303d34 1488 struct batadv_tt_change_node *entry, *safe;
c6c8fea2 1489
807736f6 1490 spin_lock_bh(&bat_priv->tt.changes_list_lock);
c6c8fea2 1491
807736f6 1492 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
a73105b8
AQ
1493 list) {
1494 list_del(&entry->list);
86452f81 1495 kmem_cache_free(batadv_tt_change_cache, entry);
a73105b8 1496 }
c6c8fea2 1497
807736f6
SE
1498 atomic_set(&bat_priv->tt.local_changes, 0);
1499 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8 1500}
c6c8fea2 1501
62fe710f 1502/**
7e9a8c2c 1503 * batadv_tt_global_orig_entry_find() - find a TT orig_list_entry
d15cd622
AQ
1504 * @entry: the TT global entry where the orig_list_entry has to be
1505 * extracted from
1506 * @orig_node: the originator for which the orig_list_entry has to be found
62fe710f 1507 *
d15cd622 1508 * retrieve the orig_tt_list_entry belonging to orig_node from the
d657e621
AQ
1509 * batadv_tt_global_entry list
1510 *
62fe710f 1511 * Return: it with an increased refcounter, NULL if not found
db08e6e5 1512 */
d657e621
AQ
1513static struct batadv_tt_orig_list_entry *
1514batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1515 const struct batadv_orig_node *orig_node)
db08e6e5 1516{
d657e621 1517 struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
db08e6e5 1518 const struct hlist_head *head;
db08e6e5
SW
1519
1520 rcu_read_lock();
1521 head = &entry->orig_list;
b67bfe0d 1522 hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
d657e621
AQ
1523 if (tmp_orig_entry->orig_node != orig_node)
1524 continue;
6e8ef69d 1525 if (!kref_get_unless_zero(&tmp_orig_entry->refcount))
d657e621
AQ
1526 continue;
1527
1528 orig_entry = tmp_orig_entry;
1529 break;
db08e6e5
SW
1530 }
1531 rcu_read_unlock();
d657e621
AQ
1532
1533 return orig_entry;
1534}
1535
62fe710f 1536/**
7e9a8c2c
SE
1537 * batadv_tt_global_entry_has_orig() - check if a TT global entry is also
1538 * handled by a given originator
d15cd622
AQ
1539 * @entry: the TT global entry to check
1540 * @orig_node: the originator to search in the list
7072337e
LL
1541 * @flags: a pointer to store TT flags for the given @entry received
1542 * from @orig_node
62fe710f
SE
1543 *
1544 * find out if an orig_node is already in the list of a tt_global_entry.
1545 *
1546 * Return: true if found, false otherwise
d657e621
AQ
1547 */
1548static bool
1549batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
7072337e
LL
1550 const struct batadv_orig_node *orig_node,
1551 u8 *flags)
d657e621
AQ
1552{
1553 struct batadv_tt_orig_list_entry *orig_entry;
1554 bool found = false;
1555
1556 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
1557 if (orig_entry) {
1558 found = true;
7072337e
LL
1559
1560 if (flags)
1561 *flags = orig_entry->flags;
1562
7e2366c6 1563 batadv_tt_orig_list_entry_put(orig_entry);
d657e621
AQ
1564 }
1565
db08e6e5
SW
1566 return found;
1567}
1568
54e22f26 1569/**
7e9a8c2c 1570 * batadv_tt_global_sync_flags() - update TT sync flags
54e22f26
LL
1571 * @tt_global: the TT global entry to update sync flags in
1572 *
1573 * Updates the sync flag bits in the tt_global flag attribute with a logical
1574 * OR of all sync flags from any of its TT orig entries.
1575 */
1576static void
1577batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
1578{
1579 struct batadv_tt_orig_list_entry *orig_entry;
1580 const struct hlist_head *head;
1581 u16 flags = BATADV_NO_FLAGS;
1582
1583 rcu_read_lock();
1584 head = &tt_global->orig_list;
1585 hlist_for_each_entry_rcu(orig_entry, head, list)
1586 flags |= orig_entry->flags;
1587 rcu_read_unlock();
1588
1589 flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
1590 tt_global->common.flags = flags;
1591}
1592
1593/**
7e9a8c2c 1594 * batadv_tt_global_orig_entry_add() - add or update a TT orig entry
54e22f26
LL
1595 * @tt_global: the TT global entry to add an orig entry in
1596 * @orig_node: the originator to add an orig entry for
1597 * @ttvn: translation table version number of this changeset
1598 * @flags: TT sync flags
1599 */
a513088d 1600static void
d657e621 1601batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
54e22f26
LL
1602 struct batadv_orig_node *orig_node, int ttvn,
1603 u8 flags)
db08e6e5 1604{
56303d34 1605 struct batadv_tt_orig_list_entry *orig_entry;
db08e6e5 1606
d657e621 1607 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
30cfd02b
AQ
1608 if (orig_entry) {
1609 /* refresh the ttvn: the current value could be a bogus one that
1610 * was added during a "temporary client detection"
1611 */
1612 orig_entry->ttvn = ttvn;
54e22f26
LL
1613 orig_entry->flags = flags;
1614 goto sync_flags;
30cfd02b 1615 }
d657e621 1616
86452f81 1617 orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
db08e6e5 1618 if (!orig_entry)
d657e621 1619 goto out;
db08e6e5
SW
1620
1621 INIT_HLIST_NODE(&orig_entry->list);
7c124391 1622 kref_get(&orig_node->refcount);
7ea7b4a1 1623 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
db08e6e5
SW
1624 orig_entry->orig_node = orig_node;
1625 orig_entry->ttvn = ttvn;
54e22f26 1626 orig_entry->flags = flags;
6e8ef69d 1627 kref_init(&orig_entry->refcount);
db08e6e5 1628
d657e621 1629 spin_lock_bh(&tt_global->list_lock);
23f55485 1630 kref_get(&orig_entry->refcount);
db08e6e5 1631 hlist_add_head_rcu(&orig_entry->list,
d657e621
AQ
1632 &tt_global->orig_list);
1633 spin_unlock_bh(&tt_global->list_lock);
1d8ab8d3
LL
1634 atomic_inc(&tt_global->orig_list_count);
1635
54e22f26
LL
1636sync_flags:
1637 batadv_tt_global_sync_flags(tt_global);
d657e621
AQ
1638out:
1639 if (orig_entry)
7e2366c6 1640 batadv_tt_orig_list_entry_put(orig_entry);
db08e6e5
SW
1641}
1642
d4ff40f6 1643/**
7e9a8c2c 1644 * batadv_tt_global_add() - add a new TT global entry or update an existing one
d4ff40f6
AQ
1645 * @bat_priv: the bat priv with all the soft interface information
1646 * @orig_node: the originator announcing the client
1647 * @tt_addr: the mac address of the non-mesh client
c018ad3d 1648 * @vid: VLAN identifier
d4ff40f6
AQ
1649 * @flags: TT flags that have to be set for this non-mesh client
1650 * @ttvn: the tt version number ever announcing this non-mesh client
1651 *
1652 * Add a new TT global entry for the given originator. If the entry already
1653 * exists add a new reference to the given originator (a global entry can have
1654 * references to multiple originators) and adjust the flags attribute to reflect
1655 * the function argument.
1656 * If a TT local entry exists for this non-mesh client remove it.
1657 *
1658 * The caller must hold orig_node refcount.
1e5d49fc 1659 *
62fe710f 1660 * Return: true if the new entry has been added, false otherwise
d4ff40f6 1661 */
1e5d49fc
AQ
1662static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1663 struct batadv_orig_node *orig_node,
c018ad3d 1664 const unsigned char *tt_addr,
6b5e971a 1665 unsigned short vid, u16 flags, u8 ttvn)
a73105b8 1666{
170173bf
SE
1667 struct batadv_tt_global_entry *tt_global_entry;
1668 struct batadv_tt_local_entry *tt_local_entry;
1e5d49fc 1669 bool ret = false;
80b3f58c 1670 int hash_added;
56303d34 1671 struct batadv_tt_common_entry *common;
6b5e971a 1672 u16 local_flags;
c6c8fea2 1673
cfd4f757
AQ
1674 /* ignore global entries from backbone nodes */
1675 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
1676 return true;
1677
c018ad3d
AQ
1678 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
1679 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
068ee6e2
AQ
1680
1681 /* if the node already has a local client for this entry, it has to wait
1682 * for a roaming advertisement instead of manually messing up the global
1683 * table
1684 */
1685 if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
1686 !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
1687 goto out;
a73105b8
AQ
1688
1689 if (!tt_global_entry) {
86452f81
SE
1690 tt_global_entry = kmem_cache_zalloc(batadv_tg_cache,
1691 GFP_ATOMIC);
a73105b8 1692 if (!tt_global_entry)
7683fdc1
AQ
1693 goto out;
1694
c0a55929 1695 common = &tt_global_entry->common;
8fdd0153 1696 ether_addr_copy(common->addr, tt_addr);
c018ad3d 1697 common->vid = vid;
db08e6e5 1698
d4f44692 1699 common->flags = flags;
cc47f66e 1700 tt_global_entry->roam_at = 0;
fdf79320
AQ
1701 /* node must store current time in case of roaming. This is
1702 * needed to purge this entry out on timeout (if nobody claims
1703 * it)
1704 */
1705 if (flags & BATADV_TT_CLIENT_ROAM)
1706 tt_global_entry->roam_at = jiffies;
92dcdf09 1707 kref_init(&common->refcount);
30cfd02b 1708 common->added_at = jiffies;
db08e6e5
SW
1709
1710 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
1d8ab8d3 1711 atomic_set(&tt_global_entry->orig_list_count, 0);
db08e6e5 1712 spin_lock_init(&tt_global_entry->list_lock);
7683fdc1 1713
15d5ffde 1714 kref_get(&common->refcount);
807736f6 1715 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
a513088d 1716 batadv_compare_tt,
c018ad3d 1717 batadv_choose_tt, common,
a513088d 1718 &common->hash_entry);
80b3f58c
SW
1719
1720 if (unlikely(hash_added != 0)) {
1721 /* remove the reference for the hash */
5dafd8a6 1722 batadv_tt_global_entry_put(tt_global_entry);
80b3f58c
SW
1723 goto out_remove;
1724 }
a73105b8 1725 } else {
068ee6e2 1726 common = &tt_global_entry->common;
30cfd02b
AQ
1727 /* If there is already a global entry, we can use this one for
1728 * our processing.
068ee6e2
AQ
1729 * But if we are trying to add a temporary client then here are
1730 * two options at this point:
1731 * 1) the global client is not a temporary client: the global
1732 * client has to be left as it is, temporary information
1733 * should never override any already known client state
1734 * 2) the global client is a temporary client: purge the
1735 * originator list and add the new one orig_entry
30cfd02b 1736 */
068ee6e2
AQ
1737 if (flags & BATADV_TT_CLIENT_TEMP) {
1738 if (!(common->flags & BATADV_TT_CLIENT_TEMP))
1739 goto out;
1740 if (batadv_tt_global_entry_has_orig(tt_global_entry,
7072337e 1741 orig_node, NULL))
068ee6e2
AQ
1742 goto out_remove;
1743 batadv_tt_global_del_orig_list(tt_global_entry);
1744 goto add_orig_entry;
1745 }
30cfd02b
AQ
1746
1747 /* if the client was temporary added before receiving the first
a6cb3909
SW
1748 * OGM announcing it, we have to clear the TEMP flag. Also,
1749 * remove the previous temporary orig node and re-add it
1750 * if required. If the orig entry changed, the new one which
1751 * is a non-temporary entry is preferred.
30cfd02b 1752 */
a6cb3909
SW
1753 if (common->flags & BATADV_TT_CLIENT_TEMP) {
1754 batadv_tt_global_del_orig_list(tt_global_entry);
1755 common->flags &= ~BATADV_TT_CLIENT_TEMP;
1756 }
db08e6e5 1757
e9c00136 1758 /* the change can carry possible "attribute" flags like the
54e22f26 1759 * TT_CLIENT_TEMP, therefore they have to be copied in the
e9c00136
AQ
1760 * client entry
1761 */
54e22f26 1762 common->flags |= flags & (~BATADV_TT_SYNC_MASK);
e9c00136 1763
acd34afa
SE
1764 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
1765 * one originator left in the list and we previously received a
db08e6e5
SW
1766 * delete + roaming change for this originator.
1767 *
1768 * We should first delete the old originator before adding the
1769 * new one.
1770 */
068ee6e2 1771 if (common->flags & BATADV_TT_CLIENT_ROAM) {
a513088d 1772 batadv_tt_global_del_orig_list(tt_global_entry);
068ee6e2 1773 common->flags &= ~BATADV_TT_CLIENT_ROAM;
db08e6e5 1774 tt_global_entry->roam_at = 0;
a73105b8
AQ
1775 }
1776 }
068ee6e2 1777add_orig_entry:
30cfd02b 1778 /* add the new orig_entry (if needed) or update it */
54e22f26
LL
1779 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
1780 flags & BATADV_TT_SYNC_MASK);
c6c8fea2 1781
39c75a51 1782 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 1783 "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
f7a2bd65 1784 common->addr, batadv_print_vid(common->vid),
16052789 1785 orig_node->orig);
1e5d49fc 1786 ret = true;
c6c8fea2 1787
80b3f58c 1788out_remove:
c5caf4ef
LL
1789 /* Do not remove multicast addresses from the local hash on
1790 * global additions
1791 */
1792 if (is_multicast_ether_addr(tt_addr))
1793 goto out;
7f91d06c 1794
a73105b8 1795 /* remove address from local hash if present */
c018ad3d 1796 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
7f91d06c 1797 "global tt received",
c1d07431 1798 flags & BATADV_TT_CLIENT_ROAM);
7f91d06c
AQ
1799 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
1800
068ee6e2
AQ
1801 if (!(flags & BATADV_TT_CLIENT_ROAM))
1802 /* this is a normal global add. Therefore the client is not in a
1803 * roaming state anymore.
1804 */
1805 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
1806
7683fdc1
AQ
1807out:
1808 if (tt_global_entry)
5dafd8a6 1809 batadv_tt_global_entry_put(tt_global_entry);
068ee6e2 1810 if (tt_local_entry)
95c0db90 1811 batadv_tt_local_entry_put(tt_local_entry);
7683fdc1 1812 return ret;
c6c8fea2
SE
1813}
1814
1b371d13 1815/**
7e9a8c2c 1816 * batadv_transtable_best_orig() - Get best originator list entry from tt entry
4627456a 1817 * @bat_priv: the bat priv with all the soft interface information
981d8900
SE
1818 * @tt_global_entry: global translation table entry to be analyzed
1819 *
1820 * This functon assumes the caller holds rcu_read_lock().
62fe710f 1821 * Return: best originator list entry or NULL on errors.
981d8900
SE
1822 */
1823static struct batadv_tt_orig_list_entry *
4627456a
AQ
1824batadv_transtable_best_orig(struct batadv_priv *bat_priv,
1825 struct batadv_tt_global_entry *tt_global_entry)
981d8900 1826{
4627456a 1827 struct batadv_neigh_node *router, *best_router = NULL;
29824a55 1828 struct batadv_algo_ops *bao = bat_priv->algo_ops;
981d8900 1829 struct hlist_head *head;
981d8900 1830 struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
981d8900
SE
1831
1832 head = &tt_global_entry->orig_list;
b67bfe0d 1833 hlist_for_each_entry_rcu(orig_entry, head, list) {
7351a482
SW
1834 router = batadv_orig_router_get(orig_entry->orig_node,
1835 BATADV_IF_DEFAULT);
981d8900
SE
1836 if (!router)
1837 continue;
1838
4627456a 1839 if (best_router &&
29824a55
AQ
1840 bao->neigh.cmp(router, BATADV_IF_DEFAULT, best_router,
1841 BATADV_IF_DEFAULT) <= 0) {
25bb2509 1842 batadv_neigh_node_put(router);
4627456a 1843 continue;
981d8900
SE
1844 }
1845
4627456a
AQ
1846 /* release the refcount for the "old" best */
1847 if (best_router)
25bb2509 1848 batadv_neigh_node_put(best_router);
4627456a
AQ
1849
1850 best_entry = orig_entry;
1851 best_router = router;
981d8900
SE
1852 }
1853
4627456a 1854 if (best_router)
25bb2509 1855 batadv_neigh_node_put(best_router);
4627456a 1856
981d8900
SE
1857 return best_entry;
1858}
1859
dc1cbd14 1860#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1b371d13 1861/**
7e9a8c2c
SE
1862 * batadv_tt_global_print_entry() - print all orig nodes who announce the
1863 * address for this global entry
4627456a 1864 * @bat_priv: the bat priv with all the soft interface information
981d8900
SE
1865 * @tt_global_entry: global translation table entry to be printed
1866 * @seq: debugfs table seq_file struct
1867 *
1868 * This functon assumes the caller holds rcu_read_lock().
db08e6e5 1869 */
a513088d 1870static void
4627456a
AQ
1871batadv_tt_global_print_entry(struct batadv_priv *bat_priv,
1872 struct batadv_tt_global_entry *tt_global_entry,
a513088d 1873 struct seq_file *seq)
db08e6e5 1874{
981d8900 1875 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
56303d34 1876 struct batadv_tt_common_entry *tt_common_entry;
7ea7b4a1
AQ
1877 struct batadv_orig_node_vlan *vlan;
1878 struct hlist_head *head;
6b5e971a
SE
1879 u8 last_ttvn;
1880 u16 flags;
db08e6e5
SW
1881
1882 tt_common_entry = &tt_global_entry->common;
981d8900
SE
1883 flags = tt_common_entry->flags;
1884
4627456a 1885 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
981d8900 1886 if (best_entry) {
7ea7b4a1
AQ
1887 vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
1888 tt_common_entry->vid);
1889 if (!vlan) {
1890 seq_printf(seq,
1891 " * Cannot retrieve VLAN %d for originator %pM\n",
f7a2bd65 1892 batadv_print_vid(tt_common_entry->vid),
7ea7b4a1
AQ
1893 best_entry->orig_node->orig);
1894 goto print_list;
1895 }
1896
981d8900 1897 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
f9d8a537 1898 seq_printf(seq,
dd24ddb2 1899 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
981d8900 1900 '*', tt_global_entry->common.addr,
f7a2bd65 1901 batadv_print_vid(tt_global_entry->common.vid),
981d8900 1902 best_entry->ttvn, best_entry->orig_node->orig,
7ea7b4a1 1903 last_ttvn, vlan->tt.crc,
a2f2b6cd
SE
1904 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1905 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1906 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1907 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
7ea7b4a1 1908
21754e25 1909 batadv_orig_node_vlan_put(vlan);
981d8900 1910 }
db08e6e5 1911
7ea7b4a1 1912print_list:
db08e6e5
SW
1913 head = &tt_global_entry->orig_list;
1914
b67bfe0d 1915 hlist_for_each_entry_rcu(orig_entry, head, list) {
981d8900
SE
1916 if (best_entry == orig_entry)
1917 continue;
1918
7ea7b4a1
AQ
1919 vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
1920 tt_common_entry->vid);
1921 if (!vlan) {
1922 seq_printf(seq,
1923 " + Cannot retrieve VLAN %d for originator %pM\n",
f7a2bd65 1924 batadv_print_vid(tt_common_entry->vid),
7ea7b4a1
AQ
1925 orig_entry->orig_node->orig);
1926 continue;
1927 }
1928
db08e6e5 1929 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
16052789 1930 seq_printf(seq,
dd24ddb2 1931 " %c %pM %4d (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
981d8900 1932 '+', tt_global_entry->common.addr,
f7a2bd65 1933 batadv_print_vid(tt_global_entry->common.vid),
981d8900 1934 orig_entry->ttvn, orig_entry->orig_node->orig,
7ea7b4a1 1935 last_ttvn, vlan->tt.crc,
a2f2b6cd
SE
1936 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1937 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1938 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1939 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
7ea7b4a1 1940
21754e25 1941 batadv_orig_node_vlan_put(vlan);
db08e6e5
SW
1942 }
1943}
1944
ff15c27c
SE
1945/**
1946 * batadv_tt_global_seq_print_text() - Print the global tt table in a seq file
1947 * @seq: seq file to print on
1948 * @offset: not used
1949 *
1950 * Return: always 0
1951 */
08c36d3e 1952int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea2
SE
1953{
1954 struct net_device *net_dev = (struct net_device *)seq->private;
56303d34 1955 struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6 1956 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
56303d34
SE
1957 struct batadv_tt_common_entry *tt_common_entry;
1958 struct batadv_tt_global_entry *tt_global;
1959 struct batadv_hard_iface *primary_if;
c6c8fea2 1960 struct hlist_head *head;
6b5e971a 1961 u32 i;
c6c8fea2 1962
30da63a6
ML
1963 primary_if = batadv_seq_print_text_primary_if_get(seq);
1964 if (!primary_if)
32ae9b22 1965 goto out;
c6c8fea2 1966
2dafb49d
AQ
1967 seq_printf(seq,
1968 "Globally announced TT entries received via the mesh %s\n",
c6c8fea2 1969 net_dev->name);
925a6f37
AQ
1970 seq_puts(seq,
1971 " Client VID (TTVN) Originator (Curr TTVN) (CRC ) Flags\n");
c6c8fea2 1972
c6c8fea2
SE
1973 for (i = 0; i < hash->size; i++) {
1974 head = &hash->table[i];
1975
7aadf889 1976 rcu_read_lock();
b67bfe0d 1977 hlist_for_each_entry_rcu(tt_common_entry,
7aadf889 1978 head, hash_entry) {
56303d34
SE
1979 tt_global = container_of(tt_common_entry,
1980 struct batadv_tt_global_entry,
1981 common);
4627456a 1982 batadv_tt_global_print_entry(bat_priv, tt_global, seq);
c6c8fea2 1983 }
7aadf889 1984 rcu_read_unlock();
c6c8fea2 1985 }
32ae9b22
ML
1986out:
1987 if (primary_if)
82047ad7 1988 batadv_hardif_put(primary_if);
30da63a6 1989 return 0;
c6c8fea2 1990}
dc1cbd14 1991#endif
c6c8fea2 1992
d34f0550 1993/**
7e9a8c2c 1994 * batadv_tt_global_dump_subentry() - Dump all TT local entries into a message
d34f0550
MS
1995 * @msg: Netlink message to dump into
1996 * @portid: Port making netlink request
1997 * @seq: Sequence number of netlink message
1998 * @common: tt local & tt global common data
1999 * @orig: Originator node announcing a non-mesh client
2000 * @best: Is the best originator for the TT entry
2001 *
2002 * Return: Error code, or 0 on success
2003 */
2004static int
2005batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
2006 struct batadv_tt_common_entry *common,
2007 struct batadv_tt_orig_list_entry *orig,
2008 bool best)
2009{
54e22f26 2010 u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
d34f0550
MS
2011 void *hdr;
2012 struct batadv_orig_node_vlan *vlan;
2013 u8 last_ttvn;
2014 u32 crc;
2015
2016 vlan = batadv_orig_node_vlan_get(orig->orig_node,
2017 common->vid);
2018 if (!vlan)
2019 return 0;
2020
2021 crc = vlan->tt.crc;
2022
2023 batadv_orig_node_vlan_put(vlan);
2024
2025 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
2026 NLM_F_MULTI,
2027 BATADV_CMD_GET_TRANSTABLE_GLOBAL);
2028 if (!hdr)
2029 return -ENOBUFS;
2030
2031 last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
2032
2033 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
2034 nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
2035 orig->orig_node->orig) ||
2036 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
2037 nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
2038 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
2039 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
54e22f26 2040 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
d34f0550
MS
2041 goto nla_put_failure;
2042
2043 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
2044 goto nla_put_failure;
2045
2046 genlmsg_end(msg, hdr);
2047 return 0;
2048
2049 nla_put_failure:
2050 genlmsg_cancel(msg, hdr);
2051 return -EMSGSIZE;
2052}
2053
2054/**
7e9a8c2c 2055 * batadv_tt_global_dump_entry() - Dump one TT global entry into a message
d34f0550
MS
2056 * @msg: Netlink message to dump into
2057 * @portid: Port making netlink request
2058 * @seq: Sequence number of netlink message
2059 * @bat_priv: The bat priv with all the soft interface information
2060 * @common: tt local & tt global common data
2061 * @sub_s: Number of entries to skip
2062 *
2063 * This function assumes the caller holds rcu_read_lock().
2064 *
2065 * Return: Error code, or 0 on success
2066 */
2067static int
2068batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2069 struct batadv_priv *bat_priv,
2070 struct batadv_tt_common_entry *common, int *sub_s)
2071{
2072 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
2073 struct batadv_tt_global_entry *global;
2074 struct hlist_head *head;
2075 int sub = 0;
2076 bool best;
2077
2078 global = container_of(common, struct batadv_tt_global_entry, common);
2079 best_entry = batadv_transtable_best_orig(bat_priv, global);
2080 head = &global->orig_list;
2081
2082 hlist_for_each_entry_rcu(orig_entry, head, list) {
2083 if (sub++ < *sub_s)
2084 continue;
2085
2086 best = (orig_entry == best_entry);
2087
2088 if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
2089 orig_entry, best)) {
2090 *sub_s = sub - 1;
2091 return -EMSGSIZE;
2092 }
2093 }
2094
2095 *sub_s = 0;
2096 return 0;
2097}
2098
2099/**
7e9a8c2c 2100 * batadv_tt_global_dump_bucket() - Dump one TT local bucket into a message
d34f0550
MS
2101 * @msg: Netlink message to dump into
2102 * @portid: Port making netlink request
2103 * @seq: Sequence number of netlink message
2104 * @bat_priv: The bat priv with all the soft interface information
2105 * @head: Pointer to the list containing the global tt entries
2106 * @idx_s: Number of entries to skip
2107 * @sub: Number of entries to skip
2108 *
2109 * Return: Error code, or 0 on success
2110 */
2111static int
2112batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
2113 struct batadv_priv *bat_priv,
2114 struct hlist_head *head, int *idx_s, int *sub)
2115{
2116 struct batadv_tt_common_entry *common;
2117 int idx = 0;
2118
2119 rcu_read_lock();
2120 hlist_for_each_entry_rcu(common, head, hash_entry) {
2121 if (idx++ < *idx_s)
2122 continue;
2123
2124 if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
2125 common, sub)) {
2126 rcu_read_unlock();
2127 *idx_s = idx - 1;
2128 return -EMSGSIZE;
2129 }
2130 }
2131 rcu_read_unlock();
2132
2133 *idx_s = 0;
2134 *sub = 0;
2135 return 0;
2136}
2137
2138/**
7e9a8c2c 2139 * batadv_tt_global_dump() - Dump TT global entries into a message
d34f0550
MS
2140 * @msg: Netlink message to dump into
2141 * @cb: Parameters from query
2142 *
2143 * Return: Error code, or length of message on success
2144 */
2145int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
2146{
2147 struct net *net = sock_net(cb->skb->sk);
2148 struct net_device *soft_iface;
2149 struct batadv_priv *bat_priv;
2150 struct batadv_hard_iface *primary_if = NULL;
2151 struct batadv_hashtable *hash;
2152 struct hlist_head *head;
2153 int ret;
2154 int ifindex;
2155 int bucket = cb->args[0];
2156 int idx = cb->args[1];
2157 int sub = cb->args[2];
2158 int portid = NETLINK_CB(cb->skb).portid;
2159
2160 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
2161 if (!ifindex)
2162 return -EINVAL;
2163
2164 soft_iface = dev_get_by_index(net, ifindex);
2165 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2166 ret = -ENODEV;
2167 goto out;
2168 }
2169
2170 bat_priv = netdev_priv(soft_iface);
2171
2172 primary_if = batadv_primary_if_get_selected(bat_priv);
2173 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2174 ret = -ENOENT;
2175 goto out;
2176 }
2177
2178 hash = bat_priv->tt.global_hash;
2179
2180 while (bucket < hash->size) {
2181 head = &hash->table[bucket];
2182
2183 if (batadv_tt_global_dump_bucket(msg, portid,
2184 cb->nlh->nlmsg_seq, bat_priv,
2185 head, &idx, &sub))
2186 break;
2187
2188 bucket++;
2189 }
2190
2191 ret = msg->len;
2192
2193 out:
2194 if (primary_if)
2195 batadv_hardif_put(primary_if);
2196 if (soft_iface)
2197 dev_put(soft_iface);
2198
2199 cb->args[0] = bucket;
2200 cb->args[1] = idx;
2201 cb->args[2] = sub;
2202
2203 return ret;
2204}
2205
1d8ab8d3 2206/**
7e9a8c2c 2207 * _batadv_tt_global_del_orig_entry() - remove and free an orig_entry
1d8ab8d3
LL
2208 * @tt_global_entry: the global entry to remove the orig_entry from
2209 * @orig_entry: the orig entry to remove and free
2210 *
2211 * Remove an orig_entry from its list in the given tt_global_entry and
2212 * free this orig_entry afterwards.
433ff98f
ML
2213 *
2214 * Caller must hold tt_global_entry->list_lock and ensure orig_entry->list is
2215 * part of a list.
1d8ab8d3
LL
2216 */
2217static void
433ff98f
ML
2218_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
2219 struct batadv_tt_orig_list_entry *orig_entry)
1d8ab8d3 2220{
2c72d655
SE
2221 lockdep_assert_held(&tt_global_entry->list_lock);
2222
1d8ab8d3
LL
2223 batadv_tt_global_size_dec(orig_entry->orig_node,
2224 tt_global_entry->common.vid);
2225 atomic_dec(&tt_global_entry->orig_list_count);
433ff98f
ML
2226 /* requires holding tt_global_entry->list_lock and orig_entry->list
2227 * being part of a list
2228 */
1d8ab8d3 2229 hlist_del_rcu(&orig_entry->list);
7e2366c6 2230 batadv_tt_orig_list_entry_put(orig_entry);
1d8ab8d3
LL
2231}
2232
db08e6e5 2233/* deletes the orig list of a tt_global_entry */
a513088d 2234static void
56303d34 2235batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
c6c8fea2 2236{
db08e6e5 2237 struct hlist_head *head;
b67bfe0d 2238 struct hlist_node *safe;
56303d34 2239 struct batadv_tt_orig_list_entry *orig_entry;
a73105b8 2240
db08e6e5
SW
2241 spin_lock_bh(&tt_global_entry->list_lock);
2242 head = &tt_global_entry->orig_list;
1d8ab8d3 2243 hlist_for_each_entry_safe(orig_entry, safe, head, list)
433ff98f 2244 _batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
db08e6e5 2245 spin_unlock_bh(&tt_global_entry->list_lock);
db08e6e5
SW
2246}
2247
1d8ab8d3 2248/**
7e9a8c2c 2249 * batadv_tt_global_del_orig_node() - remove orig_node from a global tt entry
1d8ab8d3
LL
2250 * @bat_priv: the bat priv with all the soft interface information
2251 * @tt_global_entry: the global entry to remove the orig_node from
2252 * @orig_node: the originator announcing the client
2253 * @message: message to append to the log on deletion
2254 *
2255 * Remove the given orig_node and its according orig_entry from the given
2256 * global tt entry.
2257 */
a513088d 2258static void
1d8ab8d3
LL
2259batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
2260 struct batadv_tt_global_entry *tt_global_entry,
2261 struct batadv_orig_node *orig_node,
2262 const char *message)
db08e6e5
SW
2263{
2264 struct hlist_head *head;
b67bfe0d 2265 struct hlist_node *safe;
56303d34 2266 struct batadv_tt_orig_list_entry *orig_entry;
16052789 2267 unsigned short vid;
db08e6e5
SW
2268
2269 spin_lock_bh(&tt_global_entry->list_lock);
2270 head = &tt_global_entry->orig_list;
b67bfe0d 2271 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
db08e6e5 2272 if (orig_entry->orig_node == orig_node) {
16052789 2273 vid = tt_global_entry->common.vid;
39c75a51 2274 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 2275 "Deleting %pM from global tt entry %pM (vid: %d): %s\n",
1eda58bf 2276 orig_node->orig,
16052789 2277 tt_global_entry->common.addr,
f7a2bd65 2278 batadv_print_vid(vid), message);
433ff98f
ML
2279 _batadv_tt_global_del_orig_entry(tt_global_entry,
2280 orig_entry);
db08e6e5
SW
2281 }
2282 }
2283 spin_unlock_bh(&tt_global_entry->list_lock);
2284}
2285
db08e6e5 2286/* If the client is to be deleted, we check if it is the last origantor entry
acd34afa
SE
2287 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
2288 * timer, otherwise we simply remove the originator scheduled for deletion.
db08e6e5 2289 */
a513088d 2290static void
56303d34
SE
2291batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
2292 struct batadv_tt_global_entry *tt_global_entry,
2293 struct batadv_orig_node *orig_node,
2294 const char *message)
db08e6e5
SW
2295{
2296 bool last_entry = true;
2297 struct hlist_head *head;
56303d34 2298 struct batadv_tt_orig_list_entry *orig_entry;
db08e6e5
SW
2299
2300 /* no local entry exists, case 1:
2301 * Check if this is the last one or if other entries exist.
2302 */
2303
2304 rcu_read_lock();
2305 head = &tt_global_entry->orig_list;
b67bfe0d 2306 hlist_for_each_entry_rcu(orig_entry, head, list) {
db08e6e5
SW
2307 if (orig_entry->orig_node != orig_node) {
2308 last_entry = false;
2309 break;
2310 }
2311 }
2312 rcu_read_unlock();
2313
2314 if (last_entry) {
2315 /* its the last one, mark for roaming. */
acd34afa 2316 tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
db08e6e5 2317 tt_global_entry->roam_at = jiffies;
1fda4c0a 2318 } else {
db08e6e5
SW
2319 /* there is another entry, we can simply delete this
2320 * one and can still use the other one.
2321 */
1d8ab8d3
LL
2322 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2323 orig_node, message);
1fda4c0a 2324 }
db08e6e5
SW
2325}
2326
c018ad3d 2327/**
7e9a8c2c 2328 * batadv_tt_global_del() - remove a client from the global table
c018ad3d
AQ
2329 * @bat_priv: the bat priv with all the soft interface information
2330 * @orig_node: an originator serving this client
2331 * @addr: the mac address of the client
2332 * @vid: VLAN identifier
2333 * @message: a message explaining the reason for deleting the client to print
2334 * for debugging purpose
2335 * @roaming: true if the deletion has been triggered by a roaming event
2336 */
56303d34
SE
2337static void batadv_tt_global_del(struct batadv_priv *bat_priv,
2338 struct batadv_orig_node *orig_node,
c018ad3d 2339 const unsigned char *addr, unsigned short vid,
a513088d 2340 const char *message, bool roaming)
a73105b8 2341{
170173bf 2342 struct batadv_tt_global_entry *tt_global_entry;
56303d34 2343 struct batadv_tt_local_entry *local_entry = NULL;
a73105b8 2344
c018ad3d 2345 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
db08e6e5 2346 if (!tt_global_entry)
7683fdc1 2347 goto out;
a73105b8 2348
db08e6e5 2349 if (!roaming) {
1d8ab8d3
LL
2350 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2351 orig_node, message);
db08e6e5
SW
2352
2353 if (hlist_empty(&tt_global_entry->orig_list))
be73b488
AQ
2354 batadv_tt_global_free(bat_priv, tt_global_entry,
2355 message);
db08e6e5
SW
2356
2357 goto out;
2358 }
92f90f56
SE
2359
2360 /* if we are deleting a global entry due to a roam
2361 * event, there are two possibilities:
db08e6e5
SW
2362 * 1) the client roamed from node A to node B => if there
2363 * is only one originator left for this client, we mark
acd34afa 2364 * it with BATADV_TT_CLIENT_ROAM, we start a timer and we
92f90f56
SE
2365 * wait for node B to claim it. In case of timeout
2366 * the entry is purged.
db08e6e5
SW
2367 *
2368 * If there are other originators left, we directly delete
2369 * the originator.
92f90f56 2370 * 2) the client roamed to us => we can directly delete
9cfc7bd6
SE
2371 * the global entry, since it is useless now.
2372 */
a513088d 2373 local_entry = batadv_tt_local_hash_find(bat_priv,
c018ad3d
AQ
2374 tt_global_entry->common.addr,
2375 vid);
a513088d 2376 if (local_entry) {
db08e6e5 2377 /* local entry exists, case 2: client roamed to us. */
a513088d 2378 batadv_tt_global_del_orig_list(tt_global_entry);
be73b488 2379 batadv_tt_global_free(bat_priv, tt_global_entry, message);
1fda4c0a 2380 } else {
db08e6e5 2381 /* no local entry exists, case 1: check for roaming */
a513088d
SE
2382 batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
2383 orig_node, message);
1fda4c0a 2384 }
92f90f56 2385
cc47f66e 2386out:
7683fdc1 2387 if (tt_global_entry)
5dafd8a6 2388 batadv_tt_global_entry_put(tt_global_entry);
a513088d 2389 if (local_entry)
95c0db90 2390 batadv_tt_local_entry_put(local_entry);
a73105b8
AQ
2391}
2392
95fb130d 2393/**
7e9a8c2c
SE
2394 * batadv_tt_global_del_orig() - remove all the TT global entries belonging to
2395 * the given originator matching the provided vid
95fb130d
AQ
2396 * @bat_priv: the bat priv with all the soft interface information
2397 * @orig_node: the originator owning the entries to remove
2398 * @match_vid: the VLAN identifier to match. If negative all the entries will be
2399 * removed
2400 * @message: debug message to print as "reason"
2401 */
56303d34
SE
2402void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
2403 struct batadv_orig_node *orig_node,
6b5e971a 2404 s32 match_vid,
56303d34 2405 const char *message)
c6c8fea2 2406{
56303d34
SE
2407 struct batadv_tt_global_entry *tt_global;
2408 struct batadv_tt_common_entry *tt_common_entry;
6b5e971a 2409 u32 i;
807736f6 2410 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
b67bfe0d 2411 struct hlist_node *safe;
a73105b8 2412 struct hlist_head *head;
7683fdc1 2413 spinlock_t *list_lock; /* protects write access to the hash lists */
16052789 2414 unsigned short vid;
c6c8fea2 2415
6e801494
SW
2416 if (!hash)
2417 return;
2418
a73105b8
AQ
2419 for (i = 0; i < hash->size; i++) {
2420 head = &hash->table[i];
7683fdc1 2421 list_lock = &hash->list_locks[i];
c6c8fea2 2422
7683fdc1 2423 spin_lock_bh(list_lock);
b67bfe0d 2424 hlist_for_each_entry_safe(tt_common_entry, safe,
7c64fd98 2425 head, hash_entry) {
95fb130d
AQ
2426 /* remove only matching entries */
2427 if (match_vid >= 0 && tt_common_entry->vid != match_vid)
2428 continue;
2429
56303d34
SE
2430 tt_global = container_of(tt_common_entry,
2431 struct batadv_tt_global_entry,
2432 common);
db08e6e5 2433
1d8ab8d3
LL
2434 batadv_tt_global_del_orig_node(bat_priv, tt_global,
2435 orig_node, message);
db08e6e5 2436
56303d34 2437 if (hlist_empty(&tt_global->orig_list)) {
16052789 2438 vid = tt_global->common.vid;
39c75a51 2439 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
2440 "Deleting global tt entry %pM (vid: %d): %s\n",
2441 tt_global->common.addr,
f7a2bd65 2442 batadv_print_vid(vid), message);
b67bfe0d 2443 hlist_del_rcu(&tt_common_entry->hash_entry);
5dafd8a6 2444 batadv_tt_global_entry_put(tt_global);
7683fdc1 2445 }
a73105b8 2446 }
7683fdc1 2447 spin_unlock_bh(list_lock);
c6c8fea2 2448 }
ac4eebd4 2449 clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
c6c8fea2
SE
2450}
2451
30cfd02b
AQ
2452static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
2453 char **msg)
cc47f66e 2454{
30cfd02b
AQ
2455 bool purge = false;
2456 unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
2457 unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
42d0b044 2458
30cfd02b
AQ
2459 if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
2460 batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
2461 purge = true;
2462 *msg = "Roaming timeout\n";
2463 }
42d0b044 2464
30cfd02b
AQ
2465 if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
2466 batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
2467 purge = true;
2468 *msg = "Temporary client timeout\n";
42d0b044 2469 }
30cfd02b
AQ
2470
2471 return purge;
42d0b044
SE
2472}
2473
30cfd02b 2474static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
42d0b044 2475{
807736f6 2476 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
cc47f66e 2477 struct hlist_head *head;
b67bfe0d 2478 struct hlist_node *node_tmp;
7683fdc1 2479 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 2480 u32 i;
30cfd02b
AQ
2481 char *msg = NULL;
2482 struct batadv_tt_common_entry *tt_common;
2483 struct batadv_tt_global_entry *tt_global;
cc47f66e 2484
cc47f66e
AQ
2485 for (i = 0; i < hash->size; i++) {
2486 head = &hash->table[i];
7683fdc1 2487 list_lock = &hash->list_locks[i];
cc47f66e 2488
7683fdc1 2489 spin_lock_bh(list_lock);
b67bfe0d 2490 hlist_for_each_entry_safe(tt_common, node_tmp, head,
30cfd02b
AQ
2491 hash_entry) {
2492 tt_global = container_of(tt_common,
2493 struct batadv_tt_global_entry,
2494 common);
2495
2496 if (!batadv_tt_global_to_purge(tt_global, &msg))
2497 continue;
2498
2499 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
2500 "Deleting global tt entry %pM (vid: %d): %s\n",
2501 tt_global->common.addr,
f7a2bd65 2502 batadv_print_vid(tt_global->common.vid),
16052789 2503 msg);
30cfd02b 2504
b67bfe0d 2505 hlist_del_rcu(&tt_common->hash_entry);
30cfd02b 2506
5dafd8a6 2507 batadv_tt_global_entry_put(tt_global);
30cfd02b 2508 }
7683fdc1 2509 spin_unlock_bh(list_lock);
cc47f66e 2510 }
cc47f66e
AQ
2511}
2512
56303d34 2513static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
c6c8fea2 2514{
5bf74e9c 2515 struct batadv_hashtable *hash;
7683fdc1 2516 spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34
SE
2517 struct batadv_tt_common_entry *tt_common_entry;
2518 struct batadv_tt_global_entry *tt_global;
b67bfe0d 2519 struct hlist_node *node_tmp;
7683fdc1 2520 struct hlist_head *head;
6b5e971a 2521 u32 i;
7683fdc1 2522
807736f6 2523 if (!bat_priv->tt.global_hash)
c6c8fea2
SE
2524 return;
2525
807736f6 2526 hash = bat_priv->tt.global_hash;
7683fdc1
AQ
2527
2528 for (i = 0; i < hash->size; i++) {
2529 head = &hash->table[i];
2530 list_lock = &hash->list_locks[i];
2531
2532 spin_lock_bh(list_lock);
b67bfe0d 2533 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
7683fdc1 2534 head, hash_entry) {
b67bfe0d 2535 hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34
SE
2536 tt_global = container_of(tt_common_entry,
2537 struct batadv_tt_global_entry,
2538 common);
5dafd8a6 2539 batadv_tt_global_entry_put(tt_global);
7683fdc1
AQ
2540 }
2541 spin_unlock_bh(list_lock);
2542 }
2543
1a8eaf07 2544 batadv_hash_destroy(hash);
7683fdc1 2545
807736f6 2546 bat_priv->tt.global_hash = NULL;
c6c8fea2
SE
2547}
2548
56303d34
SE
2549static bool
2550_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
2551 struct batadv_tt_global_entry *tt_global_entry)
59b699cd 2552{
acd34afa
SE
2553 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
2554 tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
75ae84a4 2555 return true;
59b699cd 2556
2d2fcc2a
AQ
2557 /* check if the two clients are marked as isolated */
2558 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
2559 tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
75ae84a4 2560 return true;
2d2fcc2a 2561
75ae84a4 2562 return false;
59b699cd
AQ
2563}
2564
c018ad3d 2565/**
7e9a8c2c 2566 * batadv_transtable_search() - get the mesh destination for a given client
c018ad3d
AQ
2567 * @bat_priv: the bat priv with all the soft interface information
2568 * @src: mac address of the source client
2569 * @addr: mac address of the destination client
2570 * @vid: VLAN identifier
2571 *
62fe710f 2572 * Return: a pointer to the originator that was selected as destination in the
c018ad3d
AQ
2573 * mesh for contacting the client 'addr', NULL otherwise.
2574 * In case of multiple originators serving the same client, the function returns
2575 * the best one (best in terms of metric towards the destination node).
2576 *
2577 * If the two clients are AP isolated the function returns NULL.
2578 */
56303d34 2579struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
6b5e971a
SE
2580 const u8 *src,
2581 const u8 *addr,
c018ad3d 2582 unsigned short vid)
c6c8fea2 2583{
56303d34
SE
2584 struct batadv_tt_local_entry *tt_local_entry = NULL;
2585 struct batadv_tt_global_entry *tt_global_entry = NULL;
2586 struct batadv_orig_node *orig_node = NULL;
981d8900 2587 struct batadv_tt_orig_list_entry *best_entry;
b8cbd81d 2588
eceb22ae 2589 if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
c018ad3d 2590 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
068ee6e2
AQ
2591 if (!tt_local_entry ||
2592 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
3d393e47
AQ
2593 goto out;
2594 }
7aadf889 2595
c018ad3d 2596 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2dafb49d 2597 if (!tt_global_entry)
7b36e8ee 2598 goto out;
7aadf889 2599
3d393e47 2600 /* check whether the clients should not communicate due to AP
9cfc7bd6
SE
2601 * isolation
2602 */
a513088d
SE
2603 if (tt_local_entry &&
2604 _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3d393e47
AQ
2605 goto out;
2606
db08e6e5 2607 rcu_read_lock();
4627456a 2608 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
db08e6e5 2609 /* found anything? */
981d8900
SE
2610 if (best_entry)
2611 orig_node = best_entry->orig_node;
7c124391 2612 if (orig_node && !kref_get_unless_zero(&orig_node->refcount))
db08e6e5
SW
2613 orig_node = NULL;
2614 rcu_read_unlock();
981d8900 2615
7b36e8ee 2616out:
3d393e47 2617 if (tt_global_entry)
5dafd8a6 2618 batadv_tt_global_entry_put(tt_global_entry);
3d393e47 2619 if (tt_local_entry)
95c0db90 2620 batadv_tt_local_entry_put(tt_local_entry);
3d393e47 2621
7b36e8ee 2622 return orig_node;
c6c8fea2 2623}
a73105b8 2624
ced72933 2625/**
7e9a8c2c 2626 * batadv_tt_global_crc() - calculates the checksum of the local table belonging
ced72933
AQ
2627 * to the given orig_node
2628 * @bat_priv: the bat priv with all the soft interface information
0ffa9e8d 2629 * @orig_node: originator for which the CRC should be computed
7ea7b4a1 2630 * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d
AQ
2631 *
2632 * This function computes the checksum for the global table corresponding to a
2633 * specific originator. In particular, the checksum is computed as follows: For
2634 * each client connected to the originator the CRC32C of the MAC address and the
2635 * VID is computed and then all the CRC32Cs of the various clients are xor'ed
2636 * together.
2637 *
2638 * The idea behind is that CRC32C should be used as much as possible in order to
2639 * produce a unique hash of the table, but since the order which is used to feed
2640 * the CRC32C function affects the result and since every node in the network
2641 * probably sorts the clients differently, the hash function cannot be directly
2642 * computed over the entire table. Hence the CRC32C is used only on
2643 * the single client entry, while all the results are then xor'ed together
2644 * because the XOR operation can combine them all while trying to reduce the
2645 * noise as much as possible.
2646 *
62fe710f 2647 * Return: the checksum of the global table of a given originator.
ced72933 2648 */
6b5e971a
SE
2649static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
2650 struct batadv_orig_node *orig_node,
2651 unsigned short vid)
a73105b8 2652{
807736f6 2653 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
54e22f26 2654 struct batadv_tt_orig_list_entry *tt_orig;
56303d34
SE
2655 struct batadv_tt_common_entry *tt_common;
2656 struct batadv_tt_global_entry *tt_global;
a73105b8 2657 struct hlist_head *head;
6b5e971a
SE
2658 u32 i, crc_tmp, crc = 0;
2659 u8 flags;
a30e22ca 2660 __be16 tmp_vid;
a73105b8
AQ
2661
2662 for (i = 0; i < hash->size; i++) {
2663 head = &hash->table[i];
2664
2665 rcu_read_lock();
b67bfe0d 2666 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
56303d34
SE
2667 tt_global = container_of(tt_common,
2668 struct batadv_tt_global_entry,
2669 common);
7ea7b4a1
AQ
2670 /* compute the CRC only for entries belonging to the
2671 * VLAN identified by the vid passed as parameter
2672 */
2673 if (tt_common->vid != vid)
2674 continue;
2675
db08e6e5
SW
2676 /* Roaming clients are in the global table for
2677 * consistency only. They don't have to be
2678 * taken into account while computing the
2679 * global crc
2680 */
acd34afa 2681 if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
db08e6e5 2682 continue;
30cfd02b
AQ
2683 /* Temporary clients have not been announced yet, so
2684 * they have to be skipped while computing the global
2685 * crc
2686 */
2687 if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
2688 continue;
db08e6e5
SW
2689
2690 /* find out if this global entry is announced by this
2691 * originator
2692 */
54e22f26
LL
2693 tt_orig = batadv_tt_global_orig_entry_find(tt_global,
2694 orig_node);
2695 if (!tt_orig)
db08e6e5
SW
2696 continue;
2697
a30e22ca
AQ
2698 /* use network order to read the VID: this ensures that
2699 * every node reads the bytes in the same order.
2700 */
2701 tmp_vid = htons(tt_common->vid);
2702 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568
AQ
2703
2704 /* compute the CRC on flags that have to be kept in sync
2705 * among nodes
2706 */
54e22f26 2707 flags = tt_orig->flags;
0eb01568
AQ
2708 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2709
0ffa9e8d 2710 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
54e22f26
LL
2711
2712 batadv_tt_orig_list_entry_put(tt_orig);
a73105b8
AQ
2713 }
2714 rcu_read_unlock();
2715 }
2716
ced72933 2717 return crc;
a73105b8
AQ
2718}
2719
ced72933 2720/**
7e9a8c2c 2721 * batadv_tt_local_crc() - calculates the checksum of the local table
ced72933 2722 * @bat_priv: the bat priv with all the soft interface information
7ea7b4a1 2723 * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d
AQ
2724 *
2725 * For details about the computation, please refer to the documentation for
2726 * batadv_tt_global_crc().
2727 *
62fe710f 2728 * Return: the checksum of the local table
ced72933 2729 */
6b5e971a
SE
2730static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
2731 unsigned short vid)
a73105b8 2732{
807736f6 2733 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34 2734 struct batadv_tt_common_entry *tt_common;
a73105b8 2735 struct hlist_head *head;
6b5e971a
SE
2736 u32 i, crc_tmp, crc = 0;
2737 u8 flags;
a30e22ca 2738 __be16 tmp_vid;
a73105b8
AQ
2739
2740 for (i = 0; i < hash->size; i++) {
2741 head = &hash->table[i];
2742
2743 rcu_read_lock();
b67bfe0d 2744 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
7ea7b4a1
AQ
2745 /* compute the CRC only for entries belonging to the
2746 * VLAN identified by vid
2747 */
2748 if (tt_common->vid != vid)
2749 continue;
2750
058d0e26 2751 /* not yet committed clients have not to be taken into
9cfc7bd6
SE
2752 * account while computing the CRC
2753 */
acd34afa 2754 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
058d0e26 2755 continue;
ced72933 2756
a30e22ca
AQ
2757 /* use network order to read the VID: this ensures that
2758 * every node reads the bytes in the same order.
2759 */
2760 tmp_vid = htons(tt_common->vid);
2761 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568
AQ
2762
2763 /* compute the CRC on flags that have to be kept in sync
2764 * among nodes
2765 */
2766 flags = tt_common->flags & BATADV_TT_SYNC_MASK;
2767 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2768
0ffa9e8d 2769 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
a73105b8 2770 }
a73105b8
AQ
2771 rcu_read_unlock();
2772 }
2773
ced72933 2774 return crc;
a73105b8
AQ
2775}
2776
9c4604a2 2777/**
7e9a8c2c 2778 * batadv_tt_req_node_release() - free tt_req node entry
9c4604a2
SE
2779 * @ref: kref pointer of the tt req_node entry
2780 */
2781static void batadv_tt_req_node_release(struct kref *ref)
2782{
2783 struct batadv_tt_req_node *tt_req_node;
2784
2785 tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount);
2786
86452f81 2787 kmem_cache_free(batadv_tt_req_cache, tt_req_node);
9c4604a2
SE
2788}
2789
2790/**
7e9a8c2c 2791 * batadv_tt_req_node_put() - decrement the tt_req_node refcounter and
9c4604a2
SE
2792 * possibly release it
2793 * @tt_req_node: tt_req_node to be free'd
2794 */
2795static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
2796{
2797 kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
2798}
2799
56303d34 2800static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
a73105b8 2801{
7c26a53b
ML
2802 struct batadv_tt_req_node *node;
2803 struct hlist_node *safe;
a73105b8 2804
807736f6 2805 spin_lock_bh(&bat_priv->tt.req_list_lock);
a73105b8 2806
7c26a53b
ML
2807 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2808 hlist_del_init(&node->list);
9c4604a2 2809 batadv_tt_req_node_put(node);
a73105b8
AQ
2810 }
2811
807736f6 2812 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2813}
2814
56303d34
SE
2815static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
2816 struct batadv_orig_node *orig_node,
e8cf234a 2817 const void *tt_buff,
6b5e971a 2818 u16 tt_buff_len)
a73105b8 2819{
a73105b8 2820 /* Replace the old buffer only if I received something in the
9cfc7bd6
SE
2821 * last OGM (the OGM could carry no changes)
2822 */
a73105b8
AQ
2823 spin_lock_bh(&orig_node->tt_buff_lock);
2824 if (tt_buff_len > 0) {
2825 kfree(orig_node->tt_buff);
2826 orig_node->tt_buff_len = 0;
2827 orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
2828 if (orig_node->tt_buff) {
2829 memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
2830 orig_node->tt_buff_len = tt_buff_len;
2831 }
2832 }
2833 spin_unlock_bh(&orig_node->tt_buff_lock);
2834}
2835
56303d34 2836static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
a73105b8 2837{
7c26a53b
ML
2838 struct batadv_tt_req_node *node;
2839 struct hlist_node *safe;
a73105b8 2840
807736f6 2841 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 2842 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
42d0b044
SE
2843 if (batadv_has_timed_out(node->issued_at,
2844 BATADV_TT_REQUEST_TIMEOUT)) {
7c26a53b 2845 hlist_del_init(&node->list);
9c4604a2 2846 batadv_tt_req_node_put(node);
a73105b8
AQ
2847 }
2848 }
807736f6 2849 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2850}
2851
383b8636 2852/**
7e9a8c2c 2853 * batadv_tt_req_node_new() - search and possibly create a tt_req_node object
383b8636
ML
2854 * @bat_priv: the bat priv with all the soft interface information
2855 * @orig_node: orig node this request is being issued for
2856 *
62fe710f 2857 * Return: the pointer to the new tt_req_node struct if no request
383b8636 2858 * has already been issued for this orig_node, NULL otherwise.
9cfc7bd6 2859 */
56303d34 2860static struct batadv_tt_req_node *
383b8636 2861batadv_tt_req_node_new(struct batadv_priv *bat_priv,
56303d34 2862 struct batadv_orig_node *orig_node)
a73105b8 2863{
56303d34 2864 struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
a73105b8 2865
807736f6 2866 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 2867 hlist_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1eda58bf
SE
2868 if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
2869 !batadv_has_timed_out(tt_req_node_tmp->issued_at,
42d0b044 2870 BATADV_TT_REQUEST_TIMEOUT))
a73105b8
AQ
2871 goto unlock;
2872 }
2873
86452f81 2874 tt_req_node = kmem_cache_alloc(batadv_tt_req_cache, GFP_ATOMIC);
a73105b8
AQ
2875 if (!tt_req_node)
2876 goto unlock;
2877
9c4604a2 2878 kref_init(&tt_req_node->refcount);
8fdd0153 2879 ether_addr_copy(tt_req_node->addr, orig_node->orig);
a73105b8
AQ
2880 tt_req_node->issued_at = jiffies;
2881
9c4604a2 2882 kref_get(&tt_req_node->refcount);
7c26a53b 2883 hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
a73105b8 2884unlock:
807736f6 2885 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2886 return tt_req_node;
2887}
2888
335fbe0f 2889/**
7072337e 2890 * batadv_tt_local_valid() - verify local tt entry and get flags
335fbe0f
ML
2891 * @entry_ptr: to be checked local tt entry
2892 * @data_ptr: not used but definition required to satisfy the callback prototype
7072337e
LL
2893 * @flags: a pointer to store TT flags for this client to
2894 *
2895 * Checks the validity of the given local TT entry. If it is, then the provided
2896 * flags pointer is updated.
335fbe0f 2897 *
4b426b10 2898 * Return: true if the entry is a valid, false otherwise.
335fbe0f 2899 */
7072337e
LL
2900static bool batadv_tt_local_valid(const void *entry_ptr,
2901 const void *data_ptr,
2902 u8 *flags)
058d0e26 2903{
56303d34 2904 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
058d0e26 2905
acd34afa 2906 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
4b426b10 2907 return false;
7072337e
LL
2908
2909 if (flags)
2910 *flags = tt_common_entry->flags;
2911
4b426b10 2912 return true;
058d0e26
AQ
2913}
2914
7072337e
LL
2915/**
2916 * batadv_tt_global_valid() - verify global tt entry and get flags
2917 * @entry_ptr: to be checked global tt entry
2918 * @data_ptr: an orig_node object (may be NULL)
2919 * @flags: a pointer to store TT flags for this client to
2920 *
2921 * Checks the validity of the given global TT entry. If it is, then the provided
2922 * flags pointer is updated either with the common (summed) TT flags if data_ptr
2923 * is NULL or the specific, per originator TT flags otherwise.
2924 *
2925 * Return: true if the entry is a valid, false otherwise.
2926 */
4b426b10 2927static bool batadv_tt_global_valid(const void *entry_ptr,
7072337e
LL
2928 const void *data_ptr,
2929 u8 *flags)
a73105b8 2930{
56303d34
SE
2931 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2932 const struct batadv_tt_global_entry *tt_global_entry;
2933 const struct batadv_orig_node *orig_node = data_ptr;
a73105b8 2934
30cfd02b
AQ
2935 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
2936 tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
4b426b10 2937 return false;
cc47f66e 2938
56303d34
SE
2939 tt_global_entry = container_of(tt_common_entry,
2940 struct batadv_tt_global_entry,
48100bac
AQ
2941 common);
2942
7072337e
LL
2943 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
2944 flags);
a73105b8
AQ
2945}
2946
335fbe0f 2947/**
7e9a8c2c 2948 * batadv_tt_tvlv_generate() - fill the tvlv buff with the tt entries from the
7ea7b4a1 2949 * specified tt hash
335fbe0f
ML
2950 * @bat_priv: the bat priv with all the soft interface information
2951 * @hash: hash table containing the tt entries
2952 * @tt_len: expected tvlv tt data buffer length in number of bytes
7ea7b4a1 2953 * @tvlv_buff: pointer to the buffer to fill with the TT data
7072337e 2954 * @valid_cb: function to filter tt change entries and to return TT flags
335fbe0f 2955 * @cb_data: data passed to the filter function as argument
7072337e
LL
2956 *
2957 * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
2958 * is not provided then this becomes a no-op.
335fbe0f 2959 */
7ea7b4a1
AQ
2960static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2961 struct batadv_hashtable *hash,
6b5e971a 2962 void *tvlv_buff, u16 tt_len,
4b426b10 2963 bool (*valid_cb)(const void *,
7072337e
LL
2964 const void *,
2965 u8 *flags),
7ea7b4a1 2966 void *cb_data)
a73105b8 2967{
56303d34 2968 struct batadv_tt_common_entry *tt_common_entry;
335fbe0f 2969 struct batadv_tvlv_tt_change *tt_change;
a73105b8 2970 struct hlist_head *head;
6b5e971a 2971 u16 tt_tot, tt_num_entries = 0;
7072337e
LL
2972 u8 flags;
2973 bool ret;
6b5e971a 2974 u32 i;
a73105b8 2975
298e6e68 2976 tt_tot = batadv_tt_entries(tt_len);
7ea7b4a1 2977 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
a73105b8 2978
7072337e
LL
2979 if (!valid_cb)
2980 return;
2981
a73105b8
AQ
2982 rcu_read_lock();
2983 for (i = 0; i < hash->size; i++) {
2984 head = &hash->table[i];
2985
b67bfe0d 2986 hlist_for_each_entry_rcu(tt_common_entry,
a73105b8 2987 head, hash_entry) {
335fbe0f 2988 if (tt_tot == tt_num_entries)
a73105b8
AQ
2989 break;
2990
7072337e
LL
2991 ret = valid_cb(tt_common_entry, cb_data, &flags);
2992 if (!ret)
a73105b8
AQ
2993 continue;
2994
8fdd0153 2995 ether_addr_copy(tt_change->addr, tt_common_entry->addr);
7072337e 2996 tt_change->flags = flags;
c018ad3d 2997 tt_change->vid = htons(tt_common_entry->vid);
ca663046
AQ
2998 memset(tt_change->reserved, 0,
2999 sizeof(tt_change->reserved));
a73105b8 3000
335fbe0f 3001 tt_num_entries++;
a73105b8
AQ
3002 tt_change++;
3003 }
3004 }
3005 rcu_read_unlock();
7ea7b4a1 3006}
a73105b8 3007
7ea7b4a1 3008/**
7e9a8c2c 3009 * batadv_tt_global_check_crc() - check if all the CRCs are correct
7ea7b4a1
AQ
3010 * @orig_node: originator for which the CRCs have to be checked
3011 * @tt_vlan: pointer to the first tvlv VLAN entry
3012 * @num_vlan: number of tvlv VLAN entries
7ea7b4a1 3013 *
62fe710f 3014 * Return: true if all the received CRCs match the locally stored ones, false
7ea7b4a1
AQ
3015 * otherwise
3016 */
3017static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
3018 struct batadv_tvlv_tt_vlan_data *tt_vlan,
6b5e971a 3019 u16 num_vlan)
7ea7b4a1
AQ
3020{
3021 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
3022 struct batadv_orig_node_vlan *vlan;
c169c59d 3023 int i, orig_num_vlan;
6b5e971a 3024 u32 crc;
7ea7b4a1
AQ
3025
3026 /* check if each received CRC matches the locally stored one */
3027 for (i = 0; i < num_vlan; i++) {
3028 tt_vlan_tmp = tt_vlan + i;
3029
3030 /* if orig_node is a backbone node for this VLAN, don't check
3031 * the CRC as we ignore all the global entries over it
3032 */
3033 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
cfd4f757
AQ
3034 orig_node->orig,
3035 ntohs(tt_vlan_tmp->vid)))
7ea7b4a1
AQ
3036 continue;
3037
3038 vlan = batadv_orig_node_vlan_get(orig_node,
3039 ntohs(tt_vlan_tmp->vid));
3040 if (!vlan)
3041 return false;
3042
91c2b1a9 3043 crc = vlan->tt.crc;
21754e25 3044 batadv_orig_node_vlan_put(vlan);
91c2b1a9
AQ
3045
3046 if (crc != ntohl(tt_vlan_tmp->crc))
7ea7b4a1
AQ
3047 return false;
3048 }
3049
c169c59d
SW
3050 /* check if any excess VLANs exist locally for the originator
3051 * which are not mentioned in the TVLV from the originator.
3052 */
3053 rcu_read_lock();
3054 orig_num_vlan = 0;
3055 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list)
3056 orig_num_vlan++;
3057 rcu_read_unlock();
3058
3059 if (orig_num_vlan > num_vlan)
3060 return false;
3061
7ea7b4a1
AQ
3062 return true;
3063}
3064
3065/**
7e9a8c2c 3066 * batadv_tt_local_update_crc() - update all the local CRCs
7ea7b4a1
AQ
3067 * @bat_priv: the bat priv with all the soft interface information
3068 */
3069static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
3070{
3071 struct batadv_softif_vlan *vlan;
3072
3073 /* recompute the global CRC for each VLAN */
3074 rcu_read_lock();
3075 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
3076 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
3077 }
3078 rcu_read_unlock();
3079}
3080
3081/**
7e9a8c2c 3082 * batadv_tt_global_update_crc() - update all the global CRCs for this orig_node
7ea7b4a1
AQ
3083 * @bat_priv: the bat priv with all the soft interface information
3084 * @orig_node: the orig_node for which the CRCs have to be updated
3085 */
3086static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
3087 struct batadv_orig_node *orig_node)
3088{
3089 struct batadv_orig_node_vlan *vlan;
6b5e971a 3090 u32 crc;
7ea7b4a1
AQ
3091
3092 /* recompute the global CRC for each VLAN */
3093 rcu_read_lock();
d0fa4f3f 3094 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
7ea7b4a1
AQ
3095 /* if orig_node is a backbone node for this VLAN, don't compute
3096 * the CRC as we ignore all the global entries over it
3097 */
cfd4f757
AQ
3098 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
3099 vlan->vid))
7ea7b4a1
AQ
3100 continue;
3101
3102 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
3103 vlan->tt.crc = crc;
3104 }
3105 rcu_read_unlock();
a73105b8
AQ
3106}
3107
ced72933 3108/**
7e9a8c2c 3109 * batadv_send_tt_request() - send a TT Request message to a given node
ced72933
AQ
3110 * @bat_priv: the bat priv with all the soft interface information
3111 * @dst_orig_node: the destination of the message
3112 * @ttvn: the version number that the source of the message is looking for
7ea7b4a1
AQ
3113 * @tt_vlan: pointer to the first tvlv VLAN object to request
3114 * @num_vlan: number of tvlv VLAN entries
ced72933
AQ
3115 * @full_table: ask for the entire translation table if true, while only for the
3116 * last TT diff otherwise
d15cd622
AQ
3117 *
3118 * Return: true if the TT Request was sent, false otherwise
ced72933 3119 */
4b426b10
SE
3120static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
3121 struct batadv_orig_node *dst_orig_node,
3122 u8 ttvn,
3123 struct batadv_tvlv_tt_vlan_data *tt_vlan,
3124 u16 num_vlan, bool full_table)
a73105b8 3125{
335fbe0f 3126 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34 3127 struct batadv_tt_req_node *tt_req_node = NULL;
7ea7b4a1
AQ
3128 struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
3129 struct batadv_hard_iface *primary_if;
335fbe0f 3130 bool ret = false;
7ea7b4a1 3131 int i, size;
a73105b8 3132
e5d89254 3133 primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8
AQ
3134 if (!primary_if)
3135 goto out;
3136
3137 /* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd6
SE
3138 * reply from the same orig_node yet
3139 */
383b8636 3140 tt_req_node = batadv_tt_req_node_new(bat_priv, dst_orig_node);
a73105b8
AQ
3141 if (!tt_req_node)
3142 goto out;
3143
7ea7b4a1
AQ
3144 size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
3145 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
335fbe0f 3146 if (!tvlv_tt_data)
a73105b8
AQ
3147 goto out;
3148
335fbe0f
ML
3149 tvlv_tt_data->flags = BATADV_TT_REQUEST;
3150 tvlv_tt_data->ttvn = ttvn;
7ea7b4a1
AQ
3151 tvlv_tt_data->num_vlan = htons(num_vlan);
3152
3153 /* send all the CRCs within the request. This is needed by intermediate
3154 * nodes to ensure they have the correct table before replying
3155 */
3156 tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
3157 for (i = 0; i < num_vlan; i++) {
3158 tt_vlan_req->vid = tt_vlan->vid;
3159 tt_vlan_req->crc = tt_vlan->crc;
3160
3161 tt_vlan_req++;
3162 tt_vlan++;
3163 }
a73105b8
AQ
3164
3165 if (full_table)
335fbe0f 3166 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3167
bb351ba0 3168 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
335fbe0f 3169 dst_orig_node->orig, full_table ? 'F' : '.');
a73105b8 3170
d69909d2 3171 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
335fbe0f
ML
3172 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3173 dst_orig_node->orig, BATADV_TVLV_TT, 1,
7ea7b4a1 3174 tvlv_tt_data, size);
335fbe0f 3175 ret = true;
a73105b8
AQ
3176
3177out:
a73105b8 3178 if (primary_if)
82047ad7 3179 batadv_hardif_put(primary_if);
9c4604a2 3180
a73105b8 3181 if (ret && tt_req_node) {
807736f6 3182 spin_lock_bh(&bat_priv->tt.req_list_lock);
9c4604a2
SE
3183 if (!hlist_unhashed(&tt_req_node->list)) {
3184 hlist_del_init(&tt_req_node->list);
3185 batadv_tt_req_node_put(tt_req_node);
3186 }
807736f6 3187 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8 3188 }
9c4604a2
SE
3189
3190 if (tt_req_node)
3191 batadv_tt_req_node_put(tt_req_node);
3192
335fbe0f 3193 kfree(tvlv_tt_data);
a73105b8
AQ
3194 return ret;
3195}
3196
335fbe0f 3197/**
7e9a8c2c 3198 * batadv_send_other_tt_response() - send reply to tt request concerning another
335fbe0f
ML
3199 * node's translation table
3200 * @bat_priv: the bat priv with all the soft interface information
3201 * @tt_data: tt data containing the tt request information
3202 * @req_src: mac address of tt request sender
3203 * @req_dst: mac address of tt request recipient
3204 *
62fe710f 3205 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3206 */
3207static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
3208 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3209 u8 *req_src, u8 *req_dst)
a73105b8 3210{
170173bf 3211 struct batadv_orig_node *req_dst_orig_node;
56303d34 3212 struct batadv_orig_node *res_dst_orig_node = NULL;
7ea7b4a1 3213 struct batadv_tvlv_tt_change *tt_change;
335fbe0f 3214 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
7ea7b4a1 3215 struct batadv_tvlv_tt_vlan_data *tt_vlan;
335fbe0f 3216 bool ret = false, full_table;
6b5e971a
SE
3217 u8 orig_ttvn, req_ttvn;
3218 u16 tvlv_len;
3219 s32 tt_len;
a73105b8 3220
39c75a51 3221 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3222 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
335fbe0f 3223 req_src, tt_data->ttvn, req_dst,
a2f2b6cd 3224 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8
AQ
3225
3226 /* Let's get the orig node of the REAL destination */
335fbe0f 3227 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
a73105b8
AQ
3228 if (!req_dst_orig_node)
3229 goto out;
3230
335fbe0f 3231 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8
AQ
3232 if (!res_dst_orig_node)
3233 goto out;
3234
6b5e971a 3235 orig_ttvn = (u8)atomic_read(&req_dst_orig_node->last_ttvn);
335fbe0f 3236 req_ttvn = tt_data->ttvn;
a73105b8 3237
7ea7b4a1 3238 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
335fbe0f 3239 /* this node doesn't have the requested data */
a73105b8 3240 if (orig_ttvn != req_ttvn ||
7ea7b4a1
AQ
3241 !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
3242 ntohs(tt_data->num_vlan)))
a73105b8
AQ
3243 goto out;
3244
015758d0 3245 /* If the full table has been explicitly requested */
335fbe0f 3246 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
a73105b8
AQ
3247 !req_dst_orig_node->tt_buff)
3248 full_table = true;
3249 else
3250 full_table = false;
3251
335fbe0f
ML
3252 /* TT fragmentation hasn't been implemented yet, so send as many
3253 * TT entries fit a single packet as possible only
9cfc7bd6 3254 */
a73105b8
AQ
3255 if (!full_table) {
3256 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
3257 tt_len = req_dst_orig_node->tt_buff_len;
a73105b8 3258
7ea7b4a1
AQ
3259 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3260 &tvlv_tt_data,
3261 &tt_change,
3262 &tt_len);
3263 if (!tt_len)
a73105b8
AQ
3264 goto unlock;
3265
a73105b8 3266 /* Copy the last orig_node's OGM buffer */
7ea7b4a1 3267 memcpy(tt_change, req_dst_orig_node->tt_buff,
a73105b8 3268 req_dst_orig_node->tt_buff_len);
a73105b8
AQ
3269 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3270 } else {
7ea7b4a1
AQ
3271 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3272 * in the initial part
3273 */
3274 tt_len = -1;
3275 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3276 &tvlv_tt_data,
3277 &tt_change,
3278 &tt_len);
3279 if (!tt_len)
a73105b8 3280 goto out;
7ea7b4a1
AQ
3281
3282 /* fill the rest of the tvlv with the real TT entries */
3283 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
3284 tt_change, tt_len,
3285 batadv_tt_global_valid,
3286 req_dst_orig_node);
a73105b8
AQ
3287 }
3288
a19d3d85
ML
3289 /* Don't send the response, if larger than fragmented packet. */
3290 tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
3291 if (tt_len > atomic_read(&bat_priv->packet_size_max)) {
3292 net_ratelimited_function(batadv_info, bat_priv->soft_iface,
3293 "Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.\n",
3294 res_dst_orig_node->orig);
3295 goto out;
3296 }
3297
335fbe0f
ML
3298 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3299 tvlv_tt_data->ttvn = req_ttvn;
a73105b8
AQ
3300
3301 if (full_table)
335fbe0f 3302 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3303
39c75a51 3304 batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f
ML
3305 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
3306 res_dst_orig_node->orig, req_dst_orig_node->orig,
3307 full_table ? 'F' : '.', req_ttvn);
a73105b8 3308
d69909d2 3309 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865 3310
335fbe0f 3311 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
7ea7b4a1
AQ
3312 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3313 tvlv_len);
e91ecfc6 3314
335fbe0f 3315 ret = true;
a73105b8
AQ
3316 goto out;
3317
3318unlock:
3319 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3320
3321out:
3322 if (res_dst_orig_node)
5d967310 3323 batadv_orig_node_put(res_dst_orig_node);
a73105b8 3324 if (req_dst_orig_node)
5d967310 3325 batadv_orig_node_put(req_dst_orig_node);
335fbe0f 3326 kfree(tvlv_tt_data);
a73105b8 3327 return ret;
a73105b8 3328}
96412690 3329
335fbe0f 3330/**
7e9a8c2c
SE
3331 * batadv_send_my_tt_response() - send reply to tt request concerning this
3332 * node's translation table
335fbe0f
ML
3333 * @bat_priv: the bat priv with all the soft interface information
3334 * @tt_data: tt data containing the tt request information
3335 * @req_src: mac address of tt request sender
3336 *
62fe710f 3337 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3338 */
3339static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
3340 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3341 u8 *req_src)
a73105b8 3342{
335fbe0f 3343 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34 3344 struct batadv_hard_iface *primary_if = NULL;
7ea7b4a1
AQ
3345 struct batadv_tvlv_tt_change *tt_change;
3346 struct batadv_orig_node *orig_node;
6b5e971a
SE
3347 u8 my_ttvn, req_ttvn;
3348 u16 tvlv_len;
a73105b8 3349 bool full_table;
6b5e971a 3350 s32 tt_len;
a73105b8 3351
39c75a51 3352 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3353 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
335fbe0f 3354 req_src, tt_data->ttvn,
a2f2b6cd 3355 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8 3356
a70a9aa9 3357 spin_lock_bh(&bat_priv->tt.commit_lock);
a73105b8 3358
6b5e971a 3359 my_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
335fbe0f 3360 req_ttvn = tt_data->ttvn;
a73105b8 3361
335fbe0f 3362 orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8
AQ
3363 if (!orig_node)
3364 goto out;
3365
e5d89254 3366 primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8
AQ
3367 if (!primary_if)
3368 goto out;
3369
3370 /* If the full table has been explicitly requested or the gap
9cfc7bd6
SE
3371 * is too big send the whole local translation table
3372 */
335fbe0f 3373 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
807736f6 3374 !bat_priv->tt.last_changeset)
a73105b8
AQ
3375 full_table = true;
3376 else
3377 full_table = false;
3378
335fbe0f
ML
3379 /* TT fragmentation hasn't been implemented yet, so send as many
3380 * TT entries fit a single packet as possible only
9cfc7bd6 3381 */
a73105b8 3382 if (!full_table) {
807736f6 3383 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3384
7ea7b4a1
AQ
3385 tt_len = bat_priv->tt.last_changeset_len;
3386 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3387 &tvlv_tt_data,
3388 &tt_change,
3389 &tt_len);
c2d0f48a 3390 if (!tt_len || !tvlv_len)
a73105b8
AQ
3391 goto unlock;
3392
335fbe0f 3393 /* Copy the last orig_node's OGM buffer */
7ea7b4a1 3394 memcpy(tt_change, bat_priv->tt.last_changeset,
807736f6
SE
3395 bat_priv->tt.last_changeset_len);
3396 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3397 } else {
6b5e971a 3398 req_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
335fbe0f 3399
7ea7b4a1
AQ
3400 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3401 * in the initial part
3402 */
3403 tt_len = -1;
3404 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3405 &tvlv_tt_data,
3406 &tt_change,
3407 &tt_len);
c2d0f48a 3408 if (!tt_len || !tvlv_len)
a73105b8 3409 goto out;
7ea7b4a1
AQ
3410
3411 /* fill the rest of the tvlv with the real TT entries */
3412 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
3413 tt_change, tt_len,
3414 batadv_tt_local_valid, NULL);
a73105b8
AQ
3415 }
3416
335fbe0f
ML
3417 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3418 tvlv_tt_data->ttvn = req_ttvn;
a73105b8
AQ
3419
3420 if (full_table)
335fbe0f 3421 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3422
39c75a51 3423 batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f
ML
3424 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
3425 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
a73105b8 3426
d69909d2 3427 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865 3428
335fbe0f 3429 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
7ea7b4a1
AQ
3430 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3431 tvlv_len);
335fbe0f 3432
a73105b8
AQ
3433 goto out;
3434
3435unlock:
807736f6 3436 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3437out:
a70a9aa9 3438 spin_unlock_bh(&bat_priv->tt.commit_lock);
a73105b8 3439 if (orig_node)
5d967310 3440 batadv_orig_node_put(orig_node);
a73105b8 3441 if (primary_if)
82047ad7 3442 batadv_hardif_put(primary_if);
335fbe0f
ML
3443 kfree(tvlv_tt_data);
3444 /* The packet was for this host, so it doesn't need to be re-routed */
a73105b8
AQ
3445 return true;
3446}
3447
335fbe0f 3448/**
7e9a8c2c 3449 * batadv_send_tt_response() - send reply to tt request
335fbe0f
ML
3450 * @bat_priv: the bat priv with all the soft interface information
3451 * @tt_data: tt data containing the tt request information
3452 * @req_src: mac address of tt request sender
3453 * @req_dst: mac address of tt request recipient
3454 *
62fe710f 3455 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3456 */
3457static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
3458 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3459 u8 *req_src, u8 *req_dst)
a73105b8 3460{
cfd4f757 3461 if (batadv_is_my_mac(bat_priv, req_dst))
335fbe0f 3462 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
24820df1
AQ
3463 return batadv_send_other_tt_response(bat_priv, tt_data, req_src,
3464 req_dst);
a73105b8
AQ
3465}
3466
56303d34
SE
3467static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
3468 struct batadv_orig_node *orig_node,
335fbe0f 3469 struct batadv_tvlv_tt_change *tt_change,
6b5e971a 3470 u16 tt_num_changes, u8 ttvn)
a73105b8
AQ
3471{
3472 int i;
a513088d 3473 int roams;
a73105b8
AQ
3474
3475 for (i = 0; i < tt_num_changes; i++) {
acd34afa
SE
3476 if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
3477 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
a513088d
SE
3478 batadv_tt_global_del(bat_priv, orig_node,
3479 (tt_change + i)->addr,
c018ad3d 3480 ntohs((tt_change + i)->vid),
d4f44692
AQ
3481 "tt removed by changes",
3482 roams);
08c36d3e 3483 } else {
08c36d3e 3484 if (!batadv_tt_global_add(bat_priv, orig_node,
d4f44692 3485 (tt_change + i)->addr,
c018ad3d 3486 ntohs((tt_change + i)->vid),
d4f44692 3487 (tt_change + i)->flags, ttvn))
a73105b8
AQ
3488 /* In case of problem while storing a
3489 * global_entry, we stop the updating
3490 * procedure without committing the
3491 * ttvn change. This will avoid to send
3492 * corrupted data on tt_request
3493 */
3494 return;
08c36d3e 3495 }
a73105b8 3496 }
ac4eebd4 3497 set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
a73105b8
AQ
3498}
3499
56303d34 3500static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
7ea7b4a1 3501 struct batadv_tvlv_tt_change *tt_change,
6b5e971a
SE
3502 u8 ttvn, u8 *resp_src,
3503 u16 num_entries)
a73105b8 3504{
170173bf 3505 struct batadv_orig_node *orig_node;
a73105b8 3506
335fbe0f 3507 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8
AQ
3508 if (!orig_node)
3509 goto out;
3510
3511 /* Purge the old table first.. */
95fb130d
AQ
3512 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
3513 "Received full table");
a73105b8 3514
7ea7b4a1
AQ
3515 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
3516 ttvn);
a73105b8
AQ
3517
3518 spin_lock_bh(&orig_node->tt_buff_lock);
3519 kfree(orig_node->tt_buff);
3520 orig_node->tt_buff_len = 0;
3521 orig_node->tt_buff = NULL;
3522 spin_unlock_bh(&orig_node->tt_buff_lock);
3523
7ea7b4a1 3524 atomic_set(&orig_node->last_ttvn, ttvn);
a73105b8
AQ
3525
3526out:
3527 if (orig_node)
5d967310 3528 batadv_orig_node_put(orig_node);
a73105b8
AQ
3529}
3530
56303d34
SE
3531static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
3532 struct batadv_orig_node *orig_node,
6b5e971a 3533 u16 tt_num_changes, u8 ttvn,
335fbe0f 3534 struct batadv_tvlv_tt_change *tt_change)
a73105b8 3535{
a513088d
SE
3536 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
3537 tt_num_changes, ttvn);
a73105b8 3538
e8cf234a
AQ
3539 batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
3540 batadv_tt_len(tt_num_changes));
a73105b8
AQ
3541 atomic_set(&orig_node->last_ttvn, ttvn);
3542}
3543
c018ad3d 3544/**
7e9a8c2c 3545 * batadv_is_my_client() - check if a client is served by the local node
c018ad3d 3546 * @bat_priv: the bat priv with all the soft interface information
3f68785e 3547 * @addr: the mac address of the client to check
c018ad3d
AQ
3548 * @vid: VLAN identifier
3549 *
62fe710f 3550 * Return: true if the client is served by this node, false otherwise.
c018ad3d 3551 */
6b5e971a 3552bool batadv_is_my_client(struct batadv_priv *bat_priv, const u8 *addr,
c018ad3d 3553 unsigned short vid)
a73105b8 3554{
170173bf 3555 struct batadv_tt_local_entry *tt_local_entry;
7683fdc1 3556 bool ret = false;
a73105b8 3557
c018ad3d 3558 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1
AQ
3559 if (!tt_local_entry)
3560 goto out;
058d0e26 3561 /* Check if the client has been logically deleted (but is kept for
9cfc7bd6
SE
3562 * consistency purpose)
3563 */
7c1fd91d
AQ
3564 if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
3565 (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
058d0e26 3566 goto out;
7683fdc1
AQ
3567 ret = true;
3568out:
a73105b8 3569 if (tt_local_entry)
95c0db90 3570 batadv_tt_local_entry_put(tt_local_entry);
7683fdc1 3571 return ret;
a73105b8
AQ
3572}
3573
335fbe0f 3574/**
7e9a8c2c 3575 * batadv_handle_tt_response() - process incoming tt reply
335fbe0f
ML
3576 * @bat_priv: the bat priv with all the soft interface information
3577 * @tt_data: tt data containing the tt request information
3578 * @resp_src: mac address of tt reply sender
3579 * @num_entries: number of tt change entries appended to the tt data
3580 */
3581static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
3582 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3583 u8 *resp_src, u16 num_entries)
a73105b8 3584{
7c26a53b
ML
3585 struct batadv_tt_req_node *node;
3586 struct hlist_node *safe;
56303d34 3587 struct batadv_orig_node *orig_node = NULL;
335fbe0f 3588 struct batadv_tvlv_tt_change *tt_change;
6b5e971a
SE
3589 u8 *tvlv_ptr = (u8 *)tt_data;
3590 u16 change_offset;
a73105b8 3591
39c75a51 3592 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3593 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
335fbe0f 3594 resp_src, tt_data->ttvn, num_entries,
a2f2b6cd 3595 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8 3596
335fbe0f 3597 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8
AQ
3598 if (!orig_node)
3599 goto out;
3600
a70a9aa9
AQ
3601 spin_lock_bh(&orig_node->tt_lock);
3602
7ea7b4a1
AQ
3603 change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
3604 change_offset *= ntohs(tt_data->num_vlan);
3605 change_offset += sizeof(*tt_data);
3606 tvlv_ptr += change_offset;
3607
3608 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
335fbe0f 3609 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
7ea7b4a1
AQ
3610 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
3611 resp_src, num_entries);
96412690 3612 } else {
335fbe0f
ML
3613 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
3614 tt_data->ttvn, tt_change);
96412690 3615 }
a73105b8 3616
a70a9aa9 3617 /* Recalculate the CRC for this orig_node and store it */
7ea7b4a1 3618 batadv_tt_global_update_crc(bat_priv, orig_node);
a70a9aa9
AQ
3619
3620 spin_unlock_bh(&orig_node->tt_lock);
3621
a73105b8 3622 /* Delete the tt_req_node from pending tt_requests list */
807736f6 3623 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 3624 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
335fbe0f 3625 if (!batadv_compare_eth(node->addr, resp_src))
a73105b8 3626 continue;
7c26a53b 3627 hlist_del_init(&node->list);
9c4604a2 3628 batadv_tt_req_node_put(node);
a73105b8 3629 }
7ea7b4a1 3630
807736f6 3631 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
3632out:
3633 if (orig_node)
5d967310 3634 batadv_orig_node_put(orig_node);
a73105b8
AQ
3635}
3636
56303d34 3637static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
a73105b8 3638{
56303d34 3639 struct batadv_tt_roam_node *node, *safe;
a73105b8 3640
807736f6 3641 spin_lock_bh(&bat_priv->tt.roam_list_lock);
a73105b8 3642
807736f6 3643 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
cc47f66e 3644 list_del(&node->list);
86452f81 3645 kmem_cache_free(batadv_tt_roam_cache, node);
cc47f66e
AQ
3646 }
3647
807736f6 3648 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3649}
3650
56303d34 3651static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
cc47f66e 3652{
56303d34 3653 struct batadv_tt_roam_node *node, *safe;
cc47f66e 3654
807736f6
SE
3655 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3656 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
42d0b044
SE
3657 if (!batadv_has_timed_out(node->first_time,
3658 BATADV_ROAMING_MAX_TIME))
cc47f66e
AQ
3659 continue;
3660
3661 list_del(&node->list);
86452f81 3662 kmem_cache_free(batadv_tt_roam_cache, node);
cc47f66e 3663 }
807736f6 3664 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3665}
3666
62fe710f 3667/**
7e9a8c2c 3668 * batadv_tt_check_roam_count() - check if a client has roamed too frequently
d15cd622
AQ
3669 * @bat_priv: the bat priv with all the soft interface information
3670 * @client: mac address of the roaming client
62fe710f
SE
3671 *
3672 * This function checks whether the client already reached the
cc47f66e
AQ
3673 * maximum number of possible roaming phases. In this case the ROAMING_ADV
3674 * will not be sent.
3675 *
62fe710f 3676 * Return: true if the ROAMING_ADV can be sent, false otherwise
9cfc7bd6 3677 */
6b5e971a 3678static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, u8 *client)
cc47f66e 3679{
56303d34 3680 struct batadv_tt_roam_node *tt_roam_node;
cc47f66e
AQ
3681 bool ret = false;
3682
807736f6 3683 spin_lock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e 3684 /* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd6
SE
3685 * reply from the same orig_node yet
3686 */
807736f6 3687 list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
1eda58bf 3688 if (!batadv_compare_eth(tt_roam_node->addr, client))
cc47f66e
AQ
3689 continue;
3690
1eda58bf 3691 if (batadv_has_timed_out(tt_roam_node->first_time,
42d0b044 3692 BATADV_ROAMING_MAX_TIME))
cc47f66e
AQ
3693 continue;
3694
3e34819e 3695 if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
cc47f66e
AQ
3696 /* Sorry, you roamed too many times! */
3697 goto unlock;
3698 ret = true;
3699 break;
3700 }
3701
3702 if (!ret) {
86452f81
SE
3703 tt_roam_node = kmem_cache_alloc(batadv_tt_roam_cache,
3704 GFP_ATOMIC);
cc47f66e
AQ
3705 if (!tt_roam_node)
3706 goto unlock;
3707
3708 tt_roam_node->first_time = jiffies;
42d0b044
SE
3709 atomic_set(&tt_roam_node->counter,
3710 BATADV_ROAMING_MAX_COUNT - 1);
8fdd0153 3711 ether_addr_copy(tt_roam_node->addr, client);
cc47f66e 3712
807736f6 3713 list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
cc47f66e
AQ
3714 ret = true;
3715 }
3716
3717unlock:
807736f6 3718 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3719 return ret;
3720}
3721
c018ad3d 3722/**
7e9a8c2c 3723 * batadv_send_roam_adv() - send a roaming advertisement message
c018ad3d
AQ
3724 * @bat_priv: the bat priv with all the soft interface information
3725 * @client: mac address of the roaming client
3726 * @vid: VLAN identifier
3727 * @orig_node: message destination
3728 *
3729 * Send a ROAMING_ADV message to the node which was previously serving this
3730 * client. This is done to inform the node that from now on all traffic destined
3731 * for this particular roamed client has to be forwarded to the sender of the
3732 * roaming message.
3733 */
6b5e971a 3734static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
c018ad3d 3735 unsigned short vid,
56303d34 3736 struct batadv_orig_node *orig_node)
cc47f66e 3737{
56303d34 3738 struct batadv_hard_iface *primary_if;
122edaa0
ML
3739 struct batadv_tvlv_roam_adv tvlv_roam;
3740
3741 primary_if = batadv_primary_if_get_selected(bat_priv);
3742 if (!primary_if)
3743 goto out;
cc47f66e
AQ
3744
3745 /* before going on we have to check whether the client has
9cfc7bd6
SE
3746 * already roamed to us too many times
3747 */
a513088d 3748 if (!batadv_tt_check_roam_count(bat_priv, client))
cc47f66e
AQ
3749 goto out;
3750
39c75a51 3751 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 3752 "Sending ROAMING_ADV to %pM (client %pM, vid: %d)\n",
f7a2bd65 3753 orig_node->orig, client, batadv_print_vid(vid));
cc47f66e 3754
d69909d2 3755 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
f8214865 3756
122edaa0 3757 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
c018ad3d 3758 tvlv_roam.vid = htons(vid);
122edaa0
ML
3759
3760 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3761 orig_node->orig, BATADV_TVLV_ROAM, 1,
3762 &tvlv_roam, sizeof(tvlv_roam));
cc47f66e
AQ
3763
3764out:
122edaa0 3765 if (primary_if)
82047ad7 3766 batadv_hardif_put(primary_if);
a73105b8
AQ
3767}
3768
a513088d 3769static void batadv_tt_purge(struct work_struct *work)
a73105b8 3770{
56303d34 3771 struct delayed_work *delayed_work;
807736f6 3772 struct batadv_priv_tt *priv_tt;
56303d34
SE
3773 struct batadv_priv *bat_priv;
3774
4ba4bc0f 3775 delayed_work = to_delayed_work(work);
807736f6
SE
3776 priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
3777 bat_priv = container_of(priv_tt, struct batadv_priv, tt);
a73105b8 3778
a19d3d85 3779 batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT);
30cfd02b 3780 batadv_tt_global_purge(bat_priv);
a513088d
SE
3781 batadv_tt_req_purge(bat_priv);
3782 batadv_tt_roam_purge(bat_priv);
a73105b8 3783
72414442
AQ
3784 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
3785 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
a73105b8 3786}
cc47f66e 3787
ff15c27c
SE
3788/**
3789 * batadv_tt_free() - Free translation table of soft interface
3790 * @bat_priv: the bat priv with all the soft interface information
3791 */
56303d34 3792void batadv_tt_free(struct batadv_priv *bat_priv)
cc47f66e 3793{
e1bf0c14
ML
3794 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
3795 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
3796
807736f6 3797 cancel_delayed_work_sync(&bat_priv->tt.work);
cc47f66e 3798
a513088d
SE
3799 batadv_tt_local_table_free(bat_priv);
3800 batadv_tt_global_table_free(bat_priv);
3801 batadv_tt_req_list_free(bat_priv);
3802 batadv_tt_changes_list_free(bat_priv);
3803 batadv_tt_roam_list_free(bat_priv);
cc47f66e 3804
807736f6 3805 kfree(bat_priv->tt.last_changeset);
cc47f66e 3806}
058d0e26 3807
7ea7b4a1 3808/**
7e9a8c2c 3809 * batadv_tt_local_set_flags() - set or unset the specified flags on the local
7ea7b4a1
AQ
3810 * table and possibly count them in the TT size
3811 * @bat_priv: the bat priv with all the soft interface information
3812 * @flags: the flag to switch
3813 * @enable: whether to set or unset the flag
3814 * @count: whether to increase the TT size by the number of changed entries
9cfc7bd6 3815 */
6b5e971a
SE
3816static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv, u16 flags,
3817 bool enable, bool count)
058d0e26 3818{
7ea7b4a1
AQ
3819 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
3820 struct batadv_tt_common_entry *tt_common_entry;
058d0e26 3821 struct hlist_head *head;
6b5e971a 3822 u32 i;
058d0e26
AQ
3823
3824 if (!hash)
7ea7b4a1 3825 return;
058d0e26
AQ
3826
3827 for (i = 0; i < hash->size; i++) {
3828 head = &hash->table[i];
3829
3830 rcu_read_lock();
b67bfe0d 3831 hlist_for_each_entry_rcu(tt_common_entry,
058d0e26 3832 head, hash_entry) {
697f2531
AQ
3833 if (enable) {
3834 if ((tt_common_entry->flags & flags) == flags)
3835 continue;
3836 tt_common_entry->flags |= flags;
3837 } else {
3838 if (!(tt_common_entry->flags & flags))
3839 continue;
3840 tt_common_entry->flags &= ~flags;
3841 }
7ea7b4a1
AQ
3842
3843 if (!count)
3844 continue;
3845
3846 batadv_tt_local_size_inc(bat_priv,
3847 tt_common_entry->vid);
058d0e26
AQ
3848 }
3849 rcu_read_unlock();
3850 }
058d0e26
AQ
3851}
3852
acd34afa 3853/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
56303d34 3854static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
058d0e26 3855{
807736f6 3856 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34
SE
3857 struct batadv_tt_common_entry *tt_common;
3858 struct batadv_tt_local_entry *tt_local;
b67bfe0d 3859 struct hlist_node *node_tmp;
058d0e26
AQ
3860 struct hlist_head *head;
3861 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 3862 u32 i;
058d0e26
AQ
3863
3864 if (!hash)
3865 return;
3866
3867 for (i = 0; i < hash->size; i++) {
3868 head = &hash->table[i];
3869 list_lock = &hash->list_locks[i];
3870
3871 spin_lock_bh(list_lock);
b67bfe0d 3872 hlist_for_each_entry_safe(tt_common, node_tmp, head,
acd34afa
SE
3873 hash_entry) {
3874 if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
058d0e26
AQ
3875 continue;
3876
39c75a51 3877 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
3878 "Deleting local tt entry (%pM, vid: %d): pending\n",
3879 tt_common->addr,
f7a2bd65 3880 batadv_print_vid(tt_common->vid));
058d0e26 3881
7ea7b4a1 3882 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
b67bfe0d 3883 hlist_del_rcu(&tt_common->hash_entry);
56303d34
SE
3884 tt_local = container_of(tt_common,
3885 struct batadv_tt_local_entry,
3886 common);
35df3b29 3887
95c0db90 3888 batadv_tt_local_entry_put(tt_local);
058d0e26
AQ
3889 }
3890 spin_unlock_bh(list_lock);
3891 }
058d0e26
AQ
3892}
3893
e1bf0c14 3894/**
7e9a8c2c 3895 * batadv_tt_local_commit_changes_nolock() - commit all pending local tt changes
a19d3d85 3896 * which have been queued in the time since the last commit
e1bf0c14 3897 * @bat_priv: the bat priv with all the soft interface information
a19d3d85
ML
3898 *
3899 * Caller must hold tt->commit_lock.
e1bf0c14 3900 */
a19d3d85 3901static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
058d0e26 3902{
5274cd68
SE
3903 lockdep_assert_held(&bat_priv->tt.commit_lock);
3904
e1bf0c14
ML
3905 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
3906 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
3907 batadv_tt_tvlv_container_update(bat_priv);
a19d3d85 3908 return;
e1bf0c14 3909 }
be9aa4c1 3910
7ea7b4a1 3911 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
be9aa4c1 3912
a513088d 3913 batadv_tt_local_purge_pending_clients(bat_priv);
7ea7b4a1 3914 batadv_tt_local_update_crc(bat_priv);
058d0e26
AQ
3915
3916 /* Increment the TTVN only once per OGM interval */
807736f6 3917 atomic_inc(&bat_priv->tt.vn);
39c75a51 3918 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3919 "Local changes committed, updating to ttvn %u\n",
6b5e971a 3920 (u8)atomic_read(&bat_priv->tt.vn));
be9aa4c1
ML
3921
3922 /* reset the sending counter */
807736f6 3923 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
e1bf0c14 3924 batadv_tt_tvlv_container_update(bat_priv);
a19d3d85 3925}
a70a9aa9 3926
a19d3d85 3927/**
7e9a8c2c 3928 * batadv_tt_local_commit_changes() - commit all pending local tt changes which
a19d3d85
ML
3929 * have been queued in the time since the last commit
3930 * @bat_priv: the bat priv with all the soft interface information
3931 */
3932void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
3933{
3934 spin_lock_bh(&bat_priv->tt.commit_lock);
3935 batadv_tt_local_commit_changes_nolock(bat_priv);
a70a9aa9 3936 spin_unlock_bh(&bat_priv->tt.commit_lock);
058d0e26 3937}
59b699cd 3938
ff15c27c
SE
3939/**
3940 * batadv_is_ap_isolated() - Check if packet from upper layer should be dropped
3941 * @bat_priv: the bat priv with all the soft interface information
3942 * @src: source mac address of packet
3943 * @dst: destination mac address of packet
3944 * @vid: vlan id of packet
3945 *
3946 * Return: true when src+dst(+vid) pair should be isolated, false otherwise
3947 */
6b5e971a
SE
3948bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
3949 unsigned short vid)
59b699cd 3950{
393b299d
ME
3951 struct batadv_tt_local_entry *tt_local_entry;
3952 struct batadv_tt_global_entry *tt_global_entry;
b8cbd81d 3953 struct batadv_softif_vlan *vlan;
5870adc6 3954 bool ret = false;
59b699cd 3955
b8cbd81d 3956 vlan = batadv_softif_vlan_get(bat_priv, vid);
e087f34f
ME
3957 if (!vlan)
3958 return false;
3959
3960 if (!atomic_read(&vlan->ap_isolation))
393b299d 3961 goto vlan_put;
59b699cd 3962
b8cbd81d 3963 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
59b699cd 3964 if (!tt_local_entry)
393b299d 3965 goto vlan_put;
59b699cd 3966
b8cbd81d 3967 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
59b699cd 3968 if (!tt_global_entry)
393b299d 3969 goto local_entry_put;
59b699cd 3970
393b299d
ME
3971 if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3972 ret = true;
59b699cd 3973
393b299d
ME
3974 batadv_tt_global_entry_put(tt_global_entry);
3975local_entry_put:
3976 batadv_tt_local_entry_put(tt_local_entry);
3977vlan_put:
9c3bf081 3978 batadv_softif_vlan_put(vlan);
59b699cd
AQ
3979 return ret;
3980}
a943cac1 3981
e1bf0c14 3982/**
7e9a8c2c 3983 * batadv_tt_update_orig() - update global translation table with new tt
e1bf0c14
ML
3984 * information received via ogms
3985 * @bat_priv: the bat priv with all the soft interface information
e51f0397
SE
3986 * @orig_node: the orig_node of the ogm
3987 * @tt_buff: pointer to the first tvlv VLAN entry
7ea7b4a1
AQ
3988 * @tt_num_vlan: number of tvlv VLAN entries
3989 * @tt_change: pointer to the first entry in the TT buffer
e1bf0c14
ML
3990 * @tt_num_changes: number of tt changes inside the tt buffer
3991 * @ttvn: translation table version number of this changeset
e1bf0c14
ML
3992 */
3993static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
3994 struct batadv_orig_node *orig_node,
6b5e971a 3995 const void *tt_buff, u16 tt_num_vlan,
7ea7b4a1 3996 struct batadv_tvlv_tt_change *tt_change,
6b5e971a 3997 u16 tt_num_changes, u8 ttvn)
a943cac1 3998{
6b5e971a 3999 u8 orig_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
7ea7b4a1 4000 struct batadv_tvlv_tt_vlan_data *tt_vlan;
a943cac1 4001 bool full_table = true;
e17931d1 4002 bool has_tt_init;
a943cac1 4003
7ea7b4a1 4004 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
ac4eebd4
LL
4005 has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
4006 &orig_node->capa_initialized);
e17931d1 4007
17071578 4008 /* orig table not initialised AND first diff is in the OGM OR the ttvn
9cfc7bd6
SE
4009 * increased by one -> we can apply the attached changes
4010 */
e17931d1 4011 if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) {
a943cac1 4012 /* the OGM could not contain the changes due to their size or
42d0b044
SE
4013 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
4014 * times.
9cfc7bd6
SE
4015 * In this case send a tt request
4016 */
a943cac1
ML
4017 if (!tt_num_changes) {
4018 full_table = false;
4019 goto request_table;
4020 }
4021
a70a9aa9
AQ
4022 spin_lock_bh(&orig_node->tt_lock);
4023
a513088d 4024 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
96412690 4025 ttvn, tt_change);
a943cac1
ML
4026
4027 /* Even if we received the precomputed crc with the OGM, we
4028 * prefer to recompute it to spot any possible inconsistency
9cfc7bd6
SE
4029 * in the global table
4030 */
7ea7b4a1 4031 batadv_tt_global_update_crc(bat_priv, orig_node);
a943cac1 4032
a70a9aa9
AQ
4033 spin_unlock_bh(&orig_node->tt_lock);
4034
a943cac1
ML
4035 /* The ttvn alone is not enough to guarantee consistency
4036 * because a single value could represent different states
4037 * (due to the wrap around). Thus a node has to check whether
4038 * the resulting table (after applying the changes) is still
4039 * consistent or not. E.g. a node could disconnect while its
4040 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
4041 * checking the CRC value is mandatory to detect the
9cfc7bd6
SE
4042 * inconsistency
4043 */
7ea7b4a1
AQ
4044 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
4045 tt_num_vlan))
a943cac1 4046 goto request_table;
a943cac1
ML
4047 } else {
4048 /* if we missed more than one change or our tables are not
9cfc7bd6
SE
4049 * in sync anymore -> request fresh tt data
4050 */
e17931d1 4051 if (!has_tt_init || ttvn != orig_ttvn ||
7ea7b4a1
AQ
4052 !batadv_tt_global_check_crc(orig_node, tt_vlan,
4053 tt_num_vlan)) {
a943cac1 4054request_table:
39c75a51 4055 batadv_dbg(BATADV_DBG_TT, bat_priv,
7ea7b4a1
AQ
4056 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
4057 orig_node->orig, ttvn, orig_ttvn,
4058 tt_num_changes);
a513088d 4059 batadv_send_tt_request(bat_priv, orig_node, ttvn,
7ea7b4a1
AQ
4060 tt_vlan, tt_num_vlan,
4061 full_table);
a943cac1
ML
4062 return;
4063 }
4064 }
4065}
3275e7cc 4066
c018ad3d 4067/**
7e9a8c2c 4068 * batadv_tt_global_client_is_roaming() - check if a client is marked as roaming
c018ad3d
AQ
4069 * @bat_priv: the bat priv with all the soft interface information
4070 * @addr: the mac address of the client to check
4071 * @vid: VLAN identifier
4072 *
62fe710f 4073 * Return: true if we know that the client has moved from its old originator
c018ad3d
AQ
4074 * to another one. This entry is still kept for consistency purposes and will be
4075 * deleted later by a DEL or because of timeout
3275e7cc 4076 */
56303d34 4077bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
6b5e971a 4078 u8 *addr, unsigned short vid)
3275e7cc 4079{
56303d34 4080 struct batadv_tt_global_entry *tt_global_entry;
3275e7cc
AQ
4081 bool ret = false;
4082
c018ad3d 4083 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
3275e7cc
AQ
4084 if (!tt_global_entry)
4085 goto out;
4086
c1d07431 4087 ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
5dafd8a6 4088 batadv_tt_global_entry_put(tt_global_entry);
3275e7cc
AQ
4089out:
4090 return ret;
4091}
30cfd02b 4092
7c1fd91d 4093/**
7e9a8c2c 4094 * batadv_tt_local_client_is_roaming() - tells whether the client is roaming
7c1fd91d 4095 * @bat_priv: the bat priv with all the soft interface information
c018ad3d
AQ
4096 * @addr: the mac address of the local client to query
4097 * @vid: VLAN identifier
7c1fd91d 4098 *
62fe710f 4099 * Return: true if the local client is known to be roaming (it is not served by
7c1fd91d
AQ
4100 * this node anymore) or not. If yes, the client is still present in the table
4101 * to keep the latter consistent with the node TTVN
4102 */
4103bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
6b5e971a 4104 u8 *addr, unsigned short vid)
7c1fd91d
AQ
4105{
4106 struct batadv_tt_local_entry *tt_local_entry;
4107 bool ret = false;
4108
c018ad3d 4109 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7c1fd91d
AQ
4110 if (!tt_local_entry)
4111 goto out;
4112
4113 ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
95c0db90 4114 batadv_tt_local_entry_put(tt_local_entry);
7c1fd91d
AQ
4115out:
4116 return ret;
7c1fd91d
AQ
4117}
4118
ff15c27c
SE
4119/**
4120 * batadv_tt_add_temporary_global_entry() - Add temporary entry to global TT
4121 * @bat_priv: the bat priv with all the soft interface information
4122 * @orig_node: orig node which the temporary entry should be associated with
4123 * @addr: mac address of the client
4124 * @vid: VLAN id of the new temporary global translation table
4125 *
4126 * Return: true when temporary tt entry could be added, false otherwise
4127 */
30cfd02b
AQ
4128bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
4129 struct batadv_orig_node *orig_node,
c018ad3d 4130 const unsigned char *addr,
16052789 4131 unsigned short vid)
30cfd02b 4132{
1227c9ae
SW
4133 /* ignore loop detect macs, they are not supposed to be in the tt local
4134 * data as well.
4135 */
4136 if (batadv_bla_is_loopdetect_mac(addr))
4137 return false;
4138
16052789 4139 if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
30cfd02b
AQ
4140 BATADV_TT_CLIENT_TEMP,
4141 atomic_read(&orig_node->last_ttvn)))
75ae84a4 4142 return false;
30cfd02b
AQ
4143
4144 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 4145 "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
f7a2bd65 4146 addr, batadv_print_vid(vid), orig_node->orig);
75ae84a4
SW
4147
4148 return true;
30cfd02b 4149}
e1bf0c14 4150
a19d3d85 4151/**
7e9a8c2c 4152 * batadv_tt_local_resize_to_mtu() - resize the local translation table fit the
a19d3d85
ML
4153 * maximum packet size that can be transported through the mesh
4154 * @soft_iface: netdev struct of the mesh interface
4155 *
4156 * Remove entries older than 'timeout' and half timeout if more entries need
4157 * to be removed.
4158 */
4159void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
4160{
4161 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
4162 int packet_size_max = atomic_read(&bat_priv->packet_size_max);
4163 int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
4164 bool reduced = false;
4165
4166 spin_lock_bh(&bat_priv->tt.commit_lock);
4167
4168 while (true) {
4169 table_size = batadv_tt_local_table_transmit_size(bat_priv);
4170 if (packet_size_max >= table_size)
4171 break;
4172
4173 batadv_tt_local_purge(bat_priv, timeout);
4174 batadv_tt_local_purge_pending_clients(bat_priv);
4175
4176 timeout /= 2;
4177 reduced = true;
4178 net_ratelimited_function(batadv_info, soft_iface,
4179 "Forced to purge local tt entries to fit new maximum fragment MTU (%i)\n",
4180 packet_size_max);
4181 }
4182
4183 /* commit these changes immediately, to avoid synchronization problem
4184 * with the TTVN
4185 */
4186 if (reduced)
4187 batadv_tt_local_commit_changes_nolock(bat_priv);
4188
4189 spin_unlock_bh(&bat_priv->tt.commit_lock);
4190}
4191
e1bf0c14 4192/**
7e9a8c2c 4193 * batadv_tt_tvlv_ogm_handler_v1() - process incoming tt tvlv container
e1bf0c14
ML
4194 * @bat_priv: the bat priv with all the soft interface information
4195 * @orig: the orig_node of the ogm
4196 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
4197 * @tvlv_value: tvlv buffer containing the gateway data
4198 * @tvlv_value_len: tvlv buffer length
4199 */
4200static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
4201 struct batadv_orig_node *orig,
6b5e971a
SE
4202 u8 flags, void *tvlv_value,
4203 u16 tvlv_value_len)
e1bf0c14 4204{
7ea7b4a1
AQ
4205 struct batadv_tvlv_tt_vlan_data *tt_vlan;
4206 struct batadv_tvlv_tt_change *tt_change;
e1bf0c14 4207 struct batadv_tvlv_tt_data *tt_data;
6b5e971a 4208 u16 num_entries, num_vlan;
e1bf0c14
ML
4209
4210 if (tvlv_value_len < sizeof(*tt_data))
4211 return;
4212
4213 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4214 tvlv_value_len -= sizeof(*tt_data);
4215
7ea7b4a1
AQ
4216 num_vlan = ntohs(tt_data->num_vlan);
4217
4218 if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
4219 return;
4220
4221 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
4222 tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
4223 tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
4224
298e6e68 4225 num_entries = batadv_tt_entries(tvlv_value_len);
e1bf0c14 4226
7ea7b4a1
AQ
4227 batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
4228 num_entries, tt_data->ttvn);
e1bf0c14
ML
4229}
4230
335fbe0f 4231/**
7e9a8c2c 4232 * batadv_tt_tvlv_unicast_handler_v1() - process incoming (unicast) tt tvlv
335fbe0f
ML
4233 * container
4234 * @bat_priv: the bat priv with all the soft interface information
4235 * @src: mac address of tt tvlv sender
4236 * @dst: mac address of tt tvlv recipient
4237 * @tvlv_value: tvlv buffer containing the tt data
4238 * @tvlv_value_len: tvlv buffer length
4239 *
62fe710f 4240 * Return: NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
335fbe0f
ML
4241 * otherwise.
4242 */
4243static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
6b5e971a 4244 u8 *src, u8 *dst,
335fbe0f 4245 void *tvlv_value,
6b5e971a 4246 u16 tvlv_value_len)
335fbe0f
ML
4247{
4248 struct batadv_tvlv_tt_data *tt_data;
6b5e971a 4249 u16 tt_vlan_len, tt_num_entries;
335fbe0f
ML
4250 char tt_flag;
4251 bool ret;
4252
4253 if (tvlv_value_len < sizeof(*tt_data))
4254 return NET_RX_SUCCESS;
4255
4256 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4257 tvlv_value_len -= sizeof(*tt_data);
4258
7ea7b4a1
AQ
4259 tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
4260 tt_vlan_len *= ntohs(tt_data->num_vlan);
4261
4262 if (tvlv_value_len < tt_vlan_len)
4263 return NET_RX_SUCCESS;
4264
4265 tvlv_value_len -= tt_vlan_len;
4266 tt_num_entries = batadv_tt_entries(tvlv_value_len);
335fbe0f
ML
4267
4268 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
4269 case BATADV_TT_REQUEST:
4270 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
4271
4272 /* If this node cannot provide a TT response the tt_request is
4273 * forwarded
4274 */
4275 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
4276 if (!ret) {
4277 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4278 tt_flag = 'F';
4279 else
4280 tt_flag = '.';
4281
4282 batadv_dbg(BATADV_DBG_TT, bat_priv,
4283 "Routing TT_REQUEST to %pM [%c]\n",
4284 dst, tt_flag);
4285 /* tvlv API will re-route the packet */
4286 return NET_RX_DROP;
4287 }
4288 break;
4289 case BATADV_TT_RESPONSE:
4290 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
4291
4292 if (batadv_is_my_mac(bat_priv, dst)) {
4293 batadv_handle_tt_response(bat_priv, tt_data,
7ea7b4a1 4294 src, tt_num_entries);
335fbe0f
ML
4295 return NET_RX_SUCCESS;
4296 }
4297
4298 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4299 tt_flag = 'F';
4300 else
4301 tt_flag = '.';
4302
4303 batadv_dbg(BATADV_DBG_TT, bat_priv,
4304 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
4305
4306 /* tvlv API will re-route the packet */
4307 return NET_RX_DROP;
4308 }
4309
4310 return NET_RX_SUCCESS;
4311}
4312
122edaa0 4313/**
7e9a8c2c
SE
4314 * batadv_roam_tvlv_unicast_handler_v1() - process incoming tt roam tvlv
4315 * container
122edaa0
ML
4316 * @bat_priv: the bat priv with all the soft interface information
4317 * @src: mac address of tt tvlv sender
4318 * @dst: mac address of tt tvlv recipient
4319 * @tvlv_value: tvlv buffer containing the tt data
4320 * @tvlv_value_len: tvlv buffer length
4321 *
62fe710f 4322 * Return: NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
122edaa0
ML
4323 * otherwise.
4324 */
4325static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
6b5e971a 4326 u8 *src, u8 *dst,
122edaa0 4327 void *tvlv_value,
6b5e971a 4328 u16 tvlv_value_len)
122edaa0
ML
4329{
4330 struct batadv_tvlv_roam_adv *roaming_adv;
4331 struct batadv_orig_node *orig_node = NULL;
4332
4333 /* If this node is not the intended recipient of the
4334 * roaming advertisement the packet is forwarded
4335 * (the tvlv API will re-route the packet).
4336 */
4337 if (!batadv_is_my_mac(bat_priv, dst))
4338 return NET_RX_DROP;
4339
122edaa0
ML
4340 if (tvlv_value_len < sizeof(*roaming_adv))
4341 goto out;
4342
4343 orig_node = batadv_orig_hash_find(bat_priv, src);
4344 if (!orig_node)
4345 goto out;
4346
4347 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
4348 roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value;
4349
4350 batadv_dbg(BATADV_DBG_TT, bat_priv,
4351 "Received ROAMING_ADV from %pM (client %pM)\n",
4352 src, roaming_adv->client);
4353
4354 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
c018ad3d 4355 ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
122edaa0
ML
4356 atomic_read(&orig_node->last_ttvn) + 1);
4357
4358out:
4359 if (orig_node)
5d967310 4360 batadv_orig_node_put(orig_node);
122edaa0
ML
4361 return NET_RX_SUCCESS;
4362}
4363
e1bf0c14 4364/**
7e9a8c2c 4365 * batadv_tt_init() - initialise the translation table internals
e1bf0c14
ML
4366 * @bat_priv: the bat priv with all the soft interface information
4367 *
62fe710f 4368 * Return: 0 on success or negative error number in case of failure.
e1bf0c14
ML
4369 */
4370int batadv_tt_init(struct batadv_priv *bat_priv)
4371{
4372 int ret;
4373
0eb01568
AQ
4374 /* synchronized flags must be remote */
4375 BUILD_BUG_ON(!(BATADV_TT_SYNC_MASK & BATADV_TT_REMOTE_MASK));
4376
e1bf0c14
ML
4377 ret = batadv_tt_local_init(bat_priv);
4378 if (ret < 0)
4379 return ret;
4380
4381 ret = batadv_tt_global_init(bat_priv);
4382 if (ret < 0)
4383 return ret;
4384
4385 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
335fbe0f
ML
4386 batadv_tt_tvlv_unicast_handler_v1,
4387 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
e1bf0c14 4388
122edaa0
ML
4389 batadv_tvlv_handler_register(bat_priv, NULL,
4390 batadv_roam_tvlv_unicast_handler_v1,
4391 BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
4392
e1bf0c14
ML
4393 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
4394 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
4395 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
4396
4397 return 1;
4398}
42cb0bef
AQ
4399
4400/**
7e9a8c2c 4401 * batadv_tt_global_is_isolated() - check if a client is marked as isolated
42cb0bef
AQ
4402 * @bat_priv: the bat priv with all the soft interface information
4403 * @addr: the mac address of the client
4404 * @vid: the identifier of the VLAN where this client is connected
4405 *
62fe710f 4406 * Return: true if the client is marked with the TT_CLIENT_ISOLA flag, false
42cb0bef
AQ
4407 * otherwise
4408 */
4409bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
6b5e971a 4410 const u8 *addr, unsigned short vid)
42cb0bef
AQ
4411{
4412 struct batadv_tt_global_entry *tt;
4413 bool ret;
4414
4415 tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
4416 if (!tt)
4417 return false;
4418
4419 ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
4420
5dafd8a6 4421 batadv_tt_global_entry_put(tt);
42cb0bef
AQ
4422
4423 return ret;
4424}
86452f81
SE
4425
4426/**
7e9a8c2c 4427 * batadv_tt_cache_init() - Initialize tt memory object cache
86452f81
SE
4428 *
4429 * Return: 0 on success or negative error number in case of failure.
4430 */
4431int __init batadv_tt_cache_init(void)
4432{
4433 size_t tl_size = sizeof(struct batadv_tt_local_entry);
4434 size_t tg_size = sizeof(struct batadv_tt_global_entry);
4435 size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
4436 size_t tt_change_size = sizeof(struct batadv_tt_change_node);
4437 size_t tt_req_size = sizeof(struct batadv_tt_req_node);
4438 size_t tt_roam_size = sizeof(struct batadv_tt_roam_node);
4439
4440 batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
4441 SLAB_HWCACHE_ALIGN, NULL);
4442 if (!batadv_tl_cache)
4443 return -ENOMEM;
4444
4445 batadv_tg_cache = kmem_cache_create("batadv_tg_cache", tg_size, 0,
4446 SLAB_HWCACHE_ALIGN, NULL);
4447 if (!batadv_tg_cache)
4448 goto err_tt_tl_destroy;
4449
4450 batadv_tt_orig_cache = kmem_cache_create("batadv_tt_orig_cache",
4451 tt_orig_size, 0,
4452 SLAB_HWCACHE_ALIGN, NULL);
4453 if (!batadv_tt_orig_cache)
4454 goto err_tt_tg_destroy;
4455
4456 batadv_tt_change_cache = kmem_cache_create("batadv_tt_change_cache",
4457 tt_change_size, 0,
4458 SLAB_HWCACHE_ALIGN, NULL);
4459 if (!batadv_tt_change_cache)
4460 goto err_tt_orig_destroy;
4461
4462 batadv_tt_req_cache = kmem_cache_create("batadv_tt_req_cache",
4463 tt_req_size, 0,
4464 SLAB_HWCACHE_ALIGN, NULL);
4465 if (!batadv_tt_req_cache)
4466 goto err_tt_change_destroy;
4467
4468 batadv_tt_roam_cache = kmem_cache_create("batadv_tt_roam_cache",
4469 tt_roam_size, 0,
4470 SLAB_HWCACHE_ALIGN, NULL);
4471 if (!batadv_tt_roam_cache)
4472 goto err_tt_req_destroy;
4473
4474 return 0;
4475
4476err_tt_req_destroy:
4477 kmem_cache_destroy(batadv_tt_req_cache);
4478 batadv_tt_req_cache = NULL;
4479err_tt_change_destroy:
4480 kmem_cache_destroy(batadv_tt_change_cache);
4481 batadv_tt_change_cache = NULL;
4482err_tt_orig_destroy:
4483 kmem_cache_destroy(batadv_tt_orig_cache);
4484 batadv_tt_orig_cache = NULL;
4485err_tt_tg_destroy:
4486 kmem_cache_destroy(batadv_tg_cache);
4487 batadv_tg_cache = NULL;
4488err_tt_tl_destroy:
4489 kmem_cache_destroy(batadv_tl_cache);
4490 batadv_tl_cache = NULL;
4491
4492 return -ENOMEM;
4493}
4494
4495/**
7e9a8c2c 4496 * batadv_tt_cache_destroy() - Destroy tt memory object cache
86452f81
SE
4497 */
4498void batadv_tt_cache_destroy(void)
4499{
4500 kmem_cache_destroy(batadv_tl_cache);
4501 kmem_cache_destroy(batadv_tg_cache);
4502 kmem_cache_destroy(batadv_tt_orig_cache);
4503 kmem_cache_destroy(batadv_tt_change_cache);
4504 kmem_cache_destroy(batadv_tt_req_cache);
4505 kmem_cache_destroy(batadv_tt_roam_cache);
4506}