zoukankan      html  css  js  c++  java
  • 套接字缓存之alloc_skb、dev_alloc_skb、kfree_skb、dev_kfree_skb、consume_skb

    alloc_skb

    –分配skb,进行基本的初始化;

    1 static inline struct sk_buff *alloc_skb(unsigned int size,
    2                     gfp_t priority)
    3 {
    4     return __alloc_skb(size, priority, 0, NUMA_NO_NODE);
    5 }
      1 /**
      2  *    __alloc_skb    -    allocate a network buffer
      3  *    @size: size to allocate
      4  *    @gfp_mask: allocation mask
      5  *    @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache
      6  *        instead of head cache and allocate a cloned (child) skb.
      7  *        If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for
      8  *        allocations in case the data is required for writeback
      9  *    @node: numa node to allocate memory on
     10  *
     11  *    Allocate a new &sk_buff. The returned buffer has no headroom and a
     12  *    tail room of at least size bytes. The object has a reference count
     13  *    of one. The return is the buffer. On a failure the return is %NULL.
     14  *
     15  *    Buffers may only be allocated from interrupts using a @gfp_mask of
     16  *    %GFP_ATOMIC.
     17  */
     18 struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
     19                 int flags, int node)
     20 {
     21     struct kmem_cache *cache;
     22     struct skb_shared_info *shinfo;
     23     struct sk_buff *skb;
     24     u8 *data;
     25     bool pfmemalloc;
     26 
     27     /* 得到分配使用的高速缓存 */
     28     cache = (flags & SKB_ALLOC_FCLONE)
     29         ? skbuff_fclone_cache : skbuff_head_cache;
     30 
     31     if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX))
     32         gfp_mask |= __GFP_MEMALLOC;
     33 
     34     /* Get the HEAD */
     35     /* 分配skb */
     36     skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
     37     if (!skb)
     38         goto out;
     39     prefetchw(skb);
     40 
     41     /* We do our best to align skb_shared_info on a separate cache
     42      * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives
     43      * aligned memory blocks, unless SLUB/SLAB debug is enabled.
     44      * Both skb->head and skb_shared_info are cache line aligned.
     45      */
     46     /* 数据对齐 */
     47     size = SKB_DATA_ALIGN(size);
     48     /* 对齐后的数据加上skb_shared_info对齐后的大小 */
     49     size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
     50 
     51     //分配数据区
     52     data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc);
     53     if (!data)
     54         goto nodata;
     55     /* kmalloc(size) might give us more room than requested.
     56      * Put skb_shared_info exactly at the end of allocated zone,
     57      * to allow max possible filling before reallocation.
     58      */
     59     /* 除了skb_shared_info以外的数据大小 */
     60     size = SKB_WITH_OVERHEAD(ksize(data));
     61     prefetchw(data + size);
     62 
     63     /*
     64      * Only clear those fields we need to clear, not those that we will
     65      * actually initialise below. Hence, don't put any more fields after
     66      * the tail pointer in struct sk_buff!
     67      */
     68     memset(skb, 0, offsetof(struct sk_buff, tail));
     69     /* Account for allocated memory : skb + skb->head */
     70     /* 总长度= skb大小+  数据大小+  skb_shared_info大小 */
     71     skb->truesize = SKB_TRUESIZE(size);
     72     /* PFMEMALLOC分配标记 */
     73     skb->pfmemalloc = pfmemalloc;
     74     /* 设置引用计数为1 */
     75     atomic_set(&skb->users, 1);
     76     /*head data tail均指向数据区头部*/
     77     skb->head = data;
     78     skb->data = data;
     79     skb_reset_tail_pointer(skb);
     80 
     81     /* end指向数据区尾部 */
     82     skb->end = skb->tail + size;
     83     /* 初始化默认各层header偏移值 */
     84     skb->mac_header = (typeof(skb->mac_header))~0U;
     85     skb->transport_header = (typeof(skb->transport_header))~0U;
     86 
     87     /* make sure we initialize shinfo sequentially */
     88     /* 从end开始的区域为skb_shared_info */
     89     shinfo = skb_shinfo(skb);
     90     memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
     91     /* 设置引用计数为1 */
     92     atomic_set(&shinfo->dataref, 1);
     93     kmemcheck_annotate_variable(shinfo->destructor_arg);
     94 
     95     /* 如果有克隆标记 */
     96     if (flags & SKB_ALLOC_FCLONE) {
     97         struct sk_buff_fclones *fclones;
     98 
     99         /* 得到clone结构 */
    100         fclones = container_of(skb, struct sk_buff_fclones, skb1);
    101 
    102         kmemcheck_annotate_bitfield(&fclones->skb2, flags1);
    103 
    104         /* 设置克隆标记 */
    105         skb->fclone = SKB_FCLONE_ORIG;
    106 
    107         /* 设置引用为1 */
    108         atomic_set(&fclones->fclone_ref, 1);
    109 
    110         /* 设置skb2的克隆标记 */
    111         fclones->skb2.fclone = SKB_FCLONE_CLONE;
    112     }
    113 out:
    114     return skb;
    115 nodata:
    116     kmem_cache_free(cache, skb);
    117     skb = NULL;
    118     goto out;
    119 }
    dev_alloc_skb

    –分配skb,通常被设备驱动用在中断上下文中,它是alloc_skb的封装函数,因为在中断处理函数中被调用,因此要求原子操作(GFP_ATOMIC);

    1 /* legacy helper around netdev_alloc_skb() */
    2 static inline struct sk_buff *dev_alloc_skb(unsigned int length)
    3 {
    4     return netdev_alloc_skb(NULL, length);
    5 }
     1 /**
     2  *    netdev_alloc_skb - allocate an skbuff for rx on a specific device
     3  *    @dev: network device to receive on
     4  *    @length: length to allocate
     5  *
     6  *    Allocate a new &sk_buff and assign it a usage count of one. The
     7  *    buffer has unspecified headroom built in. Users should allocate
     8  *    the headroom they think they need without accounting for the
     9  *    built in space. The built in space is used for optimisations.
    10  *
    11  *    %NULL is returned if there is no free memory. Although this function
    12  *    allocates memory it can be called from an interrupt.
    13  */
    14 static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
    15                            unsigned int length)
    16 {
    17     return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
    18 }
     1 /**
     2  *    __netdev_alloc_skb - allocate an skbuff for rx on a specific device
     3  *    @dev: network device to receive on
     4  *    @len: length to allocate
     5  *    @gfp_mask: get_free_pages mask, passed to alloc_skb
     6  *
     7  *    Allocate a new &sk_buff and assign it a usage count of one. The
     8  *    buffer has NET_SKB_PAD headroom built in. Users should allocate
     9  *    the headroom they think they need without accounting for the
    10  *    built in space. The built in space is used for optimisations.
    11  *
    12  *    %NULL is returned if there is no free memory.
    13  */
    14 struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
    15                    gfp_t gfp_mask)
    16 {
    17     struct page_frag_cache *nc;
    18     unsigned long flags;
    19     struct sk_buff *skb;
    20     bool pfmemalloc;
    21     void *data;
    22 
    23     len += NET_SKB_PAD;
    24 
    25     /* 
    26         分配长度+ skb_shared_info长度> 一页
    27         有__GFP_DIRECT_RECLAIM | GFP_DMA 标记
    28     */
    29     if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) ||
    30         (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
    31         /* 通过__alloc_skb分配内存*/
    32         skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE);
    33         if (!skb)
    34             goto skb_fail;
    35 
    36         /* 分配成功 */
    37         goto skb_success;
    38     }
    39 
    40     /* 分配长度+ skb_shared_info长度*/
    41     len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
    42     /* 对整个长度进行对齐 */
    43     len = SKB_DATA_ALIGN(len);
    44 
    45     if (sk_memalloc_socks())
    46         gfp_mask |= __GFP_MEMALLOC;
    47 
    48     /* 保存中断 */
    49     local_irq_save(flags);
    50 
    51     nc = this_cpu_ptr(&netdev_alloc_cache);
    52     /* 分配空间 */
    53     data = page_frag_alloc(nc, len, gfp_mask);
    54     pfmemalloc = nc->pfmemalloc;
    55 
    56     /* 恢复中断 */
    57     local_irq_restore(flags);
    58 
    59     if (unlikely(!data))
    60         return NULL;
    61 
    62     /* 构建skb */
    63     skb = __build_skb(data, len);
    64     if (unlikely(!skb)) {
    65         skb_free_frag(data);
    66         return NULL;
    67     }
    68 
    69     /* use OR instead of assignment to avoid clearing of bits in mask */
    70     /* 设置PFMEMALLOC标记 */
    71     if (pfmemalloc)
    72         skb->pfmemalloc = 1;
    73 
    74     //打内存分配标记
    75     skb->head_frag = 1;
    76 
    77 skb_success:
    78     /* 保留空间 */
    79     skb_reserve(skb, NET_SKB_PAD);
    80     /* 设置输入设备 */
    81     skb->dev = dev;
    82 
    83 skb_fail:
    84     return skb;
    85 }
    kfree_skb

    –减少skb引用,为0则释放,用于出错丢包时释放skb使用;

     1 /**
     2  *    kfree_skb - free an sk_buff
     3  *    @skb: buffer to free
     4  *
     5  *    Drop a reference to the buffer and free it if the usage count has
     6  *    hit zero.
     7  */
     8 /*
     9     释放skb
    10 */
    11 void kfree_skb(struct sk_buff *skb)
    12 {
    13     if (unlikely(!skb))
    14         return;
    15     /* 引用为1,可直接释放 */
    16     if (likely(atomic_read(&skb->users) == 1))
    17         smp_rmb();
    18     /*
    19         对引用减1,并且判断,如果结果不为0
    20         说明还有引用,返回
    21     */
    22     else if (likely(!atomic_dec_and_test(&skb->users)))
    23         return;
    24     trace_kfree_skb(skb, __builtin_return_address(0));
    25 
    26     //真正的skb释放
    27     __kfree_skb(skb);
    28 }
     1 /**
     2  *    __kfree_skb - private function
     3  *    @skb: buffer
     4  *
     5  *    Free an sk_buff. Release anything attached to the buffer.
     6  *    Clean the state. This is an internal helper function. Users should
     7  *    always call kfree_skb
     8  */
     9 /* 释放skb */
    10 void __kfree_skb(struct sk_buff *skb)
    11 {
    12     /* 释放skb附带的所有数据 */
    13     skb_release_all(skb);
    14     /* 释放skb */
    15     kfree_skbmem(skb);
    16 }
    dev_kfree_skb && consume_skb

    –减少skb引用,为0则释放,成功状态下释放skb使用;

     1 /**
     2  *    consume_skb - free an skbuff
     3  *    @skb: buffer to free
     4  *
     5  *    Drop a ref to the buffer and free it if the usage count has hit zero
     6  *    Functions identically to kfree_skb, but kfree_skb assumes that the frame
     7  *    is being dropped after a failure and notes that
     8  */
     9 /* 释放skb,与kfree_skb区别是,kfree_skb用于失败时丢包释放 */
    10 void consume_skb(struct sk_buff *skb)
    11 {
    12     if (unlikely(!skb))
    13         return;
    14     if (likely(atomic_read(&skb->users) == 1))
    15         smp_rmb();
    16     else if (likely(!atomic_dec_and_test(&skb->users)))
    17         return;
    18     trace_consume_skb(skb);
    19     __kfree_skb(skb);
    20 }
    1 #define dev_kfree_skb(a)    consume_skb(a)
  • 相关阅读:
    克罗谈投资策略14
    克罗谈投资策略13
    克罗谈投资策略12
    克罗谈投资策略11
    克罗谈投资策略10
    克罗谈投资策略09
    克罗谈投资策略08
    克罗谈投资策略07
    克罗谈投资策略06
    克罗谈投资策略05
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/7529576.html
Copyright © 2011-2022 走看看