All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.