Linux 核心--11.网络(7) Linux网络层初始化时,每一协议通过将 packet_type 结构加入到 ptype_all列表或ptype_base hash表中来 注册它自己。packet_type 结构包含了协议类型,一个指向网络设备的指针,一个指向协议的接收数据处理例程的指针,最后还包括一个指向列表链或hash链中下一个 packet_type 结构的指针。ptype_all 链用于监听从网络设备上接收的所有包,通常不使用它。ptype_base hash表是被协议标识符弄乱的,用于决定哪个协议将接收传入的网络包。网络底层通过两个表中的一个或多个 packet_type 项来匹配传入 sk_buff 的协议类型。协议可以和多于一个的项相匹配,如在监听网上所有的传输时要复制多个 sk_buff 。 sk_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。 10.5.4 数据分块 每个网络设备都有一个包大小的最大值,发送或接收数据包不能比这一值大。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 结构将被丢弃,传送的信息则被假定为丢失。然后提交给层协议来重传该信息。 10.6 地址解析协议 (ARP) 地址解析协议担当了一个把IP地址翻译成物理硬件地址如以太网地址的角色。IP在将数据(以 sk_buff 的形式)通过设备驱动传送时需要这一转换。 它执行各种检查,来看是否这一设备需要硬件头,是否需要重建包的硬件头。Linux缓存了硬件头,这样可以避频繁重建。如果需要重建硬件头,则调用设备指定的硬件头重建例程。所有的以太网设备使用相同的头重例程,这些例程将目的IP地址转换成物理地址。