diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 0495a7dc7505..62b1f89b7b4d 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -71,6 +71,7 @@ static int __init batadv_init(void) batadv_debugfs_init(); register_netdevice_notifier(&batadv_hard_if_notifier); + rtnl_link_register(&batadv_link_ops); pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION); @@ -81,6 +82,7 @@ static int __init batadv_init(void) static void __exit batadv_exit(void) { batadv_debugfs_destroy(); + rtnl_link_unregister(&batadv_link_ops); unregister_netdevice_notifier(&batadv_hard_if_notifier); batadv_hardif_remove_interfaces(); diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 0afd4ee7708b..a9e12e65aa15 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -152,6 +152,7 @@ enum batadv_uev_type { #include #include #include /* struct sock */ +#include #include #include #include "types.h" diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index bc77a5be960d..545c863b35fc 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -570,6 +570,8 @@ struct net_device *batadv_softif_create(const char *name) if (!soft_iface) return NULL; + soft_iface->rtnl_link_ops = &batadv_link_ops; + ret = register_netdevice(soft_iface); if (ret < 0) { pr_err("Unable to register the batman interface '%s': %i\n", @@ -592,6 +594,26 @@ void batadv_softif_destroy_sysfs(struct net_device *soft_iface) queue_work(batadv_event_workqueue, &bat_priv->cleanup_work); } +/** + * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink + * @soft_iface: the to-be-removed batman-adv interface + * @head: list pointer + */ +static void batadv_softif_destroy_netlink(struct net_device *soft_iface, + struct list_head *head) +{ + struct batadv_hard_iface *hard_iface; + + list_for_each_entry(hard_iface, &batadv_hardif_list, list) { + if (hard_iface->soft_iface == soft_iface) + batadv_hardif_disable_interface(hard_iface, + BATADV_IF_CLEANUP_KEEP); + } + + batadv_sysfs_del_meshif(soft_iface); + unregister_netdevice_queue(soft_iface, head); +} + int batadv_softif_is_valid(const struct net_device *net_dev) { if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) @@ -600,6 +622,13 @@ int batadv_softif_is_valid(const struct net_device *net_dev) return 0; } +struct rtnl_link_ops batadv_link_ops __read_mostly = { + .kind = "batadv", + .priv_size = sizeof(struct batadv_priv), + .setup = batadv_softif_init_early, + .dellink = batadv_softif_destroy_netlink, +}; + /* ethtool */ static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 49bc66bb774a..2f2472c2ea0d 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h @@ -27,5 +27,6 @@ void batadv_interface_rx(struct net_device *soft_iface, struct net_device *batadv_softif_create(const char *name); void batadv_softif_destroy_sysfs(struct net_device *soft_iface); int batadv_softif_is_valid(const struct net_device *net_dev); +extern struct rtnl_link_ops batadv_link_ops; #endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */