- /* Allocate a new skbuff. We do this ourselves so we can fill in a few
-
* 'private' fields and also do memory statistics to find all the
-
* [BEEP] leaks.
-
*
-
*/
-
-
/**
-
* __alloc_skb - allocate a network buffer
-
* @size: size to allocate
-
* @gfp_mask: allocation mask
-
* @fclone: allocate from fclone cache instead of head cache
-
* and allocate a cloned (child) skb
-
* @node: numa node to allocate memory on
-
*
-
* Allocate a new &sk_buff. The returned buffer has no headroom and a
-
* tail room of size bytes. The object has a reference count of one.
-
* The return is the buffer. On a failure the return is %NULL.
-
*
-
* Buffers may only be allocated from interrupts using a @gfp_mask of
-
* %GFP_ATOMIC.
-
*/
-
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
-
int fclone, int node)
-
{
-
struct kmem_cache *cache;
-
struct skb_shared_info *shinfo;
-
struct sk_buff *skb;
-
u8 *data;
-
-
/* 如果fclone被设置,则从skbuff_fclone_cache缓冲区中分配,如果没有设置
-
* 则从skbuff_head_cache缓冲区中分配。
-
* skbuff_fclone_cache:预先知道该skbuf会被clone,因此分配父子skbuf结构
-
* 并指向同一数据缓冲区
-
* skbuff_head_cache:该skbuf不会被clone */
-
cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
-
-
/* Get the HEAD */
-
/* skbuf不能在DMA中分配,因此调用了gfp_mask & ~__GFP_DMA */
-
skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
-
if (!skb)
-
goto out;
-
/* 写缓存预取址 */
-
prefetchw(skb);
-
-
/* 边界对齐 */
-
size = SKB_DATA_ALIGN(size);
-
/* 分配skb的数据存储区 */
-
data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),
-
gfp_mask, node);
-
if (!data)
-
goto nodata;
-
prefetchw(data + size);
-
-
/*
-
* Only clear those fields we need to clear, not those that we will
-
* actually initialise below. Hence, don't put any more fields after
-
* the tail pointer in struct sk_buff!
-
*/
-
memset(skb, 0, offsetof(struct sk_buff, tail));
-
skb->truesize = size + sizeof(struct sk_buff);
-
/* 设置引用计数 */
-
atomic_set(&skb->users, 1);
-
skb->head = data;
-
skb->data = data;
-
skb_reset_tail_pointer(skb);
-
skb->end = skb->tail + size;
-
kmemcheck_annotate_bitfield(skb, flags1);
-
kmemcheck_annotate_bitfield(skb, flags2);
-
#ifdef NET_SKBUFF_DATA_USES_OFFSET
-
skb->mac_header = ~0U;
-
#endif
-
-
/* make sure we initialize shinfo sequentially */
-
shinfo = skb_shinfo(skb);
-
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
-
atomic_set(&shinfo->dataref, 1);
-
-
/* 子skb的初始化 */
-
if (fclone) {
-
struct sk_buff *child = skb + 1;
-
/* 父子skb的总计数在两个skb结构的末尾 */
-
atomic_t *fclone_ref = (atomic_t *) (child + 1);
-
-
kmemcheck_annotate_bitfield(child, flags1);
-
kmemcheck_annotate_bitfield(child, flags2);
-
skb->fclone = SKB_FCLONE_ORIG;
-
/* 设置clone标记 */
-
atomic_set(fclone_ref, 1);
-
-
/* 子skb还未创建 */
-
child->fclone = SKB_FCLONE_UNAVAILABLE;
-
}
-
out:
-
return skb;
-
nodata:
-
kmem_cache_free(cache, skb);
-
skb = NULL;
-
goto out;
- }