Skip to contentSkip to conversation

: Make VLAN devices work in net namespaces.

PATCH In review Pavel Emelyanov 3 participants 24 messages Apr 15, 2008 – Apr 16, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover : Make VLAN devices work in net namespaces.

This set does not intersect with the TUN one at all, since they both use generic net pointers.

It also includes some changes in RTNL code to facilitate VLAN netnsization and a bit more VLAN cleanups.

#1 lore raw

PATCH 1/10 : Relax for_each_netdev_safe in __rtnl_link_unregister.

Each potential list_del (happening from inside a ->dellink call) is followed by goto restart, so there's no need in _safe iteration.

---
 net/core/rtnetlink.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
net/core/rtnetlink.c +2 -2
index da99ac0..edc6dbf 100644
@@ -277,12 +277,12 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-	struct net_device *dev, *n;
+	struct net_device *dev;
 	struct net *net;
 
 	for_each_net(net) {
 restart:
-		for_each_netdev_safe(net, dev, n) {
+		for_each_netdev(net, dev) {
 			if (dev->rtnl_link_ops == ops) {
 				ops->dellink(dev);
 				goto restart;
Signature · 1 line
1.5.3.4
#3 lore raw

PATCH 2/10 : Introduce the rtnl_kill_links helper.

In reply to Pavel Emelyanov

This one is responsible for calling ->dellink on each net device found in net to help with vlan net_exit hook in the nearest future.

---
 include/net/rtnetlink.h |    1 +
 net/core/rtnetlink.c    |   29 +++++++++++++++++++++--------
 2 files changed, 22 insertions(+), 8 deletions(-)
include/net/rtnetlink.h +1 -0
index 793863e..3c1895e 100644
@@ -74,6 +74,7 @@ struct rtnl_link_ops {
 
 extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	__rtnl_link_unregister(struct rtnl_link_ops *ops);
+extern void	rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops);
 
 extern int	rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
net/core/rtnetlink.c +21 -8
index edc6dbf..bc39e41 100644
@@ -269,6 +269,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops)
 
 EXPORT_SYMBOL_GPL(rtnl_link_register);
 
+static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+	struct net_device *dev;
+restart:
+	for_each_netdev(net, dev) {
+		if (dev->rtnl_link_ops == ops) {
+			ops->dellink(dev);
+			goto restart;
+		}
+	}
+}
+
+void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+	rtnl_lock();
+	__rtnl_kill_links(net, ops);
+	rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(rtnl_kill_links);
+
 /**
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
@@ -277,17 +297,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-	struct net_device *dev;
 	struct net *net;
 
 	for_each_net(net) {
-restart:
-		for_each_netdev(net, dev) {
-			if (dev->rtnl_link_ops == ops) {
-				ops->dellink(dev);
-				goto restart;
-			}
-		}
+		__rtnl_kill_links(net, ops);
 	}
 	list_del(&ops->list);
 }
Signature · 1 line
1.5.3.4
#5 lore raw

PATCH 3/10 : Tag vlan_group_device with net device, not ifindex.

In reply to Pavel Emelyanov

Currently vlan group is searched using one key - the ifindex. We'll have to lookup the vlan_group by two keys - ifindex and net. Turning the vlan_group lookup key to struct net_device pointer will make this process easier.

Besides, this will eliminate one more place in the networking, that assumes that indexes are unique in the kernel.

---
 include/linux/if_vlan.h |    4 +++-
 net/8021q/vlan.c        |   22 +++++++++++-----------
 2 files changed, 14 insertions(+), 12 deletions(-)
include/linux/if_vlan.h +3 -1
index edd55af..15ace02 100644
@@ -81,7 +81,9 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
 #define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
 
 struct vlan_group {
-	int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
+	struct net_device	*real_dev; /* The ethernet(like) device
+					    * the vlan is attached to.
+					    */
 	unsigned int		nr_vlans;
 	struct hlist_node	hlist;	/* linked list */
 	struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
net/8021q/vlan.c +11 -11
index 5975ec3..cf8d810 100644
@@ -65,14 +65,14 @@ static inline unsigned int vlan_grp_hashfn(unsigned int idx)
 }
 
 /* Must be invoked with RCU read lock (no preempt) */
-static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
+static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
 {
 	struct vlan_group *grp;
 	struct hlist_node *n;
-	int hash = vlan_grp_hashfn(real_dev_ifindex);
+	int hash = vlan_grp_hashfn(real_dev->ifindex);
 
 	hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
-		if (grp->real_dev_ifindex == real_dev_ifindex)
+		if (grp->real_dev == real_dev)
 			return grp;
 	}
 
@@ -86,7 +86,7 @@ static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
 struct net_device *__find_vlan_dev(struct net_device *real_dev,
 				   unsigned short VID)
 {
-	struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
+	struct vlan_group *grp = __vlan_find_group(real_dev);
 
 	if (grp)
 		return vlan_group_get_device(grp, VID);
@@ -103,7 +103,7 @@ static void vlan_group_free(struct vlan_group *grp)
 	kfree(grp);
 }
 
-static struct vlan_group *vlan_group_alloc(int ifindex)
+static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
 {
 	struct vlan_group *grp;
 
@@ -111,9 +111,9 @@ static struct vlan_group *vlan_group_alloc(int ifindex)
 	if (!grp)
 		return NULL;
 
-	grp->real_dev_ifindex = ifindex;
+	grp->real_dev = real_dev;
 	hlist_add_head_rcu(&grp->hlist,
-			   &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
+			&vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
 	return grp;
 }
 
@@ -151,7 +151,7 @@ void unregister_vlan_dev(struct net_device *dev)
 
 	ASSERT_RTNL();
 
-	grp = __vlan_find_group(real_dev->ifindex);
+	grp = __vlan_find_group(real_dev);
 	BUG_ON(!grp);
 
 	vlan_proc_rem_dev(dev);
@@ -246,9 +246,9 @@ int register_vlan_dev(struct net_device *dev)
 	struct vlan_group *grp, *ngrp = NULL;
 	int err;
 
-	grp = __vlan_find_group(real_dev->ifindex);
+	grp = __vlan_find_group(real_dev);
 	if (!grp) {
-		ngrp = grp = vlan_group_alloc(real_dev->ifindex);
+		ngrp = grp = vlan_group_alloc(real_dev);
 		if (!grp)
 			return -ENOBUFS;
 	}
@@ -412,7 +412,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 		goto out;
 	}
 
-	grp = __vlan_find_group(dev->ifindex);
+	grp = __vlan_find_group(dev);
 	if (!grp)
 		goto out;
 
Signature · 1 line
1.5.3.4
Acked-by on v1 3/10
#6 lore raw

Re: [PATCH net-2.6.26 3/10][VLAN]: Tag vlan_group_device with net device, not ifindex.

Quoted 9 lines · Pavel Emelyanov

Currently vlan group is searched using one key - the ifindex. We'll have to lookup the vlan_group by two keys - ifindex and net. Turning the vlan_group lookup key to struct net_device pointer will make this process easier.

Besides, this will eliminate one more place in the networking, that assumes that indexes are unique in the kernel.

#7 lore raw

PATCH 4/10 : Introduce the vlan_net structure and init/exit net ops.

In reply to Pavel Emelyanov

Unlike TUN, it is empty from the very beginning, and will be eventually populated later.

---
 net/8021q/vlan.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 net/8021q/vlan.h |    5 +++++
 2 files changed, 51 insertions(+), 0 deletions(-)
net/8021q/vlan.c +46 -0
index cf8d810..9296601 100644
@@ -32,6 +32,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
 
 #include <linux/if_vlan.h>
 #include "vlan.h"
@@ -41,6 +42,8 @@
 
 /* Global VLAN variables */
 
+int vlan_net_id;
+
 /* Our listing of VLAN group(s) */
 static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
 
@@ -625,6 +628,41 @@ out:
 	return err;
 }
 
+static int vlan_init_net(struct net *net)
+{
+	int err;
+	struct vlan_net *vn;
+
+	err = -ENOMEM;
+	vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
+	if (vn == NULL)
+		goto err_alloc;
+
+	err = net_assign_generic(net, vlan_net_id, vn);
+	if (err < 0)
+		goto err_assign;
+
+	return 0;
+
+err_assign:
+	kfree(vn);
+err_alloc:
+	return err;
+}
+
+static void vlan_exit_net(struct net *net)
+{
+	struct vlan_net *vn;
+
+	vn = net_generic(net, vlan_net_id);
+	kfree(vn);
+}
+
+static struct pernet_operations vlan_net_ops = {
+	.init = vlan_init_net,
+	.exit = vlan_exit_net,
+};
+
 static int __init vlan_proto_init(void)
 {
 	int err;
@@ -632,6 +670,10 @@ static int __init vlan_proto_init(void)
 	pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
 	pr_info("All bugs added by %s\n", vlan_buggyright);
 
+	err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+	if (err < 0)
+		goto err0;
+
 	err = vlan_proc_init();
 	if (err < 0)
 		goto err1;
@@ -653,6 +695,8 @@ err3:
 err2:
 	vlan_proc_cleanup();
 err1:
+	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
+err0:
 	return err;
 }
 
@@ -673,6 +717,8 @@ static void __exit vlan_cleanup_module(void)
 
 	vlan_proc_cleanup();
 
+	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
+
 	synchronize_net();
 }
 
net/8021q/vlan.h +5 -0
index 51271ae..f27d8d6 100644
@@ -50,4 +50,9 @@ static inline int is_vlan_dev(struct net_device *dev)
 	return dev->priv_flags & IFF_802_1Q_VLAN;
 }
 
+extern int vlan_net_id;
+
+struct vlan_net {
+};
+
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
Signature · 1 line
1.5.3.4
#8 lore raw

Re: [PATCH net-2.6.26 4/10][VLAN]: Introduce the vlan_net structure and init/exit net ops.

net/8021q/vlan.c static int __init vlan_proto_init(void) · line 675

Quoted 7 lines · Pavel Emelyanov
net/8021q/vlan.c +3 -0
@@ -632,6 +670,10 @@ static int __init vlan_proto_init(void)
 	pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
 	pr_info("All bugs added by %s\n", vlan_buggyright);
 
+	err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+	if (err < 0)
+		goto err0;

I'm wondering what vlan_net_id is used for, but I can't find that function in the current net-2.6.26.git tree. What tree are these patches based on?

#9 lore raw

Re: [PATCH net-2.6.26 4/10][VLAN]: Introduce the vlan_net structure and init/exit net ops.

Quoted 5 lines · Patrick McHardy
Quoted 4 lines · Pavel Emelyanov
net/8021q/vlan.c +0 -0
@@ -632,6 +670,10 @@ static int __init vlan_proto_init(void)
 	pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
 	pr_info("All bugs added by %s\n", vlan_buggyright);
 
Quoted 8 lines

net/8021q/vlan.c static int __init vlan_proto_init(void) · line 675

Quoted 3 lines
net/8021q/vlan.c +3 -0
+	err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+	if (err < 0)
+		goto err0;

I'm wondering what vlan_net_id is used for, but I can't find that function in the current net-2.6.26.git tree. What tree are these patches based on?

They are for net-2.6.26 with this
http://marc.info/?l=linux-netdev&m=120799367318572&w=2
and this
http://marc.info/?l=linux-netdev&m=120799357618440&w=2
patches.

David said the he accepted them both and agreed that I send other work based on them.

Thanks,
Pavel

#11 lore raw

PATCH 5/10 : Add a net argument to proc init and cleanup calls.

In reply to Pavel Emelyanov

All proc files will be created in each net, so prepare them for this change now, not to mess it with real creation patch.

The net != &init_net checks in them are for git-bisect sanity, but I will drop them soon.

---
 net/8021q/vlan.c     |   15 +++++++--------
 net/8021q/vlanproc.c |   12 +++++++++---
 net/8021q/vlanproc.h |   10 ++++++----
 3 files changed, 22 insertions(+), 15 deletions(-)
net/8021q/vlan.c +7 -8
index 9296601..541542e 100644
@@ -642,8 +642,14 @@ static int vlan_init_net(struct net *net)
 	if (err < 0)
 		goto err_assign;
 
+	err = vlan_proc_init(net);
+	if (err < 0)
+		goto err_proc;
+
 	return 0;
 
+err_proc:
+	/* nothing */
 err_assign:
 	kfree(vn);
 err_alloc:
@@ -655,6 +661,7 @@ static void vlan_exit_net(struct net *net)
 	struct vlan_net *vn;
 
 	vn = net_generic(net, vlan_net_id);
+	vlan_proc_cleanup(net);
 	kfree(vn);
 }
 
@@ -674,10 +681,6 @@ static int __init vlan_proto_init(void)
 	if (err < 0)
 		goto err0;
 
-	err = vlan_proc_init();
-	if (err < 0)
-		goto err1;
-
 	err = register_netdevice_notifier(&vlan_notifier_block);
 	if (err < 0)
 		goto err2;
@@ -693,8 +696,6 @@ static int __init vlan_proto_init(void)
 err3:
 	unregister_netdevice_notifier(&vlan_notifier_block);
 err2:
-	vlan_proc_cleanup();
-err1:
 	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 err0:
 	return err;
@@ -715,8 +716,6 @@ static void __exit vlan_cleanup_module(void)
 	for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
 		BUG_ON(!hlist_empty(&vlan_group_hash[i]));
 
-	vlan_proc_cleanup();
-
 	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 
 	synchronize_net();
net/8021q/vlanproc.c +9 -3
index 24cd96e..4d13aeb 100644
@@ -138,8 +138,11 @@ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
  *	Clean up /proc/net/vlan entries
  */
 
-void vlan_proc_cleanup(void)
+void vlan_proc_cleanup(struct net *net)
 {
+	if (net != &init_net)
+		return;
+
 	if (proc_vlan_conf)
 		remove_proc_entry(name_conf, proc_vlan_dir);
 
@@ -155,8 +158,11 @@ void vlan_proc_cleanup(void)
  *	Create /proc/net/vlan entries
  */
 
-int __init vlan_proc_init(void)
+int vlan_proc_init(struct net *net)
 {
+	if (net != &init_net)
+		return 0;
+
 	proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
 	if (!proc_vlan_dir)
 		goto err;
@@ -169,7 +175,7 @@ int __init vlan_proc_init(void)
 
 err:
 	pr_err("%s: can't create entry in proc filesystem!\n", __func__);
-	vlan_proc_cleanup();
+	vlan_proc_cleanup(net);
 	return -ENOBUFS;
 }
 
net/8021q/vlanproc.h +6 -4
index da542ca..063f60a 100644
@@ -2,15 +2,17 @@
 #define __BEN_VLAN_PROC_INC__
 
 #ifdef CONFIG_PROC_FS
-int vlan_proc_init(void);
+struct net;
+
+int vlan_proc_init(struct net *net);
 int vlan_proc_rem_dev(struct net_device *vlandev);
 int vlan_proc_add_dev(struct net_device *vlandev);
-void vlan_proc_cleanup(void);
+void vlan_proc_cleanup(struct net *net);
 
 #else /* No CONFIG_PROC_FS */
 
-#define vlan_proc_init()	(0)
-#define vlan_proc_cleanup()	do {} while (0)
+#define vlan_proc_init(net)	(0)
+#define vlan_proc_cleanup(net)	do {} while (0)
 #define vlan_proc_add_dev(dev)	({(void)(dev), 0; })
 #define vlan_proc_rem_dev(dev)	({(void)(dev), 0; })
 #endif
Signature · 1 line
1.5.3.4
#12 lore raw

Re: [PATCH net-2.6.26 5/10][VLAN]: Add a net argument to proc init and cleanup calls.

Quoted 18 lines · Pavel Emelyanov

All proc files will be created in each net, so prepare them for this change now, not to mess it with real creation patch.

The net != &init_net checks in them are for git-bisect sanity, but I will drop them soon.

---
 net/8021q/vlan.c     |   15 +++++++--------
 net/8021q/vlanproc.c |   12 +++++++++---
 net/8021q/vlanproc.h |   10 ++++++----
 3 files changed, 22 insertions(+), 15 deletions(-)
net/8021q/vlan.c +0 -0
index 9296601..541542e 100644
@@ -642,8 +642,14 @@ static int vlan_init_net(struct net *net)
 	if (err < 0)

net/8021q/vlan.c static int vlan_init_net(struct net *net) · line 652

Quoted 10 lines
net/8021q/vlan.c +6 -0
 		goto err_assign;
 
+	err = vlan_proc_init(net);
+	if (err < 0)
+		goto err_proc;
+
 	return 0;
 
+err_proc:
+	/* nothing */

What is going to clean up net_generic_assign above?

Quoted 23 lines
net/8021q/vlan.c +1 -4
 err_assign:
 	kfree(vn);
 err_alloc:
@@ -655,6 +661,7 @@ static void vlan_exit_net(struct net *net)
 	struct vlan_net *vn;
 
 	vn = net_generic(net, vlan_net_id);
+	vlan_proc_cleanup(net);
 	kfree(vn);
 }
 
@@ -674,10 +681,6 @@ static int __init vlan_proto_init(void)
 	if (err < 0)
 		goto err0;
 
-	err = vlan_proc_init();
-	if (err < 0)
-		goto err1;
-
 	err = register_netdevice_notifier(&vlan_notifier_block);
 	if (err < 0)
 		goto err2;

net/8021q/vlan.c static int __init vlan_proto_init(void) · line 701

Quoted 8 lines
net/8021q/vlan.c +0 -2
@@ -693,8 +696,6 @@ static int __init vlan_proto_init(void)
 err3:
 	unregister_netdevice_notifier(&vlan_notifier_block);
 err2:
-	vlan_proc_cleanup();
-err1:
 	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 err0:
 	return err;

This could be done nicer, not leaving holes in the numbering.

#13 lore raw

Re: [PATCH net-2.6.26 5/10][VLAN]: Add a net argument to proc init and cleanup calls.

Quoted 11 lines
Quoted 11 lines

+++ b/net/8021q/vlan.c

net/8021q/vlan.c +4 -0
@@ -642,8 +642,14 @@ static int vlan_init_net(struct net *net)
 	if (err < 0)
 		goto err_assign;
 
+	err = vlan_proc_init(net);
+	if (err < 0)
+		goto err_proc;
+
 	return 0;
 
Quoted 4 lines

net/8021q/vlan.c static int vlan_init_net(struct net *net) · line 652

Quoted 2 lines
net/8021q/vlan.c +2 -0
+err_proc:
+	/* nothing */

What is going to clean up net_generic_assign above?

This is not required. Net will be just destroyed after this function returns.

Quoted 11 lines

net/8021q/vlan.c static int __init vlan_proto_init(void) · line 701

Quoted 9 lines
net/8021q/vlan.c +0 -2
@@ -693,8 +696,6 @@ static int __init vlan_proto_init(void)
 err3:
 	unregister_netdevice_notifier(&vlan_notifier_block);
 err2:
-	vlan_proc_cleanup();
-err1:
 	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 err0:
 	return err;

This could be done nicer, not leaving holes in the numbering.

Well, yes. Bu this patch is large enough without it. Can I make this in a separate patch?

#14 lore raw

Re: [PATCH net-2.6.26 5/10][VLAN]: Add a net argument to proc init and cleanup calls.

Quoted 11 lines · Pavel Emelyanov
Quoted 11 lines
Quoted 11 lines

+++ b/net/8021q/vlan.c

net/8021q/vlan.c +4 -0
@@ -642,8 +642,14 @@ static int vlan_init_net(struct net *net)
 	if (err < 0)
 		goto err_assign;
 
+	err = vlan_proc_init(net);
+	if (err < 0)
+		goto err_proc;
+
 	return 0;
 
Quoted 6 lines
Quoted 3 lines

net/8021q/vlan.c static int vlan_init_net(struct net *net) · line 652

Quoted 2 lines
net/8021q/vlan.c +2 -0
+err_proc:
+	/* nothing */

What is going to clean up net_generic_assign above?

This is not required. Net will be just destroyed after this function returns.

Thanks for the explanation, I wasn't sure about that.

Quoted 12 lines
Quoted 11 lines

net/8021q/vlan.c static int __init vlan_proto_init(void) · line 701

Quoted 10 lines
net/8021q/vlan.c +0 -2
@@ -693,8 +696,6 @@ static int __init vlan_proto_init(void)
 err3:
 	unregister_netdevice_notifier(&vlan_notifier_block);
 err2:
-	vlan_proc_cleanup();
-err1:
 	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
 err0:
 	return err;

This could be done nicer, not leaving holes in the numbering.

Quoted 2 lines

Well, yes. Bu this patch is large enough without it. Can I make this in a separate patch?

Of course, thanks.

#15 lore raw

PATCH 6/10 : Create proc entries in the proper net.

In reply to Pavel Emelyanov

The proc_vlan_dir and proc_vlan_conf migrate on the struct vlan_net and their creation uses the struct net.

The devices' entries use the corresponding device's net.

---
 net/8021q/vlan.h     |    6 ++++++
 net/8021q/vlanproc.c |   44 +++++++++++++++++---------------------------
 2 files changed, 23 insertions(+), 27 deletions(-)
net/8021q/vlan.h +6 -0
index f27d8d6..7258357 100644
@@ -52,7 +52,13 @@ static inline int is_vlan_dev(struct net_device *dev)
 
 extern int vlan_net_id;
 
+struct proc_dir_entry;
+
 struct vlan_net {
+	/* /proc/net/vlan */
+	struct proc_dir_entry *proc_vlan_dir;
+	/* /proc/net/vlan/config */
+	struct proc_dir_entry *proc_vlan_conf;
 };
 
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
net/8021q/vlanproc.c +17 -27

90 lines not on this page · raw message

Signature · 1 line
1.5.3.4
#17 lore raw

PATCH 7/10 : Make the /proc/net/vlan/conf file show per-net info.

In reply to Pavel Emelyanov

It is created in a proper net, so make is show info, related to this particular net.

---
 net/8021q/vlanproc.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)
net/8021q/vlanproc.c +8 -5
index 995544b..cc17b72 100644
@@ -80,7 +80,8 @@ static const struct seq_operations vlan_seq_ops = {
 
 static int vlan_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &vlan_seq_ops);
+	return seq_open_net(inode, file, &vlan_seq_ops,
+			sizeof(struct seq_net_private));
 }
 
 static const struct file_operations vlan_fops = {
@@ -88,7 +89,7 @@ static const struct file_operations vlan_fops = {
 	.open    = vlan_seq_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_net,
 };
 
 /*
@@ -211,6 +212,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 	__acquires(dev_base_lock)
 {
 	struct net_device *dev;
+	struct net *net = seq_file_net(seq);
 	loff_t i = 1;
 
 	read_lock(&dev_base_lock);
@@ -218,7 +220,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for_each_netdev(&init_net, dev) {
+	for_each_netdev(net, dev) {
 		if (!is_vlan_dev(dev))
 			continue;
 
@@ -232,14 +234,15 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct net_device *dev;
+	struct net *net = seq_file_net(seq);
 
 	++*pos;
 
 	dev = (struct net_device *)v;
 	if (v == SEQ_START_TOKEN)
-		dev = net_device_entry(&init_net.dev_base_head);
+		dev = net_device_entry(&net->dev_base_head);
 
-	for_each_netdev_continue(&init_net, dev) {
+	for_each_netdev_continue(net, dev) {
 		if (!is_vlan_dev(dev))
 			continue;
 
Signature · 1 line
1.5.3.4
#19 lore raw

PATCH 8/10 : Make the vlan_name_type per-net.

In reply to Pavel Emelyanov

This includes moving one on the struct vlan_net and s/vlan_name_type/vn->name_type/ over the code.

---
 net/8021q/vlan.c     |   14 +++++++++-----
 net/8021q/vlan.h     |    4 ++--
 net/8021q/vlanproc.c |    7 +++++--
 3 files changed, 16 insertions(+), 9 deletions(-)
net/8021q/vlan.c +9 -5
index 541542e..5cacad0 100644
@@ -52,9 +52,6 @@ static char vlan_version[] = DRV_VERSION;
 static char vlan_copyright[] = "Ben Greear <[email protected]>";
 static char vlan_buggyright[] = "David S. Miller <[email protected]>";
 
-/* Determines interface naming scheme. */
-unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
-
 static struct packet_type vlan_packet_type = {
 	.type = __constant_htons(ETH_P_8021Q),
 	.func = vlan_skb_recv, /* VLAN receive method */
@@ -299,6 +296,8 @@ static int register_vlan_device(struct net_device *real_dev,
 				unsigned short VLAN_ID)
 {
 	struct net_device *new_dev;
+	struct net *net = dev_net(real_dev);
+	struct vlan_net *vn = net_generic(net, vlan_net_id);
 	char name[IFNAMSIZ];
 	int err;
 
@@ -310,7 +309,7 @@ static int register_vlan_device(struct net_device *real_dev,
 		return err;
 
 	/* Gotta set up the fields for the device. */
-	switch (vlan_name_type) {
+	switch (vn->name_type) {
 	case VLAN_NAME_TYPE_RAW_PLUS_VID:
 		/* name will look like:	 eth1.0005 */
 		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
@@ -580,7 +579,10 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 			break;
 		if ((args.u.name_type >= 0) &&
 		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
-			vlan_name_type = args.u.name_type;
+			struct vlan_net *vn;
+
+			vn = net_generic(net, vlan_net_id);
+			vn->name_type = args.u.name_type;
 			err = 0;
 		} else {
 			err = -EINVAL;
@@ -642,6 +644,8 @@ static int vlan_init_net(struct net *net)
 	if (err < 0)
 		goto err_assign;
 
+	vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
+
 	err = vlan_proc_init(net);
 	if (err < 0)
 		goto err_proc;
net/8021q/vlan.h +2 -2
index 7258357..5229a72 100644
@@ -3,8 +3,6 @@
 
 #include <linux/if_vlan.h>
 
-extern unsigned short vlan_name_type;
-
 #define VLAN_GRP_HASH_SHIFT	5
 #define VLAN_GRP_HASH_SIZE	(1 << VLAN_GRP_HASH_SHIFT)
 #define VLAN_GRP_HASH_MASK	(VLAN_GRP_HASH_SIZE - 1)
@@ -59,6 +57,8 @@ struct vlan_net {
 	struct proc_dir_entry *proc_vlan_dir;
 	/* /proc/net/vlan/config */
 	struct proc_dir_entry *proc_vlan_conf;
+	/* Determines interface naming scheme. */
+	unsigned short name_type;
 };
 
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
net/8021q/vlanproc.c +5 -2
index cc17b72..daad006 100644
@@ -260,13 +260,16 @@ static void vlan_seq_stop(struct seq_file *seq, void *v)
 
 static int vlan_seq_show(struct seq_file *seq, void *v)
 {
+	struct net *net = seq_file_net(seq);
+	struct vlan_net *vn = net_generic(net, vlan_net_id);
+
 	if (v == SEQ_START_TOKEN) {
 		const char *nmtype = NULL;
 
 		seq_puts(seq, "VLAN Dev name	 | VLAN ID\n");
 
-		if (vlan_name_type < ARRAY_SIZE(vlan_name_type_str))
-		    nmtype =  vlan_name_type_str[vlan_name_type];
+		if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
+		    nmtype =  vlan_name_type_str[vn->name_type];
 
 		seq_printf(seq, "Name-Type: %s\n",
 			   nmtype ? nmtype :  "UNKNOWN");
Signature · 1 line
1.5.3.4
#20 lore raw

PATCH 9/10 : Allow vlan devices registration in net namespaces.

In reply to Pavel Emelyanov

This one is similar to what I've done for TUN - set the proper net after device allocation and clean VLANs on net exit (use the rtnl_kill_links helper finally).

Plus, drop explicit init_net usage and net != &init_net checks.

---
 net/8021q/vlan.c         |    7 +++----
 net/8021q/vlan_dev.c     |    3 ---
 net/8021q/vlan_netlink.c |    2 +-
 3 files changed, 4 insertions(+), 8 deletions(-)
net/8021q/vlan.c +3 -4
index 5cacad0..7e9d22e 100644
@@ -340,6 +340,7 @@ static int register_vlan_device(struct net_device *real_dev,
 	if (new_dev == NULL)
 		return -ENOBUFS;
 
+	dev_net_set(new_dev, net);
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
 	 */
@@ -406,9 +407,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	int i, flgs;
 	struct net_device *vlandev;
 
-	if (dev_net(dev) != &init_net)
-		return NOTIFY_DONE;
-
 	if (is_vlan_dev(dev)) {
 		__vlan_device_event(dev, event);
 		goto out;
@@ -534,7 +532,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 	case GET_VLAN_REALDEV_NAME_CMD:
 	case GET_VLAN_VID_CMD:
 		err = -ENODEV;
-		dev = __dev_get_by_name(&init_net, args.device1);
+		dev = __dev_get_by_name(net, args.device1);
 		if (!dev)
 			goto out;
 
@@ -665,6 +663,7 @@ static void vlan_exit_net(struct net *net)
 	struct vlan_net *vn;
 
 	vn = net_generic(net, vlan_net_id);
+	rtnl_kill_links(net, &vlan_link_ops);
 	vlan_proc_cleanup(net);
 	kfree(vn);
 }
net/8021q/vlan_dev.c +0 -3
index 4ae0d7e..c961f08 100644
@@ -153,9 +153,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 	struct net_device_stats *stats;
 	unsigned short vlan_TCI;
 
-	if (dev_net(dev) != &init_net)
-		goto err_free;
-
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		goto err_free;
net/8021q/vlan_netlink.c +1 -1
index e32eeb3..c93e69e 100644
@@ -113,7 +113,7 @@ static int vlan_newlink(struct net_device *dev,
 
 	if (!tb[IFLA_LINK])
 		return -EINVAL;
-	real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
+	real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
 	if (!real_dev)
 		return -ENODEV;
 
Signature · 1 line
1.5.3.4
#21 lore raw

PATCH 10/10 : Handle vlan devices net namespace changing.

In reply to Pavel Emelyanov

When van device is moved to another namespace proc files, related to this device, should also change one.

Use the netdev REGISTER and UNREGISTER event handlers for this.

---
 net/8021q/vlan.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)
net/8021q/vlan.c +8 -5
index 7e9d22e..2a739ad 100644
@@ -154,8 +154,6 @@ void unregister_vlan_dev(struct net_device *dev)
 	grp = __vlan_find_group(real_dev);
 	BUG_ON(!grp);
 
-	vlan_proc_rem_dev(dev);
-
 	/* Take it out of our own structures, but be sure to interlock with
 	 * HW accelerating devices or SW vlan input packet processing.
 	 */
@@ -278,9 +276,6 @@ int register_vlan_dev(struct net_device *dev)
 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 		real_dev->vlan_rx_add_vid(real_dev, vlan_id);
 
-	if (vlan_proc_add_dev(dev) < 0)
-		pr_warning("8021q: failed to add proc entry for %s\n",
-			   dev->name);
 	return 0;
 
 out_free_group:
@@ -396,6 +391,14 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
 			pr_warning("8021q: failed to change proc name for %s\n",
 					dev->name);
 		break;
+	case NETDEV_REGISTER:
+		if (vlan_proc_add_dev(dev) < 0)
+			pr_warning("8021q: failed to add proc entry for %s\n",
+					dev->name);
+		break;
+	case NETDEV_UNREGISTER:
+		vlan_proc_rem_dev(dev);
+		break;
 	}
 }
 
Signature · 1 line
1.5.3.4