netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace
@ 2008-01-25 16:50 Daniel Lezcano
  2008-01-25 16:50 ` [patch 01/11][NETNS][IPV6] ip6_fib - dynamically allocate the tables Daniel Lezcano
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

This patchset makes a subset of the routing to be per
namespace. It takes into account fib tables, garbage
collecting timer, fib rules and route statistics.

The routing per namespace is not complete with this
patchset, so there are some interactions between the init
network namespace and other namespaces, but nothing
critical.

This patchset will be followed by another one which
will complete the routing per namespace. I just don't want
to flood netdev@ with a huge patchset.

-- 

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

* [patch 01/11][NETNS][IPV6] ip6_fib - dynamically allocate the tables
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 02/11][NETNS][IPV6] ip6_fib - make the tables per namespace Daniel Lezcano
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-dynamic-allocation.patch --]
[-- Type: text/plain, Size: 4135 bytes --]

This patch changes the fib6 tables to be dynamically allocated.
That provides the ability to make several instances of them when
a new network namespace is created.

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

Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -166,20 +166,14 @@ static __inline__ void rt6_release(struc
 		dst_free(&rt->u.dst);
 }
 
-static struct fib6_table fib6_main_tbl = {
-	.tb6_id		= RT6_TABLE_MAIN,
-	.tb6_root	= {
-		.leaf		= &ip6_null_entry,
-		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
-	},
-};
+static struct fib6_table *fib6_main_tbl;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 #define FIB_TABLE_HASHSZ 256
 #else
 #define FIB_TABLE_HASHSZ 1
 #endif
-static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+static struct hlist_head *fib_table_hash;
 
 static void fib6_link_table(struct fib6_table *tb)
 {
@@ -201,13 +195,8 @@ static void fib6_link_table(struct fib6_
 }
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-static struct fib6_table fib6_local_tbl = {
-	.tb6_id		= RT6_TABLE_LOCAL,
-	.tb6_root 	= {
-		.leaf		= &ip6_null_entry,
-		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
-	},
-};
+
+static struct fib6_table *fib6_local_tbl;
 
 static struct fib6_table *fib6_alloc_table(u32 id)
 {
@@ -263,8 +252,8 @@ struct fib6_table *fib6_get_table(u32 id
 
 static void __init fib6_tables_init(void)
 {
-	fib6_link_table(&fib6_main_tbl);
-	fib6_link_table(&fib6_local_tbl);
+	fib6_link_table(fib6_main_tbl);
+	fib6_link_table(fib6_local_tbl);
 }
 
 #else
@@ -276,18 +265,18 @@ struct fib6_table *fib6_new_table(u32 id
 
 struct fib6_table *fib6_get_table(u32 id)
 {
-	return &fib6_main_tbl;
+	return fib6_main_tbl;
 }
 
 struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
 				   pol_lookup_t lookup)
 {
-	return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
+	return (struct dst_entry *) lookup(fib6_main_tbl, fl, flags);
 }
 
 static void __init fib6_tables_init(void)
 {
-	fib6_link_table(&fib6_main_tbl);
+	fib6_link_table(fib6_main_tbl);
 }
 
 #endif
@@ -1479,22 +1468,53 @@ void fib6_run_gc(unsigned long dummy)
 
 int __init fib6_init(void)
 {
-	int ret;
+	int ret = -ENOMEM;
 	fib6_node_kmem = kmem_cache_create("fib6_nodes",
 					   sizeof(struct fib6_node),
 					   0, SLAB_HWCACHE_ALIGN,
 					   NULL);
 	if (!fib6_node_kmem)
-		return -ENOMEM;
+		goto out;
+
+	fib_table_hash = kzalloc(sizeof(*fib_table_hash)*FIB_TABLE_HASHSZ,
+				 GFP_KERNEL);
+	if (!fib_table_hash)
+		goto out_kmem_cache_create;
+
+	fib6_main_tbl = kzalloc(sizeof(*fib6_main_tbl), GFP_KERNEL);
+	if (!fib6_main_tbl)
+		goto out_fib_table_hash;
+
+	fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
+	fib6_main_tbl->tb6_root.leaf = &ip6_null_entry;
+	fib6_main_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	fib6_local_tbl = kzalloc(sizeof(*fib6_local_tbl), GFP_KERNEL);
+	if (!fib6_local_tbl)
+		goto out_fib6_main_tbl;
+
+	fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
+	fib6_local_tbl->tb6_root.leaf = &ip6_null_entry;
+	fib6_local_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+#endif
 
 	fib6_tables_init();
 
 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
 	if (ret)
-		goto out_kmem_cache_create;
+		goto out_fib6_local_tbl;
 out:
 	return ret;
 
+out_fib6_local_tbl:
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(fib6_local_tbl);
+out_fib6_main_tbl:
+#endif
+	kfree(fib6_main_tbl);
+out_fib_table_hash:
+	kfree(fib_table_hash);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1503,5 +1523,10 @@ out_kmem_cache_create:
 void fib6_gc_cleanup(void)
 {
 	del_timer(&ip6_fib_timer);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(fib6_local_tbl);
+#endif
+	kfree(fib6_main_tbl);
+	kfree(fib_table_hash);
 	kmem_cache_destroy(fib6_node_kmem);
 }

-- 

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

* [patch 02/11][NETNS][IPV6] ip6_fib - make the tables per namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
  2008-01-25 16:50 ` [patch 01/11][NETNS][IPV6] ip6_fib - dynamically allocate the tables Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 03/11][NETNS][IPV6] ip6_fib - make fib6_clean_all " Daniel Lezcano
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-per-network-namespace.patch --]
[-- Type: text/plain, Size: 14465 bytes --]

The fib table for ipv6 are moved to the network namespace structure.
All references to them are made relatively to the network namespace.

All external calls to the ip6_fib functions taking the network namespace 
parameter are made using the init_net variable, so the ip6_fib engine is
ready for the namespaces but the callers not yet.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_fib.h    |    9 +-
 include/net/netns/ipv6.h |    6 +
 net/ipv6/fib6_rules.c    |    8 +-
 net/ipv6/ip6_fib.c       |  161 +++++++++++++++++++++++++++--------------------
 net/ipv6/route.c         |   22 +++---
 5 files changed, 120 insertions(+), 86 deletions(-)

Index: net-2.6.25/include/net/ip6_fib.h
===================================================================
--- net-2.6.25.orig/include/net/ip6_fib.h
+++ net-2.6.25/include/net/ip6_fib.h
@@ -194,10 +194,11 @@ typedef struct rt6_info *(*pol_lookup_t)
  *	exported functions
  */
 
-extern struct fib6_table *	fib6_get_table(u32 id);
-extern struct fib6_table *	fib6_new_table(u32 id);
-extern struct dst_entry *	fib6_rule_lookup(struct flowi *fl, int flags,
-						 pol_lookup_t lookup);
+extern struct fib6_table        *fib6_get_table(struct net *net, u32 id);
+extern struct fib6_table        *fib6_new_table(struct net *net, u32 id);
+extern struct dst_entry         *fib6_rule_lookup(struct net *net,
+						  struct flowi *fl, int flags,
+						  pol_lookup_t lookup);
 
 extern struct fib6_node		*fib6_lookup(struct fib6_node *root,
 					     struct in6_addr *daddr,
Index: net-2.6.25/include/net/netns/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/netns/ipv6.h
+++ net-2.6.25/include/net/netns/ipv6.h
@@ -31,5 +31,11 @@ struct netns_ipv6 {
 	struct ipv6_devconf	*devconf_all;
 	struct ipv6_devconf	*devconf_dflt;
 	struct netns_frags	frags;
+
+	struct hlist_head       *fib_table_hash;
+	struct fib6_table       *fib6_main_tbl;
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	struct fib6_table       *fib6_local_tbl;
+#endif
 };
 #endif
Index: net-2.6.25/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.25.orig/net/ipv6/fib6_rules.c
+++ net-2.6.25/net/ipv6/fib6_rules.c
@@ -31,8 +31,8 @@ struct fib6_rule
 
 static struct fib_rules_ops fib6_rules_ops;
 
-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
-				   pol_lookup_t lookup)
+struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
+				   int flags, pol_lookup_t lookup)
 {
 	struct fib_lookup_arg arg = {
 		.lookup_ptr = lookup,
@@ -71,7 +71,7 @@ static int fib6_rule_action(struct fib_r
 		goto discard_pkt;
 	}
 
-	table = fib6_get_table(rule->table);
+	table = fib6_get_table(&init_net, rule->table);
 	if (table)
 		rt = lookup(table, flp, flags);
 
@@ -151,7 +151,7 @@ static int fib6_rule_configure(struct fi
 		if (rule->table == RT6_TABLE_UNSPEC)
 			goto errout;
 
-		if (fib6_new_table(rule->table) == NULL) {
+		if (fib6_new_table(&init_net, rule->table) == NULL) {
 			err = -ENOBUFS;
 			goto errout;
 		}
Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -166,16 +166,13 @@ static __inline__ void rt6_release(struc
 		dst_free(&rt->u.dst);
 }
 
-static struct fib6_table *fib6_main_tbl;
-
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 #define FIB_TABLE_HASHSZ 256
 #else
 #define FIB_TABLE_HASHSZ 1
 #endif
-static struct hlist_head *fib_table_hash;
 
-static void fib6_link_table(struct fib6_table *tb)
+static void fib6_link_table(struct net *net, struct fib6_table *tb)
 {
 	unsigned int h;
 
@@ -191,13 +188,11 @@ static void fib6_link_table(struct fib6_
 	 * No protection necessary, this is the only list mutatation
 	 * operation, tables never disappear once they exist.
 	 */
-	hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
+	hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]);
 }
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
-static struct fib6_table *fib6_local_tbl;
-
 static struct fib6_table *fib6_alloc_table(u32 id)
 {
 	struct fib6_table *table;
@@ -212,26 +207,27 @@ static struct fib6_table *fib6_alloc_tab
 	return table;
 }
 
-struct fib6_table *fib6_new_table(u32 id)
+struct fib6_table *fib6_new_table(struct net *net, u32 id)
 {
 	struct fib6_table *tb;
 
 	if (id == 0)
 		id = RT6_TABLE_MAIN;
-	tb = fib6_get_table(id);
+	tb = fib6_get_table(net, id);
 	if (tb)
 		return tb;
 
 	tb = fib6_alloc_table(id);
 	if (tb != NULL)
-		fib6_link_table(tb);
+		fib6_link_table(net, tb);
 
 	return tb;
 }
 
-struct fib6_table *fib6_get_table(u32 id)
+struct fib6_table *fib6_get_table(struct net *net, u32 id)
 {
 	struct fib6_table *tb;
+	struct hlist_head *head;
 	struct hlist_node *node;
 	unsigned int h;
 
@@ -239,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id
 		id = RT6_TABLE_MAIN;
 	h = id & (FIB_TABLE_HASHSZ - 1);
 	rcu_read_lock();
-	hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
+	head = &net->ipv6.fib_table_hash[h];
+	hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
 		if (tb->tb6_id == id) {
 			rcu_read_unlock();
 			return tb;
@@ -250,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id
 	return NULL;
 }
 
-static void __init fib6_tables_init(void)
+static void fib6_tables_init(struct net *net)
 {
-	fib6_link_table(fib6_main_tbl);
-	fib6_link_table(fib6_local_tbl);
+	fib6_link_table(net, net->ipv6.fib6_main_tbl);
+	fib6_link_table(net, net->ipv6.fib6_local_tbl);
 }
-
 #else
 
-struct fib6_table *fib6_new_table(u32 id)
+struct fib6_table *fib6_new_table(struct net *net, u32 id)
 {
-	return fib6_get_table(id);
+	return fib6_get_table(net, id);
 }
 
-struct fib6_table *fib6_get_table(u32 id)
+struct fib6_table *fib6_get_table(struct net *net, u32 id)
 {
-	return fib6_main_tbl;
+	  return net->ipv6.fib6_main_tbl;
 }
 
-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
-				   pol_lookup_t lookup)
+struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
+				   int flags, pol_lookup_t lookup)
 {
-	return (struct dst_entry *) lookup(fib6_main_tbl, fl, flags);
+	return (struct dst_entry *) lookup(net->ipv6.fib6_main_tbl, fl, flags);
 }
 
-static void __init fib6_tables_init(void)
+static void fib6_tables_init(struct net *net)
 {
-	fib6_link_table(fib6_main_tbl);
+	fib6_link_table(net, net->ipv6.fib6_main_tbl);
 }
 
 #endif
@@ -357,11 +353,9 @@ static int inet6_dump_fib(struct sk_buff
 	struct fib6_walker_t *w;
 	struct fib6_table *tb;
 	struct hlist_node *node;
+	struct hlist_head *head;
 	int res = 0;
 
-	if (net != &init_net)
-		return 0;
-
 	s_h = cb->args[0];
 	s_e = cb->args[1];
 
@@ -390,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff
 
 	for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
 		e = 0;
-		hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) {
+		head = &net->ipv6.fib_table_hash[h];
+		hlist_for_each_entry(tb, node, head, tb6_hlist) {
 			if (e < s_e)
 				goto next;
 			res = fib6_dump_table(tb, skb, cb);
@@ -1360,12 +1355,13 @@ void fib6_clean_all(int (*func)(struct r
 {
 	struct fib6_table *table;
 	struct hlist_node *node;
+	struct hlist_head *head;
 	unsigned int h;
 
 	rcu_read_lock();
 	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
-		hlist_for_each_entry_rcu(table, node, &fib_table_hash[h],
-					 tb6_hlist) {
+		head = &init_net.ipv6.fib_table_hash[h];
+		hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
 			write_lock_bh(&table->tb6_lock);
 			fib6_clean_tree(&table->tb6_root, func, prune, arg);
 			write_unlock_bh(&table->tb6_lock);
@@ -1466,55 +1462,88 @@ void fib6_run_gc(unsigned long dummy)
 	spin_unlock_bh(&fib6_gc_lock);
 }
 
-int __init fib6_init(void)
+static int fib6_net_init(struct net *net)
 {
-	int ret = -ENOMEM;
-	fib6_node_kmem = kmem_cache_create("fib6_nodes",
-					   sizeof(struct fib6_node),
-					   0, SLAB_HWCACHE_ALIGN,
-					   NULL);
-	if (!fib6_node_kmem)
-		goto out;
+	int ret;
 
-	fib_table_hash = kzalloc(sizeof(*fib_table_hash)*FIB_TABLE_HASHSZ,
-				 GFP_KERNEL);
-	if (!fib_table_hash)
-		goto out_kmem_cache_create;
+	ret = -ENOMEM;
+	net->ipv6.fib_table_hash =
+		kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
+			GFP_KERNEL);
+	if (!net->ipv6.fib_table_hash)
+		goto out;
 
-	fib6_main_tbl = kzalloc(sizeof(*fib6_main_tbl), GFP_KERNEL);
-	if (!fib6_main_tbl)
+	net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
+					  GFP_KERNEL);
+	if (!net->ipv6.fib6_main_tbl)
 		goto out_fib_table_hash;
 
-	fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
-	fib6_main_tbl->tb6_root.leaf = &ip6_null_entry;
-	fib6_main_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+	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.fn_flags =
+		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	fib6_local_tbl = kzalloc(sizeof(*fib6_local_tbl), GFP_KERNEL);
-	if (!fib6_local_tbl)
+	net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl),
+					   GFP_KERNEL);
+	if (!net->ipv6.fib6_local_tbl)
 		goto out_fib6_main_tbl;
-
-	fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
-	fib6_local_tbl->tb6_root.leaf = &ip6_null_entry;
-	fib6_local_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+	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.fn_flags =
+		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
 #endif
+	fib6_tables_init(net);
 
-	fib6_tables_init();
-
-	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
-	if (ret)
-		goto out_fib6_local_tbl;
+	ret = 0;
 out:
 	return ret;
 
-out_fib6_local_tbl:
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	kfree(fib6_local_tbl);
 out_fib6_main_tbl:
+	kfree(net->ipv6.fib6_main_tbl);
 #endif
-	kfree(fib6_main_tbl);
 out_fib_table_hash:
-	kfree(fib_table_hash);
+	kfree(net->ipv6.fib_table_hash);
+	goto out;
+ }
+
+static void fib6_net_exit(struct net *net)
+{
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	kfree(net->ipv6.fib6_local_tbl);
+#endif
+	kfree(net->ipv6.fib6_main_tbl);
+	kfree(net->ipv6.fib_table_hash);
+}
+
+static struct pernet_operations fib6_net_ops = {
+	.init = fib6_net_init,
+	.exit = fib6_net_exit,
+};
+
+int __init fib6_init(void)
+{
+	int ret = -ENOMEM;
+	fib6_node_kmem = kmem_cache_create("fib6_nodes",
+					   sizeof(struct fib6_node),
+					   0, SLAB_HWCACHE_ALIGN,
+					   NULL);
+	if (!fib6_node_kmem)
+		goto out;
+
+	ret = register_pernet_subsys(&fib6_net_ops);
+	if (ret)
+		goto out_kmem_cache_create;
+
+	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+	if (ret)
+		goto out_unregister_subsys;
+out:
+	return ret;
+
+out_unregister_subsys:
+	unregister_pernet_subsys(&fib6_net_ops);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1523,10 +1552,6 @@ out_kmem_cache_create:
 void fib6_gc_cleanup(void)
 {
 	del_timer(&ip6_fib_timer);
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	kfree(fib6_local_tbl);
-#endif
-	kfree(fib6_main_tbl);
-	kfree(fib_table_hash);
+	unregister_pernet_subsys(&fib6_net_ops);
 	kmem_cache_destroy(fib6_node_kmem);
 }
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -569,7 +569,7 @@ struct rt6_info *rt6_lookup(struct in6_a
 		flags |= RT6_LOOKUP_F_HAS_SADDR;
 	}
 
-	dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
+	dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_lookup);
 	if (dst->error == 0)
 		return (struct rt6_info *) dst;
 
@@ -756,7 +756,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(&fl, flags, ip6_pol_route_input);
+	skb->dst = fib6_rule_lookup(&init_net, &fl, flags, ip6_pol_route_input);
 }
 
 static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
@@ -775,7 +775,7 @@ struct dst_entry * ip6_route_output(stru
 	if (!ipv6_addr_any(&fl->fl6_src))
 		flags |= RT6_LOOKUP_F_HAS_SADDR;
 
-	return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
+	return fib6_rule_lookup(&init_net, fl, flags, ip6_pol_route_output);
 }
 
 EXPORT_SYMBOL(ip6_route_output);
@@ -1068,7 +1068,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(cfg->fc_table);
+	table = fib6_new_table(&init_net, cfg->fc_table);
 	if (table == NULL) {
 		err = -ENOBUFS;
 		goto out;
@@ -1274,7 +1274,7 @@ static int ip6_route_del(struct fib6_con
 	struct rt6_info *rt;
 	int err = -ESRCH;
 
-	table = fib6_get_table(cfg->fc_table);
+	table = fib6_get_table(&init_net, cfg->fc_table);
 	if (table == NULL)
 		return err;
 
@@ -1389,7 +1389,9 @@ static struct rt6_info *ip6_route_redire
 	if (rt6_need_strict(dest))
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
+	return (struct rt6_info *)fib6_rule_lookup(&init_net,
+						   (struct flowi *)&rdfl,
+						   flags, __ip6_route_redirect);
 }
 
 void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
@@ -1588,7 +1590,7 @@ static struct rt6_info *rt6_get_route_in
 	struct rt6_info *rt = NULL;
 	struct fib6_table *table;
 
-	table = fib6_get_table(RT6_TABLE_INFO);
+	table = fib6_get_table(&init_net, RT6_TABLE_INFO);
 	if (table == NULL)
 		return NULL;
 
@@ -1643,7 +1645,7 @@ struct rt6_info *rt6_get_dflt_router(str
 	struct rt6_info *rt;
 	struct fib6_table *table;
 
-	table = fib6_get_table(RT6_TABLE_DFLT);
+	table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
 	if (table == NULL)
 		return NULL;
 
@@ -1687,7 +1689,7 @@ void rt6_purge_dflt_routers(void)
 	struct fib6_table *table;
 
 	/* NOTE: Keep consistent with rt6_get_dflt_router */
-	table = fib6_get_table(RT6_TABLE_DFLT);
+	table = fib6_get_table(&init_net, RT6_TABLE_DFLT);
 	if (table == NULL)
 		return;
 
@@ -1848,7 +1850,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(RT6_TABLE_LOCAL);
+	rt->rt6i_table = fib6_get_table(&init_net, RT6_TABLE_LOCAL);
 
 	atomic_set(&rt->u.dst.__refcnt, 1);
 

-- 

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

* [patch 03/11][NETNS][IPV6] ip6_fib - make fib6_clean_all per namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
  2008-01-25 16:50 ` [patch 01/11][NETNS][IPV6] ip6_fib - dynamically allocate the tables Daniel Lezcano
  2008-01-25 16:50 ` [patch 02/11][NETNS][IPV6] ip6_fib - make the tables per namespace Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 04/11][NETNS][IPV6] ip6_fib - pass the network namespace parameter to timer callback Daniel Lezcano
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-make-fib6_clean_all-per-namespace.patch --]
[-- Type: text/plain, Size: 5624 bytes --]

The function fib6_clean_all takes the network namespace
as parameter. That allows to flush the routes related to 
a specific 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/ip6_route.h |    2 +-
 net/ipv6/addrconf.c     |    3 ++-
 net/ipv6/ip6_fib.c      |    7 ++++---
 net/ipv6/route.c        |   28 ++++++++++++++++++++--------
 5 files changed, 29 insertions(+), 14 deletions(-)

Index: net-2.6.25/include/net/ip6_fib.h
===================================================================
--- net-2.6.25.orig/include/net/ip6_fib.h
+++ net-2.6.25/include/net/ip6_fib.h
@@ -208,7 +208,8 @@ struct fib6_node		*fib6_locate(struct fi
 					     struct in6_addr *daddr, int dst_len,
 					     struct in6_addr *saddr, int src_len);
 
-extern void			fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
+extern void			fib6_clean_all(struct net *net,
+					       int (*func)(struct rt6_info *, void *arg),
 					       int prune, void *arg);
 
 extern int			fib6_add(struct fib6_node *root,
Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -1350,7 +1350,7 @@ static void fib6_clean_tree(struct fib6_
 	fib6_walk(&c.w);
 }
 
-void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
+void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
 		    int prune, void *arg)
 {
 	struct fib6_table *table;
@@ -1360,7 +1360,7 @@ void fib6_clean_all(int (*func)(struct r
 
 	rcu_read_lock();
 	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
-		head = &init_net.ipv6.fib_table_hash[h];
+		head = &net->ipv6.fib_table_hash[h];
 		hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
 			write_lock_bh(&table->tb6_lock);
 			fib6_clean_tree(&table->tb6_root, func, prune, arg);
@@ -1450,7 +1450,8 @@ void fib6_run_gc(unsigned long dummy)
 	gc_args.more = 0;
 
 	ndisc_dst_gc(&gc_args.more);
-	fib6_clean_all(fib6_age, 0, NULL);
+
+	fib6_clean_all(&init_net, fib6_age, 0, NULL);
 
 	if (gc_args.more)
 		mod_timer(&ip6_fib_timer, jiffies +
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -1867,9 +1867,9 @@ static int fib6_ifdown(struct rt6_info *
 	return 0;
 }
 
-void rt6_ifdown(struct net_device *dev)
+void rt6_ifdown(struct net *net, struct net_device *dev)
 {
-	fib6_clean_all(fib6_ifdown, 0, dev);
+	fib6_clean_all(net, fib6_ifdown, 0, dev);
 }
 
 struct rt6_mtu_change_arg
@@ -1925,7 +1925,7 @@ void rt6_mtu_change(struct net_device *d
 		.mtu = mtu,
 	};
 
-	fib6_clean_all(rt6_mtu_change_route, 0, &arg);
+	fib6_clean_all(dev->nd_net, rt6_mtu_change_route, 0, &arg);
 }
 
 static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
@@ -2313,13 +2313,25 @@ static int rt6_info_route(struct rt6_inf
 
 static int ipv6_route_show(struct seq_file *m, void *v)
 {
-	fib6_clean_all(rt6_info_route, 0, m);
+	struct net *net = (struct net *)m->private;
+	fib6_clean_all(net, rt6_info_route, 0, m);
 	return 0;
 }
 
 static int ipv6_route_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ipv6_route_show, NULL);
+	struct net *net = get_proc_net(inode);
+	if (!net)
+		return -ENXIO;
+	return single_open(file, ipv6_route_show, net);
+}
+
+static int ipv6_route_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct net *net = seq->private;
+	put_net(net);
+	return single_release(inode, file);
 }
 
 static const struct file_operations ipv6_route_proc_fops = {
@@ -2327,7 +2339,7 @@ static const struct file_operations ipv6
 	.open		= ipv6_route_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= ipv6_route_release,
 };
 
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
@@ -2551,7 +2563,7 @@ xfrm6_init:
 out_proc_init:
 	ipv6_route_proc_fini(&init_net);
 out_fib6_init:
-	rt6_ifdown(NULL);
+	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();
 out_kmem_cache:
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
@@ -2563,7 +2575,7 @@ void ip6_route_cleanup(void)
 	fib6_rules_cleanup();
 	ipv6_route_proc_fini(&init_net);
 	xfrm6_fini();
-	rt6_ifdown(NULL);
+	rt6_ifdown(&init_net, NULL);
 	fib6_gc_cleanup();
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
 }
Index: net-2.6.25/include/net/ip6_route.h
===================================================================
--- net-2.6.25.orig/include/net/ip6_route.h
+++ net-2.6.25/include/net/ip6_route.h
@@ -123,7 +123,7 @@ struct rt6_rtnl_dump_arg
 };
 
 extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
-extern void rt6_ifdown(struct net_device *dev);
+extern void rt6_ifdown(struct net *net, struct net_device *dev);
 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
 
 extern rwlock_t rt6_lock;
Index: net-2.6.25/net/ipv6/addrconf.c
===================================================================
--- net-2.6.25.orig/net/ipv6/addrconf.c
+++ net-2.6.25/net/ipv6/addrconf.c
@@ -2430,6 +2430,7 @@ static int addrconf_ifdown(struct net_de
 {
 	struct inet6_dev *idev;
 	struct inet6_ifaddr *ifa, **bifa;
+	struct net *net = dev->nd_net;
 	int i;
 
 	ASSERT_RTNL();
@@ -2437,7 +2438,7 @@ static int addrconf_ifdown(struct net_de
 	if (dev == init_net.loopback_dev && how == 1)
 		how = 0;
 
-	rt6_ifdown(dev);
+	rt6_ifdown(net, dev);
 	neigh_ifdown(&nd_tbl, dev);
 
 	idev = __in6_dev_get(dev);

-- 

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

* [patch 04/11][NETNS][IPV6] ip6_fib - pass the network namespace parameter to timer callback
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (2 preceding siblings ...)
  2008-01-25 16:50 ` [patch 03/11][NETNS][IPV6] ip6_fib - make fib6_clean_all " Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 05/11][NETNS][IPV6] ip6_fib - dynamically allocate the gc_timer Daniel Lezcano
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-add-net-to-gc-timer-parameter.patch --]
[-- Type: text/plain, Size: 5694 bytes --]

The fib tables are now relative to the network namespace. When the 
garbage collector timer expires, we must have a network namespace 
parameter in order to retrieve the tables. For now this is the 
init_net, but we should be able to have a timer per namespace and 
use the timer callback parameter to pass the network namespace from 
the expired timer.

The timer callback, fib6_run_gc, is actually used to be called 
synchronously by some functions and asynchronously when the timer 
expires.

When the timer expires, the delay specified for fib6_run_gc parameter
is always zero. So, I changed fib6_run_gc to not be a timer callback
but a function called by the timer callback and I added a timer callback
where its work is just to retrieve from the data arg of the timer the 
network namespace and call fib6_run_gc with zero expiring time and
the network namespace parameters. That makes the code cleaner for the
fib6_run_gc callers.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
 include/net/ip6_fib.h |    3 ++-
 net/ipv6/ip6_fib.c    |   24 ++++++++++++++++--------
 net/ipv6/ndisc.c      |    5 +++--
 net/ipv6/route.c      |    8 +++++---
 4 files changed, 26 insertions(+), 14 deletions(-)

Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -93,7 +93,10 @@ static int fib6_walk_continue(struct fib
 
 static __u32 rt_sernum;
 
-static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
+static void fib6_gc_timer_cb(unsigned long arg);
+
+static DEFINE_TIMER(ip6_fib_timer, fib6_gc_timer_cb, 0,
+		    (unsigned long)&init_net);
 
 static struct fib6_walker_t fib6_walker_list = {
 	.prev	= &fib6_walker_list,
@@ -1432,12 +1435,12 @@ static int fib6_age(struct rt6_info *rt,
 
 static DEFINE_SPINLOCK(fib6_gc_lock);
 
-void fib6_run_gc(unsigned long dummy)
+void fib6_run_gc(unsigned long expires, struct net *net)
 {
-	if (dummy != ~0UL) {
+	if (expires != ~0UL) {
 		spin_lock_bh(&fib6_gc_lock);
-		gc_args.timeout = dummy ? (int)dummy :
-			init_net.ipv6.sysctl.ip6_rt_gc_interval;
+		gc_args.timeout = expires ? (int)expires :
+			net->ipv6.sysctl.ip6_rt_gc_interval;
 	} else {
 		local_bh_disable();
 		if (!spin_trylock(&fib6_gc_lock)) {
@@ -1445,17 +1448,17 @@ void fib6_run_gc(unsigned long dummy)
 			local_bh_enable();
 			return;
 		}
-		gc_args.timeout = init_net.ipv6.sysctl.ip6_rt_gc_interval;
+		gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
 	}
 	gc_args.more = 0;
 
 	ndisc_dst_gc(&gc_args.more);
 
-	fib6_clean_all(&init_net, fib6_age, 0, NULL);
+	fib6_clean_all(net, fib6_age, 0, NULL);
 
 	if (gc_args.more)
 		mod_timer(&ip6_fib_timer, jiffies +
-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
+			  net->ipv6.sysctl.ip6_rt_gc_interval);
 	else {
 		del_timer(&ip6_fib_timer);
 		ip6_fib_timer.expires = 0;
@@ -1463,6 +1466,11 @@ void fib6_run_gc(unsigned long dummy)
 	spin_unlock_bh(&fib6_gc_lock);
 }
 
+static void fib6_gc_timer_cb(unsigned long arg)
+{
+	fib6_run_gc(0, (struct net *)arg);
+}
+
 static int fib6_net_init(struct net *net)
 {
 	int ret;
Index: net-2.6.25/include/net/ip6_fib.h
===================================================================
--- net-2.6.25.orig/include/net/ip6_fib.h
+++ net-2.6.25/include/net/ip6_fib.h
@@ -222,7 +222,8 @@ extern int			fib6_del(struct rt6_info *r
 extern void			inet6_rt_notify(int event, struct rt6_info *rt,
 						struct nl_info *info);
 
-extern void			fib6_run_gc(unsigned long dummy);
+extern void			fib6_run_gc(unsigned long expires,
+					    struct net *net);
 
 extern void			fib6_gc_cleanup(void);
 
Index: net-2.6.25/net/ipv6/ndisc.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ndisc.c
+++ net-2.6.25/net/ipv6/ndisc.c
@@ -1613,6 +1613,7 @@ int ndisc_rcv(struct sk_buff *skb)
 static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
 	struct net_device *dev = ptr;
+	struct net *net = dev->nd_net;
 
 	if (dev->nd_net != &init_net)
 		return NOTIFY_DONE;
@@ -1620,11 +1621,11 @@ static int ndisc_netdev_event(struct not
 	switch (event) {
 	case NETDEV_CHANGEADDR:
 		neigh_changeaddr(&nd_tbl, dev);
-		fib6_run_gc(~0UL);
+		fib6_run_gc(~0UL, net);
 		break;
 	case NETDEV_DOWN:
 		neigh_ifdown(&nd_tbl, dev);
-		fib6_run_gc(~0UL);
+		fib6_run_gc(~0UL, net);
 		break;
 	default:
 		break;
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -40,6 +40,7 @@
 #include <linux/if_arp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/nsproxy.h>
 #include <net/net_namespace.h>
 #include <net/snmp.h>
 #include <net/ipv6.h>
@@ -994,7 +995,7 @@ static int ip6_dst_gc(struct dst_ops *op
 		goto out;
 
 	expire++;
-	fib6_run_gc(expire);
+	fib6_run_gc(expire, &init_net);
 	last_gc = now;
 	if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh)
 		expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
@@ -2408,10 +2409,11 @@ static
 int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
 			      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-	int delay = init_net.ipv6.sysctl.flush_delay;
+	struct net *net = current->nsproxy->net_ns;
+	int delay = net->ipv6.sysctl.flush_delay;
 	if (write) {
 		proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
-		fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay);
+		fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
 		return 0;
 	} else
 		return -EINVAL;

-- 

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

* [patch 05/11][NETNS][IPV6] ip6_fib - dynamically allocate the gc_timer
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (3 preceding siblings ...)
  2008-01-25 16:50 ` [patch 04/11][NETNS][IPV6] ip6_fib - pass the network namespace parameter to timer callback Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 06/11][NETNS][IPV6] ip6_fib - make the ip6 fib gc timer per network namespace Daniel Lezcano
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-dynamically-allocate-gc-timer.patch --]
[-- Type: text/plain, Size: 3216 bytes --]

The ip6_fib_timer gc timer is dynamically allocated and initialized in
the ip6 fib init function. There are no more references to a
static global variable. That will allow to make multiple instance
of the garbage collecting timer and make them per namespace.

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

Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -95,8 +95,7 @@ static __u32 rt_sernum;
 
 static void fib6_gc_timer_cb(unsigned long arg);
 
-static DEFINE_TIMER(ip6_fib_timer, fib6_gc_timer_cb, 0,
-		    (unsigned long)&init_net);
+static struct timer_list *ip6_fib_timer;
 
 static struct fib6_walker_t fib6_walker_list = {
 	.prev	= &fib6_walker_list,
@@ -666,16 +665,16 @@ static int fib6_add_rt2node(struct fib6_
 
 static __inline__ void fib6_start_gc(struct rt6_info *rt)
 {
-	if (ip6_fib_timer.expires == 0 &&
+	if (ip6_fib_timer->expires == 0 &&
 	    (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
-		mod_timer(&ip6_fib_timer, jiffies +
+		mod_timer(ip6_fib_timer, jiffies +
 			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
 }
 
 void fib6_force_start_gc(void)
 {
-	if (ip6_fib_timer.expires == 0)
-		mod_timer(&ip6_fib_timer, jiffies +
+	if (ip6_fib_timer->expires == 0)
+		mod_timer(ip6_fib_timer, jiffies +
 			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
 }
 
@@ -1444,7 +1443,7 @@ void fib6_run_gc(unsigned long expires, 
 	} else {
 		local_bh_disable();
 		if (!spin_trylock(&fib6_gc_lock)) {
-			mod_timer(&ip6_fib_timer, jiffies + HZ);
+			mod_timer(ip6_fib_timer, jiffies + HZ);
 			local_bh_enable();
 			return;
 		}
@@ -1457,11 +1456,11 @@ void fib6_run_gc(unsigned long expires, 
 	fib6_clean_all(net, fib6_age, 0, NULL);
 
 	if (gc_args.more)
-		mod_timer(&ip6_fib_timer, jiffies +
+		mod_timer(ip6_fib_timer, jiffies +
 			  net->ipv6.sysctl.ip6_rt_gc_interval);
 	else {
-		del_timer(&ip6_fib_timer);
-		ip6_fib_timer.expires = 0;
+		del_timer(ip6_fib_timer);
+		ip6_fib_timer->expires = 0;
 	}
 	spin_unlock_bh(&fib6_gc_lock);
 }
@@ -1541,9 +1540,16 @@ int __init fib6_init(void)
 	if (!fib6_node_kmem)
 		goto out;
 
+	ret = -ENOMEM;
+	ip6_fib_timer = kzalloc(sizeof(*ip6_fib_timer), GFP_KERNEL);
+	if (!ip6_fib_timer)
+		goto out_kmem_cache_create;
+
+	setup_timer(ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)&init_net);
+
 	ret = register_pernet_subsys(&fib6_net_ops);
 	if (ret)
-		goto out_kmem_cache_create;
+		goto out_timer;
 
 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
 	if (ret)
@@ -1553,6 +1559,8 @@ out:
 
 out_unregister_subsys:
 	unregister_pernet_subsys(&fib6_net_ops);
+out_timer:
+	kfree(ip6_fib_timer);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1560,7 +1568,8 @@ out_kmem_cache_create:
 
 void fib6_gc_cleanup(void)
 {
-	del_timer(&ip6_fib_timer);
+	del_timer(ip6_fib_timer);
+	kfree(ip6_fib_timer);
 	unregister_pernet_subsys(&fib6_net_ops);
 	kmem_cache_destroy(fib6_node_kmem);
 }

-- 

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

* [patch 06/11][NETNS][IPV6] ip6_fib - make the ip6 fib gc timer per network namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (4 preceding siblings ...)
  2008-01-25 16:50 ` [patch 05/11][NETNS][IPV6] ip6_fib - dynamically allocate the gc_timer Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 07/11][NETNS][IPV6] make fib6_clean_node to use the " Daniel Lezcano
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-gc-timer-per-namespace.patch --]
[-- Type: text/plain, Size: 6564 bytes --]

Move the timer initialization at the network namespace creation
and store the network namespace in the timer argument.

That enables multiple timers (one per network namespace) to do garbage
collecting.

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

Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -95,8 +95,6 @@ static __u32 rt_sernum;
 
 static void fib6_gc_timer_cb(unsigned long arg);
 
-static struct timer_list *ip6_fib_timer;
-
 static struct fib6_walker_t fib6_walker_list = {
 	.prev	= &fib6_walker_list,
 	.next	= &fib6_walker_list,
@@ -663,19 +661,19 @@ static int fib6_add_rt2node(struct fib6_
 	return 0;
 }
 
-static __inline__ void fib6_start_gc(struct rt6_info *rt)
+static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
 {
-	if (ip6_fib_timer->expires == 0 &&
+	if (net->ipv6.ip6_fib_timer->expires == 0 &&
 	    (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
-		mod_timer(ip6_fib_timer, jiffies +
-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
+		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
+			  net->ipv6.sysctl.ip6_rt_gc_interval);
 }
 
-void fib6_force_start_gc(void)
+void fib6_force_start_gc(struct net *net)
 {
-	if (ip6_fib_timer->expires == 0)
-		mod_timer(ip6_fib_timer, jiffies +
-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
+	if (net->ipv6.ip6_fib_timer->expires == 0)
+		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
+			  net->ipv6.sysctl.ip6_rt_gc_interval);
 }
 
 /*
@@ -762,7 +760,7 @@ int fib6_add(struct fib6_node *root, str
 	err = fib6_add_rt2node(fn, rt, info);
 
 	if (err == 0) {
-		fib6_start_gc(rt);
+		fib6_start_gc(info->nl_net, rt);
 		if (!(rt->rt6i_flags&RTF_CACHE))
 			fib6_prune_clones(pn, rt);
 	}
@@ -1443,7 +1441,7 @@ void fib6_run_gc(unsigned long expires, 
 	} else {
 		local_bh_disable();
 		if (!spin_trylock(&fib6_gc_lock)) {
-			mod_timer(ip6_fib_timer, jiffies + HZ);
+			mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
 			local_bh_enable();
 			return;
 		}
@@ -1456,11 +1454,11 @@ void fib6_run_gc(unsigned long expires, 
 	fib6_clean_all(net, fib6_age, 0, NULL);
 
 	if (gc_args.more)
-		mod_timer(ip6_fib_timer, jiffies +
+		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
 			  net->ipv6.sysctl.ip6_rt_gc_interval);
 	else {
-		del_timer(ip6_fib_timer);
-		ip6_fib_timer->expires = 0;
+		del_timer(net->ipv6.ip6_fib_timer);
+		net->ipv6.ip6_fib_timer->expires = 0;
 	}
 	spin_unlock_bh(&fib6_gc_lock);
 }
@@ -1473,13 +1471,21 @@ static void fib6_gc_timer_cb(unsigned lo
 static int fib6_net_init(struct net *net)
 {
 	int ret;
+	struct timer_list *timer;
 
 	ret = -ENOMEM;
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		goto out;
+
+	setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
+	net->ipv6.ip6_fib_timer = timer;
+
 	net->ipv6.fib_table_hash =
 		kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
 			GFP_KERNEL);
 	if (!net->ipv6.fib_table_hash)
-		goto out;
+		goto out_timer;
 
 	net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
 					  GFP_KERNEL);
@@ -1513,11 +1519,15 @@ out_fib6_main_tbl:
 #endif
 out_fib_table_hash:
 	kfree(net->ipv6.fib_table_hash);
+out_timer:
+	kfree(timer);
 	goto out;
  }
 
 static void fib6_net_exit(struct net *net)
 {
+	del_timer(net->ipv6.ip6_fib_timer);
+	kfree(net->ipv6.ip6_fib_timer);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	kfree(net->ipv6.fib6_local_tbl);
 #endif
@@ -1533,6 +1543,7 @@ static struct pernet_operations fib6_net
 int __init fib6_init(void)
 {
 	int ret = -ENOMEM;
+
 	fib6_node_kmem = kmem_cache_create("fib6_nodes",
 					   sizeof(struct fib6_node),
 					   0, SLAB_HWCACHE_ALIGN,
@@ -1540,16 +1551,9 @@ int __init fib6_init(void)
 	if (!fib6_node_kmem)
 		goto out;
 
-	ret = -ENOMEM;
-	ip6_fib_timer = kzalloc(sizeof(*ip6_fib_timer), GFP_KERNEL);
-	if (!ip6_fib_timer)
-		goto out_kmem_cache_create;
-
-	setup_timer(ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)&init_net);
-
 	ret = register_pernet_subsys(&fib6_net_ops);
 	if (ret)
-		goto out_timer;
+		goto out_kmem_cache_create;
 
 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
 	if (ret)
@@ -1559,8 +1563,6 @@ out:
 
 out_unregister_subsys:
 	unregister_pernet_subsys(&fib6_net_ops);
-out_timer:
-	kfree(ip6_fib_timer);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1568,8 +1570,6 @@ out_kmem_cache_create:
 
 void fib6_gc_cleanup(void)
 {
-	del_timer(ip6_fib_timer);
-	kfree(ip6_fib_timer);
 	unregister_pernet_subsys(&fib6_net_ops);
 	kmem_cache_destroy(fib6_node_kmem);
 }
Index: net-2.6.25/include/net/netns/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/netns/ipv6.h
+++ net-2.6.25/include/net/netns/ipv6.h
@@ -32,6 +32,7 @@ struct netns_ipv6 {
 	struct ipv6_devconf	*devconf_dflt;
 	struct netns_frags	frags;
 
+	struct timer_list       *ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
Index: net-2.6.25/include/net/ip6_route.h
===================================================================
--- net-2.6.25.orig/include/net/ip6_route.h
+++ net-2.6.25/include/net/ip6_route.h
@@ -80,7 +80,7 @@ extern struct dst_entry *ndisc_dst_alloc
 					 struct in6_addr *addr,
 					 int (*output)(struct sk_buff *));
 extern int ndisc_dst_gc(int *more);
-extern void fib6_force_start_gc(void);
+extern void fib6_force_start_gc(struct net *net);
 
 extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 					   const struct in6_addr *addr,
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -951,7 +951,7 @@ struct dst_entry *ndisc_dst_alloc(struct
 	ndisc_dst_gc_list = &rt->u.dst;
 	spin_unlock_bh(&ndisc_lock);
 
-	fib6_force_start_gc();
+	fib6_force_start_gc(dev->nd_net);
 
 out:
 	return &rt->u.dst;
@@ -1229,6 +1229,9 @@ install_route:
 	rt->u.dst.dev = dev;
 	rt->rt6i_idev = idev;
 	rt->rt6i_table = table;
+
+	cfg->fc_nlinfo.nl_net = dev->nd_net;
+
 	return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
 
 out:

-- 

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

* [patch 07/11][NETNS][IPV6] make fib6_clean_node to use the network namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (5 preceding siblings ...)
  2008-01-25 16:50 ` [patch 06/11][NETNS][IPV6] ip6_fib - make the ip6 fib gc timer per network namespace Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 08/11][NETNS][IPV6] fib6_rules - dynamically allocate the fib rules ops Daniel Lezcano
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: ip6-fib-clean-node-use-namespace.patch --]
[-- Type: text/plain, Size: 3376 bytes --]

The fib6_clean_node function should have the network namespace
it is working on. The fib6_cleaner_t structure is extended with the
network namespace field to be passed to the fib6_clean_node function.

The different functions calling the fib6_clean_node function are extended
with the netns parameter when needed to propagate the netns pointer.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 net/ipv6/ip6_fib.c |   25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -66,6 +66,7 @@ enum fib_walk_state_t
 struct fib6_cleaner_t
 {
 	struct fib6_walker_t w;
+	struct net *net;
 	int (*func)(struct rt6_info *, void *arg);
 	void *arg;
 };
@@ -78,7 +79,8 @@ static DEFINE_RWLOCK(fib6_walker_lock);
 #define FWS_INIT FWS_L
 #endif
 
-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
+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 int fib6_walk(struct fib6_walker_t *w);
@@ -762,7 +764,7 @@ int fib6_add(struct fib6_node *root, str
 	if (err == 0) {
 		fib6_start_gc(info->nl_net, rt);
 		if (!(rt->rt6i_flags&RTF_CACHE))
-			fib6_prune_clones(pn, rt);
+			fib6_prune_clones(info->nl_net, pn, rt);
 	}
 
 out:
@@ -1168,7 +1170,7 @@ int fib6_del(struct rt6_info *rt, struct
 			pn = pn->parent;
 		}
 #endif
-		fib6_prune_clones(pn, rt);
+		fib6_prune_clones(info->nl_net, pn, rt);
 	}
 
 	/*
@@ -1298,12 +1300,12 @@ static int fib6_walk(struct fib6_walker_
 
 static int fib6_clean_node(struct fib6_walker_t *w)
 {
-	struct nl_info info = {
-		.nl_net = &init_net,
-	};
 	int res;
 	struct rt6_info *rt;
 	struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w);
+	struct nl_info info = {
+		.nl_net = c->net,
+	};
 
 	for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
 		res = c->func(rt, c->arg);
@@ -1335,7 +1337,7 @@ static int fib6_clean_node(struct fib6_w
  *	ignoring pure split nodes) will be scanned.
  */
 
-static void fib6_clean_tree(struct fib6_node *root,
+static void fib6_clean_tree(struct net *net, struct fib6_node *root,
 			    int (*func)(struct rt6_info *, void *arg),
 			    int prune, void *arg)
 {
@@ -1346,6 +1348,7 @@ static void fib6_clean_tree(struct fib6_
 	c.w.prune = prune;
 	c.func = func;
 	c.arg = arg;
+	c.net = net;
 
 	fib6_walk(&c.w);
 }
@@ -1363,7 +1366,8 @@ void fib6_clean_all(struct net *net, int
 		head = &net->ipv6.fib_table_hash[h];
 		hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
 			write_lock_bh(&table->tb6_lock);
-			fib6_clean_tree(&table->tb6_root, func, prune, arg);
+			fib6_clean_tree(net, &table->tb6_root,
+					func, prune, arg);
 			write_unlock_bh(&table->tb6_lock);
 		}
 	}
@@ -1380,9 +1384,10 @@ static int fib6_prune_clone(struct rt6_i
 	return 0;
 }
 
-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt)
+static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
+			      struct rt6_info *rt)
 {
-	fib6_clean_tree(fn, fib6_prune_clone, 1, rt);
+	fib6_clean_tree(net, fn, fib6_prune_clone, 1, rt);
 }
 
 /*

-- 

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

* [patch 08/11][NETNS][IPV6] fib6_rules - dynamically allocate the fib rules ops
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (6 preceding siblings ...)
  2008-01-25 16:50 ` [patch 07/11][NETNS][IPV6] make fib6_clean_node to use the " Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 09/11][NETNS][IPV6] fib6_rules: make per network namespace Daniel Lezcano
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: fib6-rules-dynamic-allocation.patch --]
[-- Type: text/plain, Size: 2897 bytes --]

The fib6_rules_ops structure is dynamically allocated, so that allows
to make several instances of it per network namespace.

The global static fib6_rules_ops structure is renamed to 
fib6_rules_ops_template in order to quickly memcopy it for the
structure initialization.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 net/ipv6/fib6_rules.c |   26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

Index: net-2.6.25/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.25.orig/net/ipv6/fib6_rules.c
+++ net-2.6.25/net/ipv6/fib6_rules.c
@@ -29,7 +29,7 @@ struct fib6_rule
 	u8			tclass;
 };
 
-static struct fib_rules_ops fib6_rules_ops;
+static struct fib_rules_ops *fib6_rules_ops;
 
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
 				   int flags, pol_lookup_t lookup)
@@ -38,7 +38,7 @@ struct dst_entry *fib6_rule_lookup(struc
 		.lookup_ptr = lookup,
 	};
 
-	fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
+	fib_rules_lookup(fib6_rules_ops, fl, flags, &arg);
 	if (arg.rule)
 		fib_rule_put(arg.rule);
 
@@ -234,7 +234,7 @@ static size_t fib6_rule_nlmsg_payload(st
 	       + nla_total_size(16); /* src */
 }
 
-static struct fib_rules_ops fib6_rules_ops = {
+static struct fib_rules_ops fib6_rules_ops_template = {
 	.family			= AF_INET6,
 	.rule_size		= sizeof(struct fib6_rule),
 	.addr_size		= sizeof(struct in6_addr),
@@ -247,7 +247,6 @@ static struct fib_rules_ops fib6_rules_o
 	.nlmsg_payload		= fib6_rule_nlmsg_payload,
 	.nlgroup		= RTNLGRP_IPV6_RULE,
 	.policy			= fib6_rule_policy,
-	.rules_list		= LIST_HEAD_INIT(fib6_rules_ops.rules_list),
 	.owner			= THIS_MODULE,
 	.fro_net		= &init_net,
 };
@@ -256,11 +255,18 @@ static int __init fib6_default_rules_ini
 {
 	int err;
 
-	err = fib_default_rule_add(&fib6_rules_ops, 0,
+	fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
+				 sizeof(*fib6_rules_ops), GFP_KERNEL);
+	if (!fib6_rules_ops)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&fib6_rules_ops->rules_list);
+
+	err = fib_default_rule_add(fib6_rules_ops, 0,
 				   RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
 	if (err < 0)
 		return err;
-	err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
+	err = fib_default_rule_add(fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
 	if (err < 0)
 		return err;
 	return 0;
@@ -274,18 +280,20 @@ int __init fib6_rules_init(void)
 	if (ret)
 		goto out;
 
-	ret = fib_rules_register(&fib6_rules_ops);
+	ret = fib_rules_register(fib6_rules_ops);
 	if (ret)
 		goto out_default_rules_init;
 out:
 	return ret;
 
 out_default_rules_init:
-	fib_rules_cleanup_ops(&fib6_rules_ops);
+	fib_rules_cleanup_ops(fib6_rules_ops);
+	kfree(fib6_rules_ops);
 	goto out;
 }
 
 void fib6_rules_cleanup(void)
 {
-	fib_rules_unregister(&fib6_rules_ops);
+	fib_rules_unregister(fib6_rules_ops);
+	kfree(fib6_rules_ops);
 }

-- 

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

* [patch 09/11][NETNS][IPV6] fib6_rules: make per network namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (7 preceding siblings ...)
  2008-01-25 16:50 ` [patch 08/11][NETNS][IPV6] fib6_rules - dynamically allocate the fib rules ops Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 10/11][NETNS][IPV6] rt6_stats - dynamically allocate the rt6_stats Daniel Lezcano
  2008-01-25 16:50 ` [patch 11/11][NETNS][IPV6] rt6_stats - make rt6_stats per namespace Daniel Lezcano
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: fib6-rules-per-network-namespace.patch --]
[-- Type: text/plain, Size: 4708 bytes --]

The fib6_rules_ops is moved to the network namespace structure.
All references are changed to have it relatively to it.

Each time a network namespace is created a new fib6_rules_ops is
allocated, initialized and stored into the network namespace
structure.

The common part of the fib rules is namespace aware, so it is
quite easy to retrieve the network namespace from the rules and use
it in the different callbacks.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/netns/ipv6.h |    1 
 net/ipv6/fib6_rules.c    |   82 ++++++++++++++++++++++++++---------------------
 2 files changed, 47 insertions(+), 36 deletions(-)

Index: net-2.6.25/include/net/netns/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/netns/ipv6.h
+++ net-2.6.25/include/net/netns/ipv6.h
@@ -37,6 +37,7 @@ struct netns_ipv6 {
 	struct fib6_table       *fib6_main_tbl;
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	struct fib6_table       *fib6_local_tbl;
+	struct fib_rules_ops    *fib6_rules_ops;
 #endif
 };
 #endif
Index: net-2.6.25/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.25.orig/net/ipv6/fib6_rules.c
+++ net-2.6.25/net/ipv6/fib6_rules.c
@@ -29,8 +29,6 @@ struct fib6_rule
 	u8			tclass;
 };
 
-static struct fib_rules_ops *fib6_rules_ops;
-
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
 				   int flags, pol_lookup_t lookup)
 {
@@ -38,7 +36,7 @@ struct dst_entry *fib6_rule_lookup(struc
 		.lookup_ptr = lookup,
 	};
 
-	fib_rules_lookup(fib6_rules_ops, fl, flags, &arg);
+	fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg);
 	if (arg.rule)
 		fib_rule_put(arg.rule);
 
@@ -71,7 +69,7 @@ static int fib6_rule_action(struct fib_r
 		goto discard_pkt;
 	}
 
-	table = fib6_get_table(&init_net, rule->table);
+	table = fib6_get_table(rule->fr_net, rule->table);
 	if (table)
 		rt = lookup(table, flp, flags);
 
@@ -145,13 +143,14 @@ static int fib6_rule_configure(struct fi
 			       struct nlattr **tb)
 {
 	int err = -EINVAL;
+	struct net *net = skb->sk->sk_net;
 	struct fib6_rule *rule6 = (struct fib6_rule *) rule;
 
 	if (rule->action == FR_ACT_TO_TBL) {
 		if (rule->table == RT6_TABLE_UNSPEC)
 			goto errout;
 
-		if (fib6_new_table(&init_net, rule->table) == NULL) {
+		if (fib6_new_table(net, rule->table) == NULL) {
 			err = -ENOBUFS;
 			goto errout;
 		}
@@ -251,49 +250,60 @@ static struct fib_rules_ops fib6_rules_o
 	.fro_net		= &init_net,
 };
 
-static int __init fib6_default_rules_init(void)
+static int fib6_rules_net_init(struct net *net)
 {
-	int err;
+	int err = -ENOMEM;
 
-	fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
-				 sizeof(*fib6_rules_ops), GFP_KERNEL);
-	if (!fib6_rules_ops)
-		return -ENOMEM;
+	net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
+					   sizeof(*net->ipv6.fib6_rules_ops),
+					   GFP_KERNEL);
+	if (!net->ipv6.fib6_rules_ops)
+		goto out;
 
-	INIT_LIST_HEAD(&fib6_rules_ops->rules_list);
+	net->ipv6.fib6_rules_ops->fro_net = net;
+	INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
 
-	err = fib_default_rule_add(fib6_rules_ops, 0,
+	err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
 				   RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
-	if (err < 0)
-		return err;
-	err = fib_default_rule_add(fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
-	if (err < 0)
-		return err;
-	return 0;
+	if (err)
+		goto out_fib6_rules_ops;
+
+	err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
+				   0x7FFE, RT6_TABLE_MAIN, 0);
+	if (err)
+		goto out_fib6_default_rule_add;
+
+	err = fib_rules_register(net->ipv6.fib6_rules_ops);
+	if (err)
+		goto out_fib6_default_rule_add;
+out:
+	return err;
+
+out_fib6_default_rule_add:
+	fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
+out_fib6_rules_ops:
+	kfree(net->ipv6.fib6_rules_ops);
+	goto out;
 }
 
-int __init fib6_rules_init(void)
+static void fib6_rules_net_exit(struct net *net)
 {
-	int ret;
-
-	ret = fib6_default_rules_init();
-	if (ret)
-		goto out;
+	fib_rules_unregister(net->ipv6.fib6_rules_ops);
+	kfree(net->ipv6.fib6_rules_ops);
+}
 
-	ret = fib_rules_register(fib6_rules_ops);
-	if (ret)
-		goto out_default_rules_init;
-out:
-	return ret;
+static struct pernet_operations fib6_rules_net_ops = {
+	.init = fib6_rules_net_init,
+	.exit = fib6_rules_net_exit,
+};
 
-out_default_rules_init:
-	fib_rules_cleanup_ops(fib6_rules_ops);
-	kfree(fib6_rules_ops);
-	goto out;
+int __init fib6_rules_init(void)
+{
+	return register_pernet_subsys(&fib6_rules_net_ops);
 }
 
+
 void fib6_rules_cleanup(void)
 {
-	fib_rules_unregister(fib6_rules_ops);
-	kfree(fib6_rules_ops);
+	return unregister_pernet_subsys(&fib6_rules_net_ops);
 }

-- 

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

* [patch 10/11][NETNS][IPV6] rt6_stats - dynamically allocate the rt6_stats
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (8 preceding siblings ...)
  2008-01-25 16:50 ` [patch 09/11][NETNS][IPV6] fib6_rules: make per network namespace Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  2008-01-25 16:50 ` [patch 11/11][NETNS][IPV6] rt6_stats - make rt6_stats per namespace Daniel Lezcano
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: rt6-stats-dynamic-allocation.patch --]
[-- Type: text/plain, Size: 3946 bytes --]

This patch allocates the rt6_stats struct dynamically when
the fib6 is initialized. That provides the ability to create
several instances of this structure for the network namespaces.

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

Index: net-2.6.25/include/net/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/ipv6.h
+++ net-2.6.25/include/net/ipv6.h
@@ -604,7 +604,7 @@ extern void ipv6_misc_proc_exit(void);
 extern int snmp6_register_dev(struct inet6_dev *idev);
 extern int snmp6_unregister_dev(struct inet6_dev *idev);
 
-extern struct rt6_statistics rt6_stats;
+extern struct rt6_statistics *rt6_stats;
 #else
 static inline int snmp6_register_dev(struct inet6_dev *idev)
 {
Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -48,7 +48,7 @@
 #define RT6_TRACE(x...) do { ; } while (0)
 #endif
 
-struct rt6_statistics	rt6_stats;
+struct rt6_statistics *rt6_stats;
 
 static struct kmem_cache * fib6_node_kmem __read_mostly;
 
@@ -653,10 +653,10 @@ static int fib6_add_rt2node(struct fib6_
 	rt->rt6i_node = fn;
 	atomic_inc(&rt->rt6i_ref);
 	inet6_rt_notify(RTM_NEWROUTE, rt, info);
-	rt6_stats.fib_rt_entries++;
+	rt6_stats->fib_rt_entries++;
 
 	if ((fn->fn_flags & RTN_RTINFO) == 0) {
-		rt6_stats.fib_route_nodes++;
+		rt6_stats->fib_route_nodes++;
 		fn->fn_flags |= RTN_RTINFO;
 	}
 
@@ -1093,8 +1093,8 @@ static void fib6_del_route(struct fib6_n
 	/* Unlink it */
 	*rtp = rt->u.dst.rt6_next;
 	rt->rt6i_node = NULL;
-	rt6_stats.fib_rt_entries--;
-	rt6_stats.fib_discarded_routes++;
+	rt6_stats->fib_rt_entries--;
+	rt6_stats->fib_discarded_routes++;
 
 	/* Reset round-robin state, if necessary */
 	if (fn->rr_ptr == rt)
@@ -1117,7 +1117,7 @@ static void fib6_del_route(struct fib6_n
 	/* If it was last route, expunge its radix tree node */
 	if (fn->leaf == NULL) {
 		fn->fn_flags &= ~RTN_RTINFO;
-		rt6_stats.fib_route_nodes--;
+		rt6_stats->fib_route_nodes--;
 		fn = fib6_repair_tree(fn);
 	}
 
@@ -1556,9 +1556,14 @@ int __init fib6_init(void)
 	if (!fib6_node_kmem)
 		goto out;
 
+	ret = -ENOMEM;
+	rt6_stats = kzalloc(sizeof(*rt6_stats), GFP_KERNEL);
+	if (!rt6_stats)
+		goto out_kmem_cache_create;
+
 	ret = register_pernet_subsys(&fib6_net_ops);
 	if (ret)
-		goto out_kmem_cache_create;
+		goto out_rt6_stats;
 
 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
 	if (ret)
@@ -1568,6 +1573,8 @@ out:
 
 out_unregister_subsys:
 	unregister_pernet_subsys(&fib6_net_ops);
+out_rt6_stats:
+	kfree(rt6_stats);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1576,5 +1583,6 @@ out_kmem_cache_create:
 void fib6_gc_cleanup(void)
 {
 	unregister_pernet_subsys(&fib6_net_ops);
+	kfree(rt6_stats);
 	kmem_cache_destroy(fib6_node_kmem);
 }
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -2349,11 +2349,11 @@ static const struct file_operations ipv6
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
 {
 	seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
-		      rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,
-		      rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,
-		      rt6_stats.fib_rt_cache,
+		      rt6_stats->fib_nodes, rt6_stats->fib_route_nodes,
+		      rt6_stats->fib_rt_alloc, rt6_stats->fib_rt_entries,
+		      rt6_stats->fib_rt_cache,
 		      atomic_read(&ip6_dst_ops.entries),
-		      rt6_stats.fib_discarded_routes);
+		      rt6_stats->fib_discarded_routes);
 
 	return 0;
 }

-- 

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

* [patch 11/11][NETNS][IPV6] rt6_stats - make rt6_stats per namespace
  2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
                   ` (9 preceding siblings ...)
  2008-01-25 16:50 ` [patch 10/11][NETNS][IPV6] rt6_stats - dynamically allocate the rt6_stats Daniel Lezcano
@ 2008-01-25 16:50 ` Daniel Lezcano
  10 siblings, 0 replies; 12+ messages in thread
From: Daniel Lezcano @ 2008-01-25 16:50 UTC (permalink / raw)
  To: davem; +Cc: benjamin.thery, netdev, den

[-- Attachment #1: rt6-stats-per-namespace.patch --]
[-- Type: text/plain, Size: 5759 bytes --]

The rt6_stats is now per namespace with this patch. It is
allocated when a network namespace is created and freed
when the network namespace exits and references are relative
to the network namespace.

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

Index: net-2.6.25/include/net/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/ipv6.h
+++ net-2.6.25/include/net/ipv6.h
@@ -604,7 +604,6 @@ extern void ipv6_misc_proc_exit(void);
 extern int snmp6_register_dev(struct inet6_dev *idev);
 extern int snmp6_unregister_dev(struct inet6_dev *idev);
 
-extern struct rt6_statistics *rt6_stats;
 #else
 static inline int snmp6_register_dev(struct inet6_dev *idev)
 {
Index: net-2.6.25/net/ipv6/ip6_fib.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_fib.c
+++ net-2.6.25/net/ipv6/ip6_fib.c
@@ -48,8 +48,6 @@
 #define RT6_TRACE(x...) do { ; } while (0)
 #endif
 
-struct rt6_statistics *rt6_stats;
-
 static struct kmem_cache * fib6_node_kmem __read_mostly;
 
 enum fib_walk_state_t
@@ -653,10 +651,10 @@ static int fib6_add_rt2node(struct fib6_
 	rt->rt6i_node = fn;
 	atomic_inc(&rt->rt6i_ref);
 	inet6_rt_notify(RTM_NEWROUTE, rt, info);
-	rt6_stats->fib_rt_entries++;
+	info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
 
 	if ((fn->fn_flags & RTN_RTINFO) == 0) {
-		rt6_stats->fib_route_nodes++;
+		info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
 		fn->fn_flags |= RTN_RTINFO;
 	}
 
@@ -1087,14 +1085,15 @@ static void fib6_del_route(struct fib6_n
 {
 	struct fib6_walker_t *w;
 	struct rt6_info *rt = *rtp;
+	struct net *net = info->nl_net;
 
 	RT6_TRACE("fib6_del_route\n");
 
 	/* Unlink it */
 	*rtp = rt->u.dst.rt6_next;
 	rt->rt6i_node = NULL;
-	rt6_stats->fib_rt_entries--;
-	rt6_stats->fib_discarded_routes++;
+	net->ipv6.rt6_stats->fib_rt_entries--;
+	net->ipv6.rt6_stats->fib_discarded_routes++;
 
 	/* Reset round-robin state, if necessary */
 	if (fn->rr_ptr == rt)
@@ -1117,7 +1116,7 @@ static void fib6_del_route(struct fib6_n
 	/* If it was last route, expunge its radix tree node */
 	if (fn->leaf == NULL) {
 		fn->fn_flags &= ~RTN_RTINFO;
-		rt6_stats->fib_route_nodes--;
+		net->ipv6.rt6_stats->fib_route_nodes--;
 		fn = fib6_repair_tree(fn);
 	}
 
@@ -1486,11 +1485,15 @@ static int fib6_net_init(struct net *net
 	setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
 	net->ipv6.ip6_fib_timer = timer;
 
+	net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
+	if (!net->ipv6.rt6_stats)
+		goto out_timer;
+
 	net->ipv6.fib_table_hash =
 		kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
 			GFP_KERNEL);
 	if (!net->ipv6.fib_table_hash)
-		goto out_timer;
+		goto out_rt6_stats;
 
 	net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
 					  GFP_KERNEL);
@@ -1524,6 +1527,8 @@ out_fib6_main_tbl:
 #endif
 out_fib_table_hash:
 	kfree(net->ipv6.fib_table_hash);
+out_rt6_stats:
+	kfree(net->ipv6.rt6_stats);
 out_timer:
 	kfree(timer);
 	goto out;
@@ -1538,6 +1543,7 @@ static void fib6_net_exit(struct net *ne
 #endif
 	kfree(net->ipv6.fib6_main_tbl);
 	kfree(net->ipv6.fib_table_hash);
+	kfree(net->ipv6.rt6_stats);
 }
 
 static struct pernet_operations fib6_net_ops = {
@@ -1556,14 +1562,9 @@ int __init fib6_init(void)
 	if (!fib6_node_kmem)
 		goto out;
 
-	ret = -ENOMEM;
-	rt6_stats = kzalloc(sizeof(*rt6_stats), GFP_KERNEL);
-	if (!rt6_stats)
-		goto out_kmem_cache_create;
-
 	ret = register_pernet_subsys(&fib6_net_ops);
 	if (ret)
-		goto out_rt6_stats;
+		goto out_kmem_cache_create;
 
 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
 	if (ret)
@@ -1573,8 +1574,6 @@ out:
 
 out_unregister_subsys:
 	unregister_pernet_subsys(&fib6_net_ops);
-out_rt6_stats:
-	kfree(rt6_stats);
 out_kmem_cache_create:
 	kmem_cache_destroy(fib6_node_kmem);
 	goto out;
@@ -1583,6 +1582,5 @@ out_kmem_cache_create:
 void fib6_gc_cleanup(void)
 {
 	unregister_pernet_subsys(&fib6_net_ops);
-	kfree(rt6_stats);
 	kmem_cache_destroy(fib6_node_kmem);
 }
Index: net-2.6.25/net/ipv6/route.c
===================================================================
--- net-2.6.25.orig/net/ipv6/route.c
+++ net-2.6.25/net/ipv6/route.c
@@ -2349,11 +2349,13 @@ static const struct file_operations ipv6
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
 {
 	seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
-		      rt6_stats->fib_nodes, rt6_stats->fib_route_nodes,
-		      rt6_stats->fib_rt_alloc, rt6_stats->fib_rt_entries,
-		      rt6_stats->fib_rt_cache,
-		      atomic_read(&ip6_dst_ops.entries),
-		      rt6_stats->fib_discarded_routes);
+		   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,
+		   atomic_read(&ip6_dst_ops.entries),
+		   init_net.ipv6.rt6_stats->fib_discarded_routes);
 
 	return 0;
 }
Index: net-2.6.25/include/net/netns/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/netns/ipv6.h
+++ net-2.6.25/include/net/netns/ipv6.h
@@ -32,6 +32,7 @@ struct netns_ipv6 {
 	struct ipv6_devconf	*devconf_dflt;
 	struct netns_frags	frags;
 
+	struct rt6_statistics   *rt6_stats;
 	struct timer_list       *ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;

-- 

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

end of thread, other threads:[~2008-01-25 17:11 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-25 16:50 [patch 00/11][NETNS][IPV6] make a subset of the routing per namespace Daniel Lezcano
2008-01-25 16:50 ` [patch 01/11][NETNS][IPV6] ip6_fib - dynamically allocate the tables Daniel Lezcano
2008-01-25 16:50 ` [patch 02/11][NETNS][IPV6] ip6_fib - make the tables per namespace Daniel Lezcano
2008-01-25 16:50 ` [patch 03/11][NETNS][IPV6] ip6_fib - make fib6_clean_all " Daniel Lezcano
2008-01-25 16:50 ` [patch 04/11][NETNS][IPV6] ip6_fib - pass the network namespace parameter to timer callback Daniel Lezcano
2008-01-25 16:50 ` [patch 05/11][NETNS][IPV6] ip6_fib - dynamically allocate the gc_timer Daniel Lezcano
2008-01-25 16:50 ` [patch 06/11][NETNS][IPV6] ip6_fib - make the ip6 fib gc timer per network namespace Daniel Lezcano
2008-01-25 16:50 ` [patch 07/11][NETNS][IPV6] make fib6_clean_node to use the " Daniel Lezcano
2008-01-25 16:50 ` [patch 08/11][NETNS][IPV6] fib6_rules - dynamically allocate the fib rules ops Daniel Lezcano
2008-01-25 16:50 ` [patch 09/11][NETNS][IPV6] fib6_rules: make per network namespace Daniel Lezcano
2008-01-25 16:50 ` [patch 10/11][NETNS][IPV6] rt6_stats - dynamically allocate the rt6_stats Daniel Lezcano
2008-01-25 16:50 ` [patch 11/11][NETNS][IPV6] rt6_stats - make rt6_stats per namespace Daniel Lezcano

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