hard-interface.c 18.7 KB
Newer Older
1
/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "main.h"
21
#include "distributed-arp-table.h"
22 23 24 25 26
#include "hard-interface.h"
#include "soft-interface.h"
#include "send.h"
#include "translation-table.h"
#include "routing.h"
27
#include "sysfs.h"
28 29
#include "originator.h"
#include "hash.h"
30
#include "bridge_loop_avoidance.h"
31 32

#include <linux/if_arp.h>
A
Antonio Quartulli 已提交
33
#include <linux/if_ether.h>
34

35
void batadv_hardif_free_rcu(struct rcu_head *rcu)
36
{
37
	struct batadv_hard_iface *hard_iface;
38

39
	hard_iface = container_of(rcu, struct batadv_hard_iface, rcu);
40 41
	dev_put(hard_iface->net_dev);
	kfree(hard_iface);
42 43
}

44 45
struct batadv_hard_iface *
batadv_hardif_get_by_netdev(const struct net_device *net_dev)
46
{
47
	struct batadv_hard_iface *hard_iface;
48 49

	rcu_read_lock();
50
	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
51 52
		if (hard_iface->net_dev == net_dev &&
		    atomic_inc_not_zero(&hard_iface->refcount))
53 54 55
			goto out;
	}

56
	hard_iface = NULL;
57 58 59

out:
	rcu_read_unlock();
60
	return hard_iface;
61 62
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/**
 * batadv_is_on_batman_iface - check if a device is a batman iface descendant
 * @net_dev: the device to check
 *
 * If the user creates any virtual device on top of a batman-adv interface, it
 * is important to prevent this new interface to be used to create a new mesh
 * network (this behaviour would lead to a batman-over-batman configuration).
 * This function recursively checks all the fathers of the device passed as
 * argument looking for a batman-adv soft interface.
 *
 * Returns true if the device is descendant of a batman-adv mesh interface (or
 * if it is a batman-adv interface itself), false otherwise
 */
static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
{
	struct net_device *parent_dev;
	bool ret;

	/* check if this is a batman-adv mesh interface */
	if (batadv_softif_is_valid(net_dev))
		return true;

	/* no more parents..stop recursion */
	if (net_dev->iflink == net_dev->ifindex)
		return false;

	/* recurse over the parent device */
	parent_dev = dev_get_by_index(&init_net, net_dev->iflink);
	/* if we got a NULL parent_dev there is something broken.. */
	if (WARN(!parent_dev, "Cannot find parent device"))
		return false;

	ret = batadv_is_on_batman_iface(parent_dev);

	if (parent_dev)
		dev_put(parent_dev);
	return ret;
}

102
static int batadv_is_valid_iface(const struct net_device *net_dev)
103 104 105 106 107 108 109 110 111 112 113
{
	if (net_dev->flags & IFF_LOOPBACK)
		return 0;

	if (net_dev->type != ARPHRD_ETHER)
		return 0;

	if (net_dev->addr_len != ETH_ALEN)
		return 0;

	/* no batman over batman */
114
	if (batadv_is_on_batman_iface(net_dev))
115 116 117 118 119
		return 0;

	return 1;
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
/**
 * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
 *  interface
 * @net_device: the device to check
 *
 * Returns true if the net device is a 802.11 wireless device, false otherwise.
 */
static bool batadv_is_wifi_netdev(struct net_device *net_device)
{
#ifdef CONFIG_WIRELESS_EXT
	/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
	 * check for wireless_handlers != NULL
	 */
	if (net_device->wireless_handlers)
		return true;
#endif

	/* cfg80211 drivers have to set ieee80211_ptr */
	if (net_device->ieee80211_ptr)
		return true;

	return false;
}

/**
 * batadv_is_wifi_iface - check if the given interface represented by ifindex
 *  is a wifi interface
 * @ifindex: interface index to check
 *
 * Returns true if the interface represented by ifindex is a 802.11 wireless
 * device, false otherwise.
 */
bool batadv_is_wifi_iface(int ifindex)
{
	struct net_device *net_device = NULL;
	bool ret = false;

	if (ifindex == BATADV_NULL_IFINDEX)
		goto out;

	net_device = dev_get_by_index(&init_net, ifindex);
	if (!net_device)
		goto out;

	ret = batadv_is_wifi_netdev(net_device);

out:
	if (net_device)
		dev_put(net_device);
	return ret;
}

172
static struct batadv_hard_iface *
173
batadv_hardif_get_active(const struct net_device *soft_iface)
174
{
175
	struct batadv_hard_iface *hard_iface;
176 177

	rcu_read_lock();
178
	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
179
		if (hard_iface->soft_iface != soft_iface)
180 181
			continue;

182
		if (hard_iface->if_status == BATADV_IF_ACTIVE &&
183
		    atomic_inc_not_zero(&hard_iface->refcount))
184 185 186
			goto out;
	}

187
	hard_iface = NULL;
188 189 190

out:
	rcu_read_unlock();
191
	return hard_iface;
192 193
}

194 195
static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
					  struct batadv_hard_iface *oldif)
196
{
197
	struct batadv_hard_iface *primary_if;
198

199
	primary_if = batadv_primary_if_get_selected(bat_priv);
200 201
	if (!primary_if)
		goto out;
202

203
	batadv_dat_init_own_addr(bat_priv, primary_if);
204
	batadv_bla_update_orig_address(bat_priv, primary_if, oldif);
205 206
out:
	if (primary_if)
207
		batadv_hardif_free_ref(primary_if);
208 209
}

210 211
static void batadv_primary_if_select(struct batadv_priv *bat_priv,
				     struct batadv_hard_iface *new_hard_iface)
212
{
213
	struct batadv_hard_iface *curr_hard_iface;
214

215
	ASSERT_RTNL();
216

217 218
	if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
		new_hard_iface = NULL;
219

220
	curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
221
	rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
222

223
	if (!new_hard_iface)
224
		goto out;
225

226
	bat_priv->bat_algo_ops->bat_primary_iface_set(new_hard_iface);
227
	batadv_primary_if_update_addr(bat_priv, curr_hard_iface);
228 229 230

out:
	if (curr_hard_iface)
231
		batadv_hardif_free_ref(curr_hard_iface);
232 233
}

234 235
static bool
batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface)
236
{
237
	if (hard_iface->net_dev->flags & IFF_UP)
238 239 240 241 242
		return true;

	return false;
}

243
static void batadv_check_known_mac_addr(const struct net_device *net_dev)
244
{
245
	const struct batadv_hard_iface *hard_iface;
246 247

	rcu_read_lock();
248
	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
249 250
		if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
		    (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
251 252
			continue;

253
		if (hard_iface->net_dev == net_dev)
254 255
			continue;

256 257
		if (!batadv_compare_eth(hard_iface->net_dev->dev_addr,
					net_dev->dev_addr))
258 259
			continue;

260 261 262
		pr_warn("The newly added mac address (%pM) already exists on: %s\n",
			net_dev->dev_addr, hard_iface->net_dev->name);
		pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n");
263 264 265 266
	}
	rcu_read_unlock();
}

267
int batadv_hardif_min_mtu(struct net_device *soft_iface)
268
{
269 270
	const struct batadv_priv *bat_priv = netdev_priv(soft_iface);
	const struct batadv_hard_iface *hard_iface;
271
	/* allow big frames if all devices are capable to do so
272
	 * (have MTU > 1500 + batadv_max_header_len())
273
	 */
274
	int min_mtu = ETH_DATA_LEN;
275
	int max_header_len = batadv_max_header_len();
276 277 278 279 280

	if (atomic_read(&bat_priv->fragmentation))
		goto out;

	rcu_read_lock();
281
	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
282 283
		if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
		    (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
284 285
			continue;

286
		if (hard_iface->soft_iface != soft_iface)
287 288
			continue;

289
		min_mtu = min_t(int, hard_iface->net_dev->mtu - max_header_len,
290 291 292 293 294 295 296 297
				min_mtu);
	}
	rcu_read_unlock();
out:
	return min_mtu;
}

/* adjusts the MTU if a new interface with a smaller MTU appeared. */
298
void batadv_update_min_mtu(struct net_device *soft_iface)
299 300 301
{
	int min_mtu;

302
	min_mtu = batadv_hardif_min_mtu(soft_iface);
303 304 305 306
	if (soft_iface->mtu != min_mtu)
		soft_iface->mtu = min_mtu;
}

307 308
static void
batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
309
{
310 311
	struct batadv_priv *bat_priv;
	struct batadv_hard_iface *primary_if = NULL;
312

313
	if (hard_iface->if_status != BATADV_IF_INACTIVE)
314
		goto out;
315

316
	bat_priv = netdev_priv(hard_iface->soft_iface);
317

318
	bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
319
	hard_iface->if_status = BATADV_IF_TO_BE_ACTIVATED;
320

321
	/* the first active interface becomes our primary interface or
322
	 * the next active interface after the old primary interface was removed
323
	 */
324
	primary_if = batadv_primary_if_get_selected(bat_priv);
325
	if (!primary_if)
326
		batadv_primary_if_select(bat_priv, hard_iface);
327

328 329
	batadv_info(hard_iface->soft_iface, "Interface activated: %s\n",
		    hard_iface->net_dev->name);
330

331
	batadv_update_min_mtu(hard_iface->soft_iface);
332 333 334

out:
	if (primary_if)
335
		batadv_hardif_free_ref(primary_if);
336 337
}

338 339
static void
batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
340
{
341 342
	if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
	    (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
343 344
		return;

345
	hard_iface->if_status = BATADV_IF_INACTIVE;
346

347 348
	batadv_info(hard_iface->soft_iface, "Interface deactivated: %s\n",
		    hard_iface->net_dev->name);
349

350
	batadv_update_min_mtu(hard_iface->soft_iface);
351 352
}

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
/**
 * batadv_master_del_slave - remove hard_iface from the current master interface
 * @slave: the interface enslaved in another master
 * @master: the master from which slave has to be removed
 *
 * Invoke ndo_del_slave on master passing slave as argument. In this way slave
 * is free'd and master can correctly change its internal state.
 * Return 0 on success, a negative value representing the error otherwise
 */
static int batadv_master_del_slave(struct batadv_hard_iface *slave,
				   struct net_device *master)
{
	int ret;

	if (!master)
		return 0;

	ret = -EBUSY;
	if (master->netdev_ops->ndo_del_slave)
		ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);

	return ret;
}

377
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
378
				   const char *iface_name)
379
{
380
	struct batadv_priv *bat_priv;
381
	struct net_device *soft_iface, *master;
382
	__be16 ethertype = htons(ETH_P_BATMAN);
383
	int max_header_len = batadv_max_header_len();
384
	int ret;
385

386
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
387 388
		goto out;

389
	if (!atomic_inc_not_zero(&hard_iface->refcount))
390 391
		goto out;

392
	soft_iface = dev_get_by_name(&init_net, iface_name);
393

394
	if (!soft_iface) {
395
		soft_iface = batadv_softif_create(iface_name);
396

397 398
		if (!soft_iface) {
			ret = -ENOMEM;
399
			goto err;
400
		}
401 402

		/* dev_get_by_name() increases the reference counter for us */
403 404 405
		dev_hold(soft_iface);
	}

406
	if (!batadv_softif_is_valid(soft_iface)) {
407
		pr_err("Can't create batman mesh interface %s: already exists as regular interface\n",
408 409
		       soft_iface->name);
		ret = -EINVAL;
410
		goto err_dev;
411 412
	}

413 414 415 416 417 418 419 420
	/* check if the interface is enslaved in another virtual one and
	 * in that case unlink it first
	 */
	master = netdev_master_upper_dev_get(hard_iface->net_dev);
	ret = batadv_master_del_slave(hard_iface, master);
	if (ret)
		goto err_dev;

421
	hard_iface->soft_iface = soft_iface;
422
	bat_priv = netdev_priv(hard_iface->soft_iface);
423

424 425 426 427
	ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface);
	if (ret)
		goto err_dev;

428
	ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
429
	if (ret < 0)
430
		goto err_upper;
431

432
	hard_iface->if_num = bat_priv->num_ifaces;
433
	bat_priv->num_ifaces++;
434
	hard_iface->if_status = BATADV_IF_INACTIVE;
435 436 437 438 439
	ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
	if (ret < 0) {
		bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
		bat_priv->num_ifaces--;
		hard_iface->if_status = BATADV_IF_NOT_IN_USE;
440
		goto err_upper;
441
	}
442

443
	hard_iface->batman_adv_ptype.type = ethertype;
444
	hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
445 446
	hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
	dev_add_pack(&hard_iface->batman_adv_ptype);
447

448 449
	batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",
		    hard_iface->net_dev->name);
450

451
	if (atomic_read(&bat_priv->fragmentation) &&
452
	    hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
453
		batadv_info(hard_iface->soft_iface,
454
			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %i would solve the problem.\n",
455
			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
456
			    ETH_DATA_LEN + max_header_len);
457

458
	if (!atomic_read(&bat_priv->fragmentation) &&
459
	    hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
460
		batadv_info(hard_iface->soft_iface,
461
			    "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %i.\n",
462
			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
463
			    ETH_DATA_LEN + max_header_len);
464

465 466
	if (batadv_hardif_is_iface_up(hard_iface))
		batadv_hardif_activate_interface(hard_iface);
467
	else
468 469 470
		batadv_err(hard_iface->soft_iface,
			   "Not using interface %s (retrying later): interface not active\n",
			   hard_iface->net_dev->name);
471 472

	/* begin scheduling originator messages on that interface */
473
	batadv_schedule_bat_ogm(hard_iface);
474 475 476 477

out:
	return 0;

478 479
err_upper:
	netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface);
480
err_dev:
481
	hard_iface->soft_iface = NULL;
482
	dev_put(soft_iface);
483
err:
484
	batadv_hardif_free_ref(hard_iface);
485
	return ret;
486 487
}

488 489
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
				     enum batadv_hard_if_cleanup autodel)
490
{
491 492
	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
	struct batadv_hard_iface *primary_if = NULL;
493

494
	if (hard_iface->if_status == BATADV_IF_ACTIVE)
495
		batadv_hardif_deactivate_interface(hard_iface);
496

497
	if (hard_iface->if_status != BATADV_IF_INACTIVE)
498
		goto out;
499

500 501
	batadv_info(hard_iface->soft_iface, "Removing interface: %s\n",
		    hard_iface->net_dev->name);
502
	dev_remove_pack(&hard_iface->batman_adv_ptype);
503 504

	bat_priv->num_ifaces--;
505
	batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
506

507
	primary_if = batadv_primary_if_get_selected(bat_priv);
508
	if (hard_iface == primary_if) {
509
		struct batadv_hard_iface *new_if;
510

511 512
		new_if = batadv_hardif_get_active(hard_iface->soft_iface);
		batadv_primary_if_select(bat_priv, new_if);
513 514

		if (new_if)
515
			batadv_hardif_free_ref(new_if);
516 517
	}

518
	bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
519
	hard_iface->if_status = BATADV_IF_NOT_IN_USE;
520

521
	/* delete all references to this hard_iface */
522
	batadv_purge_orig_ref(bat_priv);
523
	batadv_purge_outstanding_packets(bat_priv, hard_iface);
524
	dev_put(hard_iface->soft_iface);
525 526

	/* nobody uses this interface anymore */
527
	if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO)
528
		batadv_softif_destroy_sysfs(hard_iface->soft_iface);
529

530
	netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
531
	hard_iface->soft_iface = NULL;
532
	batadv_hardif_free_ref(hard_iface);
533 534 535

out:
	if (primary_if)
536
		batadv_hardif_free_ref(primary_if);
537 538
}

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
/**
 * batadv_hardif_remove_interface_finish - cleans up the remains of a hardif
 * @work: work queue item
 *
 * Free the parts of the hard interface which can not be removed under
 * rtnl lock (to prevent deadlock situations).
 */
static void batadv_hardif_remove_interface_finish(struct work_struct *work)
{
	struct batadv_hard_iface *hard_iface;

	hard_iface = container_of(work, struct batadv_hard_iface,
				  cleanup_work);

	batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
	batadv_hardif_free_ref(hard_iface);
}

557
static struct batadv_hard_iface *
558
batadv_hardif_add_interface(struct net_device *net_dev)
559
{
560
	struct batadv_hard_iface *hard_iface;
561 562
	int ret;

563 564
	ASSERT_RTNL();

565
	ret = batadv_is_valid_iface(net_dev);
566 567 568 569 570
	if (ret != 1)
		goto out;

	dev_hold(net_dev);

571
	hard_iface = kzalloc(sizeof(*hard_iface), GFP_ATOMIC);
572
	if (!hard_iface)
573 574
		goto release_dev;

575
	ret = batadv_sysfs_add_hardif(&hard_iface->hardif_obj, net_dev);
576 577 578
	if (ret)
		goto free_if;

579 580 581
	hard_iface->if_num = -1;
	hard_iface->net_dev = net_dev;
	hard_iface->soft_iface = NULL;
582
	hard_iface->if_status = BATADV_IF_NOT_IN_USE;
583
	INIT_LIST_HEAD(&hard_iface->list);
584 585 586
	INIT_WORK(&hard_iface->cleanup_work,
		  batadv_hardif_remove_interface_finish);

587 588 589 590
	hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
	if (batadv_is_wifi_netdev(net_dev))
		hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;

591
	/* extra reference for return */
592
	atomic_set(&hard_iface->refcount, 2);
593

594
	batadv_check_known_mac_addr(hard_iface->net_dev);
595
	list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
596

597
	return hard_iface;
598 599

free_if:
600
	kfree(hard_iface);
601 602 603 604 605 606
release_dev:
	dev_put(net_dev);
out:
	return NULL;
}

607
static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
608
{
609 610
	ASSERT_RTNL();

611
	/* first deactivate interface */
612
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
613 614
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
615

616
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
617 618
		return;

619
	hard_iface->if_status = BATADV_IF_TO_BE_REMOVED;
620
	queue_work(batadv_event_workqueue, &hard_iface->cleanup_work);
621 622
}

623
void batadv_hardif_remove_interfaces(void)
624
{
625
	struct batadv_hard_iface *hard_iface, *hard_iface_tmp;
626

627
	rtnl_lock();
628
	list_for_each_entry_safe(hard_iface, hard_iface_tmp,
629
				 &batadv_hardif_list, list) {
630
		list_del_rcu(&hard_iface->list);
631
		batadv_hardif_remove_interface(hard_iface);
632 633 634 635
	}
	rtnl_unlock();
}

636 637
static int batadv_hard_if_event(struct notifier_block *this,
				unsigned long event, void *ptr)
638
{
639
	struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
640 641 642
	struct batadv_hard_iface *hard_iface;
	struct batadv_hard_iface *primary_if = NULL;
	struct batadv_priv *bat_priv;
643

644 645 646 647 648
	if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
		batadv_sysfs_add_meshif(net_dev);
		return NOTIFY_DONE;
	}

649
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
650
	if (!hard_iface && event == NETDEV_REGISTER)
651
		hard_iface = batadv_hardif_add_interface(net_dev);
652

653
	if (!hard_iface)
654 655 656 657
		goto out;

	switch (event) {
	case NETDEV_UP:
658
		batadv_hardif_activate_interface(hard_iface);
659 660 661
		break;
	case NETDEV_GOING_DOWN:
	case NETDEV_DOWN:
662
		batadv_hardif_deactivate_interface(hard_iface);
663 664
		break;
	case NETDEV_UNREGISTER:
665
		list_del_rcu(&hard_iface->list);
666

667
		batadv_hardif_remove_interface(hard_iface);
668 669
		break;
	case NETDEV_CHANGEMTU:
670
		if (hard_iface->soft_iface)
671
			batadv_update_min_mtu(hard_iface->soft_iface);
672 673
		break;
	case NETDEV_CHANGEADDR:
674
		if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
675 676
			goto hardif_put;

677
		batadv_check_known_mac_addr(hard_iface->net_dev);
678

679
		bat_priv = netdev_priv(hard_iface->soft_iface);
680
		bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
681

682
		primary_if = batadv_primary_if_get_selected(bat_priv);
683 684 685 686
		if (!primary_if)
			goto hardif_put;

		if (hard_iface == primary_if)
687
			batadv_primary_if_update_addr(bat_priv, NULL);
688 689 690
		break;
	default:
		break;
J
Joe Perches 已提交
691
	}
692 693

hardif_put:
694
	batadv_hardif_free_ref(hard_iface);
695
out:
696
	if (primary_if)
697
		batadv_hardif_free_ref(primary_if);
698 699 700
	return NOTIFY_DONE;
}

701
struct notifier_block batadv_hard_if_notifier = {
702
	.notifier_call = batadv_hard_if_event,
703
};