aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/reassembly.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-07-27 11:59:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-27 11:59:19 -0400
commit800f65bba8d2030b3fef62850e203f9f176625a8 (patch)
tree6507c4fe7a0826c253b4afb29375ab306a0fd9c8 /net/ipv6/reassembly.c
parent06b3cda0c12986f5bba578b918b188d731c4e191 (diff)
parentb3190df628617c7a4f188a9465aeabe1f5761933 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-commands.h
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r--net/ipv6/reassembly.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 6d4292ff5854..545c4141b755 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -150,11 +150,8 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a)
150EXPORT_SYMBOL(ip6_frag_match); 150EXPORT_SYMBOL(ip6_frag_match);
151 151
152/* Memory Tracking Functions. */ 152/* Memory Tracking Functions. */
153static inline void frag_kfree_skb(struct netns_frags *nf, 153static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
154 struct sk_buff *skb, int *work)
155{ 154{
156 if (work)
157 *work -= skb->truesize;
158 atomic_sub(skb->truesize, &nf->mem); 155 atomic_sub(skb->truesize, &nf->mem);
159 kfree_skb(skb); 156 kfree_skb(skb);
160} 157}
@@ -336,6 +333,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
336 * in the chain of fragments so far. We must know where to put 333 * in the chain of fragments so far. We must know where to put
337 * this fragment, right? 334 * this fragment, right?
338 */ 335 */
336 prev = fq->q.fragments_tail;
337 if (!prev || FRAG6_CB(prev)->offset < offset) {
338 next = NULL;
339 goto found;
340 }
339 prev = NULL; 341 prev = NULL;
340 for(next = fq->q.fragments; next != NULL; next = next->next) { 342 for(next = fq->q.fragments; next != NULL; next = next->next) {
341 if (FRAG6_CB(next)->offset >= offset) 343 if (FRAG6_CB(next)->offset >= offset)
@@ -343,6 +345,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
343 prev = next; 345 prev = next;
344 } 346 }
345 347
348found:
346 /* We found where to put this one. Check for overlap with 349 /* We found where to put this one. Check for overlap with
347 * preceding fragment, and, if needed, align things so that 350 * preceding fragment, and, if needed, align things so that
348 * any overlaps are eliminated. 351 * any overlaps are eliminated.
@@ -392,7 +395,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
392 fq->q.fragments = next; 395 fq->q.fragments = next;
393 396
394 fq->q.meat -= free_it->len; 397 fq->q.meat -= free_it->len;
395 frag_kfree_skb(fq->q.net, free_it, NULL); 398 frag_kfree_skb(fq->q.net, free_it);
396 } 399 }
397 } 400 }
398 401
@@ -400,6 +403,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
400 403
401 /* Insert this fragment in the chain of fragments. */ 404 /* Insert this fragment in the chain of fragments. */
402 skb->next = next; 405 skb->next = next;
406 if (!next)
407 fq->q.fragments_tail = skb;
403 if (prev) 408 if (prev)
404 prev->next = skb; 409 prev->next = skb;
405 else 410 else
@@ -466,6 +471,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
466 goto out_oom; 471 goto out_oom;
467 472
468 fp->next = head->next; 473 fp->next = head->next;
474 if (!fp->next)
475 fq->q.fragments_tail = fp;
469 prev->next = fp; 476 prev->next = fp;
470 477
471 skb_morph(head, fq->q.fragments); 478 skb_morph(head, fq->q.fragments);
@@ -524,7 +531,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
524 skb_shinfo(head)->frag_list = head->next; 531 skb_shinfo(head)->frag_list = head->next;
525 skb_reset_transport_header(head); 532 skb_reset_transport_header(head);
526 skb_push(head, head->data - skb_network_header(head)); 533 skb_push(head, head->data - skb_network_header(head));
527 atomic_sub(head->truesize, &fq->q.net->mem);
528 534
529 for (fp=head->next; fp; fp = fp->next) { 535 for (fp=head->next; fp; fp = fp->next) {
530 head->data_len += fp->len; 536 head->data_len += fp->len;
@@ -534,8 +540,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
534 else if (head->ip_summed == CHECKSUM_COMPLETE) 540 else if (head->ip_summed == CHECKSUM_COMPLETE)
535 head->csum = csum_add(head->csum, fp->csum); 541 head->csum = csum_add(head->csum, fp->csum);
536 head->truesize += fp->truesize; 542 head->truesize += fp->truesize;
537 atomic_sub(fp->truesize, &fq->q.net->mem);
538 } 543 }
544 atomic_sub(head->truesize, &fq->q.net->mem);
539 545
540 head->next = NULL; 546 head->next = NULL;
541 head->dev = dev; 547 head->dev = dev;
@@ -553,6 +559,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
553 IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); 559 IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
554 rcu_read_unlock(); 560 rcu_read_unlock();
555 fq->q.fragments = NULL; 561 fq->q.fragments = NULL;
562 fq->q.fragments_tail = NULL;
556 return 1; 563 return 1;
557 564
558out_oversize: 565out_oversize: