sk_buff操作函数

内核 专栏收录该内容
12 篇文章 0 订阅

几个操作sk_buff指针的函数

首先来认识三个空间:
第一个:headroom  就是skb->head和skb->data之间的空间
第二个:data   就是skb->data和skb->tail之间的空间
第三个:tailroom  就是skb->tail和skb->end之间的空间

head -->      |----------|
              | headroom |
data -->      |----------|
              |   data   |
tail -->      |----------|
              | tailroom |
end  -->      |----------|

接下来说四个操作sk_buff结构中的指针的函数
(a) skb_put()
(b) skb_push()
(c) skb_pull()
(d) skb_reserver()
这四个函数在数据包在各层之间的传输起到了至关重要的作用。

        (a)skb_put():向后扩大数据区空间,headroom空间不变,tailroom空间减少,skb->data指针不变,skb->tail指针下移;

        (b)skb_push():向前扩大数据区空间,headroom空间减少,tailroom空间不变,skb->tail指针不变,skb->data指针上移;
        (c)skb_pull():缩小数据区空间,headroom空间增大,tailroom空间不变,skb->data指针下移,skb->tail指针不变;

        (d)skb_reserve():数据区不变,headroom空间增大,tailroom空间减少,skb->data和skb->tail同时下移;

skb_header_pointer()

static inline void * __must_check
skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
{
    return __skb_header_pointer(skb, offset, len, skb->data,
                skb_headlen(skb), buffer);
}

unsigned int
skb_headlen(const struct sk_buff *skb)
{
    return skb->len - skb->data_len;
}

static inline void * __must_check
__skb_header_pointer(const struct sk_buff *skb, int offset,
                int len, void *data, int hlen, void *buffer)
{
    if (hlen - offset >= len)
        return data + offset;

    if(!skb ||
        sbb_copy_bits(skb, offset, buffer, len) < 0)
        return NULL;

    return buffer;
}
/**
 * skb_share_check - check if the buffer is shared and if so clone it
 * @skb: buffer to check
 * @pri: priority for memory allocation
 *
 * If the buffer is shared the buffer is cloned and the old copy 
 * drop a reference. A new clone with a single reference is returned.
 * If the buffer is not shared the original buffer is returned. When
 * being called from interrupt status or with spinlocks held pri must
 * be GFP_ATOMIC.
 *
 * NULL is returned on a memory allocation failure.   
 */
static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri)
{
    might_sleep_if(gfpflags_allow_blocking(pri));
    if (skb_shared(skb)) {
        struct sk_buff *nskb = skb_clone(skb, pri);

        if (likely(nskb))
            consume_skb(skb);
        else
            kfree_skb(skb);
        skb = nskb;
    }
    return skb;
}

/**
 * skb_shared - is the buffer shared
 * @skb: buffer to check
 *
 * return true if more than one person has a reference to this
 * buffer.
 */
static inline int skb_shared(const sk_buff *skb)
{
    return atomic_read(&skb->users) != 1;
}

/**
 * skb_clone - duplicate a sk_buff
 * @skb: buffer to clone
 * @gfp_mask: allocation priority
 *
 * Duplicate an &sk_buff. The new one is not owned by a socket. Both
 * copies share the same packet data but not structure. The new
 * buffer has a reference count of 1. If the allocation fails the 
 * function return %NULL otherwise the new buffer is returned.
 *
 * If this function is called from an interupt gfp_mask must be 
 * %GFP_ATOMIC.
 */
struct sk_buff *skb_clone(const sk_buff *skb, gfp_t gfp_mask)
{
    struct sk_buff_fclones *fclones = container_of(skb,
                                        struct sk_buff_fclones,
                                        skb1);
    struct sk_buff *n;

    if (skb_orphan_frags(skb, gfp_mask))
        return NULL;

    if (skb->fclone == SKB_FCLONE_ORIG &&
        atomic_read(&fclones->fclone_ref) == 1){
        n = &fclones->skb2;
        atomic_set(&fclones->fclone_ref, 2);
    } else {
        if (skb_pfmemalloc(skb))
            gfp_mask |= __GFP_MEMALLOC;
        n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
        if (!n)
            return NULL;

        kmemcheck_annotate_bitfield(n, flag1);
        n->fclone = SKB_FCLONE_UNAVAILABLE;
    }

    return __skb_clone(n, skb);
}

/**
 * consume_skb - free an skbuff
 * @skb: buffer to free
 *
 * Drop a ref to the buffer and free it if the usage count has hit zero
 * Functions identically to kfree_skb, but kfree_skb assumes that the frame
 * is being dropped after a failure and notes that
 */
consume_skb(const sk_buff *skb)
{
    if (unlikly(!skb))
        return;
    if (likely(atomic_read(&skb->users) == 1))
        smp_rmb();
    else if (likely(!atomic_dec_and_test(&skb->users)))
        return;
    trace_consume_skb(skb);
    __kfree_skb(skb);
}

skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)
{

}


 

  • 1
    点赞
  • 1
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值