struct s_mbuf与struct sk_buff本文的copyleft归[email protected]所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
博客:linuxfocus.blog.chinaunix.net
为了有一个入口来研究TCP/IP源码,那么就按照《TCP/IP详解——卷2》来开始吧。
TCP/IP详解的内容是Linux2.4的,在Linux2.6中mbuf有了很大的变化。
文件位置:linux-2.6.36.1/drivers/net/skfp/h/mubf.h
#define M_SIZE 4504
#ifndef MAX_MBUF
#define MAX_MBUF 4
#endif
#ifndef NO_STD_MBUF
#define sm_next m_next
#define sm_off m_off
#define sm_len m_len
#define sm_data m_data
#define SMbuf Mbuf
#define mtod smtod
#define mtodoff smtodoff
struct s_mbuf {
struct s_mbuf *sm_next ; /* low level linked list */
short sm_off ; /* offset in m_data */
u_int sm_len ; /* len of data */
#ifdef PCI
int sm_use_count ;
char sm_data[M_SIZE] ;
} ;
typedef struct s_mbuf SMbuf ;
/* mbuf head, to typed data */
/* 得到s_mbuf中的数据转换成指定的类型t */
#define smtod(x,t) ((t)((x)->sm_data + (x)->sm_off))
/* 这个宏没有被别的地方调用,用途是将data指定偏移地址o的指针转为类型t */
#define smtodoff(x,t,o) ((t)((x)->sm_data + (o)))
通过查询SMbuf在源代码中的引用,可以看出s_mbuf在linux2.6中的用途远没有mbuf在linux中广泛——linux2.4中,mbuf负责了内核中的存储器缓存。
那么在linux2.6中,又由哪一个结构来承担linux2.4中mbuf的作用——答案是sk_buff。
struct sk_buff {
/*
These two members must be first. */
/* 这两个变量用于形成sk_buff的双链表 */
struct sk_buff *next;
struct sk_buff *prev;
/* 数据包到达的时间 */
ktime_t tstamp;
/* 这个sk_buff被哪个sock拥有 */
struct sock *sk;
/* 这个sk_buff到达的device或者要从哪个device发送 */
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);
/* destination entry */
unsigned long _skb_refdst;
#ifdef CONFIG_XFRM
struct sec_path *sp;
/* len为实际数据长度,data_len为数据长度 */
unsigned int len,
data_len;
/* mac_len:数据链路层地址长度,hdr_len:克隆的skb可写头部的长度 */
__u16 mac_len,
hdr_len;
union {
__wsum csum;
struct {
__u16 csum_start;
__u16 csum_offset;
};
};
/* 包的排队优先级 */
__u32 priority;
kmemcheck_bitfield_begin(flags1);
/*
一些标志位:
local_df:允许本地分片;
nohdr:只能引用其payload
*/
__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;
struct sk_buff *nfct_reasm;
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
/* 由哪个interface到达的 */
int skb_iif;
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd; /* traffic control verdict */
__u32 rxhash;
kmemcheck_bitfield_begin(flags2);
__u16 queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2,
deliver_no_wcard:1;
#else
__u8 deliver_no_wcard:1;
kmemcheck_bitfield_end(flags2);
0/14 bit hole */
#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;
/* 这个sk_buff被哪个sock拥有 */
__u32 mark;
__u32 dropcount;
__u16 vlan_tci;
/* 传输层报头 */
sk_buff_data_t transport_header;
/* 网络层报头 */
sk_buff_data_t network_header;
/* 链路层报头 */
sk_buff_data_t mac_header;
sk_buff_data_t tail;
sk_buff_data_t end;
unsigned char *head,
*data;
unsigned int truesize;
atomic_t users;
};
今天只能先写到这里,明天继续分析sk_buff结构。其实在linux 2.6代码中,每个变量的用途,注释写得很明白。