关于网络套接字缓存区结构体sk_buff的解析

时间:2022-10-31 11:00:57

上面蓝色部分是对于网路套接字缓冲区结构的解释,红色部分是对于该结构体具体成员变量的解析;

其中在程序中使用到成员是data,end,tail,head等,当该结构在各协议层传输时,变动的也是data部分。需要重点理解的也主要是这几个关键成员变量;

该结构定义的文件:/linux-3.15/include\linux/skbuff.h,

而主要对该结构成员解释的文件是:/linux-3.15/net/core/skbuff.c

/** 

 *struct sk_buff - socket buffer
 * @next: Next buffer in list
 * @prev: Previous buffer in list
 * @tstamp: Time we arrived/left
 * @sk: Socket we are owned by
 * @dev: Device we arrived on/are leaving by
 * @cb: Control buffer. Free for use by every layer. Put private vars here
 * @_skb_refdst: destination entry (with norefcount bit)
 * @sp: the security path, used for xfrm
 * @len: Length of actual data
 * @data_len: Data length
 * @mac_len: Length of link layer header
 * @hdr_len: writable header length of cloned skb
 * @csum: Checksum (must include start/offset pair)
 * @csum_start: Offset from skb->head where checksumming should start
 * @csum_offset: Offset from csum_start where checksum should be stored
 * @priority: Packet queueing priority
 * @local_df: allow local fragmentation
 * @cloned: Head may be cloned (check refcnt to be sure)
 * @ip_summed: Driver fed us an IP checksum
 * @nohdr: Payload reference only, must not modify header
 * @nfctinfo: Relationship of this skb to the connection
 * @pkt_type: Packet class
 * @fclone: skbuff clone status
 * @ipvs_property: skbuff is owned by ipvs
 * @peeked: this packet has been seen already, so stats have been
 * done for it, don't do them again
 * @nf_trace: netfilter packet trace flag
 * @protocol: Packet protocol from driver
 * @destructor: Destruct function
 * @nfct: Associated connection, if any
 * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 * @skb_iif: ifindex of device we arrived on
 * @tc_index: Traffic control index
 * @tc_verd: traffic control verdict
 * @hash: the packet hash
 * @queue_mapping: Queue mapping for multiqueue devices
 * @ndisc_nodetype: router type (from link layer)
 * @ooo_okay: allow the mapping of a socket to a queue to be changed
 * @l4_hash: indicate hash is a canonical 4-tuple hash over transport
 * ports.
 * @wifi_acked_valid: wifi_acked was set
 * @wifi_acked: whether frame was acked on wifi or not
 * @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
 * @dma_cookie: a cookie to one of several possible DMA operations
 * done by skb DMA functions
  * @napi_id: id of the NAPI struct this skb came from
 * @secmark: security marking
 * @mark: Generic packet mark
 * @dropcount: total number of sk_receive_queue overflows
 * @vlan_proto: vlan encapsulation protocol
 * @vlan_tci: vlan tag control information
 * @inner_protocol: Protocol (encapsulation)
 * @inner_transport_header: Inner transport layer header (encapsulation)
 * @inner_network_header: Network layer header (encapsulation)
 * @inner_mac_header: Link layer header (encapsulation)
 * @transport_header: Transport layer header
 * @network_header: Network layer header
 * @mac_header: Link layer header
 * @tail: Tail pointer
 * @end: End pointer
 * @head: Head of buffer
 * @data: Data head pointer
 * @truesize: Buffer size
 * @users: User count - see {datagram,tcp}.c
 */


struct sk_buff {
/* These two members must be first. */
struct sk_buff*next;
struct sk_buff*prev;


union {
ktime_t tstamp;
struct skb_mstamp skb_mstamp;
};


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;
#ifdef CONFIG_XFRM
struct sec_path *sp;
#endif
unsigned int len,
data_len;
__u16 mac_len,
hdr_len;
union {
__wsum csum;
struct {
__u16 csum_start;
__u16 csum_offset;
};
};
__u32 priority;
kmemcheck_bitfield_begin(flags1);
__u8 local_df:1,
cloned:1,
ip_summed:2,
nohdr:1,
nfctinfo:3;
__u8 pkt_type:3,
fclone:2,
ipvs_property:1,
peeked:1,
nf_trace:1;
kmemcheck_bitfield_end(flags1);
__be16 protocol;


void (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack*nfct;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info*nf_bridge;
#endif


int skb_iif;


__u32 hash;


__be16 vlan_proto;
__u16 vlan_tci;


#ifdef CONFIG_NET_SCHED
__u16 tc_index;/* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd;/* traffic control verdict */
#endif
#endif


__u16 queue_mapping;
kmemcheck_bitfield_begin(flags2);
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
__u8 pfmemalloc:1;
__u8 ooo_okay:1;
__u8 l4_hash:1;
__u8 wifi_acked_valid:1;
__u8 wifi_acked:1;
__u8 no_fcs:1;
__u8 head_frag:1;
/* Encapsulation protocol and NIC drivers should use
* this flag to indicate to each other if the skb contains
* encapsulated packet or not and maybe use the inner packet
* headers if needed
*/
__u8 encapsulation:1;
/* 6/8 bit hole (depending on ndisc_nodetype presence) */
kmemcheck_bitfield_end(flags2);


#if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL
union {
unsigned int napi_id;
dma_cookie_t dma_cookie;
};
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;
#endif
union {
__u32 mark;
__u32 dropcount;
__u32 reserved_tailroom;
};


__be16 inner_protocol;
__u16 inner_transport_header;
__u16 inner_network_header;
__u16 inner_mac_header;
__u16 transport_header;
__u16 network_header;
__u16 mac_header;
/* These elements must be at the end, see alloc_skb() for details.  */
sk_buff_data_ttail;
sk_buff_data_tend;
unsigned char *head,
*data;
unsigned int truesize;
atomic_t users;
};