batman-adv: Add kernel-doc to functions in headers
[linux-2.6-block.git] / net / batman-adv / translation-table.c
CommitLineData
7db7d9f3 1// SPDX-License-Identifier: GPL-2.0
ac79cbb9 2/* Copyright (C) 2007-2017 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>
55#include <uapi/linux/batman_adv.h>
1e2c2a4f
SE
56
57#include "bridge_loop_avoidance.h"
32ae9b22 58#include "hard-interface.h"
c6c8fea2 59#include "hash.h"
ba412080 60#include "log.h"
d34f0550 61#include "netlink.h"
1e2c2a4f
SE
62#include "originator.h"
63#include "packet.h"
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
AQ
864
865 rcu_read_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:
903 rcu_read_unlock();
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
939 rcu_read_lock();
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:
977 rcu_read_unlock();
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
08c36d3e 1058int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea2
SE
1059{
1060 struct net_device *net_dev = (struct net_device *)seq->private;
56303d34 1061 struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6 1062 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34 1063 struct batadv_tt_common_entry *tt_common_entry;
85766a82 1064 struct batadv_tt_local_entry *tt_local;
56303d34 1065 struct batadv_hard_iface *primary_if;
c6c8fea2 1066 struct hlist_head *head;
6b5e971a 1067 u32 i;
85766a82
AQ
1068 int last_seen_secs;
1069 int last_seen_msecs;
1070 unsigned long last_seen_jiffies;
1071 bool no_purge;
6b5e971a 1072 u16 np_flag = BATADV_TT_CLIENT_NOPURGE;
c6c8fea2 1073
30da63a6
ML
1074 primary_if = batadv_seq_print_text_primary_if_get(seq);
1075 if (!primary_if)
32ae9b22 1076 goto out;
c6c8fea2 1077
86ceb360 1078 seq_printf(seq,
7ea7b4a1 1079 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
6b5e971a 1080 net_dev->name, (u8)atomic_read(&bat_priv->tt.vn));
925a6f37
AQ
1081 seq_puts(seq,
1082 " Client VID Flags Last seen (CRC )\n");
c6c8fea2 1083
c6c8fea2
SE
1084 for (i = 0; i < hash->size; i++) {
1085 head = &hash->table[i];
1086
7aadf889 1087 rcu_read_lock();
b67bfe0d 1088 hlist_for_each_entry_rcu(tt_common_entry,
7aadf889 1089 head, hash_entry) {
85766a82
AQ
1090 tt_local = container_of(tt_common_entry,
1091 struct batadv_tt_local_entry,
1092 common);
1093 last_seen_jiffies = jiffies - tt_local->last_seen;
1094 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
1095 last_seen_secs = last_seen_msecs / 1000;
1096 last_seen_msecs = last_seen_msecs % 1000;
1097
1098 no_purge = tt_common_entry->flags & np_flag;
7ea7b4a1 1099 seq_printf(seq,
dd24ddb2 1100 " * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
7c64fd98 1101 tt_common_entry->addr,
f7a2bd65 1102 batadv_print_vid(tt_common_entry->vid),
a2f2b6cd
SE
1103 ((tt_common_entry->flags &
1104 BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
85766a82 1105 no_purge ? 'P' : '.',
a2f2b6cd
SE
1106 ((tt_common_entry->flags &
1107 BATADV_TT_CLIENT_NEW) ? 'N' : '.'),
1108 ((tt_common_entry->flags &
1109 BATADV_TT_CLIENT_PENDING) ? 'X' : '.'),
1110 ((tt_common_entry->flags &
1111 BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1112 ((tt_common_entry->flags &
1113 BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
a7966d90 1114 no_purge ? 0 : last_seen_secs,
7ea7b4a1 1115 no_purge ? 0 : last_seen_msecs,
a33d970d 1116 tt_local->vlan->tt.crc);
c6c8fea2 1117 }
7aadf889 1118 rcu_read_unlock();
c6c8fea2 1119 }
32ae9b22
ML
1120out:
1121 if (primary_if)
82047ad7 1122 batadv_hardif_put(primary_if);
30da63a6 1123 return 0;
c6c8fea2 1124}
dc1cbd14 1125#endif
c6c8fea2 1126
d34f0550 1127/**
7e9a8c2c 1128 * batadv_tt_local_dump_entry() - Dump one TT local entry into a message
d34f0550
MS
1129 * @msg :Netlink message to dump into
1130 * @portid: Port making netlink request
1131 * @seq: Sequence number of netlink message
1132 * @bat_priv: The bat priv with all the soft interface information
1133 * @common: tt local & tt global common data
1134 *
1135 * Return: Error code, or 0 on success
1136 */
1137static int
1138batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1139 struct batadv_priv *bat_priv,
1140 struct batadv_tt_common_entry *common)
1141{
1142 void *hdr;
1143 struct batadv_softif_vlan *vlan;
1144 struct batadv_tt_local_entry *local;
1145 unsigned int last_seen_msecs;
1146 u32 crc;
1147
1148 local = container_of(common, struct batadv_tt_local_entry, common);
1149 last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
1150
1151 vlan = batadv_softif_vlan_get(bat_priv, common->vid);
1152 if (!vlan)
1153 return 0;
1154
1155 crc = vlan->tt.crc;
1156
1157 batadv_softif_vlan_put(vlan);
1158
1159 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1160 NLM_F_MULTI,
1161 BATADV_CMD_GET_TRANSTABLE_LOCAL);
1162 if (!hdr)
1163 return -ENOBUFS;
1164
1165 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1166 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1167 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1168 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1169 goto nla_put_failure;
1170
1171 if (!(common->flags & BATADV_TT_CLIENT_NOPURGE) &&
1172 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, last_seen_msecs))
1173 goto nla_put_failure;
1174
1175 genlmsg_end(msg, hdr);
1176 return 0;
1177
1178 nla_put_failure:
1179 genlmsg_cancel(msg, hdr);
1180 return -EMSGSIZE;
1181}
1182
1183/**
7e9a8c2c 1184 * batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message
d34f0550
MS
1185 * @msg: Netlink message to dump into
1186 * @portid: Port making netlink request
1187 * @seq: Sequence number of netlink message
1188 * @bat_priv: The bat priv with all the soft interface information
1189 * @head: Pointer to the list containing the local tt entries
1190 * @idx_s: Number of entries to skip
1191 *
1192 * Return: Error code, or 0 on success
1193 */
1194static int
1195batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1196 struct batadv_priv *bat_priv,
1197 struct hlist_head *head, int *idx_s)
1198{
1199 struct batadv_tt_common_entry *common;
1200 int idx = 0;
1201
1202 rcu_read_lock();
1203 hlist_for_each_entry_rcu(common, head, hash_entry) {
1204 if (idx++ < *idx_s)
1205 continue;
1206
1207 if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
1208 common)) {
1209 rcu_read_unlock();
1210 *idx_s = idx - 1;
1211 return -EMSGSIZE;
1212 }
1213 }
1214 rcu_read_unlock();
1215
1216 *idx_s = 0;
1217 return 0;
1218}
1219
1220/**
7e9a8c2c 1221 * batadv_tt_local_dump() - Dump TT local entries into a message
d34f0550
MS
1222 * @msg: Netlink message to dump into
1223 * @cb: Parameters from query
1224 *
1225 * Return: Error code, or 0 on success
1226 */
1227int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
1228{
1229 struct net *net = sock_net(cb->skb->sk);
1230 struct net_device *soft_iface;
1231 struct batadv_priv *bat_priv;
1232 struct batadv_hard_iface *primary_if = NULL;
1233 struct batadv_hashtable *hash;
1234 struct hlist_head *head;
1235 int ret;
1236 int ifindex;
1237 int bucket = cb->args[0];
1238 int idx = cb->args[1];
1239 int portid = NETLINK_CB(cb->skb).portid;
1240
1241 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1242 if (!ifindex)
1243 return -EINVAL;
1244
1245 soft_iface = dev_get_by_index(net, ifindex);
1246 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1247 ret = -ENODEV;
1248 goto out;
1249 }
1250
1251 bat_priv = netdev_priv(soft_iface);
1252
1253 primary_if = batadv_primary_if_get_selected(bat_priv);
1254 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1255 ret = -ENOENT;
1256 goto out;
1257 }
1258
1259 hash = bat_priv->tt.local_hash;
1260
1261 while (bucket < hash->size) {
1262 head = &hash->table[bucket];
1263
1264 if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
1265 bat_priv, head, &idx))
1266 break;
1267
1268 bucket++;
1269 }
1270
1271 ret = msg->len;
1272
1273 out:
1274 if (primary_if)
1275 batadv_hardif_put(primary_if);
1276 if (soft_iface)
1277 dev_put(soft_iface);
1278
1279 cb->args[0] = bucket;
1280 cb->args[1] = idx;
1281
1282 return ret;
1283}
1284
56303d34
SE
1285static void
1286batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
1287 struct batadv_tt_local_entry *tt_local_entry,
6b5e971a 1288 u16 flags, const char *message)
c6c8fea2 1289{
3abe4adb 1290 batadv_tt_local_event(bat_priv, tt_local_entry, flags);
a73105b8 1291
015758d0
AQ
1292 /* The local client has to be marked as "pending to be removed" but has
1293 * to be kept in the table in order to send it in a full table
9cfc7bd6
SE
1294 * response issued before the net ttvn increment (consistency check)
1295 */
acd34afa 1296 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
c566dbbe 1297
39c75a51 1298 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
1299 "Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
1300 tt_local_entry->common.addr,
f7a2bd65 1301 batadv_print_vid(tt_local_entry->common.vid), message);
c6c8fea2
SE
1302}
1303
7f91d06c 1304/**
7e9a8c2c 1305 * batadv_tt_local_remove() - logically remove an entry from the local table
7f91d06c
AQ
1306 * @bat_priv: the bat priv with all the soft interface information
1307 * @addr: the MAC address of the client to remove
c018ad3d 1308 * @vid: VLAN identifier
7f91d06c
AQ
1309 * @message: message to append to the log on deletion
1310 * @roaming: true if the deletion is due to a roaming event
1311 *
62fe710f 1312 * Return: the flags assigned to the local entry before being deleted
7f91d06c 1313 */
6b5e971a
SE
1314u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
1315 unsigned short vid, const char *message,
1316 bool roaming)
c6c8fea2 1317{
170173bf 1318 struct batadv_tt_local_entry *tt_local_entry;
6b5e971a 1319 u16 flags, curr_flags = BATADV_NO_FLAGS;
ef72706a 1320 void *tt_entry_exists;
c6c8fea2 1321
c018ad3d 1322 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1
AQ
1323 if (!tt_local_entry)
1324 goto out;
1325
7f91d06c
AQ
1326 curr_flags = tt_local_entry->common.flags;
1327
acd34afa 1328 flags = BATADV_TT_CLIENT_DEL;
068ee6e2
AQ
1329 /* if this global entry addition is due to a roaming, the node has to
1330 * mark the local entry as "roamed" in order to correctly reroute
1331 * packets later
1332 */
7c1fd91d 1333 if (roaming) {
acd34afa 1334 flags |= BATADV_TT_CLIENT_ROAM;
7c1fd91d
AQ
1335 /* mark the local client as ROAMed */
1336 tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1337 }
42d0b044 1338
068ee6e2
AQ
1339 if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
1340 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
1341 message);
1342 goto out;
1343 }
1344 /* if this client has been added right now, it is possible to
1345 * immediately purge it
1346 */
3abe4adb 1347 batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
ef72706a
ML
1348
1349 tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
1350 batadv_compare_tt,
1351 batadv_choose_tt,
1352 &tt_local_entry->common);
1353 if (!tt_entry_exists)
1354 goto out;
1355
1356 /* extra call to free the local tt entry */
95c0db90 1357 batadv_tt_local_entry_put(tt_local_entry);
7f91d06c 1358
7683fdc1
AQ
1359out:
1360 if (tt_local_entry)
95c0db90 1361 batadv_tt_local_entry_put(tt_local_entry);
7f91d06c
AQ
1362
1363 return curr_flags;
c6c8fea2
SE
1364}
1365
a19d3d85 1366/**
7e9a8c2c 1367 * batadv_tt_local_purge_list() - purge inactive tt local entries
a19d3d85
ML
1368 * @bat_priv: the bat priv with all the soft interface information
1369 * @head: pointer to the list containing the local tt entries
1370 * @timeout: parameter deciding whether a given tt local entry is considered
1371 * inactive or not
1372 */
56303d34 1373static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
a19d3d85
ML
1374 struct hlist_head *head,
1375 int timeout)
c6c8fea2 1376{
56303d34
SE
1377 struct batadv_tt_local_entry *tt_local_entry;
1378 struct batadv_tt_common_entry *tt_common_entry;
b67bfe0d 1379 struct hlist_node *node_tmp;
acd34afa 1380
b67bfe0d 1381 hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
acd34afa
SE
1382 hash_entry) {
1383 tt_local_entry = container_of(tt_common_entry,
56303d34
SE
1384 struct batadv_tt_local_entry,
1385 common);
acd34afa
SE
1386 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
1387 continue;
1388
1389 /* entry already marked for deletion */
1390 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
1391 continue;
1392
a19d3d85 1393 if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
acd34afa
SE
1394 continue;
1395
1396 batadv_tt_local_set_pending(bat_priv, tt_local_entry,
1397 BATADV_TT_CLIENT_DEL, "timed out");
1398 }
1399}
1400
a19d3d85 1401/**
7e9a8c2c 1402 * batadv_tt_local_purge() - purge inactive tt local entries
a19d3d85
ML
1403 * @bat_priv: the bat priv with all the soft interface information
1404 * @timeout: parameter deciding whether a given tt local entry is considered
1405 * inactive or not
1406 */
1407static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
1408 int timeout)
acd34afa 1409{
807736f6 1410 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
c6c8fea2 1411 struct hlist_head *head;
7683fdc1 1412 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 1413 u32 i;
c6c8fea2 1414
c6c8fea2
SE
1415 for (i = 0; i < hash->size; i++) {
1416 head = &hash->table[i];
7683fdc1 1417 list_lock = &hash->list_locks[i];
c6c8fea2 1418
7683fdc1 1419 spin_lock_bh(list_lock);
a19d3d85 1420 batadv_tt_local_purge_list(bat_priv, head, timeout);
7683fdc1 1421 spin_unlock_bh(list_lock);
c6c8fea2 1422 }
c6c8fea2
SE
1423}
1424
56303d34 1425static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
c6c8fea2 1426{
5bf74e9c 1427 struct batadv_hashtable *hash;
a73105b8 1428 spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34
SE
1429 struct batadv_tt_common_entry *tt_common_entry;
1430 struct batadv_tt_local_entry *tt_local;
b67bfe0d 1431 struct hlist_node *node_tmp;
7683fdc1 1432 struct hlist_head *head;
6b5e971a 1433 u32 i;
a73105b8 1434
807736f6 1435 if (!bat_priv->tt.local_hash)
c6c8fea2
SE
1436 return;
1437
807736f6 1438 hash = bat_priv->tt.local_hash;
a73105b8
AQ
1439
1440 for (i = 0; i < hash->size; i++) {
1441 head = &hash->table[i];
1442 list_lock = &hash->list_locks[i];
1443
1444 spin_lock_bh(list_lock);
b67bfe0d 1445 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
a73105b8 1446 head, hash_entry) {
b67bfe0d 1447 hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34
SE
1448 tt_local = container_of(tt_common_entry,
1449 struct batadv_tt_local_entry,
1450 common);
35df3b29 1451
95c0db90 1452 batadv_tt_local_entry_put(tt_local);
a73105b8
AQ
1453 }
1454 spin_unlock_bh(list_lock);
1455 }
1456
1a8eaf07 1457 batadv_hash_destroy(hash);
a73105b8 1458
807736f6 1459 bat_priv->tt.local_hash = NULL;
c6c8fea2
SE
1460}
1461
56303d34 1462static int batadv_tt_global_init(struct batadv_priv *bat_priv)
c6c8fea2 1463{
807736f6 1464 if (bat_priv->tt.global_hash)
5346c35e 1465 return 0;
c6c8fea2 1466
807736f6 1467 bat_priv->tt.global_hash = batadv_hash_new(1024);
c6c8fea2 1468
807736f6 1469 if (!bat_priv->tt.global_hash)
5346c35e 1470 return -ENOMEM;
c6c8fea2 1471
dec05074
AQ
1472 batadv_hash_set_lock_class(bat_priv->tt.global_hash,
1473 &batadv_tt_global_hash_lock_class_key);
1474
5346c35e 1475 return 0;
c6c8fea2
SE
1476}
1477
56303d34 1478static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
c6c8fea2 1479{
56303d34 1480 struct batadv_tt_change_node *entry, *safe;
c6c8fea2 1481
807736f6 1482 spin_lock_bh(&bat_priv->tt.changes_list_lock);
c6c8fea2 1483
807736f6 1484 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
a73105b8
AQ
1485 list) {
1486 list_del(&entry->list);
86452f81 1487 kmem_cache_free(batadv_tt_change_cache, entry);
a73105b8 1488 }
c6c8fea2 1489
807736f6
SE
1490 atomic_set(&bat_priv->tt.local_changes, 0);
1491 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8 1492}
c6c8fea2 1493
62fe710f 1494/**
7e9a8c2c 1495 * batadv_tt_global_orig_entry_find() - find a TT orig_list_entry
d15cd622
AQ
1496 * @entry: the TT global entry where the orig_list_entry has to be
1497 * extracted from
1498 * @orig_node: the originator for which the orig_list_entry has to be found
62fe710f 1499 *
d15cd622 1500 * retrieve the orig_tt_list_entry belonging to orig_node from the
d657e621
AQ
1501 * batadv_tt_global_entry list
1502 *
62fe710f 1503 * Return: it with an increased refcounter, NULL if not found
db08e6e5 1504 */
d657e621
AQ
1505static struct batadv_tt_orig_list_entry *
1506batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1507 const struct batadv_orig_node *orig_node)
db08e6e5 1508{
d657e621 1509 struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
db08e6e5 1510 const struct hlist_head *head;
db08e6e5
SW
1511
1512 rcu_read_lock();
1513 head = &entry->orig_list;
b67bfe0d 1514 hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
d657e621
AQ
1515 if (tmp_orig_entry->orig_node != orig_node)
1516 continue;
6e8ef69d 1517 if (!kref_get_unless_zero(&tmp_orig_entry->refcount))
d657e621
AQ
1518 continue;
1519
1520 orig_entry = tmp_orig_entry;
1521 break;
db08e6e5
SW
1522 }
1523 rcu_read_unlock();
d657e621
AQ
1524
1525 return orig_entry;
1526}
1527
62fe710f 1528/**
7e9a8c2c
SE
1529 * batadv_tt_global_entry_has_orig() - check if a TT global entry is also
1530 * handled by a given originator
d15cd622
AQ
1531 * @entry: the TT global entry to check
1532 * @orig_node: the originator to search in the list
62fe710f
SE
1533 *
1534 * find out if an orig_node is already in the list of a tt_global_entry.
1535 *
1536 * Return: true if found, false otherwise
d657e621
AQ
1537 */
1538static bool
1539batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1540 const struct batadv_orig_node *orig_node)
1541{
1542 struct batadv_tt_orig_list_entry *orig_entry;
1543 bool found = false;
1544
1545 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
1546 if (orig_entry) {
1547 found = true;
7e2366c6 1548 batadv_tt_orig_list_entry_put(orig_entry);
d657e621
AQ
1549 }
1550
db08e6e5
SW
1551 return found;
1552}
1553
54e22f26 1554/**
7e9a8c2c 1555 * batadv_tt_global_sync_flags() - update TT sync flags
54e22f26
LL
1556 * @tt_global: the TT global entry to update sync flags in
1557 *
1558 * Updates the sync flag bits in the tt_global flag attribute with a logical
1559 * OR of all sync flags from any of its TT orig entries.
1560 */
1561static void
1562batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
1563{
1564 struct batadv_tt_orig_list_entry *orig_entry;
1565 const struct hlist_head *head;
1566 u16 flags = BATADV_NO_FLAGS;
1567
1568 rcu_read_lock();
1569 head = &tt_global->orig_list;
1570 hlist_for_each_entry_rcu(orig_entry, head, list)
1571 flags |= orig_entry->flags;
1572 rcu_read_unlock();
1573
1574 flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
1575 tt_global->common.flags = flags;
1576}
1577
1578/**
7e9a8c2c 1579 * batadv_tt_global_orig_entry_add() - add or update a TT orig entry
54e22f26
LL
1580 * @tt_global: the TT global entry to add an orig entry in
1581 * @orig_node: the originator to add an orig entry for
1582 * @ttvn: translation table version number of this changeset
1583 * @flags: TT sync flags
1584 */
a513088d 1585static void
d657e621 1586batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
54e22f26
LL
1587 struct batadv_orig_node *orig_node, int ttvn,
1588 u8 flags)
db08e6e5 1589{
56303d34 1590 struct batadv_tt_orig_list_entry *orig_entry;
db08e6e5 1591
d657e621 1592 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
30cfd02b
AQ
1593 if (orig_entry) {
1594 /* refresh the ttvn: the current value could be a bogus one that
1595 * was added during a "temporary client detection"
1596 */
1597 orig_entry->ttvn = ttvn;
54e22f26
LL
1598 orig_entry->flags = flags;
1599 goto sync_flags;
30cfd02b 1600 }
d657e621 1601
86452f81 1602 orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
db08e6e5 1603 if (!orig_entry)
d657e621 1604 goto out;
db08e6e5
SW
1605
1606 INIT_HLIST_NODE(&orig_entry->list);
7c124391 1607 kref_get(&orig_node->refcount);
7ea7b4a1 1608 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
db08e6e5
SW
1609 orig_entry->orig_node = orig_node;
1610 orig_entry->ttvn = ttvn;
54e22f26 1611 orig_entry->flags = flags;
6e8ef69d 1612 kref_init(&orig_entry->refcount);
db08e6e5 1613
d657e621 1614 spin_lock_bh(&tt_global->list_lock);
23f55485 1615 kref_get(&orig_entry->refcount);
db08e6e5 1616 hlist_add_head_rcu(&orig_entry->list,
d657e621
AQ
1617 &tt_global->orig_list);
1618 spin_unlock_bh(&tt_global->list_lock);
1d8ab8d3
LL
1619 atomic_inc(&tt_global->orig_list_count);
1620
54e22f26
LL
1621sync_flags:
1622 batadv_tt_global_sync_flags(tt_global);
d657e621
AQ
1623out:
1624 if (orig_entry)
7e2366c6 1625 batadv_tt_orig_list_entry_put(orig_entry);
db08e6e5
SW
1626}
1627
d4ff40f6 1628/**
7e9a8c2c 1629 * batadv_tt_global_add() - add a new TT global entry or update an existing one
d4ff40f6
AQ
1630 * @bat_priv: the bat priv with all the soft interface information
1631 * @orig_node: the originator announcing the client
1632 * @tt_addr: the mac address of the non-mesh client
c018ad3d 1633 * @vid: VLAN identifier
d4ff40f6
AQ
1634 * @flags: TT flags that have to be set for this non-mesh client
1635 * @ttvn: the tt version number ever announcing this non-mesh client
1636 *
1637 * Add a new TT global entry for the given originator. If the entry already
1638 * exists add a new reference to the given originator (a global entry can have
1639 * references to multiple originators) and adjust the flags attribute to reflect
1640 * the function argument.
1641 * If a TT local entry exists for this non-mesh client remove it.
1642 *
1643 * The caller must hold orig_node refcount.
1e5d49fc 1644 *
62fe710f 1645 * Return: true if the new entry has been added, false otherwise
d4ff40f6 1646 */
1e5d49fc
AQ
1647static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1648 struct batadv_orig_node *orig_node,
c018ad3d 1649 const unsigned char *tt_addr,
6b5e971a 1650 unsigned short vid, u16 flags, u8 ttvn)
a73105b8 1651{
170173bf
SE
1652 struct batadv_tt_global_entry *tt_global_entry;
1653 struct batadv_tt_local_entry *tt_local_entry;
1e5d49fc 1654 bool ret = false;
80b3f58c 1655 int hash_added;
56303d34 1656 struct batadv_tt_common_entry *common;
6b5e971a 1657 u16 local_flags;
c6c8fea2 1658
cfd4f757
AQ
1659 /* ignore global entries from backbone nodes */
1660 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
1661 return true;
1662
c018ad3d
AQ
1663 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
1664 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
068ee6e2
AQ
1665
1666 /* if the node already has a local client for this entry, it has to wait
1667 * for a roaming advertisement instead of manually messing up the global
1668 * table
1669 */
1670 if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
1671 !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
1672 goto out;
a73105b8
AQ
1673
1674 if (!tt_global_entry) {
86452f81
SE
1675 tt_global_entry = kmem_cache_zalloc(batadv_tg_cache,
1676 GFP_ATOMIC);
a73105b8 1677 if (!tt_global_entry)
7683fdc1
AQ
1678 goto out;
1679
c0a55929 1680 common = &tt_global_entry->common;
8fdd0153 1681 ether_addr_copy(common->addr, tt_addr);
c018ad3d 1682 common->vid = vid;
db08e6e5 1683
d4f44692 1684 common->flags = flags;
cc47f66e 1685 tt_global_entry->roam_at = 0;
fdf79320
AQ
1686 /* node must store current time in case of roaming. This is
1687 * needed to purge this entry out on timeout (if nobody claims
1688 * it)
1689 */
1690 if (flags & BATADV_TT_CLIENT_ROAM)
1691 tt_global_entry->roam_at = jiffies;
92dcdf09 1692 kref_init(&common->refcount);
30cfd02b 1693 common->added_at = jiffies;
db08e6e5
SW
1694
1695 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
1d8ab8d3 1696 atomic_set(&tt_global_entry->orig_list_count, 0);
db08e6e5 1697 spin_lock_init(&tt_global_entry->list_lock);
7683fdc1 1698
15d5ffde 1699 kref_get(&common->refcount);
807736f6 1700 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
a513088d 1701 batadv_compare_tt,
c018ad3d 1702 batadv_choose_tt, common,
a513088d 1703 &common->hash_entry);
80b3f58c
SW
1704
1705 if (unlikely(hash_added != 0)) {
1706 /* remove the reference for the hash */
5dafd8a6 1707 batadv_tt_global_entry_put(tt_global_entry);
80b3f58c
SW
1708 goto out_remove;
1709 }
a73105b8 1710 } else {
068ee6e2 1711 common = &tt_global_entry->common;
30cfd02b
AQ
1712 /* If there is already a global entry, we can use this one for
1713 * our processing.
068ee6e2
AQ
1714 * But if we are trying to add a temporary client then here are
1715 * two options at this point:
1716 * 1) the global client is not a temporary client: the global
1717 * client has to be left as it is, temporary information
1718 * should never override any already known client state
1719 * 2) the global client is a temporary client: purge the
1720 * originator list and add the new one orig_entry
30cfd02b 1721 */
068ee6e2
AQ
1722 if (flags & BATADV_TT_CLIENT_TEMP) {
1723 if (!(common->flags & BATADV_TT_CLIENT_TEMP))
1724 goto out;
1725 if (batadv_tt_global_entry_has_orig(tt_global_entry,
1726 orig_node))
1727 goto out_remove;
1728 batadv_tt_global_del_orig_list(tt_global_entry);
1729 goto add_orig_entry;
1730 }
30cfd02b
AQ
1731
1732 /* if the client was temporary added before receiving the first
a6cb3909
SW
1733 * OGM announcing it, we have to clear the TEMP flag. Also,
1734 * remove the previous temporary orig node and re-add it
1735 * if required. If the orig entry changed, the new one which
1736 * is a non-temporary entry is preferred.
30cfd02b 1737 */
a6cb3909
SW
1738 if (common->flags & BATADV_TT_CLIENT_TEMP) {
1739 batadv_tt_global_del_orig_list(tt_global_entry);
1740 common->flags &= ~BATADV_TT_CLIENT_TEMP;
1741 }
db08e6e5 1742
e9c00136 1743 /* the change can carry possible "attribute" flags like the
54e22f26 1744 * TT_CLIENT_TEMP, therefore they have to be copied in the
e9c00136
AQ
1745 * client entry
1746 */
54e22f26 1747 common->flags |= flags & (~BATADV_TT_SYNC_MASK);
e9c00136 1748
acd34afa
SE
1749 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
1750 * one originator left in the list and we previously received a
db08e6e5
SW
1751 * delete + roaming change for this originator.
1752 *
1753 * We should first delete the old originator before adding the
1754 * new one.
1755 */
068ee6e2 1756 if (common->flags & BATADV_TT_CLIENT_ROAM) {
a513088d 1757 batadv_tt_global_del_orig_list(tt_global_entry);
068ee6e2 1758 common->flags &= ~BATADV_TT_CLIENT_ROAM;
db08e6e5 1759 tt_global_entry->roam_at = 0;
a73105b8
AQ
1760 }
1761 }
068ee6e2 1762add_orig_entry:
30cfd02b 1763 /* add the new orig_entry (if needed) or update it */
54e22f26
LL
1764 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
1765 flags & BATADV_TT_SYNC_MASK);
c6c8fea2 1766
39c75a51 1767 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 1768 "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
f7a2bd65 1769 common->addr, batadv_print_vid(common->vid),
16052789 1770 orig_node->orig);
1e5d49fc 1771 ret = true;
c6c8fea2 1772
80b3f58c 1773out_remove:
c5caf4ef
LL
1774 /* Do not remove multicast addresses from the local hash on
1775 * global additions
1776 */
1777 if (is_multicast_ether_addr(tt_addr))
1778 goto out;
7f91d06c 1779
a73105b8 1780 /* remove address from local hash if present */
c018ad3d 1781 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
7f91d06c 1782 "global tt received",
c1d07431 1783 flags & BATADV_TT_CLIENT_ROAM);
7f91d06c
AQ
1784 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
1785
068ee6e2
AQ
1786 if (!(flags & BATADV_TT_CLIENT_ROAM))
1787 /* this is a normal global add. Therefore the client is not in a
1788 * roaming state anymore.
1789 */
1790 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
1791
7683fdc1
AQ
1792out:
1793 if (tt_global_entry)
5dafd8a6 1794 batadv_tt_global_entry_put(tt_global_entry);
068ee6e2 1795 if (tt_local_entry)
95c0db90 1796 batadv_tt_local_entry_put(tt_local_entry);
7683fdc1 1797 return ret;
c6c8fea2
SE
1798}
1799
1b371d13 1800/**
7e9a8c2c 1801 * batadv_transtable_best_orig() - Get best originator list entry from tt entry
4627456a 1802 * @bat_priv: the bat priv with all the soft interface information
981d8900
SE
1803 * @tt_global_entry: global translation table entry to be analyzed
1804 *
1805 * This functon assumes the caller holds rcu_read_lock().
62fe710f 1806 * Return: best originator list entry or NULL on errors.
981d8900
SE
1807 */
1808static struct batadv_tt_orig_list_entry *
4627456a
AQ
1809batadv_transtable_best_orig(struct batadv_priv *bat_priv,
1810 struct batadv_tt_global_entry *tt_global_entry)
981d8900 1811{
4627456a 1812 struct batadv_neigh_node *router, *best_router = NULL;
29824a55 1813 struct batadv_algo_ops *bao = bat_priv->algo_ops;
981d8900 1814 struct hlist_head *head;
981d8900 1815 struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
981d8900
SE
1816
1817 head = &tt_global_entry->orig_list;
b67bfe0d 1818 hlist_for_each_entry_rcu(orig_entry, head, list) {
7351a482
SW
1819 router = batadv_orig_router_get(orig_entry->orig_node,
1820 BATADV_IF_DEFAULT);
981d8900
SE
1821 if (!router)
1822 continue;
1823
4627456a 1824 if (best_router &&
29824a55
AQ
1825 bao->neigh.cmp(router, BATADV_IF_DEFAULT, best_router,
1826 BATADV_IF_DEFAULT) <= 0) {
25bb2509 1827 batadv_neigh_node_put(router);
4627456a 1828 continue;
981d8900
SE
1829 }
1830
4627456a
AQ
1831 /* release the refcount for the "old" best */
1832 if (best_router)
25bb2509 1833 batadv_neigh_node_put(best_router);
4627456a
AQ
1834
1835 best_entry = orig_entry;
1836 best_router = router;
981d8900
SE
1837 }
1838
4627456a 1839 if (best_router)
25bb2509 1840 batadv_neigh_node_put(best_router);
4627456a 1841
981d8900
SE
1842 return best_entry;
1843}
1844
dc1cbd14 1845#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1b371d13 1846/**
7e9a8c2c
SE
1847 * batadv_tt_global_print_entry() - print all orig nodes who announce the
1848 * address for this global entry
4627456a 1849 * @bat_priv: the bat priv with all the soft interface information
981d8900
SE
1850 * @tt_global_entry: global translation table entry to be printed
1851 * @seq: debugfs table seq_file struct
1852 *
1853 * This functon assumes the caller holds rcu_read_lock().
db08e6e5 1854 */
a513088d 1855static void
4627456a
AQ
1856batadv_tt_global_print_entry(struct batadv_priv *bat_priv,
1857 struct batadv_tt_global_entry *tt_global_entry,
a513088d 1858 struct seq_file *seq)
db08e6e5 1859{
981d8900 1860 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
56303d34 1861 struct batadv_tt_common_entry *tt_common_entry;
7ea7b4a1
AQ
1862 struct batadv_orig_node_vlan *vlan;
1863 struct hlist_head *head;
6b5e971a
SE
1864 u8 last_ttvn;
1865 u16 flags;
db08e6e5
SW
1866
1867 tt_common_entry = &tt_global_entry->common;
981d8900
SE
1868 flags = tt_common_entry->flags;
1869
4627456a 1870 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
981d8900 1871 if (best_entry) {
7ea7b4a1
AQ
1872 vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
1873 tt_common_entry->vid);
1874 if (!vlan) {
1875 seq_printf(seq,
1876 " * Cannot retrieve VLAN %d for originator %pM\n",
f7a2bd65 1877 batadv_print_vid(tt_common_entry->vid),
7ea7b4a1
AQ
1878 best_entry->orig_node->orig);
1879 goto print_list;
1880 }
1881
981d8900 1882 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
f9d8a537 1883 seq_printf(seq,
dd24ddb2 1884 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
981d8900 1885 '*', tt_global_entry->common.addr,
f7a2bd65 1886 batadv_print_vid(tt_global_entry->common.vid),
981d8900 1887 best_entry->ttvn, best_entry->orig_node->orig,
7ea7b4a1 1888 last_ttvn, vlan->tt.crc,
a2f2b6cd
SE
1889 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1890 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1891 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1892 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
7ea7b4a1 1893
21754e25 1894 batadv_orig_node_vlan_put(vlan);
981d8900 1895 }
db08e6e5 1896
7ea7b4a1 1897print_list:
db08e6e5
SW
1898 head = &tt_global_entry->orig_list;
1899
b67bfe0d 1900 hlist_for_each_entry_rcu(orig_entry, head, list) {
981d8900
SE
1901 if (best_entry == orig_entry)
1902 continue;
1903
7ea7b4a1
AQ
1904 vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
1905 tt_common_entry->vid);
1906 if (!vlan) {
1907 seq_printf(seq,
1908 " + Cannot retrieve VLAN %d for originator %pM\n",
f7a2bd65 1909 batadv_print_vid(tt_common_entry->vid),
7ea7b4a1
AQ
1910 orig_entry->orig_node->orig);
1911 continue;
1912 }
1913
db08e6e5 1914 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
16052789 1915 seq_printf(seq,
dd24ddb2 1916 " %c %pM %4d (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
981d8900 1917 '+', tt_global_entry->common.addr,
f7a2bd65 1918 batadv_print_vid(tt_global_entry->common.vid),
981d8900 1919 orig_entry->ttvn, orig_entry->orig_node->orig,
7ea7b4a1 1920 last_ttvn, vlan->tt.crc,
a2f2b6cd
SE
1921 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1922 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1923 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1924 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
7ea7b4a1 1925
21754e25 1926 batadv_orig_node_vlan_put(vlan);
db08e6e5
SW
1927 }
1928}
1929
08c36d3e 1930int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea2
SE
1931{
1932 struct net_device *net_dev = (struct net_device *)seq->private;
56303d34 1933 struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6 1934 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
56303d34
SE
1935 struct batadv_tt_common_entry *tt_common_entry;
1936 struct batadv_tt_global_entry *tt_global;
1937 struct batadv_hard_iface *primary_if;
c6c8fea2 1938 struct hlist_head *head;
6b5e971a 1939 u32 i;
c6c8fea2 1940
30da63a6
ML
1941 primary_if = batadv_seq_print_text_primary_if_get(seq);
1942 if (!primary_if)
32ae9b22 1943 goto out;
c6c8fea2 1944
2dafb49d
AQ
1945 seq_printf(seq,
1946 "Globally announced TT entries received via the mesh %s\n",
c6c8fea2 1947 net_dev->name);
925a6f37
AQ
1948 seq_puts(seq,
1949 " Client VID (TTVN) Originator (Curr TTVN) (CRC ) Flags\n");
c6c8fea2 1950
c6c8fea2
SE
1951 for (i = 0; i < hash->size; i++) {
1952 head = &hash->table[i];
1953
7aadf889 1954 rcu_read_lock();
b67bfe0d 1955 hlist_for_each_entry_rcu(tt_common_entry,
7aadf889 1956 head, hash_entry) {
56303d34
SE
1957 tt_global = container_of(tt_common_entry,
1958 struct batadv_tt_global_entry,
1959 common);
4627456a 1960 batadv_tt_global_print_entry(bat_priv, tt_global, seq);
c6c8fea2 1961 }
7aadf889 1962 rcu_read_unlock();
c6c8fea2 1963 }
32ae9b22
ML
1964out:
1965 if (primary_if)
82047ad7 1966 batadv_hardif_put(primary_if);
30da63a6 1967 return 0;
c6c8fea2 1968}
dc1cbd14 1969#endif
c6c8fea2 1970
d34f0550 1971/**
7e9a8c2c 1972 * batadv_tt_global_dump_subentry() - Dump all TT local entries into a message
d34f0550
MS
1973 * @msg: Netlink message to dump into
1974 * @portid: Port making netlink request
1975 * @seq: Sequence number of netlink message
1976 * @common: tt local & tt global common data
1977 * @orig: Originator node announcing a non-mesh client
1978 * @best: Is the best originator for the TT entry
1979 *
1980 * Return: Error code, or 0 on success
1981 */
1982static int
1983batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
1984 struct batadv_tt_common_entry *common,
1985 struct batadv_tt_orig_list_entry *orig,
1986 bool best)
1987{
54e22f26 1988 u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
d34f0550
MS
1989 void *hdr;
1990 struct batadv_orig_node_vlan *vlan;
1991 u8 last_ttvn;
1992 u32 crc;
1993
1994 vlan = batadv_orig_node_vlan_get(orig->orig_node,
1995 common->vid);
1996 if (!vlan)
1997 return 0;
1998
1999 crc = vlan->tt.crc;
2000
2001 batadv_orig_node_vlan_put(vlan);
2002
2003 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
2004 NLM_F_MULTI,
2005 BATADV_CMD_GET_TRANSTABLE_GLOBAL);
2006 if (!hdr)
2007 return -ENOBUFS;
2008
2009 last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
2010
2011 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
2012 nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
2013 orig->orig_node->orig) ||
2014 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
2015 nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
2016 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
2017 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
54e22f26 2018 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
d34f0550
MS
2019 goto nla_put_failure;
2020
2021 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
2022 goto nla_put_failure;
2023
2024 genlmsg_end(msg, hdr);
2025 return 0;
2026
2027 nla_put_failure:
2028 genlmsg_cancel(msg, hdr);
2029 return -EMSGSIZE;
2030}
2031
2032/**
7e9a8c2c 2033 * batadv_tt_global_dump_entry() - Dump one TT global entry into a message
d34f0550
MS
2034 * @msg: Netlink message to dump into
2035 * @portid: Port making netlink request
2036 * @seq: Sequence number of netlink message
2037 * @bat_priv: The bat priv with all the soft interface information
2038 * @common: tt local & tt global common data
2039 * @sub_s: Number of entries to skip
2040 *
2041 * This function assumes the caller holds rcu_read_lock().
2042 *
2043 * Return: Error code, or 0 on success
2044 */
2045static int
2046batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2047 struct batadv_priv *bat_priv,
2048 struct batadv_tt_common_entry *common, int *sub_s)
2049{
2050 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
2051 struct batadv_tt_global_entry *global;
2052 struct hlist_head *head;
2053 int sub = 0;
2054 bool best;
2055
2056 global = container_of(common, struct batadv_tt_global_entry, common);
2057 best_entry = batadv_transtable_best_orig(bat_priv, global);
2058 head = &global->orig_list;
2059
2060 hlist_for_each_entry_rcu(orig_entry, head, list) {
2061 if (sub++ < *sub_s)
2062 continue;
2063
2064 best = (orig_entry == best_entry);
2065
2066 if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
2067 orig_entry, best)) {
2068 *sub_s = sub - 1;
2069 return -EMSGSIZE;
2070 }
2071 }
2072
2073 *sub_s = 0;
2074 return 0;
2075}
2076
2077/**
7e9a8c2c 2078 * batadv_tt_global_dump_bucket() - Dump one TT local bucket into a message
d34f0550
MS
2079 * @msg: Netlink message to dump into
2080 * @portid: Port making netlink request
2081 * @seq: Sequence number of netlink message
2082 * @bat_priv: The bat priv with all the soft interface information
2083 * @head: Pointer to the list containing the global tt entries
2084 * @idx_s: Number of entries to skip
2085 * @sub: Number of entries to skip
2086 *
2087 * Return: Error code, or 0 on success
2088 */
2089static int
2090batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
2091 struct batadv_priv *bat_priv,
2092 struct hlist_head *head, int *idx_s, int *sub)
2093{
2094 struct batadv_tt_common_entry *common;
2095 int idx = 0;
2096
2097 rcu_read_lock();
2098 hlist_for_each_entry_rcu(common, head, hash_entry) {
2099 if (idx++ < *idx_s)
2100 continue;
2101
2102 if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
2103 common, sub)) {
2104 rcu_read_unlock();
2105 *idx_s = idx - 1;
2106 return -EMSGSIZE;
2107 }
2108 }
2109 rcu_read_unlock();
2110
2111 *idx_s = 0;
2112 *sub = 0;
2113 return 0;
2114}
2115
2116/**
7e9a8c2c 2117 * batadv_tt_global_dump() - Dump TT global entries into a message
d34f0550
MS
2118 * @msg: Netlink message to dump into
2119 * @cb: Parameters from query
2120 *
2121 * Return: Error code, or length of message on success
2122 */
2123int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
2124{
2125 struct net *net = sock_net(cb->skb->sk);
2126 struct net_device *soft_iface;
2127 struct batadv_priv *bat_priv;
2128 struct batadv_hard_iface *primary_if = NULL;
2129 struct batadv_hashtable *hash;
2130 struct hlist_head *head;
2131 int ret;
2132 int ifindex;
2133 int bucket = cb->args[0];
2134 int idx = cb->args[1];
2135 int sub = cb->args[2];
2136 int portid = NETLINK_CB(cb->skb).portid;
2137
2138 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
2139 if (!ifindex)
2140 return -EINVAL;
2141
2142 soft_iface = dev_get_by_index(net, ifindex);
2143 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2144 ret = -ENODEV;
2145 goto out;
2146 }
2147
2148 bat_priv = netdev_priv(soft_iface);
2149
2150 primary_if = batadv_primary_if_get_selected(bat_priv);
2151 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2152 ret = -ENOENT;
2153 goto out;
2154 }
2155
2156 hash = bat_priv->tt.global_hash;
2157
2158 while (bucket < hash->size) {
2159 head = &hash->table[bucket];
2160
2161 if (batadv_tt_global_dump_bucket(msg, portid,
2162 cb->nlh->nlmsg_seq, bat_priv,
2163 head, &idx, &sub))
2164 break;
2165
2166 bucket++;
2167 }
2168
2169 ret = msg->len;
2170
2171 out:
2172 if (primary_if)
2173 batadv_hardif_put(primary_if);
2174 if (soft_iface)
2175 dev_put(soft_iface);
2176
2177 cb->args[0] = bucket;
2178 cb->args[1] = idx;
2179 cb->args[2] = sub;
2180
2181 return ret;
2182}
2183
1d8ab8d3 2184/**
7e9a8c2c 2185 * _batadv_tt_global_del_orig_entry() - remove and free an orig_entry
1d8ab8d3
LL
2186 * @tt_global_entry: the global entry to remove the orig_entry from
2187 * @orig_entry: the orig entry to remove and free
2188 *
2189 * Remove an orig_entry from its list in the given tt_global_entry and
2190 * free this orig_entry afterwards.
433ff98f
ML
2191 *
2192 * Caller must hold tt_global_entry->list_lock and ensure orig_entry->list is
2193 * part of a list.
1d8ab8d3
LL
2194 */
2195static void
433ff98f
ML
2196_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
2197 struct batadv_tt_orig_list_entry *orig_entry)
1d8ab8d3 2198{
2c72d655
SE
2199 lockdep_assert_held(&tt_global_entry->list_lock);
2200
1d8ab8d3
LL
2201 batadv_tt_global_size_dec(orig_entry->orig_node,
2202 tt_global_entry->common.vid);
2203 atomic_dec(&tt_global_entry->orig_list_count);
433ff98f
ML
2204 /* requires holding tt_global_entry->list_lock and orig_entry->list
2205 * being part of a list
2206 */
1d8ab8d3 2207 hlist_del_rcu(&orig_entry->list);
7e2366c6 2208 batadv_tt_orig_list_entry_put(orig_entry);
1d8ab8d3
LL
2209}
2210
db08e6e5 2211/* deletes the orig list of a tt_global_entry */
a513088d 2212static void
56303d34 2213batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
c6c8fea2 2214{
db08e6e5 2215 struct hlist_head *head;
b67bfe0d 2216 struct hlist_node *safe;
56303d34 2217 struct batadv_tt_orig_list_entry *orig_entry;
a73105b8 2218
db08e6e5
SW
2219 spin_lock_bh(&tt_global_entry->list_lock);
2220 head = &tt_global_entry->orig_list;
1d8ab8d3 2221 hlist_for_each_entry_safe(orig_entry, safe, head, list)
433ff98f 2222 _batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
db08e6e5 2223 spin_unlock_bh(&tt_global_entry->list_lock);
db08e6e5
SW
2224}
2225
1d8ab8d3 2226/**
7e9a8c2c 2227 * batadv_tt_global_del_orig_node() - remove orig_node from a global tt entry
1d8ab8d3
LL
2228 * @bat_priv: the bat priv with all the soft interface information
2229 * @tt_global_entry: the global entry to remove the orig_node from
2230 * @orig_node: the originator announcing the client
2231 * @message: message to append to the log on deletion
2232 *
2233 * Remove the given orig_node and its according orig_entry from the given
2234 * global tt entry.
2235 */
a513088d 2236static void
1d8ab8d3
LL
2237batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
2238 struct batadv_tt_global_entry *tt_global_entry,
2239 struct batadv_orig_node *orig_node,
2240 const char *message)
db08e6e5
SW
2241{
2242 struct hlist_head *head;
b67bfe0d 2243 struct hlist_node *safe;
56303d34 2244 struct batadv_tt_orig_list_entry *orig_entry;
16052789 2245 unsigned short vid;
db08e6e5
SW
2246
2247 spin_lock_bh(&tt_global_entry->list_lock);
2248 head = &tt_global_entry->orig_list;
b67bfe0d 2249 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
db08e6e5 2250 if (orig_entry->orig_node == orig_node) {
16052789 2251 vid = tt_global_entry->common.vid;
39c75a51 2252 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 2253 "Deleting %pM from global tt entry %pM (vid: %d): %s\n",
1eda58bf 2254 orig_node->orig,
16052789 2255 tt_global_entry->common.addr,
f7a2bd65 2256 batadv_print_vid(vid), message);
433ff98f
ML
2257 _batadv_tt_global_del_orig_entry(tt_global_entry,
2258 orig_entry);
db08e6e5
SW
2259 }
2260 }
2261 spin_unlock_bh(&tt_global_entry->list_lock);
2262}
2263
db08e6e5 2264/* If the client is to be deleted, we check if it is the last origantor entry
acd34afa
SE
2265 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
2266 * timer, otherwise we simply remove the originator scheduled for deletion.
db08e6e5 2267 */
a513088d 2268static void
56303d34
SE
2269batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
2270 struct batadv_tt_global_entry *tt_global_entry,
2271 struct batadv_orig_node *orig_node,
2272 const char *message)
db08e6e5
SW
2273{
2274 bool last_entry = true;
2275 struct hlist_head *head;
56303d34 2276 struct batadv_tt_orig_list_entry *orig_entry;
db08e6e5
SW
2277
2278 /* no local entry exists, case 1:
2279 * Check if this is the last one or if other entries exist.
2280 */
2281
2282 rcu_read_lock();
2283 head = &tt_global_entry->orig_list;
b67bfe0d 2284 hlist_for_each_entry_rcu(orig_entry, head, list) {
db08e6e5
SW
2285 if (orig_entry->orig_node != orig_node) {
2286 last_entry = false;
2287 break;
2288 }
2289 }
2290 rcu_read_unlock();
2291
2292 if (last_entry) {
2293 /* its the last one, mark for roaming. */
acd34afa 2294 tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
db08e6e5 2295 tt_global_entry->roam_at = jiffies;
1fda4c0a 2296 } else {
db08e6e5
SW
2297 /* there is another entry, we can simply delete this
2298 * one and can still use the other one.
2299 */
1d8ab8d3
LL
2300 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2301 orig_node, message);
1fda4c0a 2302 }
db08e6e5
SW
2303}
2304
c018ad3d 2305/**
7e9a8c2c 2306 * batadv_tt_global_del() - remove a client from the global table
c018ad3d
AQ
2307 * @bat_priv: the bat priv with all the soft interface information
2308 * @orig_node: an originator serving this client
2309 * @addr: the mac address of the client
2310 * @vid: VLAN identifier
2311 * @message: a message explaining the reason for deleting the client to print
2312 * for debugging purpose
2313 * @roaming: true if the deletion has been triggered by a roaming event
2314 */
56303d34
SE
2315static void batadv_tt_global_del(struct batadv_priv *bat_priv,
2316 struct batadv_orig_node *orig_node,
c018ad3d 2317 const unsigned char *addr, unsigned short vid,
a513088d 2318 const char *message, bool roaming)
a73105b8 2319{
170173bf 2320 struct batadv_tt_global_entry *tt_global_entry;
56303d34 2321 struct batadv_tt_local_entry *local_entry = NULL;
a73105b8 2322
c018ad3d 2323 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
db08e6e5 2324 if (!tt_global_entry)
7683fdc1 2325 goto out;
a73105b8 2326
db08e6e5 2327 if (!roaming) {
1d8ab8d3
LL
2328 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2329 orig_node, message);
db08e6e5
SW
2330
2331 if (hlist_empty(&tt_global_entry->orig_list))
be73b488
AQ
2332 batadv_tt_global_free(bat_priv, tt_global_entry,
2333 message);
db08e6e5
SW
2334
2335 goto out;
2336 }
92f90f56
SE
2337
2338 /* if we are deleting a global entry due to a roam
2339 * event, there are two possibilities:
db08e6e5
SW
2340 * 1) the client roamed from node A to node B => if there
2341 * is only one originator left for this client, we mark
acd34afa 2342 * it with BATADV_TT_CLIENT_ROAM, we start a timer and we
92f90f56
SE
2343 * wait for node B to claim it. In case of timeout
2344 * the entry is purged.
db08e6e5
SW
2345 *
2346 * If there are other originators left, we directly delete
2347 * the originator.
92f90f56 2348 * 2) the client roamed to us => we can directly delete
9cfc7bd6
SE
2349 * the global entry, since it is useless now.
2350 */
a513088d 2351 local_entry = batadv_tt_local_hash_find(bat_priv,
c018ad3d
AQ
2352 tt_global_entry->common.addr,
2353 vid);
a513088d 2354 if (local_entry) {
db08e6e5 2355 /* local entry exists, case 2: client roamed to us. */
a513088d 2356 batadv_tt_global_del_orig_list(tt_global_entry);
be73b488 2357 batadv_tt_global_free(bat_priv, tt_global_entry, message);
1fda4c0a 2358 } else {
db08e6e5 2359 /* no local entry exists, case 1: check for roaming */
a513088d
SE
2360 batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
2361 orig_node, message);
1fda4c0a 2362 }
92f90f56 2363
cc47f66e 2364out:
7683fdc1 2365 if (tt_global_entry)
5dafd8a6 2366 batadv_tt_global_entry_put(tt_global_entry);
a513088d 2367 if (local_entry)
95c0db90 2368 batadv_tt_local_entry_put(local_entry);
a73105b8
AQ
2369}
2370
95fb130d 2371/**
7e9a8c2c
SE
2372 * batadv_tt_global_del_orig() - remove all the TT global entries belonging to
2373 * the given originator matching the provided vid
95fb130d
AQ
2374 * @bat_priv: the bat priv with all the soft interface information
2375 * @orig_node: the originator owning the entries to remove
2376 * @match_vid: the VLAN identifier to match. If negative all the entries will be
2377 * removed
2378 * @message: debug message to print as "reason"
2379 */
56303d34
SE
2380void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
2381 struct batadv_orig_node *orig_node,
6b5e971a 2382 s32 match_vid,
56303d34 2383 const char *message)
c6c8fea2 2384{
56303d34
SE
2385 struct batadv_tt_global_entry *tt_global;
2386 struct batadv_tt_common_entry *tt_common_entry;
6b5e971a 2387 u32 i;
807736f6 2388 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
b67bfe0d 2389 struct hlist_node *safe;
a73105b8 2390 struct hlist_head *head;
7683fdc1 2391 spinlock_t *list_lock; /* protects write access to the hash lists */
16052789 2392 unsigned short vid;
c6c8fea2 2393
6e801494
SW
2394 if (!hash)
2395 return;
2396
a73105b8
AQ
2397 for (i = 0; i < hash->size; i++) {
2398 head = &hash->table[i];
7683fdc1 2399 list_lock = &hash->list_locks[i];
c6c8fea2 2400
7683fdc1 2401 spin_lock_bh(list_lock);
b67bfe0d 2402 hlist_for_each_entry_safe(tt_common_entry, safe,
7c64fd98 2403 head, hash_entry) {
95fb130d
AQ
2404 /* remove only matching entries */
2405 if (match_vid >= 0 && tt_common_entry->vid != match_vid)
2406 continue;
2407
56303d34
SE
2408 tt_global = container_of(tt_common_entry,
2409 struct batadv_tt_global_entry,
2410 common);
db08e6e5 2411
1d8ab8d3
LL
2412 batadv_tt_global_del_orig_node(bat_priv, tt_global,
2413 orig_node, message);
db08e6e5 2414
56303d34 2415 if (hlist_empty(&tt_global->orig_list)) {
16052789 2416 vid = tt_global->common.vid;
39c75a51 2417 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
2418 "Deleting global tt entry %pM (vid: %d): %s\n",
2419 tt_global->common.addr,
f7a2bd65 2420 batadv_print_vid(vid), message);
b67bfe0d 2421 hlist_del_rcu(&tt_common_entry->hash_entry);
5dafd8a6 2422 batadv_tt_global_entry_put(tt_global);
7683fdc1 2423 }
a73105b8 2424 }
7683fdc1 2425 spin_unlock_bh(list_lock);
c6c8fea2 2426 }
ac4eebd4 2427 clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
c6c8fea2
SE
2428}
2429
30cfd02b
AQ
2430static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
2431 char **msg)
cc47f66e 2432{
30cfd02b
AQ
2433 bool purge = false;
2434 unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
2435 unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
42d0b044 2436
30cfd02b
AQ
2437 if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
2438 batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
2439 purge = true;
2440 *msg = "Roaming timeout\n";
2441 }
42d0b044 2442
30cfd02b
AQ
2443 if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
2444 batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
2445 purge = true;
2446 *msg = "Temporary client timeout\n";
42d0b044 2447 }
30cfd02b
AQ
2448
2449 return purge;
42d0b044
SE
2450}
2451
30cfd02b 2452static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
42d0b044 2453{
807736f6 2454 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
cc47f66e 2455 struct hlist_head *head;
b67bfe0d 2456 struct hlist_node *node_tmp;
7683fdc1 2457 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 2458 u32 i;
30cfd02b
AQ
2459 char *msg = NULL;
2460 struct batadv_tt_common_entry *tt_common;
2461 struct batadv_tt_global_entry *tt_global;
cc47f66e 2462
cc47f66e
AQ
2463 for (i = 0; i < hash->size; i++) {
2464 head = &hash->table[i];
7683fdc1 2465 list_lock = &hash->list_locks[i];
cc47f66e 2466
7683fdc1 2467 spin_lock_bh(list_lock);
b67bfe0d 2468 hlist_for_each_entry_safe(tt_common, node_tmp, head,
30cfd02b
AQ
2469 hash_entry) {
2470 tt_global = container_of(tt_common,
2471 struct batadv_tt_global_entry,
2472 common);
2473
2474 if (!batadv_tt_global_to_purge(tt_global, &msg))
2475 continue;
2476
2477 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
2478 "Deleting global tt entry %pM (vid: %d): %s\n",
2479 tt_global->common.addr,
f7a2bd65 2480 batadv_print_vid(tt_global->common.vid),
16052789 2481 msg);
30cfd02b 2482
b67bfe0d 2483 hlist_del_rcu(&tt_common->hash_entry);
30cfd02b 2484
5dafd8a6 2485 batadv_tt_global_entry_put(tt_global);
30cfd02b 2486 }
7683fdc1 2487 spin_unlock_bh(list_lock);
cc47f66e 2488 }
cc47f66e
AQ
2489}
2490
56303d34 2491static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
c6c8fea2 2492{
5bf74e9c 2493 struct batadv_hashtable *hash;
7683fdc1 2494 spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34
SE
2495 struct batadv_tt_common_entry *tt_common_entry;
2496 struct batadv_tt_global_entry *tt_global;
b67bfe0d 2497 struct hlist_node *node_tmp;
7683fdc1 2498 struct hlist_head *head;
6b5e971a 2499 u32 i;
7683fdc1 2500
807736f6 2501 if (!bat_priv->tt.global_hash)
c6c8fea2
SE
2502 return;
2503
807736f6 2504 hash = bat_priv->tt.global_hash;
7683fdc1
AQ
2505
2506 for (i = 0; i < hash->size; i++) {
2507 head = &hash->table[i];
2508 list_lock = &hash->list_locks[i];
2509
2510 spin_lock_bh(list_lock);
b67bfe0d 2511 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
7683fdc1 2512 head, hash_entry) {
b67bfe0d 2513 hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34
SE
2514 tt_global = container_of(tt_common_entry,
2515 struct batadv_tt_global_entry,
2516 common);
5dafd8a6 2517 batadv_tt_global_entry_put(tt_global);
7683fdc1
AQ
2518 }
2519 spin_unlock_bh(list_lock);
2520 }
2521
1a8eaf07 2522 batadv_hash_destroy(hash);
7683fdc1 2523
807736f6 2524 bat_priv->tt.global_hash = NULL;
c6c8fea2
SE
2525}
2526
56303d34
SE
2527static bool
2528_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
2529 struct batadv_tt_global_entry *tt_global_entry)
59b699cd 2530{
acd34afa
SE
2531 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
2532 tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
75ae84a4 2533 return true;
59b699cd 2534
2d2fcc2a
AQ
2535 /* check if the two clients are marked as isolated */
2536 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
2537 tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
75ae84a4 2538 return true;
2d2fcc2a 2539
75ae84a4 2540 return false;
59b699cd
AQ
2541}
2542
c018ad3d 2543/**
7e9a8c2c 2544 * batadv_transtable_search() - get the mesh destination for a given client
c018ad3d
AQ
2545 * @bat_priv: the bat priv with all the soft interface information
2546 * @src: mac address of the source client
2547 * @addr: mac address of the destination client
2548 * @vid: VLAN identifier
2549 *
62fe710f 2550 * Return: a pointer to the originator that was selected as destination in the
c018ad3d
AQ
2551 * mesh for contacting the client 'addr', NULL otherwise.
2552 * In case of multiple originators serving the same client, the function returns
2553 * the best one (best in terms of metric towards the destination node).
2554 *
2555 * If the two clients are AP isolated the function returns NULL.
2556 */
56303d34 2557struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
6b5e971a
SE
2558 const u8 *src,
2559 const u8 *addr,
c018ad3d 2560 unsigned short vid)
c6c8fea2 2561{
56303d34
SE
2562 struct batadv_tt_local_entry *tt_local_entry = NULL;
2563 struct batadv_tt_global_entry *tt_global_entry = NULL;
2564 struct batadv_orig_node *orig_node = NULL;
981d8900 2565 struct batadv_tt_orig_list_entry *best_entry;
b8cbd81d 2566
eceb22ae 2567 if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
c018ad3d 2568 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
068ee6e2
AQ
2569 if (!tt_local_entry ||
2570 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
3d393e47
AQ
2571 goto out;
2572 }
7aadf889 2573
c018ad3d 2574 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2dafb49d 2575 if (!tt_global_entry)
7b36e8ee 2576 goto out;
7aadf889 2577
3d393e47 2578 /* check whether the clients should not communicate due to AP
9cfc7bd6
SE
2579 * isolation
2580 */
a513088d
SE
2581 if (tt_local_entry &&
2582 _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3d393e47
AQ
2583 goto out;
2584
db08e6e5 2585 rcu_read_lock();
4627456a 2586 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
db08e6e5 2587 /* found anything? */
981d8900
SE
2588 if (best_entry)
2589 orig_node = best_entry->orig_node;
7c124391 2590 if (orig_node && !kref_get_unless_zero(&orig_node->refcount))
db08e6e5
SW
2591 orig_node = NULL;
2592 rcu_read_unlock();
981d8900 2593
7b36e8ee 2594out:
3d393e47 2595 if (tt_global_entry)
5dafd8a6 2596 batadv_tt_global_entry_put(tt_global_entry);
3d393e47 2597 if (tt_local_entry)
95c0db90 2598 batadv_tt_local_entry_put(tt_local_entry);
3d393e47 2599
7b36e8ee 2600 return orig_node;
c6c8fea2 2601}
a73105b8 2602
ced72933 2603/**
7e9a8c2c 2604 * batadv_tt_global_crc() - calculates the checksum of the local table belonging
ced72933
AQ
2605 * to the given orig_node
2606 * @bat_priv: the bat priv with all the soft interface information
0ffa9e8d 2607 * @orig_node: originator for which the CRC should be computed
7ea7b4a1 2608 * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d
AQ
2609 *
2610 * This function computes the checksum for the global table corresponding to a
2611 * specific originator. In particular, the checksum is computed as follows: For
2612 * each client connected to the originator the CRC32C of the MAC address and the
2613 * VID is computed and then all the CRC32Cs of the various clients are xor'ed
2614 * together.
2615 *
2616 * The idea behind is that CRC32C should be used as much as possible in order to
2617 * produce a unique hash of the table, but since the order which is used to feed
2618 * the CRC32C function affects the result and since every node in the network
2619 * probably sorts the clients differently, the hash function cannot be directly
2620 * computed over the entire table. Hence the CRC32C is used only on
2621 * the single client entry, while all the results are then xor'ed together
2622 * because the XOR operation can combine them all while trying to reduce the
2623 * noise as much as possible.
2624 *
62fe710f 2625 * Return: the checksum of the global table of a given originator.
ced72933 2626 */
6b5e971a
SE
2627static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
2628 struct batadv_orig_node *orig_node,
2629 unsigned short vid)
a73105b8 2630{
807736f6 2631 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
54e22f26 2632 struct batadv_tt_orig_list_entry *tt_orig;
56303d34
SE
2633 struct batadv_tt_common_entry *tt_common;
2634 struct batadv_tt_global_entry *tt_global;
a73105b8 2635 struct hlist_head *head;
6b5e971a
SE
2636 u32 i, crc_tmp, crc = 0;
2637 u8 flags;
a30e22ca 2638 __be16 tmp_vid;
a73105b8
AQ
2639
2640 for (i = 0; i < hash->size; i++) {
2641 head = &hash->table[i];
2642
2643 rcu_read_lock();
b67bfe0d 2644 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
56303d34
SE
2645 tt_global = container_of(tt_common,
2646 struct batadv_tt_global_entry,
2647 common);
7ea7b4a1
AQ
2648 /* compute the CRC only for entries belonging to the
2649 * VLAN identified by the vid passed as parameter
2650 */
2651 if (tt_common->vid != vid)
2652 continue;
2653
db08e6e5
SW
2654 /* Roaming clients are in the global table for
2655 * consistency only. They don't have to be
2656 * taken into account while computing the
2657 * global crc
2658 */
acd34afa 2659 if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
db08e6e5 2660 continue;
30cfd02b
AQ
2661 /* Temporary clients have not been announced yet, so
2662 * they have to be skipped while computing the global
2663 * crc
2664 */
2665 if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
2666 continue;
db08e6e5
SW
2667
2668 /* find out if this global entry is announced by this
2669 * originator
2670 */
54e22f26
LL
2671 tt_orig = batadv_tt_global_orig_entry_find(tt_global,
2672 orig_node);
2673 if (!tt_orig)
db08e6e5
SW
2674 continue;
2675
a30e22ca
AQ
2676 /* use network order to read the VID: this ensures that
2677 * every node reads the bytes in the same order.
2678 */
2679 tmp_vid = htons(tt_common->vid);
2680 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568
AQ
2681
2682 /* compute the CRC on flags that have to be kept in sync
2683 * among nodes
2684 */
54e22f26 2685 flags = tt_orig->flags;
0eb01568
AQ
2686 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2687
0ffa9e8d 2688 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
54e22f26
LL
2689
2690 batadv_tt_orig_list_entry_put(tt_orig);
a73105b8
AQ
2691 }
2692 rcu_read_unlock();
2693 }
2694
ced72933 2695 return crc;
a73105b8
AQ
2696}
2697
ced72933 2698/**
7e9a8c2c 2699 * batadv_tt_local_crc() - calculates the checksum of the local table
ced72933 2700 * @bat_priv: the bat priv with all the soft interface information
7ea7b4a1 2701 * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d
AQ
2702 *
2703 * For details about the computation, please refer to the documentation for
2704 * batadv_tt_global_crc().
2705 *
62fe710f 2706 * Return: the checksum of the local table
ced72933 2707 */
6b5e971a
SE
2708static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
2709 unsigned short vid)
a73105b8 2710{
807736f6 2711 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34 2712 struct batadv_tt_common_entry *tt_common;
a73105b8 2713 struct hlist_head *head;
6b5e971a
SE
2714 u32 i, crc_tmp, crc = 0;
2715 u8 flags;
a30e22ca 2716 __be16 tmp_vid;
a73105b8
AQ
2717
2718 for (i = 0; i < hash->size; i++) {
2719 head = &hash->table[i];
2720
2721 rcu_read_lock();
b67bfe0d 2722 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
7ea7b4a1
AQ
2723 /* compute the CRC only for entries belonging to the
2724 * VLAN identified by vid
2725 */
2726 if (tt_common->vid != vid)
2727 continue;
2728
058d0e26 2729 /* not yet committed clients have not to be taken into
9cfc7bd6
SE
2730 * account while computing the CRC
2731 */
acd34afa 2732 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
058d0e26 2733 continue;
ced72933 2734
a30e22ca
AQ
2735 /* use network order to read the VID: this ensures that
2736 * every node reads the bytes in the same order.
2737 */
2738 tmp_vid = htons(tt_common->vid);
2739 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568
AQ
2740
2741 /* compute the CRC on flags that have to be kept in sync
2742 * among nodes
2743 */
2744 flags = tt_common->flags & BATADV_TT_SYNC_MASK;
2745 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2746
0ffa9e8d 2747 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
a73105b8 2748 }
a73105b8
AQ
2749 rcu_read_unlock();
2750 }
2751
ced72933 2752 return crc;
a73105b8
AQ
2753}
2754
9c4604a2 2755/**
7e9a8c2c 2756 * batadv_tt_req_node_release() - free tt_req node entry
9c4604a2
SE
2757 * @ref: kref pointer of the tt req_node entry
2758 */
2759static void batadv_tt_req_node_release(struct kref *ref)
2760{
2761 struct batadv_tt_req_node *tt_req_node;
2762
2763 tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount);
2764
86452f81 2765 kmem_cache_free(batadv_tt_req_cache, tt_req_node);
9c4604a2
SE
2766}
2767
2768/**
7e9a8c2c 2769 * batadv_tt_req_node_put() - decrement the tt_req_node refcounter and
9c4604a2
SE
2770 * possibly release it
2771 * @tt_req_node: tt_req_node to be free'd
2772 */
2773static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
2774{
2775 kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
2776}
2777
56303d34 2778static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
a73105b8 2779{
7c26a53b
ML
2780 struct batadv_tt_req_node *node;
2781 struct hlist_node *safe;
a73105b8 2782
807736f6 2783 spin_lock_bh(&bat_priv->tt.req_list_lock);
a73105b8 2784
7c26a53b
ML
2785 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2786 hlist_del_init(&node->list);
9c4604a2 2787 batadv_tt_req_node_put(node);
a73105b8
AQ
2788 }
2789
807736f6 2790 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2791}
2792
56303d34
SE
2793static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
2794 struct batadv_orig_node *orig_node,
e8cf234a 2795 const void *tt_buff,
6b5e971a 2796 u16 tt_buff_len)
a73105b8 2797{
a73105b8 2798 /* Replace the old buffer only if I received something in the
9cfc7bd6
SE
2799 * last OGM (the OGM could carry no changes)
2800 */
a73105b8
AQ
2801 spin_lock_bh(&orig_node->tt_buff_lock);
2802 if (tt_buff_len > 0) {
2803 kfree(orig_node->tt_buff);
2804 orig_node->tt_buff_len = 0;
2805 orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
2806 if (orig_node->tt_buff) {
2807 memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
2808 orig_node->tt_buff_len = tt_buff_len;
2809 }
2810 }
2811 spin_unlock_bh(&orig_node->tt_buff_lock);
2812}
2813
56303d34 2814static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
a73105b8 2815{
7c26a53b
ML
2816 struct batadv_tt_req_node *node;
2817 struct hlist_node *safe;
a73105b8 2818
807736f6 2819 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 2820 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
42d0b044
SE
2821 if (batadv_has_timed_out(node->issued_at,
2822 BATADV_TT_REQUEST_TIMEOUT)) {
7c26a53b 2823 hlist_del_init(&node->list);
9c4604a2 2824 batadv_tt_req_node_put(node);
a73105b8
AQ
2825 }
2826 }
807736f6 2827 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2828}
2829
383b8636 2830/**
7e9a8c2c 2831 * batadv_tt_req_node_new() - search and possibly create a tt_req_node object
383b8636
ML
2832 * @bat_priv: the bat priv with all the soft interface information
2833 * @orig_node: orig node this request is being issued for
2834 *
62fe710f 2835 * Return: the pointer to the new tt_req_node struct if no request
383b8636 2836 * has already been issued for this orig_node, NULL otherwise.
9cfc7bd6 2837 */
56303d34 2838static struct batadv_tt_req_node *
383b8636 2839batadv_tt_req_node_new(struct batadv_priv *bat_priv,
56303d34 2840 struct batadv_orig_node *orig_node)
a73105b8 2841{
56303d34 2842 struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
a73105b8 2843
807736f6 2844 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 2845 hlist_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1eda58bf
SE
2846 if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
2847 !batadv_has_timed_out(tt_req_node_tmp->issued_at,
42d0b044 2848 BATADV_TT_REQUEST_TIMEOUT))
a73105b8
AQ
2849 goto unlock;
2850 }
2851
86452f81 2852 tt_req_node = kmem_cache_alloc(batadv_tt_req_cache, GFP_ATOMIC);
a73105b8
AQ
2853 if (!tt_req_node)
2854 goto unlock;
2855
9c4604a2 2856 kref_init(&tt_req_node->refcount);
8fdd0153 2857 ether_addr_copy(tt_req_node->addr, orig_node->orig);
a73105b8
AQ
2858 tt_req_node->issued_at = jiffies;
2859
9c4604a2 2860 kref_get(&tt_req_node->refcount);
7c26a53b 2861 hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
a73105b8 2862unlock:
807736f6 2863 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
2864 return tt_req_node;
2865}
2866
335fbe0f 2867/**
7e9a8c2c 2868 * batadv_tt_local_valid() - verify that given tt entry is a valid one
335fbe0f
ML
2869 * @entry_ptr: to be checked local tt entry
2870 * @data_ptr: not used but definition required to satisfy the callback prototype
2871 *
4b426b10 2872 * Return: true if the entry is a valid, false otherwise.
335fbe0f 2873 */
4b426b10 2874static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
058d0e26 2875{
56303d34 2876 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
058d0e26 2877
acd34afa 2878 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
4b426b10
SE
2879 return false;
2880 return true;
058d0e26
AQ
2881}
2882
4b426b10
SE
2883static bool batadv_tt_global_valid(const void *entry_ptr,
2884 const void *data_ptr)
a73105b8 2885{
56303d34
SE
2886 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2887 const struct batadv_tt_global_entry *tt_global_entry;
2888 const struct batadv_orig_node *orig_node = data_ptr;
a73105b8 2889
30cfd02b
AQ
2890 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
2891 tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
4b426b10 2892 return false;
cc47f66e 2893
56303d34
SE
2894 tt_global_entry = container_of(tt_common_entry,
2895 struct batadv_tt_global_entry,
48100bac
AQ
2896 common);
2897
a513088d 2898 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
a73105b8
AQ
2899}
2900
335fbe0f 2901/**
7e9a8c2c 2902 * batadv_tt_tvlv_generate() - fill the tvlv buff with the tt entries from the
7ea7b4a1 2903 * specified tt hash
335fbe0f
ML
2904 * @bat_priv: the bat priv with all the soft interface information
2905 * @hash: hash table containing the tt entries
2906 * @tt_len: expected tvlv tt data buffer length in number of bytes
7ea7b4a1 2907 * @tvlv_buff: pointer to the buffer to fill with the TT data
335fbe0f
ML
2908 * @valid_cb: function to filter tt change entries
2909 * @cb_data: data passed to the filter function as argument
335fbe0f 2910 */
7ea7b4a1
AQ
2911static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2912 struct batadv_hashtable *hash,
6b5e971a 2913 void *tvlv_buff, u16 tt_len,
4b426b10
SE
2914 bool (*valid_cb)(const void *,
2915 const void *),
7ea7b4a1 2916 void *cb_data)
a73105b8 2917{
56303d34 2918 struct batadv_tt_common_entry *tt_common_entry;
335fbe0f 2919 struct batadv_tvlv_tt_change *tt_change;
a73105b8 2920 struct hlist_head *head;
6b5e971a
SE
2921 u16 tt_tot, tt_num_entries = 0;
2922 u32 i;
a73105b8 2923
298e6e68 2924 tt_tot = batadv_tt_entries(tt_len);
7ea7b4a1 2925 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
a73105b8
AQ
2926
2927 rcu_read_lock();
2928 for (i = 0; i < hash->size; i++) {
2929 head = &hash->table[i];
2930
b67bfe0d 2931 hlist_for_each_entry_rcu(tt_common_entry,
a73105b8 2932 head, hash_entry) {
335fbe0f 2933 if (tt_tot == tt_num_entries)
a73105b8
AQ
2934 break;
2935
48100bac 2936 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
a73105b8
AQ
2937 continue;
2938
8fdd0153 2939 ether_addr_copy(tt_change->addr, tt_common_entry->addr);
27b37ebf 2940 tt_change->flags = tt_common_entry->flags;
c018ad3d 2941 tt_change->vid = htons(tt_common_entry->vid);
ca663046
AQ
2942 memset(tt_change->reserved, 0,
2943 sizeof(tt_change->reserved));
a73105b8 2944
335fbe0f 2945 tt_num_entries++;
a73105b8
AQ
2946 tt_change++;
2947 }
2948 }
2949 rcu_read_unlock();
7ea7b4a1 2950}
a73105b8 2951
7ea7b4a1 2952/**
7e9a8c2c 2953 * batadv_tt_global_check_crc() - check if all the CRCs are correct
7ea7b4a1
AQ
2954 * @orig_node: originator for which the CRCs have to be checked
2955 * @tt_vlan: pointer to the first tvlv VLAN entry
2956 * @num_vlan: number of tvlv VLAN entries
7ea7b4a1 2957 *
62fe710f 2958 * Return: true if all the received CRCs match the locally stored ones, false
7ea7b4a1
AQ
2959 * otherwise
2960 */
2961static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
2962 struct batadv_tvlv_tt_vlan_data *tt_vlan,
6b5e971a 2963 u16 num_vlan)
7ea7b4a1
AQ
2964{
2965 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
2966 struct batadv_orig_node_vlan *vlan;
c169c59d 2967 int i, orig_num_vlan;
6b5e971a 2968 u32 crc;
7ea7b4a1
AQ
2969
2970 /* check if each received CRC matches the locally stored one */
2971 for (i = 0; i < num_vlan; i++) {
2972 tt_vlan_tmp = tt_vlan + i;
2973
2974 /* if orig_node is a backbone node for this VLAN, don't check
2975 * the CRC as we ignore all the global entries over it
2976 */
2977 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
cfd4f757
AQ
2978 orig_node->orig,
2979 ntohs(tt_vlan_tmp->vid)))
7ea7b4a1
AQ
2980 continue;
2981
2982 vlan = batadv_orig_node_vlan_get(orig_node,
2983 ntohs(tt_vlan_tmp->vid));
2984 if (!vlan)
2985 return false;
2986
91c2b1a9 2987 crc = vlan->tt.crc;
21754e25 2988 batadv_orig_node_vlan_put(vlan);
91c2b1a9
AQ
2989
2990 if (crc != ntohl(tt_vlan_tmp->crc))
7ea7b4a1
AQ
2991 return false;
2992 }
2993
c169c59d
SW
2994 /* check if any excess VLANs exist locally for the originator
2995 * which are not mentioned in the TVLV from the originator.
2996 */
2997 rcu_read_lock();
2998 orig_num_vlan = 0;
2999 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list)
3000 orig_num_vlan++;
3001 rcu_read_unlock();
3002
3003 if (orig_num_vlan > num_vlan)
3004 return false;
3005
7ea7b4a1
AQ
3006 return true;
3007}
3008
3009/**
7e9a8c2c 3010 * batadv_tt_local_update_crc() - update all the local CRCs
7ea7b4a1
AQ
3011 * @bat_priv: the bat priv with all the soft interface information
3012 */
3013static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
3014{
3015 struct batadv_softif_vlan *vlan;
3016
3017 /* recompute the global CRC for each VLAN */
3018 rcu_read_lock();
3019 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
3020 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
3021 }
3022 rcu_read_unlock();
3023}
3024
3025/**
7e9a8c2c 3026 * batadv_tt_global_update_crc() - update all the global CRCs for this orig_node
7ea7b4a1
AQ
3027 * @bat_priv: the bat priv with all the soft interface information
3028 * @orig_node: the orig_node for which the CRCs have to be updated
3029 */
3030static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
3031 struct batadv_orig_node *orig_node)
3032{
3033 struct batadv_orig_node_vlan *vlan;
6b5e971a 3034 u32 crc;
7ea7b4a1
AQ
3035
3036 /* recompute the global CRC for each VLAN */
3037 rcu_read_lock();
d0fa4f3f 3038 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
7ea7b4a1
AQ
3039 /* if orig_node is a backbone node for this VLAN, don't compute
3040 * the CRC as we ignore all the global entries over it
3041 */
cfd4f757
AQ
3042 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
3043 vlan->vid))
7ea7b4a1
AQ
3044 continue;
3045
3046 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
3047 vlan->tt.crc = crc;
3048 }
3049 rcu_read_unlock();
a73105b8
AQ
3050}
3051
ced72933 3052/**
7e9a8c2c 3053 * batadv_send_tt_request() - send a TT Request message to a given node
ced72933
AQ
3054 * @bat_priv: the bat priv with all the soft interface information
3055 * @dst_orig_node: the destination of the message
3056 * @ttvn: the version number that the source of the message is looking for
7ea7b4a1
AQ
3057 * @tt_vlan: pointer to the first tvlv VLAN object to request
3058 * @num_vlan: number of tvlv VLAN entries
ced72933
AQ
3059 * @full_table: ask for the entire translation table if true, while only for the
3060 * last TT diff otherwise
d15cd622
AQ
3061 *
3062 * Return: true if the TT Request was sent, false otherwise
ced72933 3063 */
4b426b10
SE
3064static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
3065 struct batadv_orig_node *dst_orig_node,
3066 u8 ttvn,
3067 struct batadv_tvlv_tt_vlan_data *tt_vlan,
3068 u16 num_vlan, bool full_table)
a73105b8 3069{
335fbe0f 3070 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34 3071 struct batadv_tt_req_node *tt_req_node = NULL;
7ea7b4a1
AQ
3072 struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
3073 struct batadv_hard_iface *primary_if;
335fbe0f 3074 bool ret = false;
7ea7b4a1 3075 int i, size;
a73105b8 3076
e5d89254 3077 primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8
AQ
3078 if (!primary_if)
3079 goto out;
3080
3081 /* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd6
SE
3082 * reply from the same orig_node yet
3083 */
383b8636 3084 tt_req_node = batadv_tt_req_node_new(bat_priv, dst_orig_node);
a73105b8
AQ
3085 if (!tt_req_node)
3086 goto out;
3087
7ea7b4a1
AQ
3088 size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
3089 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
335fbe0f 3090 if (!tvlv_tt_data)
a73105b8
AQ
3091 goto out;
3092
335fbe0f
ML
3093 tvlv_tt_data->flags = BATADV_TT_REQUEST;
3094 tvlv_tt_data->ttvn = ttvn;
7ea7b4a1
AQ
3095 tvlv_tt_data->num_vlan = htons(num_vlan);
3096
3097 /* send all the CRCs within the request. This is needed by intermediate
3098 * nodes to ensure they have the correct table before replying
3099 */
3100 tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
3101 for (i = 0; i < num_vlan; i++) {
3102 tt_vlan_req->vid = tt_vlan->vid;
3103 tt_vlan_req->crc = tt_vlan->crc;
3104
3105 tt_vlan_req++;
3106 tt_vlan++;
3107 }
a73105b8
AQ
3108
3109 if (full_table)
335fbe0f 3110 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3111
bb351ba0 3112 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
335fbe0f 3113 dst_orig_node->orig, full_table ? 'F' : '.');
a73105b8 3114
d69909d2 3115 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
335fbe0f
ML
3116 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3117 dst_orig_node->orig, BATADV_TVLV_TT, 1,
7ea7b4a1 3118 tvlv_tt_data, size);
335fbe0f 3119 ret = true;
a73105b8
AQ
3120
3121out:
a73105b8 3122 if (primary_if)
82047ad7 3123 batadv_hardif_put(primary_if);
9c4604a2 3124
a73105b8 3125 if (ret && tt_req_node) {
807736f6 3126 spin_lock_bh(&bat_priv->tt.req_list_lock);
9c4604a2
SE
3127 if (!hlist_unhashed(&tt_req_node->list)) {
3128 hlist_del_init(&tt_req_node->list);
3129 batadv_tt_req_node_put(tt_req_node);
3130 }
807736f6 3131 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8 3132 }
9c4604a2
SE
3133
3134 if (tt_req_node)
3135 batadv_tt_req_node_put(tt_req_node);
3136
335fbe0f 3137 kfree(tvlv_tt_data);
a73105b8
AQ
3138 return ret;
3139}
3140
335fbe0f 3141/**
7e9a8c2c 3142 * batadv_send_other_tt_response() - send reply to tt request concerning another
335fbe0f
ML
3143 * node's translation table
3144 * @bat_priv: the bat priv with all the soft interface information
3145 * @tt_data: tt data containing the tt request information
3146 * @req_src: mac address of tt request sender
3147 * @req_dst: mac address of tt request recipient
3148 *
62fe710f 3149 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3150 */
3151static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
3152 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3153 u8 *req_src, u8 *req_dst)
a73105b8 3154{
170173bf 3155 struct batadv_orig_node *req_dst_orig_node;
56303d34 3156 struct batadv_orig_node *res_dst_orig_node = NULL;
7ea7b4a1 3157 struct batadv_tvlv_tt_change *tt_change;
335fbe0f 3158 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
7ea7b4a1 3159 struct batadv_tvlv_tt_vlan_data *tt_vlan;
335fbe0f 3160 bool ret = false, full_table;
6b5e971a
SE
3161 u8 orig_ttvn, req_ttvn;
3162 u16 tvlv_len;
3163 s32 tt_len;
a73105b8 3164
39c75a51 3165 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3166 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
335fbe0f 3167 req_src, tt_data->ttvn, req_dst,
a2f2b6cd 3168 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8
AQ
3169
3170 /* Let's get the orig node of the REAL destination */
335fbe0f 3171 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
a73105b8
AQ
3172 if (!req_dst_orig_node)
3173 goto out;
3174
335fbe0f 3175 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8
AQ
3176 if (!res_dst_orig_node)
3177 goto out;
3178
6b5e971a 3179 orig_ttvn = (u8)atomic_read(&req_dst_orig_node->last_ttvn);
335fbe0f 3180 req_ttvn = tt_data->ttvn;
a73105b8 3181
7ea7b4a1 3182 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
335fbe0f 3183 /* this node doesn't have the requested data */
a73105b8 3184 if (orig_ttvn != req_ttvn ||
7ea7b4a1
AQ
3185 !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
3186 ntohs(tt_data->num_vlan)))
a73105b8
AQ
3187 goto out;
3188
015758d0 3189 /* If the full table has been explicitly requested */
335fbe0f 3190 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
a73105b8
AQ
3191 !req_dst_orig_node->tt_buff)
3192 full_table = true;
3193 else
3194 full_table = false;
3195
335fbe0f
ML
3196 /* TT fragmentation hasn't been implemented yet, so send as many
3197 * TT entries fit a single packet as possible only
9cfc7bd6 3198 */
a73105b8
AQ
3199 if (!full_table) {
3200 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
3201 tt_len = req_dst_orig_node->tt_buff_len;
a73105b8 3202
7ea7b4a1
AQ
3203 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3204 &tvlv_tt_data,
3205 &tt_change,
3206 &tt_len);
3207 if (!tt_len)
a73105b8
AQ
3208 goto unlock;
3209
a73105b8 3210 /* Copy the last orig_node's OGM buffer */
7ea7b4a1 3211 memcpy(tt_change, req_dst_orig_node->tt_buff,
a73105b8 3212 req_dst_orig_node->tt_buff_len);
a73105b8
AQ
3213 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3214 } else {
7ea7b4a1
AQ
3215 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3216 * in the initial part
3217 */
3218 tt_len = -1;
3219 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3220 &tvlv_tt_data,
3221 &tt_change,
3222 &tt_len);
3223 if (!tt_len)
a73105b8 3224 goto out;
7ea7b4a1
AQ
3225
3226 /* fill the rest of the tvlv with the real TT entries */
3227 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
3228 tt_change, tt_len,
3229 batadv_tt_global_valid,
3230 req_dst_orig_node);
a73105b8
AQ
3231 }
3232
a19d3d85
ML
3233 /* Don't send the response, if larger than fragmented packet. */
3234 tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
3235 if (tt_len > atomic_read(&bat_priv->packet_size_max)) {
3236 net_ratelimited_function(batadv_info, bat_priv->soft_iface,
3237 "Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.\n",
3238 res_dst_orig_node->orig);
3239 goto out;
3240 }
3241
335fbe0f
ML
3242 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3243 tvlv_tt_data->ttvn = req_ttvn;
a73105b8
AQ
3244
3245 if (full_table)
335fbe0f 3246 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3247
39c75a51 3248 batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f
ML
3249 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
3250 res_dst_orig_node->orig, req_dst_orig_node->orig,
3251 full_table ? 'F' : '.', req_ttvn);
a73105b8 3252
d69909d2 3253 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865 3254
335fbe0f 3255 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
7ea7b4a1
AQ
3256 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3257 tvlv_len);
e91ecfc6 3258
335fbe0f 3259 ret = true;
a73105b8
AQ
3260 goto out;
3261
3262unlock:
3263 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3264
3265out:
3266 if (res_dst_orig_node)
5d967310 3267 batadv_orig_node_put(res_dst_orig_node);
a73105b8 3268 if (req_dst_orig_node)
5d967310 3269 batadv_orig_node_put(req_dst_orig_node);
335fbe0f 3270 kfree(tvlv_tt_data);
a73105b8 3271 return ret;
a73105b8 3272}
96412690 3273
335fbe0f 3274/**
7e9a8c2c
SE
3275 * batadv_send_my_tt_response() - send reply to tt request concerning this
3276 * node's translation table
335fbe0f
ML
3277 * @bat_priv: the bat priv with all the soft interface information
3278 * @tt_data: tt data containing the tt request information
3279 * @req_src: mac address of tt request sender
3280 *
62fe710f 3281 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3282 */
3283static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
3284 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3285 u8 *req_src)
a73105b8 3286{
335fbe0f 3287 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34 3288 struct batadv_hard_iface *primary_if = NULL;
7ea7b4a1
AQ
3289 struct batadv_tvlv_tt_change *tt_change;
3290 struct batadv_orig_node *orig_node;
6b5e971a
SE
3291 u8 my_ttvn, req_ttvn;
3292 u16 tvlv_len;
a73105b8 3293 bool full_table;
6b5e971a 3294 s32 tt_len;
a73105b8 3295
39c75a51 3296 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3297 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
335fbe0f 3298 req_src, tt_data->ttvn,
a2f2b6cd 3299 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8 3300
a70a9aa9 3301 spin_lock_bh(&bat_priv->tt.commit_lock);
a73105b8 3302
6b5e971a 3303 my_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
335fbe0f 3304 req_ttvn = tt_data->ttvn;
a73105b8 3305
335fbe0f 3306 orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8
AQ
3307 if (!orig_node)
3308 goto out;
3309
e5d89254 3310 primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8
AQ
3311 if (!primary_if)
3312 goto out;
3313
3314 /* If the full table has been explicitly requested or the gap
9cfc7bd6
SE
3315 * is too big send the whole local translation table
3316 */
335fbe0f 3317 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
807736f6 3318 !bat_priv->tt.last_changeset)
a73105b8
AQ
3319 full_table = true;
3320 else
3321 full_table = false;
3322
335fbe0f
ML
3323 /* TT fragmentation hasn't been implemented yet, so send as many
3324 * TT entries fit a single packet as possible only
9cfc7bd6 3325 */
a73105b8 3326 if (!full_table) {
807736f6 3327 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3328
7ea7b4a1
AQ
3329 tt_len = bat_priv->tt.last_changeset_len;
3330 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3331 &tvlv_tt_data,
3332 &tt_change,
3333 &tt_len);
c2d0f48a 3334 if (!tt_len || !tvlv_len)
a73105b8
AQ
3335 goto unlock;
3336
335fbe0f 3337 /* Copy the last orig_node's OGM buffer */
7ea7b4a1 3338 memcpy(tt_change, bat_priv->tt.last_changeset,
807736f6
SE
3339 bat_priv->tt.last_changeset_len);
3340 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3341 } else {
6b5e971a 3342 req_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
335fbe0f 3343
7ea7b4a1
AQ
3344 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3345 * in the initial part
3346 */
3347 tt_len = -1;
3348 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3349 &tvlv_tt_data,
3350 &tt_change,
3351 &tt_len);
c2d0f48a 3352 if (!tt_len || !tvlv_len)
a73105b8 3353 goto out;
7ea7b4a1
AQ
3354
3355 /* fill the rest of the tvlv with the real TT entries */
3356 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
3357 tt_change, tt_len,
3358 batadv_tt_local_valid, NULL);
a73105b8
AQ
3359 }
3360
335fbe0f
ML
3361 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3362 tvlv_tt_data->ttvn = req_ttvn;
a73105b8
AQ
3363
3364 if (full_table)
335fbe0f 3365 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8 3366
39c75a51 3367 batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f
ML
3368 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
3369 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
a73105b8 3370
d69909d2 3371 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865 3372
335fbe0f 3373 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
7ea7b4a1
AQ
3374 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3375 tvlv_len);
335fbe0f 3376
a73105b8
AQ
3377 goto out;
3378
3379unlock:
807736f6 3380 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8 3381out:
a70a9aa9 3382 spin_unlock_bh(&bat_priv->tt.commit_lock);
a73105b8 3383 if (orig_node)
5d967310 3384 batadv_orig_node_put(orig_node);
a73105b8 3385 if (primary_if)
82047ad7 3386 batadv_hardif_put(primary_if);
335fbe0f
ML
3387 kfree(tvlv_tt_data);
3388 /* The packet was for this host, so it doesn't need to be re-routed */
a73105b8
AQ
3389 return true;
3390}
3391
335fbe0f 3392/**
7e9a8c2c 3393 * batadv_send_tt_response() - send reply to tt request
335fbe0f
ML
3394 * @bat_priv: the bat priv with all the soft interface information
3395 * @tt_data: tt data containing the tt request information
3396 * @req_src: mac address of tt request sender
3397 * @req_dst: mac address of tt request recipient
3398 *
62fe710f 3399 * Return: true if tt request reply was sent, false otherwise.
335fbe0f
ML
3400 */
3401static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
3402 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3403 u8 *req_src, u8 *req_dst)
a73105b8 3404{
cfd4f757 3405 if (batadv_is_my_mac(bat_priv, req_dst))
335fbe0f 3406 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
24820df1
AQ
3407 return batadv_send_other_tt_response(bat_priv, tt_data, req_src,
3408 req_dst);
a73105b8
AQ
3409}
3410
56303d34
SE
3411static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
3412 struct batadv_orig_node *orig_node,
335fbe0f 3413 struct batadv_tvlv_tt_change *tt_change,
6b5e971a 3414 u16 tt_num_changes, u8 ttvn)
a73105b8
AQ
3415{
3416 int i;
a513088d 3417 int roams;
a73105b8
AQ
3418
3419 for (i = 0; i < tt_num_changes; i++) {
acd34afa
SE
3420 if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
3421 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
a513088d
SE
3422 batadv_tt_global_del(bat_priv, orig_node,
3423 (tt_change + i)->addr,
c018ad3d 3424 ntohs((tt_change + i)->vid),
d4f44692
AQ
3425 "tt removed by changes",
3426 roams);
08c36d3e 3427 } else {
08c36d3e 3428 if (!batadv_tt_global_add(bat_priv, orig_node,
d4f44692 3429 (tt_change + i)->addr,
c018ad3d 3430 ntohs((tt_change + i)->vid),
d4f44692 3431 (tt_change + i)->flags, ttvn))
a73105b8
AQ
3432 /* In case of problem while storing a
3433 * global_entry, we stop the updating
3434 * procedure without committing the
3435 * ttvn change. This will avoid to send
3436 * corrupted data on tt_request
3437 */
3438 return;
08c36d3e 3439 }
a73105b8 3440 }
ac4eebd4 3441 set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
a73105b8
AQ
3442}
3443
56303d34 3444static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
7ea7b4a1 3445 struct batadv_tvlv_tt_change *tt_change,
6b5e971a
SE
3446 u8 ttvn, u8 *resp_src,
3447 u16 num_entries)
a73105b8 3448{
170173bf 3449 struct batadv_orig_node *orig_node;
a73105b8 3450
335fbe0f 3451 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8
AQ
3452 if (!orig_node)
3453 goto out;
3454
3455 /* Purge the old table first.. */
95fb130d
AQ
3456 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
3457 "Received full table");
a73105b8 3458
7ea7b4a1
AQ
3459 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
3460 ttvn);
a73105b8
AQ
3461
3462 spin_lock_bh(&orig_node->tt_buff_lock);
3463 kfree(orig_node->tt_buff);
3464 orig_node->tt_buff_len = 0;
3465 orig_node->tt_buff = NULL;
3466 spin_unlock_bh(&orig_node->tt_buff_lock);
3467
7ea7b4a1 3468 atomic_set(&orig_node->last_ttvn, ttvn);
a73105b8
AQ
3469
3470out:
3471 if (orig_node)
5d967310 3472 batadv_orig_node_put(orig_node);
a73105b8
AQ
3473}
3474
56303d34
SE
3475static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
3476 struct batadv_orig_node *orig_node,
6b5e971a 3477 u16 tt_num_changes, u8 ttvn,
335fbe0f 3478 struct batadv_tvlv_tt_change *tt_change)
a73105b8 3479{
a513088d
SE
3480 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
3481 tt_num_changes, ttvn);
a73105b8 3482
e8cf234a
AQ
3483 batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
3484 batadv_tt_len(tt_num_changes));
a73105b8
AQ
3485 atomic_set(&orig_node->last_ttvn, ttvn);
3486}
3487
c018ad3d 3488/**
7e9a8c2c 3489 * batadv_is_my_client() - check if a client is served by the local node
c018ad3d 3490 * @bat_priv: the bat priv with all the soft interface information
3f68785e 3491 * @addr: the mac address of the client to check
c018ad3d
AQ
3492 * @vid: VLAN identifier
3493 *
62fe710f 3494 * Return: true if the client is served by this node, false otherwise.
c018ad3d 3495 */
6b5e971a 3496bool batadv_is_my_client(struct batadv_priv *bat_priv, const u8 *addr,
c018ad3d 3497 unsigned short vid)
a73105b8 3498{
170173bf 3499 struct batadv_tt_local_entry *tt_local_entry;
7683fdc1 3500 bool ret = false;
a73105b8 3501
c018ad3d 3502 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1
AQ
3503 if (!tt_local_entry)
3504 goto out;
058d0e26 3505 /* Check if the client has been logically deleted (but is kept for
9cfc7bd6
SE
3506 * consistency purpose)
3507 */
7c1fd91d
AQ
3508 if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
3509 (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
058d0e26 3510 goto out;
7683fdc1
AQ
3511 ret = true;
3512out:
a73105b8 3513 if (tt_local_entry)
95c0db90 3514 batadv_tt_local_entry_put(tt_local_entry);
7683fdc1 3515 return ret;
a73105b8
AQ
3516}
3517
335fbe0f 3518/**
7e9a8c2c 3519 * batadv_handle_tt_response() - process incoming tt reply
335fbe0f
ML
3520 * @bat_priv: the bat priv with all the soft interface information
3521 * @tt_data: tt data containing the tt request information
3522 * @resp_src: mac address of tt reply sender
3523 * @num_entries: number of tt change entries appended to the tt data
3524 */
3525static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
3526 struct batadv_tvlv_tt_data *tt_data,
6b5e971a 3527 u8 *resp_src, u16 num_entries)
a73105b8 3528{
7c26a53b
ML
3529 struct batadv_tt_req_node *node;
3530 struct hlist_node *safe;
56303d34 3531 struct batadv_orig_node *orig_node = NULL;
335fbe0f 3532 struct batadv_tvlv_tt_change *tt_change;
6b5e971a
SE
3533 u8 *tvlv_ptr = (u8 *)tt_data;
3534 u16 change_offset;
a73105b8 3535
39c75a51 3536 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3537 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
335fbe0f 3538 resp_src, tt_data->ttvn, num_entries,
a2f2b6cd 3539 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
a73105b8 3540
335fbe0f 3541 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8
AQ
3542 if (!orig_node)
3543 goto out;
3544
a70a9aa9
AQ
3545 spin_lock_bh(&orig_node->tt_lock);
3546
7ea7b4a1
AQ
3547 change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
3548 change_offset *= ntohs(tt_data->num_vlan);
3549 change_offset += sizeof(*tt_data);
3550 tvlv_ptr += change_offset;
3551
3552 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
335fbe0f 3553 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
7ea7b4a1
AQ
3554 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
3555 resp_src, num_entries);
96412690 3556 } else {
335fbe0f
ML
3557 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
3558 tt_data->ttvn, tt_change);
96412690 3559 }
a73105b8 3560
a70a9aa9 3561 /* Recalculate the CRC for this orig_node and store it */
7ea7b4a1 3562 batadv_tt_global_update_crc(bat_priv, orig_node);
a70a9aa9
AQ
3563
3564 spin_unlock_bh(&orig_node->tt_lock);
3565
a73105b8 3566 /* Delete the tt_req_node from pending tt_requests list */
807736f6 3567 spin_lock_bh(&bat_priv->tt.req_list_lock);
7c26a53b 3568 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
335fbe0f 3569 if (!batadv_compare_eth(node->addr, resp_src))
a73105b8 3570 continue;
7c26a53b 3571 hlist_del_init(&node->list);
9c4604a2 3572 batadv_tt_req_node_put(node);
a73105b8 3573 }
7ea7b4a1 3574
807736f6 3575 spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8
AQ
3576out:
3577 if (orig_node)
5d967310 3578 batadv_orig_node_put(orig_node);
a73105b8
AQ
3579}
3580
56303d34 3581static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
a73105b8 3582{
56303d34 3583 struct batadv_tt_roam_node *node, *safe;
a73105b8 3584
807736f6 3585 spin_lock_bh(&bat_priv->tt.roam_list_lock);
a73105b8 3586
807736f6 3587 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
cc47f66e 3588 list_del(&node->list);
86452f81 3589 kmem_cache_free(batadv_tt_roam_cache, node);
cc47f66e
AQ
3590 }
3591
807736f6 3592 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3593}
3594
56303d34 3595static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
cc47f66e 3596{
56303d34 3597 struct batadv_tt_roam_node *node, *safe;
cc47f66e 3598
807736f6
SE
3599 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3600 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
42d0b044
SE
3601 if (!batadv_has_timed_out(node->first_time,
3602 BATADV_ROAMING_MAX_TIME))
cc47f66e
AQ
3603 continue;
3604
3605 list_del(&node->list);
86452f81 3606 kmem_cache_free(batadv_tt_roam_cache, node);
cc47f66e 3607 }
807736f6 3608 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3609}
3610
62fe710f 3611/**
7e9a8c2c 3612 * batadv_tt_check_roam_count() - check if a client has roamed too frequently
d15cd622
AQ
3613 * @bat_priv: the bat priv with all the soft interface information
3614 * @client: mac address of the roaming client
62fe710f
SE
3615 *
3616 * This function checks whether the client already reached the
cc47f66e
AQ
3617 * maximum number of possible roaming phases. In this case the ROAMING_ADV
3618 * will not be sent.
3619 *
62fe710f 3620 * Return: true if the ROAMING_ADV can be sent, false otherwise
9cfc7bd6 3621 */
6b5e971a 3622static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, u8 *client)
cc47f66e 3623{
56303d34 3624 struct batadv_tt_roam_node *tt_roam_node;
cc47f66e
AQ
3625 bool ret = false;
3626
807736f6 3627 spin_lock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e 3628 /* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd6
SE
3629 * reply from the same orig_node yet
3630 */
807736f6 3631 list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
1eda58bf 3632 if (!batadv_compare_eth(tt_roam_node->addr, client))
cc47f66e
AQ
3633 continue;
3634
1eda58bf 3635 if (batadv_has_timed_out(tt_roam_node->first_time,
42d0b044 3636 BATADV_ROAMING_MAX_TIME))
cc47f66e
AQ
3637 continue;
3638
3e34819e 3639 if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
cc47f66e
AQ
3640 /* Sorry, you roamed too many times! */
3641 goto unlock;
3642 ret = true;
3643 break;
3644 }
3645
3646 if (!ret) {
86452f81
SE
3647 tt_roam_node = kmem_cache_alloc(batadv_tt_roam_cache,
3648 GFP_ATOMIC);
cc47f66e
AQ
3649 if (!tt_roam_node)
3650 goto unlock;
3651
3652 tt_roam_node->first_time = jiffies;
42d0b044
SE
3653 atomic_set(&tt_roam_node->counter,
3654 BATADV_ROAMING_MAX_COUNT - 1);
8fdd0153 3655 ether_addr_copy(tt_roam_node->addr, client);
cc47f66e 3656
807736f6 3657 list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
cc47f66e
AQ
3658 ret = true;
3659 }
3660
3661unlock:
807736f6 3662 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e
AQ
3663 return ret;
3664}
3665
c018ad3d 3666/**
7e9a8c2c 3667 * batadv_send_roam_adv() - send a roaming advertisement message
c018ad3d
AQ
3668 * @bat_priv: the bat priv with all the soft interface information
3669 * @client: mac address of the roaming client
3670 * @vid: VLAN identifier
3671 * @orig_node: message destination
3672 *
3673 * Send a ROAMING_ADV message to the node which was previously serving this
3674 * client. This is done to inform the node that from now on all traffic destined
3675 * for this particular roamed client has to be forwarded to the sender of the
3676 * roaming message.
3677 */
6b5e971a 3678static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
c018ad3d 3679 unsigned short vid,
56303d34 3680 struct batadv_orig_node *orig_node)
cc47f66e 3681{
56303d34 3682 struct batadv_hard_iface *primary_if;
122edaa0
ML
3683 struct batadv_tvlv_roam_adv tvlv_roam;
3684
3685 primary_if = batadv_primary_if_get_selected(bat_priv);
3686 if (!primary_if)
3687 goto out;
cc47f66e
AQ
3688
3689 /* before going on we have to check whether the client has
9cfc7bd6
SE
3690 * already roamed to us too many times
3691 */
a513088d 3692 if (!batadv_tt_check_roam_count(bat_priv, client))
cc47f66e
AQ
3693 goto out;
3694
39c75a51 3695 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 3696 "Sending ROAMING_ADV to %pM (client %pM, vid: %d)\n",
f7a2bd65 3697 orig_node->orig, client, batadv_print_vid(vid));
cc47f66e 3698
d69909d2 3699 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
f8214865 3700
122edaa0 3701 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
c018ad3d 3702 tvlv_roam.vid = htons(vid);
122edaa0
ML
3703
3704 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3705 orig_node->orig, BATADV_TVLV_ROAM, 1,
3706 &tvlv_roam, sizeof(tvlv_roam));
cc47f66e
AQ
3707
3708out:
122edaa0 3709 if (primary_if)
82047ad7 3710 batadv_hardif_put(primary_if);
a73105b8
AQ
3711}
3712
a513088d 3713static void batadv_tt_purge(struct work_struct *work)
a73105b8 3714{
56303d34 3715 struct delayed_work *delayed_work;
807736f6 3716 struct batadv_priv_tt *priv_tt;
56303d34
SE
3717 struct batadv_priv *bat_priv;
3718
4ba4bc0f 3719 delayed_work = to_delayed_work(work);
807736f6
SE
3720 priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
3721 bat_priv = container_of(priv_tt, struct batadv_priv, tt);
a73105b8 3722
a19d3d85 3723 batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT);
30cfd02b 3724 batadv_tt_global_purge(bat_priv);
a513088d
SE
3725 batadv_tt_req_purge(bat_priv);
3726 batadv_tt_roam_purge(bat_priv);
a73105b8 3727
72414442
AQ
3728 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
3729 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
a73105b8 3730}
cc47f66e 3731
56303d34 3732void batadv_tt_free(struct batadv_priv *bat_priv)
cc47f66e 3733{
e1bf0c14
ML
3734 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
3735 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
3736
807736f6 3737 cancel_delayed_work_sync(&bat_priv->tt.work);
cc47f66e 3738
a513088d
SE
3739 batadv_tt_local_table_free(bat_priv);
3740 batadv_tt_global_table_free(bat_priv);
3741 batadv_tt_req_list_free(bat_priv);
3742 batadv_tt_changes_list_free(bat_priv);
3743 batadv_tt_roam_list_free(bat_priv);
cc47f66e 3744
807736f6 3745 kfree(bat_priv->tt.last_changeset);
cc47f66e 3746}
058d0e26 3747
7ea7b4a1 3748/**
7e9a8c2c 3749 * batadv_tt_local_set_flags() - set or unset the specified flags on the local
7ea7b4a1
AQ
3750 * table and possibly count them in the TT size
3751 * @bat_priv: the bat priv with all the soft interface information
3752 * @flags: the flag to switch
3753 * @enable: whether to set or unset the flag
3754 * @count: whether to increase the TT size by the number of changed entries
9cfc7bd6 3755 */
6b5e971a
SE
3756static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv, u16 flags,
3757 bool enable, bool count)
058d0e26 3758{
7ea7b4a1
AQ
3759 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
3760 struct batadv_tt_common_entry *tt_common_entry;
058d0e26 3761 struct hlist_head *head;
6b5e971a 3762 u32 i;
058d0e26
AQ
3763
3764 if (!hash)
7ea7b4a1 3765 return;
058d0e26
AQ
3766
3767 for (i = 0; i < hash->size; i++) {
3768 head = &hash->table[i];
3769
3770 rcu_read_lock();
b67bfe0d 3771 hlist_for_each_entry_rcu(tt_common_entry,
058d0e26 3772 head, hash_entry) {
697f2531
AQ
3773 if (enable) {
3774 if ((tt_common_entry->flags & flags) == flags)
3775 continue;
3776 tt_common_entry->flags |= flags;
3777 } else {
3778 if (!(tt_common_entry->flags & flags))
3779 continue;
3780 tt_common_entry->flags &= ~flags;
3781 }
7ea7b4a1
AQ
3782
3783 if (!count)
3784 continue;
3785
3786 batadv_tt_local_size_inc(bat_priv,
3787 tt_common_entry->vid);
058d0e26
AQ
3788 }
3789 rcu_read_unlock();
3790 }
058d0e26
AQ
3791}
3792
acd34afa 3793/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
56303d34 3794static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
058d0e26 3795{
807736f6 3796 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34
SE
3797 struct batadv_tt_common_entry *tt_common;
3798 struct batadv_tt_local_entry *tt_local;
b67bfe0d 3799 struct hlist_node *node_tmp;
058d0e26
AQ
3800 struct hlist_head *head;
3801 spinlock_t *list_lock; /* protects write access to the hash lists */
6b5e971a 3802 u32 i;
058d0e26
AQ
3803
3804 if (!hash)
3805 return;
3806
3807 for (i = 0; i < hash->size; i++) {
3808 head = &hash->table[i];
3809 list_lock = &hash->list_locks[i];
3810
3811 spin_lock_bh(list_lock);
b67bfe0d 3812 hlist_for_each_entry_safe(tt_common, node_tmp, head,
acd34afa
SE
3813 hash_entry) {
3814 if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
058d0e26
AQ
3815 continue;
3816
39c75a51 3817 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789
AQ
3818 "Deleting local tt entry (%pM, vid: %d): pending\n",
3819 tt_common->addr,
f7a2bd65 3820 batadv_print_vid(tt_common->vid));
058d0e26 3821
7ea7b4a1 3822 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
b67bfe0d 3823 hlist_del_rcu(&tt_common->hash_entry);
56303d34
SE
3824 tt_local = container_of(tt_common,
3825 struct batadv_tt_local_entry,
3826 common);
35df3b29 3827
95c0db90 3828 batadv_tt_local_entry_put(tt_local);
058d0e26
AQ
3829 }
3830 spin_unlock_bh(list_lock);
3831 }
058d0e26
AQ
3832}
3833
e1bf0c14 3834/**
7e9a8c2c 3835 * batadv_tt_local_commit_changes_nolock() - commit all pending local tt changes
a19d3d85 3836 * which have been queued in the time since the last commit
e1bf0c14 3837 * @bat_priv: the bat priv with all the soft interface information
a19d3d85
ML
3838 *
3839 * Caller must hold tt->commit_lock.
e1bf0c14 3840 */
a19d3d85 3841static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
058d0e26 3842{
5274cd68
SE
3843 lockdep_assert_held(&bat_priv->tt.commit_lock);
3844
e1bf0c14
ML
3845 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
3846 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
3847 batadv_tt_tvlv_container_update(bat_priv);
a19d3d85 3848 return;
e1bf0c14 3849 }
be9aa4c1 3850
7ea7b4a1 3851 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
be9aa4c1 3852
a513088d 3853 batadv_tt_local_purge_pending_clients(bat_priv);
7ea7b4a1 3854 batadv_tt_local_update_crc(bat_priv);
058d0e26
AQ
3855
3856 /* Increment the TTVN only once per OGM interval */
807736f6 3857 atomic_inc(&bat_priv->tt.vn);
39c75a51 3858 batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bf 3859 "Local changes committed, updating to ttvn %u\n",
6b5e971a 3860 (u8)atomic_read(&bat_priv->tt.vn));
be9aa4c1
ML
3861
3862 /* reset the sending counter */
807736f6 3863 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
e1bf0c14 3864 batadv_tt_tvlv_container_update(bat_priv);
a19d3d85 3865}
a70a9aa9 3866
a19d3d85 3867/**
7e9a8c2c 3868 * batadv_tt_local_commit_changes() - commit all pending local tt changes which
a19d3d85
ML
3869 * have been queued in the time since the last commit
3870 * @bat_priv: the bat priv with all the soft interface information
3871 */
3872void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
3873{
3874 spin_lock_bh(&bat_priv->tt.commit_lock);
3875 batadv_tt_local_commit_changes_nolock(bat_priv);
a70a9aa9 3876 spin_unlock_bh(&bat_priv->tt.commit_lock);
058d0e26 3877}
59b699cd 3878
6b5e971a
SE
3879bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
3880 unsigned short vid)
59b699cd 3881{
393b299d
ME
3882 struct batadv_tt_local_entry *tt_local_entry;
3883 struct batadv_tt_global_entry *tt_global_entry;
b8cbd81d 3884 struct batadv_softif_vlan *vlan;
5870adc6 3885 bool ret = false;
59b699cd 3886
b8cbd81d 3887 vlan = batadv_softif_vlan_get(bat_priv, vid);
e087f34f
ME
3888 if (!vlan)
3889 return false;
3890
3891 if (!atomic_read(&vlan->ap_isolation))
393b299d 3892 goto vlan_put;
59b699cd 3893
b8cbd81d 3894 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
59b699cd 3895 if (!tt_local_entry)
393b299d 3896 goto vlan_put;
59b699cd 3897
b8cbd81d 3898 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
59b699cd 3899 if (!tt_global_entry)
393b299d 3900 goto local_entry_put;
59b699cd 3901
393b299d
ME
3902 if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3903 ret = true;
59b699cd 3904
393b299d
ME
3905 batadv_tt_global_entry_put(tt_global_entry);
3906local_entry_put:
3907 batadv_tt_local_entry_put(tt_local_entry);
3908vlan_put:
9c3bf081 3909 batadv_softif_vlan_put(vlan);
59b699cd
AQ
3910 return ret;
3911}
a943cac1 3912
e1bf0c14 3913/**
7e9a8c2c 3914 * batadv_tt_update_orig() - update global translation table with new tt
e1bf0c14
ML
3915 * information received via ogms
3916 * @bat_priv: the bat priv with all the soft interface information
e51f0397
SE
3917 * @orig_node: the orig_node of the ogm
3918 * @tt_buff: pointer to the first tvlv VLAN entry
7ea7b4a1
AQ
3919 * @tt_num_vlan: number of tvlv VLAN entries
3920 * @tt_change: pointer to the first entry in the TT buffer
e1bf0c14
ML
3921 * @tt_num_changes: number of tt changes inside the tt buffer
3922 * @ttvn: translation table version number of this changeset
e1bf0c14
ML
3923 */
3924static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
3925 struct batadv_orig_node *orig_node,
6b5e971a 3926 const void *tt_buff, u16 tt_num_vlan,
7ea7b4a1 3927 struct batadv_tvlv_tt_change *tt_change,
6b5e971a 3928 u16 tt_num_changes, u8 ttvn)
a943cac1 3929{
6b5e971a 3930 u8 orig_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
7ea7b4a1 3931 struct batadv_tvlv_tt_vlan_data *tt_vlan;
a943cac1 3932 bool full_table = true;
e17931d1 3933 bool has_tt_init;
a943cac1 3934
7ea7b4a1 3935 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
ac4eebd4
LL
3936 has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
3937 &orig_node->capa_initialized);
e17931d1 3938
17071578 3939 /* orig table not initialised AND first diff is in the OGM OR the ttvn
9cfc7bd6
SE
3940 * increased by one -> we can apply the attached changes
3941 */
e17931d1 3942 if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) {
a943cac1 3943 /* the OGM could not contain the changes due to their size or
42d0b044
SE
3944 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
3945 * times.
9cfc7bd6
SE
3946 * In this case send a tt request
3947 */
a943cac1
ML
3948 if (!tt_num_changes) {
3949 full_table = false;
3950 goto request_table;
3951 }
3952
a70a9aa9
AQ
3953 spin_lock_bh(&orig_node->tt_lock);
3954
a513088d 3955 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
96412690 3956 ttvn, tt_change);
a943cac1
ML
3957
3958 /* Even if we received the precomputed crc with the OGM, we
3959 * prefer to recompute it to spot any possible inconsistency
9cfc7bd6
SE
3960 * in the global table
3961 */
7ea7b4a1 3962 batadv_tt_global_update_crc(bat_priv, orig_node);
a943cac1 3963
a70a9aa9
AQ
3964 spin_unlock_bh(&orig_node->tt_lock);
3965
a943cac1
ML
3966 /* The ttvn alone is not enough to guarantee consistency
3967 * because a single value could represent different states
3968 * (due to the wrap around). Thus a node has to check whether
3969 * the resulting table (after applying the changes) is still
3970 * consistent or not. E.g. a node could disconnect while its
3971 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
3972 * checking the CRC value is mandatory to detect the
9cfc7bd6
SE
3973 * inconsistency
3974 */
7ea7b4a1
AQ
3975 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
3976 tt_num_vlan))
a943cac1 3977 goto request_table;
a943cac1
ML
3978 } else {
3979 /* if we missed more than one change or our tables are not
9cfc7bd6
SE
3980 * in sync anymore -> request fresh tt data
3981 */
e17931d1 3982 if (!has_tt_init || ttvn != orig_ttvn ||
7ea7b4a1
AQ
3983 !batadv_tt_global_check_crc(orig_node, tt_vlan,
3984 tt_num_vlan)) {
a943cac1 3985request_table:
39c75a51 3986 batadv_dbg(BATADV_DBG_TT, bat_priv,
7ea7b4a1
AQ
3987 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
3988 orig_node->orig, ttvn, orig_ttvn,
3989 tt_num_changes);
a513088d 3990 batadv_send_tt_request(bat_priv, orig_node, ttvn,
7ea7b4a1
AQ
3991 tt_vlan, tt_num_vlan,
3992 full_table);
a943cac1
ML
3993 return;
3994 }
3995 }
3996}
3275e7cc 3997
c018ad3d 3998/**
7e9a8c2c 3999 * batadv_tt_global_client_is_roaming() - check if a client is marked as roaming
c018ad3d
AQ
4000 * @bat_priv: the bat priv with all the soft interface information
4001 * @addr: the mac address of the client to check
4002 * @vid: VLAN identifier
4003 *
62fe710f 4004 * Return: true if we know that the client has moved from its old originator
c018ad3d
AQ
4005 * to another one. This entry is still kept for consistency purposes and will be
4006 * deleted later by a DEL or because of timeout
3275e7cc 4007 */
56303d34 4008bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
6b5e971a 4009 u8 *addr, unsigned short vid)
3275e7cc 4010{
56303d34 4011 struct batadv_tt_global_entry *tt_global_entry;
3275e7cc
AQ
4012 bool ret = false;
4013
c018ad3d 4014 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
3275e7cc
AQ
4015 if (!tt_global_entry)
4016 goto out;
4017
c1d07431 4018 ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
5dafd8a6 4019 batadv_tt_global_entry_put(tt_global_entry);
3275e7cc
AQ
4020out:
4021 return ret;
4022}
30cfd02b 4023
7c1fd91d 4024/**
7e9a8c2c 4025 * batadv_tt_local_client_is_roaming() - tells whether the client is roaming
7c1fd91d 4026 * @bat_priv: the bat priv with all the soft interface information
c018ad3d
AQ
4027 * @addr: the mac address of the local client to query
4028 * @vid: VLAN identifier
7c1fd91d 4029 *
62fe710f 4030 * Return: true if the local client is known to be roaming (it is not served by
7c1fd91d
AQ
4031 * this node anymore) or not. If yes, the client is still present in the table
4032 * to keep the latter consistent with the node TTVN
4033 */
4034bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
6b5e971a 4035 u8 *addr, unsigned short vid)
7c1fd91d
AQ
4036{
4037 struct batadv_tt_local_entry *tt_local_entry;
4038 bool ret = false;
4039
c018ad3d 4040 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7c1fd91d
AQ
4041 if (!tt_local_entry)
4042 goto out;
4043
4044 ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
95c0db90 4045 batadv_tt_local_entry_put(tt_local_entry);
7c1fd91d
AQ
4046out:
4047 return ret;
7c1fd91d
AQ
4048}
4049
30cfd02b
AQ
4050bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
4051 struct batadv_orig_node *orig_node,
c018ad3d 4052 const unsigned char *addr,
16052789 4053 unsigned short vid)
30cfd02b 4054{
1227c9ae
SW
4055 /* ignore loop detect macs, they are not supposed to be in the tt local
4056 * data as well.
4057 */
4058 if (batadv_bla_is_loopdetect_mac(addr))
4059 return false;
4060
16052789 4061 if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
30cfd02b
AQ
4062 BATADV_TT_CLIENT_TEMP,
4063 atomic_read(&orig_node->last_ttvn)))
75ae84a4 4064 return false;
30cfd02b
AQ
4065
4066 batadv_dbg(BATADV_DBG_TT, bat_priv,
16052789 4067 "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
f7a2bd65 4068 addr, batadv_print_vid(vid), orig_node->orig);
75ae84a4
SW
4069
4070 return true;
30cfd02b 4071}
e1bf0c14 4072
a19d3d85 4073/**
7e9a8c2c 4074 * batadv_tt_local_resize_to_mtu() - resize the local translation table fit the
a19d3d85
ML
4075 * maximum packet size that can be transported through the mesh
4076 * @soft_iface: netdev struct of the mesh interface
4077 *
4078 * Remove entries older than 'timeout' and half timeout if more entries need
4079 * to be removed.
4080 */
4081void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
4082{
4083 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
4084 int packet_size_max = atomic_read(&bat_priv->packet_size_max);
4085 int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
4086 bool reduced = false;
4087
4088 spin_lock_bh(&bat_priv->tt.commit_lock);
4089
4090 while (true) {
4091 table_size = batadv_tt_local_table_transmit_size(bat_priv);
4092 if (packet_size_max >= table_size)
4093 break;
4094
4095 batadv_tt_local_purge(bat_priv, timeout);
4096 batadv_tt_local_purge_pending_clients(bat_priv);
4097
4098 timeout /= 2;
4099 reduced = true;
4100 net_ratelimited_function(batadv_info, soft_iface,
4101 "Forced to purge local tt entries to fit new maximum fragment MTU (%i)\n",
4102 packet_size_max);
4103 }
4104
4105 /* commit these changes immediately, to avoid synchronization problem
4106 * with the TTVN
4107 */
4108 if (reduced)
4109 batadv_tt_local_commit_changes_nolock(bat_priv);
4110
4111 spin_unlock_bh(&bat_priv->tt.commit_lock);
4112}
4113
e1bf0c14 4114/**
7e9a8c2c 4115 * batadv_tt_tvlv_ogm_handler_v1() - process incoming tt tvlv container
e1bf0c14
ML
4116 * @bat_priv: the bat priv with all the soft interface information
4117 * @orig: the orig_node of the ogm
4118 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
4119 * @tvlv_value: tvlv buffer containing the gateway data
4120 * @tvlv_value_len: tvlv buffer length
4121 */
4122static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
4123 struct batadv_orig_node *orig,
6b5e971a
SE
4124 u8 flags, void *tvlv_value,
4125 u16 tvlv_value_len)
e1bf0c14 4126{
7ea7b4a1
AQ
4127 struct batadv_tvlv_tt_vlan_data *tt_vlan;
4128 struct batadv_tvlv_tt_change *tt_change;
e1bf0c14 4129 struct batadv_tvlv_tt_data *tt_data;
6b5e971a 4130 u16 num_entries, num_vlan;
e1bf0c14
ML
4131
4132 if (tvlv_value_len < sizeof(*tt_data))
4133 return;
4134
4135 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4136 tvlv_value_len -= sizeof(*tt_data);
4137
7ea7b4a1
AQ
4138 num_vlan = ntohs(tt_data->num_vlan);
4139
4140 if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
4141 return;
4142
4143 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
4144 tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
4145 tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
4146
298e6e68 4147 num_entries = batadv_tt_entries(tvlv_value_len);
e1bf0c14 4148
7ea7b4a1
AQ
4149 batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
4150 num_entries, tt_data->ttvn);
e1bf0c14
ML
4151}
4152
335fbe0f 4153/**
7e9a8c2c 4154 * batadv_tt_tvlv_unicast_handler_v1() - process incoming (unicast) tt tvlv
335fbe0f
ML
4155 * container
4156 * @bat_priv: the bat priv with all the soft interface information
4157 * @src: mac address of tt tvlv sender
4158 * @dst: mac address of tt tvlv recipient
4159 * @tvlv_value: tvlv buffer containing the tt data
4160 * @tvlv_value_len: tvlv buffer length
4161 *
62fe710f 4162 * Return: NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
335fbe0f
ML
4163 * otherwise.
4164 */
4165static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
6b5e971a 4166 u8 *src, u8 *dst,
335fbe0f 4167 void *tvlv_value,
6b5e971a 4168 u16 tvlv_value_len)
335fbe0f
ML
4169{
4170 struct batadv_tvlv_tt_data *tt_data;
6b5e971a 4171 u16 tt_vlan_len, tt_num_entries;
335fbe0f
ML
4172 char tt_flag;
4173 bool ret;
4174
4175 if (tvlv_value_len < sizeof(*tt_data))
4176 return NET_RX_SUCCESS;
4177
4178 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4179 tvlv_value_len -= sizeof(*tt_data);
4180
7ea7b4a1
AQ
4181 tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
4182 tt_vlan_len *= ntohs(tt_data->num_vlan);
4183
4184 if (tvlv_value_len < tt_vlan_len)
4185 return NET_RX_SUCCESS;
4186
4187 tvlv_value_len -= tt_vlan_len;
4188 tt_num_entries = batadv_tt_entries(tvlv_value_len);
335fbe0f
ML
4189
4190 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
4191 case BATADV_TT_REQUEST:
4192 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
4193
4194 /* If this node cannot provide a TT response the tt_request is
4195 * forwarded
4196 */
4197 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
4198 if (!ret) {
4199 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4200 tt_flag = 'F';
4201 else
4202 tt_flag = '.';
4203
4204 batadv_dbg(BATADV_DBG_TT, bat_priv,
4205 "Routing TT_REQUEST to %pM [%c]\n",
4206 dst, tt_flag);
4207 /* tvlv API will re-route the packet */
4208 return NET_RX_DROP;
4209 }
4210 break;
4211 case BATADV_TT_RESPONSE:
4212 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
4213
4214 if (batadv_is_my_mac(bat_priv, dst)) {
4215 batadv_handle_tt_response(bat_priv, tt_data,
7ea7b4a1 4216 src, tt_num_entries);
335fbe0f
ML
4217 return NET_RX_SUCCESS;
4218 }
4219
4220 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4221 tt_flag = 'F';
4222 else
4223 tt_flag = '.';
4224
4225 batadv_dbg(BATADV_DBG_TT, bat_priv,
4226 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
4227
4228 /* tvlv API will re-route the packet */
4229 return NET_RX_DROP;
4230 }
4231
4232 return NET_RX_SUCCESS;
4233}
4234
122edaa0 4235/**
7e9a8c2c
SE
4236 * batadv_roam_tvlv_unicast_handler_v1() - process incoming tt roam tvlv
4237 * container
122edaa0
ML
4238 * @bat_priv: the bat priv with all the soft interface information
4239 * @src: mac address of tt tvlv sender
4240 * @dst: mac address of tt tvlv recipient
4241 * @tvlv_value: tvlv buffer containing the tt data
4242 * @tvlv_value_len: tvlv buffer length
4243 *
62fe710f 4244 * Return: NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
122edaa0
ML
4245 * otherwise.
4246 */
4247static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
6b5e971a 4248 u8 *src, u8 *dst,
122edaa0 4249 void *tvlv_value,
6b5e971a 4250 u16 tvlv_value_len)
122edaa0
ML
4251{
4252 struct batadv_tvlv_roam_adv *roaming_adv;
4253 struct batadv_orig_node *orig_node = NULL;
4254
4255 /* If this node is not the intended recipient of the
4256 * roaming advertisement the packet is forwarded
4257 * (the tvlv API will re-route the packet).
4258 */
4259 if (!batadv_is_my_mac(bat_priv, dst))
4260 return NET_RX_DROP;
4261
122edaa0
ML
4262 if (tvlv_value_len < sizeof(*roaming_adv))
4263 goto out;
4264
4265 orig_node = batadv_orig_hash_find(bat_priv, src);
4266 if (!orig_node)
4267 goto out;
4268
4269 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
4270 roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value;
4271
4272 batadv_dbg(BATADV_DBG_TT, bat_priv,
4273 "Received ROAMING_ADV from %pM (client %pM)\n",
4274 src, roaming_adv->client);
4275
4276 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
c018ad3d 4277 ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
122edaa0
ML
4278 atomic_read(&orig_node->last_ttvn) + 1);
4279
4280out:
4281 if (orig_node)
5d967310 4282 batadv_orig_node_put(orig_node);
122edaa0
ML
4283 return NET_RX_SUCCESS;
4284}
4285
e1bf0c14 4286/**
7e9a8c2c 4287 * batadv_tt_init() - initialise the translation table internals
e1bf0c14
ML
4288 * @bat_priv: the bat priv with all the soft interface information
4289 *
62fe710f 4290 * Return: 0 on success or negative error number in case of failure.
e1bf0c14
ML
4291 */
4292int batadv_tt_init(struct batadv_priv *bat_priv)
4293{
4294 int ret;
4295
0eb01568
AQ
4296 /* synchronized flags must be remote */
4297 BUILD_BUG_ON(!(BATADV_TT_SYNC_MASK & BATADV_TT_REMOTE_MASK));
4298
e1bf0c14
ML
4299 ret = batadv_tt_local_init(bat_priv);
4300 if (ret < 0)
4301 return ret;
4302
4303 ret = batadv_tt_global_init(bat_priv);
4304 if (ret < 0)
4305 return ret;
4306
4307 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
335fbe0f
ML
4308 batadv_tt_tvlv_unicast_handler_v1,
4309 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
e1bf0c14 4310
122edaa0
ML
4311 batadv_tvlv_handler_register(bat_priv, NULL,
4312 batadv_roam_tvlv_unicast_handler_v1,
4313 BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
4314
e1bf0c14
ML
4315 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
4316 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
4317 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
4318
4319 return 1;
4320}
42cb0bef
AQ
4321
4322/**
7e9a8c2c 4323 * batadv_tt_global_is_isolated() - check if a client is marked as isolated
42cb0bef
AQ
4324 * @bat_priv: the bat priv with all the soft interface information
4325 * @addr: the mac address of the client
4326 * @vid: the identifier of the VLAN where this client is connected
4327 *
62fe710f 4328 * Return: true if the client is marked with the TT_CLIENT_ISOLA flag, false
42cb0bef
AQ
4329 * otherwise
4330 */
4331bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
6b5e971a 4332 const u8 *addr, unsigned short vid)
42cb0bef
AQ
4333{
4334 struct batadv_tt_global_entry *tt;
4335 bool ret;
4336
4337 tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
4338 if (!tt)
4339 return false;
4340
4341 ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
4342
5dafd8a6 4343 batadv_tt_global_entry_put(tt);
42cb0bef
AQ
4344
4345 return ret;
4346}
86452f81
SE
4347
4348/**
7e9a8c2c 4349 * batadv_tt_cache_init() - Initialize tt memory object cache
86452f81
SE
4350 *
4351 * Return: 0 on success or negative error number in case of failure.
4352 */
4353int __init batadv_tt_cache_init(void)
4354{
4355 size_t tl_size = sizeof(struct batadv_tt_local_entry);
4356 size_t tg_size = sizeof(struct batadv_tt_global_entry);
4357 size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
4358 size_t tt_change_size = sizeof(struct batadv_tt_change_node);
4359 size_t tt_req_size = sizeof(struct batadv_tt_req_node);
4360 size_t tt_roam_size = sizeof(struct batadv_tt_roam_node);
4361
4362 batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
4363 SLAB_HWCACHE_ALIGN, NULL);
4364 if (!batadv_tl_cache)
4365 return -ENOMEM;
4366
4367 batadv_tg_cache = kmem_cache_create("batadv_tg_cache", tg_size, 0,
4368 SLAB_HWCACHE_ALIGN, NULL);
4369 if (!batadv_tg_cache)
4370 goto err_tt_tl_destroy;
4371
4372 batadv_tt_orig_cache = kmem_cache_create("batadv_tt_orig_cache",
4373 tt_orig_size, 0,
4374 SLAB_HWCACHE_ALIGN, NULL);
4375 if (!batadv_tt_orig_cache)
4376 goto err_tt_tg_destroy;
4377
4378 batadv_tt_change_cache = kmem_cache_create("batadv_tt_change_cache",
4379 tt_change_size, 0,
4380 SLAB_HWCACHE_ALIGN, NULL);
4381 if (!batadv_tt_change_cache)
4382 goto err_tt_orig_destroy;
4383
4384 batadv_tt_req_cache = kmem_cache_create("batadv_tt_req_cache",
4385 tt_req_size, 0,
4386 SLAB_HWCACHE_ALIGN, NULL);
4387 if (!batadv_tt_req_cache)
4388 goto err_tt_change_destroy;
4389
4390 batadv_tt_roam_cache = kmem_cache_create("batadv_tt_roam_cache",
4391 tt_roam_size, 0,
4392 SLAB_HWCACHE_ALIGN, NULL);
4393 if (!batadv_tt_roam_cache)
4394 goto err_tt_req_destroy;
4395
4396 return 0;
4397
4398err_tt_req_destroy:
4399 kmem_cache_destroy(batadv_tt_req_cache);
4400 batadv_tt_req_cache = NULL;
4401err_tt_change_destroy:
4402 kmem_cache_destroy(batadv_tt_change_cache);
4403 batadv_tt_change_cache = NULL;
4404err_tt_orig_destroy:
4405 kmem_cache_destroy(batadv_tt_orig_cache);
4406 batadv_tt_orig_cache = NULL;
4407err_tt_tg_destroy:
4408 kmem_cache_destroy(batadv_tg_cache);
4409 batadv_tg_cache = NULL;
4410err_tt_tl_destroy:
4411 kmem_cache_destroy(batadv_tl_cache);
4412 batadv_tl_cache = NULL;
4413
4414 return -ENOMEM;
4415}
4416
4417/**
7e9a8c2c 4418 * batadv_tt_cache_destroy() - Destroy tt memory object cache
86452f81
SE
4419 */
4420void batadv_tt_cache_destroy(void)
4421{
4422 kmem_cache_destroy(batadv_tl_cache);
4423 kmem_cache_destroy(batadv_tg_cache);
4424 kmem_cache_destroy(batadv_tt_orig_cache);
4425 kmem_cache_destroy(batadv_tt_change_cache);
4426 kmem_cache_destroy(batadv_tt_req_cache);
4427 kmem_cache_destroy(batadv_tt_roam_cache);
4428}