skb 几个关键指针
Note: 针对于Linux2.6,随之Linux迁移,可能会有所变化。
在申请一个skb的时候,其实申请了两块内存,一块用于存放sk_buff,另一块用于存放真正的包内的数据。
在sk_buff当中会有几个指针指向数据块内存。
- skb->head: 申请的数据块的头
- skb->end: 申请的数据块的尾
- skb->data: 申请的有效数据块的头
- skb->tail: 申请的有效数据块的结尾
- skb->len: 指的是有效数据块的长度
如下图所示:
skb_push: 向数据有效区加协议头
static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
{
skb->data -= len;
skb->len += len;
if (unlikely(skb->data<skb->head))
skb_under_panic(skb, len, current_text_addr());
return skb->data;
}
skb_pull: 将某个协议头从数据有效区移出
static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb->len -= len;
BUG_ON(skb->len < skb->data_len);
return skb->data += len;
}
static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
{
return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
}
skb_put: 向数据有效区加协议尾
static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
{
unsigned char *tmp = skb->tail;
SKB_LINEAR_ASSERT(skb);
skb->tail += len;
skb->len += len;
if (unlikely(skb->tail>skb->end))
skb_over_panic(skb, len, current_text_addr());
return tmp;
}
skb_reserve: 增加头部空间
static inline void skb_reserve(struct sk_buff *skb, unsigned int len)
{
skb->data += len;
skb->tail += len;
}