diff options
author | Patrick McHardy <kaber@trash.net> | 2010-04-13 01:03:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-13 17:49:32 -0400 |
commit | e258beb22f4d3ea3dc88586ffc9c990d0eb03380 (patch) | |
tree | 7bd4dc984757894cbfb355189e9172a4a566596c /net/ipv4/ipmr.c | |
parent | f74e49b5613206fb18468bdc9509a1db746aa01b (diff) |
ipv4: ipmr: move unres_queue and timer to per-namespace data
The unres_queue is currently shared between all namespaces. Following patches
will additionally allow to create multiple multicast routing tables in each
namespace. Having a single shared queue for all these users seems to excessive,
move the queue and the cleanup timer to the per-namespace data to unshare it.
As a side-effect, this fixes a bug in the seq file iteration functions: the
first entry returned is always from the current namespace, entries returned
after that may belong to any namespace.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 70 |
1 files changed, 29 insertions, 41 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9d4f6d1340a4..d6aa65e2b08f 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -80,8 +80,6 @@ static DEFINE_RWLOCK(mrt_lock); | |||
80 | 80 | ||
81 | #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) | 81 | #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) |
82 | 82 | ||
83 | static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ | ||
84 | |||
85 | /* Special spinlock for queue of unresolved entries */ | 83 | /* Special spinlock for queue of unresolved entries */ |
86 | static DEFINE_SPINLOCK(mfc_unres_lock); | 84 | static DEFINE_SPINLOCK(mfc_unres_lock); |
87 | 85 | ||
@@ -100,8 +98,6 @@ static int ipmr_cache_report(struct net *net, | |||
100 | struct sk_buff *pkt, vifi_t vifi, int assert); | 98 | struct sk_buff *pkt, vifi_t vifi, int assert); |
101 | static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); | 99 | static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); |
102 | 100 | ||
103 | static struct timer_list ipmr_expire_timer; | ||
104 | |||
105 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ | 101 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ |
106 | 102 | ||
107 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | 103 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) |
@@ -364,25 +360,26 @@ static void ipmr_destroy_unres(struct mfc_cache *c) | |||
364 | } | 360 | } |
365 | 361 | ||
366 | 362 | ||
367 | /* Single timer process for all the unresolved queue. */ | 363 | /* Timer process for the unresolved queue. */ |
368 | 364 | ||
369 | static void ipmr_expire_process(unsigned long dummy) | 365 | static void ipmr_expire_process(unsigned long arg) |
370 | { | 366 | { |
367 | struct net *net = (struct net *)arg; | ||
371 | unsigned long now; | 368 | unsigned long now; |
372 | unsigned long expires; | 369 | unsigned long expires; |
373 | struct mfc_cache *c, **cp; | 370 | struct mfc_cache *c, **cp; |
374 | 371 | ||
375 | if (!spin_trylock(&mfc_unres_lock)) { | 372 | if (!spin_trylock(&mfc_unres_lock)) { |
376 | mod_timer(&ipmr_expire_timer, jiffies+HZ/10); | 373 | mod_timer(&net->ipv4.ipmr_expire_timer, jiffies+HZ/10); |
377 | return; | 374 | return; |
378 | } | 375 | } |
379 | 376 | ||
380 | if (mfc_unres_queue == NULL) | 377 | if (net->ipv4.mfc_unres_queue == NULL) |
381 | goto out; | 378 | goto out; |
382 | 379 | ||
383 | now = jiffies; | 380 | now = jiffies; |
384 | expires = 10*HZ; | 381 | expires = 10*HZ; |
385 | cp = &mfc_unres_queue; | 382 | cp = &net->ipv4.mfc_unres_queue; |
386 | 383 | ||
387 | while ((c=*cp) != NULL) { | 384 | while ((c=*cp) != NULL) { |
388 | if (time_after(c->mfc_un.unres.expires, now)) { | 385 | if (time_after(c->mfc_un.unres.expires, now)) { |
@@ -398,8 +395,8 @@ static void ipmr_expire_process(unsigned long dummy) | |||
398 | ipmr_destroy_unres(c); | 395 | ipmr_destroy_unres(c); |
399 | } | 396 | } |
400 | 397 | ||
401 | if (mfc_unres_queue != NULL) | 398 | if (net->ipv4.mfc_unres_queue != NULL) |
402 | mod_timer(&ipmr_expire_timer, jiffies + expires); | 399 | mod_timer(&net->ipv4.ipmr_expire_timer, jiffies + expires); |
403 | 400 | ||
404 | out: | 401 | out: |
405 | spin_unlock(&mfc_unres_lock); | 402 | spin_unlock(&mfc_unres_lock); |
@@ -708,9 +705,8 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | |||
708 | const struct iphdr *iph = ip_hdr(skb); | 705 | const struct iphdr *iph = ip_hdr(skb); |
709 | 706 | ||
710 | spin_lock_bh(&mfc_unres_lock); | 707 | spin_lock_bh(&mfc_unres_lock); |
711 | for (c=mfc_unres_queue; c; c=c->next) { | 708 | for (c=net->ipv4.mfc_unres_queue; c; c=c->next) { |
712 | if (net_eq(mfc_net(c), net) && | 709 | if (c->mfc_mcastgrp == iph->daddr && |
713 | c->mfc_mcastgrp == iph->daddr && | ||
714 | c->mfc_origin == iph->saddr) | 710 | c->mfc_origin == iph->saddr) |
715 | break; | 711 | break; |
716 | } | 712 | } |
@@ -751,10 +747,10 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | |||
751 | } | 747 | } |
752 | 748 | ||
753 | atomic_inc(&net->ipv4.cache_resolve_queue_len); | 749 | atomic_inc(&net->ipv4.cache_resolve_queue_len); |
754 | c->next = mfc_unres_queue; | 750 | c->next = net->ipv4.mfc_unres_queue; |
755 | mfc_unres_queue = c; | 751 | net->ipv4.mfc_unres_queue = c; |
756 | 752 | ||
757 | mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); | 753 | mod_timer(&net->ipv4.ipmr_expire_timer, c->mfc_un.unres.expires); |
758 | } | 754 | } |
759 | 755 | ||
760 | /* | 756 | /* |
@@ -849,18 +845,17 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | |||
849 | * need to send on the frames and tidy up. | 845 | * need to send on the frames and tidy up. |
850 | */ | 846 | */ |
851 | spin_lock_bh(&mfc_unres_lock); | 847 | spin_lock_bh(&mfc_unres_lock); |
852 | for (cp = &mfc_unres_queue; (uc=*cp) != NULL; | 848 | for (cp = &net->ipv4.mfc_unres_queue; (uc=*cp) != NULL; |
853 | cp = &uc->next) { | 849 | cp = &uc->next) { |
854 | if (net_eq(mfc_net(uc), net) && | 850 | if (uc->mfc_origin == c->mfc_origin && |
855 | uc->mfc_origin == c->mfc_origin && | ||
856 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { | 851 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { |
857 | *cp = uc->next; | 852 | *cp = uc->next; |
858 | atomic_dec(&net->ipv4.cache_resolve_queue_len); | 853 | atomic_dec(&net->ipv4.cache_resolve_queue_len); |
859 | break; | 854 | break; |
860 | } | 855 | } |
861 | } | 856 | } |
862 | if (mfc_unres_queue == NULL) | 857 | if (net->ipv4.mfc_unres_queue == NULL) |
863 | del_timer(&ipmr_expire_timer); | 858 | del_timer(&net->ipv4.ipmr_expire_timer); |
864 | spin_unlock_bh(&mfc_unres_lock); | 859 | spin_unlock_bh(&mfc_unres_lock); |
865 | 860 | ||
866 | if (uc) { | 861 | if (uc) { |
@@ -912,14 +907,9 @@ static void mroute_clean_tables(struct net *net) | |||
912 | struct mfc_cache *c, **cp; | 907 | struct mfc_cache *c, **cp; |
913 | 908 | ||
914 | spin_lock_bh(&mfc_unres_lock); | 909 | spin_lock_bh(&mfc_unres_lock); |
915 | cp = &mfc_unres_queue; | 910 | cp = &net->ipv4.mfc_unres_queue; |
916 | while ((c = *cp) != NULL) { | 911 | while ((c = *cp) != NULL) { |
917 | if (!net_eq(mfc_net(c), net)) { | ||
918 | cp = &c->next; | ||
919 | continue; | ||
920 | } | ||
921 | *cp = c->next; | 912 | *cp = c->next; |
922 | |||
923 | ipmr_destroy_unres(c); | 913 | ipmr_destroy_unres(c); |
924 | } | 914 | } |
925 | spin_unlock_bh(&mfc_unres_lock); | 915 | spin_unlock_bh(&mfc_unres_lock); |
@@ -1819,11 +1809,10 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, | |||
1819 | return mfc; | 1809 | return mfc; |
1820 | read_unlock(&mrt_lock); | 1810 | read_unlock(&mrt_lock); |
1821 | 1811 | ||
1822 | it->cache = &mfc_unres_queue; | 1812 | it->cache = &net->ipv4.mfc_unres_queue; |
1823 | spin_lock_bh(&mfc_unres_lock); | 1813 | spin_lock_bh(&mfc_unres_lock); |
1824 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 1814 | for (mfc = net->ipv4.mfc_unres_queue; mfc; mfc = mfc->next) |
1825 | if (net_eq(mfc_net(mfc), net) && | 1815 | if (pos-- == 0) |
1826 | pos-- == 0) | ||
1827 | return mfc; | 1816 | return mfc; |
1828 | spin_unlock_bh(&mfc_unres_lock); | 1817 | spin_unlock_bh(&mfc_unres_lock); |
1829 | 1818 | ||
@@ -1857,7 +1846,7 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1857 | if (mfc->next) | 1846 | if (mfc->next) |
1858 | return mfc->next; | 1847 | return mfc->next; |
1859 | 1848 | ||
1860 | if (it->cache == &mfc_unres_queue) | 1849 | if (it->cache == &net->ipv4.mfc_unres_queue) |
1861 | goto end_of_list; | 1850 | goto end_of_list; |
1862 | 1851 | ||
1863 | BUG_ON(it->cache != net->ipv4.mfc_cache_array); | 1852 | BUG_ON(it->cache != net->ipv4.mfc_cache_array); |
@@ -1870,13 +1859,11 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1870 | 1859 | ||
1871 | /* exhausted cache_array, show unresolved */ | 1860 | /* exhausted cache_array, show unresolved */ |
1872 | read_unlock(&mrt_lock); | 1861 | read_unlock(&mrt_lock); |
1873 | it->cache = &mfc_unres_queue; | 1862 | it->cache = &net->ipv4.mfc_unres_queue; |
1874 | it->ct = 0; | 1863 | it->ct = 0; |
1875 | 1864 | ||
1876 | spin_lock_bh(&mfc_unres_lock); | 1865 | spin_lock_bh(&mfc_unres_lock); |
1877 | mfc = mfc_unres_queue; | 1866 | mfc = net->ipv4.mfc_unres_queue; |
1878 | while (mfc && !net_eq(mfc_net(mfc), net)) | ||
1879 | mfc = mfc->next; | ||
1880 | if (mfc) | 1867 | if (mfc) |
1881 | return mfc; | 1868 | return mfc; |
1882 | 1869 | ||
@@ -1892,7 +1879,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | |||
1892 | struct ipmr_mfc_iter *it = seq->private; | 1879 | struct ipmr_mfc_iter *it = seq->private; |
1893 | struct net *net = seq_file_net(seq); | 1880 | struct net *net = seq_file_net(seq); |
1894 | 1881 | ||
1895 | if (it->cache == &mfc_unres_queue) | 1882 | if (it->cache == &net->ipv4.mfc_unres_queue) |
1896 | spin_unlock_bh(&mfc_unres_lock); | 1883 | spin_unlock_bh(&mfc_unres_lock); |
1897 | else if (it->cache == net->ipv4.mfc_cache_array) | 1884 | else if (it->cache == net->ipv4.mfc_cache_array) |
1898 | read_unlock(&mrt_lock); | 1885 | read_unlock(&mrt_lock); |
@@ -1915,7 +1902,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
1915 | (unsigned long) mfc->mfc_origin, | 1902 | (unsigned long) mfc->mfc_origin, |
1916 | mfc->mfc_parent); | 1903 | mfc->mfc_parent); |
1917 | 1904 | ||
1918 | if (it->cache != &mfc_unres_queue) { | 1905 | if (it->cache != &net->ipv4.mfc_unres_queue) { |
1919 | seq_printf(seq, " %8lu %8lu %8lu", | 1906 | seq_printf(seq, " %8lu %8lu %8lu", |
1920 | mfc->mfc_un.res.pkt, | 1907 | mfc->mfc_un.res.pkt, |
1921 | mfc->mfc_un.res.bytes, | 1908 | mfc->mfc_un.res.bytes, |
@@ -1992,6 +1979,9 @@ static int __net_init ipmr_net_init(struct net *net) | |||
1992 | goto fail_mfc_cache; | 1979 | goto fail_mfc_cache; |
1993 | } | 1980 | } |
1994 | 1981 | ||
1982 | setup_timer(&net->ipv4.ipmr_expire_timer, ipmr_expire_process, | ||
1983 | (unsigned long)net); | ||
1984 | |||
1995 | #ifdef CONFIG_IP_PIMSM | 1985 | #ifdef CONFIG_IP_PIMSM |
1996 | net->ipv4.mroute_reg_vif_num = -1; | 1986 | net->ipv4.mroute_reg_vif_num = -1; |
1997 | #endif | 1987 | #endif |
@@ -2047,7 +2037,6 @@ int __init ip_mr_init(void) | |||
2047 | if (err) | 2037 | if (err) |
2048 | goto reg_pernet_fail; | 2038 | goto reg_pernet_fail; |
2049 | 2039 | ||
2050 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | ||
2051 | err = register_netdevice_notifier(&ip_mr_notifier); | 2040 | err = register_netdevice_notifier(&ip_mr_notifier); |
2052 | if (err) | 2041 | if (err) |
2053 | goto reg_notif_fail; | 2042 | goto reg_notif_fail; |
@@ -2065,7 +2054,6 @@ add_proto_fail: | |||
2065 | unregister_netdevice_notifier(&ip_mr_notifier); | 2054 | unregister_netdevice_notifier(&ip_mr_notifier); |
2066 | #endif | 2055 | #endif |
2067 | reg_notif_fail: | 2056 | reg_notif_fail: |
2068 | del_timer(&ipmr_expire_timer); | ||
2069 | unregister_pernet_subsys(&ipmr_net_ops); | 2057 | unregister_pernet_subsys(&ipmr_net_ops); |
2070 | reg_pernet_fail: | 2058 | reg_pernet_fail: |
2071 | kmem_cache_destroy(mrt_cachep); | 2059 | kmem_cache_destroy(mrt_cachep); |