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