From: Daniel Lezcano Date: Tue, 4 Mar 2008 07:27:06 +0000 (-0800) Subject: [NETNS][IPV6] ip6_fib - fib6_clean_all handle several network namespaces X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f3db4851;p=linux-beck.git [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 --- diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 4d4c8aca8fb9..e54075d902db 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -195,7 +195,8 @@ struct fib6_node *fib6_locate(struct fib6_node *root, 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, diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 8d155a645aba..a158abe71933 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -121,7 +121,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; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 9b3a2d0e4269..a1d872dacad6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2431,6 +2431,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) { struct inet6_dev *idev; struct inet6_ifaddr *ifa, **bifa; + struct net *net = dev->nd_net; int i; ASSERT_RTNL(); @@ -2438,7 +2439,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) 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); 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 + diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 09206f7ba525..2e6da2afd948 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1870,9 +1870,9 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) 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 @@ -1928,7 +1928,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) .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] = { @@ -2318,13 +2318,25 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) 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 = { @@ -2332,7 +2344,7 @@ static const struct file_operations ipv6_route_proc_fops = { .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) @@ -2570,7 +2582,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); @@ -2582,7 +2594,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); }