struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用。 
// 这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变。
// L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部。 添加头部比在不同层之间拷贝数据的效率更高。
//由于在缓冲区的头部 添加数据意味着要修改指向缓冲区的指针,这是个复杂的操作,所以内核提供了一个函数skb_reserve来完成这个功能。
//协议栈中的每一层在往下一层传 递缓冲区前,第一件事就是调用skb_reserve在缓冲区的头部给协议头预留一定的空间
skb_reserve同样被设备驱动使用来对齐接收到包的包头。如果缓冲区向上层协议传递,旧的协议层的头部信息就没什么用了。
例如,L2的头部只有在 网络驱动处理L2的协议时有用,L3是不会关心它的信息的。
但是,内核并没有把L2的头部从缓冲区中删除,而是把有效荷载的指针指向L3的头部,这样做, 可以节省CPU时间。

有些sk_buff成员变量的作用是方便查找或者是连接数据结构本身。内核可以把sk_buff组织成一个双向链表。
当然,这个链表的结构要比常见的双向 链表的结构复杂一点。
就像任何一个双向链表一样,sk_buff中有两个指针next和prev,其中,next指向下一个节点,而prev指向上一个节 点。
在第一个节点前面会插入另一个结构sk_buff_head,这是一个辅助节点(作为sk_buff双向链表的头),它的定义如下:
struct sk_buff_head { 
struct sk_buff -*next; 
struct sk_buff -*prev; 
__u32 qlen; //qlen代表链表元素的个数 
spinlock_t lock; //lock用于防止对链表的并发访问

};

struct sk_buff {
/* These two members must be first. */
struct sk_buff  *next; //Next buffer in list
struct sk_buff  *prev; // Previous buffer in list
//next和prev指针:协议栈中经常用到sk_buff的队列,队列通过sk_buff中的指针相连接。这两个指针用来连接相关的skb的(例如有分片)ktime_t  tstamp; //报文到达或者离开的时间戳; Time we arrived 表示这个skb被接收的时间struct sock *sk; //指向报文所属的套接字指针;Socket we are owned by 表示从属于那个socket,主要是被4层用到。
/*
这是一个指向拥有这个sk_buff的sock结构的指针。
这个指针在网络包由本机发出或者由本机进程接收时有效,因为插口相关的信息被L4(TCP或 UDP)或者用户空间程序使用。
如果sk_buff只在转发中使用(这意味着,源地址和目的地址都不是本机地址),这个指针是NULL
*/
struct net_device   *dev; //表示一个接收或者发送报文的网络设备; Device we arrived on/are leaving by
//这个表示一个网络设备,当skb为输出时它表示skb将要输出的设备,当接收时,它表示输入设备。要注意,这个设备有可能会是虚拟设备(在3层以上看来)
char    cb[48] __aligned(8); //保存每一层的控制信息,以及私有信息;Control buffer. Free for use by every layer. Put private vars here
/*
cb 这个域很重要,我们下面会详细说明。这里只需要知道这个域是保存每层的控制信息的就够
中的48个字节是控制字段,配合各层协议工作,为每层存储必要的控制信息。 )
*/
unsigned long   _skb_refdst; // destination entry (with norefcount bit)
///这里其实应该是dst_entry类型,不知道为什么内核要改为ul。这个域主要用于路由子系统。这个数据结构保存了一些路由相关信息
#ifdef CONFIG_XFRM
struct  sec_path    *sp; 安全路径,用于xfrm
#endif
unsigned int    len, // Length of actual data //当前协议数据包的长度,包括主缓冲区中数据长度和分片中数据长度
//(个人理解为当前协议层包头和数据区域长度)。skb的组成是sk_buff控制+线性数据+非线性数据(skb_shared_info)组成!
// 表示当前协议数据包的长度。它包括主缓冲区中的数据长度(data指针指向它)和分片中的数据长度
//这个长度表示当前的skb中的数据的长度,这个长度即包括buf中的数据也包括切片的数据,也就是保存在skb_shared_info中的数据。
//这个值是会随着从一层到另一层而改变的。下面我们会对比这几个长度的。
data_len; //Data length ;//分片中数据长度 和len不同,data_len只计算分片中数据的长度 // 这个长度只表示切片数据的长度,也就是skb_shared_info中的长度。 __u16 mac_len, // Length of link layer header 这是mac头的长度 //这个长度表示mac头的长度(2层的头的长度)
hdr_len; //writable header length of cloned skb 用于clone时,表示clone的skb的头长度;//这个主要用于clone的时候,它表示clone的skb的头的长度。
///接下来是校验相关的域。
union {
__wsum  csum; // Checksum (must include start/offset pair)
struct {
__u16   csum_start; //skb->head即校验和计算起始点 Offset from skb->head where checksumming should start
__u16   csum_offset; //Offset from csum_start where checksum should be stored 校验和存储位置偏移(以csum_start处起始偏移csum_offset大小)};
};
///优先级,主要用于QOS。
__u32   priority; //Packet queueing priority 报文排队优先级,取决于ip中的tos域kmemcheck_bitfield_begin(flags1);///接下来是一些标志位。 __u8  local_df:1, //是否可以本地切片的标志。
cloned:1, ///为1说明头可能被clone。
ip_summed:2, ///这个表示校验相关的一个标记,表示硬件驱动是否为我们已经进行了校验(前面的blog有介绍)
nohdr:1, ///这个域如果为1,则说明这个skb的头域指针已经分配完毕,因此这个时候计算头的长度只需要head和data的差就可以了。 nfctinfo:3;
__u8    pkt_type:3, ///pkt_type主要是表示数据包的类型,比如多播,单播,回环等等。
fclone:2, ///这个域是一个clone标记。主要是在fast clone中被设置,我们后面讲到fast clone时会详细介绍这个域。
ipvs_property:1, ///ipvs拥有的域。
peeked:1, ///这个域应该是udp使用的一个域。表示只是查看数据。
nf_trace:1; ///netfilter使用的域。是一个trace 标记 kmemcheck_bitfield_end(flags1);
__be16  protocol; ///这个表示L3层的协议。比如IP,IPV6等等。void    (*destructor)(struct sk_buff *skb); //skb的析构函数,一般都是设置为sock_rfree或者sock_wfree.
///netfilter相关的域。
#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;
#endifint   skb_iif; //接收设备的index。 ///流量控制的相关域。
#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;kmemcheck_bitfield_begin(flags2);
///多队列设备的映射,也就是说映射到那个队列。
__u16   queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8    ndisc_nodetype:2;
#endif
__u8    ooo_okay: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; // skb的标记。
__u32   dropcount;
};
__u16   vlan_tci; //vlan标签控制信息;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; //保存数据内容的首地址;(实际数据区域开始位置)/*
sk_buff->head sk_buff->data sk_buff->tail sk_buff->end 它们表示缓冲区和数据部分的边界。
在每一层申请缓冲区时,它会分配比协议头或协议数据大的空间。head和end指向缓冲区的头部和尾部,而data和 tail指向实际数据的头部和尾部。
每一层会在head和data之间填充协议头,或者在tail和end之间添加新的协议数据。数据部分会在尾部包含一 个附加的头部。
*/
unsigned int    truesize; //该缓冲区分配的所有总的内存,包括:skb_buff + 所有数据大小;//这个表示整个skb的大小,包括skb本身,以及数据。
/*这是缓冲区的总长度,包括sk_buff结构和数据部分。如果申请一个len字节的缓冲区,alloc_skb函数会把它初始化成len+sizeof(sk_buff)。当skb->len变化时,这个变量也会变化
*/
atomic_t    users; //保存引用skb_buff的数量
/*
这是一个引用计数,用于计算有多少实体引用了这个sk_buff缓冲区。
它的主要用途是防止释放sk_buff后,还有其他实体引用这个sk_buff。
因此,每个引用这个缓冲区的实体都必须在适当的时候增加或减小这个变量。
这个计数器只保护sk_buff结构本身,而缓冲区的数据部分由类似的计数器 (dataref)来保护.有时可以用atomic_inc和atomic_dec函数来直接增加或减小users,
但是,通常还是使用函数 skb_get和kfree_skb来操作这个变量。
*/};

1: http://www.cnblogs.com/image-eye/archive/2012/01/17/2324866.html
http://blog.csdn.net/ysu108/article/details/7764461
http://blog.csdn.net/geekcome/article/details/7488828
http://blog.csdn.net/ysu108/article/details/7764461
http://blog.csdn.net/yuzhihui_no1/article/details/38666589

http://www.cnblogs.com/zengkefu/p/5583618.html

http://www.cnblogs.com/sammyliu/p/5225623.html
http://www.cnblogs.com/sammyliu/p/5225623.html
http://simohayha.iteye.com/blog/556168 //IMPORENT

http://www.cnblogs.com/zengkefu/p/5583618.html

http://blog.csdn.net/lmjjw/article/details/9992235

http://www.cnblogs.com/zengkefu/p/5602396.html //important

http://www.cnblogs.com/zengkefu/p/5583618.html

http://www.cnblogs.com/zengkefu/p/5602396.html

sk_buff详细介绍相关推荐

  1. HTML页面加载和解析流程详细介绍

    浏览器加载和渲染html的顺序.如何加快HTML页面加载速度.HTML页面加载和解析流程等等,在本文将为大家详细介绍下,感兴趣的朋友不要错过 浏览器加载和渲染html的顺序 1. IE下载的顺序是从上 ...

  2. mysql为什么要压测_mysql集群压测的详细介绍

    本篇文章给大家带来的内容是关于mysql集群压测的详细介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. mysql压测 mysql自带就有一个叫mysqlslap的压力测试工具,通 ...

  3. php比较运算符案列,PHP实例:PHP比较运算符的详细介绍

    <PHP实例:PHP比较运算符的详细介绍>要点: 本文介绍了PHP实例:PHP比较运算符的详细介绍,希望对您有用.如果有疑问,可以联系我们. 比拟运算符种类 PHP实战如同它们名称所暗示的 ...

  4. Tempdb数据库详细介绍

    Tempdb数据库详细介绍 一.Tempdb简介 tempdb是SQLServer的系统数据库一直都是SQLServer的重要组成部分,用来存储临时对象.可以简单理解tempdb是SQLServer的 ...

  5. linux路由介绍,Linux的路由表详细介绍

    Linux的路由表详细介绍 一 在Linux下执行route命令[root@localhost backup]# route -nKernel IP routing tableDestination ...

  6. pythonexcel介绍_Python 中pandas.read_excel详细介绍

    Python 中pandas.read_excel详细介绍 #coding:utf-8 import pandas as pd import numpy as np filefullpath = r& ...

  7. 渡神纪帧数测试软件,渡神纪芬尼斯崛起配置要求高吗 渡神纪配置要求详细介绍_游侠网...

    渡神纪芬尼斯崛起配置要求高吗?本作将在12月3日登陆主机和PC,很多玩家比较关心游戏的配置,这里给大家带来了渡神纪配置要求详细介绍,快来了解下吧. 渡神纪配置要求详细介绍 最低要求(720p/30 f ...

  8. C++11 unordered_map详细介绍

    整理的算法模板合集: ACM模板 目录: 1.介绍 1.1 特性 2. 模版 2.1 迭代器 3. 功能函数 3.1 构造函数 3.2 容量操作 3.2.1 size 3.2.2 empty 3.3 ...

  9. autosar中com模块_详细介绍AUTOSAR各个模块作用PART1(OS,SYS)

    这片文章中我们详细讲解下每个模块的功能,上图是vector的autosar方案,每个模块的详细介绍后续会有单独文章进行讲解,请关注.以下是各个模块的简介 1.VHSM hardware Securit ...

最新文章

  1. 拷贝构造函数的第一个参数必须是自身类类型的引用
  2. python爬虫代码提取图片中的文字_python识别图像并提取文字的实现方法
  3. Topaz Labs AI深度学习图像处理(Gigapixel、Video Enhance)
  4. linux如何登陆oracle?如何停止、启动oracle和其监听?
  5. Netty实战 IM即时通讯系统(二)Netty简介
  6. three.js和php,threejs--初创项目
  7. AR VR或将彻底变革广告营销行业
  8. 吴恩达 Deeplearning深度学习笔记v5.7 最新PDF版 免积分下载
  9. Madis模拟黏滞阻尼器
  10. 听别人的故事探索属于自己的方法
  11. 浏览器访问网站标签页小图标显示
  12. 【高级微观经济学】厂商理论:生产技术与生产函数
  13. dparsf是什么_老师,我用DPARSF做Slice Timeing时老报错,请问您是什么原因呢?
  14. 解析KDTCN:知识图谱和深度学习模型联合实现股票预测
  15. AST还原技术专题:浅谈去控制流平坦化的思路及方法
  16. php递归写法,php递归无法返回问题,递归正确写法
  17. linux下创建用户6,Linux 用户管理
  18. 纯配置方式使用durid的数据库密码加密
  19. RocketMQ—Producer(三)发送方式和消息类型
  20. 2023天津工业大学计算机考研信息汇总

热门文章

  1. windows安全运维
  2. [深度学习][数据集][目标检测]工程车辆数据集16881张15种类别车辆介绍
  3. python输出到文件乱码_解决python解析文件时输出乱码
  4. logstash multi-pipelines
  5. PAT (Advanced Level) Practise 1013. Battle Over Cities (25)
  6. JS弹出“是否确认删除窗口”
  7. FastCGI 进程管理器(FPM)配置项目列表
  8. oracle 碎片高的表,表的碎片化-oracle狂热分子-ChinaUnix博客
  9. 高效压缩位图RoaringBitmap的原理与应用
  10. 小程序bindtap和cachetap的区别