diff options
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 47 |
2 files changed, 32 insertions, 16 deletions
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 4ab0cb01a7a..14c1bbe68a8 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -57,6 +57,7 @@ struct netns_ipv6 { | |||
57 | struct sock *igmp_sk; | 57 | struct sock *igmp_sk; |
58 | #ifdef CONFIG_IPV6_MROUTE | 58 | #ifdef CONFIG_IPV6_MROUTE |
59 | struct sock *mroute6_sk; | 59 | struct sock *mroute6_sk; |
60 | struct mfc6_cache **mfc6_cache_array; | ||
60 | struct mif_device *vif6_table; | 61 | struct mif_device *vif6_table; |
61 | int maxvif; | 62 | int maxvif; |
62 | #endif | 63 | #endif |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index fab5aba28a2..287e526ba03 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -68,8 +68,6 @@ static int mroute_do_pim; | |||
68 | #define mroute_do_pim 0 | 68 | #define mroute_do_pim 0 |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */ | ||
72 | |||
73 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ | 71 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ |
74 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ | 72 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ |
75 | 73 | ||
@@ -109,10 +107,11 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | |||
109 | { | 107 | { |
110 | struct mfc6_cache *mfc; | 108 | struct mfc6_cache *mfc; |
111 | 109 | ||
112 | it->cache = mfc6_cache_array; | 110 | it->cache = init_net.ipv6.mfc6_cache_array; |
113 | read_lock(&mrt_lock); | 111 | read_lock(&mrt_lock); |
114 | for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++) | 112 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) |
115 | for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next) | 113 | for (mfc = init_net.ipv6.mfc6_cache_array[it->ct]; |
114 | mfc; mfc = mfc->next) | ||
116 | if (pos-- == 0) | 115 | if (pos-- == 0) |
117 | return mfc; | 116 | return mfc; |
118 | read_unlock(&mrt_lock); | 117 | read_unlock(&mrt_lock); |
@@ -243,10 +242,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
243 | if (it->cache == &mfc_unres_queue) | 242 | if (it->cache == &mfc_unres_queue) |
244 | goto end_of_list; | 243 | goto end_of_list; |
245 | 244 | ||
246 | BUG_ON(it->cache != mfc6_cache_array); | 245 | BUG_ON(it->cache != init_net.ipv6.mfc6_cache_array); |
247 | 246 | ||
248 | while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) { | 247 | while (++it->ct < MFC6_LINES) { |
249 | mfc = mfc6_cache_array[it->ct]; | 248 | mfc = init_net.ipv6.mfc6_cache_array[it->ct]; |
250 | if (mfc) | 249 | if (mfc) |
251 | return mfc; | 250 | return mfc; |
252 | } | 251 | } |
@@ -274,7 +273,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | |||
274 | 273 | ||
275 | if (it->cache == &mfc_unres_queue) | 274 | if (it->cache == &mfc_unres_queue) |
276 | spin_unlock_bh(&mfc_unres_lock); | 275 | spin_unlock_bh(&mfc_unres_lock); |
277 | else if (it->cache == mfc6_cache_array) | 276 | else if (it->cache == init_net.ipv6.mfc6_cache_array) |
278 | read_unlock(&mrt_lock); | 277 | read_unlock(&mrt_lock); |
279 | } | 278 | } |
280 | 279 | ||
@@ -680,7 +679,7 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a | |||
680 | int line = MFC6_HASH(mcastgrp, origin); | 679 | int line = MFC6_HASH(mcastgrp, origin); |
681 | struct mfc6_cache *c; | 680 | struct mfc6_cache *c; |
682 | 681 | ||
683 | for (c = mfc6_cache_array[line]; c; c = c->next) { | 682 | for (c = init_net.ipv6.mfc6_cache_array[line]; c; c = c->next) { |
684 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && | 683 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && |
685 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) | 684 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) |
686 | break; | 685 | break; |
@@ -925,7 +924,8 @@ static int ip6mr_mfc_delete(struct mf6cctl *mfc) | |||
925 | 924 | ||
926 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 925 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
927 | 926 | ||
928 | for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { | 927 | for (cp = &init_net.ipv6.mfc6_cache_array[line]; |
928 | (c = *cp) != NULL; cp = &c->next) { | ||
929 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 929 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
930 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { | 930 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { |
931 | write_lock_bh(&mrt_lock); | 931 | write_lock_bh(&mrt_lock); |
@@ -978,12 +978,26 @@ static int __net_init ip6mr_net_init(struct net *net) | |||
978 | err = -ENOMEM; | 978 | err = -ENOMEM; |
979 | goto fail; | 979 | goto fail; |
980 | } | 980 | } |
981 | |||
982 | /* Forwarding cache */ | ||
983 | net->ipv6.mfc6_cache_array = kcalloc(MFC6_LINES, | ||
984 | sizeof(struct mfc6_cache *), | ||
985 | GFP_KERNEL); | ||
986 | if (!net->ipv6.mfc6_cache_array) { | ||
987 | err = -ENOMEM; | ||
988 | goto fail_mfc6_cache; | ||
989 | } | ||
990 | return 0; | ||
991 | |||
992 | fail_mfc6_cache: | ||
993 | kfree(net->ipv6.vif6_table); | ||
981 | fail: | 994 | fail: |
982 | return err; | 995 | return err; |
983 | } | 996 | } |
984 | 997 | ||
985 | static void __net_exit ip6mr_net_exit(struct net *net) | 998 | static void __net_exit ip6mr_net_exit(struct net *net) |
986 | { | 999 | { |
1000 | kfree(net->ipv6.mfc6_cache_array); | ||
987 | kfree(net->ipv6.vif6_table); | 1001 | kfree(net->ipv6.vif6_table); |
988 | } | 1002 | } |
989 | 1003 | ||
@@ -1062,7 +1076,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) | |||
1062 | 1076 | ||
1063 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 1077 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
1064 | 1078 | ||
1065 | for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { | 1079 | for (cp = &init_net.ipv6.mfc6_cache_array[line]; |
1080 | (c = *cp) != NULL; cp = &c->next) { | ||
1066 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 1081 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
1067 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) | 1082 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) |
1068 | break; | 1083 | break; |
@@ -1093,8 +1108,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) | |||
1093 | c->mfc_flags |= MFC_STATIC; | 1108 | c->mfc_flags |= MFC_STATIC; |
1094 | 1109 | ||
1095 | write_lock_bh(&mrt_lock); | 1110 | write_lock_bh(&mrt_lock); |
1096 | c->next = mfc6_cache_array[line]; | 1111 | c->next = init_net.ipv6.mfc6_cache_array[line]; |
1097 | mfc6_cache_array[line] = c; | 1112 | init_net.ipv6.mfc6_cache_array[line] = c; |
1098 | write_unlock_bh(&mrt_lock); | 1113 | write_unlock_bh(&mrt_lock); |
1099 | 1114 | ||
1100 | /* | 1115 | /* |
@@ -1140,10 +1155,10 @@ static void mroute_clean_tables(struct sock *sk) | |||
1140 | /* | 1155 | /* |
1141 | * Wipe the cache | 1156 | * Wipe the cache |
1142 | */ | 1157 | */ |
1143 | for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) { | 1158 | for (i = 0; i < MFC6_LINES; i++) { |
1144 | struct mfc6_cache *c, **cp; | 1159 | struct mfc6_cache *c, **cp; |
1145 | 1160 | ||
1146 | cp = &mfc6_cache_array[i]; | 1161 | cp = &init_net.ipv6.mfc6_cache_array[i]; |
1147 | while ((c = *cp) != NULL) { | 1162 | while ((c = *cp) != NULL) { |
1148 | if (c->mfc_flags & MFC_STATIC) { | 1163 | if (c->mfc_flags & MFC_STATIC) { |
1149 | cp = &c->next; | 1164 | cp = &c->next; |