`

dev_alloc_skb

阅读更多
/****************************************************
 *      dev_alloc_skb - 分配内存为接受的包
 *      @length: 分配的长度
 *      GFP_ATOMIC:原子类型,此函数经常用于终端上下文中
 ***************************************************/
struct sk_buff *dev_alloc_skb(unsigned int length)
{
    return __dev_alloc_skb(length, GFP_ATOMIC); 
}
EXPORT_SYMBOL(dev_alloc_skb);

#ifndef NET_SKB_PAD
#define NET_SKB_PAD     32
#endif

/*************************************************************
 *gfp_mask: get_free_pages mask, passed to alloc_skb
 *alloc_skb()增加32字节的空间,优化读写的效率
**************************************************************/
static inline struct sk_buff *__dev_alloc_skb(unsigned int length, gfp_t gfp_mask)
{
    struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
	if (likely(skb))
		skb_reserve(skb, NET_SKB_PAD);
	return skb;
}

static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority)
{
    return __alloc_skb(size, priority, 0, -1);
}

/****************************************************************************
 *      __alloc_skb 分配network的缓冲区
 *      @size: 分配的内存大小
 *      @gfp_mask: 分配的标签
 *      @fclone: 从fclone缓存分配内存并分配一个克隆的skb
 *      @node: 分配的节点号,一般为-1
 ****************************************************************************/
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 = fclone ? skbuff_fclone_cache : skbuff_head_cache;
	
	/* 获取头 */
	skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
		if (!skb)
			goto out;
	
	size = SKB_DATA_ALIGN(size); //字节对齐
	data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),gfp_mask, node);
		if (!data)
			goto nodata;
	
		
	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;

	shinfo = skb_shinfo(skb);
	atomic_set(&shinfo->dataref, 1);
	shinfo->nr_frags  = 0;
	shinfo->gso_size = 0;
	shinfo->gso_segs = 0;
	shinfo->gso_type = 0;
	shinfo->ip6_frag_id = 0;
	shinfo->tx_flags.flags = 0;
	shinfo->frag_list = NULL;
	memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps));
	
	if (fclone)
	{
		struct sk_buff *child = skb + 1;
		atomic_t *fclone_ref = (atomic_t *) (child + 1);
	
		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;
}
EXPORT_SYMBOL(__alloc_skb);

/**
 *      @skb: buffer to alter
 *      @len: bytes to move
 *
 *      Increase the headroom of an empty &sk_buff by reducing the tail
 *      room. This is only allowed for an empty buffer.
 */
static inline void skb_reserve(struct sk_buff *skb, int len)
{
	skb->data += len;
	skb->tail += len;
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics