【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. 1、在内核中sk_buff是一个网络数据包,它是一个双向链表,而链表头就是sk_buff_head
  1. sk_buff的内存布局能够分作3个段,第一个就是sk_buff自身。第二个是linear-data buff,第三个是paged-data buff(也就是skb_shared_info)。
  2. 先来看一下sk_buff_head:
  1. struct sk_buff_head {
  2.     /* These two members must be first. */
  3.     struct sk_buff    *next;
  4.     struct sk_buff    *prev;
  5.     __u32        qlen;
  6.     spinlock_t    lock;
  7. };
  8. 这里能够看到前两个域是和sk_buff一致的,并且内核的凝视是必须放到最前面。这里的原因是: 

    这使得两个不同的结构能够放到同一个链表中,虽然sk_buff_head要比sk_buff小巧的多。另外,相同的函数能够相同应用于sk_buffsk_buff_head

  9. 然后qlen域表示了当前的sk_buff链上包含多少个skb 

    lock域是自旋锁。

  10. 2sk_buff结构

  11.   1 /**
  12.   2  *    struct sk_buff - socket buffer
  13.   3  *    @next: Next buffer in list
  14.   4  *    @prev: Previous buffer in list
  15.   5  *    @sk: Socket we are owned by
  16.   6  *    @tstamp: Time we arrived
  17.   7  *    @dev: Device we arrived on/are leaving by
  18.   8  *    @transport_header: Transport layer header
  19.   9  *    @network_header: Network layer header
  20.  10  *    @mac_header: Link layer header
  21.  11  *    @_skb_refdst: destination entry (with norefcount bit)
  22.  12  *    @sp: the security path, used for xfrm
  23.  13  *    @cb: Control buffer. Free for use by every layer. Put private vars here
  24.  14  *    @len: Length of actual data
  25.  15  *    @data_len: Data length
  26.  16  *    @mac_len: Length of link layer header
  27.  17  *    @hdr_len: writable header length of cloned skb
  28.  18  *    @csum: Checksum (must include start/offset pair)
  29.  19  *    @csum_start: Offset from skb->head where checksumming should start
  30.  20  *    @csum_offset: Offset from csum_start where checksum should be stored
  31.  21  *    @local_df: allow local fragmentation
  32.  22  *    @cloned: Head may be cloned (check refcnt to be sure)
  33.  23  *    @nohdr: Payload reference only, must not modify header
  34.  24  *    @pkt_type: Packet class
  35.  25  *    @fclone: skbuff clone status
  36.  26  *    @ip_summed: Driver fed us an IP checksum
  37.  27  *    @priority: Packet queueing priority
  38.  28  *    @users: User count - see {datagram,tcp}.c
  39.  29  *    @protocol: Packet protocol from driver
  40.  30  *    @truesize: Buffer size
  41.  31  *    @head: Head of buffer
  42.  32  *    @data: Data head pointer
  43.  33  *    @tail: Tail pointer
  44.  34  *    @end: End pointer
  45.  35  *    @destructor: Destruct function
  46.  36  *    @mark: Generic packet mark
  47.  37  *    @nfct: Associated connection, if any
  48.  38  *    @ipvs_property: skbuff is owned by ipvs
  49.  39  *    @peeked: this packet has been seen already, so stats have been
  50.  40  *        done for it, don't do them again
  51.  41  *    @nf_trace: netfilter packet trace flag
  52.  42  *    @nfctinfo: Relationship of this skb to the connection
  53.  43  *    @nfct_reasm: netfilter conntrack re-assembly pointer
  54.  44  *    @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  55.  45  *    @skb_iif: ifindex of device we arrived on
  56.  46  *    @rxhash: the packet hash computed on receive
  57.  47  *    @queue_mapping: Queue mapping for multiqueue devices
  58.  48  *    @tc_index: Traffic control index
  59.  49  *    @tc_verd: traffic control verdict
  60.  50  *    @ndisc_nodetype: router type (from link layer)
  61.  51  *    @dma_cookie: a cookie to one of several possible DMA operations
  62.  52  *        done by skb DMA functions
  63.  53  *    @secmark: security marking
  64.  54  *    @vlan_tci: vlan tag control information
  65.  55  */
  66.  56
  67.  57 struct sk_buff {
  68.  58     /* These two members must be first. */
  69.  59     struct sk_buff        *next;
  70.  60     struct sk_buff        *prev;
  71.  61
  72.  62     //表示这个skb被接收的时间。
  73.  63     ktime_t            tstamp;
  74.  64     //表示从属于那个socket。主要是被4层用到
  75.  65     struct sock        *sk;
  76.  66     /*这个表示一个网络设备,当skb为输出时它表示skb将要输出的设备,当接收时,它表示输入设备。
  77. 67      * 要注意。这个设备有可能会是虚拟设备(在3层以上看来)
  78.  68      */
  79.  69     struct net_device    *dev;
  80.  70
  81.  71     /*
  82.  72      * This is the control buffer. It is free to use for every
  83.  73      * layer. Please put your private variables there. If you
  84.  74      * want to keep them across layers you have to do a skb_clone()
  85.  75      * first. This is owned by whoever has the skb queued ATM.
  86.  76      */
  87.  77     char            cb[48] __aligned(8);
  88.  78     ///这里事实上应该是dst_entry类型。不知道为什么内核要改为ul。这个域主要用于路由子系统。
  89. 79     //这个数据结构保存了一些路由相关信息
  90.  80     unsigned long        _skb_refdst;
  91.  81 #ifdef CONFIG_XFRM
  92.  82     struct    sec_path    *sp;
  93.  83 #endif
  94.  84     ///这个长度表示当前的skb中的数据的长度,这个长度即包含buf中的数据也包含切片的数据,
  95.  85     //也就是保存在skb_shared_info中的数据。这个值是会随着从一层到还有一层而改变的。以下我们会对照这几个长度的。
  96.  86     unsigned int        len,
  97.  87     ///这个长度仅仅表示切片数据的长度,也就是skb_shared_info中的长度
  98.  88                     data_len;
  99.  89     //链路层头部的长度
  100.  90     __u16            mac_len,
  101.  91     //这个主要用于clone的时候,它表示clone的skb的头的长度
  102.  92                 hdr_len;
  103.  93     //接下来是校验相关的域
  104.  94     union {
  105.  95         __wsum        csum;
  106.  96         struct {
  107.  97             __u16    csum_start;
  108.  98             __u16    csum_offset;
  109.  99         };
  110. 100     };
  111. 101     __u32            priority;
  112. 102     kmemcheck_bitfield_begin(flags1);
  113. 103     //首先是能否够本地切片的标志。
  114. 104     __u8            local_df:1,
  115. 105     //为1说明头可能已被clone
  116. 106                 cloned:1,
  117. 107     //这个表示校验相关的一个标记,表示硬件驱动是否为我们已经进行了校验
  118. 108                 ip_summed:2,
  119. 109     //这个域假设为1,则说明这个skb的头域指针已经分配完成。因此这个时候计算头的长度仅仅须要head和data的差就能够了。
  120. 110                 nohdr:1,
  121. 111                 nfctinfo:3;
  122. 112     //pkt_type主要是表示数据包的类型。比方多播,单播。回环等等
  123. 113     __u8            pkt_type:3,
  124. 114     //这个域是一个clone标记。主要是在fast clone中被设置,我们后面讲到fast clone时会具体介绍这个域
  125. 115                 fclone:2,
  126. 116     //ipvs拥有的域
  127. 117                 ipvs_property:1,
  128. 118     //这个包已经被查看过了
  129. 119                 peeked:1,
  130. 120     //netfilter使用的域。是一个trace 标记
  131. 121                 nf_trace:1;
  132. 122     kmemcheck_bitfield_end(flags1);
  133. 123     __be16            protocol;
  134. 124     //skb的析构函数,一般都是设置为sock_rfree或者sock_wfree
  135. 125     void            (*destructor)(struct sk_buff *skb);
  136. 126 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  137. 127     struct nf_conntrack    *nfct;
  138. 128 #endif
  139. 129 #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
  140. 130     struct sk_buff        *nfct_reasm;
  141. 131 #endif
  142. 132 #ifdef CONFIG_BRIDGE_NETFILTER
  143. 133     struct nf_bridge_info    *nf_bridge;
  144. 134 #endif
  145. 135     //接收设备的index
  146. 136     int            skb_iif;
  147. 137
  148. 138     //流量控制的相关域
  149. 139 #ifdef CONFIG_NET_SCHED
  150. 140     __u16            tc_index;    /* traffic control index */
  151. 141 #ifdef CONFIG_NET_CLS_ACT
  152. 142     __u16            tc_verd;    /* traffic control verdict */
  153. 143 #endif
  154. 144 #endif
  155. 145
  156. 146     __u32            rxhash;
  157. 147
  158. 148     kmemcheck_bitfield_begin(flags2);
  159. 149     //多队列设备的映射。也就是说映射到那个队列
  160. 150     __u16            queue_mapping:16;
  161. 151 #ifdef CONFIG_IPV6_NDISC_NODETYPE
  162. 152     __u8            ndisc_nodetype:2,
  163. 153                 deliver_no_wcard:1;
  164. 154 #else
  165. 155     __u8            deliver_no_wcard:1;
  166. 156 #endif
  167. 157     __u8            ooo_okay:1;
  168. 158     kmemcheck_bitfield_end(flags2);
  169. 159
  170. 160     /* 0/13 bit hole */
  171. 161
  172. 162 #ifdef CONFIG_NET_DMA
  173. 163     dma_cookie_t        dma_cookie;
  174. 164 #endif
  175. 165 #ifdef CONFIG_NETWORK_SECMARK
  176. 166     __u32            secmark;
  177. 167 #endif
  178. 168     union {
  179. 169         //skb的标记
  180. 170         __u32        mark;
  181. 171         __u32        dropcount;
  182. 172     };
  183. 173     //vlan的控制tag
  184. 174     __u16            vlan_tci;
  185. 175     //传输层的头
  186. 176     sk_buff_data_t        transport_header;
  187. 177     //网络层的头
  188. 178     sk_buff_data_t        network_header;
  189. 179     //链路层的头
  190. 180     sk_buff_data_t        mac_header;
  191. 181     /* These elements must be at the end, see alloc_skb() for details.  */
  192. 182     sk_buff_data_t        tail;
  193. 183     sk_buff_data_t        end;
  194. 184     unsigned char        *head,
  195. 185                 *data;
  196. 186     //这个表示整个skb的大小,包含skb本身。以及数据
  197. 187     unsigned int        truesize;
  198. 188     //skb的引用计数
  199. 189     atomic_t        users;
  200. 190 };

【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析的更多相关文章

  1. 【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现

    一.dm9000_init 打印出驱动的版本,注冊dm9000_driver驱动,将驱动加入到总线上.运行match,假设匹配,将会运行probe函数. 1 static int __init 2 d ...

  2. Mini2440 DM9000 驱动分析(一)

    Mini2440 DM9000 驱动分析(一) 硬件特性 Mini2440开发板上DM9000的电气连接和Mach-mini2440.c文件的关系: PW_RST 连接到复位按键,复位按键按下,低电平 ...

  3. linux i2c驱动架构-dm368 i2c驱动分析

      linux i2c驱动架构-dm368 i2c驱动分析   在阅读本文最好先熟悉一种i2c设备的驱动程序,并且浏览一下i2c-core.c以及芯片提供商的提供的i2c总线驱动(i2c-davinc ...

  4. Linux内核中SPI总线驱动分析

    本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...

  5. linux driver ------ platform模型,驱动开发分析

    一.platform总线.设备与驱动 在Linux 2.6 的设备驱动模型中,关心总线.设备和驱动3个实体,总线将设备和驱动绑定.在系统每注册一个设备的时候,会寻找与之匹配的驱动:相反的,在系统每注册 ...

  6. linux设备驱动之USB主机控制器驱动分析 【转】

    转自:http://blog.chinaunix.net/uid-20543183-id-1930831.html   ---------------------------------------- ...

  7. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  8. Linux驱动开发:USB驱动之usb_skel分析

    在学习了这么些天的驱动之后,个人觉得驱动就是个架构的问题,只要把架构弄清楚了 然后往里面添砖加瓦就可以了,所以似乎看起来不是太困难,但也许是是我经验不足吧,这只能算是个人浅见了 这两天在学习USB驱动 ...

  9. Linux驱动中的platform总线分析

    copy from :https://blog.csdn.net/fml1997/article/details/77622860 概述 从Linux2.6内核起,引入一套新的驱动管理和注册机制:pl ...

随机推荐

  1. DocView mode 3 -- 配置

    ;在当前页中滚动doc-view-continuous nil ;指定默认的字体大小doc-view-resolution ;gs生成的缓存的目录doc-view-cache-directory

  2. PYDay14:反射、面向对象基础-封装、集成、多态

    1.反射 通过字符串的形式,导入模块再通过字符串的形式,去模块中寻找指定的函数并执行eg:__import__(模块) 更加字符串的形式去对象(某个模块)中操作其成员 常用方法: getattr() ...

  3. bounds 和frame区别

    仔细看下这个图就知道了

  4. get 发送ajax请求

    上demo小案例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  5. 【Luogu】P1602Sramoc问题(堆)

    题目链接 很巧妙的想法.一开始将1~k-1加入堆中,然后每次从堆里取出一个最小的,判断是不是答案,如果不是,那么就枚举新数的末一位加上. 代码如下 #include<cstdio> #in ...

  6. Luogu【P1901】发射站(单调栈)

    题目链接 题目说明比自己矮的塔收不到自己的能量,摆明了就是单调栈呗. 把比自己矮的全都从栈里弹出去,于是碰到第一个比自己高的.让他接受自己发射的能量. 当然由于发射站发射的能量有两个方向,所以正反两遍 ...

  7. BZOJ 1974 [Sdoi2010]auction 代码拍卖会 ——动态规划

    把每一位上不递减的数拆成1+11+11111+11111+..... 然后就可以把巨大的N从复杂度中消掉,因为随着长度的增加1...111%p出现了循环节. 然后就是从n个数中选出几个使他们结果为0( ...

  8. 【Codevs1922】骑士共存问题(最小割,二分图最大独立集转最大匹配)

    题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个 ...

  9. Day 5 Linux之用户、群组和权限

    Linux之用户.群组和权限 一.各文件及内容对应含义 1./etc/passwd文件 功能:存储所有用户的相关信息,该文件也被称为用户信息数据库(Database). 含义:如下图所示. 2./et ...

  10. linux top %VSZ含义

    https://blog.csdn.net/sinohenu/article/details/58216013 https://unix.stackexchange.com/questions/449 ...