- /*
- 参数:
- size:skb的数据大小
- gfp_mask:不用解释
- fclone:表示从哪个cache中分配
- 当fclone为1时,从skbuff_fclone_cache上分配
- 当fclone为0时,从skbuff_head_cache上分配
- node: NUMA节点
- */
- 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;
/* 获得指定的cache */
-
cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
/* 从cache上分配, 如果cache上无法分配,则从内存中申请 */
-
/* Get the HEAD */
-
skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
-
if (!skb)
-
goto out;
-
prefetchw(skb);
-
-
size = SKB_DATA_ALIGN(size);
-
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
-
*/
-
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);
-
-
if (fclone) {
- /* 如果是fclone cache的话,那么skb的下一个buf,也将被分配*/
-
struct sk_buff *child = skb + 1;
-
atomic_t *fclone_ref = (atomic_t *) (child + 1);
-
-
kmemcheck_annotate_bitfield(child, flags1);
-
kmemcheck_annotate_bitfield(child, flags2);
-
skb->fclone = SKB_FCLONE_ORIG;
-
atomic_set(fclone_ref, 1);
-
-
child->fclone = SKB_FCLONE_UNAVAILABLE;
-
}
-
out:
-
return skb;
-
nodata:
-
kmem_cache_free(cache, skb);
-
skb = NULL;
-
goto out;
-
}