skb_alloc()

/*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参考资料

你可能感兴趣的:(struct,cache,list,null,NetWork,include)