aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--net/ipv6/ip6_fib.c56
-rw-r--r--net/ipv6/route.c5
4 files changed, 34 insertions, 30 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index a158abe71933..79dce496f4d4 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -78,7 +78,7 @@ extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
78 struct in6_addr *addr); 78 struct in6_addr *addr);
79extern int icmp6_dst_gc(int *more); 79extern int icmp6_dst_gc(int *more);
80 80
81extern void fib6_force_start_gc(void); 81extern void fib6_force_start_gc(struct net *net);
82 82
83extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, 83extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
84 const struct in6_addr *addr, 84 const struct in6_addr *addr,
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index b0653261c5a3..5279cd6a00ba 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -36,6 +36,7 @@ struct netns_ipv6 {
36 struct xt_table *ip6table_mangle; 36 struct xt_table *ip6table_mangle;
37 struct xt_table *ip6table_raw; 37 struct xt_table *ip6table_raw;
38#endif 38#endif
39 struct timer_list *ip6_fib_timer;
39 struct hlist_head *fib_table_hash; 40 struct hlist_head *fib_table_hash;
40 struct fib6_table *fib6_main_tbl; 41 struct fib6_table *fib6_main_tbl;
41#ifdef CONFIG_IPV6_MULTIPLE_TABLES 42#ifdef CONFIG_IPV6_MULTIPLE_TABLES
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 77ad1002c904..4aa67988f518 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -95,8 +95,6 @@ static __u32 rt_sernum;
95 95
96static void fib6_gc_timer_cb(unsigned long arg); 96static void fib6_gc_timer_cb(unsigned long arg);
97 97
98static struct timer_list *ip6_fib_timer;
99
100static struct fib6_walker_t fib6_walker_list = { 98static struct fib6_walker_t fib6_walker_list = {
101 .prev = &fib6_walker_list, 99 .prev = &fib6_walker_list,
102 .next = &fib6_walker_list, 100 .next = &fib6_walker_list,
@@ -663,19 +661,19 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
663 return 0; 661 return 0;
664} 662}
665 663
666static __inline__ void fib6_start_gc(struct rt6_info *rt) 664static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
667{ 665{
668 if (ip6_fib_timer->expires == 0 && 666 if (net->ipv6.ip6_fib_timer->expires == 0 &&
669 (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) 667 (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
670 mod_timer(ip6_fib_timer, jiffies + 668 mod_timer(net->ipv6.ip6_fib_timer, jiffies +
671 init_net.ipv6.sysctl.ip6_rt_gc_interval); 669 net->ipv6.sysctl.ip6_rt_gc_interval);
672} 670}
673 671
674void fib6_force_start_gc(void) 672void fib6_force_start_gc(struct net *net)
675{ 673{
676 if (ip6_fib_timer->expires == 0) 674 if (net->ipv6.ip6_fib_timer->expires == 0)
677 mod_timer(ip6_fib_timer, jiffies + 675 mod_timer(net->ipv6.ip6_fib_timer, jiffies +
678 init_net.ipv6.sysctl.ip6_rt_gc_interval); 676 net->ipv6.sysctl.ip6_rt_gc_interval);
679} 677}
680 678
681/* 679/*
@@ -762,7 +760,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
762 err = fib6_add_rt2node(fn, rt, info); 760 err = fib6_add_rt2node(fn, rt, info);
763 761
764 if (err == 0) { 762 if (err == 0) {
765 fib6_start_gc(rt); 763 fib6_start_gc(info->nl_net, rt);
766 if (!(rt->rt6i_flags&RTF_CACHE)) 764 if (!(rt->rt6i_flags&RTF_CACHE))
767 fib6_prune_clones(pn, rt); 765 fib6_prune_clones(pn, rt);
768 } 766 }
@@ -1443,7 +1441,7 @@ void fib6_run_gc(unsigned long expires, struct net *net)
1443 } else { 1441 } else {
1444 local_bh_disable(); 1442 local_bh_disable();
1445 if (!spin_trylock(&fib6_gc_lock)) { 1443 if (!spin_trylock(&fib6_gc_lock)) {
1446 mod_timer(ip6_fib_timer, jiffies + HZ); 1444 mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
1447 local_bh_enable(); 1445 local_bh_enable();
1448 return; 1446 return;
1449 } 1447 }
@@ -1456,11 +1454,11 @@ void fib6_run_gc(unsigned long expires, struct net *net)
1456 fib6_clean_all(net, fib6_age, 0, NULL); 1454 fib6_clean_all(net, fib6_age, 0, NULL);
1457 1455
1458 if (gc_args.more) 1456 if (gc_args.more)
1459 mod_timer(ip6_fib_timer, jiffies + 1457 mod_timer(net->ipv6.ip6_fib_timer, jiffies +
1460 net->ipv6.sysctl.ip6_rt_gc_interval); 1458 net->ipv6.sysctl.ip6_rt_gc_interval);
1461 else { 1459 else {
1462 del_timer(ip6_fib_timer); 1460 del_timer(net->ipv6.ip6_fib_timer);
1463 ip6_fib_timer->expires = 0; 1461 net->ipv6.ip6_fib_timer->expires = 0;
1464 } 1462 }
1465 spin_unlock_bh(&fib6_gc_lock); 1463 spin_unlock_bh(&fib6_gc_lock);
1466} 1464}
@@ -1473,13 +1471,21 @@ static void fib6_gc_timer_cb(unsigned long arg)
1473static int fib6_net_init(struct net *net) 1471static int fib6_net_init(struct net *net)
1474{ 1472{
1475 int ret; 1473 int ret;
1474 struct timer_list *timer;
1476 1475
1477 ret = -ENOMEM; 1476 ret = -ENOMEM;
1477 timer = kzalloc(sizeof(*timer), GFP_KERNEL);
1478 if (!timer)
1479 goto out;
1480
1481 setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
1482 net->ipv6.ip6_fib_timer = timer;
1483
1478 net->ipv6.fib_table_hash = 1484 net->ipv6.fib_table_hash =
1479 kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ, 1485 kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
1480 GFP_KERNEL); 1486 GFP_KERNEL);
1481 if (!net->ipv6.fib_table_hash) 1487 if (!net->ipv6.fib_table_hash)
1482 goto out; 1488 goto out_timer;
1483 1489
1484 net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), 1490 net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
1485 GFP_KERNEL); 1491 GFP_KERNEL);
@@ -1513,11 +1519,15 @@ out_fib6_main_tbl:
1513#endif 1519#endif
1514out_fib_table_hash: 1520out_fib_table_hash:
1515 kfree(net->ipv6.fib_table_hash); 1521 kfree(net->ipv6.fib_table_hash);
1522out_timer:
1523 kfree(timer);
1516 goto out; 1524 goto out;
1517 } 1525 }
1518 1526
1519static void fib6_net_exit(struct net *net) 1527static void fib6_net_exit(struct net *net)
1520{ 1528{
1529 del_timer(net->ipv6.ip6_fib_timer);
1530 kfree(net->ipv6.ip6_fib_timer);
1521#ifdef CONFIG_IPV6_MULTIPLE_TABLES 1531#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1522 kfree(net->ipv6.fib6_local_tbl); 1532 kfree(net->ipv6.fib6_local_tbl);
1523#endif 1533#endif
@@ -1533,6 +1543,7 @@ static struct pernet_operations fib6_net_ops = {
1533int __init fib6_init(void) 1543int __init fib6_init(void)
1534{ 1544{
1535 int ret = -ENOMEM; 1545 int ret = -ENOMEM;
1546
1536 fib6_node_kmem = kmem_cache_create("fib6_nodes", 1547 fib6_node_kmem = kmem_cache_create("fib6_nodes",
1537 sizeof(struct fib6_node), 1548 sizeof(struct fib6_node),
1538 0, SLAB_HWCACHE_ALIGN, 1549 0, SLAB_HWCACHE_ALIGN,
@@ -1540,16 +1551,9 @@ int __init fib6_init(void)
1540 if (!fib6_node_kmem) 1551 if (!fib6_node_kmem)
1541 goto out; 1552 goto out;
1542 1553
1543 ret = -ENOMEM;
1544 ip6_fib_timer = kzalloc(sizeof(*ip6_fib_timer), GFP_KERNEL);
1545 if (!ip6_fib_timer)
1546 goto out_kmem_cache_create;
1547
1548 setup_timer(ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)&init_net);
1549
1550 ret = register_pernet_subsys(&fib6_net_ops); 1554 ret = register_pernet_subsys(&fib6_net_ops);
1551 if (ret) 1555 if (ret)
1552 goto out_timer; 1556 goto out_kmem_cache_create;
1553 1557
1554 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); 1558 ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
1555 if (ret) 1559 if (ret)
@@ -1559,8 +1563,6 @@ out:
1559 1563
1560out_unregister_subsys: 1564out_unregister_subsys:
1561 unregister_pernet_subsys(&fib6_net_ops); 1565 unregister_pernet_subsys(&fib6_net_ops);
1562out_timer:
1563 kfree(ip6_fib_timer);
1564out_kmem_cache_create: 1566out_kmem_cache_create:
1565 kmem_cache_destroy(fib6_node_kmem); 1567 kmem_cache_destroy(fib6_node_kmem);
1566 goto out; 1568 goto out;
@@ -1568,8 +1570,6 @@ out_kmem_cache_create:
1568 1570
1569void fib6_gc_cleanup(void) 1571void fib6_gc_cleanup(void)
1570{ 1572{
1571 del_timer(ip6_fib_timer);
1572 kfree(ip6_fib_timer);
1573 unregister_pernet_subsys(&fib6_net_ops); 1573 unregister_pernet_subsys(&fib6_net_ops);
1574 kmem_cache_destroy(fib6_node_kmem); 1574 kmem_cache_destroy(fib6_node_kmem);
1575} 1575}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index fd44721abebb..b13eb0111270 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -952,7 +952,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
952 icmp6_dst_gc_list = &rt->u.dst; 952 icmp6_dst_gc_list = &rt->u.dst;
953 spin_unlock_bh(&icmp6_dst_lock); 953 spin_unlock_bh(&icmp6_dst_lock);
954 954
955 fib6_force_start_gc(); 955 fib6_force_start_gc(dev->nd_net);
956 956
957out: 957out:
958 return &rt->u.dst; 958 return &rt->u.dst;
@@ -1230,6 +1230,9 @@ install_route:
1230 rt->u.dst.dev = dev; 1230 rt->u.dst.dev = dev;
1231 rt->rt6i_idev = idev; 1231 rt->rt6i_idev = idev;
1232 rt->rt6i_table = table; 1232 rt->rt6i_table = table;
1233
1234 cfg->fc_nlinfo.nl_net = dev->nd_net;
1235
1233 return __ip6_ins_rt(rt, &cfg->fc_nlinfo); 1236 return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
1234 1237
1235out: 1238out: