Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/batman-adv/originator.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
/* Copyright (C) B.A.T.M.A.N. contributors:
3
*
4
* Marek Lindner, Simon Wunderlich
5
*/
6
7
#include "originator.h"
8
#include "main.h"
9
10
#include <linux/atomic.h>
11
#include <linux/container_of.h>
12
#include <linux/err.h>
13
#include <linux/errno.h>
14
#include <linux/etherdevice.h>
15
#include <linux/gfp.h>
16
#include <linux/if_vlan.h>
17
#include <linux/jiffies.h>
18
#include <linux/kref.h>
19
#include <linux/list.h>
20
#include <linux/lockdep.h>
21
#include <linux/netdevice.h>
22
#include <linux/netlink.h>
23
#include <linux/rculist.h>
24
#include <linux/rcupdate.h>
25
#include <linux/skbuff.h>
26
#include <linux/slab.h>
27
#include <linux/spinlock.h>
28
#include <linux/stddef.h>
29
#include <linux/workqueue.h>
30
#include <uapi/linux/batadv_packet.h>
31
32
#include "distributed-arp-table.h"
33
#include "fragmentation.h"
34
#include "gateway_client.h"
35
#include "hard-interface.h"
36
#include "hash.h"
37
#include "log.h"
38
#include "multicast.h"
39
#include "netlink.h"
40
#include "network-coding.h"
41
#include "routing.h"
42
#include "translation-table.h"
43
44
/* hash class keys */
45
static struct lock_class_key batadv_orig_hash_lock_class_key;
46
47
/**
48
* batadv_orig_hash_find() - Find and return originator from orig_hash
49
* @bat_priv: the bat priv with all the mesh interface information
50
* @data: mac address of the originator
51
*
52
* Return: orig_node (with increased refcnt), NULL on errors
53
*/
54
struct batadv_orig_node *
55
batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
56
{
57
struct batadv_hashtable *hash = bat_priv->orig_hash;
58
struct hlist_head *head;
59
struct batadv_orig_node *orig_node, *orig_node_tmp = NULL;
60
int index;
61
62
if (!hash)
63
return NULL;
64
65
index = batadv_choose_orig(data, hash->size);
66
head = &hash->table[index];
67
68
rcu_read_lock();
69
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
70
if (!batadv_compare_eth(orig_node, data))
71
continue;
72
73
if (!kref_get_unless_zero(&orig_node->refcount))
74
continue;
75
76
orig_node_tmp = orig_node;
77
break;
78
}
79
rcu_read_unlock();
80
81
return orig_node_tmp;
82
}
83
84
static void batadv_purge_orig(struct work_struct *work);
85
86
/**
87
* batadv_compare_orig() - comparing function used in the originator hash table
88
* @node: node in the local table
89
* @data2: second object to compare the node to
90
*
91
* Return: true if they are the same originator
92
*/
93
bool batadv_compare_orig(const struct hlist_node *node, const void *data2)
94
{
95
const void *data1 = container_of(node, struct batadv_orig_node,
96
hash_entry);
97
98
return batadv_compare_eth(data1, data2);
99
}
100
101
/**
102
* batadv_orig_node_vlan_get() - get an orig_node_vlan object
103
* @orig_node: the originator serving the VLAN
104
* @vid: the VLAN identifier
105
*
106
* Return: the vlan object identified by vid and belonging to orig_node or NULL
107
* if it does not exist.
108
*/
109
struct batadv_orig_node_vlan *
110
batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
111
unsigned short vid)
112
{
113
struct batadv_orig_node_vlan *vlan = NULL, *tmp;
114
115
rcu_read_lock();
116
hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
117
if (tmp->vid != vid)
118
continue;
119
120
if (!kref_get_unless_zero(&tmp->refcount))
121
continue;
122
123
vlan = tmp;
124
125
break;
126
}
127
rcu_read_unlock();
128
129
return vlan;
130
}
131
132
/**
133
* batadv_vlan_id_valid() - check if vlan id is in valid batman-adv encoding
134
* @vid: the VLAN identifier
135
*
136
* Return: true when either no vlan is set or if VLAN is in correct range,
137
* false otherwise
138
*/
139
static bool batadv_vlan_id_valid(unsigned short vid)
140
{
141
unsigned short non_vlan = vid & ~(BATADV_VLAN_HAS_TAG | VLAN_VID_MASK);
142
143
if (vid == 0)
144
return true;
145
146
if (!(vid & BATADV_VLAN_HAS_TAG))
147
return false;
148
149
if (non_vlan)
150
return false;
151
152
return true;
153
}
154
155
/**
156
* batadv_orig_node_vlan_new() - search and possibly create an orig_node_vlan
157
* object
158
* @orig_node: the originator serving the VLAN
159
* @vid: the VLAN identifier
160
*
161
* Return: NULL in case of failure or the vlan object identified by vid and
162
* belonging to orig_node otherwise. The object is created and added to the list
163
* if it does not exist.
164
*
165
* The object is returned with refcounter increased by 1.
166
*/
167
struct batadv_orig_node_vlan *
168
batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
169
unsigned short vid)
170
{
171
struct batadv_orig_node_vlan *vlan;
172
173
if (!batadv_vlan_id_valid(vid))
174
return NULL;
175
176
spin_lock_bh(&orig_node->vlan_list_lock);
177
178
/* first look if an object for this vid already exists */
179
vlan = batadv_orig_node_vlan_get(orig_node, vid);
180
if (vlan)
181
goto out;
182
183
vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
184
if (!vlan)
185
goto out;
186
187
kref_init(&vlan->refcount);
188
vlan->vid = vid;
189
190
kref_get(&vlan->refcount);
191
hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list);
192
193
out:
194
spin_unlock_bh(&orig_node->vlan_list_lock);
195
196
return vlan;
197
}
198
199
/**
200
* batadv_orig_node_vlan_release() - release originator-vlan object from lists
201
* and queue for free after rcu grace period
202
* @ref: kref pointer of the originator-vlan object
203
*/
204
void batadv_orig_node_vlan_release(struct kref *ref)
205
{
206
struct batadv_orig_node_vlan *orig_vlan;
207
208
orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount);
209
210
kfree_rcu(orig_vlan, rcu);
211
}
212
213
/**
214
* batadv_originator_init() - Initialize all originator structures
215
* @bat_priv: the bat priv with all the mesh interface information
216
*
217
* Return: 0 on success or negative error number in case of failure
218
*/
219
int batadv_originator_init(struct batadv_priv *bat_priv)
220
{
221
if (bat_priv->orig_hash)
222
return 0;
223
224
bat_priv->orig_hash = batadv_hash_new(1024);
225
226
if (!bat_priv->orig_hash)
227
goto err;
228
229
batadv_hash_set_lock_class(bat_priv->orig_hash,
230
&batadv_orig_hash_lock_class_key);
231
232
INIT_DELAYED_WORK(&bat_priv->orig_work, batadv_purge_orig);
233
queue_delayed_work(batadv_event_workqueue,
234
&bat_priv->orig_work,
235
msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD));
236
237
return 0;
238
239
err:
240
return -ENOMEM;
241
}
242
243
/**
244
* batadv_neigh_ifinfo_release() - release neigh_ifinfo from lists and queue for
245
* free after rcu grace period
246
* @ref: kref pointer of the neigh_ifinfo
247
*/
248
void batadv_neigh_ifinfo_release(struct kref *ref)
249
{
250
struct batadv_neigh_ifinfo *neigh_ifinfo;
251
252
neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount);
253
254
if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
255
batadv_hardif_put(neigh_ifinfo->if_outgoing);
256
257
kfree_rcu(neigh_ifinfo, rcu);
258
}
259
260
/**
261
* batadv_hardif_neigh_release() - release hardif neigh node from lists and
262
* queue for free after rcu grace period
263
* @ref: kref pointer of the neigh_node
264
*/
265
void batadv_hardif_neigh_release(struct kref *ref)
266
{
267
struct batadv_hardif_neigh_node *hardif_neigh;
268
269
hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node,
270
refcount);
271
272
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
273
hlist_del_init_rcu(&hardif_neigh->list);
274
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
275
276
batadv_hardif_put(hardif_neigh->if_incoming);
277
kfree_rcu(hardif_neigh, rcu);
278
}
279
280
/**
281
* batadv_neigh_node_release() - release neigh_node from lists and queue for
282
* free after rcu grace period
283
* @ref: kref pointer of the neigh_node
284
*/
285
void batadv_neigh_node_release(struct kref *ref)
286
{
287
struct hlist_node *node_tmp;
288
struct batadv_neigh_node *neigh_node;
289
struct batadv_neigh_ifinfo *neigh_ifinfo;
290
291
neigh_node = container_of(ref, struct batadv_neigh_node, refcount);
292
293
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
294
&neigh_node->ifinfo_list, list) {
295
batadv_neigh_ifinfo_put(neigh_ifinfo);
296
}
297
298
batadv_hardif_neigh_put(neigh_node->hardif_neigh);
299
300
batadv_hardif_put(neigh_node->if_incoming);
301
302
kfree_rcu(neigh_node, rcu);
303
}
304
305
/**
306
* batadv_orig_router_get() - router to the originator depending on iface
307
* @orig_node: the orig node for the router
308
* @if_outgoing: the interface where the payload packet has been received or
309
* the OGM should be sent to
310
*
311
* Return: the neighbor which should be the router for this orig_node/iface.
312
*
313
* The object is returned with refcounter increased by 1.
314
*/
315
struct batadv_neigh_node *
316
batadv_orig_router_get(struct batadv_orig_node *orig_node,
317
const struct batadv_hard_iface *if_outgoing)
318
{
319
struct batadv_orig_ifinfo *orig_ifinfo;
320
struct batadv_neigh_node *router = NULL;
321
322
rcu_read_lock();
323
hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) {
324
if (orig_ifinfo->if_outgoing != if_outgoing)
325
continue;
326
327
router = rcu_dereference(orig_ifinfo->router);
328
break;
329
}
330
331
if (router && !kref_get_unless_zero(&router->refcount))
332
router = NULL;
333
334
rcu_read_unlock();
335
return router;
336
}
337
338
/**
339
* batadv_orig_to_router() - get next hop neighbor to an orig address
340
* @bat_priv: the bat priv with all the mesh interface information
341
* @orig_addr: the originator MAC address to search the best next hop router for
342
* @if_outgoing: the interface where the payload packet has been received or
343
* the OGM should be sent to
344
*
345
* Return: A neighbor node which is the best router towards the given originator
346
* address.
347
*/
348
struct batadv_neigh_node *
349
batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr,
350
struct batadv_hard_iface *if_outgoing)
351
{
352
struct batadv_neigh_node *neigh_node;
353
struct batadv_orig_node *orig_node;
354
355
orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
356
if (!orig_node)
357
return NULL;
358
359
neigh_node = batadv_find_router(bat_priv, orig_node, if_outgoing);
360
batadv_orig_node_put(orig_node);
361
362
return neigh_node;
363
}
364
365
/**
366
* batadv_orig_ifinfo_get() - find the ifinfo from an orig_node
367
* @orig_node: the orig node to be queried
368
* @if_outgoing: the interface for which the ifinfo should be acquired
369
*
370
* Return: the requested orig_ifinfo or NULL if not found.
371
*
372
* The object is returned with refcounter increased by 1.
373
*/
374
struct batadv_orig_ifinfo *
375
batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
376
struct batadv_hard_iface *if_outgoing)
377
{
378
struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL;
379
380
rcu_read_lock();
381
hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list,
382
list) {
383
if (tmp->if_outgoing != if_outgoing)
384
continue;
385
386
if (!kref_get_unless_zero(&tmp->refcount))
387
continue;
388
389
orig_ifinfo = tmp;
390
break;
391
}
392
rcu_read_unlock();
393
394
return orig_ifinfo;
395
}
396
397
/**
398
* batadv_orig_ifinfo_new() - search and possibly create an orig_ifinfo object
399
* @orig_node: the orig node to be queried
400
* @if_outgoing: the interface for which the ifinfo should be acquired
401
*
402
* Return: NULL in case of failure or the orig_ifinfo object for the if_outgoing
403
* interface otherwise. The object is created and added to the list
404
* if it does not exist.
405
*
406
* The object is returned with refcounter increased by 1.
407
*/
408
struct batadv_orig_ifinfo *
409
batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
410
struct batadv_hard_iface *if_outgoing)
411
{
412
struct batadv_orig_ifinfo *orig_ifinfo;
413
unsigned long reset_time;
414
415
spin_lock_bh(&orig_node->neigh_list_lock);
416
417
orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing);
418
if (orig_ifinfo)
419
goto out;
420
421
orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC);
422
if (!orig_ifinfo)
423
goto out;
424
425
if (if_outgoing != BATADV_IF_DEFAULT)
426
kref_get(&if_outgoing->refcount);
427
428
reset_time = jiffies - 1;
429
reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
430
orig_ifinfo->batman_seqno_reset = reset_time;
431
orig_ifinfo->if_outgoing = if_outgoing;
432
INIT_HLIST_NODE(&orig_ifinfo->list);
433
kref_init(&orig_ifinfo->refcount);
434
435
kref_get(&orig_ifinfo->refcount);
436
hlist_add_head_rcu(&orig_ifinfo->list,
437
&orig_node->ifinfo_list);
438
out:
439
spin_unlock_bh(&orig_node->neigh_list_lock);
440
return orig_ifinfo;
441
}
442
443
/**
444
* batadv_neigh_ifinfo_get() - find the ifinfo from an neigh_node
445
* @neigh: the neigh node to be queried
446
* @if_outgoing: the interface for which the ifinfo should be acquired
447
*
448
* The object is returned with refcounter increased by 1.
449
*
450
* Return: the requested neigh_ifinfo or NULL if not found
451
*/
452
struct batadv_neigh_ifinfo *
453
batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
454
struct batadv_hard_iface *if_outgoing)
455
{
456
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL,
457
*tmp_neigh_ifinfo;
458
459
rcu_read_lock();
460
hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list,
461
list) {
462
if (tmp_neigh_ifinfo->if_outgoing != if_outgoing)
463
continue;
464
465
if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount))
466
continue;
467
468
neigh_ifinfo = tmp_neigh_ifinfo;
469
break;
470
}
471
rcu_read_unlock();
472
473
return neigh_ifinfo;
474
}
475
476
/**
477
* batadv_neigh_ifinfo_new() - search and possibly create an neigh_ifinfo object
478
* @neigh: the neigh node to be queried
479
* @if_outgoing: the interface for which the ifinfo should be acquired
480
*
481
* Return: NULL in case of failure or the neigh_ifinfo object for the
482
* if_outgoing interface otherwise. The object is created and added to the list
483
* if it does not exist.
484
*
485
* The object is returned with refcounter increased by 1.
486
*/
487
struct batadv_neigh_ifinfo *
488
batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
489
struct batadv_hard_iface *if_outgoing)
490
{
491
struct batadv_neigh_ifinfo *neigh_ifinfo;
492
493
spin_lock_bh(&neigh->ifinfo_lock);
494
495
neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing);
496
if (neigh_ifinfo)
497
goto out;
498
499
neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC);
500
if (!neigh_ifinfo)
501
goto out;
502
503
if (if_outgoing)
504
kref_get(&if_outgoing->refcount);
505
506
INIT_HLIST_NODE(&neigh_ifinfo->list);
507
kref_init(&neigh_ifinfo->refcount);
508
neigh_ifinfo->if_outgoing = if_outgoing;
509
510
kref_get(&neigh_ifinfo->refcount);
511
hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list);
512
513
out:
514
spin_unlock_bh(&neigh->ifinfo_lock);
515
516
return neigh_ifinfo;
517
}
518
519
/**
520
* batadv_neigh_node_get() - retrieve a neighbour from the list
521
* @orig_node: originator which the neighbour belongs to
522
* @hard_iface: the interface where this neighbour is connected to
523
* @addr: the address of the neighbour
524
*
525
* Looks for and possibly returns a neighbour belonging to this originator list
526
* which is connected through the provided hard interface.
527
*
528
* Return: neighbor when found. Otherwise NULL
529
*/
530
static struct batadv_neigh_node *
531
batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
532
const struct batadv_hard_iface *hard_iface,
533
const u8 *addr)
534
{
535
struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
536
537
rcu_read_lock();
538
hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
539
if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
540
continue;
541
542
if (tmp_neigh_node->if_incoming != hard_iface)
543
continue;
544
545
if (!kref_get_unless_zero(&tmp_neigh_node->refcount))
546
continue;
547
548
res = tmp_neigh_node;
549
break;
550
}
551
rcu_read_unlock();
552
553
return res;
554
}
555
556
/**
557
* batadv_hardif_neigh_create() - create a hardif neighbour node
558
* @hard_iface: the interface this neighbour is connected to
559
* @neigh_addr: the interface address of the neighbour to retrieve
560
* @orig_node: originator object representing the neighbour
561
*
562
* Return: the hardif neighbour node if found or created or NULL otherwise.
563
*/
564
static struct batadv_hardif_neigh_node *
565
batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
566
const u8 *neigh_addr,
567
struct batadv_orig_node *orig_node)
568
{
569
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
570
struct batadv_hardif_neigh_node *hardif_neigh;
571
572
spin_lock_bh(&hard_iface->neigh_list_lock);
573
574
/* check if neighbor hasn't been added in the meantime */
575
hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
576
if (hardif_neigh)
577
goto out;
578
579
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC);
580
if (!hardif_neigh)
581
goto out;
582
583
kref_get(&hard_iface->refcount);
584
INIT_HLIST_NODE(&hardif_neigh->list);
585
ether_addr_copy(hardif_neigh->addr, neigh_addr);
586
ether_addr_copy(hardif_neigh->orig, orig_node->orig);
587
hardif_neigh->if_incoming = hard_iface;
588
hardif_neigh->last_seen = jiffies;
589
590
kref_init(&hardif_neigh->refcount);
591
592
if (bat_priv->algo_ops->neigh.hardif_init)
593
bat_priv->algo_ops->neigh.hardif_init(hardif_neigh);
594
595
hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list);
596
597
out:
598
spin_unlock_bh(&hard_iface->neigh_list_lock);
599
return hardif_neigh;
600
}
601
602
/**
603
* batadv_hardif_neigh_get_or_create() - retrieve or create a hardif neighbour
604
* node
605
* @hard_iface: the interface this neighbour is connected to
606
* @neigh_addr: the interface address of the neighbour to retrieve
607
* @orig_node: originator object representing the neighbour
608
*
609
* Return: the hardif neighbour node if found or created or NULL otherwise.
610
*/
611
static struct batadv_hardif_neigh_node *
612
batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface,
613
const u8 *neigh_addr,
614
struct batadv_orig_node *orig_node)
615
{
616
struct batadv_hardif_neigh_node *hardif_neigh;
617
618
/* first check without locking to avoid the overhead */
619
hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
620
if (hardif_neigh)
621
return hardif_neigh;
622
623
return batadv_hardif_neigh_create(hard_iface, neigh_addr, orig_node);
624
}
625
626
/**
627
* batadv_hardif_neigh_get() - retrieve a hardif neighbour from the list
628
* @hard_iface: the interface where this neighbour is connected to
629
* @neigh_addr: the address of the neighbour
630
*
631
* Looks for and possibly returns a neighbour belonging to this hard interface.
632
*
633
* Return: neighbor when found. Otherwise NULL
634
*/
635
struct batadv_hardif_neigh_node *
636
batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
637
const u8 *neigh_addr)
638
{
639
struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL;
640
641
rcu_read_lock();
642
hlist_for_each_entry_rcu(tmp_hardif_neigh,
643
&hard_iface->neigh_list, list) {
644
if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr))
645
continue;
646
647
if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount))
648
continue;
649
650
hardif_neigh = tmp_hardif_neigh;
651
break;
652
}
653
rcu_read_unlock();
654
655
return hardif_neigh;
656
}
657
658
/**
659
* batadv_neigh_node_create() - create a neigh node object
660
* @orig_node: originator object representing the neighbour
661
* @hard_iface: the interface where the neighbour is connected to
662
* @neigh_addr: the mac address of the neighbour interface
663
*
664
* Allocates a new neigh_node object and initialises all the generic fields.
665
*
666
* Return: the neighbour node if found or created or NULL otherwise.
667
*/
668
static struct batadv_neigh_node *
669
batadv_neigh_node_create(struct batadv_orig_node *orig_node,
670
struct batadv_hard_iface *hard_iface,
671
const u8 *neigh_addr)
672
{
673
struct batadv_neigh_node *neigh_node;
674
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
675
676
spin_lock_bh(&orig_node->neigh_list_lock);
677
678
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
679
if (neigh_node)
680
goto out;
681
682
hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface,
683
neigh_addr, orig_node);
684
if (!hardif_neigh)
685
goto out;
686
687
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
688
if (!neigh_node)
689
goto out;
690
691
INIT_HLIST_NODE(&neigh_node->list);
692
INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
693
spin_lock_init(&neigh_node->ifinfo_lock);
694
695
kref_get(&hard_iface->refcount);
696
ether_addr_copy(neigh_node->addr, neigh_addr);
697
neigh_node->if_incoming = hard_iface;
698
neigh_node->orig_node = orig_node;
699
neigh_node->last_seen = jiffies;
700
701
/* increment unique neighbor refcount */
702
kref_get(&hardif_neigh->refcount);
703
neigh_node->hardif_neigh = hardif_neigh;
704
705
/* extra reference for return */
706
kref_init(&neigh_node->refcount);
707
708
kref_get(&neigh_node->refcount);
709
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
710
711
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
712
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
713
neigh_addr, orig_node->orig, hard_iface->net_dev->name);
714
715
out:
716
spin_unlock_bh(&orig_node->neigh_list_lock);
717
718
batadv_hardif_neigh_put(hardif_neigh);
719
return neigh_node;
720
}
721
722
/**
723
* batadv_neigh_node_get_or_create() - retrieve or create a neigh node object
724
* @orig_node: originator object representing the neighbour
725
* @hard_iface: the interface where the neighbour is connected to
726
* @neigh_addr: the mac address of the neighbour interface
727
*
728
* Return: the neighbour node if found or created or NULL otherwise.
729
*/
730
struct batadv_neigh_node *
731
batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
732
struct batadv_hard_iface *hard_iface,
733
const u8 *neigh_addr)
734
{
735
struct batadv_neigh_node *neigh_node;
736
737
/* first check without locking to avoid the overhead */
738
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
739
if (neigh_node)
740
return neigh_node;
741
742
return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr);
743
}
744
745
/**
746
* batadv_hardif_neigh_dump() - Dump to netlink the neighbor infos for a
747
* specific outgoing interface
748
* @msg: message to dump into
749
* @cb: parameters for the dump
750
*
751
* Return: 0 or error value
752
*/
753
int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
754
{
755
struct batadv_hard_iface *primary_if, *hard_iface;
756
struct net_device *mesh_iface;
757
struct batadv_priv *bat_priv;
758
int ret;
759
760
mesh_iface = batadv_netlink_get_meshif(cb);
761
if (IS_ERR(mesh_iface))
762
return PTR_ERR(mesh_iface);
763
764
bat_priv = netdev_priv(mesh_iface);
765
766
primary_if = batadv_primary_if_get_selected(bat_priv);
767
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
768
ret = -ENOENT;
769
goto out_put_mesh_iface;
770
}
771
772
hard_iface = batadv_netlink_get_hardif(bat_priv, cb);
773
if (IS_ERR(hard_iface) && PTR_ERR(hard_iface) != -ENONET) {
774
ret = PTR_ERR(hard_iface);
775
goto out_put_primary_if;
776
} else if (IS_ERR(hard_iface)) {
777
/* => PTR_ERR(hard_iface) == -ENONET
778
* => no hard-iface given, ok
779
*/
780
hard_iface = BATADV_IF_DEFAULT;
781
}
782
783
if (!bat_priv->algo_ops->neigh.dump) {
784
ret = -EOPNOTSUPP;
785
goto out_put_hard_iface;
786
}
787
788
bat_priv->algo_ops->neigh.dump(msg, cb, bat_priv, hard_iface);
789
790
ret = msg->len;
791
792
out_put_hard_iface:
793
batadv_hardif_put(hard_iface);
794
out_put_primary_if:
795
batadv_hardif_put(primary_if);
796
out_put_mesh_iface:
797
dev_put(mesh_iface);
798
799
return ret;
800
}
801
802
/**
803
* batadv_orig_ifinfo_release() - release orig_ifinfo from lists and queue for
804
* free after rcu grace period
805
* @ref: kref pointer of the orig_ifinfo
806
*/
807
void batadv_orig_ifinfo_release(struct kref *ref)
808
{
809
struct batadv_orig_ifinfo *orig_ifinfo;
810
struct batadv_neigh_node *router;
811
812
orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount);
813
814
if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
815
batadv_hardif_put(orig_ifinfo->if_outgoing);
816
817
/* this is the last reference to this object */
818
router = rcu_dereference_protected(orig_ifinfo->router, true);
819
batadv_neigh_node_put(router);
820
821
kfree_rcu(orig_ifinfo, rcu);
822
}
823
824
/**
825
* batadv_orig_node_free_rcu() - free the orig_node
826
* @rcu: rcu pointer of the orig_node
827
*/
828
static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
829
{
830
struct batadv_orig_node *orig_node;
831
832
orig_node = container_of(rcu, struct batadv_orig_node, rcu);
833
834
batadv_mcast_purge_orig(orig_node);
835
836
batadv_frag_purge_orig(orig_node, NULL);
837
838
kfree(orig_node->tt_buff);
839
kfree(orig_node);
840
}
841
842
/**
843
* batadv_orig_node_release() - release orig_node from lists and queue for
844
* free after rcu grace period
845
* @ref: kref pointer of the orig_node
846
*/
847
void batadv_orig_node_release(struct kref *ref)
848
{
849
struct hlist_node *node_tmp;
850
struct batadv_neigh_node *neigh_node;
851
struct batadv_orig_node *orig_node;
852
struct batadv_orig_ifinfo *orig_ifinfo;
853
struct batadv_orig_node_vlan *vlan;
854
struct batadv_orig_ifinfo *last_candidate;
855
856
orig_node = container_of(ref, struct batadv_orig_node, refcount);
857
858
spin_lock_bh(&orig_node->neigh_list_lock);
859
860
/* for all neighbors towards this originator ... */
861
hlist_for_each_entry_safe(neigh_node, node_tmp,
862
&orig_node->neigh_list, list) {
863
hlist_del_rcu(&neigh_node->list);
864
batadv_neigh_node_put(neigh_node);
865
}
866
867
hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
868
&orig_node->ifinfo_list, list) {
869
hlist_del_rcu(&orig_ifinfo->list);
870
batadv_orig_ifinfo_put(orig_ifinfo);
871
}
872
873
last_candidate = orig_node->last_bonding_candidate;
874
orig_node->last_bonding_candidate = NULL;
875
spin_unlock_bh(&orig_node->neigh_list_lock);
876
877
batadv_orig_ifinfo_put(last_candidate);
878
879
spin_lock_bh(&orig_node->vlan_list_lock);
880
hlist_for_each_entry_safe(vlan, node_tmp, &orig_node->vlan_list, list) {
881
hlist_del_rcu(&vlan->list);
882
batadv_orig_node_vlan_put(vlan);
883
}
884
spin_unlock_bh(&orig_node->vlan_list_lock);
885
886
/* Free nc_nodes */
887
batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
888
889
call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
890
}
891
892
/**
893
* batadv_originator_free() - Free all originator structures
894
* @bat_priv: the bat priv with all the mesh interface information
895
*/
896
void batadv_originator_free(struct batadv_priv *bat_priv)
897
{
898
struct batadv_hashtable *hash = bat_priv->orig_hash;
899
struct hlist_node *node_tmp;
900
struct hlist_head *head;
901
spinlock_t *list_lock; /* spinlock to protect write access */
902
struct batadv_orig_node *orig_node;
903
u32 i;
904
905
if (!hash)
906
return;
907
908
cancel_delayed_work_sync(&bat_priv->orig_work);
909
910
bat_priv->orig_hash = NULL;
911
912
for (i = 0; i < hash->size; i++) {
913
head = &hash->table[i];
914
list_lock = &hash->list_locks[i];
915
916
spin_lock_bh(list_lock);
917
hlist_for_each_entry_safe(orig_node, node_tmp,
918
head, hash_entry) {
919
hlist_del_rcu(&orig_node->hash_entry);
920
batadv_orig_node_put(orig_node);
921
}
922
spin_unlock_bh(list_lock);
923
}
924
925
batadv_hash_destroy(hash);
926
}
927
928
/**
929
* batadv_orig_node_new() - creates a new orig_node
930
* @bat_priv: the bat priv with all the mesh interface information
931
* @addr: the mac address of the originator
932
*
933
* Creates a new originator object and initialises all the generic fields.
934
* The new object is not added to the originator list.
935
*
936
* Return: the newly created object or NULL on failure.
937
*/
938
struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
939
const u8 *addr)
940
{
941
struct batadv_orig_node *orig_node;
942
struct batadv_orig_node_vlan *vlan;
943
unsigned long reset_time;
944
int i;
945
946
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
947
"Creating new originator: %pM\n", addr);
948
949
orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC);
950
if (!orig_node)
951
return NULL;
952
953
INIT_HLIST_HEAD(&orig_node->neigh_list);
954
INIT_HLIST_HEAD(&orig_node->vlan_list);
955
INIT_HLIST_HEAD(&orig_node->ifinfo_list);
956
spin_lock_init(&orig_node->bcast_seqno_lock);
957
spin_lock_init(&orig_node->neigh_list_lock);
958
spin_lock_init(&orig_node->tt_buff_lock);
959
spin_lock_init(&orig_node->tt_lock);
960
spin_lock_init(&orig_node->vlan_list_lock);
961
962
batadv_nc_init_orig(orig_node);
963
964
/* extra reference for return */
965
kref_init(&orig_node->refcount);
966
967
orig_node->bat_priv = bat_priv;
968
ether_addr_copy(orig_node->orig, addr);
969
batadv_dat_init_orig_node_addr(orig_node);
970
atomic_set(&orig_node->last_ttvn, 0);
971
orig_node->tt_buff = NULL;
972
orig_node->tt_buff_len = 0;
973
orig_node->last_seen = jiffies;
974
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
975
orig_node->bcast_seqno_reset = reset_time;
976
977
#ifdef CONFIG_BATMAN_ADV_MCAST
978
orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4;
979
orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6;
980
orig_node->mcast_flags |= BATADV_MCAST_HAVE_MC_PTYPE_CAPA;
981
INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node);
982
INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node);
983
INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node);
984
spin_lock_init(&orig_node->mcast_handler_lock);
985
#endif
986
987
/* create a vlan object for the "untagged" LAN */
988
vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
989
if (!vlan)
990
goto free_orig_node;
991
/* batadv_orig_node_vlan_new() increases the refcounter.
992
* Immediately release vlan since it is not needed anymore in this
993
* context
994
*/
995
batadv_orig_node_vlan_put(vlan);
996
997
for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
998
INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list);
999
spin_lock_init(&orig_node->fragments[i].lock);
1000
orig_node->fragments[i].size = 0;
1001
}
1002
1003
return orig_node;
1004
free_orig_node:
1005
kfree(orig_node);
1006
return NULL;
1007
}
1008
1009
/**
1010
* batadv_purge_neigh_ifinfo() - purge obsolete ifinfo entries from neighbor
1011
* @bat_priv: the bat priv with all the mesh interface information
1012
* @neigh: orig node which is to be checked
1013
*/
1014
static void
1015
batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
1016
struct batadv_neigh_node *neigh)
1017
{
1018
struct batadv_neigh_ifinfo *neigh_ifinfo;
1019
struct batadv_hard_iface *if_outgoing;
1020
struct hlist_node *node_tmp;
1021
1022
spin_lock_bh(&neigh->ifinfo_lock);
1023
1024
/* for all ifinfo objects for this neighinator */
1025
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
1026
&neigh->ifinfo_list, list) {
1027
if_outgoing = neigh_ifinfo->if_outgoing;
1028
1029
/* always keep the default interface */
1030
if (if_outgoing == BATADV_IF_DEFAULT)
1031
continue;
1032
1033
/* don't purge if the interface is not (going) down */
1034
if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
1035
if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
1036
if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
1037
continue;
1038
1039
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1040
"neighbor/ifinfo purge: neighbor %pM, iface: %s\n",
1041
neigh->addr, if_outgoing->net_dev->name);
1042
1043
hlist_del_rcu(&neigh_ifinfo->list);
1044
batadv_neigh_ifinfo_put(neigh_ifinfo);
1045
}
1046
1047
spin_unlock_bh(&neigh->ifinfo_lock);
1048
}
1049
1050
/**
1051
* batadv_purge_orig_ifinfo() - purge obsolete ifinfo entries from originator
1052
* @bat_priv: the bat priv with all the mesh interface information
1053
* @orig_node: orig node which is to be checked
1054
*
1055
* Return: true if any ifinfo entry was purged, false otherwise.
1056
*/
1057
static bool
1058
batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
1059
struct batadv_orig_node *orig_node)
1060
{
1061
struct batadv_orig_ifinfo *orig_ifinfo;
1062
struct batadv_hard_iface *if_outgoing;
1063
struct hlist_node *node_tmp;
1064
bool ifinfo_purged = false;
1065
1066
spin_lock_bh(&orig_node->neigh_list_lock);
1067
1068
/* for all ifinfo objects for this originator */
1069
hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
1070
&orig_node->ifinfo_list, list) {
1071
if_outgoing = orig_ifinfo->if_outgoing;
1072
1073
/* always keep the default interface */
1074
if (if_outgoing == BATADV_IF_DEFAULT)
1075
continue;
1076
1077
/* don't purge if the interface is not (going) down */
1078
if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
1079
if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
1080
if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
1081
continue;
1082
1083
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1084
"router/ifinfo purge: originator %pM, iface: %s\n",
1085
orig_node->orig, if_outgoing->net_dev->name);
1086
1087
ifinfo_purged = true;
1088
1089
hlist_del_rcu(&orig_ifinfo->list);
1090
batadv_orig_ifinfo_put(orig_ifinfo);
1091
if (orig_node->last_bonding_candidate == orig_ifinfo) {
1092
orig_node->last_bonding_candidate = NULL;
1093
batadv_orig_ifinfo_put(orig_ifinfo);
1094
}
1095
}
1096
1097
spin_unlock_bh(&orig_node->neigh_list_lock);
1098
1099
return ifinfo_purged;
1100
}
1101
1102
/**
1103
* batadv_purge_orig_neighbors() - purges neighbors from originator
1104
* @bat_priv: the bat priv with all the mesh interface information
1105
* @orig_node: orig node which is to be checked
1106
*
1107
* Return: true if any neighbor was purged, false otherwise
1108
*/
1109
static bool
1110
batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
1111
struct batadv_orig_node *orig_node)
1112
{
1113
struct hlist_node *node_tmp;
1114
struct batadv_neigh_node *neigh_node;
1115
bool neigh_purged = false;
1116
unsigned long last_seen;
1117
struct batadv_hard_iface *if_incoming;
1118
1119
spin_lock_bh(&orig_node->neigh_list_lock);
1120
1121
/* for all neighbors towards this originator ... */
1122
hlist_for_each_entry_safe(neigh_node, node_tmp,
1123
&orig_node->neigh_list, list) {
1124
last_seen = neigh_node->last_seen;
1125
if_incoming = neigh_node->if_incoming;
1126
1127
if (batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT) ||
1128
if_incoming->if_status == BATADV_IF_INACTIVE ||
1129
if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
1130
if_incoming->if_status == BATADV_IF_TO_BE_REMOVED) {
1131
if (if_incoming->if_status == BATADV_IF_INACTIVE ||
1132
if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
1133
if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)
1134
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1135
"neighbor purge: originator %pM, neighbor: %pM, iface: %s\n",
1136
orig_node->orig, neigh_node->addr,
1137
if_incoming->net_dev->name);
1138
else
1139
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1140
"neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n",
1141
orig_node->orig, neigh_node->addr,
1142
jiffies_to_msecs(last_seen));
1143
1144
neigh_purged = true;
1145
1146
hlist_del_rcu(&neigh_node->list);
1147
batadv_neigh_node_put(neigh_node);
1148
} else {
1149
/* only necessary if not the whole neighbor is to be
1150
* deleted, but some interface has been removed.
1151
*/
1152
batadv_purge_neigh_ifinfo(bat_priv, neigh_node);
1153
}
1154
}
1155
1156
spin_unlock_bh(&orig_node->neigh_list_lock);
1157
return neigh_purged;
1158
}
1159
1160
/**
1161
* batadv_find_best_neighbor() - finds the best neighbor after purging
1162
* @bat_priv: the bat priv with all the mesh interface information
1163
* @orig_node: orig node which is to be checked
1164
* @if_outgoing: the interface for which the metric should be compared
1165
*
1166
* Return: the current best neighbor, with refcount increased.
1167
*/
1168
static struct batadv_neigh_node *
1169
batadv_find_best_neighbor(struct batadv_priv *bat_priv,
1170
struct batadv_orig_node *orig_node,
1171
struct batadv_hard_iface *if_outgoing)
1172
{
1173
struct batadv_neigh_node *best = NULL, *neigh;
1174
struct batadv_algo_ops *bao = bat_priv->algo_ops;
1175
1176
rcu_read_lock();
1177
hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) {
1178
if (best && (bao->neigh.cmp(neigh, if_outgoing, best,
1179
if_outgoing) <= 0))
1180
continue;
1181
1182
if (!kref_get_unless_zero(&neigh->refcount))
1183
continue;
1184
1185
batadv_neigh_node_put(best);
1186
1187
best = neigh;
1188
}
1189
rcu_read_unlock();
1190
1191
return best;
1192
}
1193
1194
/**
1195
* batadv_purge_orig_node() - purges obsolete information from an orig_node
1196
* @bat_priv: the bat priv with all the mesh interface information
1197
* @orig_node: orig node which is to be checked
1198
*
1199
* This function checks if the orig_node or substructures of it have become
1200
* obsolete, and purges this information if that's the case.
1201
*
1202
* Return: true if the orig_node is to be removed, false otherwise.
1203
*/
1204
static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
1205
struct batadv_orig_node *orig_node)
1206
{
1207
struct batadv_neigh_node *best_neigh_node;
1208
struct batadv_hard_iface *hard_iface;
1209
bool changed_ifinfo, changed_neigh;
1210
struct list_head *iter;
1211
1212
if (batadv_has_timed_out(orig_node->last_seen,
1213
2 * BATADV_PURGE_TIMEOUT)) {
1214
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1215
"Originator timeout: originator %pM, last_seen %u\n",
1216
orig_node->orig,
1217
jiffies_to_msecs(orig_node->last_seen));
1218
return true;
1219
}
1220
changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node);
1221
changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node);
1222
1223
if (!changed_ifinfo && !changed_neigh)
1224
return false;
1225
1226
/* first for NULL ... */
1227
best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node,
1228
BATADV_IF_DEFAULT);
1229
batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT,
1230
best_neigh_node);
1231
batadv_neigh_node_put(best_neigh_node);
1232
1233
/* ... then for all other interfaces. */
1234
rcu_read_lock();
1235
netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) {
1236
if (hard_iface->if_status != BATADV_IF_ACTIVE)
1237
continue;
1238
1239
if (!kref_get_unless_zero(&hard_iface->refcount))
1240
continue;
1241
1242
best_neigh_node = batadv_find_best_neighbor(bat_priv,
1243
orig_node,
1244
hard_iface);
1245
batadv_update_route(bat_priv, orig_node, hard_iface,
1246
best_neigh_node);
1247
batadv_neigh_node_put(best_neigh_node);
1248
1249
batadv_hardif_put(hard_iface);
1250
}
1251
rcu_read_unlock();
1252
1253
return false;
1254
}
1255
1256
/**
1257
* batadv_purge_orig_ref() - Purge all outdated originators
1258
* @bat_priv: the bat priv with all the mesh interface information
1259
*/
1260
void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
1261
{
1262
struct batadv_hashtable *hash = bat_priv->orig_hash;
1263
struct hlist_node *node_tmp;
1264
struct hlist_head *head;
1265
spinlock_t *list_lock; /* spinlock to protect write access */
1266
struct batadv_orig_node *orig_node;
1267
u32 i;
1268
1269
if (!hash)
1270
return;
1271
1272
/* for all origins... */
1273
for (i = 0; i < hash->size; i++) {
1274
head = &hash->table[i];
1275
if (hlist_empty(head))
1276
continue;
1277
list_lock = &hash->list_locks[i];
1278
1279
spin_lock_bh(list_lock);
1280
hlist_for_each_entry_safe(orig_node, node_tmp,
1281
head, hash_entry) {
1282
if (batadv_purge_orig_node(bat_priv, orig_node)) {
1283
batadv_gw_node_delete(bat_priv, orig_node);
1284
hlist_del_rcu(&orig_node->hash_entry);
1285
batadv_tt_global_del_orig(orig_node->bat_priv,
1286
orig_node, -1,
1287
"originator timed out");
1288
batadv_orig_node_put(orig_node);
1289
continue;
1290
}
1291
1292
batadv_frag_purge_orig(orig_node,
1293
batadv_frag_check_entry);
1294
}
1295
spin_unlock_bh(list_lock);
1296
}
1297
1298
batadv_gw_election(bat_priv);
1299
}
1300
1301
static void batadv_purge_orig(struct work_struct *work)
1302
{
1303
struct delayed_work *delayed_work;
1304
struct batadv_priv *bat_priv;
1305
1306
delayed_work = to_delayed_work(work);
1307
bat_priv = container_of(delayed_work, struct batadv_priv, orig_work);
1308
batadv_purge_orig_ref(bat_priv);
1309
queue_delayed_work(batadv_event_workqueue,
1310
&bat_priv->orig_work,
1311
msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD));
1312
}
1313
1314
/**
1315
* batadv_orig_dump() - Dump to netlink the originator infos for a specific
1316
* outgoing interface
1317
* @msg: message to dump into
1318
* @cb: parameters for the dump
1319
*
1320
* Return: 0 or error value
1321
*/
1322
int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
1323
{
1324
struct batadv_hard_iface *primary_if, *hard_iface;
1325
struct net_device *mesh_iface;
1326
struct batadv_priv *bat_priv;
1327
int ret;
1328
1329
mesh_iface = batadv_netlink_get_meshif(cb);
1330
if (IS_ERR(mesh_iface))
1331
return PTR_ERR(mesh_iface);
1332
1333
bat_priv = netdev_priv(mesh_iface);
1334
1335
primary_if = batadv_primary_if_get_selected(bat_priv);
1336
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1337
ret = -ENOENT;
1338
goto out_put_mesh_iface;
1339
}
1340
1341
hard_iface = batadv_netlink_get_hardif(bat_priv, cb);
1342
if (IS_ERR(hard_iface) && PTR_ERR(hard_iface) != -ENONET) {
1343
ret = PTR_ERR(hard_iface);
1344
goto out_put_primary_if;
1345
} else if (IS_ERR(hard_iface)) {
1346
/* => PTR_ERR(hard_iface) == -ENONET
1347
* => no hard-iface given, ok
1348
*/
1349
hard_iface = BATADV_IF_DEFAULT;
1350
}
1351
1352
if (!bat_priv->algo_ops->orig.dump) {
1353
ret = -EOPNOTSUPP;
1354
goto out_put_hard_iface;
1355
}
1356
1357
bat_priv->algo_ops->orig.dump(msg, cb, bat_priv, hard_iface);
1358
1359
ret = msg->len;
1360
1361
out_put_hard_iface:
1362
batadv_hardif_put(hard_iface);
1363
out_put_primary_if:
1364
batadv_hardif_put(primary_if);
1365
out_put_mesh_iface:
1366
dev_put(mesh_iface);
1367
1368
return ret;
1369
}
1370
1371