aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r--net/ipv6/ip6_fib.c71
1 files changed, 48 insertions, 23 deletions
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)
166 dst_free(&rt->u.dst); 166 dst_free(&rt->u.dst);
167} 167}
168 168
169static struct fib6_table fib6_main_tbl = { 169static struct fib6_table *fib6_main_tbl;
170 .tb6_id = RT6_TABLE_MAIN,
171 .tb6_root = {
172 .leaf = &ip6_null_entry,
173 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
174 },
175};
176 170
177#ifdef CONFIG_IPV6_MULTIPLE_TABLES 171#ifdef CONFIG_IPV6_MULTIPLE_TABLES
178#define FIB_TABLE_HASHSZ 256 172#define FIB_TABLE_HASHSZ 256
179#else 173#else
180#define FIB_TABLE_HASHSZ 1 174#define FIB_TABLE_HASHSZ 1
181#endif 175#endif
182static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; 176static struct hlist_head *fib_table_hash;
183 177
184static void fib6_link_table(struct fib6_table *tb) 178static void fib6_link_table(struct fib6_table *tb)
185{ 179{
@@ -201,13 +195,8 @@ static void fib6_link_table(struct fib6_table *tb)
201} 195}
202 196
203#ifdef CONFIG_IPV6_MULTIPLE_TABLES 197#ifdef CONFIG_IPV6_MULTIPLE_TABLES
204static struct fib6_table fib6_local_tbl = { 198
205 .tb6_id = RT6_TABLE_LOCAL, 199static struct fib6_table *fib6_local_tbl;
206 .tb6_root = {
207 .leaf = &ip6_null_entry,
208 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
209 },
210};
211 200
212static struct fib6_table *fib6_alloc_table(u32 id) 201static struct fib6_table *fib6_alloc_table(u32 id)
213{ 202{
@@ -263,8 +252,8 @@ struct fib6_table *fib6_get_table(u32 id)
263 252
264static void __init fib6_tables_init(void) 253static void __init fib6_tables_init(void)
265{ 254{
266 fib6_link_table(&fib6_main_tbl); 255 fib6_link_table(fib6_main_tbl);
267 fib6_link_table(&fib6_local_tbl); 256 fib6_link_table(fib6_local_tbl);
268} 257}
269 258
270#else 259#else
@@ -276,18 +265,18 @@ struct fib6_table *fib6_new_table(u32 id)
276 265
277struct fib6_table *fib6_get_table(u32 id) 266struct fib6_table *fib6_get_table(u32 id)
278{ 267{
279 return &fib6_main_tbl; 268 return fib6_main_tbl;
280} 269}
281 270
282struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, 271struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
283 pol_lookup_t lookup) 272 pol_lookup_t lookup)
284{ 273{
285 return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags); 274 return (struct dst_entry *) lookup(fib6_main_tbl, fl, flags);
286} 275}
287 276
288static void __init fib6_tables_init(void) 277static void __init fib6_tables_init(void)
289{ 278{
290 fib6_link_table(&fib6_main_tbl); 279 fib6_link_table(fib6_main_tbl);
291} 280}
292 281
293#endif 282#endif
@@ -1479,22 +1468,53 @@ void fib6_run_gc(unsigned long dummy)
1479 1468
1480int __init fib6_init(void) 1469int __init fib6_init(void)
1481{ 1470{
1482 int ret; 1471 int ret = -ENOMEM;
1483 fib6_node_kmem = kmem_cache_create("fib6_nodes", 1472 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1484 sizeof(struct fib6_node), 1473 sizeof(struct fib6_node),
1485 0, SLAB_HWCACHE_ALIGN, 1474 0, SLAB_HWCACHE_ALIGN,
1486 NULL); 1475 NULL);
1487 if (!fib6_node_kmem) 1476 if (!fib6_node_kmem)
1488 return -ENOMEM; 1477 goto out;
1478
1479 fib_table_hash = kzalloc(sizeof(*fib_table_hash)*FIB_TABLE_HASHSZ,
1480 GFP_KERNEL);
1481 if (!fib_table_hash)
1482 goto out_kmem_cache_create;
1483
1484 fib6_main_tbl = kzalloc(sizeof(*fib6_main_tbl), GFP_KERNEL);
1485 if (!fib6_main_tbl)
1486 goto out_fib_table_hash;
1487
1488 fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
1489 fib6_main_tbl->tb6_root.leaf = &ip6_null_entry;
1490 fib6_main_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1491
1492#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1493 fib6_local_tbl = kzalloc(sizeof(*fib6_local_tbl), GFP_KERNEL);
1494 if (!fib6_local_tbl)
1495 goto out_fib6_main_tbl;
1496
1497 fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
1498 fib6_local_tbl->tb6_root.leaf = &ip6_null_entry;
1499 fib6_local_tbl->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1500#endif
1489 1501
1490 fib6_tables_init(); 1502 fib6_tables_init();
1491 1503
1492 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); 1504 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
1493 if (ret) 1505 if (ret)
1494 goto out_kmem_cache_create; 1506 goto out_fib6_local_tbl;
1495out: 1507out:
1496 return ret; 1508 return ret;
1497 1509
1510out_fib6_local_tbl:
1511#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1512 kfree(fib6_local_tbl);
1513out_fib6_main_tbl:
1514#endif
1515 kfree(fib6_main_tbl);
1516out_fib_table_hash:
1517 kfree(fib_table_hash);
1498out_kmem_cache_create: 1518out_kmem_cache_create:
1499 kmem_cache_destroy(fib6_node_kmem); 1519 kmem_cache_destroy(fib6_node_kmem);
1500 goto out; 1520 goto out;
@@ -1503,5 +1523,10 @@ out_kmem_cache_create:
1503void fib6_gc_cleanup(void) 1523void fib6_gc_cleanup(void)
1504{ 1524{
1505 del_timer(&ip6_fib_timer); 1525 del_timer(&ip6_fib_timer);
1526#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1527 kfree(fib6_local_tbl);
1528#endif
1529 kfree(fib6_main_tbl);
1530 kfree(fib_table_hash);
1506 kmem_cache_destroy(fib6_node_kmem); 1531 kmem_cache_destroy(fib6_node_kmem);
1507} 1532}