diff options
-rw-r--r-- | include/net/ip6_route.h | 2 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 56 | ||||
-rw-r--r-- | net/ipv6/route.c | 5 |
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); |
79 | extern int icmp6_dst_gc(int *more); | 79 | extern int icmp6_dst_gc(int *more); |
80 | 80 | ||
81 | extern void fib6_force_start_gc(void); | 81 | extern void fib6_force_start_gc(struct net *net); |
82 | 82 | ||
83 | extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | 83 | extern 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 | ||
96 | static void fib6_gc_timer_cb(unsigned long arg); | 96 | static void fib6_gc_timer_cb(unsigned long arg); |
97 | 97 | ||
98 | static struct timer_list *ip6_fib_timer; | ||
99 | |||
100 | static struct fib6_walker_t fib6_walker_list = { | 98 | static 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 | ||
666 | static __inline__ void fib6_start_gc(struct rt6_info *rt) | 664 | static __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 | ||
674 | void fib6_force_start_gc(void) | 672 | void 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) | |||
1473 | static int fib6_net_init(struct net *net) | 1471 | static 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 |
1514 | out_fib_table_hash: | 1520 | out_fib_table_hash: |
1515 | kfree(net->ipv6.fib_table_hash); | 1521 | kfree(net->ipv6.fib_table_hash); |
1522 | out_timer: | ||
1523 | kfree(timer); | ||
1516 | goto out; | 1524 | goto out; |
1517 | } | 1525 | } |
1518 | 1526 | ||
1519 | static void fib6_net_exit(struct net *net) | 1527 | static 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 = { | |||
1533 | int __init fib6_init(void) | 1543 | int __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 | ||
1560 | out_unregister_subsys: | 1564 | out_unregister_subsys: |
1561 | unregister_pernet_subsys(&fib6_net_ops); | 1565 | unregister_pernet_subsys(&fib6_net_ops); |
1562 | out_timer: | ||
1563 | kfree(ip6_fib_timer); | ||
1564 | out_kmem_cache_create: | 1566 | out_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 | ||
1569 | void fib6_gc_cleanup(void) | 1571 | void 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 | ||
957 | out: | 957 | out: |
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 | ||
1235 | out: | 1238 | out: |