diff options
author | Sven Eckelmann <sven@narfation.org> | 2013-02-11 04:10:27 -0500 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2013-03-27 05:29:52 -0400 |
commit | 3dbd550b8b2e204833d8305451bbde990e1cd743 (patch) | |
tree | 0f6d28971ca8e045d372064fde6ae7822acac414 | |
parent | a4ac28c0d06a1c22138225a228d3a4eaffe9dd77 (diff) |
batman-adv: Allow to modify slaves of soft-interfaces through rntl_link
The sysfs configuration interface of batman-adv to add/remove slaves of an
soft-iface is not deadlock free and doesn't follow the currently common way to
modify slaves of an interface.
An additional configuration interface though rtnl_link is introduced which
provides easy device adding/removing with tools like "ip":
$ ip link set dev eth0 master bat0
$ ip link set dev eth0 nomaster
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
-rw-r--r-- | net/batman-adv/hard-interface.c | 12 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 56 |
2 files changed, 65 insertions, 3 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 6c32607a6e93..f33ced8e31f4 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -350,9 +350,13 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
350 | hard_iface->soft_iface = soft_iface; | 350 | hard_iface->soft_iface = soft_iface; |
351 | bat_priv = netdev_priv(hard_iface->soft_iface); | 351 | bat_priv = netdev_priv(hard_iface->soft_iface); |
352 | 352 | ||
353 | ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface); | ||
354 | if (ret) | ||
355 | goto err_dev; | ||
356 | |||
353 | ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); | 357 | ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); |
354 | if (ret < 0) | 358 | if (ret < 0) |
355 | goto err_dev; | 359 | goto err_upper; |
356 | 360 | ||
357 | hard_iface->if_num = bat_priv->num_ifaces; | 361 | hard_iface->if_num = bat_priv->num_ifaces; |
358 | bat_priv->num_ifaces++; | 362 | bat_priv->num_ifaces++; |
@@ -362,7 +366,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
362 | bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); | 366 | bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); |
363 | bat_priv->num_ifaces--; | 367 | bat_priv->num_ifaces--; |
364 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; | 368 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; |
365 | goto err_dev; | 369 | goto err_upper; |
366 | } | 370 | } |
367 | 371 | ||
368 | hard_iface->batman_adv_ptype.type = ethertype; | 372 | hard_iface->batman_adv_ptype.type = ethertype; |
@@ -401,7 +405,10 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
401 | out: | 405 | out: |
402 | return 0; | 406 | return 0; |
403 | 407 | ||
408 | err_upper: | ||
409 | netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface); | ||
404 | err_dev: | 410 | err_dev: |
411 | hard_iface->soft_iface = NULL; | ||
405 | dev_put(soft_iface); | 412 | dev_put(soft_iface); |
406 | err: | 413 | err: |
407 | batadv_hardif_free_ref(hard_iface); | 414 | batadv_hardif_free_ref(hard_iface); |
@@ -450,6 +457,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface, | |||
450 | if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO) | 457 | if (!bat_priv->num_ifaces && autodel == BATADV_IF_CLEANUP_AUTO) |
451 | batadv_softif_destroy_sysfs(hard_iface->soft_iface); | 458 | batadv_softif_destroy_sysfs(hard_iface->soft_iface); |
452 | 459 | ||
460 | netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface); | ||
453 | hard_iface->soft_iface = NULL; | 461 | hard_iface->soft_iface = NULL; |
454 | batadv_hardif_free_ref(hard_iface); | 462 | batadv_hardif_free_ref(hard_iface); |
455 | 463 | ||
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 545c863b35fc..403b8c46085e 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -509,6 +509,58 @@ free_bat_counters: | |||
509 | return ret; | 509 | return ret; |
510 | } | 510 | } |
511 | 511 | ||
512 | /** | ||
513 | * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface | ||
514 | * @dev: batadv_soft_interface used as master interface | ||
515 | * @slave_dev: net_device which should become the slave interface | ||
516 | * | ||
517 | * Return 0 if successful or error otherwise. | ||
518 | */ | ||
519 | static int batadv_softif_slave_add(struct net_device *dev, | ||
520 | struct net_device *slave_dev) | ||
521 | { | ||
522 | struct batadv_hard_iface *hard_iface; | ||
523 | int ret = -EINVAL; | ||
524 | |||
525 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); | ||
526 | if (!hard_iface || hard_iface->soft_iface != NULL) | ||
527 | goto out; | ||
528 | |||
529 | ret = batadv_hardif_enable_interface(hard_iface, dev->name); | ||
530 | |||
531 | out: | ||
532 | if (hard_iface) | ||
533 | batadv_hardif_free_ref(hard_iface); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface | ||
539 | * @dev: batadv_soft_interface used as master interface | ||
540 | * @slave_dev: net_device which should be removed from the master interface | ||
541 | * | ||
542 | * Return 0 if successful or error otherwise. | ||
543 | */ | ||
544 | static int batadv_softif_slave_del(struct net_device *dev, | ||
545 | struct net_device *slave_dev) | ||
546 | { | ||
547 | struct batadv_hard_iface *hard_iface; | ||
548 | int ret = -EINVAL; | ||
549 | |||
550 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); | ||
551 | |||
552 | if (!hard_iface || hard_iface->soft_iface != dev) | ||
553 | goto out; | ||
554 | |||
555 | batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP); | ||
556 | ret = 0; | ||
557 | |||
558 | out: | ||
559 | if (hard_iface) | ||
560 | batadv_hardif_free_ref(hard_iface); | ||
561 | return ret; | ||
562 | } | ||
563 | |||
512 | static const struct net_device_ops batadv_netdev_ops = { | 564 | static const struct net_device_ops batadv_netdev_ops = { |
513 | .ndo_init = batadv_softif_init_late, | 565 | .ndo_init = batadv_softif_init_late, |
514 | .ndo_open = batadv_interface_open, | 566 | .ndo_open = batadv_interface_open, |
@@ -517,7 +569,9 @@ static const struct net_device_ops batadv_netdev_ops = { | |||
517 | .ndo_set_mac_address = batadv_interface_set_mac_addr, | 569 | .ndo_set_mac_address = batadv_interface_set_mac_addr, |
518 | .ndo_change_mtu = batadv_interface_change_mtu, | 570 | .ndo_change_mtu = batadv_interface_change_mtu, |
519 | .ndo_start_xmit = batadv_interface_tx, | 571 | .ndo_start_xmit = batadv_interface_tx, |
520 | .ndo_validate_addr = eth_validate_addr | 572 | .ndo_validate_addr = eth_validate_addr, |
573 | .ndo_add_slave = batadv_softif_slave_add, | ||
574 | .ndo_del_slave = batadv_softif_slave_del, | ||
521 | }; | 575 | }; |
522 | 576 | ||
523 | /** | 577 | /** |