diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/skbuff.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ca1ccdf1ef76..2c218a0808b4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -363,8 +363,7 @@ static void kfree_skbmem(struct sk_buff *skb) | |||
363 | } | 363 | } |
364 | } | 364 | } |
365 | 365 | ||
366 | /* Free everything but the sk_buff shell. */ | 366 | static void skb_release_head_state(struct sk_buff *skb) |
367 | static void skb_release_all(struct sk_buff *skb) | ||
368 | { | 367 | { |
369 | dst_release(skb->dst); | 368 | dst_release(skb->dst); |
370 | #ifdef CONFIG_XFRM | 369 | #ifdef CONFIG_XFRM |
@@ -388,6 +387,12 @@ static void skb_release_all(struct sk_buff *skb) | |||
388 | skb->tc_verd = 0; | 387 | skb->tc_verd = 0; |
389 | #endif | 388 | #endif |
390 | #endif | 389 | #endif |
390 | } | ||
391 | |||
392 | /* Free everything but the sk_buff shell. */ | ||
393 | static void skb_release_all(struct sk_buff *skb) | ||
394 | { | ||
395 | skb_release_head_state(skb); | ||
391 | skb_release_data(skb); | 396 | skb_release_data(skb); |
392 | } | 397 | } |
393 | 398 | ||
@@ -424,6 +429,38 @@ void kfree_skb(struct sk_buff *skb) | |||
424 | __kfree_skb(skb); | 429 | __kfree_skb(skb); |
425 | } | 430 | } |
426 | 431 | ||
432 | int skb_recycle_check(struct sk_buff *skb, int skb_size) | ||
433 | { | ||
434 | struct skb_shared_info *shinfo; | ||
435 | |||
436 | if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) | ||
437 | return 0; | ||
438 | |||
439 | skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); | ||
440 | if (skb_end_pointer(skb) - skb->head < skb_size) | ||
441 | return 0; | ||
442 | |||
443 | if (skb_shared(skb) || skb_cloned(skb)) | ||
444 | return 0; | ||
445 | |||
446 | skb_release_head_state(skb); | ||
447 | shinfo = skb_shinfo(skb); | ||
448 | atomic_set(&shinfo->dataref, 1); | ||
449 | shinfo->nr_frags = 0; | ||
450 | shinfo->gso_size = 0; | ||
451 | shinfo->gso_segs = 0; | ||
452 | shinfo->gso_type = 0; | ||
453 | shinfo->ip6_frag_id = 0; | ||
454 | shinfo->frag_list = NULL; | ||
455 | |||
456 | memset(skb, 0, offsetof(struct sk_buff, tail)); | ||
457 | skb_reset_tail_pointer(skb); | ||
458 | skb->data = skb->head + NET_SKB_PAD; | ||
459 | |||
460 | return 1; | ||
461 | } | ||
462 | EXPORT_SYMBOL(skb_recycle_check); | ||
463 | |||
427 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 464 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
428 | { | 465 | { |
429 | new->tstamp = old->tstamp; | 466 | new->tstamp = old->tstamp; |