Blame view
net/batman-adv/originator.c
42.8 KB
0046b0402 batman-adv: updat... |
1 |
/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: |
c6c8fea29 net: Add batman-a... |
2 3 4 5 6 7 8 9 10 11 12 13 14 |
* * Marek Lindner, Simon Wunderlich * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License |
ebf38fb7a batman-adv: remov... |
15 |
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
c6c8fea29 net: Add batman-a... |
16 |
*/ |
1e2c2a4fe batman-adv: Add r... |
17 |
#include "originator.h" |
c6c8fea29 net: Add batman-a... |
18 |
#include "main.h" |
1e2c2a4fe batman-adv: Add r... |
19 |
|
7c1243911 batman-adv: Conve... |
20 |
#include <linux/atomic.h> |
1e2c2a4fe batman-adv: Add r... |
21 22 23 24 25 |
#include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/fs.h> #include <linux/jiffies.h> #include <linux/kernel.h> |
90f564dff batman-adv: Conve... |
26 |
#include <linux/kref.h> |
1e2c2a4fe batman-adv: Add r... |
27 28 29 |
#include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> |
85cf8c859 batman-adv: netli... |
30 |
#include <linux/netlink.h> |
d0fa4f3f5 batman-adv: conve... |
31 |
#include <linux/rculist.h> |
1e2c2a4fe batman-adv: Add r... |
32 |
#include <linux/seq_file.h> |
85cf8c859 batman-adv: netli... |
33 |
#include <linux/skbuff.h> |
1e2c2a4fe batman-adv: Add r... |
34 35 36 |
#include <linux/slab.h> #include <linux/spinlock.h> #include <linux/workqueue.h> |
85cf8c859 batman-adv: netli... |
37 38 |
#include <net/sock.h> #include <uapi/linux/batman_adv.h> |
1e2c2a4fe batman-adv: Add r... |
39 |
|
01d350d14 batman-adv: move ... |
40 |
#include "bat_algo.h" |
785ea1144 batman-adv: Distr... |
41 |
#include "distributed-arp-table.h" |
1e2c2a4fe batman-adv: Add r... |
42 |
#include "fragmentation.h" |
c6c8fea29 net: Add batman-a... |
43 44 |
#include "gateway_client.h" #include "hard-interface.h" |
1e2c2a4fe batman-adv: Add r... |
45 |
#include "hash.h" |
ba412080f batman-adv: Conso... |
46 |
#include "log.h" |
60432d756 batman-adv: Annou... |
47 |
#include "multicast.h" |
85cf8c859 batman-adv: netli... |
48 |
#include "netlink.h" |
1e2c2a4fe batman-adv: Add r... |
49 50 |
#include "network-coding.h" #include "routing.h" |
85cf8c859 batman-adv: netli... |
51 |
#include "soft-interface.h" |
1e2c2a4fe batman-adv: Add r... |
52 |
#include "translation-table.h" |
c6c8fea29 net: Add batman-a... |
53 |
|
dec05074b batman-adv: Initi... |
54 55 |
/* hash class keys */ static struct lock_class_key batadv_orig_hash_lock_class_key; |
03fc7f863 batman-adv: Prefi... |
56 |
static void batadv_purge_orig(struct work_struct *work); |
c6c8fea29 net: Add batman-a... |
57 |
|
62fe710f6 batman-adv: Fix k... |
58 |
/** |
7afcbbef6 batman-adv: Fix k... |
59 60 61 |
* batadv_compare_orig - comparing function used in the originator hash table * @node: node in the local table * @data2: second object to compare the node to |
62fe710f6 batman-adv: Fix k... |
62 |
* |
4b426b108 batman-adv: Use b... |
63 |
* Return: true if they are the same originator |
62fe710f6 batman-adv: Fix k... |
64 |
*/ |
4b426b108 batman-adv: Use b... |
65 |
bool batadv_compare_orig(const struct hlist_node *node, const void *data2) |
b8e2dd135 batman-adv: Move ... |
66 |
{ |
56303d34a batman-adv: Prefi... |
67 68 |
const void *data1 = container_of(node, struct batadv_orig_node, hash_entry); |
b8e2dd135 batman-adv: Move ... |
69 |
|
323813ed2 batman-adv: use b... |
70 |
return batadv_compare_eth(data1, data2); |
b8e2dd135 batman-adv: Move ... |
71 |
} |
7ea7b4a14 batman-adv: make ... |
72 73 74 75 76 |
/** * batadv_orig_node_vlan_get - get an orig_node_vlan object * @orig_node: the originator serving the VLAN * @vid: the VLAN identifier * |
62fe710f6 batman-adv: Fix k... |
77 |
* Return: the vlan object identified by vid and belonging to orig_node or NULL |
7ea7b4a14 batman-adv: make ... |
78 79 80 81 82 83 84 85 86 |
* if it does not exist. */ struct batadv_orig_node_vlan * batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node, unsigned short vid) { struct batadv_orig_node_vlan *vlan = NULL, *tmp; rcu_read_lock(); |
d0fa4f3f5 batman-adv: conve... |
87 |
hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) { |
7ea7b4a14 batman-adv: make ... |
88 89 |
if (tmp->vid != vid) continue; |
161a3be93 batman-adv: Conve... |
90 |
if (!kref_get_unless_zero(&tmp->refcount)) |
7ea7b4a14 batman-adv: make ... |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
continue; vlan = tmp; break; } rcu_read_unlock(); return vlan; } /** * batadv_orig_node_vlan_new - search and possibly create an orig_node_vlan * object * @orig_node: the originator serving the VLAN * @vid: the VLAN identifier * |
62fe710f6 batman-adv: Fix k... |
108 |
* Return: NULL in case of failure or the vlan object identified by vid and |
7ea7b4a14 batman-adv: make ... |
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
* belonging to orig_node otherwise. The object is created and added to the list * if it does not exist. * * The object is returned with refcounter increased by 1. */ struct batadv_orig_node_vlan * batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node, unsigned short vid) { struct batadv_orig_node_vlan *vlan; spin_lock_bh(&orig_node->vlan_list_lock); /* first look if an object for this vid already exists */ vlan = batadv_orig_node_vlan_get(orig_node, vid); if (vlan) goto out; vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC); if (!vlan) goto out; |
161a3be93 batman-adv: Conve... |
130 |
kref_init(&vlan->refcount); |
7ea7b4a14 batman-adv: make ... |
131 |
vlan->vid = vid; |
09537d186 batman-adv: Place... |
132 |
kref_get(&vlan->refcount); |
d0fa4f3f5 batman-adv: conve... |
133 |
hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list); |
7ea7b4a14 batman-adv: make ... |
134 135 136 137 138 139 140 141 |
out: spin_unlock_bh(&orig_node->vlan_list_lock); return vlan; } /** |
161a3be93 batman-adv: Conve... |
142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
* batadv_orig_node_vlan_release - release originator-vlan object from lists * and queue for free after rcu grace period * @ref: kref pointer of the originator-vlan object */ static void batadv_orig_node_vlan_release(struct kref *ref) { struct batadv_orig_node_vlan *orig_vlan; orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount); kfree_rcu(orig_vlan, rcu); } /** |
21754e250 batman-adv: Renam... |
156 157 |
* batadv_orig_node_vlan_put - decrement the refcounter and possibly release * the originator-vlan object |
7ea7b4a14 batman-adv: make ... |
158 159 |
* @orig_vlan: the originator-vlan object to release */ |
21754e250 batman-adv: Renam... |
160 |
void batadv_orig_node_vlan_put(struct batadv_orig_node_vlan *orig_vlan) |
7ea7b4a14 batman-adv: make ... |
161 |
{ |
161a3be93 batman-adv: Conve... |
162 |
kref_put(&orig_vlan->refcount, batadv_orig_node_vlan_release); |
7ea7b4a14 batman-adv: make ... |
163 |
} |
56303d34a batman-adv: Prefi... |
164 |
int batadv_originator_init(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
165 166 |
{ if (bat_priv->orig_hash) |
5346c35eb batman-adv: Retur... |
167 |
return 0; |
c6c8fea29 net: Add batman-a... |
168 |
|
1a8eaf073 batman-adv: Prefi... |
169 |
bat_priv->orig_hash = batadv_hash_new(1024); |
c6c8fea29 net: Add batman-a... |
170 171 172 |
if (!bat_priv->orig_hash) goto err; |
dec05074b batman-adv: Initi... |
173 174 |
batadv_hash_set_lock_class(bat_priv->orig_hash, &batadv_orig_hash_lock_class_key); |
724144420 batman-adv: a del... |
175 176 177 178 |
INIT_DELAYED_WORK(&bat_priv->orig_work, batadv_purge_orig); queue_delayed_work(batadv_event_workqueue, &bat_priv->orig_work, msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD)); |
5346c35eb batman-adv: Retur... |
179 |
return 0; |
c6c8fea29 net: Add batman-a... |
180 181 |
err: |
5346c35eb batman-adv: Retur... |
182 |
return -ENOMEM; |
c6c8fea29 net: Add batman-a... |
183 |
} |
89652331c batman-adv: split... |
184 |
/** |
ae3e1e36e batman-adv: Drop ... |
185 186 |
* batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for * free after rcu grace period |
962c68328 batman-adv: Conve... |
187 |
* @ref: kref pointer of the neigh_ifinfo |
89652331c batman-adv: split... |
188 |
*/ |
962c68328 batman-adv: Conve... |
189 |
static void batadv_neigh_ifinfo_release(struct kref *ref) |
89652331c batman-adv: split... |
190 |
{ |
962c68328 batman-adv: Conve... |
191 192 193 |
struct batadv_neigh_ifinfo *neigh_ifinfo; neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount); |
ae3e1e36e batman-adv: Drop ... |
194 |
if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) |
82047ad7f batman-adv: Renam... |
195 |
batadv_hardif_put(neigh_ifinfo->if_outgoing); |
ae3e1e36e batman-adv: Drop ... |
196 197 |
kfree_rcu(neigh_ifinfo, rcu); |
89652331c batman-adv: split... |
198 199 200 |
} /** |
044fa3ae1 batman-adv: Renam... |
201 |
* batadv_neigh_ifinfo_put - decrement the refcounter and possibly release |
89652331c batman-adv: split... |
202 203 204 |
* the neigh_ifinfo * @neigh_ifinfo: the neigh_ifinfo object to release */ |
044fa3ae1 batman-adv: Renam... |
205 |
void batadv_neigh_ifinfo_put(struct batadv_neigh_ifinfo *neigh_ifinfo) |
89652331c batman-adv: split... |
206 |
{ |
962c68328 batman-adv: Conve... |
207 |
kref_put(&neigh_ifinfo->refcount, batadv_neigh_ifinfo_release); |
89652331c batman-adv: split... |
208 209 210 |
} /** |
f63896928 batman-adv: Drop ... |
211 212 |
* batadv_hardif_neigh_release - release hardif neigh node from lists and * queue for free after rcu grace period |
90f564dff batman-adv: Conve... |
213 |
* @ref: kref pointer of the neigh_node |
cef63419f batman-adv: add l... |
214 |
*/ |
90f564dff batman-adv: Conve... |
215 |
static void batadv_hardif_neigh_release(struct kref *ref) |
cef63419f batman-adv: add l... |
216 |
{ |
90f564dff batman-adv: Conve... |
217 218 219 220 |
struct batadv_hardif_neigh_node *hardif_neigh; hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node, refcount); |
f63896928 batman-adv: Drop ... |
221 222 223 |
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); hlist_del_init_rcu(&hardif_neigh->list); spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); |
bab7c6c3d batman-adv: Fix l... |
224 |
|
82047ad7f batman-adv: Renam... |
225 |
batadv_hardif_put(hardif_neigh->if_incoming); |
f63896928 batman-adv: Drop ... |
226 |
kfree_rcu(hardif_neigh, rcu); |
cef63419f batman-adv: add l... |
227 228 229 |
} /** |
accadc35a batman-adv: Renam... |
230 |
* batadv_hardif_neigh_put - decrement the hardif neighbors refcounter |
f63896928 batman-adv: Drop ... |
231 |
* and possibly release it |
cef63419f batman-adv: add l... |
232 233 |
* @hardif_neigh: hardif neigh neighbor to free */ |
accadc35a batman-adv: Renam... |
234 |
void batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh) |
cef63419f batman-adv: add l... |
235 |
{ |
90f564dff batman-adv: Conve... |
236 |
kref_put(&hardif_neigh->refcount, batadv_hardif_neigh_release); |
cef63419f batman-adv: add l... |
237 238 239 |
} /** |
b4d922cfc batman-adv: Drop ... |
240 241 |
* batadv_neigh_node_release - release neigh_node from lists and queue for * free after rcu grace period |
77ae32e89 batman-adv: Conve... |
242 |
* @ref: kref pointer of the neigh_node |
89652331c batman-adv: split... |
243 |
*/ |
77ae32e89 batman-adv: Conve... |
244 |
static void batadv_neigh_node_release(struct kref *ref) |
89652331c batman-adv: split... |
245 246 |
{ struct hlist_node *node_tmp; |
77ae32e89 batman-adv: Conve... |
247 |
struct batadv_neigh_node *neigh_node; |
89652331c batman-adv: split... |
248 |
struct batadv_neigh_ifinfo *neigh_ifinfo; |
77ae32e89 batman-adv: Conve... |
249 |
neigh_node = container_of(ref, struct batadv_neigh_node, refcount); |
89652331c batman-adv: split... |
250 251 252 |
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, &neigh_node->ifinfo_list, list) { |
044fa3ae1 batman-adv: Renam... |
253 |
batadv_neigh_ifinfo_put(neigh_ifinfo); |
89652331c batman-adv: split... |
254 |
} |
bcef1f3c4 batman-adv: add b... |
255 |
|
abe59c652 batman-adv: Fix r... |
256 |
batadv_hardif_neigh_put(neigh_node->hardif_neigh); |
cef63419f batman-adv: add l... |
257 |
|
82047ad7f batman-adv: Renam... |
258 |
batadv_hardif_put(neigh_node->if_incoming); |
89652331c batman-adv: split... |
259 |
|
b4d922cfc batman-adv: Drop ... |
260 |
kfree_rcu(neigh_node, rcu); |
89652331c batman-adv: split... |
261 262 263 |
} /** |
25bb25099 batman-adv: Renam... |
264 |
* batadv_neigh_node_put - decrement the neighbors refcounter and possibly |
77ae32e89 batman-adv: Conve... |
265 |
* release it |
89652331c batman-adv: split... |
266 267 |
* @neigh_node: neigh neighbor to free */ |
25bb25099 batman-adv: Renam... |
268 |
void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node) |
a4c135c56 batman-adv: prote... |
269 |
{ |
77ae32e89 batman-adv: Conve... |
270 |
kref_put(&neigh_node->refcount, batadv_neigh_node_release); |
a4c135c56 batman-adv: prote... |
271 |
} |
7351a4822 batman-adv: split... |
272 |
/** |
6d030de89 batman-adv: fix w... |
273 |
* batadv_orig_router_get - router to the originator depending on iface |
7351a4822 batman-adv: split... |
274 275 276 277 |
* @orig_node: the orig node for the router * @if_outgoing: the interface where the payload packet has been received or * the OGM should be sent to * |
62fe710f6 batman-adv: Fix k... |
278 |
* Return: the neighbor which should be router for this orig_node/iface. |
7351a4822 batman-adv: split... |
279 280 281 |
* * The object is returned with refcounter increased by 1. */ |
56303d34a batman-adv: Prefi... |
282 |
struct batadv_neigh_node * |
7351a4822 batman-adv: split... |
283 284 |
batadv_orig_router_get(struct batadv_orig_node *orig_node, const struct batadv_hard_iface *if_outgoing) |
e1a5382f9 batman-adv: Make ... |
285 |
{ |
7351a4822 batman-adv: split... |
286 287 |
struct batadv_orig_ifinfo *orig_ifinfo; struct batadv_neigh_node *router = NULL; |
e1a5382f9 batman-adv: Make ... |
288 289 |
rcu_read_lock(); |
7351a4822 batman-adv: split... |
290 291 292 293 294 295 296 |
hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) { if (orig_ifinfo->if_outgoing != if_outgoing) continue; router = rcu_dereference(orig_ifinfo->router); break; } |
e1a5382f9 batman-adv: Make ... |
297 |
|
77ae32e89 batman-adv: Conve... |
298 |
if (router && !kref_get_unless_zero(&router->refcount)) |
e1a5382f9 batman-adv: Make ... |
299 300 301 302 303 |
router = NULL; rcu_read_unlock(); return router; } |
0538f7599 batman-adv: make ... |
304 |
/** |
7351a4822 batman-adv: split... |
305 306 307 308 |
* batadv_orig_ifinfo_get - find the ifinfo from an orig_node * @orig_node: the orig node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * |
62fe710f6 batman-adv: Fix k... |
309 |
* Return: the requested orig_ifinfo or NULL if not found. |
7351a4822 batman-adv: split... |
310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
* * The object is returned with refcounter increased by 1. */ struct batadv_orig_ifinfo * batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, struct batadv_hard_iface *if_outgoing) { struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL; rcu_read_lock(); hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list, list) { if (tmp->if_outgoing != if_outgoing) continue; |
a6ba0d340 batman-adv: Conve... |
324 |
if (!kref_get_unless_zero(&tmp->refcount)) |
7351a4822 batman-adv: split... |
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
continue; orig_ifinfo = tmp; break; } rcu_read_unlock(); return orig_ifinfo; } /** * batadv_orig_ifinfo_new - search and possibly create an orig_ifinfo object * @orig_node: the orig node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * |
62fe710f6 batman-adv: Fix k... |
340 |
* Return: NULL in case of failure or the orig_ifinfo object for the if_outgoing |
7351a4822 batman-adv: split... |
341 342 343 344 345 346 347 348 349 |
* interface otherwise. The object is created and added to the list * if it does not exist. * * The object is returned with refcounter increased by 1. */ struct batadv_orig_ifinfo * batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, struct batadv_hard_iface *if_outgoing) { |
422d2f778 batman-adv: Remov... |
350 |
struct batadv_orig_ifinfo *orig_ifinfo; |
7351a4822 batman-adv: split... |
351 352 353 354 355 356 357 358 359 360 361 |
unsigned long reset_time; spin_lock_bh(&orig_node->neigh_list_lock); orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing); if (orig_ifinfo) goto out; orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC); if (!orig_ifinfo) goto out; |
17a869150 batman-adv: Use k... |
362 363 |
if (if_outgoing != BATADV_IF_DEFAULT) kref_get(&if_outgoing->refcount); |
7351a4822 batman-adv: split... |
364 365 366 367 368 369 |
reset_time = jiffies - 1; reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); orig_ifinfo->batman_seqno_reset = reset_time; orig_ifinfo->if_outgoing = if_outgoing; INIT_HLIST_NODE(&orig_ifinfo->list); |
a6ba0d340 batman-adv: Conve... |
370 |
kref_init(&orig_ifinfo->refcount); |
f257b99be batman-adv: Place... |
371 |
|
a6ba0d340 batman-adv: Conve... |
372 |
kref_get(&orig_ifinfo->refcount); |
7351a4822 batman-adv: split... |
373 374 375 376 377 378 379 380 |
hlist_add_head_rcu(&orig_ifinfo->list, &orig_node->ifinfo_list); out: spin_unlock_bh(&orig_node->neigh_list_lock); return orig_ifinfo; } /** |
89652331c batman-adv: split... |
381 |
* batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node |
e51f0397d batman-adv: Fix n... |
382 |
* @neigh: the neigh node to be queried |
89652331c batman-adv: split... |
383 384 385 386 |
* @if_outgoing: the interface for which the ifinfo should be acquired * * The object is returned with refcounter increased by 1. * |
62fe710f6 batman-adv: Fix k... |
387 |
* Return: the requested neigh_ifinfo or NULL if not found |
89652331c batman-adv: split... |
388 389 390 391 392 393 394 395 396 397 398 399 400 |
*/ struct batadv_neigh_ifinfo * batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, struct batadv_hard_iface *if_outgoing) { struct batadv_neigh_ifinfo *neigh_ifinfo = NULL, *tmp_neigh_ifinfo; rcu_read_lock(); hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list, list) { if (tmp_neigh_ifinfo->if_outgoing != if_outgoing) continue; |
962c68328 batman-adv: Conve... |
401 |
if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount)) |
89652331c batman-adv: split... |
402 403 404 405 406 407 408 409 410 411 412 413 |
continue; neigh_ifinfo = tmp_neigh_ifinfo; break; } rcu_read_unlock(); return neigh_ifinfo; } /** * batadv_neigh_ifinfo_new - search and possibly create an neigh_ifinfo object |
e51f0397d batman-adv: Fix n... |
414 |
* @neigh: the neigh node to be queried |
89652331c batman-adv: split... |
415 416 |
* @if_outgoing: the interface for which the ifinfo should be acquired * |
62fe710f6 batman-adv: Fix k... |
417 |
* Return: NULL in case of failure or the neigh_ifinfo object for the |
89652331c batman-adv: split... |
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
* if_outgoing interface otherwise. The object is created and added to the list * if it does not exist. * * The object is returned with refcounter increased by 1. */ struct batadv_neigh_ifinfo * batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, struct batadv_hard_iface *if_outgoing) { struct batadv_neigh_ifinfo *neigh_ifinfo; spin_lock_bh(&neigh->ifinfo_lock); neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing); if (neigh_ifinfo) goto out; neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC); if (!neigh_ifinfo) goto out; |
17a869150 batman-adv: Use k... |
438 439 |
if (if_outgoing) kref_get(&if_outgoing->refcount); |
89652331c batman-adv: split... |
440 441 |
INIT_HLIST_NODE(&neigh_ifinfo->list); |
962c68328 batman-adv: Conve... |
442 |
kref_init(&neigh_ifinfo->refcount); |
89652331c batman-adv: split... |
443 |
neigh_ifinfo->if_outgoing = if_outgoing; |
2e774ac2f batman-adv: Place... |
444 |
kref_get(&neigh_ifinfo->refcount); |
89652331c batman-adv: split... |
445 446 447 448 449 450 451 452 453 |
hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list); out: spin_unlock_bh(&neigh->ifinfo_lock); return neigh_ifinfo; } /** |
ed2926634 batman-adv: turn ... |
454 455 456 457 458 459 460 |
* batadv_neigh_node_get - retrieve a neighbour from the list * @orig_node: originator which the neighbour belongs to * @hard_iface: the interface where this neighbour is connected to * @addr: the address of the neighbour * * Looks for and possibly returns a neighbour belonging to this originator list * which is connected through the provided hard interface. |
62fe710f6 batman-adv: Fix k... |
461 462 |
* * Return: neighbor when found. Othwerwise NULL |
ed2926634 batman-adv: turn ... |
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 |
*/ static struct batadv_neigh_node * batadv_neigh_node_get(const struct batadv_orig_node *orig_node, const struct batadv_hard_iface *hard_iface, const u8 *addr) { struct batadv_neigh_node *tmp_neigh_node, *res = NULL; rcu_read_lock(); hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) continue; if (tmp_neigh_node->if_incoming != hard_iface) continue; |
77ae32e89 batman-adv: Conve... |
478 |
if (!kref_get_unless_zero(&tmp_neigh_node->refcount)) |
ed2926634 batman-adv: turn ... |
479 480 481 482 483 484 485 486 487 488 489 |
continue; res = tmp_neigh_node; break; } rcu_read_unlock(); return res; } /** |
cef63419f batman-adv: add l... |
490 491 492 |
* batadv_hardif_neigh_create - create a hardif neighbour node * @hard_iface: the interface this neighbour is connected to * @neigh_addr: the interface address of the neighbour to retrieve |
3111beed0 batman-adv: Simpl... |
493 |
* @orig_node: originator object representing the neighbour |
cef63419f batman-adv: add l... |
494 |
* |
62fe710f6 batman-adv: Fix k... |
495 |
* Return: the hardif neighbour node if found or created or NULL otherwise. |
cef63419f batman-adv: add l... |
496 497 498 |
*/ static struct batadv_hardif_neigh_node * batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, |
3111beed0 batman-adv: Simpl... |
499 500 |
const u8 *neigh_addr, struct batadv_orig_node *orig_node) |
cef63419f batman-adv: add l... |
501 |
{ |
8248a4c7c batman-adv: add b... |
502 |
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
422d2f778 batman-adv: Remov... |
503 |
struct batadv_hardif_neigh_node *hardif_neigh; |
cef63419f batman-adv: add l... |
504 505 506 507 508 509 510 |
spin_lock_bh(&hard_iface->neigh_list_lock); /* check if neighbor hasn't been added in the meantime */ hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); if (hardif_neigh) goto out; |
cef63419f batman-adv: add l... |
511 |
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC); |
17a869150 batman-adv: Use k... |
512 |
if (!hardif_neigh) |
cef63419f batman-adv: add l... |
513 |
goto out; |
cef63419f batman-adv: add l... |
514 |
|
17a869150 batman-adv: Use k... |
515 |
kref_get(&hard_iface->refcount); |
cef63419f batman-adv: add l... |
516 517 |
INIT_HLIST_NODE(&hardif_neigh->list); ether_addr_copy(hardif_neigh->addr, neigh_addr); |
3111beed0 batman-adv: Simpl... |
518 |
ether_addr_copy(hardif_neigh->orig, orig_node->orig); |
cef63419f batman-adv: add l... |
519 520 |
hardif_neigh->if_incoming = hard_iface; hardif_neigh->last_seen = jiffies; |
90f564dff batman-adv: Conve... |
521 |
kref_init(&hardif_neigh->refcount); |
cef63419f batman-adv: add l... |
522 |
|
29824a55c batman-adv: split... |
523 524 |
if (bat_priv->algo_ops->neigh.hardif_init) bat_priv->algo_ops->neigh.hardif_init(hardif_neigh); |
8248a4c7c batman-adv: add b... |
525 |
|
9ca488dd5 batman-adv: Modif... |
526 |
hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list); |
cef63419f batman-adv: add l... |
527 528 529 530 531 532 533 534 535 536 537 |
out: spin_unlock_bh(&hard_iface->neigh_list_lock); return hardif_neigh; } /** * batadv_hardif_neigh_get_or_create - retrieve or create a hardif neighbour * node * @hard_iface: the interface this neighbour is connected to * @neigh_addr: the interface address of the neighbour to retrieve |
3111beed0 batman-adv: Simpl... |
538 |
* @orig_node: originator object representing the neighbour |
cef63419f batman-adv: add l... |
539 |
* |
62fe710f6 batman-adv: Fix k... |
540 |
* Return: the hardif neighbour node if found or created or NULL otherwise. |
cef63419f batman-adv: add l... |
541 542 543 |
*/ static struct batadv_hardif_neigh_node * batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface, |
3111beed0 batman-adv: Simpl... |
544 545 |
const u8 *neigh_addr, struct batadv_orig_node *orig_node) |
cef63419f batman-adv: add l... |
546 |
{ |
422d2f778 batman-adv: Remov... |
547 |
struct batadv_hardif_neigh_node *hardif_neigh; |
cef63419f batman-adv: add l... |
548 549 550 551 552 |
/* first check without locking to avoid the overhead */ hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); if (hardif_neigh) return hardif_neigh; |
3111beed0 batman-adv: Simpl... |
553 |
return batadv_hardif_neigh_create(hard_iface, neigh_addr, orig_node); |
cef63419f batman-adv: add l... |
554 555 556 557 558 559 560 561 |
} /** * batadv_hardif_neigh_get - retrieve a hardif neighbour from the list * @hard_iface: the interface where this neighbour is connected to * @neigh_addr: the address of the neighbour * * Looks for and possibly returns a neighbour belonging to this hard interface. |
62fe710f6 batman-adv: Fix k... |
562 563 |
* * Return: neighbor when found. Othwerwise NULL |
cef63419f batman-adv: add l... |
564 565 566 567 568 569 570 571 572 573 574 575 |
*/ struct batadv_hardif_neigh_node * batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, const u8 *neigh_addr) { struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL; rcu_read_lock(); hlist_for_each_entry_rcu(tmp_hardif_neigh, &hard_iface->neigh_list, list) { if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr)) continue; |
90f564dff batman-adv: Conve... |
576 |
if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount)) |
cef63419f batman-adv: add l... |
577 578 579 580 581 582 583 584 585 586 587 |
continue; hardif_neigh = tmp_hardif_neigh; break; } rcu_read_unlock(); return hardif_neigh; } /** |
6f0a6b5ee batman-adv: refac... |
588 |
* batadv_neigh_node_create - create a neigh node object |
3f32f8a68 batman-adv: rearr... |
589 |
* @orig_node: originator object representing the neighbour |
0538f7599 batman-adv: make ... |
590 591 |
* @hard_iface: the interface where the neighbour is connected to * @neigh_addr: the mac address of the neighbour interface |
0538f7599 batman-adv: make ... |
592 593 |
* * Allocates a new neigh_node object and initialises all the generic fields. |
62fe710f6 batman-adv: Fix k... |
594 |
* |
6f0a6b5ee batman-adv: refac... |
595 |
* Return: the neighbour node if found or created or NULL otherwise. |
0538f7599 batman-adv: make ... |
596 |
*/ |
6f0a6b5ee batman-adv: refac... |
597 598 599 600 |
static struct batadv_neigh_node * batadv_neigh_node_create(struct batadv_orig_node *orig_node, struct batadv_hard_iface *hard_iface, const u8 *neigh_addr) |
c6c8fea29 net: Add batman-a... |
601 |
{ |
56303d34a batman-adv: Prefi... |
602 |
struct batadv_neigh_node *neigh_node; |
cef63419f batman-adv: add l... |
603 |
struct batadv_hardif_neigh_node *hardif_neigh = NULL; |
c6c8fea29 net: Add batman-a... |
604 |
|
e123705e5 batman-adv: Avoid... |
605 |
spin_lock_bh(&orig_node->neigh_list_lock); |
741aa06bf batman-adv: move ... |
606 607 608 |
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); if (neigh_node) goto out; |
cef63419f batman-adv: add l... |
609 |
hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface, |
3111beed0 batman-adv: Simpl... |
610 |
neigh_addr, orig_node); |
cef63419f batman-adv: add l... |
611 612 |
if (!hardif_neigh) goto out; |
704509b8d batman-adv: Calcu... |
613 |
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); |
c6c8fea29 net: Add batman-a... |
614 |
if (!neigh_node) |
7ae8b2852 batman-adv: split... |
615 |
goto out; |
c6c8fea29 net: Add batman-a... |
616 |
|
9591a79f2 batman-adv: conve... |
617 |
INIT_HLIST_NODE(&neigh_node->list); |
89652331c batman-adv: split... |
618 619 |
INIT_HLIST_HEAD(&neigh_node->ifinfo_list); spin_lock_init(&neigh_node->ifinfo_lock); |
c6c8fea29 net: Add batman-a... |
620 |
|
17a869150 batman-adv: Use k... |
621 |
kref_get(&hard_iface->refcount); |
8fdd01530 batman-adv: prefe... |
622 |
ether_addr_copy(neigh_node->addr, neigh_addr); |
0538f7599 batman-adv: make ... |
623 624 |
neigh_node->if_incoming = hard_iface; neigh_node->orig_node = orig_node; |
e48474ed8 batman-adv: init ... |
625 |
neigh_node->last_seen = jiffies; |
0538f7599 batman-adv: make ... |
626 |
|
abe59c652 batman-adv: Fix r... |
627 628 629 |
/* increment unique neighbor refcount */ kref_get(&hardif_neigh->refcount); neigh_node->hardif_neigh = hardif_neigh; |
1605d0d60 batman-adv: incre... |
630 |
/* extra reference for return */ |
77ae32e89 batman-adv: Conve... |
631 |
kref_init(&neigh_node->refcount); |
c6c8fea29 net: Add batman-a... |
632 |
|
842744588 batman-adv: Place... |
633 |
kref_get(&neigh_node->refcount); |
741aa06bf batman-adv: move ... |
634 |
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); |
741aa06bf batman-adv: move ... |
635 636 637 638 639 |
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, "Creating new neighbor %pM for orig_node %pM on interface %s ", neigh_addr, orig_node->orig, hard_iface->net_dev->name); |
7ae8b2852 batman-adv: split... |
640 |
out: |
e123705e5 batman-adv: Avoid... |
641 |
spin_unlock_bh(&orig_node->neigh_list_lock); |
cef63419f batman-adv: add l... |
642 |
if (hardif_neigh) |
accadc35a batman-adv: Renam... |
643 |
batadv_hardif_neigh_put(hardif_neigh); |
c6c8fea29 net: Add batman-a... |
644 645 |
return neigh_node; } |
7351a4822 batman-adv: split... |
646 |
/** |
6f0a6b5ee batman-adv: refac... |
647 648 649 650 651 652 653 654 655 656 657 658 |
* batadv_neigh_node_get_or_create - retrieve or create a neigh node object * @orig_node: originator object representing the neighbour * @hard_iface: the interface where the neighbour is connected to * @neigh_addr: the mac address of the neighbour interface * * Return: the neighbour node if found or created or NULL otherwise. */ struct batadv_neigh_node * batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node, struct batadv_hard_iface *hard_iface, const u8 *neigh_addr) { |
422d2f778 batman-adv: Remov... |
659 |
struct batadv_neigh_node *neigh_node; |
6f0a6b5ee batman-adv: refac... |
660 661 662 663 664 665 666 667 |
/* first check without locking to avoid the overhead */ neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); if (neigh_node) return neigh_node; return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr); } |
dc1cbd145 batman-adv: Allow... |
668 |
#ifdef CONFIG_BATMAN_ADV_DEBUGFS |
6f0a6b5ee batman-adv: refac... |
669 |
/** |
7587405ab batman-adv: expor... |
670 671 672 673 |
* batadv_hardif_neigh_seq_print_text - print the single hop neighbour list * @seq: neighbour table seq_file struct * @offset: not used * |
62fe710f6 batman-adv: Fix k... |
674 |
* Return: always 0 |
7587405ab batman-adv: expor... |
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
*/ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_priv *bat_priv = netdev_priv(net_dev); struct batadv_hard_iface *primary_if; primary_if = batadv_seq_print_text_primary_if_get(seq); if (!primary_if) return 0; seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s %s)] ", BATADV_SOURCE_VERSION, primary_if->net_dev->name, primary_if->net_dev->dev_addr, net_dev->name, |
29824a55c batman-adv: split... |
690 |
bat_priv->algo_ops->name); |
7587405ab batman-adv: expor... |
691 |
|
82047ad7f batman-adv: Renam... |
692 |
batadv_hardif_put(primary_if); |
7587405ab batman-adv: expor... |
693 |
|
29824a55c batman-adv: split... |
694 |
if (!bat_priv->algo_ops->neigh.print) { |
7587405ab batman-adv: expor... |
695 696 697 698 699 |
seq_puts(seq, "No printing function for this routing protocol "); return 0; } |
29824a55c batman-adv: split... |
700 |
bat_priv->algo_ops->neigh.print(bat_priv, seq); |
7587405ab batman-adv: expor... |
701 702 |
return 0; } |
dc1cbd145 batman-adv: Allow... |
703 |
#endif |
7587405ab batman-adv: expor... |
704 705 |
/** |
85cf8c859 batman-adv: netli... |
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
* batadv_hardif_neigh_dump - Dump to netlink the neighbor infos for a specific * outgoing interface * @msg: message to dump into * @cb: parameters for the dump * * Return: 0 or error value */ int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb) { struct net *net = sock_net(cb->skb->sk); struct net_device *soft_iface; struct net_device *hard_iface = NULL; struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT; struct batadv_priv *bat_priv; struct batadv_hard_iface *primary_if = NULL; int ret; int ifindex, hard_ifindex; ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); if (!ifindex) return -EINVAL; soft_iface = dev_get_by_index(net, ifindex); if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { ret = -ENODEV; goto out; } bat_priv = netdev_priv(soft_iface); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { ret = -ENOENT; goto out; } hard_ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_HARD_IFINDEX); if (hard_ifindex) { hard_iface = dev_get_by_index(net, hard_ifindex); if (hard_iface) hardif = batadv_hardif_get_by_netdev(hard_iface); if (!hardif) { ret = -ENODEV; goto out; } if (hardif->soft_iface != soft_iface) { ret = -ENOENT; goto out; } } if (!bat_priv->algo_ops->neigh.dump) { ret = -EOPNOTSUPP; goto out; } bat_priv->algo_ops->neigh.dump(msg, cb, bat_priv, hardif); ret = msg->len; out: if (hardif) batadv_hardif_put(hardif); if (hard_iface) dev_put(hard_iface); if (primary_if) batadv_hardif_put(primary_if); if (soft_iface) dev_put(soft_iface); return ret; } /** |
2baa753c2 batman-adv: Drop ... |
783 784 |
* batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for * free after rcu grace period |
a6ba0d340 batman-adv: Conve... |
785 |
* @ref: kref pointer of the orig_ifinfo |
7351a4822 batman-adv: split... |
786 |
*/ |
a6ba0d340 batman-adv: Conve... |
787 |
static void batadv_orig_ifinfo_release(struct kref *ref) |
7351a4822 batman-adv: split... |
788 |
{ |
a6ba0d340 batman-adv: Conve... |
789 |
struct batadv_orig_ifinfo *orig_ifinfo; |
000c8dff9 batman-adv: fix n... |
790 |
struct batadv_neigh_node *router; |
7351a4822 batman-adv: split... |
791 |
|
a6ba0d340 batman-adv: Conve... |
792 |
orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount); |
7351a4822 batman-adv: split... |
793 |
if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) |
82047ad7f batman-adv: Renam... |
794 |
batadv_hardif_put(orig_ifinfo->if_outgoing); |
7351a4822 batman-adv: split... |
795 |
|
000c8dff9 batman-adv: fix n... |
796 797 798 |
/* this is the last reference to this object */ router = rcu_dereference_protected(orig_ifinfo->router, true); if (router) |
25bb25099 batman-adv: Renam... |
799 |
batadv_neigh_node_put(router); |
2baa753c2 batman-adv: Drop ... |
800 801 |
kfree_rcu(orig_ifinfo, rcu); |
7351a4822 batman-adv: split... |
802 803 804 |
} /** |
35f94779c batman-adv: Renam... |
805 |
* batadv_orig_ifinfo_put - decrement the refcounter and possibly release |
deed96605 batman-adv: Drop ... |
806 |
* the orig_ifinfo |
7351a4822 batman-adv: split... |
807 808 |
* @orig_ifinfo: the orig_ifinfo object to release */ |
35f94779c batman-adv: Renam... |
809 |
void batadv_orig_ifinfo_put(struct batadv_orig_ifinfo *orig_ifinfo) |
7351a4822 batman-adv: split... |
810 |
{ |
a6ba0d340 batman-adv: Conve... |
811 |
kref_put(&orig_ifinfo->refcount, batadv_orig_ifinfo_release); |
7351a4822 batman-adv: split... |
812 813 814 |
} /** |
deed96605 batman-adv: Drop ... |
815 816 |
* batadv_orig_node_free_rcu - free the orig_node * @rcu: rcu pointer of the orig_node |
7351a4822 batman-adv: split... |
817 |
*/ |
deed96605 batman-adv: Drop ... |
818 |
static void batadv_orig_node_free_rcu(struct rcu_head *rcu) |
7351a4822 batman-adv: split... |
819 |
{ |
deed96605 batman-adv: Drop ... |
820 821 822 823 824 825 826 |
struct batadv_orig_node *orig_node; orig_node = container_of(rcu, struct batadv_orig_node, rcu); batadv_mcast_purge_orig(orig_node); batadv_frag_purge_orig(orig_node, NULL); |
29824a55c batman-adv: split... |
827 828 |
if (orig_node->bat_priv->algo_ops->orig.free) orig_node->bat_priv->algo_ops->orig.free(orig_node); |
deed96605 batman-adv: Drop ... |
829 830 831 |
kfree(orig_node->tt_buff); kfree(orig_node); |
7351a4822 batman-adv: split... |
832 |
} |
deed96605 batman-adv: Drop ... |
833 834 835 |
/** * batadv_orig_node_release - release orig_node from lists and queue for * free after rcu grace period |
7c1243911 batman-adv: Conve... |
836 |
* @ref: kref pointer of the orig_node |
deed96605 batman-adv: Drop ... |
837 |
*/ |
7c1243911 batman-adv: Conve... |
838 |
static void batadv_orig_node_release(struct kref *ref) |
c6c8fea29 net: Add batman-a... |
839 |
{ |
b67bfe0d4 hlist: drop the n... |
840 |
struct hlist_node *node_tmp; |
f6c8b7117 batman-adv: remov... |
841 |
struct batadv_neigh_node *neigh_node; |
7c1243911 batman-adv: Conve... |
842 |
struct batadv_orig_node *orig_node; |
7351a4822 batman-adv: split... |
843 |
struct batadv_orig_ifinfo *orig_ifinfo; |
33fbb1f3d batman-adv: Fix o... |
844 |
struct batadv_orig_node_vlan *vlan; |
cbef1e102 batman-adv: Free ... |
845 |
struct batadv_orig_ifinfo *last_candidate; |
16b1aba84 batman-adv: prote... |
846 |
|
7c1243911 batman-adv: Conve... |
847 |
orig_node = container_of(ref, struct batadv_orig_node, refcount); |
f987ed6eb batman-adv: prote... |
848 |
spin_lock_bh(&orig_node->neigh_list_lock); |
c6c8fea29 net: Add batman-a... |
849 |
/* for all neighbors towards this originator ... */ |
b67bfe0d4 hlist: drop the n... |
850 |
hlist_for_each_entry_safe(neigh_node, node_tmp, |
9591a79f2 batman-adv: conve... |
851 |
&orig_node->neigh_list, list) { |
f987ed6eb batman-adv: prote... |
852 |
hlist_del_rcu(&neigh_node->list); |
25bb25099 batman-adv: Renam... |
853 |
batadv_neigh_node_put(neigh_node); |
c6c8fea29 net: Add batman-a... |
854 |
} |
7351a4822 batman-adv: split... |
855 856 857 |
hlist_for_each_entry_safe(orig_ifinfo, node_tmp, &orig_node->ifinfo_list, list) { hlist_del_rcu(&orig_ifinfo->list); |
35f94779c batman-adv: Renam... |
858 |
batadv_orig_ifinfo_put(orig_ifinfo); |
7351a4822 batman-adv: split... |
859 |
} |
cbef1e102 batman-adv: Free ... |
860 861 862 |
last_candidate = orig_node->last_bonding_candidate; orig_node->last_bonding_candidate = NULL; |
f987ed6eb batman-adv: prote... |
863 |
spin_unlock_bh(&orig_node->neigh_list_lock); |
cbef1e102 batman-adv: Free ... |
864 865 |
if (last_candidate) batadv_orig_ifinfo_put(last_candidate); |
33fbb1f3d batman-adv: Fix o... |
866 867 868 869 870 871 |
spin_lock_bh(&orig_node->vlan_list_lock); hlist_for_each_entry_safe(vlan, node_tmp, &orig_node->vlan_list, list) { hlist_del_rcu(&vlan->list); batadv_orig_node_vlan_put(vlan); } spin_unlock_bh(&orig_node->vlan_list_lock); |
d56b1705e batman-adv: netwo... |
872 873 |
/* Free nc_nodes */ batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); |
deed96605 batman-adv: Drop ... |
874 |
call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); |
c6c8fea29 net: Add batman-a... |
875 |
} |
72822225b batman-adv: Fix r... |
876 |
/** |
5d9673109 batman-adv: Renam... |
877 |
* batadv_orig_node_put - decrement the orig node refcounter and possibly |
deed96605 batman-adv: Drop ... |
878 |
* release it |
72822225b batman-adv: Fix r... |
879 880 |
* @orig_node: the orig node to free */ |
5d9673109 batman-adv: Renam... |
881 |
void batadv_orig_node_put(struct batadv_orig_node *orig_node) |
7b36e8eef batman-adv: Corre... |
882 |
{ |
7c1243911 batman-adv: Conve... |
883 |
kref_put(&orig_node->refcount, batadv_orig_node_release); |
7b36e8eef batman-adv: Corre... |
884 |
} |
56303d34a batman-adv: Prefi... |
885 |
void batadv_originator_free(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
886 |
{ |
5bf74e9ca batman-adv: Prefi... |
887 |
struct batadv_hashtable *hash = bat_priv->orig_hash; |
b67bfe0d4 hlist: drop the n... |
888 |
struct hlist_node *node_tmp; |
16b1aba84 batman-adv: prote... |
889 |
struct hlist_head *head; |
16b1aba84 batman-adv: prote... |
890 |
spinlock_t *list_lock; /* spinlock to protect write access */ |
56303d34a batman-adv: Prefi... |
891 |
struct batadv_orig_node *orig_node; |
6b5e971a2 batman-adv: Repla... |
892 |
u32 i; |
16b1aba84 batman-adv: prote... |
893 894 |
if (!hash) |
c6c8fea29 net: Add batman-a... |
895 896 897 |
return; cancel_delayed_work_sync(&bat_priv->orig_work); |
c6c8fea29 net: Add batman-a... |
898 |
bat_priv->orig_hash = NULL; |
16b1aba84 batman-adv: prote... |
899 900 901 902 903 904 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
905 |
hlist_for_each_entry_safe(orig_node, node_tmp, |
7aadf889e batman-adv: remov... |
906 |
head, hash_entry) { |
b67bfe0d4 hlist: drop the n... |
907 |
hlist_del_rcu(&orig_node->hash_entry); |
5d9673109 batman-adv: Renam... |
908 |
batadv_orig_node_put(orig_node); |
16b1aba84 batman-adv: prote... |
909 910 911 |
} spin_unlock_bh(list_lock); } |
1a8eaf073 batman-adv: Prefi... |
912 |
batadv_hash_destroy(hash); |
c6c8fea29 net: Add batman-a... |
913 |
} |
bbad0a5e3 batman-adv: make ... |
914 915 916 917 918 919 920 |
/** * batadv_orig_node_new - creates a new orig_node * @bat_priv: the bat priv with all the soft interface information * @addr: the mac address of the originator * * Creates a new originator object and initialise all the generic fields. * The new object is not added to the originator list. |
62fe710f6 batman-adv: Fix k... |
921 922 |
* * Return: the newly created object or NULL on failure. |
9cfc7bd60 batman-adv: Refor... |
923 |
*/ |
bbad0a5e3 batman-adv: make ... |
924 |
struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, |
6b5e971a2 batman-adv: Repla... |
925 |
const u8 *addr) |
c6c8fea29 net: Add batman-a... |
926 |
{ |
56303d34a batman-adv: Prefi... |
927 |
struct batadv_orig_node *orig_node; |
7ea7b4a14 batman-adv: make ... |
928 |
struct batadv_orig_node_vlan *vlan; |
42d0b044b batman-adv: Prefi... |
929 |
unsigned long reset_time; |
bbad0a5e3 batman-adv: make ... |
930 |
int i; |
c6c8fea29 net: Add batman-a... |
931 |
|
39c75a51e batman-adv: Prefi... |
932 933 934 |
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Creating new originator: %pM ", addr); |
c6c8fea29 net: Add batman-a... |
935 |
|
704509b8d batman-adv: Calcu... |
936 |
orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC); |
c6c8fea29 net: Add batman-a... |
937 938 |
if (!orig_node) return NULL; |
9591a79f2 batman-adv: conve... |
939 |
INIT_HLIST_HEAD(&orig_node->neigh_list); |
d0fa4f3f5 batman-adv: conve... |
940 |
INIT_HLIST_HEAD(&orig_node->vlan_list); |
7351a4822 batman-adv: split... |
941 |
INIT_HLIST_HEAD(&orig_node->ifinfo_list); |
f3e0008f0 batman-adv: make ... |
942 |
spin_lock_init(&orig_node->bcast_seqno_lock); |
f987ed6eb batman-adv: prote... |
943 |
spin_lock_init(&orig_node->neigh_list_lock); |
a73105b8d batman-adv: impro... |
944 |
spin_lock_init(&orig_node->tt_buff_lock); |
a70a9aa99 batman-adv: lock ... |
945 |
spin_lock_init(&orig_node->tt_lock); |
7ea7b4a14 batman-adv: make ... |
946 |
spin_lock_init(&orig_node->vlan_list_lock); |
7b36e8eef batman-adv: Corre... |
947 |
|
d56b1705e batman-adv: netwo... |
948 |
batadv_nc_init_orig(orig_node); |
7b36e8eef batman-adv: Corre... |
949 |
/* extra reference for return */ |
7c1243911 batman-adv: Conve... |
950 |
kref_init(&orig_node->refcount); |
c6c8fea29 net: Add batman-a... |
951 |
|
16b1aba84 batman-adv: prote... |
952 |
orig_node->bat_priv = bat_priv; |
8fdd01530 batman-adv: prefe... |
953 |
ether_addr_copy(orig_node->orig, addr); |
785ea1144 batman-adv: Distr... |
954 |
batadv_dat_init_orig_node_addr(orig_node); |
c8c991bf2 batman-adv: initi... |
955 |
atomic_set(&orig_node->last_ttvn, 0); |
2dafb49d8 batman-adv: renam... |
956 |
orig_node->tt_buff = NULL; |
a73105b8d batman-adv: impro... |
957 |
orig_node->tt_buff_len = 0; |
2c667a339 batman-adv: fix d... |
958 |
orig_node->last_seen = jiffies; |
42d0b044b batman-adv: Prefi... |
959 960 |
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); orig_node->bcast_seqno_reset = reset_time; |
8a4023c5b batman-adv: Fix p... |
961 |
|
60432d756 batman-adv: Annou... |
962 963 |
#ifdef CONFIG_BATMAN_ADV_MCAST orig_node->mcast_flags = BATADV_NO_FLAGS; |
8a4023c5b batman-adv: Fix p... |
964 965 966 967 |
INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node); INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node); INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node); spin_lock_init(&orig_node->mcast_handler_lock); |
60432d756 batman-adv: Annou... |
968 |
#endif |
c6c8fea29 net: Add batman-a... |
969 |
|
7ea7b4a14 batman-adv: make ... |
970 971 972 973 974 975 976 977 |
/* create a vlan object for the "untagged" LAN */ vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); if (!vlan) goto free_orig_node; /* batadv_orig_node_vlan_new() increases the refcounter. * Immediately release vlan since it is not needed anymore in this * context */ |
21754e250 batman-adv: Renam... |
978 |
batadv_orig_node_vlan_put(vlan); |
7ea7b4a14 batman-adv: make ... |
979 |
|
610bfc6bc batman-adv: Recei... |
980 |
for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) { |
176e5b772 batman-adv: Use p... |
981 |
INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list); |
610bfc6bc batman-adv: Recei... |
982 983 984 |
spin_lock_init(&orig_node->fragments[i].lock); orig_node->fragments[i].size = 0; } |
c6c8fea29 net: Add batman-a... |
985 |
return orig_node; |
c6c8fea29 net: Add batman-a... |
986 987 988 989 |
free_orig_node: kfree(orig_node); return NULL; } |
89652331c batman-adv: split... |
990 |
/** |
709de13f0 batman-adv: fix r... |
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
* batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor * @bat_priv: the bat priv with all the soft interface information * @neigh: orig node which is to be checked */ static void batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, struct batadv_neigh_node *neigh) { struct batadv_neigh_ifinfo *neigh_ifinfo; struct batadv_hard_iface *if_outgoing; struct hlist_node *node_tmp; spin_lock_bh(&neigh->ifinfo_lock); /* for all ifinfo objects for this neighinator */ hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, &neigh->ifinfo_list, list) { if_outgoing = neigh_ifinfo->if_outgoing; /* always keep the default interface */ if (if_outgoing == BATADV_IF_DEFAULT) continue; /* don't purge if the interface is not (going) down */ if ((if_outgoing->if_status != BATADV_IF_INACTIVE) && (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) && (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)) continue; batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "neighbor/ifinfo purge: neighbor %pM, iface: %s ", neigh->addr, if_outgoing->net_dev->name); hlist_del_rcu(&neigh_ifinfo->list); |
044fa3ae1 batman-adv: Renam... |
1026 |
batadv_neigh_ifinfo_put(neigh_ifinfo); |
709de13f0 batman-adv: fix r... |
1027 1028 1029 1030 1031 1032 |
} spin_unlock_bh(&neigh->ifinfo_lock); } /** |
7351a4822 batman-adv: split... |
1033 1034 1035 1036 |
* batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * |
62fe710f6 batman-adv: Fix k... |
1037 |
* Return: true if any ifinfo entry was purged, false otherwise. |
7351a4822 batman-adv: split... |
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 |
*/ static bool batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node) { struct batadv_orig_ifinfo *orig_ifinfo; struct batadv_hard_iface *if_outgoing; struct hlist_node *node_tmp; bool ifinfo_purged = false; spin_lock_bh(&orig_node->neigh_list_lock); /* for all ifinfo objects for this originator */ hlist_for_each_entry_safe(orig_ifinfo, node_tmp, &orig_node->ifinfo_list, list) { if_outgoing = orig_ifinfo->if_outgoing; /* always keep the default interface */ if (if_outgoing == BATADV_IF_DEFAULT) continue; /* don't purge if the interface is not (going) down */ if ((if_outgoing->if_status != BATADV_IF_INACTIVE) && (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) && (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)) continue; batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "router/ifinfo purge: originator %pM, iface: %s ", orig_node->orig, if_outgoing->net_dev->name); ifinfo_purged = true; hlist_del_rcu(&orig_ifinfo->list); |
35f94779c batman-adv: Renam... |
1073 |
batadv_orig_ifinfo_put(orig_ifinfo); |
f3b3d9018 batman-adv: add b... |
1074 1075 |
if (orig_node->last_bonding_candidate == orig_ifinfo) { orig_node->last_bonding_candidate = NULL; |
35f94779c batman-adv: Renam... |
1076 |
batadv_orig_ifinfo_put(orig_ifinfo); |
f3b3d9018 batman-adv: add b... |
1077 |
} |
7351a4822 batman-adv: split... |
1078 1079 1080 1081 1082 1083 |
} spin_unlock_bh(&orig_node->neigh_list_lock); return ifinfo_purged; } |
7351a4822 batman-adv: split... |
1084 |
/** |
89652331c batman-adv: split... |
1085 1086 1087 1088 |
* batadv_purge_orig_neighbors - purges neighbors from originator * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * |
62fe710f6 batman-adv: Fix k... |
1089 |
* Return: true if any neighbor was purged, false otherwise |
89652331c batman-adv: split... |
1090 |
*/ |
56303d34a batman-adv: Prefi... |
1091 1092 |
static bool batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, |
89652331c batman-adv: split... |
1093 |
struct batadv_orig_node *orig_node) |
c6c8fea29 net: Add batman-a... |
1094 |
{ |
b67bfe0d4 hlist: drop the n... |
1095 |
struct hlist_node *node_tmp; |
56303d34a batman-adv: Prefi... |
1096 |
struct batadv_neigh_node *neigh_node; |
c6c8fea29 net: Add batman-a... |
1097 |
bool neigh_purged = false; |
0b0094e00 batman-adv: repla... |
1098 |
unsigned long last_seen; |
56303d34a batman-adv: Prefi... |
1099 |
struct batadv_hard_iface *if_incoming; |
c6c8fea29 net: Add batman-a... |
1100 |
|
f987ed6eb batman-adv: prote... |
1101 |
spin_lock_bh(&orig_node->neigh_list_lock); |
c6c8fea29 net: Add batman-a... |
1102 |
/* for all neighbors towards this originator ... */ |
b67bfe0d4 hlist: drop the n... |
1103 |
hlist_for_each_entry_safe(neigh_node, node_tmp, |
9591a79f2 batman-adv: conve... |
1104 |
&orig_node->neigh_list, list) { |
1eda58bfc batman-adv: Prefi... |
1105 1106 |
last_seen = neigh_node->last_seen; if_incoming = neigh_node->if_incoming; |
42d0b044b batman-adv: Prefi... |
1107 |
if ((batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT)) || |
e9a4f295e batman-adv: Prefi... |
1108 1109 1110 |
(if_incoming->if_status == BATADV_IF_INACTIVE) || (if_incoming->if_status == BATADV_IF_NOT_IN_USE) || (if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)) { |
e9a4f295e batman-adv: Prefi... |
1111 1112 1113 |
if ((if_incoming->if_status == BATADV_IF_INACTIVE) || (if_incoming->if_status == BATADV_IF_NOT_IN_USE) || (if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)) |
39c75a51e batman-adv: Prefi... |
1114 |
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1115 1116 1117 1118 |
"neighbor purge: originator %pM, neighbor: %pM, iface: %s ", orig_node->orig, neigh_node->addr, if_incoming->net_dev->name); |
c6c8fea29 net: Add batman-a... |
1119 |
else |
39c75a51e batman-adv: Prefi... |
1120 |
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1121 1122 1123 1124 |
"neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u ", orig_node->orig, neigh_node->addr, jiffies_to_msecs(last_seen)); |
c6c8fea29 net: Add batman-a... |
1125 1126 |
neigh_purged = true; |
9591a79f2 batman-adv: conve... |
1127 |
|
f987ed6eb batman-adv: prote... |
1128 |
hlist_del_rcu(&neigh_node->list); |
25bb25099 batman-adv: Renam... |
1129 |
batadv_neigh_node_put(neigh_node); |
709de13f0 batman-adv: fix r... |
1130 1131 1132 1133 1134 |
} else { /* only necessary if not the whole neighbor is to be * deleted, but some interface has been removed. */ batadv_purge_neigh_ifinfo(bat_priv, neigh_node); |
c6c8fea29 net: Add batman-a... |
1135 1136 |
} } |
f987ed6eb batman-adv: prote... |
1137 1138 |
spin_unlock_bh(&orig_node->neigh_list_lock); |
c6c8fea29 net: Add batman-a... |
1139 1140 |
return neigh_purged; } |
89652331c batman-adv: split... |
1141 1142 1143 1144 1145 1146 |
/** * batadv_find_best_neighbor - finds the best neighbor after purging * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * @if_outgoing: the interface for which the metric should be compared * |
62fe710f6 batman-adv: Fix k... |
1147 |
* Return: the current best neighbor, with refcount increased. |
89652331c batman-adv: split... |
1148 1149 1150 1151 1152 1153 1154 |
*/ static struct batadv_neigh_node * batadv_find_best_neighbor(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, struct batadv_hard_iface *if_outgoing) { struct batadv_neigh_node *best = NULL, *neigh; |
29824a55c batman-adv: split... |
1155 |
struct batadv_algo_ops *bao = bat_priv->algo_ops; |
89652331c batman-adv: split... |
1156 1157 1158 |
rcu_read_lock(); hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) { |
29824a55c batman-adv: split... |
1159 1160 |
if (best && (bao->neigh.cmp(neigh, if_outgoing, best, if_outgoing) <= 0)) |
89652331c batman-adv: split... |
1161 |
continue; |
77ae32e89 batman-adv: Conve... |
1162 |
if (!kref_get_unless_zero(&neigh->refcount)) |
89652331c batman-adv: split... |
1163 1164 1165 |
continue; if (best) |
25bb25099 batman-adv: Renam... |
1166 |
batadv_neigh_node_put(best); |
89652331c batman-adv: split... |
1167 1168 1169 1170 1171 1172 1173 |
best = neigh; } rcu_read_unlock(); return best; } |
7351a4822 batman-adv: split... |
1174 1175 1176 1177 1178 1179 1180 1181 |
/** * batadv_purge_orig_node - purges obsolete information from an orig_node * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * * This function checks if the orig_node or substructures of it have become * obsolete, and purges this information if that's the case. * |
62fe710f6 batman-adv: Fix k... |
1182 |
* Return: true if the orig_node is to be removed, false otherwise. |
7351a4822 batman-adv: split... |
1183 |
*/ |
56303d34a batman-adv: Prefi... |
1184 1185 |
static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node) |
c6c8fea29 net: Add batman-a... |
1186 |
{ |
56303d34a batman-adv: Prefi... |
1187 |
struct batadv_neigh_node *best_neigh_node; |
7351a4822 batman-adv: split... |
1188 |
struct batadv_hard_iface *hard_iface; |
7b955a9fc batman-adv: alway... |
1189 |
bool changed_ifinfo, changed_neigh; |
c6c8fea29 net: Add batman-a... |
1190 |
|
42d0b044b batman-adv: Prefi... |
1191 1192 |
if (batadv_has_timed_out(orig_node->last_seen, 2 * BATADV_PURGE_TIMEOUT)) { |
39c75a51e batman-adv: Prefi... |
1193 |
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1194 1195 1196 1197 |
"Originator timeout: originator %pM, last_seen %u ", orig_node->orig, jiffies_to_msecs(orig_node->last_seen)); |
c6c8fea29 net: Add batman-a... |
1198 |
return true; |
c6c8fea29 net: Add batman-a... |
1199 |
} |
7b955a9fc batman-adv: alway... |
1200 1201 |
changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node); changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node); |
7351a4822 batman-adv: split... |
1202 |
|
7b955a9fc batman-adv: alway... |
1203 |
if (!changed_ifinfo && !changed_neigh) |
89652331c batman-adv: split... |
1204 |
return false; |
7351a4822 batman-adv: split... |
1205 |
/* first for NULL ... */ |
89652331c batman-adv: split... |
1206 1207 |
best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, BATADV_IF_DEFAULT); |
7351a4822 batman-adv: split... |
1208 1209 |
batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT, best_neigh_node); |
89652331c batman-adv: split... |
1210 |
if (best_neigh_node) |
25bb25099 batman-adv: Renam... |
1211 |
batadv_neigh_node_put(best_neigh_node); |
c6c8fea29 net: Add batman-a... |
1212 |
|
7351a4822 batman-adv: split... |
1213 1214 1215 1216 1217 1218 1219 1220 |
/* ... then for all other interfaces. */ rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { if (hard_iface->if_status != BATADV_IF_ACTIVE) continue; if (hard_iface->soft_iface != bat_priv->soft_iface) continue; |
273534468 batman-adv: Check... |
1221 1222 |
if (!kref_get_unless_zero(&hard_iface->refcount)) continue; |
7351a4822 batman-adv: split... |
1223 1224 1225 1226 1227 1228 |
best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, hard_iface); batadv_update_route(bat_priv, orig_node, hard_iface, best_neigh_node); if (best_neigh_node) |
25bb25099 batman-adv: Renam... |
1229 |
batadv_neigh_node_put(best_neigh_node); |
273534468 batman-adv: Check... |
1230 1231 |
batadv_hardif_put(hard_iface); |
7351a4822 batman-adv: split... |
1232 1233 |
} rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
1234 1235 |
return false; } |
56303d34a batman-adv: Prefi... |
1236 |
static void _batadv_purge_orig(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
1237 |
{ |
5bf74e9ca batman-adv: Prefi... |
1238 |
struct batadv_hashtable *hash = bat_priv->orig_hash; |
b67bfe0d4 hlist: drop the n... |
1239 |
struct hlist_node *node_tmp; |
c6c8fea29 net: Add batman-a... |
1240 |
struct hlist_head *head; |
fb778ea17 batman-adv: prote... |
1241 |
spinlock_t *list_lock; /* spinlock to protect write access */ |
56303d34a batman-adv: Prefi... |
1242 |
struct batadv_orig_node *orig_node; |
6b5e971a2 batman-adv: Repla... |
1243 |
u32 i; |
c6c8fea29 net: Add batman-a... |
1244 1245 1246 |
if (!hash) return; |
c6c8fea29 net: Add batman-a... |
1247 1248 1249 |
/* for all origins... */ for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
fb778ea17 batman-adv: prote... |
1250 |
list_lock = &hash->list_locks[i]; |
c6c8fea29 net: Add batman-a... |
1251 |
|
fb778ea17 batman-adv: prote... |
1252 |
spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
1253 |
hlist_for_each_entry_safe(orig_node, node_tmp, |
7aadf889e batman-adv: remov... |
1254 |
head, hash_entry) { |
03fc7f863 batman-adv: Prefi... |
1255 |
if (batadv_purge_orig_node(bat_priv, orig_node)) { |
414254e34 batman-adv: tvlv ... |
1256 |
batadv_gw_node_delete(bat_priv, orig_node); |
b67bfe0d4 hlist: drop the n... |
1257 |
hlist_del_rcu(&orig_node->hash_entry); |
9d31b3ce8 batman-adv: fix p... |
1258 1259 1260 |
batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1, "originator timed out"); |
5d9673109 batman-adv: Renam... |
1261 |
batadv_orig_node_put(orig_node); |
fb778ea17 batman-adv: prote... |
1262 |
continue; |
c6c8fea29 net: Add batman-a... |
1263 |
} |
610bfc6bc batman-adv: Recei... |
1264 1265 1266 |
batadv_frag_purge_orig(orig_node, batadv_frag_check_entry); |
c6c8fea29 net: Add batman-a... |
1267 |
} |
fb778ea17 batman-adv: prote... |
1268 |
spin_unlock_bh(list_lock); |
c6c8fea29 net: Add batman-a... |
1269 |
} |
7cf06bc6f batman-adv: Prefi... |
1270 |
batadv_gw_election(bat_priv); |
c6c8fea29 net: Add batman-a... |
1271 |
} |
03fc7f863 batman-adv: Prefi... |
1272 |
static void batadv_purge_orig(struct work_struct *work) |
c6c8fea29 net: Add batman-a... |
1273 |
{ |
56303d34a batman-adv: Prefi... |
1274 1275 |
struct delayed_work *delayed_work; struct batadv_priv *bat_priv; |
c6c8fea29 net: Add batman-a... |
1276 |
|
4ba4bc0f7 batman-adv: use t... |
1277 |
delayed_work = to_delayed_work(work); |
56303d34a batman-adv: Prefi... |
1278 |
bat_priv = container_of(delayed_work, struct batadv_priv, orig_work); |
03fc7f863 batman-adv: Prefi... |
1279 |
_batadv_purge_orig(bat_priv); |
724144420 batman-adv: a del... |
1280 1281 1282 |
queue_delayed_work(batadv_event_workqueue, &bat_priv->orig_work, msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD)); |
c6c8fea29 net: Add batman-a... |
1283 |
} |
56303d34a batman-adv: Prefi... |
1284 |
void batadv_purge_orig_ref(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
1285 |
{ |
03fc7f863 batman-adv: Prefi... |
1286 |
_batadv_purge_orig(bat_priv); |
c6c8fea29 net: Add batman-a... |
1287 |
} |
dc1cbd145 batman-adv: Allow... |
1288 |
#ifdef CONFIG_BATMAN_ADV_DEBUGFS |
7d211efc5 batman-adv: Prefi... |
1289 |
int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) |
c6c8fea29 net: Add batman-a... |
1290 1291 |
{ struct net_device *net_dev = (struct net_device *)seq->private; |
56303d34a batman-adv: Prefi... |
1292 |
struct batadv_priv *bat_priv = netdev_priv(net_dev); |
56303d34a batman-adv: Prefi... |
1293 |
struct batadv_hard_iface *primary_if; |
32ae9b221 batman-adv: Make ... |
1294 |
|
30da63a6a batman-adv: conso... |
1295 1296 |
primary_if = batadv_seq_print_text_primary_if_get(seq); if (!primary_if) |
737a2a229 batman-adv: add b... |
1297 |
return 0; |
c6c8fea29 net: Add batman-a... |
1298 |
|
737a2a229 batman-adv: add b... |
1299 1300 |
seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s %s)] ", |
42d0b044b batman-adv: Prefi... |
1301 |
BATADV_SOURCE_VERSION, primary_if->net_dev->name, |
737a2a229 batman-adv: add b... |
1302 |
primary_if->net_dev->dev_addr, net_dev->name, |
29824a55c batman-adv: split... |
1303 |
bat_priv->algo_ops->name); |
c6c8fea29 net: Add batman-a... |
1304 |
|
82047ad7f batman-adv: Renam... |
1305 |
batadv_hardif_put(primary_if); |
c6c8fea29 net: Add batman-a... |
1306 |
|
29824a55c batman-adv: split... |
1307 |
if (!bat_priv->algo_ops->orig.print) { |
737a2a229 batman-adv: add b... |
1308 1309 1310 1311 |
seq_puts(seq, "No printing function for this routing protocol "); return 0; |
c6c8fea29 net: Add batman-a... |
1312 |
} |
29824a55c batman-adv: split... |
1313 |
bat_priv->algo_ops->orig.print(bat_priv, seq, BATADV_IF_DEFAULT); |
c6c8fea29 net: Add batman-a... |
1314 |
|
30da63a6a batman-adv: conso... |
1315 |
return 0; |
c6c8fea29 net: Add batman-a... |
1316 |
} |
cb1c92ec3 batman-adv: add d... |
1317 1318 1319 1320 1321 1322 |
/** * batadv_orig_hardif_seq_print_text - writes originator infos for a specific * outgoing interface * @seq: debugfs table seq_file struct * @offset: not used * |
62fe710f6 batman-adv: Fix k... |
1323 |
* Return: 0 |
cb1c92ec3 batman-adv: add d... |
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 |
*/ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct batadv_hard_iface *hard_iface; struct batadv_priv *bat_priv; hard_iface = batadv_hardif_get_by_netdev(net_dev); if (!hard_iface || !hard_iface->soft_iface) { seq_puts(seq, "Interface not known to B.A.T.M.A.N. "); goto out; } bat_priv = netdev_priv(hard_iface->soft_iface); |
29824a55c batman-adv: split... |
1340 |
if (!bat_priv->algo_ops->orig.print) { |
cb1c92ec3 batman-adv: add d... |
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 |
seq_puts(seq, "No printing function for this routing protocol "); goto out; } if (hard_iface->if_status != BATADV_IF_ACTIVE) { seq_puts(seq, "Interface not active "); goto out; } seq_printf(seq, "[B.A.T.M.A.N. adv %s, IF/MAC: %s/%pM (%s %s)] ", BATADV_SOURCE_VERSION, hard_iface->net_dev->name, hard_iface->net_dev->dev_addr, |
29824a55c batman-adv: split... |
1357 |
hard_iface->soft_iface->name, bat_priv->algo_ops->name); |
cb1c92ec3 batman-adv: add d... |
1358 |
|
29824a55c batman-adv: split... |
1359 |
bat_priv->algo_ops->orig.print(bat_priv, seq, hard_iface); |
cb1c92ec3 batman-adv: add d... |
1360 1361 |
out: |
16a414236 batman-adv: fix i... |
1362 |
if (hard_iface) |
82047ad7f batman-adv: Renam... |
1363 |
batadv_hardif_put(hard_iface); |
cb1c92ec3 batman-adv: add d... |
1364 1365 |
return 0; } |
dc1cbd145 batman-adv: Allow... |
1366 |
#endif |
cb1c92ec3 batman-adv: add d... |
1367 |
|
85cf8c859 batman-adv: netli... |
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
/** * batadv_orig_dump - Dump to netlink the originator infos for a specific * outgoing interface * @msg: message to dump into * @cb: parameters for the dump * * Return: 0 or error value */ int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb) { struct net *net = sock_net(cb->skb->sk); struct net_device *soft_iface; struct net_device *hard_iface = NULL; struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT; struct batadv_priv *bat_priv; struct batadv_hard_iface *primary_if = NULL; int ret; int ifindex, hard_ifindex; ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); if (!ifindex) return -EINVAL; soft_iface = dev_get_by_index(net, ifindex); if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { ret = -ENODEV; goto out; } bat_priv = netdev_priv(soft_iface); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { ret = -ENOENT; goto out; } hard_ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_HARD_IFINDEX); if (hard_ifindex) { hard_iface = dev_get_by_index(net, hard_ifindex); if (hard_iface) hardif = batadv_hardif_get_by_netdev(hard_iface); if (!hardif) { ret = -ENODEV; goto out; } if (hardif->soft_iface != soft_iface) { ret = -ENOENT; goto out; } } if (!bat_priv->algo_ops->orig.dump) { ret = -EOPNOTSUPP; goto out; } bat_priv->algo_ops->orig.dump(msg, cb, bat_priv, hardif); ret = msg->len; out: if (hardif) batadv_hardif_put(hardif); if (hard_iface) dev_put(hard_iface); if (primary_if) batadv_hardif_put(primary_if); if (soft_iface) dev_put(soft_iface); return ret; } |
56303d34a batman-adv: Prefi... |
1444 1445 |
int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface, int max_if_num) |
c6c8fea29 net: Add batman-a... |
1446 |
{ |
56303d34a batman-adv: Prefi... |
1447 |
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
29824a55c batman-adv: split... |
1448 |
struct batadv_algo_ops *bao = bat_priv->algo_ops; |
5bf74e9ca batman-adv: Prefi... |
1449 |
struct batadv_hashtable *hash = bat_priv->orig_hash; |
c6c8fea29 net: Add batman-a... |
1450 |
struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
1451 |
struct batadv_orig_node *orig_node; |
6b5e971a2 batman-adv: Repla... |
1452 |
u32 i; |
c90681b85 batman-adv: fixed... |
1453 |
int ret; |
c6c8fea29 net: Add batman-a... |
1454 1455 |
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on |
9cfc7bd60 batman-adv: Refor... |
1456 1457 |
* if_num */ |
c6c8fea29 net: Add batman-a... |
1458 1459 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
fb778ea17 batman-adv: prote... |
1460 |
rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
1461 |
hlist_for_each_entry_rcu(orig_node, head, hash_entry) { |
d0015fdd3 batman-adv: provi... |
1462 |
ret = 0; |
29824a55c batman-adv: split... |
1463 1464 |
if (bao->orig.add_if) ret = bao->orig.add_if(orig_node, max_if_num); |
5346c35eb batman-adv: Retur... |
1465 |
if (ret == -ENOMEM) |
c6c8fea29 net: Add batman-a... |
1466 1467 |
goto err; } |
fb778ea17 batman-adv: prote... |
1468 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
1469 |
} |
c6c8fea29 net: Add batman-a... |
1470 1471 1472 |
return 0; err: |
fb778ea17 batman-adv: prote... |
1473 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
1474 1475 |
return -ENOMEM; } |
56303d34a batman-adv: Prefi... |
1476 1477 |
int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, int max_if_num) |
c6c8fea29 net: Add batman-a... |
1478 |
{ |
56303d34a batman-adv: Prefi... |
1479 |
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
5bf74e9ca batman-adv: Prefi... |
1480 |
struct batadv_hashtable *hash = bat_priv->orig_hash; |
c6c8fea29 net: Add batman-a... |
1481 |
struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
1482 1483 |
struct batadv_hard_iface *hard_iface_tmp; struct batadv_orig_node *orig_node; |
29824a55c batman-adv: split... |
1484 |
struct batadv_algo_ops *bao = bat_priv->algo_ops; |
6b5e971a2 batman-adv: Repla... |
1485 |
u32 i; |
c90681b85 batman-adv: fixed... |
1486 |
int ret; |
c6c8fea29 net: Add batman-a... |
1487 1488 |
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on |
9cfc7bd60 batman-adv: Refor... |
1489 1490 |
* if_num */ |
c6c8fea29 net: Add batman-a... |
1491 1492 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
fb778ea17 batman-adv: prote... |
1493 |
rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
1494 |
hlist_for_each_entry_rcu(orig_node, head, hash_entry) { |
d0015fdd3 batman-adv: provi... |
1495 |
ret = 0; |
29824a55c batman-adv: split... |
1496 1497 1498 |
if (bao->orig.del_if) ret = bao->orig.del_if(orig_node, max_if_num, hard_iface->if_num); |
5346c35eb batman-adv: Retur... |
1499 |
if (ret == -ENOMEM) |
c6c8fea29 net: Add batman-a... |
1500 1501 |
goto err; } |
fb778ea17 batman-adv: prote... |
1502 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
1503 1504 1505 1506 |
} /* renumber remaining batman interfaces _inside_ of orig_hash_lock */ rcu_read_lock(); |
3193e8fdf batman-adv: Prefi... |
1507 |
list_for_each_entry_rcu(hard_iface_tmp, &batadv_hardif_list, list) { |
e9a4f295e batman-adv: Prefi... |
1508 |
if (hard_iface_tmp->if_status == BATADV_IF_NOT_IN_USE) |
c6c8fea29 net: Add batman-a... |
1509 |
continue; |
e6c10f433 batman-adv: renam... |
1510 |
if (hard_iface == hard_iface_tmp) |
c6c8fea29 net: Add batman-a... |
1511 |
continue; |
e6c10f433 batman-adv: renam... |
1512 |
if (hard_iface->soft_iface != hard_iface_tmp->soft_iface) |
c6c8fea29 net: Add batman-a... |
1513 |
continue; |
e6c10f433 batman-adv: renam... |
1514 1515 |
if (hard_iface_tmp->if_num > hard_iface->if_num) hard_iface_tmp->if_num--; |
c6c8fea29 net: Add batman-a... |
1516 1517 |
} rcu_read_unlock(); |
e6c10f433 batman-adv: renam... |
1518 |
hard_iface->if_num = -1; |
c6c8fea29 net: Add batman-a... |
1519 1520 1521 |
return 0; err: |
fb778ea17 batman-adv: prote... |
1522 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
1523 1524 |
return -ENOMEM; } |