【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 };

最新文章

  1. iOS UIView动画效果 学习笔记
  2. 试验添加RAC(ORA10G)节点
  3. matlab processing for video
  4. 不引用office动态库导出excel
  5. acdeream Matrix Multiplication
  6. Dispatcher
  7. 【BZOJ】【1070】【SCOI2007】修车
  8. 【Android自学之旅】 目录
  9. asp.net 权限问题
  10. DB2系统管理试题标准答案
  11. Android使用Dom解析xml
  12. 学习C++语言的50条忠告
  13. 【零基础学习iOS开发】【01-前言】01-开篇
  14. APP生产流程图片解说
  15. Latex 去掉行号
  16. 二十、Hadoop学记笔记————Hive On Hbase
  17. 【Spark篇】---Spark初始
  18. Docker部署运行springboot项目,并使用Dockerfile制作镜像
  19. git基本操作1
  20. bzoj1861

热门文章

  1. android-csv-variants
  2. linux c中需要记住的东西
  3. if-else优化
  4. asp.net下js调用session
  5. oracle 安装 启动listener 建库相关
  6. 关于Relay Log无法自动删除的问题
  7. 九度oj 题目1185:特殊排序
  8. 最小的图灵完备语言——BrainFuck
  9. AOP面向方面(切面)编程
  10. 1109 NOIP 模拟考试