第十期-Linux内核补丁源码分析(2)

作者:罗宇哲,中国科学院软件研究所智能软件研究中心

在上一期中,我们通过CAKE系统的实例介绍了一种对Linux内核补丁的初步分析方法,这一期我们将继续通过CAKE系统的例子介绍一种对补丁文件源码的分析方法。

一、Linux内核补丁源码分析

在软件工程中,软件的数据流是对软件进行结构化分析的重要分析对象。结构化分析可以用于软件工程的需求分析阶段,用于产生符合用户需要的需求规格文档,其思想对我们分析内核源码也有启发意义。

在数据流的视角下,当信息在软件中移动时,它被一系列“变换”所修饰。通过对数据流的分析,我们可以得知数据从输入移动到输出的过程中所经受的变换。对数据流的分析可以是分层的,高层的数据流分析不关心对数据变换的具体实现形式,只关心输入输出的数据形式;而底层的数据流分析则可以将抽象的数据处理过程进一步具体化。

数据流的分析方法启发我们将操作系统模块源码分为两个部分,一部分为关键数据结构,另一部分为关键处理函数。关键数据结构是模块中包含关键的待处理信息的数据结构,它通过变换得到包含模块关键输出信息的新数据结构,或为关键处理函数实现其功能提供重要的辅助信息。关键处理函数是实现模块主要功能的函数,它通过调用实现其他子功能的函数来完成模块的主要功能。通过分析关键数据结构和关键处理函数,我们就能对模块的主要功能有一个基本的了解。

下面,我们以上一期提到的CAKE系统1中ACK Filter这一子功能为例,分析一下实现该功能的关键数据结构和关键处理函数。

通过CAKE相关的论文我们可以知道,当连接上的前向传输和ACK返回传输的能力不对称、且ACK返回传输通路的能力不足时,通过TCP ACK Filtering技术可以提升通路的性能。当队列中有携带更多有用数据的包时,这一技术可以监测队列情况,并舍弃一些不携带有用数据的ACK,被舍弃的ACK被称为PURE ACK(我们可以检查新加入队列的包携带的ACK中的信息是否比将要过滤的包携带的ACK中的信息长度更长)。为了判断ACK所携带的信息,ACK Filter会检查包的TCP头和IP头,以保证过滤不会导致信息丢失。

通过对CAKE ACK Filter子功能的分析,我们可以找到该功能的关键处理函数:

static struct sk_buff \*cake_ack_filter(struct cake_sched_data \*q, struct cake_flow \*flow)

该函数在net/sched/sch_cake.c,补丁为CAKE系统增加了ACK Filter功能,其函数代码较长,检查ACK队列进行过滤的部分代码如下:
在这里插入图片描述
该函数基于cake_sched_data结构体提供的辅助信息,来过滤cake_flow结构体中多余的ACK。这里,cake_sched_data和cake_flow为函数使用的关键数据结构,它们分别包含了过滤所用的辅助信息和待过滤的ACK队列元素。sk_buff是Linux网络模块中最重要的数据结构之一,用于描述已接收或待发送的数据报文信息。

分析该函数的我们可以发现,该函数首先将ACK队列的末尾的ACK标记为triggering,然后从头遍历ACK队列,寻找与该triggering ACK 匹配的PURE ACK。该寻找过程是通过5个if判断实现的,这5个if判断比较了triggering ACK 和待比较的ACK中携带的信息,从而确认待比较ACK是否为PURE ACK。

我们可以将这个过程分为两个阶段,第一个阶段为信息处理阶段,该阶段分析ACK包的TCP头和IP头等,并提取出有用的信息。第二阶段为比较阶段,通过5个检查项来识别PURE ACK。

对于第一个阶段,我们可以用以下函数调用图来分析:
在这里插入图片描述
从函数调用图我们可以看出,cake的ACK Filter分别解析了ACK 的TCP头和IP头的信息。对于ACK的过滤过程,我们可以考虑用流程图的方式来表示过滤算法:
在这里插入图片描述
其中检查项的主要内容依次为:

  1. 判断ACK的IP协议版本是否相同、TCP头的源地址和目的地址是否相同;

  2. 判断ACK的IP头中源地址和目的地址是否相同;

  3. 检查候选ACK的ECE/CWR标志位与之前同一个流中已选中的PURE ACK的对应标志位是否相同;

  4. 检查ACK是否有segment data、检查ACK是否有比triggering packet更高的cumulative ACK Counter值、检查ACK的SEQNO信息;

  5. 检查SACK选项。

注意在流程图中我们按if的判断条件给出了控制流的方向,而各个检查项在if条件中的具体表现形式可能与文字描述不同(主要是是否的关系问题)。

二、结语

本期我们通过CAKE系统中ACK Filter子功能的实例介绍了通过关键数据结构和关键处理函数分析源码的方法,并使用函数调用关系图和流程图分析了源码的具体实现形式。这两种图在我们以后的源码分析过程中将经常使用。下一期我们将尝试绘制Linux模块依赖关系图。
在这里插入图片描述


  1. https://kernelnewbies.org/LinuxVersions ↩︎

发布了20 篇原创文章 · 获赞 0 · 访问量 251

猜你喜欢

转载自blog.csdn.net/liucw900716/article/details/105300789