[v3,5/6] batman-adv: Allow to use rntl_link for device creation/deletion

Message ID 1360573828-24399-5-git-send-email-lindner_marek@yahoo.de (mailing list archive)
State Accepted, archived
Commit 5317331775c3168b8155b03ec89b1c4c508b9043
Headers

Commit Message

Marek Lindner Feb. 11, 2013, 9:10 a.m. UTC
  From: Sven Eckelmann <sven@narfation.org>

The sysfs configuration interface of batman-adv to add/remove soft-interfaces
is not deadlock free and doesn't follow the currently common way to create new
virtual interfaces.

An additional interface though rtnl_link is introduced which provides easy device
creation/deletion with tools like "ip":

$ ip link add dev bat0 type batadv
$ ip link del dev bat0

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 main.c           |    2 ++
 main.h           |    1 +
 soft-interface.c |   29 +++++++++++++++++++++++++++++
 soft-interface.h |    1 +
 4 files changed, 33 insertions(+)
  

Comments

Marek Lindner Feb. 16, 2013, 9:18 a.m. UTC | #1
On Monday, February 11, 2013 17:10:26 Marek Lindner wrote:
> From: Sven Eckelmann <sven@narfation.org>
> 
> The sysfs configuration interface of batman-adv to add/remove
> soft-interfaces is not deadlock free and doesn't follow the currently
> common way to create new virtual interfaces.
> 
> An additional interface though rtnl_link is introduced which provides easy
> device creation/deletion with tools like "ip":
> 
> $ ip link add dev bat0 type batadv
> $ ip link del dev bat0
> 
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
>  main.c           |    2 ++
>  main.h           |    1 +
>  soft-interface.c |   29 +++++++++++++++++++++++++++++
>  soft-interface.h |    1 +
>  4 files changed, 33 insertions(+)

Applied in revision 5317331.

Thanks,
Marek
  

Patch

diff --git a/main.c b/main.c
index bbb91a5..afccc3d 100644
--- a/main.c
+++ b/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/main.h b/main.h
index 8a9caa0..140f008 100644
--- a/main.h
+++ b/main.h
@@ -152,6 +152,7 @@  enum batadv_uev_type {
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <net/sock.h>		/* struct sock */
+#include <net/rtnetlink.h>
 #include <linux/jiffies.h>
 #include <linux/seq_file.h>
 #include "compat.h"
diff --git a/soft-interface.c b/soft-interface.c
index bc77a5b..4ef1649 100644
--- a/soft-interface.c
+++ b/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
+ */
+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/soft-interface.h b/soft-interface.h
index 49bc66b..2f2472c 100644
--- a/soft-interface.h
+++ b/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_ */