【linux驅動分析】之dm9000驅動分析(三):sk_buff結構分析

【linux驅動分析】之dm9000驅動分析(一):dm9000原理及硬件分析 

【linux驅動分析】之dm9000驅動分析(二):定義在板文件中的資源和設備以及幾個宏 

【linux驅動分析】之dm9000驅動分析(三):sk_buff結構分析 

【linux驅動分析】之dm9000驅動分析(四):net_device結構體 

【linux驅動分析】之dm9000驅動分析(五):另外幾個重要的結構體 

【linux驅動分析】之dm9000驅動分析(六):dm9000_init和dm9000_probe的實現 

【linux驅動分析】之dm9000驅動分析(七):dm9000的卸載掛起和恢復以及打開和停止


源碼分析
sk_buff_head和sk_buff定義在include/linux/skbuff.h中,下面是linux-2.6.38中的定義。
1、在內核中sk_buff是一個網絡數據包,它是一個雙向鏈表,而鏈表頭就是sk_buff_head。
而sk_buff的內存佈局可以分作3個段,第一個就是sk_buff自身,第二個是linear-data buff,第三個是paged-data buff(也就是skb_shared_info)。
先來看一下sk_buff_head:
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一致的,而且內核的註釋是必須放到最前面。這裏的原因是: 

這使得兩個不同的結構可以放到同一個鏈表中,儘管sk_buff_head要比sk_buff小巧的多。另外,相同的函數可以同樣應用於sk_buff和sk_buff_head。 

然後qlen域表示了當前的sk_buff鏈上包含多少個skb。 

lock域是自旋鎖。 2、sk_buff結構
  1 /** 
  2  *    struct sk_buff - socket buffer
  3  *    @next: Next buffer in list
  4  *    @prev: Previous buffer in list
  5  *    @sk: Socket we are owned by
  6  *    @tstamp: Time we arrived
  7  *    @dev: Device we arrived on/are leaving by
  8  *    @transport_header: Transport layer header
  9  *    @network_header: Network layer header
 10  *    @mac_header: Link layer header
 11  *    @_skb_refdst: destination entry (with norefcount bit)
 12  *    @sp: the security path, used for xfrm
 13  *    @cb: Control buffer. Free for use by every layer. Put private vars here
 14  *    @len: Length of actual data
 15  *    @data_len: Data length
 16  *    @mac_len: Length of link layer header
 17  *    @hdr_len: writable header length of cloned skb
 18  *    @csum: Checksum (must include start/offset pair)
 19  *    @csum_start: Offset from skb->head where checksumming should start
 20  *    @csum_offset: Offset from csum_start where checksum should be stored
 21  *    @local_df: allow local fragmentation
 22  *    @cloned: Head may be cloned (check refcnt to be sure)
 23  *    @nohdr: Payload reference only, must not modify header
 24  *    @pkt_type: Packet class
 25  *    @fclone: skbuff clone status
 26  *    @ip_summed: Driver fed us an IP checksum
 27  *    @priority: Packet queueing priority
 28  *    @users: User count - see {datagram,tcp}.c
 29  *    @protocol: Packet protocol from driver
 30  *    @truesize: Buffer size 
 31  *    @head: Head of buffer
 32  *    @data: Data head pointer
 33  *    @tail: Tail pointer
 34  *    @end: End pointer
 35  *    @destructor: Destruct function
 36  *    @mark: Generic packet mark
 37  *    @nfct: Associated connection, if any
 38  *    @ipvs_property: skbuff is owned by ipvs
 39  *    @peeked: this packet has been seen already, so stats have been
 40  *        done for it, don't do them again
 41  *    @nf_trace: netfilter packet trace flag
 42  *    @nfctinfo: Relationship of this skb to the connection
 43  *    @nfct_reasm: netfilter conntrack re-assembly pointer
 44  *    @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 45  *    @skb_iif: ifindex of device we arrived on
 46  *    @rxhash: the packet hash computed on receive
 47  *    @queue_mapping: Queue mapping for multiqueue devices
 48  *    @tc_index: Traffic control index
 49  *    @tc_verd: traffic control verdict
 50  *    @ndisc_nodetype: router type (from link layer)
 51  *    @dma_cookie: a cookie to one of several possible DMA operations
 52  *        done by skb DMA functions
 53  *    @secmark: security marking
 54  *    @vlan_tci: vlan tag control information
 55  */
 56 
 57 struct sk_buff {
 58     /* These two members must be first. */
 59     struct sk_buff        *next;
 60     struct sk_buff        *prev;
 61 
 62     //表示這個skb被接收的時間。
 63     ktime_t            tstamp;
 64     //表示從屬於那個socket,主要是被4層用到
 65     struct sock        *sk;
 66     /*這個表示一個網絡設備,當skb爲輸出時它表示skb將要輸出的設備,當接收時,它表示輸入設備。
 67      * 要注意,這個設備有可能會是虛擬設備(在3層以上看來)
 68      */
 69     struct net_device    *dev;
 70 
 71     /*
 72      * This is the control buffer. It is free to use for every
 73      * layer. Please put your private variables there. If you
 74      * want to keep them across layers you have to do a skb_clone()
 75      * first. This is owned by whoever has the skb queued ATM.
 76      */
 77     char            cb[48] __aligned(8);
 78     ///這裏其實應該是dst_entry類型,不知道爲什麼內核要改爲ul。這個域主要用於路由子系統。
 79     //這個數據結構保存了一些路由相關信息 
 80     unsigned long        _skb_refdst;
 81 #ifdef CONFIG_XFRM
 82     struct    sec_path    *sp;
 83 #endif
 84     ///這個長度表示當前的skb中的數據的長度,這個長度即包括buf中的數據也包括切片的數據,
 85     //也就是保存在skb_shared_info中的數據。這個值是會隨着從一層到另一層而改變的。下面我們會對比這幾個長度的。
 86     unsigned int        len,
 87     ///這個長度只表示切片數據的長度,也就是skb_shared_info中的長度
 88                     data_len;
 89     //鏈路層頭部的長度
 90     __u16            mac_len,
 91     //這個主要用於clone的時候,它表示clone的skb的頭的長度
 92                 hdr_len;
 93     //接下來是校驗相關的域
 94     union {
 95         __wsum        csum;
 96         struct {
 97             __u16    csum_start;
 98             __u16    csum_offset;
 99         };
100     };
101     __u32            priority;
102     kmemcheck_bitfield_begin(flags1);
103     //首先是是否可以本地切片的標誌。
104     __u8            local_df:1,
105     //爲1說明頭可能已被clone
106                 cloned:1,
107     //這個表示校驗相關的一個標記,表示硬件驅動是否爲我們已經進行了校驗
108                 ip_summed:2,
109     //這個域如果爲1,則說明這個skb的頭域指針已經分配完畢,因此這個時候計算頭的長度只需要head和data的差就可以了。
110                 nohdr:1,
111                 nfctinfo:3;
112     //pkt_type主要是表示數據包的類型,比如多播,單播,迴環等等
113     __u8            pkt_type:3,
114     //這個域是一個clone標記。主要是在fast clone中被設置,我們後面講到fast clone時會詳細介紹這個域
115                 fclone:2,
116     //ipvs擁有的域
117                 ipvs_property:1,
118     //這個包已經被查看過了
119                 peeked:1,
120     //netfilter使用的域。是一個trace 標記
121                 nf_trace:1;
122     kmemcheck_bitfield_end(flags1);
123     __be16            protocol;
124     //skb的析構函數,一般都是設置爲sock_rfree或者sock_wfree
125     void            (*destructor)(struct sk_buff *skb);
126 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
127     struct nf_conntrack    *nfct;
128 #endif
129 #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
130     struct sk_buff        *nfct_reasm;
131 #endif
132 #ifdef CONFIG_BRIDGE_NETFILTER
133     struct nf_bridge_info    *nf_bridge;
134 #endif
135     //接收設備的index
136     int            skb_iif;
137 
138     //流量控制的相關域
139 #ifdef CONFIG_NET_SCHED
140     __u16            tc_index;    /* traffic control index */
141 #ifdef CONFIG_NET_CLS_ACT
142     __u16            tc_verd;    /* traffic control verdict */
143 #endif
144 #endif
145 
146     __u32            rxhash;
147 
148     kmemcheck_bitfield_begin(flags2);
149     //多隊列設備的映射,也就是說映射到那個隊列
150     __u16            queue_mapping:16;
151 #ifdef CONFIG_IPV6_NDISC_NODETYPE
152     __u8            ndisc_nodetype:2,
153                 deliver_no_wcard:1;
154 #else
155     __u8            deliver_no_wcard:1;
156 #endif
157     __u8            ooo_okay:1;
158     kmemcheck_bitfield_end(flags2);
159 
160     /* 0/13 bit hole */
161 
162 #ifdef CONFIG_NET_DMA
163     dma_cookie_t        dma_cookie;
164 #endif
165 #ifdef CONFIG_NETWORK_SECMARK
166     __u32            secmark;
167 #endif
168     union {
169         //skb的標記
170         __u32        mark;
171         __u32        dropcount;
172     };
173     //vlan的控制tag
174     __u16            vlan_tci;
175     //傳輸層的頭
176     sk_buff_data_t        transport_header;
177     //網絡層的頭
178     sk_buff_data_t        network_header;
179     //鏈路層的頭
180     sk_buff_data_t        mac_header;
181     /* These elements must be at the end, see alloc_skb() for details.  */
182     sk_buff_data_t        tail;
183     sk_buff_data_t        end;
184     unsigned char        *head,
185                 *data;
186     //這個表示整個skb的大小,包括skb本身,以及數據
187     unsigned int        truesize;
188     //skb的引用計數
189     atomic_t        users;
190 };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章