几个操作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)
{
}