Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266862
b: refs/heads/master
c: 3d153a7
h: refs/heads/master
v: v3
  • Loading branch information
Andy Fleming authored and David S. Miller committed Oct 19, 2011
1 parent 2d676cb commit 9d9bf61
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1e5c22cde3b85737921d3ec6ecf2c356e5b64ea7
refs/heads/master: 3d153a7c8b23031df35e61377c0600a6c96a8b0b
21 changes: 21 additions & 0 deletions trunk/include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
return __alloc_skb(size, priority, 1, NUMA_NO_NODE);
}

extern void skb_recycle(struct sk_buff *skb);
extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);

extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
Expand Down Expand Up @@ -2484,5 +2485,25 @@ static inline void skb_checksum_none_assert(struct sk_buff *skb)

bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);

static inline bool skb_is_recycleable(struct sk_buff *skb, int skb_size)
{
if (irqs_disabled())
return false;

if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
return false;

if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
return false;

skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
if (skb_end_pointer(skb) - skb->head < skb_size)
return false;

if (skb_shared(skb) || skb_cloned(skb))
return false;

return true;
}
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */
51 changes: 26 additions & 25 deletions trunk/net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,30 @@ void consume_skb(struct sk_buff *skb)
}
EXPORT_SYMBOL(consume_skb);

/**
* skb_recycle - clean up an skb for reuse
* @skb: buffer
*
* Recycles the skb to be reused as a receive buffer. This
* function does any necessary reference count dropping, and
* cleans up the skbuff as if it just came from __alloc_skb().
*/
void skb_recycle(struct sk_buff *skb)
{
struct skb_shared_info *shinfo;

skb_release_head_state(skb);

shinfo = skb_shinfo(skb);
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);

memset(skb, 0, offsetof(struct sk_buff, tail));
skb->data = skb->head + NET_SKB_PAD;
skb_reset_tail_pointer(skb);
}
EXPORT_SYMBOL(skb_recycle);

/**
* skb_recycle_check - check if skb can be reused for receive
* @skb: buffer
Expand All @@ -498,33 +522,10 @@ EXPORT_SYMBOL(consume_skb);
*/
bool skb_recycle_check(struct sk_buff *skb, int skb_size)
{
struct skb_shared_info *shinfo;

if (irqs_disabled())
return false;

if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
return false;

if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
return false;

skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
if (skb_end_pointer(skb) - skb->head < skb_size)
return false;

if (skb_shared(skb) || skb_cloned(skb))
if (!skb_is_recycleable(skb, skb_size))
return false;

skb_release_head_state(skb);

shinfo = skb_shinfo(skb);
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);

memset(skb, 0, offsetof(struct sk_buff, tail));
skb->data = skb->head + NET_SKB_PAD;
skb_reset_tail_pointer(skb);
skb_recycle(skb);

return true;
}
Expand Down

0 comments on commit 9d9bf61

Please sign in to comment.