linux 内核网络sk_buff布局字段 “每日读书”

sk_buff 有些字段只是为了方便搜寻以及组织数据结构本身,内核在一个双向链表中维护所有的sk_buff结构,但是该表的组织比传统的双向链表更为复杂。

像任何双向链表一样,通过每个sk_buff 结构中的next和prev字段实现联系,next字段只想前,prev指向后,但是,这个表还有另一项必要需求,每个sk_buff 结构必须能够快速找到整个表的头,为了实现这个,在表的开端额外增加一个sk_buff_head 结构作为一种哑元元素,sk_buff_head结构是,

struct sk_buff_head {

struct sk_buff *next;

struct sk_buff *prev;

__u32 qlen;

spinlock_t lock;

}

qlen 代表表中的元素的数目,lock是用于防止对表的并发访问,在本章稍后的表管理函数,一节中会予以描述。

sk_buff和sk_buff_head 的前两个元素是相同的,next和prev指针,尽管sk_buff_head与sk_buff 相比实在太小,但是还是允许两个结构共同存在一个表中。

另外,同样的函数也可以用于操作sk_buff和sk_buff_head二者。

每个sk_buff 结构都包涵一个指针,指向单一的sk_buff_head 结构,增加了其复杂性,这个指针的字段名称为list, 图2-1 有助于你了解这些数据结构的关系。

sk_buff其他感兴趣的字段如下:

struct sock *sk

这是一个指针,指向拥有此缓冲区的套接字的sock数据结构,当数据在本地产生或者正由本地的进程接收时,就需要这个指针。因为该数据以及套接字相关的信息会由L4(TCP或者UDP)以及用户应用程序使用,当缓冲区只是被转发时,该指针就是NULL。

unsigned int len

这是指缓冲区中数据区块的大小。这个长度包括主要缓冲区的数据以及一些片段的数据,当缓冲区从一个网络分层移往下一个网络分层的时候,值就会变化,因为在协议栈重往上移动时报头就会被丢弃,但是往下移动的时候,就会添加进来,len也会吧协议报头算在内,如数据预留和对齐,skb_reserve,skb_put, skb_push 以及skb_pull 一节中国呢的图2-8所示。

unsigned int data_len

与len不同的是,data_len 只计算片段中的数据大小。

unsigned int mac_len

MAC报头的大小。

atomic_t user

这是引用计数,或者使用这个sk_buff缓冲区的实例的树木,这个参数的主要用途是避免在某人依然使用sk_buff结构时,把这个结构给释放,因此,此缓冲区的每个用户在必要时,都要递增和递减此字段,此计数器只计算sk_buff数据结构的用户,此缓冲区所包含的实际数据由一个相似的字段dataref 所包含,本章稍后的skb_shared_info 结构和skb_shinfo 函数,一节将予以介绍。

users 有时会直接用atomic_inc和atomic_dec函数递增和递减,但是大多数情况下,采用skb_get和kfree_skb 进行处理。

unsigned int truesize

此字段代表此缓冲区总的大小,包括sk_buff结构本身,当此缓冲区得到所分配的len个字符的数据请求空间时,此字段的初始化由alloc_skb函数设置成len + sizeof(sk_buff)

struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)

{

skb->truesize = size + sizeof(struct sk_buff);

}

每当skb->len的值增加时,此字段就会得到更新。

unsigned char *head;

unsigned char *end;

unsigned char *data;

unsigned char *tail

这些字段代表缓冲区边界一起其中的数据,每当一个分层为其工作而准备缓冲区时,可能会为一个报头或者更多的数据分配更多的空间。head和end指向已经分配缓冲区空间的开端和尾端,而data和tail则指向实际数据的开端和尾端,参见图2-2所示,然后,该分层可以吧head和data之间的空隙填上一个协议报头,或者以新数据填入tail和head之间的空隙。在稍后的分配内存,alloc_skb 和dev_alloc_skb 一节中就会知道,图2-2右边的缓冲区在底端包含一个附加报头。

void (*destructor)(...)

此函数可以被初始化为一个函数,当此缓冲区被删除时,可完成某些工作,当此缓冲区不属于一个套接字时,destructor 通常不湖北初始化,此缓冲区属于一个套接字时,通常吧诶设置成sock_kfree或者sock_wfree ,这两个sock_xxx函数可用于更新套接字队列中所持有的内存。

相关推荐
发量惊人的中年网工几秒前
SD-WAN如何赋能工业物联网?打造工厂网络远程连接和数据传输新方案
运维·网络·分布式·物联网
Chengbei115 分钟前
云存储桶漏洞检测工具OSS-2.0更新,全类型文件解析,存储桶遍历 + 敏感排查一站式完成渗透取证
网络·安全·web安全·网络安全·xss
面对疾风叭!哈撒给5 分钟前
Linux ARM架构的docker和docker-compose离线安装
linux·docker·架构
乐维_lwops18 分钟前
乐维社区“专家坐诊”第403期问答
运维·网络·监控系统·答疑·lerwee运维智能体
阿虎儿27 分钟前
Linux 下为局域网 IP(如 192.168.1.100)打造不受浏览器警告的自签名 SSL/TLS 证书
linux·安全·https
小王C语言1 小时前
虚拟机开机过程中关机,再次开机没有分配 IP
linux·网络·tcp/ip
零零信安1 小时前
暗网监测技术实践(一):威胁源采集与反爬对抗——基于《暗网情报技术能力框架》的双生态视角
网络·数据泄露·零零信安
薛定谔的悦1 小时前
光储系统 AEMS 模块的光伏控制模式设计
linux·能源·储能·bms
翼龙云_cloud1 小时前
阿里云国际站代理商:ECS弹性伸缩 自动应对流量高峰
运维·网络·数据库·阿里云·架构
ZJH__GO1 小时前
网络编程v4--群聊和私聊的实现
运维·服务器·网络