diff options
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv6/route.c | 62 |
2 files changed, 32 insertions, 31 deletions
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 311a942f36e9..53b5a283a4b3 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -41,6 +41,7 @@ struct netns_ipv6 { | |||
41 | struct timer_list *ip6_fib_timer; | 41 | struct timer_list *ip6_fib_timer; |
42 | struct hlist_head *fib_table_hash; | 42 | struct hlist_head *fib_table_hash; |
43 | struct fib6_table *fib6_main_tbl; | 43 | struct fib6_table *fib6_main_tbl; |
44 | struct dst_ops *ip6_dst_ops; | ||
44 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 45 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
45 | struct rt6_info *ip6_prohibit_entry; | 46 | struct rt6_info *ip6_prohibit_entry; |
46 | struct rt6_info *ip6_blk_hole_entry; | 47 | struct rt6_info *ip6_blk_hole_entry; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index fa014d701c1a..d88b6ec3c5d1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -113,8 +113,6 @@ static struct dst_ops ip6_dst_ops_template = { | |||
113 | .entries = ATOMIC_INIT(0), | 113 | .entries = ATOMIC_INIT(0), |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static struct dst_ops *ip6_dst_ops; | ||
117 | |||
118 | static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | 116 | static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) |
119 | { | 117 | { |
120 | } | 118 | } |
@@ -188,9 +186,9 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
188 | #endif | 186 | #endif |
189 | 187 | ||
190 | /* allocate dst with ip6_dst_ops */ | 188 | /* allocate dst with ip6_dst_ops */ |
191 | static __inline__ struct rt6_info *ip6_dst_alloc(void) | 189 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
192 | { | 190 | { |
193 | return (struct rt6_info *)dst_alloc(ip6_dst_ops); | 191 | return (struct rt6_info *)dst_alloc(ops); |
194 | } | 192 | } |
195 | 193 | ||
196 | static void ip6_dst_destroy(struct dst_entry *dst) | 194 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -925,7 +923,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
925 | if (unlikely(idev == NULL)) | 923 | if (unlikely(idev == NULL)) |
926 | return NULL; | 924 | return NULL; |
927 | 925 | ||
928 | rt = ip6_dst_alloc(); | 926 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
929 | if (unlikely(rt == NULL)) { | 927 | if (unlikely(rt == NULL)) { |
930 | in6_dev_put(idev); | 928 | in6_dev_put(idev); |
931 | goto out; | 929 | goto out; |
@@ -999,18 +997,18 @@ static int ip6_dst_gc(struct dst_ops *ops) | |||
999 | unsigned long now = jiffies; | 997 | unsigned long now = jiffies; |
1000 | 998 | ||
1001 | if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && | 999 | if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && |
1002 | atomic_read(&ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size) | 1000 | atomic_read(&init_net.ipv6.ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size) |
1003 | goto out; | 1001 | goto out; |
1004 | 1002 | ||
1005 | expire++; | 1003 | expire++; |
1006 | fib6_run_gc(expire, &init_net); | 1004 | fib6_run_gc(expire, &init_net); |
1007 | last_gc = now; | 1005 | last_gc = now; |
1008 | if (atomic_read(&ip6_dst_ops->entries) < ip6_dst_ops->gc_thresh) | 1006 | if (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) < init_net.ipv6.ip6_dst_ops->gc_thresh) |
1009 | expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; | 1007 | expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; |
1010 | 1008 | ||
1011 | out: | 1009 | out: |
1012 | expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; | 1010 | expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; |
1013 | return (atomic_read(&ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size); | 1011 | return (atomic_read(&init_net.ipv6.ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size); |
1014 | } | 1012 | } |
1015 | 1013 | ||
1016 | /* Clean host part of a prefix. Not necessary in radix tree, | 1014 | /* Clean host part of a prefix. Not necessary in radix tree, |
@@ -1084,7 +1082,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1084 | goto out; | 1082 | goto out; |
1085 | } | 1083 | } |
1086 | 1084 | ||
1087 | rt = ip6_dst_alloc(); | 1085 | rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1088 | 1086 | ||
1089 | if (rt == NULL) { | 1087 | if (rt == NULL) { |
1090 | err = -ENOMEM; | 1088 | err = -ENOMEM; |
@@ -1570,7 +1568,8 @@ out: | |||
1570 | 1568 | ||
1571 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1569 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) |
1572 | { | 1570 | { |
1573 | struct rt6_info *rt = ip6_dst_alloc(); | 1571 | struct net *net = ort->rt6i_dev->nd_net; |
1572 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | ||
1574 | 1573 | ||
1575 | if (rt) { | 1574 | if (rt) { |
1576 | rt->u.dst.input = ort->u.dst.input; | 1575 | rt->u.dst.input = ort->u.dst.input; |
@@ -1849,7 +1848,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1849 | int anycast) | 1848 | int anycast) |
1850 | { | 1849 | { |
1851 | struct net *net = idev->dev->nd_net; | 1850 | struct net *net = idev->dev->nd_net; |
1852 | struct rt6_info *rt = ip6_dst_alloc(); | 1851 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1853 | 1852 | ||
1854 | if (rt == NULL) | 1853 | if (rt == NULL) |
1855 | return ERR_PTR(-ENOMEM); | 1854 | return ERR_PTR(-ENOMEM); |
@@ -2407,7 +2406,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v) | |||
2407 | net->ipv6.rt6_stats->fib_rt_alloc, | 2406 | net->ipv6.rt6_stats->fib_rt_alloc, |
2408 | net->ipv6.rt6_stats->fib_rt_entries, | 2407 | net->ipv6.rt6_stats->fib_rt_entries, |
2409 | net->ipv6.rt6_stats->fib_rt_cache, | 2408 | net->ipv6.rt6_stats->fib_rt_cache, |
2410 | atomic_read(&ip6_dst_ops->entries), | 2409 | atomic_read(&net->ipv6.ip6_dst_ops->entries), |
2411 | net->ipv6.rt6_stats->fib_discarded_routes); | 2410 | net->ipv6.rt6_stats->fib_discarded_routes); |
2412 | 2411 | ||
2413 | return 0; | 2412 | return 0; |
@@ -2552,7 +2551,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
2552 | 2551 | ||
2553 | if (table) { | 2552 | if (table) { |
2554 | table[0].data = &net->ipv6.sysctl.flush_delay; | 2553 | table[0].data = &net->ipv6.sysctl.flush_delay; |
2555 | table[1].data = &ip6_dst_ops_template.gc_thresh; | 2554 | table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh; |
2556 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | 2555 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; |
2557 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | 2556 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; |
2558 | table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; | 2557 | table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; |
@@ -2571,14 +2570,21 @@ static int ip6_route_net_init(struct net *net) | |||
2571 | int ret = 0; | 2570 | int ret = 0; |
2572 | 2571 | ||
2573 | ret = -ENOMEM; | 2572 | ret = -ENOMEM; |
2573 | net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template, | ||
2574 | sizeof(*net->ipv6.ip6_dst_ops), | ||
2575 | GFP_KERNEL); | ||
2576 | if (!net->ipv6.ip6_dst_ops) | ||
2577 | goto out; | ||
2578 | net->ipv6.ip6_dst_ops->dst_net = net; | ||
2579 | |||
2574 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | 2580 | net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, |
2575 | sizeof(*net->ipv6.ip6_null_entry), | 2581 | sizeof(*net->ipv6.ip6_null_entry), |
2576 | GFP_KERNEL); | 2582 | GFP_KERNEL); |
2577 | if (!net->ipv6.ip6_null_entry) | 2583 | if (!net->ipv6.ip6_null_entry) |
2578 | goto out; | 2584 | goto out_ip6_dst_ops; |
2579 | net->ipv6.ip6_null_entry->u.dst.path = | 2585 | net->ipv6.ip6_null_entry->u.dst.path = |
2580 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2586 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2581 | net->ipv6.ip6_null_entry->u.dst.ops = ip6_dst_ops; | 2587 | net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops; |
2582 | 2588 | ||
2583 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2589 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2584 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2590 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2590,7 +2596,7 @@ static int ip6_route_net_init(struct net *net) | |||
2590 | } | 2596 | } |
2591 | net->ipv6.ip6_prohibit_entry->u.dst.path = | 2597 | net->ipv6.ip6_prohibit_entry->u.dst.path = |
2592 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2598 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2593 | net->ipv6.ip6_prohibit_entry->u.dst.ops = ip6_dst_ops; | 2599 | net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; |
2594 | 2600 | ||
2595 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2601 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2596 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2602 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
@@ -2602,7 +2608,7 @@ static int ip6_route_net_init(struct net *net) | |||
2602 | } | 2608 | } |
2603 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | 2609 | net->ipv6.ip6_blk_hole_entry->u.dst.path = |
2604 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2610 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2605 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = ip6_dst_ops; | 2611 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; |
2606 | #endif | 2612 | #endif |
2607 | 2613 | ||
2608 | #ifdef CONFIG_PROC_FS | 2614 | #ifdef CONFIG_PROC_FS |
@@ -2612,6 +2618,10 @@ static int ip6_route_net_init(struct net *net) | |||
2612 | ret = 0; | 2618 | ret = 0; |
2613 | out: | 2619 | out: |
2614 | return ret; | 2620 | return ret; |
2621 | |||
2622 | out_ip6_dst_ops: | ||
2623 | kfree(net->ipv6.ip6_dst_ops); | ||
2624 | goto out; | ||
2615 | } | 2625 | } |
2616 | 2626 | ||
2617 | static void ip6_route_net_exit(struct net *net) | 2627 | static void ip6_route_net_exit(struct net *net) |
@@ -2625,6 +2635,7 @@ static void ip6_route_net_exit(struct net *net) | |||
2625 | kfree(net->ipv6.ip6_prohibit_entry); | 2635 | kfree(net->ipv6.ip6_prohibit_entry); |
2626 | kfree(net->ipv6.ip6_blk_hole_entry); | 2636 | kfree(net->ipv6.ip6_blk_hole_entry); |
2627 | #endif | 2637 | #endif |
2638 | kfree(net->ipv6.ip6_dst_ops); | ||
2628 | } | 2639 | } |
2629 | 2640 | ||
2630 | static struct pernet_operations ip6_route_net_ops = { | 2641 | static struct pernet_operations ip6_route_net_ops = { |
@@ -2641,20 +2652,12 @@ int __init ip6_route_init(void) | |||
2641 | { | 2652 | { |
2642 | int ret; | 2653 | int ret; |
2643 | 2654 | ||
2644 | ip6_dst_ops = kmemdup(&ip6_dst_ops_template, | ||
2645 | sizeof(*ip6_dst_ops), GFP_KERNEL); | ||
2646 | if (!ip6_dst_ops) | ||
2647 | return -ENOMEM; | ||
2648 | |||
2649 | ret = -ENOMEM; | 2655 | ret = -ENOMEM; |
2650 | ip6_dst_ops_template.kmem_cachep = | 2656 | ip6_dst_ops_template.kmem_cachep = |
2651 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2657 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2652 | SLAB_HWCACHE_ALIGN, NULL); | 2658 | SLAB_HWCACHE_ALIGN, NULL); |
2653 | if (!ip6_dst_ops_template.kmem_cachep) | 2659 | if (!ip6_dst_ops_template.kmem_cachep) |
2654 | goto out_ip6_dst_ops; | 2660 | goto out;; |
2655 | |||
2656 | ip6_dst_ops->kmem_cachep = ip6_dst_ops_template.kmem_cachep; | ||
2657 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | ||
2658 | 2661 | ||
2659 | ret = register_pernet_subsys(&ip6_route_net_ops); | 2662 | ret = register_pernet_subsys(&ip6_route_net_ops); |
2660 | if (ret) | 2663 | if (ret) |
@@ -2705,9 +2708,7 @@ out_fib6_init: | |||
2705 | out_register_subsys: | 2708 | out_register_subsys: |
2706 | unregister_pernet_subsys(&ip6_route_net_ops); | 2709 | unregister_pernet_subsys(&ip6_route_net_ops); |
2707 | out_kmem_cache: | 2710 | out_kmem_cache: |
2708 | kmem_cache_destroy(ip6_dst_ops->kmem_cachep); | 2711 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); |
2709 | out_ip6_dst_ops: | ||
2710 | kfree(ip6_dst_ops); | ||
2711 | goto out; | 2712 | goto out; |
2712 | } | 2713 | } |
2713 | 2714 | ||
@@ -2718,6 +2719,5 @@ void ip6_route_cleanup(void) | |||
2718 | xfrm6_fini(); | 2719 | xfrm6_fini(); |
2719 | fib6_gc_cleanup(); | 2720 | fib6_gc_cleanup(); |
2720 | unregister_pernet_subsys(&ip6_route_net_ops); | 2721 | unregister_pernet_subsys(&ip6_route_net_ops); |
2721 | kmem_cache_destroy(ip6_dst_ops->kmem_cachep); | 2722 | kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); |
2722 | kfree(ip6_dst_ops); | ||
2723 | } | 2723 | } |