File Index
Files and directories
Sign in
FILE

originator.c

File preview with syntax highlighting.

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