aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_frag.h2
-rw-r--r--net/ipv4/inet_fragment.c17
-rw-r--r--net/ipv4/ip_fragment.c20
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c19
-rw-r--r--net/ipv6/reassembly.c19
5 files changed, 41 insertions, 36 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 133e187fbc98..412b8582a616 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -43,6 +43,7 @@ struct inet_frags {
43 void (*skb_free)(struct sk_buff *); 43 void (*skb_free)(struct sk_buff *);
44 int (*equal)(struct inet_frag_queue *q1, 44 int (*equal)(struct inet_frag_queue *q1,
45 struct inet_frag_queue *q2); 45 struct inet_frag_queue *q2);
46 void (*frag_expire)(unsigned long data);
46}; 47};
47 48
48void inet_frags_init(struct inet_frags *); 49void inet_frags_init(struct inet_frags *);
@@ -54,6 +55,7 @@ void inet_frag_destroy(struct inet_frag_queue *q,
54int inet_frag_evictor(struct inet_frags *f); 55int inet_frag_evictor(struct inet_frags *f);
55struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *q, 56struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *q,
56 struct inet_frags *f, unsigned int hash); 57 struct inet_frags *f, unsigned int hash);
58struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f);
57 59
58static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) 60static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
59{ 61{
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 15054eb3d4b9..57e15fa307dc 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -209,3 +209,20 @@ struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in,
209 return qp; 209 return qp;
210} 210}
211EXPORT_SYMBOL(inet_frag_intern); 211EXPORT_SYMBOL(inet_frag_intern);
212
213struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f)
214{
215 struct inet_frag_queue *q;
216
217 q = kzalloc(f->qsize, GFP_ATOMIC);
218 if (q == NULL)
219 return NULL;
220
221 atomic_add(f->qsize, &f->mem);
222 setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
223 spin_lock_init(&q->lock);
224 atomic_set(&q->refcnt, 1);
225
226 return q;
227}
228EXPORT_SYMBOL(inet_frag_alloc);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 4b1bbbee22c5..fc0d530df522 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -158,12 +158,10 @@ static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
158 158
159static __inline__ struct ipq *frag_alloc_queue(void) 159static __inline__ struct ipq *frag_alloc_queue(void)
160{ 160{
161 struct ipq *qp = kzalloc(sizeof(struct ipq), GFP_ATOMIC); 161 struct inet_frag_queue *q;
162 162
163 if (!qp) 163 q = inet_frag_alloc(&ip4_frags);
164 return NULL; 164 return q ? container_of(q, struct ipq, q) : NULL;
165 atomic_add(sizeof(struct ipq), &ip4_frags.mem);
166 return qp;
167} 165}
168 166
169 167
@@ -199,7 +197,9 @@ static void ip_evictor(void)
199 */ 197 */
200static void ip_expire(unsigned long arg) 198static void ip_expire(unsigned long arg)
201{ 199{
202 struct ipq *qp = (struct ipq *) arg; 200 struct ipq *qp;
201
202 qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
203 203
204 spin_lock(&qp->q.lock); 204 spin_lock(&qp->q.lock);
205 205
@@ -249,13 +249,6 @@ static struct ipq *ip_frag_create(struct iphdr *iph, u32 user, unsigned int h)
249 qp->user = user; 249 qp->user = user;
250 qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; 250 qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
251 251
252 /* Initialize a timer for this entry. */
253 init_timer(&qp->q.timer);
254 qp->q.timer.data = (unsigned long) qp; /* pointer to queue */
255 qp->q.timer.function = ip_expire; /* expire function */
256 spin_lock_init(&qp->q.lock);
257 atomic_set(&qp->q.refcnt, 1);
258
259 return ip_frag_intern(qp, h); 252 return ip_frag_intern(qp, h);
260 253
261out_nomem: 254out_nomem:
@@ -653,6 +646,7 @@ void __init ipfrag_init(void)
653 ip4_frags.skb_free = NULL; 646 ip4_frags.skb_free = NULL;
654 ip4_frags.qsize = sizeof(struct ipq); 647 ip4_frags.qsize = sizeof(struct ipq);
655 ip4_frags.equal = ip4_frag_equal; 648 ip4_frags.equal = ip4_frag_equal;
649 ip4_frags.frag_expire = ip_expire;
656 inet_frags_init(&ip4_frags); 650 inet_frags_init(&ip4_frags);
657} 651}
658 652
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index d7dc444ec48f..3f8c16b3301e 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -137,13 +137,10 @@ static void nf_frag_free(struct inet_frag_queue *q)
137 137
138static inline struct nf_ct_frag6_queue *frag_alloc_queue(void) 138static inline struct nf_ct_frag6_queue *frag_alloc_queue(void)
139{ 139{
140 struct nf_ct_frag6_queue *fq; 140 struct inet_frag_queue *q;
141 141
142 fq = kzalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC); 142 q = inet_frag_alloc(&nf_frags);
143 if (fq == NULL) 143 return q ? container_of(q, struct nf_ct_frag6_queue, q) : NULL;
144 return NULL;
145 atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_frags.mem);
146 return fq;
147} 144}
148 145
149/* Destruction primitives. */ 146/* Destruction primitives. */
@@ -168,7 +165,10 @@ static void nf_ct_frag6_evictor(void)
168 165
169static void nf_ct_frag6_expire(unsigned long data) 166static void nf_ct_frag6_expire(unsigned long data)
170{ 167{
171 struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data; 168 struct nf_ct_frag6_queue *fq;
169
170 fq = container_of((struct inet_frag_queue *)data,
171 struct nf_ct_frag6_queue, q);
172 172
173 spin_lock(&fq->q.lock); 173 spin_lock(&fq->q.lock);
174 174
@@ -208,10 +208,6 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str
208 ipv6_addr_copy(&fq->saddr, src); 208 ipv6_addr_copy(&fq->saddr, src);
209 ipv6_addr_copy(&fq->daddr, dst); 209 ipv6_addr_copy(&fq->daddr, dst);
210 210
211 setup_timer(&fq->q.timer, nf_ct_frag6_expire, (unsigned long)fq);
212 spin_lock_init(&fq->q.lock);
213 atomic_set(&fq->q.refcnt, 1);
214
215 return nf_ct_frag6_intern(hash, fq); 211 return nf_ct_frag6_intern(hash, fq);
216 212
217oom: 213oom:
@@ -726,6 +722,7 @@ int nf_ct_frag6_init(void)
726 nf_frags.skb_free = nf_skb_free; 722 nf_frags.skb_free = nf_skb_free;
727 nf_frags.qsize = sizeof(struct nf_ct_frag6_queue); 723 nf_frags.qsize = sizeof(struct nf_ct_frag6_queue);
728 nf_frags.equal = ip6_frag_equal; 724 nf_frags.equal = ip6_frag_equal;
725 nf_frags.frag_expire = nf_ct_frag6_expire;
729 inet_frags_init(&nf_frags); 726 inet_frags_init(&nf_frags);
730 727
731 return 0; 728 return 0;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 73ea204eaa6f..21913c78f053 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -171,12 +171,10 @@ static void ip6_frag_free(struct inet_frag_queue *fq)
171 171
172static inline struct frag_queue *frag_alloc_queue(void) 172static inline struct frag_queue *frag_alloc_queue(void)
173{ 173{
174 struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC); 174 struct inet_frag_queue *q;
175 175
176 if(!fq) 176 q = inet_frag_alloc(&ip6_frags);
177 return NULL; 177 return q ? container_of(q, struct frag_queue, q) : NULL;
178 atomic_add(sizeof(struct frag_queue), &ip6_frags.mem);
179 return fq;
180} 178}
181 179
182/* Destruction primitives. */ 180/* Destruction primitives. */
@@ -205,9 +203,11 @@ static void ip6_evictor(struct inet6_dev *idev)
205 203
206static void ip6_frag_expire(unsigned long data) 204static void ip6_frag_expire(unsigned long data)
207{ 205{
208 struct frag_queue *fq = (struct frag_queue *) data; 206 struct frag_queue *fq;
209 struct net_device *dev = NULL; 207 struct net_device *dev = NULL;
210 208
209 fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
210
211 spin_lock(&fq->q.lock); 211 spin_lock(&fq->q.lock);
212 212
213 if (fq->q.last_in & COMPLETE) 213 if (fq->q.last_in & COMPLETE)
@@ -268,12 +268,6 @@ ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst,
268 ipv6_addr_copy(&fq->saddr, src); 268 ipv6_addr_copy(&fq->saddr, src);
269 ipv6_addr_copy(&fq->daddr, dst); 269 ipv6_addr_copy(&fq->daddr, dst);
270 270
271 init_timer(&fq->q.timer);
272 fq->q.timer.function = ip6_frag_expire;
273 fq->q.timer.data = (long) fq;
274 spin_lock_init(&fq->q.lock);
275 atomic_set(&fq->q.refcnt, 1);
276
277 return ip6_frag_intern(fq, hash); 271 return ip6_frag_intern(fq, hash);
278 272
279oom: 273oom:
@@ -685,5 +679,6 @@ void __init ipv6_frag_init(void)
685 ip6_frags.skb_free = NULL; 679 ip6_frags.skb_free = NULL;
686 ip6_frags.qsize = sizeof(struct frag_queue); 680 ip6_frags.qsize = sizeof(struct frag_queue);
687 ip6_frags.equal = ip6_frag_equal; 681 ip6_frags.equal = ip6_frag_equal;
682 ip6_frags.frag_expire = ip6_frag_expire;
688 inet_frags_init(&ip6_frags); 683 inet_frags_init(&ip6_frags);
689} 684}