head 指向内存中数据区的开头。这一指针在 sk_buff 和其相关的数据块分配时就固定了。 data 指向当前协议数据的开头。这一指针是随当前拥有 sk_buff 的是哪个协议层而变化的。 tail 指向当前协议数据的结尾。同样,这一指针也是随当前拥有 sk_buff 的是哪个协议层而变化的。 end 指向内存中数据区的结尾。这一指针在 sk_buff 和其相关的数据块分配时固定。 len 和 truesize 这两个字段分别用来描述当前协议包长度和数据缓存总体长度。 sk_buff 处理代码提供标准的操作来向应用程序增加和移除协议头和协议尾。这就可以安全地操作 sk_buff 中的 data , tail 和 len 字段。
push 它把 data 指针指向数据区的开始并增加 len 。用于在要传输的数据开始处增加协议头。
pull 它把 data 指针从数据区的开始处移到数据区的结尾处,并减小 len 。用于在已接收的数据开始处移除协议头。
put 它把 tail 指针指向数据区的结尾处,并增加 len 。用于在要传输的数据结尾处增加数据或协议信息。
trim 它把 tail 指针指向数据区的开始处,并减小 len 。用于在已接收的数据尾移除数据或协议信息。
10.7 IP 路由 IP路由函数决定了将预定的有指定IP地址的IP包送到哪。在传送IP包时有很多种选择。能最终到达目标吗?如果能,要用到哪个网络设备呢?如果有多于一个的网络设备可被使用,哪一个是较好的呢?IP路由数据库里存的信息给出了这些问题的答案。有两个数据库,最重要的一个是Forwarding Information Database。这是一个有关已知的目的IP和它们的最佳路由的祥细列表,route cache则用来快速找到目的IP的路由。和其它的缓一样,它包含的只是常用的路由;它的内容来自Forwarding Information Database。
10.7.1 路由缓存 无论什么时候查找IP路由,首先都要在路由缓存中检查是否有匹配的路由。如果路由缓存里没有匹配的路由,则要从Forwarding Information Database中查找路由。如果那里也没有找到路由,则IP包发送失败并通知应用程序。如果在路由缓存中没有而在Forwarding Information Database中找到路由,则会为些路由生成一个新项,并添加到路由缓存中。路由缓存是一个表(ip_rt_hash_table),它包括指向rtable数据结构链的指针。hash函数利用IP地址中最小最重要的两个字节来从路由表中进行索引。这两个字节是在目的与提供的最佳hash值间是不同的。第个rtable项包含路由信息,目的IP地址,用于到达那个IP地址的网络设备,信息大小的最大值等等。它还有一个reference count,一个usage count和一个最近一次被用的时间信息(在 jiffies 里)。reference count在每次路由后增加,用于显示该次路由的网络连接数。它在应用程序停止使用路由时减小。useage count在每次查找路由时增加,用于将 rtable 项在它的hash链中排序。路由缓存中的对于所有项的最后被用时间信息将被周期性地检查,以确定是否 rtable 已经旧了。如果某一路由最近没有被使用,则从路由缓存中将之丢弃。由于路由缓存中的路由在有序的,所以常用的路由会排在hash链的前面。这意味着能更快地找到这些路由。
10.7.2 The Forwarding Information Database
图 10.5: The Forwarding Information Database Forwarding Information Database(如图 10.5 所示)包含对当前系统当前时间可得到的IP路由。它是一个 很复杂的数据结构,尽管进行了合理有效的安排,它仍然不是一个快速的数据库。特别是要在这个数据库中为每一要传送的IP包查找目的地时将会非常慢。这就是要用路由缓存的原因:可以用已知的好的路由来加速IP包的传送。路由缓存中的路由来源于Forwarding Information Database。