From 3b00944c5c73c49ef52bf17b66557c43c1d945fe Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Thu, 6 Dec 2007 16:11:48 -0800 Subject: [IPV6]: Make ndisc_dst_alloc() common for later use. For later use, this patch is renaming ndisc_dst_alloc() (and related function/structures) to icmp6_dst_alloc() (and so on). This patch also removing unused function- pointer argument for it. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/ip6_fib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index bab72b6f1444..c70fd38b54b7 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1464,7 +1464,7 @@ void fib6_run_gc(unsigned long dummy) } gc_args.more = 0; - ndisc_dst_gc(&gc_args.more); + icmp6_dst_gc(&gc_args.more); fib6_clean_all(fib6_age, 0, NULL); if (gc_args.more) -- cgit v1.2.3 From e0b85590bc1b50c9bbef4dd4738d9995fb1d1f64 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:24:31 -0800 Subject: [NETNS][IPV6] ip6_fib - dynamically allocate the fib tables 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 71 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index c70fd38b54b7..04d774963f3c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -166,20 +166,14 @@ static __inline__ void rt6_release(struct rt6_info *rt) 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_table *tb) } #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); } -- cgit v1.2.3 From 58f09b78b730cf0d936597272bf35b3d615e967c Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:25:27 -0800 Subject: [NETNS][IPV6] ip6_fib - make it per network namespace 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 161 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 68 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 04d774963f3c..7b549f0bc428 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -166,16 +166,13 @@ static __inline__ void rt6_release(struct rt6_info *rt) 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_table *tb) * 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_table(u32 id) 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 *skb, struct netlink_callback *cb) 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 *skb, struct netlink_callback *cb) 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 rt6_info *, void *arg), { 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); } -- cgit v1.2.3 From f3db48517f59133610f558f29de8834d7b007691 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:27:06 -0800 Subject: [NETNS][IPV6] ip6_fib - fib6_clean_all handle several network namespaces 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7b549f0bc428..0f9dc81f0e61 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1350,7 +1350,7 @@ static void fib6_clean_tree(struct fib6_node *root, 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 rt6_info *, void *arg), 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; icmp6_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 + -- cgit v1.2.3 From 5b7c931dff03621ae7ac524c4fa280d4e5f187a4 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:28:58 -0800 Subject: [NETNS][IPV6] ip6_fib - add net to gc timer parameter 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 0f9dc81f0e61..9b1c232a29ee 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -93,7 +93,10 @@ static int fib6_walk_continue(struct fib6_walker_t *w); 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, void *arg) 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; icmp6_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; -- cgit v1.2.3 From 450d19f8ab35fad4ef2b129cb383a5b8d1326611 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:29:33 -0800 Subject: [NETNS][IPV6] ip6_fib - dynamically allocate gc-timer 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 9b1c232a29ee..77ad1002c904 100644 --- a/net/ipv6/ip6_fib.c +++ b/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_node *fn, struct rt6_info *rt, 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, struct net *net) } 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, struct net *net) 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); } -- cgit v1.2.3 From 63152fc0de4dfe83da543bf133cef73d885a50fc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:31:11 -0800 Subject: [NETNS][IPV6] ip6_fib - gc timer per namespace 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 77ad1002c904..4aa67988f518 100644 --- a/net/ipv6/ip6_fib.c +++ b/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_node *fn, struct rt6_info *rt, 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, struct rt6_info *rt, struct nl_info *info) 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, struct net *net) } 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, struct net *net) 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 long arg) 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_ops = { 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); } -- cgit v1.2.3 From ec7d43c291df9f6e978733f892f7255be89feedb Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Mon, 3 Mar 2008 23:31:57 -0800 Subject: [NETNS][IPV6] ip6_fib - clean node use namespace 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: Benjamin Thery Signed-off-by: Daniel Lezcano Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4aa67988f518..350a970ca1e3 100644 --- a/net/ipv6/ip6_fib.c +++ b/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, struct rt6_info *rt, struct nl_info *info) 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 nl_info *info) 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_t *w) 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_walker_t *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_node *root, 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 (*func)(struct rt6_info *, void *arg), 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_info *rt, void *arg) 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); } /* -- cgit v1.2.3 From 6cc118bd506ae8c6436f507b838a0e1f6185fec2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 3 Mar 2008 23:33:43 -0800 Subject: [NETNS][IPV6] rt6_stats - dynamically allocate the routes statistics 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 350a970ca1e3..7d82ad540140 100644 --- a/net/ipv6/ip6_fib.c +++ b/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_node *fn, struct rt6_info *rt, 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_node *fn, struct rt6_info **rtp, /* 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_node *fn, struct rt6_info **rtp, /* 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); } -- cgit v1.2.3 From c572872f89e46e38cdb35a43b81122bfb7ff43fc Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Mon, 3 Mar 2008 23:34:17 -0800 Subject: [NETNS][IPV6] rt6_stats - make the stats per network namespace 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 Signed-off-by: Daniel Lezcano Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7d82ad540140..1c2566e3d392 100644 --- a/net/ipv6/ip6_fib.c +++ b/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_node *fn, struct rt6_info *rt, 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_node *fn, struct rt6_info **rtp, { 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_node *fn, struct rt6_info **rtp, /* 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 *net) #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); } -- cgit v1.2.3 From bdb3289f739e94bcae8b51972ae844ec66c2f4df Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 4 Mar 2008 13:48:10 -0800 Subject: [NETNS][IPV6] rt6_info - make rt6_info accessed as a pointer 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 1c2566e3d392..f028f7a1a446 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -200,7 +200,7 @@ static struct fib6_table *fib6_alloc_table(u32 id) 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, struct rt6_info *rt, struct nl_info *info) 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 fib6_node *root, 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_tree(struct fib6_node *fn) #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 nl_info *info) 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 -- cgit v1.2.3 From 8ed677896752fff056f6cf3d7ce462adc6c464f0 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 4 Mar 2008 13:48:30 -0800 Subject: [NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace 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 Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f028f7a1a446..b0814b0082e7 100644 --- a/net/ipv6/ip6_fib.c +++ b/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 *net, struct fib6_table *tb) #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 net *net, u32 id) 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 net *net, u32 id) 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, struct rt6_info *rt, struct nl_info *info) 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 fib6_node *root, * */ -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_prefix(struct fib6_node *fn) * 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_tree(struct fib6_node *fn) || (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_node *fn, struct rt6_info **rtp, 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_node *fn, struct rt6_info **rtp, */ 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_node *fn, struct rt6_info **rtp, 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 nl_info *info) 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 -- cgit v1.2.3 From 3b1e0a655f8eba44ab1ee2a1068d169ccfb853b9 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Wed, 26 Mar 2008 02:26:21 +0900 Subject: [NET] NETNS: Omit sock->sk_net without CONFIG_NET_NS. Introduce per-sock inlines: sock_net(), sock_net_set() and per-inet_timewait_sock inlines: twsk_net(), twsk_net_set(). Without CONFIG_NET_NS, no namespace other than &init_net exists. Let's explicitly define them to help compiler optimizations. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/ip6_fib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index b0814b0082e7..b3f6e03c454c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -346,7 +346,7 @@ end: static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = skb->sk->sk_net; + struct net *net = sock_net(skb->sk); unsigned int h, s_h; unsigned int e = 0, s_e; struct rt6_rtnl_dump_arg arg; -- cgit v1.2.3 From 3c051235a7f115c34e675c9cf55820bd3435f860 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 18 Apr 2008 01:46:19 -0700 Subject: [IPV6]: Fix dangling references on error in fib6_add(). Fixes bugzilla #8895 If a super-tree leaf has 'rt' assigned to it and we get an error from fib6_add_rt2node(), we'll leave a reference to 'rt' in pn->leaf and then do an unconditional dst_free(). We should prune such references. Based upon a report by Vincent Perrier. Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/ipv6/ip6_fib.c') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index b3f6e03c454c..50f3f8f8a59b 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -772,6 +772,10 @@ out: * If fib6_add_1 has cleared the old leaf pointer in the * super-tree leaf node we have to find a new one for it. */ + if (pn != fn && pn->leaf == rt) { + pn->leaf = NULL; + atomic_dec(&rt->rt6i_ref); + } if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { pn->leaf = fib6_find_prefix(info->nl_net, pn); #if RT6_DEBUG >= 2 -- cgit v1.2.3