aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c77
1 files changed, 74 insertions, 3 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index ca1ccdf1ef76..d49ef8301b5b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Routines having to do with the 'struct sk_buff' memory handlers. 2 * Routines having to do with the 'struct sk_buff' memory handlers.
3 * 3 *
4 * Authors: Alan Cox <iiitac@pyr.swan.ac.uk> 4 * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk>
5 * Florian La Roche <rzsfl@rz.uni-sb.de> 5 * Florian La Roche <rzsfl@rz.uni-sb.de>
6 * 6 *
7 * Fixes: 7 * Fixes:
@@ -263,6 +263,26 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
263 return skb; 263 return skb;
264} 264}
265 265
266struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask)
267{
268 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
269 struct page *page;
270
271 page = alloc_pages_node(node, gfp_mask, 0);
272 return page;
273}
274EXPORT_SYMBOL(__netdev_alloc_page);
275
276void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
277 int size)
278{
279 skb_fill_page_desc(skb, i, page, off, size);
280 skb->len += size;
281 skb->data_len += size;
282 skb->truesize += size;
283}
284EXPORT_SYMBOL(skb_add_rx_frag);
285
266/** 286/**
267 * dev_alloc_skb - allocate an skbuff for receiving 287 * dev_alloc_skb - allocate an skbuff for receiving
268 * @length: length to allocate 288 * @length: length to allocate
@@ -363,8 +383,7 @@ static void kfree_skbmem(struct sk_buff *skb)
363 } 383 }
364} 384}
365 385
366/* Free everything but the sk_buff shell. */ 386static void skb_release_head_state(struct sk_buff *skb)
367static void skb_release_all(struct sk_buff *skb)
368{ 387{
369 dst_release(skb->dst); 388 dst_release(skb->dst);
370#ifdef CONFIG_XFRM 389#ifdef CONFIG_XFRM
@@ -388,6 +407,12 @@ static void skb_release_all(struct sk_buff *skb)
388 skb->tc_verd = 0; 407 skb->tc_verd = 0;
389#endif 408#endif
390#endif 409#endif
410}
411
412/* Free everything but the sk_buff shell. */
413static void skb_release_all(struct sk_buff *skb)
414{
415 skb_release_head_state(skb);
391 skb_release_data(skb); 416 skb_release_data(skb);
392} 417}
393 418
@@ -424,6 +449,50 @@ void kfree_skb(struct sk_buff *skb)
424 __kfree_skb(skb); 449 __kfree_skb(skb);
425} 450}
426 451
452/**
453 * skb_recycle_check - check if skb can be reused for receive
454 * @skb: buffer
455 * @skb_size: minimum receive buffer size
456 *
457 * Checks that the skb passed in is not shared or cloned, and
458 * that it is linear and its head portion at least as large as
459 * skb_size so that it can be recycled as a receive buffer.
460 * If these conditions are met, this function does any necessary
461 * reference count dropping and cleans up the skbuff as if it
462 * just came from __alloc_skb().
463 */
464int skb_recycle_check(struct sk_buff *skb, int skb_size)
465{
466 struct skb_shared_info *shinfo;
467
468 if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
469 return 0;
470
471 skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
472 if (skb_end_pointer(skb) - skb->head < skb_size)
473 return 0;
474
475 if (skb_shared(skb) || skb_cloned(skb))
476 return 0;
477
478 skb_release_head_state(skb);
479 shinfo = skb_shinfo(skb);
480 atomic_set(&shinfo->dataref, 1);
481 shinfo->nr_frags = 0;
482 shinfo->gso_size = 0;
483 shinfo->gso_segs = 0;
484 shinfo->gso_type = 0;
485 shinfo->ip6_frag_id = 0;
486 shinfo->frag_list = NULL;
487
488 memset(skb, 0, offsetof(struct sk_buff, tail));
489 skb->data = skb->head + NET_SKB_PAD;
490 skb_reset_tail_pointer(skb);
491
492 return 1;
493}
494EXPORT_SYMBOL(skb_recycle_check);
495
427static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) 496static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
428{ 497{
429 new->tstamp = old->tstamp; 498 new->tstamp = old->tstamp;
@@ -701,6 +770,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
701#endif 770#endif
702 long off; 771 long off;
703 772
773 BUG_ON(nhead < 0);
774
704 if (skb_shared(skb)) 775 if (skb_shared(skb))
705 BUG(); 776 BUG();
706 777