aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_fib.c
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2008-03-04 02:25:27 -0500
committerDavid S. Miller <davem@davemloft.net>2008-03-04 02:25:27 -0500
commit58f09b78b730cf0d936597272bf35b3d615e967c (patch)
tree6c7fb907dd7da48384087944c81368c216b841f1 /net/ipv6/ip6_fib.c
parente0b85590bc1b50c9bbef4dd4738d9995fb1d1f64 (diff)
[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 <dlezcano@fr.ibm.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r--net/ipv6/ip6_fib.c161
1 files changed, 93 insertions, 68 deletions
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)
166 dst_free(&rt->u.dst); 166 dst_free(&rt->u.dst);
167} 167}
168 168
169static struct fib6_table *fib6_main_tbl;
170
171#ifdef CONFIG_IPV6_MULTIPLE_TABLES 169#ifdef CONFIG_IPV6_MULTIPLE_TABLES
172#define FIB_TABLE_HASHSZ 256 170#define FIB_TABLE_HASHSZ 256
173#else 171#else
174#define FIB_TABLE_HASHSZ 1 172#define FIB_TABLE_HASHSZ 1
175#endif 173#endif
176static struct hlist_head *fib_table_hash;
177 174
178static void fib6_link_table(struct fib6_table *tb) 175static void fib6_link_table(struct net *net, struct fib6_table *tb)
179{ 176{
180 unsigned int h; 177 unsigned int h;
181 178
@@ -191,13 +188,11 @@ static void fib6_link_table(struct fib6_table *tb)
191 * No protection necessary, this is the only list mutatation 188 * No protection necessary, this is the only list mutatation
192 * operation, tables never disappear once they exist. 189 * operation, tables never disappear once they exist.
193 */ 190 */
194 hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]); 191 hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]);
195} 192}
196 193
197#ifdef CONFIG_IPV6_MULTIPLE_TABLES 194#ifdef CONFIG_IPV6_MULTIPLE_TABLES
198 195
199static struct fib6_table *fib6_local_tbl;
200
201static struct fib6_table *fib6_alloc_table(u32 id) 196static struct fib6_table *fib6_alloc_table(u32 id)
202{ 197{
203 struct fib6_table *table; 198 struct fib6_table *table;
@@ -212,26 +207,27 @@ static struct fib6_table *fib6_alloc_table(u32 id)
212 return table; 207 return table;
213} 208}
214 209
215struct fib6_table *fib6_new_table(u32 id) 210struct fib6_table *fib6_new_table(struct net *net, u32 id)
216{ 211{
217 struct fib6_table *tb; 212 struct fib6_table *tb;
218 213
219 if (id == 0) 214 if (id == 0)
220 id = RT6_TABLE_MAIN; 215 id = RT6_TABLE_MAIN;
221 tb = fib6_get_table(id); 216 tb = fib6_get_table(net, id);
222 if (tb) 217 if (tb)
223 return tb; 218 return tb;
224 219
225 tb = fib6_alloc_table(id); 220 tb = fib6_alloc_table(id);
226 if (tb != NULL) 221 if (tb != NULL)
227 fib6_link_table(tb); 222 fib6_link_table(net, tb);
228 223
229 return tb; 224 return tb;
230} 225}
231 226
232struct fib6_table *fib6_get_table(u32 id) 227struct fib6_table *fib6_get_table(struct net *net, u32 id)
233{ 228{
234 struct fib6_table *tb; 229 struct fib6_table *tb;
230 struct hlist_head *head;
235 struct hlist_node *node; 231 struct hlist_node *node;
236 unsigned int h; 232 unsigned int h;
237 233
@@ -239,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id)
239 id = RT6_TABLE_MAIN; 235 id = RT6_TABLE_MAIN;
240 h = id & (FIB_TABLE_HASHSZ - 1); 236 h = id & (FIB_TABLE_HASHSZ - 1);
241 rcu_read_lock(); 237 rcu_read_lock();
242 hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) { 238 head = &net->ipv6.fib_table_hash[h];
239 hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
243 if (tb->tb6_id == id) { 240 if (tb->tb6_id == id) {
244 rcu_read_unlock(); 241 rcu_read_unlock();
245 return tb; 242 return tb;
@@ -250,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id)
250 return NULL; 247 return NULL;
251} 248}
252 249
253static void __init fib6_tables_init(void) 250static void fib6_tables_init(struct net *net)
254{ 251{
255 fib6_link_table(fib6_main_tbl); 252 fib6_link_table(net, net->ipv6.fib6_main_tbl);
256 fib6_link_table(fib6_local_tbl); 253 fib6_link_table(net, net->ipv6.fib6_local_tbl);
257} 254}
258
259#else 255#else
260 256
261struct fib6_table *fib6_new_table(u32 id) 257struct fib6_table *fib6_new_table(struct net *net, u32 id)
262{ 258{
263 return fib6_get_table(id); 259 return fib6_get_table(net, id);
264} 260}
265 261
266struct fib6_table *fib6_get_table(u32 id) 262struct fib6_table *fib6_get_table(struct net *net, u32 id)
267{ 263{
268 return fib6_main_tbl; 264 return net->ipv6.fib6_main_tbl;
269} 265}
270 266
271struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, 267struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
272 pol_lookup_t lookup) 268 int flags, pol_lookup_t lookup)
273{ 269{
274 return (struct dst_entry *) lookup(fib6_main_tbl, fl, flags); 270 return (struct dst_entry *) lookup(net->ipv6.fib6_main_tbl, fl, flags);
275} 271}
276 272
277static void __init fib6_tables_init(void) 273static void fib6_tables_init(struct net *net)
278{ 274{
279 fib6_link_table(fib6_main_tbl); 275 fib6_link_table(net, net->ipv6.fib6_main_tbl);
280} 276}
281 277
282#endif 278#endif
@@ -357,11 +353,9 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
357 struct fib6_walker_t *w; 353 struct fib6_walker_t *w;
358 struct fib6_table *tb; 354 struct fib6_table *tb;
359 struct hlist_node *node; 355 struct hlist_node *node;
356 struct hlist_head *head;
360 int res = 0; 357 int res = 0;
361 358
362 if (net != &init_net)
363 return 0;
364
365 s_h = cb->args[0]; 359 s_h = cb->args[0];
366 s_e = cb->args[1]; 360 s_e = cb->args[1];
367 361
@@ -390,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
390 384
391 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { 385 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
392 e = 0; 386 e = 0;
393 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) { 387 head = &net->ipv6.fib_table_hash[h];
388 hlist_for_each_entry(tb, node, head, tb6_hlist) {
394 if (e < s_e) 389 if (e < s_e)
395 goto next; 390 goto next;
396 res = fib6_dump_table(tb, skb, cb); 391 res = fib6_dump_table(tb, skb, cb);
@@ -1360,12 +1355,13 @@ void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
1360{ 1355{
1361 struct fib6_table *table; 1356 struct fib6_table *table;
1362 struct hlist_node *node; 1357 struct hlist_node *node;
1358 struct hlist_head *head;
1363 unsigned int h; 1359 unsigned int h;
1364 1360
1365 rcu_read_lock(); 1361 rcu_read_lock();
1366 for (h = 0; h < FIB_TABLE_HASHSZ; h++) { 1362 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
1367 hlist_for_each_entry_rcu(table, node, &fib_table_hash[h], 1363 head = &init_net.ipv6.fib_table_hash[h];
1368 tb6_hlist) { 1364 hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
1369 write_lock_bh(&table->tb6_lock); 1365 write_lock_bh(&table->tb6_lock);
1370 fib6_clean_tree(&table->tb6_root, func, prune, arg); 1366 fib6_clean_tree(&table->tb6_root, func, prune, arg);
1371 write_unlock_bh(&table->tb6_lock); 1367 write_unlock_bh(&table->tb6_lock);
@@ -1466,55 +1462,88 @@ void fib6_run_gc(unsigned long dummy)
1466 spin_unlock_bh(&fib6_gc_lock); 1462 spin_unlock_bh(&fib6_gc_lock);
1467} 1463}
1468 1464
1469int __init fib6_init(void) 1465static int fib6_net_init(struct net *net)
1470{ 1466{
1471 int ret = -ENOMEM; 1467 int ret;
1472 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1473 sizeof(struct fib6_node),
1474 0, SLAB_HWCACHE_ALIGN,
1475 NULL);
1476 if (!fib6_node_kmem)
1477 goto out;
1478 1468
1479 fib_table_hash = kzalloc(sizeof(*fib_table_hash)*FIB_TABLE_HASHSZ, 1469 ret = -ENOMEM;
1480 GFP_KERNEL); 1470 net->ipv6.fib_table_hash =
1481 if (!fib_table_hash) 1471 kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
1482 goto out_kmem_cache_create; 1472 GFP_KERNEL);
1473 if (!net->ipv6.fib_table_hash)
1474 goto out;
1483 1475
1484 fib6_main_tbl = kzalloc(sizeof(*fib6_main_tbl), GFP_KERNEL); 1476 net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
1485 if (!fib6_main_tbl) 1477 GFP_KERNEL);
1478 if (!net->ipv6.fib6_main_tbl)
1486 goto out_fib_table_hash; 1479 goto out_fib_table_hash;
1487 1480
1488 fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; 1481 net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
1489 fib6_main_tbl->tb6_root.leaf = &ip6_null_entry; 1482 net->ipv6.fib6_main_tbl->tb6_root.leaf = &ip6_null_entry;
1490 fib6_main_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 1483 net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
1484 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1491 1485
1492#ifdef CONFIG_IPV6_MULTIPLE_TABLES 1486#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1493 fib6_local_tbl = kzalloc(sizeof(*fib6_local_tbl), GFP_KERNEL); 1487 net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl),
1494 if (!fib6_local_tbl) 1488 GFP_KERNEL);
1489 if (!net->ipv6.fib6_local_tbl)
1495 goto out_fib6_main_tbl; 1490 goto out_fib6_main_tbl;
1496 1491 net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
1497 fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; 1492 net->ipv6.fib6_local_tbl->tb6_root.leaf = &ip6_null_entry;
1498 fib6_local_tbl->tb6_root.leaf = &ip6_null_entry; 1493 net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
1499 fib6_local_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 1494 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1500#endif 1495#endif
1496 fib6_tables_init(net);
1501 1497
1502 fib6_tables_init(); 1498 ret = 0;
1503
1504 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
1505 if (ret)
1506 goto out_fib6_local_tbl;
1507out: 1499out:
1508 return ret; 1500 return ret;
1509 1501
1510out_fib6_local_tbl:
1511#ifdef CONFIG_IPV6_MULTIPLE_TABLES 1502#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1512 kfree(fib6_local_tbl);
1513out_fib6_main_tbl: 1503out_fib6_main_tbl:
1504 kfree(net->ipv6.fib6_main_tbl);
1514#endif 1505#endif
1515 kfree(fib6_main_tbl);
1516out_fib_table_hash: 1506out_fib_table_hash:
1517 kfree(fib_table_hash); 1507 kfree(net->ipv6.fib_table_hash);
1508 goto out;
1509 }
1510
1511static void fib6_net_exit(struct net *net)
1512{
1513#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1514 kfree(net->ipv6.fib6_local_tbl);
1515#endif
1516 kfree(net->ipv6.fib6_main_tbl);
1517 kfree(net->ipv6.fib_table_hash);
1518}
1519
1520static struct pernet_operations fib6_net_ops = {
1521 .init = fib6_net_init,
1522 .exit = fib6_net_exit,
1523};
1524
1525int __init fib6_init(void)
1526{
1527 int ret = -ENOMEM;
1528 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1529 sizeof(struct fib6_node),
1530 0, SLAB_HWCACHE_ALIGN,
1531 NULL);
1532 if (!fib6_node_kmem)
1533 goto out;
1534
1535 ret = register_pernet_subsys(&fib6_net_ops);
1536 if (ret)
1537 goto out_kmem_cache_create;
1538
1539 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
1540 if (ret)
1541 goto out_unregister_subsys;
1542out:
1543 return ret;
1544
1545out_unregister_subsys:
1546 unregister_pernet_subsys(&fib6_net_ops);
1518out_kmem_cache_create: 1547out_kmem_cache_create:
1519 kmem_cache_destroy(fib6_node_kmem); 1548 kmem_cache_destroy(fib6_node_kmem);
1520 goto out; 1549 goto out;
@@ -1523,10 +1552,6 @@ out_kmem_cache_create:
1523void fib6_gc_cleanup(void) 1552void fib6_gc_cleanup(void)
1524{ 1553{
1525 del_timer(&ip6_fib_timer); 1554 del_timer(&ip6_fib_timer);
1526#ifdef CONFIG_IPV6_MULTIPLE_TABLES 1555 unregister_pernet_subsys(&fib6_net_ops);
1527 kfree(fib6_local_tbl);
1528#endif
1529 kfree(fib6_main_tbl);
1530 kfree(fib_table_hash);
1531 kmem_cache_destroy(fib6_node_kmem); 1556 kmem_cache_destroy(fib6_node_kmem);
1532} 1557}