/*allocate a network buffer, and init the skb->data and skb->tail to skb->head*/
struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
{
struct sk_buff *skb;
u8 *data;
if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
static int count = 0;
if (++count < 5) {
printk(KERN_ERR "alloc_skb called nonatomically "
"from interrupt %p/n", NET_CALLER(size));
BUG();
}
gfp_mask &= ~__GFP_WAIT;
}
/* Get the HEAD */
skb = skb_head_from_pool();
if (skb == NULL) {
skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask & ~__GFP_DMA);
if (skb == NULL)
goto nohead;
}
/* Get the DATA. Size must match skb_add_mtu(). */
size = SKB_DATA_ALIGN(size); //32字节对齐
data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
if (data == NULL)
goto nodata;
/* XXX: does not include slab overhead */
skb->truesize = size + sizeof(struct sk_buff);
这是缓冲区的总长度,包括sk_buff结构和数据部分。如果申请一个len字节的缓冲区,
alloc_skb函数会把它初始化成len+sizeof(sk_buff)。
/* Load the data pointers. */
skb->head = data;
skb->data = data;
skb->tail = data;
skb->end = data + size;
/* Set up other state */
skb->len = 0;
skb->cloned = 0;
skb->data_len = 0;
atomic_set(&skb->users, 1);
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->frag_list = NULL;
return skb;
nodata:
skb_head_to_pool(skb);
nohead:
return NULL;
}
skb_head_pool[NR_CPUS]就是skb head的池子,每个cpu一个struct skb_buff_head list.
当一个skb不在需要的时候,不使用kmem_cache_free释放,而是skb_head_to_poo加到当前
cpu的skb_head_pool的list上,这样下次分配skb的时候,就可以skb_head_from_pool从skb_head_pool
中取,而不用kmem_cache_alloc重新分配.int sysctl_hot_list_len=128是list的长度上限。
alloc_skb的时候先从skb_head_pool里skb_head_from_pool去sk_buff,如果没取到它返回的就是NULL,
就kmem_cache_alloc从skbuff_head_cache里分配.
skb_head_from_pool就是从skb_head_pool的list取sk_buff
skb_head_to_pool把不用的sk_buff加到skb_head_pool的list上,如果list满了就kmem_cache_free(skbuff_head_cache,skb)
在alloc_skb里面
data=kmalloc(size+sizeof(struct skb_shared_info),gfp_mask);
if(data==NULL) /*数据空间分配没有成功,上面成功分配了sk_buff*/
goto nodata;
......
nodata:
skb_head_to_pool(skb); /*skb_head_pool的list没满就加到list上,以后alloc_skb时用*/
void kfree_skbmem(struct sk_buff *skb)
{
skb_release_data(skb); /*释放数据空间*/
skb_head_to_pool(skb); /*处理sk_buff,跟上面一样*/
}
http://vger.kernel.org/~davem/ skb参考资料