hard-interface.c 18.6 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 273
	 * (have MTU > 1500 + BAT_HEADER_LEN)
	 */
274 275 276 277 278 279
	int min_mtu = ETH_DATA_LEN;

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

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

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

288 289
		min_mtu = min_t(int,
				hard_iface->net_dev->mtu - BATADV_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;
A
Antonio Quartulli 已提交
382
	__be16 ethertype = __constant_htons(ETH_P_BATMAN);
383
	int ret;
384

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

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

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

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

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

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

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

412 413 414 415 416 417 418 419
	/* 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;

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

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

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

431
	hard_iface->if_num = bat_priv->num_ifaces;
432
	bat_priv->num_ifaces++;
433
	hard_iface->if_status = BATADV_IF_INACTIVE;
434 435 436 437 438
	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;
439
		goto err_upper;
440
	}
441

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

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

450 451
	if (atomic_read(&bat_priv->fragmentation) &&
	    hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN)
452 453 454
		batadv_info(hard_iface->soft_iface,
			    "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 %zi would solve the problem.\n",
			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
455
			    ETH_DATA_LEN + BATADV_HEADER_LEN);
456

457 458
	if (!atomic_read(&bat_priv->fragmentation) &&
	    hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN)
459 460 461
		batadv_info(hard_iface->soft_iface,
			    "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 %zi.\n",
			    hard_iface->net_dev->name, hard_iface->net_dev->mtu,
462
			    ETH_DATA_LEN + BATADV_HEADER_LEN);
463

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

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

out:
	return 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
/**
 * 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);
}

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

562 563
	ASSERT_RTNL();

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

	dev_hold(net_dev);

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

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

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

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

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

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

596
	return hard_iface;
597 598

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

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

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

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

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

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

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

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

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

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

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

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

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

676
		batadv_check_known_mac_addr(hard_iface->net_dev);
677

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

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

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

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

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