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參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章