SKB中的各种长度、数据指针和操作函数
skb结构体中的长度和数据指针len: 线性区和分片区域的总长度data_len:分片区域frag page中的数据长度len-data_len: 当前协议层中的线性区长度head:线性区的起始地址data:数据的起始地址tail:数据的结束地址end:线性区的结束地址headroom:从head到data之间的空间tailroom:从tail到end之间的空间除了上面的几个成员,特别指出一个tr
skb结构体中的长度和数据指针
len: 线性区和分片区域的总长度
data_len:分片区域frag page中的数据长度
len-data_len: 当前协议层中的线性区长度
head:线性区的起始地址
data:数据的起始地址
tail:数据的结束地址
end:线性区的结束地址
headroom:从head到data之间的空间
tailroom:从tail到end之间的空间
除了上面的几个成员,特别指出一个truesize,它表示一个skb所消耗的内存,包括了skb结构体本身,skb shared info结构体和对应的数据区总占用内存大小。对于truesize来说,内核的定义如下:
#define SKB_TRUESIZE(X) ((X) + \
SKB_DATA_ALIGN(sizeof(struct sk_buff)) + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
skb操作函数
对于只有线性区的skb来说,有如下一些操作函数:
skb_put(): 向后扩大数据区空间。headroom空间不变,tailroom空间降低,skb->data指针不变,skb->tail指针下移;
skb_push(): 向前扩大数据区空间。headroom空间降低,tailroom空间不变。skb->tail指针不变,skb->data指针上移;
skb_pull(): 缩小数据区空间.headroom空间增大,tailroom空间不变,skb->data指针下移,skb->tail指针不变;
skb_reserve(): 数据区空间大小不变,headroom空间增大,tailroom空间降低,skb->data和skb->tail同时下移;
skb_reserve()只能用于空的SKB,通常会在分配SKB之后就调用该函数,此时data和tail指针还一同指向数据区的起始位置。例如,某个以太网设备驱动的接收函数,在分配SKB之后,向数据缓存区填充数据之前,会有这样的一条语句skb_reserve(skb, 2),这是因为以太网头长度为14B,再加上2B就正好16字节边界对齐,所以大多数以太网设备都会在数据包之前保留2B。
如果该skb存在分片的frag page,那么不能使用上面的函数了,必须使用:
pskb_pull():
对于带有frag page的分片skb来说,data指针往下移动,可能会导致线性区越界,因此需要判断是否线性区有足够的空间用来pull操作,如果空间不够,那么需要执行linearize,重构线性区,把一部分frags中的数据移动到线性区中来操作。
pskb_may_pull():
主要在使用skb_pull之前来检查线性区buffer有没有足够的数据用于 pull。
pskb_copy():
参考上图(a)只skb拷贝线性区的数据,对于分片的skb来说它的shared_info会拷贝过来,但是指向的frag page是共享的。所以使用该函数拷贝生成的新的skb只能修改线性区中的数据。
skb_copy():
参考上图(b)拷贝线性区和分片区的所有数据,一个分片的skb经过拷贝后会生成一个完全线性的skb。对于只想修改header的操作,建议不要使用该函数,而应该使用pskb_copy()。
skb_clone():
参考本文第一张图,只拷贝skb结构体,对应的head/data/tail/end指针指向的线性区还是共享的,所以clone的skb是不能修改其中的数据的。
https://www.cnblogs.com/zfyouxi/p/4560841.html
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)