终于下决心开始看TCP/IP部分的源码了,从《TCI/IP详解,卷二》作为入口。。。
首先来分析一下存取数据的buff,
在书上,强调的是mbuf,不过好像现在新版本的内核改动比较大,更重要的还是sk_buff,不过还是先来看看mbuff吧,
文件在:Driver/net/skfp/h/mbuf.h
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 ; #endif char sm_data[M_SIZE] ; //用于实际的数据存储 } ; typedef struct s_mbuf SMbuf ;
定义其实很简单了,与书上差异很大。。。不过重点还是来看看sk_buff的定义吧,首先是head的定义,其实他是一个占位节点,用于将sk_buff连接起来:
//sk_buff的头部的定义,其实是用于组织成一个链表 struct sk_buff_head { /* These two members must be first. */ struct sk_buff *next; //上一个 struct sk_buff *prev; //下一个 __u32 qlen; //链表的长度 spinlock_t lock; //锁 };
用两个指针构成链表,接下来来看看sk_buff的定义:
struct sk_buff { /* These two members must be first. */ struct sk_buff *next; //指向上一个buff结构 struct sk_buff *prev; //指向下一个buff结构 ktime_t tstamp; struct sock *sk; //属于哪一个sock,主要是在传输层中用到 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_dst; #ifdef CONFIG_XFRM struct sec_path *sp; #endif //表示当前sk_buff的数据的长度 unsigned int len, data_len; //mac头的长度 __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; struct sk_buff *nfct_reasm; #endif #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif int skb_iif; #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 union { __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; //链路层头部 /* 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的大小,包括sk_buff结构和头部以及数据 atomic_t users; //引用计数 };
在内核中,用sk_buff来表示一个网络数据包,它里面包含了从链路层到传输层的数据,具体的那些字段的意思再注释中已经写了出来。。。
好了第一篇,还是轻松一些好,就介绍一下buff的定义