sk_buff结构

sk_buff结构用来描述已接收或者待发送的数据报文信息;skb在不同网络协议层之间传递,可被用于不同网络协议,如二层的mac或其他链路层协议,三层的ip,四层的tcp或者udp协议,其中某些成员变量会在该结构从一层向另一层传递时发生改变,从上层向下层传递需要添加首部,从下层向上层传递需要移除首部;

 1 /* skb头结构 */
 2 struct sk_buff_head {
 3     /* These two members must be first. */
 4     /* 通过下面两个指针成员将skb连接成双向链表 */
 5     struct sk_buff    *next; /* 指向后一个skb */
 6     struct sk_buff    *prev; /* 指向前一个skb */
 7
 8     __u32        qlen; /* 链表中元素个数 */
 9     spinlock_t    lock; /* 自旋锁 */
10 };
  1 /**
  2  *    struct sk_buff - socket buffer
  3  *    @next: Next buffer in list
  4  *    @prev: Previous buffer in list
  5  *    @tstamp: Time we arrived/left
  6  *    @rbnode: RB tree node, alternative to next/prev for netem/tcp
  7  *    @sk: Socket we are owned by
  8  *    @dev: Device we arrived on/are leaving by
  9  *    @cb: Control buffer. Free for use by every layer. Put private vars here
 10  *    @_skb_refdst: destination entry (with norefcount bit)
 11  *    @sp: the security path, used for xfrm
 12  *    @len: Length of actual data
 13  *    @data_len: Data length
 14  *    @mac_len: Length of link layer header
 15  *    @hdr_len: writable header length of cloned skb
 16  *    @csum: Checksum (must include start/offset pair)
 17  *    @csum_start: Offset from skb->head where checksumming should start
 18  *    @csum_offset: Offset from csum_start where checksum should be stored
 19  *    @priority: Packet queueing priority
 20  *    @ignore_df: allow local fragmentation
 21  *    @cloned: Head may be cloned (check refcnt to be sure)
 22  *    @ip_summed: Driver fed us an IP checksum
 23  *    @nohdr: Payload reference only, must not modify header
 24  *    @pkt_type: Packet class
 25  *    @fclone: skbuff clone status
 26  *    @ipvs_property: skbuff is owned by ipvs
 27  *    @tc_skip_classify: do not classify packet. set by IFB device
 28  *    @tc_at_ingress: used within tc_classify to distinguish in/egress
 29  *    @tc_redirected: packet was redirected by a tc action
 30  *    @tc_from_ingress: if tc_redirected, tc_at_ingress at time of redirect
 31  *    @peeked: this packet has been seen already, so stats have been
 32  *        done for it, don‘t do them again
 33  *    @nf_trace: netfilter packet trace flag
 34  *    @protocol: Packet protocol from driver
 35  *    @destructor: Destruct function
 36  *    @_nfct: Associated connection, if any (with nfctinfo bits)
 37  *    @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 38  *    @skb_iif: ifindex of device we arrived on
 39  *    @tc_index: Traffic control index
 40  *    @hash: the packet hash
 41  *    @queue_mapping: Queue mapping for multiqueue devices
 42  *    @xmit_more: More SKBs are pending for this queue
 43  *    @ndisc_nodetype: router type (from link layer)
 44  *    @ooo_okay: allow the mapping of a socket to a queue to be changed
 45  *    @l4_hash: indicate hash is a canonical 4-tuple hash over transport
 46  *        ports.
 47  *    @sw_hash: indicates hash was computed in software stack
 48  *    @wifi_acked_valid: wifi_acked was set
 49  *    @wifi_acked: whether frame was acked on wifi or not
 50  *    @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
 51  *    @dst_pending_confirm: need to confirm neighbour
 52   *    @napi_id: id of the NAPI struct this skb came from
 53  *    @secmark: security marking
 54  *    @mark: Generic packet mark
 55  *    @vlan_proto: vlan encapsulation protocol
 56  *    @vlan_tci: vlan tag control information
 57  *    @inner_protocol: Protocol (encapsulation)
 58  *    @inner_transport_header: Inner transport layer header (encapsulation)
 59  *    @inner_network_header: Network layer header (encapsulation)
 60  *    @inner_mac_header: Link layer header (encapsulation)
 61  *    @transport_header: Transport layer header
 62  *    @network_header: Network layer header
 63  *    @mac_header: Link layer header
 64  *    @tail: Tail pointer
 65  *    @end: End pointer
 66  *    @head: Head of buffer
 67  *    @data: Data head pointer
 68  *    @truesize: Buffer size
 69  *    @users: User count - see {datagram,tcp}.c
 70  */
 71 /* skb结构 */
 72 struct sk_buff {
 73     union {
 74         struct {
 75             /* These two members must be first. */
 76             struct sk_buff        *next;
 77             struct sk_buff        *prev;
 78
 79             /* 报文到达或者离开的时间戳 */
 80             union {
 81                 ktime_t        tstamp;
 82                 struct skb_mstamp skb_mstamp;
 83             };
 84         };
 85         struct rb_node    rbnode; /* used in netem & tcp stack */
 86     };
 87
 88     /*
 89         指向缓冲区的套接字sock数据结构。当数据在本地产生或者正由本地进程接收时,
 90         该数据以及套接字相关信息会被L4(tcp或者udp)以及用户应用程序使用
 91         当缓冲区只是被转发时(本地机器不是来源也不是目的地),该指针为NULL
 92     */
 93     struct sock        *sk;
 94
 95     union {
 96         /* 报文到达或者离开时的网络设备 */
 97         struct net_device    *dev;
 98         /* Some protocols might use this space to store information,
 99          * while device pointer would be NULL.
100          * UDP receive path is one user.
101          */
102         unsigned long        dev_scratch;
103     };
104     /*
105      * This is the control buffer. It is free to use for every
106      * layer. Please put your private variables there. If you
107      * want to keep them across layers you have to do a skb_clone()
108      * first. This is owned by whoever has the skb queued ATM.
109      */
110     /*
111         控制缓冲区,用于存储私有信息,每层协议自己维护并使用,
112         并且只在本层有有效
113     */
114     char            cb[48] __aligned(8);
115
116     /* 路由缓存,输入或者输出报文都要查询到目的路由缓存项,才能确定流向 */
117     unsigned long        _skb_refdst;
118
119     /*
120         当缓冲区被删除时,可以完成某些清理工作
121         当缓冲区不属于一个套接字时,该函数通常不被初始化
122         属于一个套接字时,通常设置为sock_rfree或sock_wfree
123         sock_xxx函数用于更新套接字队列中所持有的内存
124     */
125     void            (*destructor)(struct sk_buff *skb);
126 #ifdef CONFIG_XFRM
127     struct    sec_path    *sp;
128 #endif
129 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
130     unsigned long         _nfct;
131 #endif
132 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
133     struct nf_bridge_info    *nf_bridge;
134 #endif
135     /*
136         缓冲区的数据区块大小,该长度包括主缓冲区(head指针指向)的数据
137         以及一些片段(fragment)的数据,当缓冲区从一个网络分层移动到下一个
138         网络分层时,该值会发生变化,因为在协议栈中向上层移动时报头会被丢弃
139         向下层移动时报头会添加,len也会把协议报头算在内,与"数据预留和对齐"操作
140     */
141     unsigned int        len,
142     /* 片段(fragment)中的数据大小 */
143                 data_len;
144     /* mac报头大小 */
145     __u16            mac_len,
146     /* 克隆skb时可写报文头部长度 */
147                 hdr_len;
148
149     /* Following fields are _not_ copied in __copy_skb_header()
150      * Note that queue_mapping is here mostly to fill a hole.
151      */
152     kmemcheck_bitfield_begin(flags1);
153     __u16            queue_mapping;
154
155 /* if you move cloned around you also must adapt those constants */
156 #ifdef __BIG_ENDIAN_BITFIELD
157 #define CLONED_MASK    (1 << 7)
158 #else
159 #define CLONED_MASK    1
160 #endif
161 #define CLONED_OFFSET()        offsetof(struct sk_buff, __cloned_offset)
162
163     __u8            __cloned_offset[0];
164     /* 表示该skb是另外一个skb的克隆 */
165     __u8            cloned:1,
166                 /*
167     payload是否被单独引用,不存在协议首部,如果被引用,则不能修改协议首部,也不能通过skb->data来访问协议首部
168                 */
169                 nohdr:1,
170                 /*
171                     当前克隆状态
172                     SKB_FCLONE_UNAVAILABLE-skb未被克隆
173                     SKB_FCLONE_ORIG-在skbuff_fclone_cache分配的父skb,可以被克隆
174     SKB_FCLONE_CLONE-在skbuff_fclone_cache分配的子skb,从父skb克隆得到
175                 */
176                 fclone:2,
177                 peeked:1,
178                 head_frag:1,
179                 xmit_more:1,
180                 __unused:1; /* one bit hole */
181     kmemcheck_bitfield_end(flags1);
182
183     /* fields enclosed in headers_start/headers_end are copied
184      * using a single memcpy() in __copy_skb_header()
185      */
186     /* private: */
187     __u32            headers_start[0];
188     /* public: */
189
190 /* if you move pkt_type around you also must adapt those constants */
191 #ifdef __BIG_ENDIAN_BITFIELD
192 #define PKT_TYPE_MAX    (7 << 5)
193 #else
194 #define PKT_TYPE_MAX    7
195 #endif
196 #define PKT_TYPE_OFFSET()    offsetof(struct sk_buff, __pkt_type_offset)
197
198     __u8            __pkt_type_offset[0];
199     /*
200         此字段根据l2的目的地址进行划分
201         PACKET_HOST-mac地址与接收设备mac地址相等,说明是发给该主机的
202         PACKET_BROADCAST-mac地址是接收设备的广播地址
203         PACKET_MULTICAST-mac地址接收改设备注册的多播地址之一
204         PACKET_OTHERHOST-mac地址不属于接收设备的地址,启用转发则转发,否则丢弃
205         PACKET_OUTGOING-数据包将被发出,用到这个标记的功能包括decnet,
206 或者为每个网络tab都复制一份发出包的函数
207         PACKET_LOOPBACK-数据包发往回环设备,有此标识,处理回环设备时,
208         可以跳过一些真实设备所需的操作
209         PACKET_USER-发送到用户空间,netlink使用
210         PACKET_KERNEL-发送到内核空间,netlink使用
211         PACKET_FASTROUTE-未使用
212     */
213     __u8            pkt_type:3;
214     __u8            pfmemalloc:1;
215     __u8            ignore_df:1;
216
217     __u8            nf_trace:1;
218     /*
219         CHECKSUM_NONE-硬件不支持,完全由软件执行校验和
220         CHECKSUM_PARTIAL-由硬件来执行校验和
221         CHECKSUM_UNNECESSARY-没必要执行校验和
222         CHECKSUM_COMPLETE-已完成执行校验和
223     */
224     __u8            ip_summed:2;
225     __u8            ooo_okay:1;
226     __u8            l4_hash:1;
227     __u8            sw_hash:1;
228     __u8            wifi_acked_valid:1;
229     __u8            wifi_acked:1;
230
231     __u8            no_fcs:1;
232     /* Indicates the inner headers are valid in the skbuff. */
233     __u8            encapsulation:1;
234     __u8            encap_hdr_csum:1;
235     __u8            csum_valid:1;
236     __u8            csum_complete_sw:1;
237     __u8            csum_level:2;
238     __u8            csum_bad:1;
239
240     __u8            dst_pending_confirm:1;
241 #ifdef CONFIG_IPV6_NDISC_NODETYPE
242     __u8            ndisc_nodetype:2;
243 #endif
244     __u8            ipvs_property:1;
245     __u8            inner_protocol_type:1;
246     __u8            remcsum_offload:1;
247 #ifdef CONFIG_NET_SWITCHDEV
248     __u8            offload_fwd_mark:1;
249 #endif
250 #ifdef CONFIG_NET_CLS_ACT
251     __u8            tc_skip_classify:1;
252     __u8            tc_at_ingress:1;
253     __u8            tc_redirected:1;
254     __u8            tc_from_ingress:1;
255 #endif
256
257 #ifdef CONFIG_NET_SCHED
258     __u16            tc_index;    /* traffic control index */
259 #endif
260
261     union {
262         /* 校验和,必须包含csum_start和csum_offset */
263         __wsum        csum;
264         struct {
265             /* 校验开始位置,相对于header */
266             __u16    csum_start;
267             /* 校验和存储位置,相对于csum_start */
268             __u16    csum_offset;
269         };
270     };
271     /*
272         正在被传输的数据包QoS等级
273         数据包由本地产生,套接字会定义优先级的值
274         数据包在被转发,则在调用ip_forward函数时,会根据
275         ip头本身的ToS字段定义该值
276     */
277     __u32            priority;
278     int            skb_iif;
279     __u32            hash;
280     __be16            vlan_proto;
281     __u16            vlan_tci;
282 #if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
283     union {
284         unsigned int    napi_id;
285         unsigned int    sender_cpu;
286     };
287 #endif
288 #ifdef CONFIG_NETWORK_SECMARK
289     __u32        secmark;
290 #endif
291
292     union {
293         __u32        mark;
294         __u32        reserved_tailroom;
295     };
296
297     /* 封装的协议 */
298     union {
299         __be16        inner_protocol;
300         __u8        inner_ipproto;
301     };
302     /* 封装的传输层头部相对于head的偏移 */
303     __u16            inner_transport_header;
304     /* 封装的网络层头部相对于head的偏移 */
305     __u16            inner_network_header;
306     /* 封装的链路层头部相对于head的偏移 */
307     __u16            inner_mac_header;
308
309     /*
310         l3层协议值
311         如ETH_P_IP-ipv4报文
312         ETH_P_ARP-arp报文等
313     */
314     __be16            protocol;
315     /* 传输层头部相对于head的偏移 */
316     __u16            transport_header;
317     /* 网络层头部相对于head的偏移 */
318     __u16            network_header;
319     /* 链路层头部相对于head的偏移 */
320     __u16            mac_header;
321
322     /* private: */
323     __u32            headers_end[0];
324     /* public: */
325
326     /* These elements must be at the end, see alloc_skb() for details.  */
327     /* 实际数据的尾部 */
328     sk_buff_data_t        tail;
329     /* 缓冲区的尾部 */
330     sk_buff_data_t        end;
331     /* 缓冲区的头部 */
332     unsigned char        *head,
333     /* 实际数据的头部 */
334                 *data;
335     /*
336         缓冲区的总大小,包括skb本身和实际数据len大小,alloc_skb函数将
337         该字段设置为len+sizeof(sk_buff)
338         每当len值更新,该值也要对应更新
339     */
340     unsigned int        truesize;
341
342     /*
343         引用计数,在使用该skb缓冲区的实例个数,当引用计数为0时,skb才能被释放
344         skb_get()获取操作中会增加引用计数,kfree_skb释放过程中检查引用计数,
345         引用计数为0时,才真正释放skb
346         该计数器只计算sk_buff结构引用计数,缓冲区包含的实际数据由
347         skb_shared_info->dataref字段记录
348     */
349     atomic_t        users;
350 };
时间: 2024-08-09 10:44:47

sk_buff结构的相关文章

struct sk_buff 结构

struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用.    这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变. L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部.添加头部比在不同层之间拷贝数据的效率更高.由于在缓冲区的头部 添加数据意味着要修改指向缓冲区的指针,这是个复杂

struct sk_buff结构体详解

struct sk_buff是linux网络系统中的核心结构体,linux网络中的所有数据包的封装以及解封装都是在这个结构体的基础上进行. struct sk_buff_head  {     struct sk_buff *next;     struct sk_buff *prev;          __u32 qlen;     spinlock_t lock; } struct sk_buff {     struct sk_buff *next;     struct sk_buff

sk_buff整理笔记(二、操作函数)

承接上一篇:sk_buff整理笔记(一.数据结构)这一篇要讲的是内核为sk_buff结构提供的一些操作函数. 第一.首先要讲的是sk_buff中的四大指针: 四大指针分别是:head.data.tail.end:这四个指针都是指向了数据区的,数据区中存放的是协议头和数据.head和end指针是每个数据包一样的,也是有这两个指针来确定数据区的大小的.最开始的时候head.data.tail三个指针都是指向一起的,当有协议数据加进来时才更改. 再来说下包的形成,首先是应用层的数据,然后到四层加上四层

【驱动】网卡驱动&#183;linux内核网络分层结构

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liucw.blog.51cto.com/6751239/1221140 Preface   Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程,又便于扩展和维护. 内核网络结构 在Linux内核中,对网络部分按照网络协议层.网络设备层.设备驱动功能层

剖析数据结构sk_buff (一)

1 sk_buff介绍 sk_buff(socket buffer)结构是linux网络代码中重要的数据结构,它管理和控制接收或发送数据包的信息. 2 sk_buff组成 Packet data:通过网卡收发的报文,包括链路层.网络层.传输层的协议头和携带的应用数据,包括head room,data,tail room三部分. skb_shared_info 作为packet data的补充,用于存储ip分片,其中sk_buff *frag_list是一系列子skbuff链表,而frag[]是由

sk_buff 剖析 (二)

5 sk_buff管理和操作函数 5.1缓冲区操作函数 有很多函数,通常都比较短小而且简单,内核用这些函数操作sk_buff的成员变量或者sk_buff链表.首先来看分配和释放缓冲区的函数,然后是一些通过移动指针在缓冲区的头部或尾部预留空间的函数.如果你看过include/linux/skbuff.h和net/core/skbuff.c中的函数,你会发现,基本上每个函数都有两个版本,名字分别是do_something和__do_something.通常第一种函数是一个包装函数,它会在第二种函数的

Network | sk_buff

sk_buff结构可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息.它在中定义,并包含很多成员变量供网络代码中的各子系统使用.    这个结构被不同的网络层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变.L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部.添加头部比在不同层之间拷贝数据的效率更高.    由于在缓冲区的头部添加数据意味着要修改指向缓冲区的指针,这是

【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析

[linux驱动分析]之dm9000驱动分析(一):dm9000原理及硬件分析 [linux驱动分析]之dm9000驱动分析(二):定义在板文件里的资源和设备以及几个宏 [linux驱动分析]之dm9000驱动分析(四):net_device结构体 [linux驱动分析]之dm9000驱动分析(五):另外几个重要的结构体 [linux驱动分析]之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现 [linux驱动分析]之dm9000驱动分析(七):dm9000的卸

sk_buff 结构分析

sk_buff分析 sk_buff是Linux网络代码中最重要的结构体之一.它是Linux在其协议栈里传送的结构体,也就是所谓的“包”,在他里面包含了各层协议的头部,比如ethernet, ip ,tcp ,udp等等.也有相关的操作等.熟悉他是进一步了解Linux网络协议栈的基础. 此结构定义在<include/linux/skbuff.h>头文件中,结构体布局大致可分为以下四部分: l       布局(layout) l       通用(general) l       功能专用(fe