现在的位置: 首页 > 综合 > 正文

skb — linux network buffers

2013年04月18日 ⁄ 综合 ⁄ 共 3125字 ⁄ 字号 评论关闭
文章目录

skbuffs are the buffers in which the linux kernel handles network packets. The packet is received by the network card, put into a skbuff and then passed to the network stack, which uses the skbuff all the time.
上面这段e文的大概意思:skb的作用就是用来衔接网卡和kernel中网络协议栈,网卡将接收到的数据包放在skbuffer里,然后再把skbuffer传给内核网络栈,网络栈在之后的一系列处理中都会用到此buffer。

Socket 缓存

每一层协议用另外层提供的服务,这样使用多层网络协议会有一个问题:每个协议都要在传送数据时都要 加上协议头和协议尾,而数据到达时又要将之去掉。这样,在不同的协议间要有数据缓存,每一层需要知道特 定协议的头和尾放在哪个位置。一个解决办法就是在每一层中都拷贝缓存,但这样做效率就很低。Linux用 socket缓存或者说
sk_buffs 来在协议层与网络设备驱动之间交换数据。 sk_buffs 包括指针和字段长度,这样每 个协议层就可以通过标准的函数或“方法”来操作应用程序数据。








图 1: Socket 缓存 (sk_buff)


1
显示了 sk_buff 数据结构;每个 sk_buff 有一个数据块与之相连。 sk_buff 有四个指针,这些指针 用来操作和管理socket缓存的数据:

head
指向内存中数据区的开头。这一指针在 sk_buff 和其相关的数据块分配时就固定了。
data
指向当前协议数据的开头。这一指针是随当前拥有 sk_buff 的是哪个协议层而变化的。
tail
指向当前协议数据的结尾。同样,这一指针也是随当前拥有 sk_buff 的是哪个协议层而变化的。
end
指向内存中数据区的结尾。这一指针在 sk_buff 和其相关的数据块分配时固定。

lentruesize 这两个字段分别用来描述当前协议包长度和数据缓存总体长度。 sk_buff 处理代码提供标准的操作来向应用程序增加和移除协议头和协议尾。这就可以安全地操作
sk_buff 中的 data , taillen 字段。

push
它把 data 指针指向数据区的开始并增加 len 。用于在要传输的数据开始处增加协议头。
pull
它把 data 指针从数据区的开始处移到数据区的结尾处,并减小 len 。用于在已接收的数据开始处移除协议头。
put
它把 tail 指针指向数据区的结尾处,并增加 len 。用于在要传输的数据结尾处增加数据或协议信息。
trim
它把 tail 指针指向数据区的开始处,并减小 len 。用于在已接收的数据尾移除数据或协议信息。

sk_buff 结构还包含了用于一些指针,用于在处理过程中存入 sk_buff 的双连接环路列表。通用sk_buff例 程可以将
sk_buff 加入到这些列表的前面或后面,也可以删除它们。

接收IP包

设备驱动一章描述了Linux的网络设备是如何置入内核并初始化的。一系列 device 数据结构在 dev_base 表中相互连接起来。每个
device 结构描述了它的设备并提供回调例程,当需要网络驱动来执行工作时,网络协议层调用这些例程。这些函数与传输的数据及网络设备地址紧密相关。当一个网络设备从网上接收包时,它必须将接收的数据转换成 sk_buff 结构。这些 sk_buff 则被网络驱动加入到了
backlog 队列中。

如果 backlog 队列太长,则丢弃接收的 sk_buff。准备好要运行时,网络底层将被设置标志。

当网络底层按计划开始运行后,处理 backlog 队列之前,任何等待着被传输的网络包都由它来处理。 sk_buff 决定哪些层处理被接收的包。

Linux网络层初始化时,每一协议通过将 packet_type 结构加入到 ptype_all列表或ptype_base hash表中来 注册它自己。packet_type 结构包含了协议类型,一个指向网络设备的指针,一个指向协议的接收数据处理例程的指针,最后还包括一个指向列表链或hash链中下一个
packet_type 结构的指针。ptype_all 链用于监听从网络设备上接收的所有包,通常不使用它。ptype_base hash表是被协议标识符弄乱的,用于决定哪个协议将接收传入的网络包。网络底层通过两个表中的一个或多个
packet_type 项来匹配传入 sk_buff 的协议类型。协议可以和多于一个的项相匹配,如在监听网上所有的传输时要复制多个
sk_buffsk_buff 将通过被匹配协议处理例程。

10.5.3 发送IP包

应用程序交换数据时要传输包,否则由网络协议在建立连接或支持一个已建立的连接时来生成。无论数据 是由哪种方法生成的,都要建立一个 sk_buff 来包含数据,当通过协议层时,这些协议层会加上各种头。

sk_buff 需要通过网络设备传输。首先协议,如IP,需要确定是哪个网络设备在用。这有赖于包的最佳路 由。对于通过modem连入一个简单网络,如通过PPP协议,的计算机来说,路由的选择是很简单的。包应该通过 本地环路设备发送给本地主机,或发送给PPP modem连接的网关。对于连在以在网上的计算机来说,连接在网 络上的计算机越多,路由越复杂。

对于每一个被传输的IP包,IP用路由表来为目的IP地址解析路由。从路由表中成功地找到目的IP时将返回一个描述了要使用的路由的 rtable 结构。这包括要用到的源IP地址,网络
device 结构的地址,有时还有预建立的硬件头。这些硬件头是网络设备特定的,包含了源和目的的物理地址和其它的特定媒体信息。如果网络设备是一个以太网设备,硬件头则应如图

10.1
所示,并且源和目的地址应是物理的以太网地址。硬件头在路由的时候会缓存起来,因为必须将它加到每一个要传输的IP包中。硬件头包含的物理地址要用ARP 协议来解析。传出的包在地址被解析后才会发出。解析了地址后,硬件头被缓存起来以便以后的IP包在使用这一接口时不需要再使用ARP。

数据分块

每个网络设备都有一个包大小的最大值,发送或接收数据包不能比这一值大。IP协议允许将数据分成更小单元以便网络设备能处理。IP协议头有分块字段,它里面包含了一个标志和分割偏移量。

当IP包准备要传输时,IP找到网络设备来将IP包发送出去。这个设备是从IP路由表中找到的。每一 device 结构中有一项 mtu ,用来描述最大传输单元(以字节为单位)。如果设备的
mtu 比要传输的IP包的包大小要小,则IP包必须被分割成更小的单元。每一单元用一个 sk_buff 结构来表征;它的IP头会被做上标记以标识它是一个分块了的包,其中还包含分割偏移量。最后一个包被标识为最后IP单元。如果在分块过程中,IP不能分配
sk_buff ,则传输失败。

接收IP分块单元要比发送它们要麻烦一些,因为这些IP单元可能以任何顺序到达,必须所有的单元都接收 到了以后才能重新将它们组装起来。每接收一个IP包都要检查其是否是IP分割单元。在第一个IP分割单元到达 时,IP会建立一个新的
ipq 结构,这一结构与用于IP单元重组的 ipqueue 列表相连。当接收到更多的IP单元时,先找到正确的 ipq 结构,并为每个单元新建立一个
ipfrag 结构。每个 ipq 结构唯一地描述一个接收IP分割单元的,包括它的源和目的IP地址,上层协议标识和本IP帧的标识。当接收到所有的IP分割单元后,将它们重新组成一个
sk_buff ,然后交给上层协议处理。每个 ipq 中包含一个定时器,它在每接收到一个合法的单元后重新时。如果定时器到时,
ipq
结构和它的一些 ipfrag 结构将被丢弃,传送的信息则被假定为丢失。然后提交给层协议来重传该信息。

抱歉!评论已关闭.