linux 内核网络 sk_buff 之数据区操作函数集合Ⅱ

5 篇文章 0 订阅

目录

1 sk_buff 中的四大指针

2 sk_buff 指针数据区操作函数集

2.1 skb_put()

2.2 skb_push()

2.3 skb_pull()

2.4 skb_reserve()


1 sk_buff 中的四大指针

四大指针分别是:head、data、tail、end;这四个指针都是指向了数据区的,数据区中存放的是协议头和数据。head 和 end 指针是每个数据包一样的,也是有这两个指针来确定数据区的大小的。最开始的时候 head、data、tail 三个指针都是指向一起的,当有协议数据加进来时才更改。

再来说下包的形成,首先是应用层的数据,然后到四层加上四层的TCP协议头(假设为TCP包),然后发往三层;在三层时把四层发来的数据都当作是负载,然后再往负载前加上一个三层IP协议头,发往二层;最后二层加上个帧头就可以发送了。所以在包形成时,这几个指针起到了非常关键的作用。下面来看下四个指针的指向地址大小,这也有利于对下面要讲到一些操作函数的理解。

        

最后一句的意思是:当数据包在二层(即data指针指向二层协议头)时,获取到三层协议头指针的一种方法。当然也可以直接用自带的获取三层协议头指针的函数(其实函数里面也是用上面这句代码实现的),这里只是为了显示data增加时,是往下移动的。方便后面的几个函数理解。

2 sk_buff 指针数据区操作函数集

首先来说下三个空间,方便下面介绍函数时理解。

  1. headroom,就是 skb->head 和 skb->data 之间的空间;
  2. data,就是 skb->data 和 skb->tail 之间的空间;
  3. tailroom,就是 skb->tail 和 skb->end 之间的空间。

具体空间如下图所示:

         

接下来说下四个操作sk_buff结构中指针的函数:skb_put(), skb_push(), skb_pull(), skb_reserve();这四个函数在数据包在各层之间传输时,起到了至关重要。

2.1 skb_put()

向后扩大数据区空间,headroom 空间不变,tailroom 空间减少,skb->data 指针不变,skb->tail 指针下移;空间变化如下图所示:

代码如下:

unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
{
	unsigned char *tmp = skb_tail_pointer(skb);
	SKB_LINEAR_ASSERT(skb);
	skb->tail += len;
	skb->len  += len;
	if (unlikely(skb->tail > skb->end))
		skb_over_panic(skb, len, __builtin_return_address(0));
	return tmp;
}

2.2 skb_push()

向前扩大数据区空间,headroom空间减少,tailroom空间不变,skb->tail 指针不变,skb->data 指针上移;空间变化如下图所示:

代码如下:

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, __builtin_return_address(0));
	return skb->data;
}

2.3 skb_pull()

缩小数据区空间,headroom空间增大,tailroom空间不变,skb->data指针下移,skb->tail指针不变;空间变化如下图所示:

代码如下:

extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
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_inline(struct sk_buff *skb, unsigned int len)
{
	return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
}

unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
{
	return skb_pull_inline(skb, len);
}

2.4 skb_reserve()

数据区不变,headroom空间增大,tailroom 空间减少,skb->data 和 skb->tail 同时下移;空间变化如下图所示:

代码如下:

static inline void skb_reserve(struct sk_buff *skb, int len)
{
	skb->data += len;
	skb->tail += len;
}

 

 

 

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

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

抵扣说明:

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

余额充值