linux内核版本3.19
struct sk_buff {
union {
struct {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
//next和prev指针:协议栈中经常用到sk_buff的队列,队列通过sk_buff中的指针相连接。这两个指针用来连接相关的skb的(例如有分片,则将这些分片连在一起。)
union {
ktime_t tstamp;
struct skb_mstamp skb_mstamp;
};//报文到达或者离开的时间戳;
};
struct rb_node rbnode; /* used in netem & tcp stack */
};
struct sock *sk;//指向报文所属的套接字指针;
struct net_device *dev;//表示一个接收或者发送报文的网络设备;
/*
* This is the control buffer. It is free to use for every
* layer. Please put your private variables there. If you
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever has the skb queued ATM.
*/
char cb[48] __aligned(8);//保存每一层的控制信息,以及私有信息;
unsigned long _skb_refdst;
void (*destructor)(struct sk_buff *skb); 这是析构函数,后期在skb内存销毁时会用到
#ifdef CONFIG_XFRM
struct sec_path *sp;//安全路径,用于xfrm
#endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;//netfilter跟踪的连接信息;
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
struct nf_bridge_info *nf_bridge;//桥接相关信息;
#endif
unsigned int len,//当前协议数据包的长度,包括主缓冲区中数据长度和分片中数据长度(个人理解为当前协议层包头和数据区域长度)。skb的组成是sk_buff控制+线性数据+非线性数据(skb_shared_info)组成!
data_len;//分片中数据长度
__u16 mac_len,//mac报头的长度
hdr_len;//用于clone时,表示clone的skb的头长度;
/* Following fields are _not_ copied in __copy_skb_header()
* Note that queue_mapping is here mostly to fill a hole.
*/
kmemcheck_bitfield_begin(flags1);
__u16 queue_mapping;//队列映射
__u8 cloned:1,//是否允许被克隆
nohdr:1,//运载时不能修改头部
fclone:2,//数据包克隆状态
peeked:1,//数据包是否处于操作状态
head_frag:1,
xmit_more:1;
/* one bit hole */
kmemcheck_bitfield_end(flags1);
/* fields enclosed in headers_start/headers_end are copied
* using a single memcpy() in __copy_skb_header()
*/
/* private: */
__u32 headers_start[0];
/* public: */
/* if you move pkt_type around you also must adapt those constants */
#ifdef __BIG_ENDIAN_BITFIELD
#define PKT_TYPE_MAX (7 << 5)
#else
#define PKT_TYPE_MAX 7
#endif
#define PKT_TYPE_OFFSET() offsetof(struct sk_buff, __pkt_type_offset)
__u8 __pkt_type_offset[0];
__u8 pkt_type:3;//报文类型
__u8 pfmemalloc:1;
__u8 ignore_df:1;//是否允许分片相关标志位
__u8 nfctinfo:3;//数据包连接关系
__u8 nf_trace:1;//netfilter对数据包的跟踪标志
__u8 ip_summed:2;//ip校验和标志
__u8 ooo_okay:1;
__u8 l4_hash:1;
__u8 sw_hash:1;
__u8 wifi_acked_valid:1;
__u8 wifi_acked:1;
__u8 no_fcs:1;
/* Indicates the inner headers are valid in the skbuff. */
__u8 encapsulation:1;
__u8 encap_hdr_csum:1;
__u8 csum_valid:1;
__u8 csum_complete_sw:1;
__u8 csum_level:2;
__u8 csum_bad:1;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
__u8 ipvs_property:1;
__u8 inner_protocol_type:1;
__u8 remcsum_offload:1;
/* 3 or 5 bit hole */
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd; /* traffic control verdict */
#endif
#endif
union {
__wsum csum;//校验和
struct {
__u16 csum_start;//skb->head即校验和计算起始点;
__u16 csum_offset;//校验和存储位置偏移(以csum_start处起始偏移csum_offset大小)
};
};
__u32 priority;//报文排队优先级,取决于ip中的tos域
int skb_iif;//报文到达接口的索引号;
__u32 hash;//数据包的hash值;
__be16 vlan_proto;//vlan封装协议;
__u16 vlan_tci;//vlan标签控制信息;
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int napi_id;
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;
#endif
union {
__u32 mark;
__u32 dropcount;
__u32 reserved_tailroom;
};
union {
__be16 inner_protocol;
__u8 inner_ipproto;
};
__u16 inner_transport_header;//内部封装的传输层头;
__u16 inner_network_header;//内部封装的网络层头;
__u16 inner_mac_header;
__be16 protocol;//协议
__u16 transport_header;//传输层头
__u16 network_header;//网络层头
__u16 mac_header;//链路层头
/* private: */
__u32 headers_end[0];
/* public: */
/* 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;//该缓冲区分配的所有总的内存,包括:skb_buff + 所有数据大小;
atomic_t users;//保存引用skb_buff的数量
};