本文分析基于Linux Kernel 3.2.1
幾個(gè)月之前做了關(guān)于Linux內(nèi)核版本1.2.13網(wǎng)絡(luò)棧的結(jié)構(gòu)框架分析并實(shí)現(xiàn)了基于Netfilter的包過(guò)濾防火墻,這里以內(nèi)核3.2.1內(nèi)核為例來(lái)進(jìn)一步分析,更全面的分析網(wǎng)絡(luò)棧的結(jié)構(gòu)。
更多請(qǐng)查看 Linux內(nèi)核--網(wǎng)絡(luò)內(nèi)核實(shí)現(xiàn)分析
1、先說(shuō)一下sk_buff結(jié)構(gòu)體
這個(gè)結(jié)構(gòu)體是套接字的緩沖區(qū),詳細(xì)記錄了一個(gè)數(shù)據(jù)包的組成,時(shí)間、網(wǎng)絡(luò)設(shè)備、各層的首部及首部長(zhǎng)度和數(shù)據(jù)的首尾指針。
下面是他的定義,挺長(zhǎng)
- struct sk_buff {
- /* These two members must be first. */
- struct sk_buff *next;
- struct sk_buff *prev;
-
- ktime_t tstamp;
-
- 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 NET_SKBUFF_NF_DEFRAG_NEEDED
- 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
-
- __u32 rxhash;
-
- __u16 queue_mapping;
- kmemcheck_bitfield_begin(flags2);
- #ifdef CONFIG_IPV6_NDISC_NODETYPE
- __u8 ndisc_nodetype:2;
- #endif
- __u8 ooo_okay:1;
- __u8 l4_rxhash:1;
- kmemcheck_bitfield_end(flags2);
-
- /* 0/13 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;
- atomic_t users;
- };
可以看到新版本內(nèi)核中發(fā)生了很多變化,其中數(shù)據(jù)包的首部在早期版本是以u(píng)nion的形式定義的,例如mac_header的定義方式如下:
- union{
- struct ethhdr *ethernet;
- unsigned char *raw;
- }mac;
這里是以指針的形式給出的
- #ifdef NET_SKBUFF_DATA_USES_OFFSET
- typedef unsigned int sk_buff_data_t;
- #else
- typedef unsigned char *sk_buff_data_t;
- #endif
|