aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2008-03-04 02:31:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-03-04 02:31:11 -0500
commit63152fc0de4dfe83da543bf133cef73d885a50fc (patch)
tree2b6546f2ebd5b3fa6d48bfd7ca4085d0f96e771f
parent450d19f8ab35fad4ef2b129cb383a5b8d1326611 (diff)
[NETNS][IPV6] ip6_fib - gc timer per namespace
Move the timer initialization at the network namespace creation and store the network namespace in the timer argument. That enables multiple timers (one per network namespace) to do garbage collecting. 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>
-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: