netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 00/12][NETNS][IPV6] Finish the routing per namespace
@ 2008-03-04 21:03 Daniel Lezcano
  2008-03-04 21:03 ` [patch 01/12][NETNS][IPV6] route6 - create route6 proc files for the namespace Daniel Lezcano
                   ` (12 more replies)
  0 siblings, 13 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

This second round of patches makes the routing per namespace to be 
complete and to have the routing engine to support multiple network
namespace.

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 01/12][NETNS][IPV6] route6 - create route6 proc files for the namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 02/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_lookup Daniel Lezcano
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-procfs.patch --]
[-- Type: text/plain, Size: 3088 bytes --]

Make /proc/net/ipv6_route and /proc/net/rt6_stats to be per namespace.
These proc files are now created when the network namespace is initialized.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 net/ipv6/route.c |   70 +++++++++++++++++++++----------------------------------
 1 file changed, 27 insertions(+), 43 deletions(-)

Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -2377,40 +2377,6 @@ static const struct file_operations rt6_
 	.llseek	 = seq_lseek,
 	.release = single_release,
 };
-
-static int ipv6_route_proc_init(struct net *net)
-{
-	int ret = -ENOMEM;
-	if (!proc_net_fops_create(net, "ipv6_route",
-				  0, &ipv6_route_proc_fops))
-		goto out;
-
-	if (!proc_net_fops_create(net, "rt6_stats",
-				  S_IRUGO, &rt6_stats_seq_fops))
-		goto out_ipv6_route;
-
-	ret = 0;
-out:
-	return ret;
-out_ipv6_route:
-	proc_net_remove(net, "ipv6_route");
-	goto out;
-}
-
-static void ipv6_route_proc_fini(struct net *net)
-{
-	proc_net_remove(net, "ipv6_route");
-	proc_net_remove(net, "rt6_stats");
-}
-#else
-static inline int ipv6_route_proc_init(struct net *net)
-{
-	return 0;
-}
-static inline void ipv6_route_proc_fini(struct net *net)
-{
-	return ;
-}
 #endif	/* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -2544,6 +2510,28 @@ struct ctl_table *ipv6_route_sysctl_init
 }
 #endif
 
+static int ip6_route_net_init(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+	proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
+	proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+#endif
+	return 0;
+}
+
+static void ip6_route_net_exit(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+	proc_net_remove(net, "ipv6_route");
+	proc_net_remove(net, "rt6_stats");
+#endif
+}
+
+static struct pernet_operations ip6_route_net_ops = {
+	.init = ip6_route_net_init,
+	.exit = ip6_route_net_exit,
+};
+
 int __init ip6_route_init(void)
 {
 	int ret;
@@ -2560,13 +2548,9 @@ int __init ip6_route_init(void)
 	if (ret)
 		goto out_kmem_cache;
 
-	ret = ipv6_route_proc_init(&init_net);
-	if (ret)
-		goto out_fib6_init;
-
 	ret = xfrm6_init();
 	if (ret)
-		goto out_proc_init;
+		goto out_fib6_init;
 
 	ret = fib6_rules_init();
 	if (ret)
@@ -2578,7 +2562,9 @@ int __init ip6_route_init(void)
 	    __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
 		goto fib6_rules_init;
 
-	ret = 0;
+	ret = register_pernet_subsys(&ip6_route_net_ops);
+	if (ret)
+		goto fib6_rules_init;
 out:
 	return ret;
 
@@ -2586,8 +2572,6 @@ fib6_rules_init:
 	fib6_rules_cleanup();
 xfrm6_init:
 	xfrm6_fini();
-out_proc_init:
-	ipv6_route_proc_fini(&init_net);
 out_fib6_init:
 	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();
@@ -2598,8 +2582,8 @@ out_kmem_cache:
 
 void ip6_route_cleanup(void)
 {
+	unregister_pernet_subsys(&ip6_route_net_ops);
 	fib6_rules_cleanup();
-	ipv6_route_proc_fini(&init_net);
 	xfrm6_fini();
 	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 02/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_lookup
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
  2008-03-04 21:03 ` [patch 01/12][NETNS][IPV6] route6 - create route6 proc files for the namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 03/12][NETNS][IPV6] route6 - Make proc entry /proc/net/rt6_stats per namespace Daniel Lezcano
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-pass-network-namespace-to-rt6_lookup.patch --]
[-- Type: text/plain, Size: 5909 bytes --]

Add a network namespace parameter to rt6_lookup().

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_route.h |    3 ++-
 net/ipv6/addrconf.c     |    4 ++--
 net/ipv6/anycast.c      |    2 +-
 net/ipv6/ip6_tunnel.c   |    4 ++--
 net/ipv6/mcast.c        |    4 ++--
 net/ipv6/route.c        |   10 +++++-----
 net/ipv6/sit.c          |    4 ++--
 7 files changed, 16 insertions(+), 15 deletions(-)

Index: net-2.6.26/include/net/ip6_route.h
===================================================================
--- net-2.6.26.orig/include/net/ip6_route.h
+++ net-2.6.26/include/net/ip6_route.h
@@ -69,7 +69,8 @@ extern void			rt6_sndmsg(int type, struc
 					   int dstlen, int srclen,
 					   int metric, __u32 flags);
 
-extern struct rt6_info		*rt6_lookup(struct in6_addr *daddr,
+extern struct rt6_info		*rt6_lookup(struct net *net,
+					    struct in6_addr *daddr,
 					    struct in6_addr *saddr,
 					    int oif, int flags);
 
Index: net-2.6.26/net/ipv6/addrconf.c
===================================================================
--- net-2.6.26.orig/net/ipv6/addrconf.c
+++ net-2.6.26/net/ipv6/addrconf.c
@@ -753,7 +753,7 @@ static void ipv6_del_addr(struct inet6_i
 		struct rt6_info *rt;
 
 		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-		rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
+		rt = rt6_lookup(&init_net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
 
 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
 			if (onlink == 0) {
@@ -1700,7 +1700,7 @@ void addrconf_prefix_rcv(struct net_devi
 
 	if (pinfo->onlink) {
 		struct rt6_info *rt;
-		rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
+		rt = rt6_lookup(&init_net, &pinfo->prefix, NULL, dev->ifindex, 1);
 
 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
 			if (rt->rt6i_flags&RTF_EXPIRES) {
Index: net-2.6.26/net/ipv6/anycast.c
===================================================================
--- net-2.6.26.orig/net/ipv6/anycast.c
+++ net-2.6.26/net/ipv6/anycast.c
@@ -101,7 +101,7 @@ int ipv6_sock_ac_join(struct sock *sk, i
 	if (ifindex == 0) {
 		struct rt6_info *rt;
 
-		rt = rt6_lookup(addr, NULL, 0, 0);
+		rt = rt6_lookup(&init_net, addr, NULL, 0, 0);
 		if (rt) {
 			dev = rt->rt6i_dev;
 			dev_hold(dev);
Index: net-2.6.26/net/ipv6/ip6_tunnel.c
===================================================================
--- net-2.6.26.orig/net/ipv6/ip6_tunnel.c
+++ net-2.6.26/net/ipv6/ip6_tunnel.c
@@ -602,7 +602,7 @@ ip6ip6_err(struct sk_buff *skb, struct i
 		skb_reset_network_header(skb2);
 
 		/* Try to guess incoming interface */
-		rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0);
+		rt = rt6_lookup(&init_net, &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
 
 		if (rt && rt->rt6i_dev)
 			skb2->dev = rt->rt6i_dev;
@@ -1112,7 +1112,7 @@ static void ip6_tnl_link_config(struct i
 		int strict = (ipv6_addr_type(&p->raddr) &
 			      (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
 
-		struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
+		struct rt6_info *rt = rt6_lookup(&init_net, &p->raddr, &p->laddr,
 						 p->link, strict);
 
 		if (rt == NULL)
Index: net-2.6.26/net/ipv6/mcast.c
===================================================================
--- net-2.6.26.orig/net/ipv6/mcast.c
+++ net-2.6.26/net/ipv6/mcast.c
@@ -208,7 +208,7 @@ int ipv6_sock_mc_join(struct sock *sk, i
 
 	if (ifindex == 0) {
 		struct rt6_info *rt;
-		rt = rt6_lookup(addr, NULL, 0, 0);
+		rt = rt6_lookup(&init_net, addr, NULL, 0, 0);
 		if (rt) {
 			dev = rt->rt6i_dev;
 			dev_hold(dev);
@@ -294,7 +294,7 @@ static struct inet6_dev *ip6_mc_find_dev
 	if (ifindex == 0) {
 		struct rt6_info *rt;
 
-		rt = rt6_lookup(group, NULL, 0, 0);
+		rt = rt6_lookup(&init_net, group, NULL, 0, 0);
 		if (rt) {
 			dev = rt->rt6i_dev;
 			dev_hold(dev);
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -553,8 +553,8 @@ out:
 
 }
 
-struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
-			    int oif, int strict)
+struct rt6_info *rt6_lookup(struct net *net, struct in6_addr *daddr,
+			    struct in6_addr *saddr, int oif, int strict)
 {
 	struct flowi fl = {
 		.oif = oif,
@@ -572,7 +572,7 @@ struct rt6_info *rt6_lookup(struct in6_a
 		flags |= RT6_LOOKUP_F_HAS_SADDR;
 	}
 
-	dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_lookup);
+	dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup);
 	if (dst->error == 0)
 		return (struct rt6_info *) dst;
 
@@ -1159,7 +1159,7 @@ int ip6_route_add(struct fib6_config *cf
 			if (!(gwa_type&IPV6_ADDR_UNICAST))
 				goto out;
 
-			grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1);
+			grt = rt6_lookup(&init_net, gw_addr, NULL, cfg->fc_ifindex, 1);
 
 			err = -EHOSTUNREACH;
 			if (grt == NULL)
@@ -1483,7 +1483,7 @@ void rt6_pmtu_discovery(struct in6_addr 
 	struct rt6_info *rt, *nrt;
 	int allfrag = 0;
 
-	rt = rt6_lookup(daddr, saddr, dev->ifindex, 0);
+	rt = rt6_lookup(dev->nd_net, daddr, saddr, dev->ifindex, 0);
 	if (rt == NULL)
 		return;
 
Index: net-2.6.26/net/ipv6/sit.c
===================================================================
--- net-2.6.26.orig/net/ipv6/sit.c
+++ net-2.6.26/net/ipv6/sit.c
@@ -339,11 +339,11 @@ out:
 	skb_reset_network_header(skb2);
 
 	/* Try to guess incoming interface */
-	rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0);
+	rt6i = rt6_lookup(&init_net, &iph6->saddr, NULL, NULL, 0);
 	if (rt6i && rt6i->rt6i_dev) {
 		skb2->dev = rt6i->rt6i_dev;
 
-		rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0);
+		rt6i = rt6_lookup(&init_net, &iph6->daddr, &iph6->saddr, NULL, 0);
 
 		if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
 			struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev);

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 03/12][NETNS][IPV6] route6 - Make proc entry /proc/net/rt6_stats per namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
  2008-03-04 21:03 ` [patch 01/12][NETNS][IPV6] route6 - create route6 proc files for the namespace Daniel Lezcano
  2008-03-04 21:03 ` [patch 02/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_lookup Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 04/12][NETNS][IPV6] route6 - Pass network namespace to rt6_add_route_info and rt6_get_route_info Daniel Lezcano
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-make-proc-entry-rt6_stats-per-namespace.patch --]
[-- Type: text/plain, Size: 2055 bytes --]

Make the proc entry /proc/net/rt6_stats work in all network namespace.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 net/ipv6/route.c |   26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -2353,21 +2353,31 @@ static const struct file_operations ipv6
 
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
 {
+	struct net *net = (struct net *)seq->private;
 	seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
-		   init_net.ipv6.rt6_stats->fib_nodes,
-		   init_net.ipv6.rt6_stats->fib_route_nodes,
-		   init_net.ipv6.rt6_stats->fib_rt_alloc,
-		   init_net.ipv6.rt6_stats->fib_rt_entries,
-		   init_net.ipv6.rt6_stats->fib_rt_cache,
+		   net->ipv6.rt6_stats->fib_nodes,
+		   net->ipv6.rt6_stats->fib_route_nodes,
+		   net->ipv6.rt6_stats->fib_rt_alloc,
+		   net->ipv6.rt6_stats->fib_rt_entries,
+		   net->ipv6.rt6_stats->fib_rt_cache,
 		   atomic_read(&ip6_dst_ops.entries),
-		   init_net.ipv6.rt6_stats->fib_discarded_routes);
+		   net->ipv6.rt6_stats->fib_discarded_routes);
 
 	return 0;
 }
 
 static int rt6_stats_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, rt6_stats_seq_show, NULL);
+	struct net *net = get_proc_net(inode);
+	return single_open(file, rt6_stats_seq_show, net);
+}
+
+static int rt6_stats_seq_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct net *net = (struct net *)seq->private;
+	put_net(net);
+	return single_release(inode, file);
 }
 
 static const struct file_operations rt6_stats_seq_fops = {
@@ -2375,7 +2385,7 @@ static const struct file_operations rt6_
 	.open	 = rt6_stats_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = single_release,
+	.release = rt6_stats_seq_release,
 };
 #endif	/* CONFIG_PROC_FS */
 

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 04/12][NETNS][IPV6] route6 - Pass network namespace to rt6_add_route_info and rt6_get_route_info
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (2 preceding siblings ...)
  2008-03-04 21:03 ` [patch 03/12][NETNS][IPV6] route6 - Make proc entry /proc/net/rt6_stats per namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 05/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_purge_dflt_routers Daniel Lezcano
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-pass-network-namespace-to-rt6_x_route_info.patch --]
[-- Type: text/plain, Size: 3546 bytes --]

Add a network namespace parameter to rt6_add_route_info() and 
rt6_get_route_info to enable them to handle multiple network namespaces.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 net/ipv6/route.c |   25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -88,10 +88,12 @@ static void		ip6_link_failure(struct sk_
 static void		ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
+static struct rt6_info *rt6_add_route_info(struct net *net,
+					   struct in6_addr *prefix, int prefixlen,
 					   struct in6_addr *gwaddr, int ifindex,
 					   unsigned pref);
-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
+static struct rt6_info *rt6_get_route_info(struct net *net,
+					   struct in6_addr *prefix, int prefixlen,
 					   struct in6_addr *gwaddr, int ifindex);
 #endif
 
@@ -442,6 +444,7 @@ static struct rt6_info *rt6_select(struc
 int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 		  struct in6_addr *gwaddr)
 {
+	struct net *net = dev->nd_net;
 	struct route_info *rinfo = (struct route_info *) opt;
 	struct in6_addr prefix_buf, *prefix;
 	unsigned int pref;
@@ -489,7 +492,8 @@ int rt6_route_rcv(struct net_device *dev
 		prefix = &prefix_buf;
 	}
 
-	rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
+	rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr,
+				dev->ifindex);
 
 	if (rt && !lifetime) {
 		ip6_del_rt(rt);
@@ -497,7 +501,7 @@ int rt6_route_rcv(struct net_device *dev
 	}
 
 	if (!rt && lifetime)
-		rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
+		rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
 					pref);
 	else if (rt)
 		rt->rt6i_flags = RTF_ROUTEINFO |
@@ -1588,14 +1592,15 @@ static struct rt6_info * ip6_rt_copy(str
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
+static struct rt6_info *rt6_get_route_info(struct net *net,
+					   struct in6_addr *prefix, int prefixlen,
 					   struct in6_addr *gwaddr, int ifindex)
 {
 	struct fib6_node *fn;
 	struct rt6_info *rt = NULL;
 	struct fib6_table *table;
 
-	table = fib6_get_table(&init_net, RT6_TABLE_INFO);
+	table = fib6_get_table(net, RT6_TABLE_INFO);
 	if (table == NULL)
 		return NULL;
 
@@ -1619,7 +1624,8 @@ out:
 	return rt;
 }
 
-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
+static struct rt6_info *rt6_add_route_info(struct net *net,
+					   struct in6_addr *prefix, int prefixlen,
 					   struct in6_addr *gwaddr, int ifindex,
 					   unsigned pref)
 {
@@ -1630,6 +1636,9 @@ static struct rt6_info *rt6_add_route_in
 		.fc_dst_len	= prefixlen,
 		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
 				  RTF_UP | RTF_PREF(pref),
+		.fc_nlinfo.pid = 0,
+		.fc_nlinfo.nlh = NULL,
+		.fc_nlinfo.nl_net = net,
 	};
 
 	ipv6_addr_copy(&cfg.fc_dst, prefix);
@@ -1641,7 +1650,7 @@ static struct rt6_info *rt6_add_route_in
 
 	ip6_route_add(&cfg);
 
-	return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
+	return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
 }
 #endif
 

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 05/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_purge_dflt_routers
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (3 preceding siblings ...)
  2008-03-04 21:03 ` [patch 04/12][NETNS][IPV6] route6 - Pass network namespace to rt6_add_route_info and rt6_get_route_info Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace Daniel Lezcano
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-pass-network-namespace-to-rt6_purge_dflt_routers.patch --]
[-- Type: text/plain, Size: 1918 bytes --]

Add a network namespace parameter to rt6_purge_dflt_routers.
This is needed to call fib6_get_table with the appropriate 
network namespace.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_route.h |    2 +-
 net/ipv6/addrconf.c     |    2 +-
 net/ipv6/route.c        |    4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

Index: net-2.6.26/include/net/ip6_route.h
===================================================================
--- net-2.6.26.orig/include/net/ip6_route.h
+++ net-2.6.26/include/net/ip6_route.h
@@ -95,7 +95,7 @@ extern struct rt6_info *	rt6_add_dflt_ro
 						    struct net_device *dev,
 						    unsigned int pref);
 
-extern void			rt6_purge_dflt_routers(void);
+extern void			rt6_purge_dflt_routers(struct net *net);
 
 extern int			rt6_route_rcv(struct net_device *dev,
 					      u8 *opt, int len,
Index: net-2.6.26/net/ipv6/addrconf.c
===================================================================
--- net-2.6.26.orig/net/ipv6/addrconf.c
+++ net-2.6.26/net/ipv6/addrconf.c
@@ -493,7 +493,7 @@ static void addrconf_fixup_forwarding(st
 		dev_forward_change((struct inet6_dev *)table->extra1);
 
 	if (*p)
-		rt6_purge_dflt_routers();
+		rt6_purge_dflt_routers(net);
 }
 #endif
 
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -1697,13 +1697,13 @@ struct rt6_info *rt6_add_dflt_router(str
 	return rt6_get_dflt_router(gwaddr, dev);
 }
 
-void rt6_purge_dflt_routers(void)
+void rt6_purge_dflt_routers(struct net *net)
 {
 	struct rt6_info *rt;
 	struct fib6_table *table;
 
 	/* NOTE: Keep consistent with rt6_get_dflt_router */
-	table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
+	table = fib6_get_table(net, RT6_TABLE_DFLT);
 	if (table == NULL)
 		return;
 

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (4 preceding siblings ...)
  2008-03-04 21:03 ` [patch 05/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_purge_dflt_routers Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 23:02   ` YOSHIFUJI Hideaki / 吉藤英明
  2008-03-04 21:03 ` [patch 07/12][NETNS][IPV6] rt6_info - make rt6_info accessed as a pointer Daniel Lezcano
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-per-namespace.patch --]
[-- Type: text/plain, Size: 15044 bytes --]

This patch makes the routing engine use the network namespaces
to access routing informations:
Add a network namespace parameter to ipv6_route_ioctl and 
propagate the network namespace value to all the routing code
that have not yet been changed.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_route.h |    4 +
 net/ipv6/af_inet6.c     |    3 -
 net/ipv6/route.c        |   98 ++++++++++++++++++++++++------------------------
 3 files changed, 54 insertions(+), 51 deletions(-)

Index: net-2.6.26/include/net/ip6_route.h
===================================================================
--- net-2.6.26.orig/include/net/ip6_route.h
+++ net-2.6.26/include/net/ip6_route.h
@@ -49,7 +49,9 @@ extern struct dst_entry *	ip6_route_outp
 extern int			ip6_route_init(void);
 extern void			ip6_route_cleanup(void);
 
-extern int			ipv6_route_ioctl(unsigned int cmd, void __user *arg);
+extern int			ipv6_route_ioctl(struct net *net,
+						 unsigned int cmd,
+						 void __user *arg);
 
 extern int			ip6_route_add(struct fib6_config *cfg);
 extern int			ip6_ins_rt(struct rt6_info *);
Index: net-2.6.26/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.26.orig/net/ipv6/af_inet6.c
+++ net-2.6.26/net/ipv6/af_inet6.c
@@ -440,6 +440,7 @@ EXPORT_SYMBOL(inet6_getname);
 int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
+	struct net *net = sk->sk_net;
 
 	switch(cmd)
 	{
@@ -452,7 +453,7 @@ int inet6_ioctl(struct socket *sock, uns
 	case SIOCADDRT:
 	case SIOCDELRT:
 
-		return(ipv6_route_ioctl(cmd,(void __user *)arg));
+		return(ipv6_route_ioctl(net, cmd, (void __user *)arg));
 
 	case SIOCSIFADDR:
 		return addrconf_add_ifaddr((void __user *) arg);
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -609,7 +609,7 @@ static int __ip6_ins_rt(struct rt6_info 
 int ip6_ins_rt(struct rt6_info *rt)
 {
 	struct nl_info info = {
-		.nl_net = &init_net,
+		.nl_net = rt->rt6i_dev->nd_net,
 	};
 	return __ip6_ins_rt(rt, &info);
 }
@@ -746,6 +746,7 @@ static struct rt6_info *ip6_pol_route_in
 void ip6_route_input(struct sk_buff *skb)
 {
 	struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct net *net = skb->dev->nd_net;
 	int flags = RT6_LOOKUP_F_HAS_SADDR;
 	struct flowi fl = {
 		.iif = skb->dev->ifindex,
@@ -763,7 +764,7 @@ void ip6_route_input(struct sk_buff *skb
 	if (rt6_need_strict(&iph->daddr))
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	skb->dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_input);
+	skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);
 }
 
 static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
@@ -891,12 +892,12 @@ static void ip6_rt_update_pmtu(struct ds
 
 static int ipv6_get_mtu(struct net_device *dev);
 
-static inline unsigned int ipv6_advmss(unsigned int mtu)
+static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu)
 {
 	mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
 
-	if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss)
-		mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss;
+	if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
+		mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
 
 	/*
 	 * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
@@ -918,6 +919,7 @@ struct dst_entry *icmp6_dst_alloc(struct
 {
 	struct rt6_info *rt;
 	struct inet6_dev *idev = in6_dev_get(dev);
+	struct net *net = dev->nd_net;
 
 	if (unlikely(idev == NULL))
 		return NULL;
@@ -940,7 +942,7 @@ struct dst_entry *icmp6_dst_alloc(struct
 	atomic_set(&rt->u.dst.__refcnt, 1);
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
-	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
 	rt->u.dst.output  = ip6_output;
 
 #if 0	/* there's no chance to use these for ndisc */
@@ -956,7 +958,7 @@ struct dst_entry *icmp6_dst_alloc(struct
 	icmp6_dst_gc_list = &rt->u.dst;
 	spin_unlock_bh(&icmp6_dst_lock);
 
-	fib6_force_start_gc(dev->nd_net);
+	fib6_force_start_gc(net);
 
 out:
 	return &rt->u.dst;
@@ -1049,6 +1051,7 @@ int ipv6_get_hoplimit(struct net_device 
 int ip6_route_add(struct fib6_config *cfg)
 {
 	int err;
+	struct net *net = cfg->fc_nlinfo.nl_net;
 	struct rt6_info *rt = NULL;
 	struct net_device *dev = NULL;
 	struct inet6_dev *idev = NULL;
@@ -1063,7 +1066,7 @@ int ip6_route_add(struct fib6_config *cf
 #endif
 	if (cfg->fc_ifindex) {
 		err = -ENODEV;
-		dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
+		dev = dev_get_by_index(net, cfg->fc_ifindex);
 		if (!dev)
 			goto out;
 		idev = in6_dev_get(dev);
@@ -1074,7 +1077,7 @@ int ip6_route_add(struct fib6_config *cf
 	if (cfg->fc_metric == 0)
 		cfg->fc_metric = IP6_RT_PRIO_USER;
 
-	table = fib6_new_table(&init_net, cfg->fc_table);
+	table = fib6_new_table(net, cfg->fc_table);
 	if (table == NULL) {
 		err = -ENOBUFS;
 		goto out;
@@ -1121,12 +1124,12 @@ int ip6_route_add(struct fib6_config *cf
 	if ((cfg->fc_flags & RTF_REJECT) ||
 	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
 		/* hold loopback dev/idev if we haven't done so. */
-		if (dev != init_net.loopback_dev) {
+		if (dev != net->loopback_dev) {
 			if (dev) {
 				dev_put(dev);
 				in6_dev_put(idev);
 			}
-			dev = init_net.loopback_dev;
+			dev = net->loopback_dev;
 			dev_hold(dev);
 			idev = in6_dev_get(dev);
 			if (!idev) {
@@ -1163,7 +1166,7 @@ int ip6_route_add(struct fib6_config *cf
 			if (!(gwa_type&IPV6_ADDR_UNICAST))
 				goto out;
 
-			grt = rt6_lookup(&init_net, gw_addr, NULL, cfg->fc_ifindex, 1);
+			grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
 
 			err = -EHOSTUNREACH;
 			if (grt == NULL)
@@ -1230,7 +1233,7 @@ install_route:
 	if (!rt->u.dst.metrics[RTAX_MTU-1])
 		rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
 	if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
-		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
 	rt->u.dst.dev = dev;
 	rt->rt6i_idev = idev;
 	rt->rt6i_table = table;
@@ -1271,7 +1274,7 @@ static int __ip6_del_rt(struct rt6_info 
 int ip6_del_rt(struct rt6_info *rt)
 {
 	struct nl_info info = {
-		.nl_net = &init_net,
+		.nl_net = rt->rt6i_dev->nd_net,
 	};
 	return __ip6_del_rt(rt, &info);
 }
@@ -1283,7 +1286,7 @@ static int ip6_route_del(struct fib6_con
 	struct rt6_info *rt;
 	int err = -ESRCH;
 
-	table = fib6_get_table(&init_net, cfg->fc_table);
+	table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
 	if (table == NULL)
 		return err;
 
@@ -1382,6 +1385,7 @@ static struct rt6_info *ip6_route_redire
 					   struct net_device *dev)
 {
 	int flags = RT6_LOOKUP_F_HAS_SADDR;
+	struct net *net = dev->nd_net;
 	struct ip6rd_flowi rdfl = {
 		.fl = {
 			.oif = dev->ifindex,
@@ -1398,8 +1402,7 @@ static struct rt6_info *ip6_route_redire
 	if (rt6_need_strict(dest))
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	return (struct rt6_info *)fib6_rule_lookup(&init_net,
-						   (struct flowi *)&rdfl,
+	return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl,
 						   flags, __ip6_route_redirect);
 }
 
@@ -1457,7 +1460,8 @@ void rt6_redirect(struct in6_addr *dest,
 	nrt->rt6i_nexthop = neigh_clone(neigh);
 	/* Reset pmtu, it may be better */
 	nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
-	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
+	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(neigh->dev->nd_net,
+							dst_mtu(&nrt->u.dst));
 
 	if (ip6_ins_rt(nrt))
 		goto out;
@@ -1485,9 +1489,10 @@ void rt6_pmtu_discovery(struct in6_addr 
 			struct net_device *dev, u32 pmtu)
 {
 	struct rt6_info *rt, *nrt;
+	struct net *net = dev->nd_net;
 	int allfrag = 0;
 
-	rt = rt6_lookup(dev->nd_net, daddr, saddr, dev->ifindex, 0);
+	rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
 	if (rt == NULL)
 		return;
 
@@ -1520,7 +1525,7 @@ void rt6_pmtu_discovery(struct in6_addr 
 		rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
 		if (allfrag)
 			rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
-		dst_set_expires(&rt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
+		dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
 		rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
 		goto out;
 	}
@@ -1546,7 +1551,7 @@ void rt6_pmtu_discovery(struct in6_addr 
 		 * which is 10 mins. After 10 mins the decreased pmtu is expired
 		 * and detecting PMTU increase will be automatically happened.
 		 */
-		dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
+		dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
 		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
 
 		ip6_ins_rt(nrt);
@@ -1659,7 +1664,7 @@ struct rt6_info *rt6_get_dflt_router(str
 	struct rt6_info *rt;
 	struct fib6_table *table;
 
-	table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
+	table = fib6_get_table(dev->nd_net, RT6_TABLE_DFLT);
 	if (table == NULL)
 		return NULL;
 
@@ -1688,6 +1693,9 @@ struct rt6_info *rt6_add_dflt_router(str
 		.fc_ifindex	= dev->ifindex,
 		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
 				  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
+		.fc_nlinfo.pid = 0,
+		.fc_nlinfo.nlh = NULL,
+		.fc_nlinfo.nl_net = dev->nd_net,
 	};
 
 	ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
@@ -1720,7 +1728,8 @@ restart:
 	read_unlock_bh(&table->tb6_lock);
 }
 
-static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
+static void rtmsg_to_fib6_config(struct net *net,
+				 struct in6_rtmsg *rtmsg,
 				 struct fib6_config *cfg)
 {
 	memset(cfg, 0, sizeof(*cfg));
@@ -1733,14 +1742,14 @@ static void rtmsg_to_fib6_config(struct 
 	cfg->fc_src_len = rtmsg->rtmsg_src_len;
 	cfg->fc_flags = rtmsg->rtmsg_flags;
 
-	cfg->fc_nlinfo.nl_net = &init_net;
+	cfg->fc_nlinfo.nl_net = net;
 
 	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
 	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
 	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
 }
 
-int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
+int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 {
 	struct fib6_config cfg;
 	struct in6_rtmsg rtmsg;
@@ -1756,7 +1765,7 @@ int ipv6_route_ioctl(unsigned int cmd, v
 		if (err)
 			return -EFAULT;
 
-		rtmsg_to_fib6_config(&rtmsg, &cfg);
+		rtmsg_to_fib6_config(net, &rtmsg, &cfg);
 
 		rtnl_lock();
 		switch (cmd) {
@@ -1835,21 +1844,22 @@ struct rt6_info *addrconf_dst_alloc(stru
 				    const struct in6_addr *addr,
 				    int anycast)
 {
+	struct net *net = idev->dev->nd_net;
 	struct rt6_info *rt = ip6_dst_alloc();
 
 	if (rt == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	dev_hold(init_net.loopback_dev);
+	dev_hold(net->loopback_dev);
 	in6_dev_hold(idev);
 
 	rt->u.dst.flags = DST_HOST;
 	rt->u.dst.input = ip6_input;
 	rt->u.dst.output = ip6_output;
-	rt->rt6i_dev = init_net.loopback_dev;
+	rt->rt6i_dev = net->loopback_dev;
 	rt->rt6i_idev = idev;
 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
-	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
 	rt->u.dst.obsolete = -1;
 
@@ -1866,7 +1876,7 @@ struct rt6_info *addrconf_dst_alloc(stru
 
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
-	rt->rt6i_table = fib6_get_table(&init_net, RT6_TABLE_LOCAL);
+	rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
 
 	atomic_set(&rt->u.dst.__refcnt, 1);
 
@@ -1898,6 +1908,7 @@ static int rt6_mtu_change_route(struct r
 {
 	struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
 	struct inet6_dev *idev;
+	struct net *net = arg->dev->nd_net;
 
 	/* In IPv6 pmtu discovery is not optional,
 	   so that RTAX_MTU lock cannot disable it.
@@ -1929,7 +1940,7 @@ static int rt6_mtu_change_route(struct r
 	     (dst_mtu(&rt->u.dst) < arg->mtu &&
 	      dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
 		rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
-		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
+		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
 	}
 	return 0;
 }
@@ -2024,13 +2035,9 @@ errout:
 
 static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
-	struct net *net = skb->sk->sk_net;
 	struct fib6_config cfg;
 	int err;
 
-	if (net != &init_net)
-		return -EINVAL;
-
 	err = rtm_to_fib6_config(skb, nlh, &cfg);
 	if (err < 0)
 		return err;
@@ -2040,13 +2047,9 @@ static int inet6_rtm_delroute(struct sk_
 
 static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
-	struct net *net = skb->sk->sk_net;
 	struct fib6_config cfg;
 	int err;
 
-	if (net != &init_net)
-		return -EINVAL;
-
 	err = rtm_to_fib6_config(skb, nlh, &cfg);
 	if (err < 0)
 		return err;
@@ -2190,9 +2193,6 @@ static int inet6_rtm_getroute(struct sk_
 	struct flowi fl;
 	int err, iif = 0;
 
-	if (net != &init_net)
-		return -EINVAL;
-
 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
 	if (err < 0)
 		goto errout;
@@ -2222,7 +2222,7 @@ static int inet6_rtm_getroute(struct sk_
 
 	if (iif) {
 		struct net_device *dev;
-		dev = __dev_get_by_index(&init_net, iif);
+		dev = __dev_get_by_index(net, iif);
 		if (!dev) {
 			err = -ENODEV;
 			goto errout;
@@ -2252,7 +2252,7 @@ static int inet6_rtm_getroute(struct sk_
 		goto errout;
 	}
 
-	err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
+	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
 errout:
 	return err;
 }
@@ -2260,6 +2260,7 @@ errout:
 void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
 {
 	struct sk_buff *skb;
+	struct net *net = info->nl_net;
 	u32 seq;
 	int err;
 
@@ -2278,11 +2279,11 @@ void inet6_rt_notify(int event, struct r
 		kfree_skb(skb);
 		goto errout;
 	}
-	err = rtnl_notify(skb, &init_net, info->pid,
-				RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any());
+	err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE,
+			  info->nlh, gfp_any());
 errout:
 	if (err < 0)
-		rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
+		rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
 }
 
 /*
@@ -2544,6 +2545,7 @@ static void ip6_route_net_exit(struct ne
 	proc_net_remove(net, "ipv6_route");
 	proc_net_remove(net, "rt6_stats");
 #endif
+	rt6_ifdown(net, NULL);
 }
 
 static struct pernet_operations ip6_route_net_ops = {
@@ -2592,7 +2594,6 @@ fib6_rules_init:
 xfrm6_init:
 	xfrm6_fini();
 out_fib6_init:
-	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();
 out_kmem_cache:
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
@@ -2604,7 +2605,6 @@ void ip6_route_cleanup(void)
 	unregister_pernet_subsys(&ip6_route_net_ops);
 	fib6_rules_cleanup();
 	xfrm6_fini();
-	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
 }

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 07/12][NETNS][IPV6] rt6_info - make rt6_info accessed as a pointer
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (5 preceding siblings ...)
  2008-03-04 21:03 ` [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 08/12][NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace Daniel Lezcano
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: rt6-info-entries-dynamic-allocation.patch --]
[-- Type: text/plain, Size: 11752 bytes --]

This patch make mindless changes and prepares the code to use dynamic 
allocation  for rt6_info structure. The code accesses the rt6_info
structure as a pointer instead of a global static variable.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_route.h |    6 ++--
 net/ipv6/addrconf.c     |   12 ++++----
 net/ipv6/fib6_rules.c   |   12 ++++----
 net/ipv6/ip6_fib.c      |   18 ++++++------
 net/ipv6/route.c        |   70 +++++++++++++++++++++++++++++++++++++-----------
 5 files changed, 78 insertions(+), 40 deletions(-)

Index: net-2.6.26/include/net/ip6_route.h
===================================================================
--- net-2.6.26.orig/include/net/ip6_route.h
+++ net-2.6.26/include/net/ip6_route.h
@@ -34,11 +34,11 @@ struct route_info {
 #define RT6_LOOKUP_F_REACHABLE	0x2
 #define RT6_LOOKUP_F_HAS_SADDR	0x4
 
-extern struct rt6_info	ip6_null_entry;
+extern struct rt6_info	*ip6_null_entry;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-extern struct rt6_info	ip6_prohibit_entry;
-extern struct rt6_info	ip6_blk_hole_entry;
+extern struct rt6_info	*ip6_prohibit_entry;
+extern struct rt6_info	*ip6_blk_hole_entry;
 #endif
 
 extern void			ip6_route_input(struct sk_buff *skb);
Index: net-2.6.26/net/ipv6/addrconf.c
===================================================================
--- net-2.6.26.orig/net/ipv6/addrconf.c
+++ net-2.6.26/net/ipv6/addrconf.c
@@ -4301,13 +4301,13 @@ int __init addrconf_init(void)
 	if (err)
 		goto errlo;
 
-	ip6_null_entry.u.dst.dev = init_net.loopback_dev;
-	ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	ip6_null_entry->u.dst.dev = init_net.loopback_dev;
+	ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev;
-	ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
-	ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev;
-	ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
+	ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
+	ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
 #endif
 
 	register_netdevice_notifier(&ipv6_dev_notf);
Index: net-2.6.26/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.26.orig/net/ipv6/fib6_rules.c
+++ net-2.6.26/net/ipv6/fib6_rules.c
@@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struc
 	if (arg.result)
 		return arg.result;
 
-	dst_hold(&ip6_null_entry.u.dst);
-	return &ip6_null_entry.u.dst;
+	dst_hold(&ip6_null_entry->u.dst);
+	return &ip6_null_entry->u.dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -58,14 +58,14 @@ static int fib6_rule_action(struct fib_r
 	case FR_ACT_TO_TBL:
 		break;
 	case FR_ACT_UNREACHABLE:
-		rt = &ip6_null_entry;
+		rt = ip6_null_entry;
 		goto discard_pkt;
 	default:
 	case FR_ACT_BLACKHOLE:
-		rt = &ip6_blk_hole_entry;
+		rt = ip6_blk_hole_entry;
 		goto discard_pkt;
 	case FR_ACT_PROHIBIT:
-		rt = &ip6_prohibit_entry;
+		rt = ip6_prohibit_entry;
 		goto discard_pkt;
 	}
 
@@ -73,7 +73,7 @@ static int fib6_rule_action(struct fib_r
 	if (table)
 		rt = lookup(table, flp, flags);
 
-	if (rt != &ip6_null_entry) {
+	if (rt != ip6_null_entry) {
 		struct fib6_rule *r = (struct fib6_rule *)rule;
 
 		/*
Index: net-2.6.26/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.26.orig/net/ipv6/ip6_fib.c
+++ net-2.6.26/net/ipv6/ip6_fib.c
@@ -200,7 +200,7 @@ static struct fib6_table *fib6_alloc_tab
 	table = kzalloc(sizeof(*table), GFP_ATOMIC);
 	if (table != NULL) {
 		table->tb6_id = id;
-		table->tb6_root.leaf = &ip6_null_entry;
+		table->tb6_root.leaf = ip6_null_entry;
 		table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 	}
 
@@ -717,8 +717,8 @@ int fib6_add(struct fib6_node *root, str
 			if (sfn == NULL)
 				goto st_failure;
 
-			sfn->leaf = &ip6_null_entry;
-			atomic_inc(&ip6_null_entry.rt6i_ref);
+			sfn->leaf = ip6_null_entry;
+			atomic_inc(&ip6_null_entry->rt6i_ref);
 			sfn->fn_flags = RTN_ROOT;
 			sfn->fn_sernum = fib6_new_sernum();
 
@@ -777,7 +777,7 @@ out:
 #if RT6_DEBUG >= 2
 			if (!pn->leaf) {
 				BUG_TRAP(pn->leaf != NULL);
-				pn->leaf = &ip6_null_entry;
+				pn->leaf = ip6_null_entry;
 			}
 #endif
 			atomic_inc(&pn->leaf->rt6i_ref);
@@ -962,7 +962,7 @@ struct fib6_node * fib6_locate(struct fi
 static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
 {
 	if (fn->fn_flags&RTN_ROOT)
-		return &ip6_null_entry;
+		return ip6_null_entry;
 
 	while(fn) {
 		if(fn->left)
@@ -1012,7 +1012,7 @@ static struct fib6_node * fib6_repair_tr
 #if RT6_DEBUG >= 2
 			if (fn->leaf==NULL) {
 				BUG_TRAP(fn->leaf);
-				fn->leaf = &ip6_null_entry;
+				fn->leaf = ip6_null_entry;
 			}
 #endif
 			atomic_inc(&fn->leaf->rt6i_ref);
@@ -1154,7 +1154,7 @@ int fib6_del(struct rt6_info *rt, struct
 		return -ENOENT;
 	}
 #endif
-	if (fn == NULL || rt == &ip6_null_entry)
+	if (fn == NULL || rt == ip6_null_entry)
 		return -ENOENT;
 
 	BUG_TRAP(fn->fn_flags&RTN_RTINFO);
@@ -1501,7 +1501,7 @@ static int fib6_net_init(struct net *net
 		goto out_fib_table_hash;
 
 	net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
-	net->ipv6.fib6_main_tbl->tb6_root.leaf = &ip6_null_entry;
+	net->ipv6.fib6_main_tbl->tb6_root.leaf = ip6_null_entry;
 	net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
 		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 
@@ -1511,7 +1511,7 @@ static int fib6_net_init(struct net *net
 	if (!net->ipv6.fib6_local_tbl)
 		goto out_fib6_main_tbl;
 	net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
-	net->ipv6.fib6_local_tbl->tb6_root.leaf = &ip6_null_entry;
+	net->ipv6.fib6_local_tbl->tb6_root.leaf = ip6_null_entry;
 	net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
 		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 #endif
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -127,7 +127,7 @@ static struct dst_ops ip6_dst_blackhole_
 	.entries		=	ATOMIC_INIT(0),
 };
 
-struct rt6_info ip6_null_entry = {
+static struct rt6_info ip6_null_entry_template = {
 	.u = {
 		.dst = {
 			.__refcnt	= ATOMIC_INIT(1),
@@ -138,7 +138,6 @@ struct rt6_info ip6_null_entry = {
 			.input		= ip6_pkt_discard,
 			.output		= ip6_pkt_discard_out,
 			.ops		= &ip6_dst_ops,
-			.path		= (struct dst_entry*)&ip6_null_entry,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -146,12 +145,14 @@ struct rt6_info ip6_null_entry = {
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
+struct rt6_info *ip6_null_entry;
+
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
 static int ip6_pkt_prohibit(struct sk_buff *skb);
 static int ip6_pkt_prohibit_out(struct sk_buff *skb);
 
-struct rt6_info ip6_prohibit_entry = {
+struct rt6_info ip6_prohibit_entry_template = {
 	.u = {
 		.dst = {
 			.__refcnt	= ATOMIC_INIT(1),
@@ -162,7 +163,6 @@ struct rt6_info ip6_prohibit_entry = {
 			.input		= ip6_pkt_prohibit,
 			.output		= ip6_pkt_prohibit_out,
 			.ops		= &ip6_dst_ops,
-			.path		= (struct dst_entry*)&ip6_prohibit_entry,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -170,7 +170,9 @@ struct rt6_info ip6_prohibit_entry = {
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
-struct rt6_info ip6_blk_hole_entry = {
+struct rt6_info *ip6_prohibit_entry;
+
+static struct rt6_info ip6_blk_hole_entry_template = {
 	.u = {
 		.dst = {
 			.__refcnt	= ATOMIC_INIT(1),
@@ -181,7 +183,6 @@ struct rt6_info ip6_blk_hole_entry = {
 			.input		= dst_discard,
 			.output		= dst_discard,
 			.ops		= &ip6_dst_ops,
-			.path		= (struct dst_entry*)&ip6_blk_hole_entry,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -189,6 +190,8 @@ struct rt6_info ip6_blk_hole_entry = {
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
+struct rt6_info *ip6_blk_hole_entry;
+
 #endif
 
 /* allocate dst with ip6_dst_ops */
@@ -271,7 +274,7 @@ static __inline__ struct rt6_info *rt6_d
 			return local;
 
 		if (strict)
-			return &ip6_null_entry;
+			return ip6_null_entry;
 	}
 	return rt;
 }
@@ -437,7 +440,7 @@ static struct rt6_info *rt6_select(struc
 	RT6_TRACE("%s() => %p\n",
 		  __FUNCTION__, match);
 
-	return (match ? match : &ip6_null_entry);
+	return (match ? match : ip6_null_entry);
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -522,7 +525,7 @@ int rt6_route_rcv(struct net_device *dev
 
 #define BACKTRACK(saddr) \
 do { \
-	if (rt == &ip6_null_entry) { \
+	if (rt == ip6_null_entry) { \
 		struct fib6_node *pn; \
 		while (1) { \
 			if (fn->fn_flags & RTN_TL_ROOT) \
@@ -686,7 +689,7 @@ restart_2:
 restart:
 	rt = rt6_select(fn, oif, strict | reachable);
 	BACKTRACK(&fl->fl6_src);
-	if (rt == &ip6_null_entry ||
+	if (rt == ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 		goto out;
 
@@ -704,7 +707,7 @@ restart:
 	}
 
 	dst_release(&rt->u.dst);
-	rt = nrt ? : &ip6_null_entry;
+	rt = nrt ? : ip6_null_entry;
 
 	dst_hold(&rt->u.dst);
 	if (nrt) {
@@ -1257,7 +1260,7 @@ static int __ip6_del_rt(struct rt6_info 
 	int err;
 	struct fib6_table *table;
 
-	if (rt == &ip6_null_entry)
+	if (rt == ip6_null_entry)
 		return -ENOENT;
 
 	table = rt->rt6i_table;
@@ -1369,7 +1372,7 @@ restart:
 	}
 
 	if (!rt)
-		rt = &ip6_null_entry;
+		rt = ip6_null_entry;
 	BACKTRACK(&fl->fl6_src);
 out:
 	dst_hold(&rt->u.dst);
@@ -1415,7 +1418,7 @@ void rt6_redirect(struct in6_addr *dest,
 
 	rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
 
-	if (rt == &ip6_null_entry) {
+	if (rt == ip6_null_entry) {
 		if (net_ratelimit())
 			printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
 			       "for redirect target\n");
@@ -1886,7 +1889,7 @@ struct rt6_info *addrconf_dst_alloc(stru
 static int fib6_ifdown(struct rt6_info *rt, void *arg)
 {
 	if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
-	    rt != &ip6_null_entry) {
+	    rt != ip6_null_entry) {
 		RT6_TRACE("deleted by ifdown %p\n", rt);
 		return -1;
 	}
@@ -2565,9 +2568,30 @@ int __init ip6_route_init(void)
 
 	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
 
+	ret = -ENOMEM;
+	ip6_null_entry = kmemdup(&ip6_null_entry_template,
+				 sizeof(*ip6_null_entry), GFP_KERNEL);
+	if (!ip6_null_entry)
+		goto out_kmem_cache;
+	ip6_null_entry->u.dst.path = (struct dst_entry *)ip6_null_entry;
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
+				     sizeof(*ip6_prohibit_entry), GFP_KERNEL);
+	if (!ip6_prohibit_entry)
+		goto out_ip6_null_entry;
+	ip6_prohibit_entry->u.dst.path = (struct dst_entry *)ip6_prohibit_entry;
+
+	ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
+				     sizeof(*ip6_blk_hole_entry), GFP_KERNEL);
+	if (!ip6_blk_hole_entry)
+		goto out_ip6_prohibit_entry;
+	ip6_blk_hole_entry->u.dst.path = (struct dst_entry *)ip6_blk_hole_entry;
+#endif
+
 	ret = fib6_init();
 	if (ret)
-		goto out_kmem_cache;
+		goto out_ip6_blk_hole_entry;
 
 	ret = xfrm6_init();
 	if (ret)
@@ -2595,6 +2619,14 @@ xfrm6_init:
 	xfrm6_fini();
 out_fib6_init:
 	fib6_gc_cleanup();
+out_ip6_blk_hole_entry:
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(ip6_blk_hole_entry);
+out_ip6_prohibit_entry:
+	kfree(ip6_prohibit_entry);
+out_ip6_null_entry:
+#endif
+	kfree(ip6_null_entry);
 out_kmem_cache:
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
 	goto out;
@@ -2607,4 +2639,10 @@ void ip6_route_cleanup(void)
 	xfrm6_fini();
 	fib6_gc_cleanup();
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+
+	kfree(ip6_null_entry);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(ip6_prohibit_entry);
+	kfree(ip6_blk_hole_entry);
+#endif
 }

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 08/12][NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (6 preceding siblings ...)
  2008-03-04 21:03 ` [patch 07/12][NETNS][IPV6] rt6_info - make rt6_info accessed as a pointer Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 09/12][NETNS][IPV6] route6 - dynamically allocate ip6_dst_ops Daniel Lezcano
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: rt6-info-entries-per-namespace.patch --]
[-- Type: text/plain, Size: 22470 bytes --]

The rt6_info structures are moved inside the network namespace
structure. All references to these structures are now relative
to the initial network namespace.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_fib.h    |    3 
 include/net/netns/ipv6.h |    3 
 net/ipv6/addrconf.c      |    9 --
 net/ipv6/fib6_rules.c    |   17 ++-
 net/ipv6/ip6_fib.c       |   45 +++++-----
 net/ipv6/route.c         |  202 ++++++++++++++++++++++++++++++-----------------
 6 files changed, 171 insertions(+), 108 deletions(-)

Index: net-2.6.26/include/net/ip6_fib.h
===================================================================
--- net-2.6.26.orig/include/net/ip6_fib.h
+++ net-2.6.26/include/net/ip6_fib.h
@@ -174,7 +174,8 @@ struct fib6_table {
 #define RT6_TABLE_LOCAL		RT6_TABLE_MAIN
 #endif
 
-typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
+typedef struct rt6_info *(*pol_lookup_t)(struct net *,
+					 struct fib6_table *,
 					 struct flowi *, int);
 
 /*
Index: net-2.6.26/include/net/netns/ipv6.h
===================================================================
--- net-2.6.26.orig/include/net/netns/ipv6.h
+++ net-2.6.26/include/net/netns/ipv6.h
@@ -36,11 +36,14 @@ struct netns_ipv6 {
 	struct xt_table		*ip6table_mangle;
 	struct xt_table		*ip6table_raw;
 #endif
+	struct rt6_info         *ip6_null_entry;
 	struct rt6_statistics   *rt6_stats;
 	struct timer_list       *ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	struct rt6_info         *ip6_prohibit_entry;
+	struct rt6_info         *ip6_blk_hole_entry;
 	struct fib6_table       *fib6_local_tbl;
 	struct fib_rules_ops    *fib6_rules_ops;
 #endif
Index: net-2.6.26/net/ipv6/addrconf.c
===================================================================
--- net-2.6.26.orig/net/ipv6/addrconf.c
+++ net-2.6.26/net/ipv6/addrconf.c
@@ -4301,15 +4301,6 @@ int __init addrconf_init(void)
 	if (err)
 		goto errlo;
 
-	ip6_null_entry->u.dst.dev = init_net.loopback_dev;
-	ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
-	ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-	ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
-	ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-#endif
-
 	register_netdevice_notifier(&ipv6_dev_notf);
 
 	addrconf_verify(0);
Index: net-2.6.26/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.26.orig/net/ipv6/fib6_rules.c
+++ net-2.6.26/net/ipv6/fib6_rules.c
@@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struc
 	if (arg.result)
 		return arg.result;
 
-	dst_hold(&ip6_null_entry->u.dst);
-	return &ip6_null_entry->u.dst;
+	dst_hold(&net->ipv6.ip6_null_entry->u.dst);
+	return &net->ipv6.ip6_null_entry->u.dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -52,28 +52,29 @@ static int fib6_rule_action(struct fib_r
 {
 	struct rt6_info *rt = NULL;
 	struct fib6_table *table;
+	struct net *net = rule->fr_net;
 	pol_lookup_t lookup = arg->lookup_ptr;
 
 	switch (rule->action) {
 	case FR_ACT_TO_TBL:
 		break;
 	case FR_ACT_UNREACHABLE:
-		rt = ip6_null_entry;
+		rt = net->ipv6.ip6_null_entry;
 		goto discard_pkt;
 	default:
 	case FR_ACT_BLACKHOLE:
-		rt = ip6_blk_hole_entry;
+		rt = net->ipv6.ip6_blk_hole_entry;
 		goto discard_pkt;
 	case FR_ACT_PROHIBIT:
-		rt = ip6_prohibit_entry;
+		rt = net->ipv6.ip6_prohibit_entry;
 		goto discard_pkt;
 	}
 
-	table = fib6_get_table(rule->fr_net, rule->table);
+	table = fib6_get_table(net, rule->table);
 	if (table)
-		rt = lookup(table, flp, flags);
+		rt = lookup(net, table, flp, flags);
 
-	if (rt != ip6_null_entry) {
+	if (rt != net->ipv6.ip6_null_entry) {
 		struct fib6_rule *r = (struct fib6_rule *)rule;
 
 		/*
Index: net-2.6.26/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.26.orig/net/ipv6/ip6_fib.c
+++ net-2.6.26/net/ipv6/ip6_fib.c
@@ -79,8 +79,8 @@ static DEFINE_RWLOCK(fib6_walker_lock);
 
 static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
 			      struct rt6_info *rt);
-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
+static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn);
+static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn);
 static int fib6_walk(struct fib6_walker_t *w);
 static int fib6_walk_continue(struct fib6_walker_t *w);
 
@@ -193,14 +193,14 @@ static void fib6_link_table(struct net *
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
-static struct fib6_table *fib6_alloc_table(u32 id)
+static struct fib6_table *fib6_alloc_table(struct net *net, u32 id)
 {
 	struct fib6_table *table;
 
 	table = kzalloc(sizeof(*table), GFP_ATOMIC);
 	if (table != NULL) {
 		table->tb6_id = id;
-		table->tb6_root.leaf = ip6_null_entry;
+		table->tb6_root.leaf = net->ipv6.ip6_null_entry;
 		table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 	}
 
@@ -217,7 +217,7 @@ struct fib6_table *fib6_new_table(struct
 	if (tb)
 		return tb;
 
-	tb = fib6_alloc_table(id);
+	tb = fib6_alloc_table(net, id);
 	if (tb != NULL)
 		fib6_link_table(net, tb);
 
@@ -267,7 +267,7 @@ struct fib6_table *fib6_get_table(struct
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
 				   int flags, pol_lookup_t lookup)
 {
-	return (struct dst_entry *) lookup(net->ipv6.fib6_main_tbl, fl, flags);
+	return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags);
 }
 
 static void fib6_tables_init(struct net *net)
@@ -717,8 +717,8 @@ int fib6_add(struct fib6_node *root, str
 			if (sfn == NULL)
 				goto st_failure;
 
-			sfn->leaf = ip6_null_entry;
-			atomic_inc(&ip6_null_entry->rt6i_ref);
+			sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
+			atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
 			sfn->fn_flags = RTN_ROOT;
 			sfn->fn_sernum = fib6_new_sernum();
 
@@ -773,11 +773,11 @@ out:
 		 * super-tree leaf node we have to find a new one for it.
 		 */
 		if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
-			pn->leaf = fib6_find_prefix(pn);
+			pn->leaf = fib6_find_prefix(info->nl_net, pn);
 #if RT6_DEBUG >= 2
 			if (!pn->leaf) {
 				BUG_TRAP(pn->leaf != NULL);
-				pn->leaf = ip6_null_entry;
+				pn->leaf = info->nl_net->ipv6.ip6_null_entry;
 			}
 #endif
 			atomic_inc(&pn->leaf->rt6i_ref);
@@ -793,7 +793,7 @@ out:
 	 */
 st_failure:
 	if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
-		fib6_repair_tree(fn);
+		fib6_repair_tree(info->nl_net, fn);
 	dst_free(&rt->u.dst);
 	return err;
 #endif
@@ -959,10 +959,10 @@ struct fib6_node * fib6_locate(struct fi
  *
  */
 
-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
+static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
 {
 	if (fn->fn_flags&RTN_ROOT)
-		return ip6_null_entry;
+		return net->ipv6.ip6_null_entry;
 
 	while(fn) {
 		if(fn->left)
@@ -981,7 +981,8 @@ static struct rt6_info * fib6_find_prefi
  *	is the node we want to try and remove.
  */
 
-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
+static struct fib6_node *fib6_repair_tree(struct net *net,
+					   struct fib6_node *fn)
 {
 	int children;
 	int nstate;
@@ -1008,11 +1009,11 @@ static struct fib6_node * fib6_repair_tr
 		    || (children && fn->fn_flags&RTN_ROOT)
 #endif
 		    ) {
-			fn->leaf = fib6_find_prefix(fn);
+			fn->leaf = fib6_find_prefix(net, fn);
 #if RT6_DEBUG >= 2
 			if (fn->leaf==NULL) {
 				BUG_TRAP(fn->leaf);
-				fn->leaf = ip6_null_entry;
+				fn->leaf = net->ipv6.ip6_null_entry;
 			}
 #endif
 			atomic_inc(&fn->leaf->rt6i_ref);
@@ -1117,7 +1118,7 @@ static void fib6_del_route(struct fib6_n
 	if (fn->leaf == NULL) {
 		fn->fn_flags &= ~RTN_RTINFO;
 		net->ipv6.rt6_stats->fib_route_nodes--;
-		fn = fib6_repair_tree(fn);
+		fn = fib6_repair_tree(net, fn);
 	}
 
 	if (atomic_read(&rt->rt6i_ref) != 1) {
@@ -1129,7 +1130,7 @@ static void fib6_del_route(struct fib6_n
 		 */
 		while (fn) {
 			if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) {
-				fn->leaf = fib6_find_prefix(fn);
+				fn->leaf = fib6_find_prefix(net, fn);
 				atomic_inc(&fn->leaf->rt6i_ref);
 				rt6_release(rt);
 			}
@@ -1145,6 +1146,7 @@ static void fib6_del_route(struct fib6_n
 
 int fib6_del(struct rt6_info *rt, struct nl_info *info)
 {
+	struct net *net = info->nl_net;
 	struct fib6_node *fn = rt->rt6i_node;
 	struct rt6_info **rtp;
 
@@ -1154,7 +1156,7 @@ int fib6_del(struct rt6_info *rt, struct
 		return -ENOENT;
 	}
 #endif
-	if (fn == NULL || rt == ip6_null_entry)
+	if (fn == NULL || rt == net->ipv6.ip6_null_entry)
 		return -ENOENT;
 
 	BUG_TRAP(fn->fn_flags&RTN_RTINFO);
@@ -1501,7 +1503,7 @@ static int fib6_net_init(struct net *net
 		goto out_fib_table_hash;
 
 	net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
-	net->ipv6.fib6_main_tbl->tb6_root.leaf = ip6_null_entry;
+	net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
 	net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
 		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 
@@ -1511,7 +1513,7 @@ static int fib6_net_init(struct net *net
 	if (!net->ipv6.fib6_local_tbl)
 		goto out_fib6_main_tbl;
 	net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
-	net->ipv6.fib6_local_tbl->tb6_root.leaf = ip6_null_entry;
+	net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
 	net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
 		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 #endif
@@ -1536,6 +1538,7 @@ out_timer:
 
 static void fib6_net_exit(struct net *net)
 {
+	rt6_ifdown(net, NULL);
 	del_timer(net->ipv6.ip6_fib_timer);
 	kfree(net->ipv6.ip6_fib_timer);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -145,8 +145,6 @@ static struct rt6_info ip6_null_entry_te
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
-struct rt6_info *ip6_null_entry;
-
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
 static int ip6_pkt_prohibit(struct sk_buff *skb);
@@ -170,8 +168,6 @@ struct rt6_info ip6_prohibit_entry_templ
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
-struct rt6_info *ip6_prohibit_entry;
-
 static struct rt6_info ip6_blk_hole_entry_template = {
 	.u = {
 		.dst = {
@@ -190,8 +186,6 @@ static struct rt6_info ip6_blk_hole_entr
 	.rt6i_ref	= ATOMIC_INIT(1),
 };
 
-struct rt6_info *ip6_blk_hole_entry;
-
 #endif
 
 /* allocate dst with ip6_dst_ops */
@@ -245,7 +239,8 @@ static inline int rt6_need_strict(struct
  *	Route lookup. Any table->tb6_lock is implied.
  */
 
-static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
+static inline struct rt6_info *rt6_device_match(struct net *net,
+						    struct rt6_info *rt,
 						    int oif,
 						    int strict)
 {
@@ -274,7 +269,7 @@ static __inline__ struct rt6_info *rt6_d
 			return local;
 
 		if (strict)
-			return ip6_null_entry;
+			return net->ipv6.ip6_null_entry;
 	}
 	return rt;
 }
@@ -415,6 +410,7 @@ static struct rt6_info *find_rr_leaf(str
 static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
 {
 	struct rt6_info *match, *rt0;
+	struct net *net;
 
 	RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n",
 		  __FUNCTION__, fn->leaf, oif);
@@ -440,7 +436,8 @@ static struct rt6_info *rt6_select(struc
 	RT6_TRACE("%s() => %p\n",
 		  __FUNCTION__, match);
 
-	return (match ? match : ip6_null_entry);
+	net = rt0->rt6i_dev->nd_net;
+	return (match ? match : net->ipv6.ip6_null_entry);
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -523,9 +520,9 @@ int rt6_route_rcv(struct net_device *dev
 }
 #endif
 
-#define BACKTRACK(saddr) \
+#define BACKTRACK(__net, saddr)			\
 do { \
-	if (rt == ip6_null_entry) { \
+	if (rt == __net->ipv6.ip6_null_entry) {	\
 		struct fib6_node *pn; \
 		while (1) { \
 			if (fn->fn_flags & RTN_TL_ROOT) \
@@ -541,7 +538,8 @@ do { \
 	} \
 } while(0)
 
-static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
+static struct rt6_info *ip6_pol_route_lookup(struct net *net,
+					     struct fib6_table *table,
 					     struct flowi *fl, int flags)
 {
 	struct fib6_node *fn;
@@ -551,8 +549,8 @@ static struct rt6_info *ip6_pol_route_lo
 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 restart:
 	rt = fn->leaf;
-	rt = rt6_device_match(rt, fl->oif, flags);
-	BACKTRACK(&fl->fl6_src);
+	rt = rt6_device_match(net, rt, fl->oif, flags);
+	BACKTRACK(net, &fl->fl6_src);
 out:
 	dst_use(&rt->u.dst, jiffies);
 	read_unlock_bh(&table->tb6_lock);
@@ -668,8 +666,8 @@ static struct rt6_info *rt6_alloc_clone(
 	return rt;
 }
 
-static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif,
-					    struct flowi *fl, int flags)
+static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
+				      struct flowi *fl, int flags)
 {
 	struct fib6_node *fn;
 	struct rt6_info *rt, *nrt;
@@ -688,8 +686,9 @@ restart_2:
 
 restart:
 	rt = rt6_select(fn, oif, strict | reachable);
-	BACKTRACK(&fl->fl6_src);
-	if (rt == ip6_null_entry ||
+
+	BACKTRACK(net, &fl->fl6_src);
+	if (rt == net->ipv6.ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 		goto out;
 
@@ -707,7 +706,7 @@ restart:
 	}
 
 	dst_release(&rt->u.dst);
-	rt = nrt ? : ip6_null_entry;
+	rt = nrt ? : net->ipv6.ip6_null_entry;
 
 	dst_hold(&rt->u.dst);
 	if (nrt) {
@@ -740,10 +739,10 @@ out2:
 	return rt;
 }
 
-static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
+static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
 					    struct flowi *fl, int flags)
 {
-	return ip6_pol_route(table, fl->iif, fl, flags);
+	return ip6_pol_route(net, table, fl->iif, fl, flags);
 }
 
 void ip6_route_input(struct sk_buff *skb)
@@ -770,10 +769,10 @@ void ip6_route_input(struct sk_buff *skb
 	skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);
 }
 
-static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
+static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
 					     struct flowi *fl, int flags)
 {
-	return ip6_pol_route(table, fl->oif, fl, flags);
+	return ip6_pol_route(net, table, fl->oif, fl, flags);
 }
 
 struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
@@ -1259,8 +1258,9 @@ static int __ip6_del_rt(struct rt6_info 
 {
 	int err;
 	struct fib6_table *table;
+	struct net *net = rt->rt6i_dev->nd_net;
 
-	if (rt == ip6_null_entry)
+	if (rt == net->ipv6.ip6_null_entry)
 		return -ENOENT;
 
 	table = rt->rt6i_table;
@@ -1329,7 +1329,8 @@ struct ip6rd_flowi {
 	struct in6_addr gateway;
 };
 
-static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
+static struct rt6_info *__ip6_route_redirect(struct net *net,
+					     struct fib6_table *table,
 					     struct flowi *fl,
 					     int flags)
 {
@@ -1372,8 +1373,8 @@ restart:
 	}
 
 	if (!rt)
-		rt = ip6_null_entry;
-	BACKTRACK(&fl->fl6_src);
+		rt = net->ipv6.ip6_null_entry;
+	BACKTRACK(net, &fl->fl6_src);
 out:
 	dst_hold(&rt->u.dst);
 
@@ -1415,10 +1416,11 @@ void rt6_redirect(struct in6_addr *dest,
 {
 	struct rt6_info *rt, *nrt = NULL;
 	struct netevent_redirect netevent;
+	struct net *net = neigh->dev->nd_net;
 
 	rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
 
-	if (rt == ip6_null_entry) {
+	if (rt == net->ipv6.ip6_null_entry) {
 		if (net_ratelimit())
 			printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
 			       "for redirect target\n");
@@ -1886,10 +1888,18 @@ struct rt6_info *addrconf_dst_alloc(stru
 	return rt;
 }
 
+struct arg_dev_net {
+	struct net_device *dev;
+	struct net *net;
+};
+
 static int fib6_ifdown(struct rt6_info *rt, void *arg)
 {
-	if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
-	    rt != ip6_null_entry) {
+	struct net_device *dev = ((struct arg_dev_net *)arg)->dev;
+	struct net *net = ((struct arg_dev_net *)arg)->net;
+
+	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
+	    rt != net->ipv6.ip6_null_entry) {
 		RT6_TRACE("deleted by ifdown %p\n", rt);
 		return -1;
 	}
@@ -1898,7 +1908,12 @@ static int fib6_ifdown(struct rt6_info *
 
 void rt6_ifdown(struct net *net, struct net_device *dev)
 {
-	fib6_clean_all(net, fib6_ifdown, 0, dev);
+	struct arg_dev_net adn = {
+		.dev = dev,
+		.net = net,
+	};
+
+	fib6_clean_all(net, fib6_ifdown, 0, &adn);
 }
 
 struct rt6_mtu_change_arg
@@ -2289,6 +2304,26 @@ errout:
 		rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
 }
 
+static int ip6_route_dev_notify(struct notifier_block *this,
+				unsigned long event, void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct net *net = dev->nd_net;
+
+	if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
+		net->ipv6.ip6_null_entry->u.dst.dev = dev;
+		net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+		net->ipv6.ip6_prohibit_entry->u.dst.dev = dev;
+		net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
+		net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev;
+		net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
+#endif
+	}
+
+	return NOTIFY_OK;
+}
+
 /*
  *	/proc
  */
@@ -2535,11 +2570,47 @@ struct ctl_table *ipv6_route_sysctl_init
 
 static int ip6_route_net_init(struct net *net)
 {
+	int ret = 0;
+
+	ret = -ENOMEM;
+	net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
+					   sizeof(*net->ipv6.ip6_null_entry),
+					   GFP_KERNEL);
+	if (!net->ipv6.ip6_null_entry)
+		goto out;
+	net->ipv6.ip6_null_entry->u.dst.path =
+		(struct dst_entry *)net->ipv6.ip6_null_entry;
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
+					       sizeof(*net->ipv6.ip6_prohibit_entry),
+					       GFP_KERNEL);
+	if (!net->ipv6.ip6_prohibit_entry) {
+		kfree(net->ipv6.ip6_null_entry);
+		goto out;
+	}
+	net->ipv6.ip6_prohibit_entry->u.dst.path =
+		(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
+
+	net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
+					       sizeof(*net->ipv6.ip6_blk_hole_entry),
+					       GFP_KERNEL);
+	if (!net->ipv6.ip6_blk_hole_entry) {
+		kfree(net->ipv6.ip6_null_entry);
+		kfree(net->ipv6.ip6_prohibit_entry);
+		goto out;
+	}
+	net->ipv6.ip6_blk_hole_entry->u.dst.path =
+		(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
+#endif
+
 #ifdef CONFIG_PROC_FS
 	proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
 	proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
 #endif
-	return 0;
+	ret = 0;
+out:
+	return ret;
 }
 
 static void ip6_route_net_exit(struct net *net)
@@ -2548,7 +2619,11 @@ static void ip6_route_net_exit(struct ne
 	proc_net_remove(net, "ipv6_route");
 	proc_net_remove(net, "rt6_stats");
 #endif
-	rt6_ifdown(net, NULL);
+	kfree(net->ipv6.ip6_null_entry);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(net->ipv6.ip6_prohibit_entry);
+	kfree(net->ipv6.ip6_blk_hole_entry);
+#endif
 }
 
 static struct pernet_operations ip6_route_net_ops = {
@@ -2556,6 +2631,11 @@ static struct pernet_operations ip6_rout
 	.exit = ip6_route_net_exit,
 };
 
+static struct notifier_block ip6_route_dev_notifier = {
+	.notifier_call = ip6_route_dev_notify,
+	.priority = 0,
+};
+
 int __init ip6_route_init(void)
 {
 	int ret;
@@ -2568,30 +2648,24 @@ int __init ip6_route_init(void)
 
 	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
 
-	ret = -ENOMEM;
-	ip6_null_entry = kmemdup(&ip6_null_entry_template,
-				 sizeof(*ip6_null_entry), GFP_KERNEL);
-	if (!ip6_null_entry)
+	ret = register_pernet_subsys(&ip6_route_net_ops);
+	if (ret)
 		goto out_kmem_cache;
-	ip6_null_entry->u.dst.path = (struct dst_entry *)ip6_null_entry;
-
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
-				     sizeof(*ip6_prohibit_entry), GFP_KERNEL);
-	if (!ip6_prohibit_entry)
-		goto out_ip6_null_entry;
-	ip6_prohibit_entry->u.dst.path = (struct dst_entry *)ip6_prohibit_entry;
-
-	ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
-				     sizeof(*ip6_blk_hole_entry), GFP_KERNEL);
-	if (!ip6_blk_hole_entry)
-		goto out_ip6_prohibit_entry;
-	ip6_blk_hole_entry->u.dst.path = (struct dst_entry *)ip6_blk_hole_entry;
-#endif
 
+	/* Registering of the loopback is done before this portion of code,
+	 * the loopback reference in rt6_info will not be taken, do it
+	 * manually for init_net */
+	init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #endif
 	ret = fib6_init();
 	if (ret)
-		goto out_ip6_blk_hole_entry;
+		goto out_register_subsys;
 
 	ret = xfrm6_init();
 	if (ret)
@@ -2607,9 +2681,10 @@ int __init ip6_route_init(void)
 	    __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
 		goto fib6_rules_init;
 
-	ret = register_pernet_subsys(&ip6_route_net_ops);
+	ret = register_netdevice_notifier(&ip6_route_dev_notifier);
 	if (ret)
 		goto fib6_rules_init;
+
 out:
 	return ret;
 
@@ -2619,14 +2694,8 @@ xfrm6_init:
 	xfrm6_fini();
 out_fib6_init:
 	fib6_gc_cleanup();
-out_ip6_blk_hole_entry:
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	kfree(ip6_blk_hole_entry);
-out_ip6_prohibit_entry:
-	kfree(ip6_prohibit_entry);
-out_ip6_null_entry:
-#endif
-	kfree(ip6_null_entry);
+out_register_subsys:
+	unregister_pernet_subsys(&ip6_route_net_ops);
 out_kmem_cache:
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
 	goto out;
@@ -2634,15 +2703,10 @@ out_kmem_cache:
 
 void ip6_route_cleanup(void)
 {
-	unregister_pernet_subsys(&ip6_route_net_ops);
+	unregister_netdevice_notifier(&ip6_route_dev_notifier);
 	fib6_rules_cleanup();
 	xfrm6_fini();
 	fib6_gc_cleanup();
+	unregister_pernet_subsys(&ip6_route_net_ops);
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
-
-	kfree(ip6_null_entry);
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	kfree(ip6_prohibit_entry);
-	kfree(ip6_blk_hole_entry);
-#endif
 }

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 09/12][NETNS][IPV6] route6 - dynamically allocate ip6_dst_ops
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (7 preceding siblings ...)
  2008-03-04 21:03 ` [patch 08/12][NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 10/12][NETNS][IPV6] route6 - move ip6_dst_ops inside the network namespace Daniel Lezcano
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-alloc-ip6_dst_ops-dynamically.patch --]
[-- Type: text/plain, Size: 6487 bytes --]

ip6_dst_ops is dynamically allocated in init and exit functions.
That provides the ability to do multiple instanciations of this structure.

This will be needed for network namespaces, indeed dst_ops stores 
data that are required to be per namespace: entries and gc_thresh.

Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 net/ipv6/route.c |   47 +++++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 18 deletions(-)

Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -97,7 +97,7 @@ static struct rt6_info *rt6_get_route_in
 					   struct in6_addr *gwaddr, int ifindex);
 #endif
 
-static struct dst_ops ip6_dst_ops = {
+static struct dst_ops ip6_dst_ops_template = {
 	.family			=	AF_INET6,
 	.protocol		=	__constant_htons(ETH_P_IPV6),
 	.gc			=	ip6_dst_gc,
@@ -113,6 +113,8 @@ static struct dst_ops ip6_dst_ops = {
 	.entries		=	ATOMIC_INIT(0),
 };
 
+static struct dst_ops *ip6_dst_ops;
+
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
@@ -137,7 +139,6 @@ static struct rt6_info ip6_null_entry_te
 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
 			.input		= ip6_pkt_discard,
 			.output		= ip6_pkt_discard_out,
-			.ops		= &ip6_dst_ops,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -160,7 +161,6 @@ struct rt6_info ip6_prohibit_entry_templ
 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
 			.input		= ip6_pkt_prohibit,
 			.output		= ip6_pkt_prohibit_out,
-			.ops		= &ip6_dst_ops,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -178,7 +178,6 @@ static struct rt6_info ip6_blk_hole_entr
 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
 			.input		= dst_discard,
 			.output		= dst_discard,
-			.ops		= &ip6_dst_ops,
 		}
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
@@ -191,7 +190,7 @@ static struct rt6_info ip6_blk_hole_entr
 /* allocate dst with ip6_dst_ops */
 static __inline__ struct rt6_info *ip6_dst_alloc(void)
 {
-	return (struct rt6_info *)dst_alloc(&ip6_dst_ops);
+	return (struct rt6_info *)dst_alloc(ip6_dst_ops);
 }
 
 static void ip6_dst_destroy(struct dst_entry *dst)
@@ -1000,18 +999,18 @@ static int ip6_dst_gc(struct dst_ops *op
 	unsigned long now = jiffies;
 
 	if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
-	    atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
+	    atomic_read(&ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
 		goto out;
 
 	expire++;
 	fib6_run_gc(expire, &init_net);
 	last_gc = now;
-	if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh)
+	if (atomic_read(&ip6_dst_ops->entries) < ip6_dst_ops->gc_thresh)
 		expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
 
 out:
 	expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
-	return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
+	return (atomic_read(&ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -2408,7 +2407,7 @@ static int rt6_stats_seq_show(struct seq
 		   net->ipv6.rt6_stats->fib_rt_alloc,
 		   net->ipv6.rt6_stats->fib_rt_entries,
 		   net->ipv6.rt6_stats->fib_rt_cache,
-		   atomic_read(&ip6_dst_ops.entries),
+		   atomic_read(&ip6_dst_ops->entries),
 		   net->ipv6.rt6_stats->fib_discarded_routes);
 
 	return 0;
@@ -2464,7 +2463,7 @@ ctl_table ipv6_route_table_template[] = 
 	{
 		.ctl_name	=	NET_IPV6_ROUTE_GC_THRESH,
 		.procname	=	"gc_thresh",
-		.data		=	&ip6_dst_ops.gc_thresh,
+		.data		=	&ip6_dst_ops_template.gc_thresh,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
 		.proc_handler	=	&proc_dointvec,
@@ -2553,8 +2552,7 @@ struct ctl_table *ipv6_route_sysctl_init
 
 	if (table) {
 		table[0].data = &net->ipv6.sysctl.flush_delay;
-		/* table[1].data will be handled when we have
-		   routes per namespace */
+		table[1].data = &ip6_dst_ops_template.gc_thresh;
 		table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
 		table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
 		table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
@@ -2580,6 +2578,7 @@ static int ip6_route_net_init(struct net
 		goto out;
 	net->ipv6.ip6_null_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_null_entry;
+	net->ipv6.ip6_null_entry->u.dst.ops = ip6_dst_ops;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2591,6 +2590,7 @@ static int ip6_route_net_init(struct net
 	}
 	net->ipv6.ip6_prohibit_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
+	net->ipv6.ip6_prohibit_entry->u.dst.ops = ip6_dst_ops;
 
 	net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
 					       sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2602,6 +2602,7 @@ static int ip6_route_net_init(struct net
 	}
 	net->ipv6.ip6_blk_hole_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
+	net->ipv6.ip6_blk_hole_entry->u.dst.ops = ip6_dst_ops;
 #endif
 
 #ifdef CONFIG_PROC_FS
@@ -2640,13 +2641,20 @@ int __init ip6_route_init(void)
 {
 	int ret;
 
-	ip6_dst_ops.kmem_cachep =
+	ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
+			      sizeof(*ip6_dst_ops), GFP_KERNEL);
+	if (!ip6_dst_ops)
+		return -ENOMEM;
+
+	ret = -ENOMEM;
+	ip6_dst_ops_template.kmem_cachep =
 		kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
 				  SLAB_HWCACHE_ALIGN, NULL);
-	if (!ip6_dst_ops.kmem_cachep)
-		return -ENOMEM;
+	if (!ip6_dst_ops_template.kmem_cachep)
+		goto out_ip6_dst_ops;
 
-	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
+	ip6_dst_ops->kmem_cachep = ip6_dst_ops_template.kmem_cachep;
+	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
 
 	ret = register_pernet_subsys(&ip6_route_net_ops);
 	if (ret)
@@ -2697,7 +2705,9 @@ out_fib6_init:
 out_register_subsys:
 	unregister_pernet_subsys(&ip6_route_net_ops);
 out_kmem_cache:
-	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+	kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
+out_ip6_dst_ops:
+	kfree(ip6_dst_ops);
 	goto out;
 }
 
@@ -2708,5 +2718,6 @@ void ip6_route_cleanup(void)
 	xfrm6_fini();
 	fib6_gc_cleanup();
 	unregister_pernet_subsys(&ip6_route_net_ops);
-	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+	kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
+	kfree(ip6_dst_ops);
 }

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 10/12][NETNS][IPV6] route6 - move ip6_dst_ops inside the network namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (8 preceding siblings ...)
  2008-03-04 21:03 ` [patch 09/12][NETNS][IPV6] route6 - dynamically allocate ip6_dst_ops Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 11/12][NETNS][IPV6] route6 - make garbage collection work with multiple network namespaces Daniel Lezcano
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-ip6_dst_ops-per-namespace.patch --]
[-- Type: text/plain, Size: 7658 bytes --]

The ip6_dst_ops is moved inside the network namespace structure. 
All references to this structure are now relative to the initial network 
namespace.

Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/netns/ipv6.h |    1 
 net/ipv6/route.c         |   62 +++++++++++++++++++++++------------------------
 2 files changed, 32 insertions(+), 31 deletions(-)

Index: net-2.6.26/include/net/netns/ipv6.h
===================================================================
--- net-2.6.26.orig/include/net/netns/ipv6.h
+++ net-2.6.26/include/net/netns/ipv6.h
@@ -41,6 +41,7 @@ struct netns_ipv6 {
 	struct timer_list       *ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;
+	struct dst_ops		*ip6_dst_ops;
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	struct rt6_info         *ip6_prohibit_entry;
 	struct rt6_info         *ip6_blk_hole_entry;
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -113,8 +113,6 @@ static struct dst_ops ip6_dst_ops_templa
 	.entries		=	ATOMIC_INIT(0),
 };
 
-static struct dst_ops *ip6_dst_ops;
-
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
@@ -188,9 +186,9 @@ static struct rt6_info ip6_blk_hole_entr
 #endif
 
 /* allocate dst with ip6_dst_ops */
-static __inline__ struct rt6_info *ip6_dst_alloc(void)
+static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops)
 {
-	return (struct rt6_info *)dst_alloc(ip6_dst_ops);
+	return (struct rt6_info *)dst_alloc(ops);
 }
 
 static void ip6_dst_destroy(struct dst_entry *dst)
@@ -925,7 +923,7 @@ struct dst_entry *icmp6_dst_alloc(struct
 	if (unlikely(idev == NULL))
 		return NULL;
 
-	rt = ip6_dst_alloc();
+	rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
 	if (unlikely(rt == NULL)) {
 		in6_dev_put(idev);
 		goto out;
@@ -999,18 +997,18 @@ static int ip6_dst_gc(struct dst_ops *op
 	unsigned long now = jiffies;
 
 	if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
-	    atomic_read(&ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
+	    atomic_read(&init_net.ipv6.ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
 		goto out;
 
 	expire++;
 	fib6_run_gc(expire, &init_net);
 	last_gc = now;
-	if (atomic_read(&ip6_dst_ops->entries) < ip6_dst_ops->gc_thresh)
+	if (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) < init_net.ipv6.ip6_dst_ops->gc_thresh)
 		expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
 
 out:
 	expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
-	return (atomic_read(&ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
+	return (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -1084,7 +1082,7 @@ int ip6_route_add(struct fib6_config *cf
 		goto out;
 	}
 
-	rt = ip6_dst_alloc();
+	rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
 
 	if (rt == NULL) {
 		err = -ENOMEM;
@@ -1570,7 +1568,8 @@ out:
 
 static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
 {
-	struct rt6_info *rt = ip6_dst_alloc();
+	struct net *net = ort->rt6i_dev->nd_net;
+	struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
 
 	if (rt) {
 		rt->u.dst.input = ort->u.dst.input;
@@ -1849,7 +1848,7 @@ struct rt6_info *addrconf_dst_alloc(stru
 				    int anycast)
 {
 	struct net *net = idev->dev->nd_net;
-	struct rt6_info *rt = ip6_dst_alloc();
+	struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
 
 	if (rt == NULL)
 		return ERR_PTR(-ENOMEM);
@@ -2407,7 +2406,7 @@ static int rt6_stats_seq_show(struct seq
 		   net->ipv6.rt6_stats->fib_rt_alloc,
 		   net->ipv6.rt6_stats->fib_rt_entries,
 		   net->ipv6.rt6_stats->fib_rt_cache,
-		   atomic_read(&ip6_dst_ops->entries),
+		   atomic_read(&net->ipv6.ip6_dst_ops->entries),
 		   net->ipv6.rt6_stats->fib_discarded_routes);
 
 	return 0;
@@ -2552,7 +2551,7 @@ struct ctl_table *ipv6_route_sysctl_init
 
 	if (table) {
 		table[0].data = &net->ipv6.sysctl.flush_delay;
-		table[1].data = &ip6_dst_ops_template.gc_thresh;
+		table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh;
 		table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
 		table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
 		table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
@@ -2571,14 +2570,21 @@ static int ip6_route_net_init(struct net
 	int ret = 0;
 
 	ret = -ENOMEM;
+	net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
+					sizeof(*net->ipv6.ip6_dst_ops),
+					GFP_KERNEL);
+	if (!net->ipv6.ip6_dst_ops)
+		goto out;
+	net->ipv6.ip6_dst_ops->dst_net = net;
+
 	net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
 					   sizeof(*net->ipv6.ip6_null_entry),
 					   GFP_KERNEL);
 	if (!net->ipv6.ip6_null_entry)
-		goto out;
+		goto out_ip6_dst_ops;
 	net->ipv6.ip6_null_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_null_entry;
-	net->ipv6.ip6_null_entry->u.dst.ops = ip6_dst_ops;
+	net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2590,7 +2596,7 @@ static int ip6_route_net_init(struct net
 	}
 	net->ipv6.ip6_prohibit_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
-	net->ipv6.ip6_prohibit_entry->u.dst.ops = ip6_dst_ops;
+	net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
 
 	net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
 					       sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2602,7 +2608,7 @@ static int ip6_route_net_init(struct net
 	}
 	net->ipv6.ip6_blk_hole_entry->u.dst.path =
 		(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
-	net->ipv6.ip6_blk_hole_entry->u.dst.ops = ip6_dst_ops;
+	net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
 #endif
 
 #ifdef CONFIG_PROC_FS
@@ -2612,6 +2618,10 @@ static int ip6_route_net_init(struct net
 	ret = 0;
 out:
 	return ret;
+
+out_ip6_dst_ops:
+	kfree(net->ipv6.ip6_dst_ops);
+	goto out;
 }
 
 static void ip6_route_net_exit(struct net *net)
@@ -2625,6 +2635,7 @@ static void ip6_route_net_exit(struct ne
 	kfree(net->ipv6.ip6_prohibit_entry);
 	kfree(net->ipv6.ip6_blk_hole_entry);
 #endif
+	kfree(net->ipv6.ip6_dst_ops);
 }
 
 static struct pernet_operations ip6_route_net_ops = {
@@ -2641,20 +2652,12 @@ int __init ip6_route_init(void)
 {
 	int ret;
 
-	ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
-			      sizeof(*ip6_dst_ops), GFP_KERNEL);
-	if (!ip6_dst_ops)
-		return -ENOMEM;
-
 	ret = -ENOMEM;
 	ip6_dst_ops_template.kmem_cachep =
 		kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
 				  SLAB_HWCACHE_ALIGN, NULL);
 	if (!ip6_dst_ops_template.kmem_cachep)
-		goto out_ip6_dst_ops;
-
-	ip6_dst_ops->kmem_cachep = ip6_dst_ops_template.kmem_cachep;
-	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
+		goto out;;
 
 	ret = register_pernet_subsys(&ip6_route_net_ops);
 	if (ret)
@@ -2705,9 +2708,7 @@ out_fib6_init:
 out_register_subsys:
 	unregister_pernet_subsys(&ip6_route_net_ops);
 out_kmem_cache:
-	kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
-out_ip6_dst_ops:
-	kfree(ip6_dst_ops);
+	kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
 	goto out;
 }
 
@@ -2718,6 +2719,5 @@ void ip6_route_cleanup(void)
 	xfrm6_fini();
 	fib6_gc_cleanup();
 	unregister_pernet_subsys(&ip6_route_net_ops);
-	kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
-	kfree(ip6_dst_ops);
+	kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
 }

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 11/12][NETNS][IPV6] route6 - make garbage collection work with multiple network namespaces
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (9 preceding siblings ...)
  2008-03-04 21:03 ` [patch 10/12][NETNS][IPV6] route6 - move ip6_dst_ops inside the network namespace Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 21:03 ` [patch 12/12][NETNS][IPV6] route6 - Make ip6_dst_gc simpler Daniel Lezcano
  2008-03-04 22:15 ` [patch 00/12][NETNS][IPV6] Finish the routing per namespace David Miller
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-make-ip6_dst_gc-per-namespace.patch --]
[-- Type: text/plain, Size: 2981 bytes --]

This patch makes the necessary changes to make IPv6 dst_entry garbage 
collection work with multiple network namespaces.

In ip6_dst_gc(), static local variables are now declared per-namespace.

Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/netns/ipv6.h |    2 ++
 net/ipv6/route.c         |   23 ++++++++++++-----------
 2 files changed, 14 insertions(+), 11 deletions(-)

Index: net-2.6.26/include/net/netns/ipv6.h
===================================================================
--- net-2.6.26.orig/include/net/netns/ipv6.h
+++ net-2.6.26/include/net/netns/ipv6.h
@@ -42,6 +42,8 @@ struct netns_ipv6 {
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;
 	struct dst_ops		*ip6_dst_ops;
+	unsigned int		 ip6_rt_gc_expire;
+	unsigned long		 ip6_rt_last_gc;
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	struct rt6_info         *ip6_prohibit_entry;
 	struct rt6_info         *ip6_blk_hole_entry;
Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -992,23 +992,22 @@ int icmp6_dst_gc(int *more)
 
 static int ip6_dst_gc(struct dst_ops *ops)
 {
-	static unsigned expire = 30*HZ;
-	static unsigned long last_gc;
+	struct net *net = ops->dst_net;
 	unsigned long now = jiffies;
 
-	if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
-	    atomic_read(&init_net.ipv6.ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
+	if (time_after(net->ipv6.ip6_rt_last_gc + net->ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
+	    atomic_read(&net->ipv6.ip6_dst_ops->entries) <= net->ipv6.sysctl.ip6_rt_max_size)
 		goto out;
 
-	expire++;
-	fib6_run_gc(expire, &init_net);
-	last_gc = now;
-	if (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) < init_net.ipv6.ip6_dst_ops->gc_thresh)
-		expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
+	net->ipv6.ip6_rt_gc_expire++;
+	fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
+	net->ipv6.ip6_rt_last_gc = now;
+	if (atomic_read(&net->ipv6.ip6_dst_ops->entries) < net->ipv6.ip6_dst_ops->gc_thresh)
+		net->ipv6.ip6_rt_gc_expire = net->ipv6.sysctl.ip6_rt_gc_timeout>>1;
 
 out:
-	expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
-	return (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
+	net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>net->ipv6.sysctl.ip6_rt_gc_elasticity;
+	return (atomic_read(&net->ipv6.ip6_dst_ops->entries) > net->ipv6.sysctl.ip6_rt_max_size);
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -2615,6 +2614,8 @@ static int ip6_route_net_init(struct net
 	proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
 	proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
 #endif
+	net->ipv6.ip6_rt_gc_expire = 30*HZ;
+
 	ret = 0;
 out:
 	return ret;

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [patch 12/12][NETNS][IPV6] route6 - Make ip6_dst_gc simpler
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (10 preceding siblings ...)
  2008-03-04 21:03 ` [patch 11/12][NETNS][IPV6] route6 - make garbage collection work with multiple network namespaces Daniel Lezcano
@ 2008-03-04 21:03 ` Daniel Lezcano
  2008-03-04 22:15 ` [patch 00/12][NETNS][IPV6] Finish the routing per namespace David Miller
  12 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-04 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, benjamin.thery

[-- Attachment #1: route6-make-ip6_dst_gc-simpler.patch --]
[-- Type: text/plain, Size: 2106 bytes --]

This patches improves the readibility of the ip6_dst_gc() routine.
It simplifies long lines which grow a lot due to the introduction
of network namespaces support.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Acked-by: Benjamin Thery <benjamin.thery@bull.net>
---
 net/ipv6/route.c |   20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

Index: net-2.6.26/net/ipv6/route.c
===================================================================
--- net-2.6.26.orig/net/ipv6/route.c
+++ net-2.6.26/net/ipv6/route.c
@@ -992,22 +992,26 @@ int icmp6_dst_gc(int *more)
 
 static int ip6_dst_gc(struct dst_ops *ops)
 {
-	struct net *net = ops->dst_net;
 	unsigned long now = jiffies;
+	struct net *net = ops->dst_net;
+	int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
+	int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
+	int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
+	int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
+	unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
 
-	if (time_after(net->ipv6.ip6_rt_last_gc + net->ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
-	    atomic_read(&net->ipv6.ip6_dst_ops->entries) <= net->ipv6.sysctl.ip6_rt_max_size)
+	if (time_after(rt_last_gc + rt_min_interval, now) &&
+	    atomic_read(&ops->entries) <= rt_max_size)
 		goto out;
 
 	net->ipv6.ip6_rt_gc_expire++;
 	fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
 	net->ipv6.ip6_rt_last_gc = now;
-	if (atomic_read(&net->ipv6.ip6_dst_ops->entries) < net->ipv6.ip6_dst_ops->gc_thresh)
-		net->ipv6.ip6_rt_gc_expire = net->ipv6.sysctl.ip6_rt_gc_timeout>>1;
-
+	if (atomic_read(&ops->entries) < ops->gc_thresh)
+		net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
 out:
-	net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>net->ipv6.sysctl.ip6_rt_gc_elasticity;
-	return (atomic_read(&net->ipv6.ip6_dst_ops->entries) > net->ipv6.sysctl.ip6_rt_max_size);
+	net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
+	return (atomic_read(&ops->entries) > rt_max_size);
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,

-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 00/12][NETNS][IPV6] Finish the routing per namespace
  2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
                   ` (11 preceding siblings ...)
  2008-03-04 21:03 ` [patch 12/12][NETNS][IPV6] route6 - Make ip6_dst_gc simpler Daniel Lezcano
@ 2008-03-04 22:15 ` David Miller
  12 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-03-04 22:15 UTC (permalink / raw)
  To: dlezcano; +Cc: netdev, benjamin.thery

From: Daniel Lezcano <dlezcano@fr.ibm.com>
Date: Tue, 04 Mar 2008 22:03:26 +0100

> This second round of patches makes the routing per namespace to be 
> complete and to have the routing engine to support multiple network
> namespace.

All applied and pushed out, thanks!

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace
  2008-03-04 21:03 ` [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace Daniel Lezcano
@ 2008-03-04 23:02   ` YOSHIFUJI Hideaki / 吉藤英明
  2008-03-05  9:33     ` Daniel Lezcano
  0 siblings, 1 reply; 16+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2008-03-04 23:02 UTC (permalink / raw)
  To: dlezcano; +Cc: davem, netdev, benjamin.thery, yoshfuji

In article <20080304211023.817913201@mai.toulouse-stg.fr.ibm.com> (at Tue, 04 Mar 2008 22:03:32 +0100), Daniel Lezcano <dlezcano@fr.ibm.com> says:

> This patch makes the routing engine use the network namespaces
> to access routing informations:
> Add a network namespace parameter to ipv6_route_ioctl and 
> propagate the network namespace value to all the routing code
> that have not yet been changed.
> 
> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
> ---
>  include/net/ip6_route.h |    4 +
>  net/ipv6/af_inet6.c     |    3 -
>  net/ipv6/route.c        |   98 ++++++++++++++++++++++++------------------------
>  3 files changed, 54 insertions(+), 51 deletions(-)
> 
:
> @@ -2544,6 +2545,7 @@ static void ip6_route_net_exit(struct ne
>  	proc_net_remove(net, "ipv6_route");
>  	proc_net_remove(net, "rt6_stats");
>  #endif
> +	rt6_ifdown(net, NULL);
>  }
>  
>  static struct pernet_operations ip6_route_net_ops = {
> @@ -2592,7 +2594,6 @@ fib6_rules_init:
>  xfrm6_init:
>  	xfrm6_fini();
>  out_fib6_init:
> -	rt6_ifdown(&init_net, NULL);
>  	fib6_gc_cleanup();
>  out_kmem_cache:
>  	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);

Please do not change the calling path here.

--yoshfuji

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace
  2008-03-04 23:02   ` YOSHIFUJI Hideaki / 吉藤英明
@ 2008-03-05  9:33     ` Daniel Lezcano
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2008-03-05  9:33 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / 吉藤英明
  Cc: davem, netdev, benjamin.thery

YOSHIFUJI Hideaki / 吉藤英明 wrote:
> In article <20080304211023.817913201@mai.toulouse-stg.fr.ibm.com> (at Tue, 04 Mar 2008 22:03:32 +0100), Daniel Lezcano <dlezcano@fr.ibm.com> says:
> 
>> This patch makes the routing engine use the network namespaces
>> to access routing informations:
>> Add a network namespace parameter to ipv6_route_ioctl and 
>> propagate the network namespace value to all the routing code
>> that have not yet been changed.
>>
>> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
>> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
>> ---
>>  include/net/ip6_route.h |    4 +
>>  net/ipv6/af_inet6.c     |    3 -
>>  net/ipv6/route.c        |   98 ++++++++++++++++++++++++------------------------
>>  3 files changed, 54 insertions(+), 51 deletions(-)
>>
> :
>> @@ -2544,6 +2545,7 @@ static void ip6_route_net_exit(struct ne
>>  	proc_net_remove(net, "ipv6_route");
>>  	proc_net_remove(net, "rt6_stats");
>>  #endif
>> +	rt6_ifdown(net, NULL);
>>  }
>>  
>>  static struct pernet_operations ip6_route_net_ops = {
>> @@ -2592,7 +2594,6 @@ fib6_rules_init:
>>  xfrm6_init:
>>  	xfrm6_fini();
>>  out_fib6_init:
>> -	rt6_ifdown(&init_net, NULL);
>>  	fib6_gc_cleanup();
>>  out_kmem_cache:
>>  	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
> 
> Please do not change the calling path here.

The calling path is still the same. Instead of having rt6_ifdown called 
before fib6_gc_cleanup, it is the first function called into 
fib6_gc_cleanup via unregister_pernet_subsys.

This is because we need to call rt6_ifdown when a network namespace 
exits or when the system shutdown (aka init_net exits).

   -- Daniel




^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2008-03-05  9:36 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-04 21:03 [patch 00/12][NETNS][IPV6] Finish the routing per namespace Daniel Lezcano
2008-03-04 21:03 ` [patch 01/12][NETNS][IPV6] route6 - create route6 proc files for the namespace Daniel Lezcano
2008-03-04 21:03 ` [patch 02/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_lookup Daniel Lezcano
2008-03-04 21:03 ` [patch 03/12][NETNS][IPV6] route6 - Make proc entry /proc/net/rt6_stats per namespace Daniel Lezcano
2008-03-04 21:03 ` [patch 04/12][NETNS][IPV6] route6 - Pass network namespace to rt6_add_route_info and rt6_get_route_info Daniel Lezcano
2008-03-04 21:03 ` [patch 05/12][NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_purge_dflt_routers Daniel Lezcano
2008-03-04 21:03 ` [patch 06/12][NETNS][IPV6] route6 - make route6 per namespace Daniel Lezcano
2008-03-04 23:02   ` YOSHIFUJI Hideaki / 吉藤英明
2008-03-05  9:33     ` Daniel Lezcano
2008-03-04 21:03 ` [patch 07/12][NETNS][IPV6] rt6_info - make rt6_info accessed as a pointer Daniel Lezcano
2008-03-04 21:03 ` [patch 08/12][NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace Daniel Lezcano
2008-03-04 21:03 ` [patch 09/12][NETNS][IPV6] route6 - dynamically allocate ip6_dst_ops Daniel Lezcano
2008-03-04 21:03 ` [patch 10/12][NETNS][IPV6] route6 - move ip6_dst_ops inside the network namespace Daniel Lezcano
2008-03-04 21:03 ` [patch 11/12][NETNS][IPV6] route6 - make garbage collection work with multiple network namespaces Daniel Lezcano
2008-03-04 21:03 ` [patch 12/12][NETNS][IPV6] route6 - Make ip6_dst_gc simpler Daniel Lezcano
2008-03-04 22:15 ` [patch 00/12][NETNS][IPV6] Finish the routing per namespace David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).