报社网站建设之思考,嘉兴网站建设定制,青海风控app下载,西安关键词优化排名skb_buff基本原理
内核中sk_buff结构体在各层协议之间传输不是用拷贝sk_buff结构体#xff0c;而是通过增加协议头和移动指针来操作的。如果是从L4传输到L2#xff0c;则是通过往sk_buff结构体中增加该层协议头来操作#xff1b;如果是从L4到L2#xff0c;则是通过移动sk_…skb_buff基本原理
内核中sk_buff结构体在各层协议之间传输不是用拷贝sk_buff结构体而是通过增加协议头和移动指针来操作的。如果是从L4传输到L2则是通过往sk_buff结构体中增加该层协议头来操作如果是从L4到L2则是通过移动sk_buff结构体中的data指针来实现不会删除各层协议头这样方式极大的提高CPU工作效率。
sk_buff结构体是linux网络代码中最重要的数据结构是整个网络传输载体。所以sk_buff结构体里面有很多关于其他功能的成员字段比如防火墙子路由系统多播等。这些字段并不是一定有的只有在满足特点条件才有的。所以可以在需要时候再去关心这些成员字段现在我们只来讲解主要的成员字段。 skb_buff主要字段
为了好理解结构中的一些成员字段先把后面要讲的内容提前说下。sk_buff结构体关联多个其他结构体主要可以分为 第一是数据区由sk_buff中head和end指向的数据块用来存储sk_buff结构的数据也即是存储数据包的内容和各层协议头。 第二是分片结构用来表示IP分片的一个结构体实则上是和sk_buff结构的数据区相连的即是end指针的下一个字节开始就是分片结构。正因此分片结构和sk_buff数据区内存分配及销毁时都是一起的。 第三个是分片结构指向的数据区即是IP分片内容。 struct sk_buff {
/* These two members must be first. */
struct sk_buff *next; // 因为sk_buff结构体是双链表所以有前驱后继。这是个指向后面的sk_buff结构体指针
struct sk_buff *prev; // 这是指向前一个sk_buff结构体指针
//老版本2.6以前应该还有个字段 sk_buff_head *list //即每个sk_buff结构都有个指针指向头节点
struct sock *sk; // 指向拥有此缓冲的套接字sock结构体即宿主传输控制模块
ktime_t tstamp; // 时间戳表示这个skb的接收到的时间一般是在包从驱动中往二层发送的接口函数中设置
struct net_device *dev; // 表示一个网络设备当skb为输出/输入时dev表示要输出/输入到的设备
unsigned long skb_dst; // 主要用于路由子系统保存路由有关的东西
char cb[48]; // 保存每层的控制信息,每一层的私有信息
unsigned int len, // 表示数据区的长度(tail - data)与分片结构体数据区的长度之和。其实这个len中数据区长度是个有效长度因为不删除协议头所以只计算有效协议头和包内容。如当在L3时不会计算L2的协议头长度。
data_len; // 只表示分片结构体数据区的长度所以len (tail - data) data_len
__u16 mac_len, // mac报头的长度
hdr_len; // 用于clone时表示clone的skb的头长度 // 接下来是校验相关域这里就不详细讲了。
__u32 priority; // 优先级主要用于QOS
kmemcheck_bitfield_begin(flags1);
__u8 local_df:1, // 是否可以本地切片的标志
cloned:1, // 为1表示该结构被克隆或者自己是个克隆的结构体同理被克隆时自身skb和克隆skb的cloned都要置1
ip_summed:2,
nohdr:1, // nohdr标识payload是否被单独引用不存在协议首部。 // 如果被引用则决不能再修改协议首部也不能通过skb-data来访问协议首部。/span/span
nfctinfo:3;
__u8 pkt_type:3, // 标记帧的类型
fclone:2, // 这个成员字段是克隆时使用表示克隆状态
ipvs_property:1,
peeked:1,
nf_trace:1;
__be16 protocol:16; // 这是包的协议类型标识是IP包还是ARP包或者其他数据包。
kmemcheck_bitfield_end(flags1);
void (*destructor)(struct sk_buff *skb); // 这是析构函数后期在skb内存销毁时会用到
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;
struct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
int iif; // 接受设备的index
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd; /* traffic control verdict */
#endif
#endif
kmemcheck_bitfield_begin(flags2);
__u16 queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
kmemcheck_bitfield_end(flags2);
/* 0/14 bit hole */
#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;
#endif
__u32 mark;
__u16 vlan_tci;
sk_buff_data_t transport_header; // 指向四层帧头结构体指针
sk_buff_data_t network_header; // 指向三层IP头结构体指针
sk_buff_data_t mac_header; // 指向二层mac头的头
/* These elements must be at the end, see alloc_skb() for details. */
sk_buff_data_t tail; // 指向数据区中实际数据结束的位置
sk_buff_data_t end; // 指向数据区中结束的位置非实际数据区域结束位置
unsigned char *head, //指向数据区中开始的位置非实际数据区域开始位置
*data; // 指向数据区中实际数据开始的位置
unsigned int truesize; // 表示总长度包括sk_buff自身长度和数据区以及分片结构体的数据区长度
atomic_t users; // skb被克隆引用的次数在内存申请和克隆时会用到
}; //end sk_buff char cb[48]这个字段是skb信息控制块也就是存储每层的一些协议信息当数据包在哪一层时存储的就是哪一层协议信息。这个字段由数据包所在层使用和维护如果要访问本层协议信息可以通过用一些宏来操作这个成员字段。如#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)((__skb)-cb[0]))
_u8 fclone:2这是个克隆状态标志到sk_buff结构内存申请时会使用到。这里提前讲下若fclone SKB_FCLONE_UNAVAILABLE则表明SKB未被克隆若fclone SKB_FCLONE_ORIG则表明是从skbuff_fclone_cache缓存池这个缓存池上分配内存时每次都分配一对skb内存中分配的父skb可以被克隆若fclone SKB_FCLONE_CLONE则表明是在skbuff_fclone_cache分配的子SKB从父SKB克隆得到的
atomic_t users这是个引用计数表明了有多少实体引用了这个skb。其作用就是在销毁skb结构体时先查看下users是否为零若不为零则调用函数递减下引用计数users即可当某一次销毁时users为零才真正释放内存空间。有两个操作函数atomic_inc()引用计数增加1atomic_dec()引用计数减去1 sk_buff-len表示当前缓冲区中数据块的大小的总长度。它包括主缓冲中即是sk_buff结构中指针data指向的数据区的实际长度data-tail和分片中的数据长度。这个长度在数据包在各层间传输时会改变因为分片数据长度不变从L2到L4时则len要减去帧头大小和网络头大小从L4到L2则相反要加上帧头和网络头大小。所以len (data - tail) data_len sk_buff-truesize这是缓冲区的总长度包括sk_buff结构和数据部分。如果申请一个len字节的缓冲区alloc_skb函数会把它初始化成lensizeof(sk_buff)。当skb-len变化时这个变量也会变化。所以truesize len sizeof(sk_buff) (data - tail) data_len sizeof(sk_buff)