aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2008-03-04 16:48:53 -0500
committerDavid S. Miller <davem@davemloft.net>2008-03-04 16:48:53 -0500
commit9a7ec3a94d8da475fe81810aa55136a81556d445 (patch)
tree57a241a178d5d60b14a00e1c77a37060fbf8e00a /net/ipv6/route.c
parent8ed677896752fff056f6cf3d7ce462adc6c464f0 (diff)
[NETNS][IPV6] route6 - dynamically allocate ip6_dst_ops
ip6_dst_ops is dynamically allocated in init and exit functions. That provides the ability to do multiple instanciations of this structure. This will be needed for network namespaces, indeed dst_ops stores data that are required to be per namespace: entries and gc_thresh. Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7ff66cebe77c..fa014d701c1a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -97,7 +97,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
97 struct in6_addr *gwaddr, int ifindex); 97 struct in6_addr *gwaddr, int ifindex);
98#endif 98#endif
99 99
100static struct dst_ops ip6_dst_ops = { 100static struct dst_ops ip6_dst_ops_template = {
101 .family = AF_INET6, 101 .family = AF_INET6,
102 .protocol = __constant_htons(ETH_P_IPV6), 102 .protocol = __constant_htons(ETH_P_IPV6),
103 .gc = ip6_dst_gc, 103 .gc = ip6_dst_gc,
@@ -113,6 +113,8 @@ static struct dst_ops ip6_dst_ops = {
113 .entries = ATOMIC_INIT(0), 113 .entries = ATOMIC_INIT(0),
114}; 114};
115 115
116static struct dst_ops *ip6_dst_ops;
117
116static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) 118static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
117{ 119{
118} 120}
@@ -137,7 +139,6 @@ static struct rt6_info ip6_null_entry_template = {
137 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 139 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
138 .input = ip6_pkt_discard, 140 .input = ip6_pkt_discard,
139 .output = ip6_pkt_discard_out, 141 .output = ip6_pkt_discard_out,
140 .ops = &ip6_dst_ops,
141 } 142 }
142 }, 143 },
143 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 144 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -160,7 +161,6 @@ struct rt6_info ip6_prohibit_entry_template = {
160 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 161 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
161 .input = ip6_pkt_prohibit, 162 .input = ip6_pkt_prohibit,
162 .output = ip6_pkt_prohibit_out, 163 .output = ip6_pkt_prohibit_out,
163 .ops = &ip6_dst_ops,
164 } 164 }
165 }, 165 },
166 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 166 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -178,7 +178,6 @@ static struct rt6_info ip6_blk_hole_entry_template = {
178 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 178 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
179 .input = dst_discard, 179 .input = dst_discard,
180 .output = dst_discard, 180 .output = dst_discard,
181 .ops = &ip6_dst_ops,
182 } 181 }
183 }, 182 },
184 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 183 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
@@ -191,7 +190,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
191/* allocate dst with ip6_dst_ops */ 190/* allocate dst with ip6_dst_ops */
192static __inline__ struct rt6_info *ip6_dst_alloc(void) 191static __inline__ struct rt6_info *ip6_dst_alloc(void)
193{ 192{
194 return (struct rt6_info *)dst_alloc(&ip6_dst_ops); 193 return (struct rt6_info *)dst_alloc(ip6_dst_ops);
195} 194}
196 195
197static void ip6_dst_destroy(struct dst_entry *dst) 196static void ip6_dst_destroy(struct dst_entry *dst)
@@ -1000,18 +999,18 @@ static int ip6_dst_gc(struct dst_ops *ops)
1000 unsigned long now = jiffies; 999 unsigned long now = jiffies;
1001 1000
1002 if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) && 1001 if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
1003 atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size) 1002 atomic_read(&ip6_dst_ops->entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
1004 goto out; 1003 goto out;
1005 1004
1006 expire++; 1005 expire++;
1007 fib6_run_gc(expire, &init_net); 1006 fib6_run_gc(expire, &init_net);
1008 last_gc = now; 1007 last_gc = now;
1009 if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh) 1008 if (atomic_read(&ip6_dst_ops->entries) < ip6_dst_ops->gc_thresh)
1010 expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1; 1009 expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
1011 1010
1012out: 1011out:
1013 expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity; 1012 expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
1014 return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size); 1013 return (atomic_read(&ip6_dst_ops->entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
1015} 1014}
1016 1015
1017/* Clean host part of a prefix. Not necessary in radix tree, 1016/* Clean host part of a prefix. Not necessary in radix tree,
@@ -2408,7 +2407,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v)
2408 net->ipv6.rt6_stats->fib_rt_alloc, 2407 net->ipv6.rt6_stats->fib_rt_alloc,
2409 net->ipv6.rt6_stats->fib_rt_entries, 2408 net->ipv6.rt6_stats->fib_rt_entries,
2410 net->ipv6.rt6_stats->fib_rt_cache, 2409 net->ipv6.rt6_stats->fib_rt_cache,
2411 atomic_read(&ip6_dst_ops.entries), 2410 atomic_read(&ip6_dst_ops->entries),
2412 net->ipv6.rt6_stats->fib_discarded_routes); 2411 net->ipv6.rt6_stats->fib_discarded_routes);
2413 2412
2414 return 0; 2413 return 0;
@@ -2464,7 +2463,7 @@ ctl_table ipv6_route_table_template[] = {
2464 { 2463 {
2465 .ctl_name = NET_IPV6_ROUTE_GC_THRESH, 2464 .ctl_name = NET_IPV6_ROUTE_GC_THRESH,
2466 .procname = "gc_thresh", 2465 .procname = "gc_thresh",
2467 .data = &ip6_dst_ops.gc_thresh, 2466 .data = &ip6_dst_ops_template.gc_thresh,
2468 .maxlen = sizeof(int), 2467 .maxlen = sizeof(int),
2469 .mode = 0644, 2468 .mode = 0644,
2470 .proc_handler = &proc_dointvec, 2469 .proc_handler = &proc_dointvec,
@@ -2553,8 +2552,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
2553 2552
2554 if (table) { 2553 if (table) {
2555 table[0].data = &net->ipv6.sysctl.flush_delay; 2554 table[0].data = &net->ipv6.sysctl.flush_delay;
2556 /* table[1].data will be handled when we have 2555 table[1].data = &ip6_dst_ops_template.gc_thresh;
2557 routes per namespace */
2558 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; 2556 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
2559 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; 2557 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
2560 table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout; 2558 table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
@@ -2580,6 +2578,7 @@ static int ip6_route_net_init(struct net *net)
2580 goto out; 2578 goto out;
2581 net->ipv6.ip6_null_entry->u.dst.path = 2579 net->ipv6.ip6_null_entry->u.dst.path =
2582 (struct dst_entry *)net->ipv6.ip6_null_entry; 2580 (struct dst_entry *)net->ipv6.ip6_null_entry;
2581 net->ipv6.ip6_null_entry->u.dst.ops = ip6_dst_ops;
2583 2582
2584#ifdef CONFIG_IPV6_MULTIPLE_TABLES 2583#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2585 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, 2584 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2591,6 +2590,7 @@ static int ip6_route_net_init(struct net *net)
2591 } 2590 }
2592 net->ipv6.ip6_prohibit_entry->u.dst.path = 2591 net->ipv6.ip6_prohibit_entry->u.dst.path =
2593 (struct dst_entry *)net->ipv6.ip6_prohibit_entry; 2592 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
2593 net->ipv6.ip6_prohibit_entry->u.dst.ops = ip6_dst_ops;
2594 2594
2595 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, 2595 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
2596 sizeof(*net->ipv6.ip6_blk_hole_entry), 2596 sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2602,6 +2602,7 @@ static int ip6_route_net_init(struct net *net)
2602 } 2602 }
2603 net->ipv6.ip6_blk_hole_entry->u.dst.path = 2603 net->ipv6.ip6_blk_hole_entry->u.dst.path =
2604 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; 2604 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
2605 net->ipv6.ip6_blk_hole_entry->u.dst.ops = ip6_dst_ops;
2605#endif 2606#endif
2606 2607
2607#ifdef CONFIG_PROC_FS 2608#ifdef CONFIG_PROC_FS
@@ -2640,13 +2641,20 @@ int __init ip6_route_init(void)
2640{ 2641{
2641 int ret; 2642 int ret;
2642 2643
2643 ip6_dst_ops.kmem_cachep = 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;
2650 ip6_dst_ops_template.kmem_cachep =
2644 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, 2651 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
2645 SLAB_HWCACHE_ALIGN, NULL); 2652 SLAB_HWCACHE_ALIGN, NULL);
2646 if (!ip6_dst_ops.kmem_cachep) 2653 if (!ip6_dst_ops_template.kmem_cachep)
2647 return -ENOMEM; 2654 goto out_ip6_dst_ops;
2648 2655
2649 ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; 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;
2650 2658
2651 ret = register_pernet_subsys(&ip6_route_net_ops); 2659 ret = register_pernet_subsys(&ip6_route_net_ops);
2652 if (ret) 2660 if (ret)
@@ -2697,7 +2705,9 @@ out_fib6_init:
2697out_register_subsys: 2705out_register_subsys:
2698 unregister_pernet_subsys(&ip6_route_net_ops); 2706 unregister_pernet_subsys(&ip6_route_net_ops);
2699out_kmem_cache: 2707out_kmem_cache:
2700 kmem_cache_destroy(ip6_dst_ops.kmem_cachep); 2708 kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
2709out_ip6_dst_ops:
2710 kfree(ip6_dst_ops);
2701 goto out; 2711 goto out;
2702} 2712}
2703 2713
@@ -2708,5 +2718,6 @@ void ip6_route_cleanup(void)
2708 xfrm6_fini(); 2718 xfrm6_fini();
2709 fib6_gc_cleanup(); 2719 fib6_gc_cleanup();
2710 unregister_pernet_subsys(&ip6_route_net_ops); 2720 unregister_pernet_subsys(&ip6_route_net_ops);
2711 kmem_cache_destroy(ip6_dst_ops.kmem_cachep); 2721 kmem_cache_destroy(ip6_dst_ops->kmem_cachep);
2722 kfree(ip6_dst_ops);
2712} 2723}