diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-01-22 09:02:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:10:34 -0500 |
commit | ac18e7509e7df327e30d6e073a787d922eaf211d (patch) | |
tree | 26be1582b59956c389a667d5426fdc538072795b | |
parent | 8d8354d2fb9277f165715a6e1cb92bcc89259975 (diff) |
[NETNS][FRAGS]: Make the inet_frag_queue lookup work in namespaces.
Since fragment management code is consolidated, we cannot have the
pointer from inet_frag_queue to struct net, since we must know what
king of fragment this is.
So, I introduce the netns_frags structure. This one is currently
empty, but will be eventually filled with per-namespace
attributes. Each inet_frag_queue is tagged with this one.
The conntrack_reasm is not "netns-izated", so it has one static
netns_frags instance to keep working in init namespace.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/inet_frag.h | 8 | ||||
-rw-r--r-- | include/net/netns/ipv4.h | 4 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 27 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 8 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 3 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 8 |
7 files changed, 38 insertions, 21 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 954def40897..8ab6df64a12 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h | |||
@@ -1,8 +1,12 @@ | |||
1 | #ifndef __NET_FRAG_H__ | 1 | #ifndef __NET_FRAG_H__ |
2 | #define __NET_FRAG_H__ | 2 | #define __NET_FRAG_H__ |
3 | 3 | ||
4 | struct netns_frags { | ||
5 | }; | ||
6 | |||
4 | struct inet_frag_queue { | 7 | struct inet_frag_queue { |
5 | struct hlist_node list; | 8 | struct hlist_node list; |
9 | struct netns_frags *net; | ||
6 | struct list_head lru_list; /* lru list member */ | 10 | struct list_head lru_list; /* lru list member */ |
7 | spinlock_t lock; | 11 | spinlock_t lock; |
8 | atomic_t refcnt; | 12 | atomic_t refcnt; |
@@ -55,8 +59,8 @@ void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); | |||
55 | void inet_frag_destroy(struct inet_frag_queue *q, | 59 | void inet_frag_destroy(struct inet_frag_queue *q, |
56 | struct inet_frags *f, int *work); | 60 | struct inet_frags *f, int *work); |
57 | int inet_frag_evictor(struct inet_frags *f); | 61 | int inet_frag_evictor(struct inet_frags *f); |
58 | struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key, | 62 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, |
59 | unsigned int hash); | 63 | struct inet_frags *f, void *key, unsigned int hash); |
60 | 64 | ||
61 | static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) | 65 | static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) |
62 | { | 66 | { |
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 3872aa7e294..80680e09443 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h | |||
@@ -5,6 +5,8 @@ | |||
5 | #ifndef __NETNS_IPV4_H__ | 5 | #ifndef __NETNS_IPV4_H__ |
6 | #define __NETNS_IPV4_H__ | 6 | #define __NETNS_IPV4_H__ |
7 | 7 | ||
8 | #include <net/inet_frag.h> | ||
9 | |||
8 | struct ctl_table_header; | 10 | struct ctl_table_header; |
9 | struct ipv4_devconf; | 11 | struct ipv4_devconf; |
10 | struct fib_rules_ops; | 12 | struct fib_rules_ops; |
@@ -22,5 +24,7 @@ struct netns_ipv4 { | |||
22 | #endif | 24 | #endif |
23 | struct hlist_head *fib_table_hash; | 25 | struct hlist_head *fib_table_hash; |
24 | struct sock *fibnl; | 26 | struct sock *fibnl; |
27 | |||
28 | struct netns_frags frags; | ||
25 | }; | 29 | }; |
26 | #endif | 30 | #endif |
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 06b4dc034bb..057c8e473a7 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -30,5 +30,6 @@ struct netns_ipv6 { | |||
30 | struct netns_sysctl_ipv6 sysctl; | 30 | struct netns_sysctl_ipv6 sysctl; |
31 | struct ipv6_devconf *devconf_all; | 31 | struct ipv6_devconf *devconf_all; |
32 | struct ipv6_devconf *devconf_dflt; | 32 | struct ipv6_devconf *devconf_dflt; |
33 | struct netns_frags frags; | ||
33 | }; | 34 | }; |
34 | #endif | 35 | #endif |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 737910767ff..158c5f60d02 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -174,8 +174,9 @@ int inet_frag_evictor(struct inet_frags *f) | |||
174 | } | 174 | } |
175 | EXPORT_SYMBOL(inet_frag_evictor); | 175 | EXPORT_SYMBOL(inet_frag_evictor); |
176 | 176 | ||
177 | static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in, | 177 | static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, |
178 | struct inet_frags *f, unsigned int hash, void *arg) | 178 | struct inet_frag_queue *qp_in, struct inet_frags *f, |
179 | unsigned int hash, void *arg) | ||
179 | { | 180 | { |
180 | struct inet_frag_queue *qp; | 181 | struct inet_frag_queue *qp; |
181 | #ifdef CONFIG_SMP | 182 | #ifdef CONFIG_SMP |
@@ -189,7 +190,7 @@ static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in, | |||
189 | * promoted read lock to write lock. | 190 | * promoted read lock to write lock. |
190 | */ | 191 | */ |
191 | hlist_for_each_entry(qp, n, &f->hash[hash], list) { | 192 | hlist_for_each_entry(qp, n, &f->hash[hash], list) { |
192 | if (f->match(qp, arg)) { | 193 | if (qp->net == nf && f->match(qp, arg)) { |
193 | atomic_inc(&qp->refcnt); | 194 | atomic_inc(&qp->refcnt); |
194 | write_unlock(&f->lock); | 195 | write_unlock(&f->lock); |
195 | qp_in->last_in |= COMPLETE; | 196 | qp_in->last_in |= COMPLETE; |
@@ -210,7 +211,8 @@ static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in, | |||
210 | return qp; | 211 | return qp; |
211 | } | 212 | } |
212 | 213 | ||
213 | static struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f, void *arg) | 214 | static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, |
215 | struct inet_frags *f, void *arg) | ||
214 | { | 216 | { |
215 | struct inet_frag_queue *q; | 217 | struct inet_frag_queue *q; |
216 | 218 | ||
@@ -223,31 +225,32 @@ static struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f, void *arg) | |||
223 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); | 225 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); |
224 | spin_lock_init(&q->lock); | 226 | spin_lock_init(&q->lock); |
225 | atomic_set(&q->refcnt, 1); | 227 | atomic_set(&q->refcnt, 1); |
228 | q->net = nf; | ||
226 | 229 | ||
227 | return q; | 230 | return q; |
228 | } | 231 | } |
229 | 232 | ||
230 | static struct inet_frag_queue *inet_frag_create(struct inet_frags *f, | 233 | static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, |
231 | void *arg, unsigned int hash) | 234 | struct inet_frags *f, void *arg, unsigned int hash) |
232 | { | 235 | { |
233 | struct inet_frag_queue *q; | 236 | struct inet_frag_queue *q; |
234 | 237 | ||
235 | q = inet_frag_alloc(f, arg); | 238 | q = inet_frag_alloc(nf, f, arg); |
236 | if (q == NULL) | 239 | if (q == NULL) |
237 | return NULL; | 240 | return NULL; |
238 | 241 | ||
239 | return inet_frag_intern(q, f, hash, arg); | 242 | return inet_frag_intern(nf, q, f, hash, arg); |
240 | } | 243 | } |
241 | 244 | ||
242 | struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key, | 245 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, |
243 | unsigned int hash) | 246 | struct inet_frags *f, void *key, unsigned int hash) |
244 | { | 247 | { |
245 | struct inet_frag_queue *q; | 248 | struct inet_frag_queue *q; |
246 | struct hlist_node *n; | 249 | struct hlist_node *n; |
247 | 250 | ||
248 | read_lock(&f->lock); | 251 | read_lock(&f->lock); |
249 | hlist_for_each_entry(q, n, &f->hash[hash], list) { | 252 | hlist_for_each_entry(q, n, &f->hash[hash], list) { |
250 | if (f->match(q, key)) { | 253 | if (q->net == nf && f->match(q, key)) { |
251 | atomic_inc(&q->refcnt); | 254 | atomic_inc(&q->refcnt); |
252 | read_unlock(&f->lock); | 255 | read_unlock(&f->lock); |
253 | return q; | 256 | return q; |
@@ -255,6 +258,6 @@ struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key, | |||
255 | } | 258 | } |
256 | read_unlock(&f->lock); | 259 | read_unlock(&f->lock); |
257 | 260 | ||
258 | return inet_frag_create(f, key, hash); | 261 | return inet_frag_create(nf, f, key, hash); |
259 | } | 262 | } |
260 | EXPORT_SYMBOL(inet_frag_find); | 263 | EXPORT_SYMBOL(inet_frag_find); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a53463e594b..56211ef46ee 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -236,7 +236,7 @@ out: | |||
236 | /* Find the correct entry in the "incomplete datagrams" queue for | 236 | /* Find the correct entry in the "incomplete datagrams" queue for |
237 | * this IP datagram, and create new one, if nothing is found. | 237 | * this IP datagram, and create new one, if nothing is found. |
238 | */ | 238 | */ |
239 | static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | 239 | static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) |
240 | { | 240 | { |
241 | struct inet_frag_queue *q; | 241 | struct inet_frag_queue *q; |
242 | struct ip4_create_arg arg; | 242 | struct ip4_create_arg arg; |
@@ -246,7 +246,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
246 | arg.user = user; | 246 | arg.user = user; |
247 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); | 247 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); |
248 | 248 | ||
249 | q = inet_frag_find(&ip4_frags, &arg, hash); | 249 | q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); |
250 | if (q == NULL) | 250 | if (q == NULL) |
251 | goto out_nomem; | 251 | goto out_nomem; |
252 | 252 | ||
@@ -582,15 +582,17 @@ out_fail: | |||
582 | int ip_defrag(struct sk_buff *skb, u32 user) | 582 | int ip_defrag(struct sk_buff *skb, u32 user) |
583 | { | 583 | { |
584 | struct ipq *qp; | 584 | struct ipq *qp; |
585 | struct net *net; | ||
585 | 586 | ||
586 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | 587 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); |
587 | 588 | ||
589 | net = skb->dev->nd_net; | ||
588 | /* Start by cleaning up the memory. */ | 590 | /* Start by cleaning up the memory. */ |
589 | if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh) | 591 | if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh) |
590 | ip_evictor(); | 592 | ip_evictor(); |
591 | 593 | ||
592 | /* Lookup (or create) queue header */ | 594 | /* Lookup (or create) queue header */ |
593 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { | 595 | if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) { |
594 | int ret; | 596 | int ret; |
595 | 597 | ||
596 | spin_lock(&qp->q.lock); | 598 | spin_lock(&qp->q.lock); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index d631631189b..18accd4eab0 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -78,6 +78,7 @@ static struct inet_frags_ctl nf_frags_ctl __read_mostly = { | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | static struct inet_frags nf_frags; | 80 | static struct inet_frags nf_frags; |
81 | static struct netns_frags nf_init_frags; | ||
81 | 82 | ||
82 | #ifdef CONFIG_SYSCTL | 83 | #ifdef CONFIG_SYSCTL |
83 | struct ctl_table nf_ct_ipv6_sysctl_table[] = { | 84 | struct ctl_table nf_ct_ipv6_sysctl_table[] = { |
@@ -212,7 +213,7 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) | |||
212 | arg.dst = dst; | 213 | arg.dst = dst; |
213 | hash = ip6qhashfn(id, src, dst); | 214 | hash = ip6qhashfn(id, src, dst); |
214 | 215 | ||
215 | q = inet_frag_find(&nf_frags, &arg, hash); | 216 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); |
216 | if (q == NULL) | 217 | if (q == NULL) |
217 | goto oom; | 218 | goto oom; |
218 | 219 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 1815ff0cf62..ab2d53b81b7 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -234,7 +234,7 @@ out: | |||
234 | } | 234 | } |
235 | 235 | ||
236 | static __inline__ struct frag_queue * | 236 | static __inline__ struct frag_queue * |
237 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, | 237 | fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, |
238 | struct inet6_dev *idev) | 238 | struct inet6_dev *idev) |
239 | { | 239 | { |
240 | struct inet_frag_queue *q; | 240 | struct inet_frag_queue *q; |
@@ -246,7 +246,7 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
246 | arg.dst = dst; | 246 | arg.dst = dst; |
247 | hash = ip6qhashfn(id, src, dst); | 247 | hash = ip6qhashfn(id, src, dst); |
248 | 248 | ||
249 | q = inet_frag_find(&ip6_frags, &arg, hash); | 249 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
250 | if (q == NULL) | 250 | if (q == NULL) |
251 | goto oom; | 251 | goto oom; |
252 | 252 | ||
@@ -568,6 +568,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
568 | struct frag_hdr *fhdr; | 568 | struct frag_hdr *fhdr; |
569 | struct frag_queue *fq; | 569 | struct frag_queue *fq; |
570 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 570 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
571 | struct net *net; | ||
571 | 572 | ||
572 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); | 573 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); |
573 | 574 | ||
@@ -598,10 +599,11 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
598 | return 1; | 599 | return 1; |
599 | } | 600 | } |
600 | 601 | ||
602 | net = skb->dev->nd_net; | ||
601 | if (atomic_read(&ip6_frags.mem) > init_net.ipv6.sysctl.frags.high_thresh) | 603 | if (atomic_read(&ip6_frags.mem) > init_net.ipv6.sysctl.frags.high_thresh) |
602 | ip6_evictor(ip6_dst_idev(skb->dst)); | 604 | ip6_evictor(ip6_dst_idev(skb->dst)); |
603 | 605 | ||
604 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, | 606 | if ((fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, |
605 | ip6_dst_idev(skb->dst))) != NULL) { | 607 | ip6_dst_idev(skb->dst))) != NULL) { |
606 | int ret; | 608 | int ret; |
607 | 609 | ||