《九章协议处理.ppt》由会员分享,可在线阅读,更多相关《九章协议处理.ppt(28页珍藏版)》请在三一办公上搜索。
1、第九章 协议处理,主要内容,缓冲区管理分片重组常规协议(TCP/UDP)处理,9.1 缓冲区管理,数据包到达后,首先要分配一个缓冲区操作系统必须提供分配和释放缓冲区的服务,包括:管理空闲缓冲区为数据包找到合适大小的缓冲空间如果多个连接或用户共享一个缓存空间,还需提供某种形式的公平性困难:包缓冲区分配必须实时完成,9.1.1 缓冲区分配,经典的BSD UNIX包缓冲区实现称为mbufs:使用一个缓冲区链来存放一个包,每个缓冲区为一段连续的存储空间BSD定义了三种大小的缓冲区:100字节、108字节、2048字节(称cluster)Mbufs设计的出发点:使用一个缓冲区链来存放一个包:允许动态扩展
2、包的缓冲空间;适应各种协议栈定义不同大小的缓冲区:充分利用内存空间缺点:访问数据和拷贝数据的开销大,Sk_buf,Linux操作系统的包缓冲区实现是sk_buf:每个包缓冲区都是一块连续地址空间,提前为路径上需要添加的各种协议头预留了空间用空间换时间(P4b):包缓冲区必须满足最大包长,有时会浪费空间,但实现简化了。避免不必要的一般性(P7):放宽对支持任意协议栈的要求,以提高速度。,如何为不同大小的包分配缓冲区?,按需分配内存:当一个包到来时,为其分配一块合适大小的缓存空间动态分配内存的困难:用户在不同的时间释放缓冲区,导致内存中出现许多不连续的、大小不同的空闲区域教科书上的标准算法(如Fi
3、st-Fit、Best-Fit)可以搜索到合适大小的空闲区域,但速度太慢,高速包缓冲区分配器,隔离池分配器(Segregated Pool Allocator)Linux分配器(Linux Allocator)批量分配器(Batch Allocator),隔离池分配器,随BSD 4.2 UNIX发布,称Kingsley malloc()。将存储空间划分成一组隔离的内存池,同一个内存池中的缓冲区大小相同,为2的幂次。内存请求被取整到最近的缓冲区大小,从相应的内存池链表头部取一个空闲缓冲区分配。若对应的内存池空间不足,分配失败。可能有内存空间浪费,但实现简单。,Linux分配器,Linux分配器最
4、初由Doug Lea实现,称为dlmalloc()内存被划分成128个内存池:前64个内存池,缓冲区大小分别为16、24、32、512字节(按8字节步长增加)后64个内存池,大小为2的幂次分配器会合并相邻的空闲缓冲区,放入合适的缓冲池中。Lea分配器比Kingsley分配器使用内存更高效,但实现起来更复杂。,批量分配器,分配器一次性向系统请求一大块内存,用来作为包缓冲区(批量的含义)当一个内存块正在使用时,后台创建另一个空闲内存块分配器在当前内存块上采用顺序分配:一个指针指向上一次分配结束的位置,新的内存请求总是从当前位置开始分配一个内存块用完,立即转移到另一个空闲内存块上,批量分配器(续),
5、当缓冲区释放的顺序与分配的顺序不一致时,内存块中形成一些孔洞,需要合并。方法一:使用足够多的内存块,确保在这些内存块用完之前,已分配的内存块被释放,避免显式回收。(目前工业界的做法)方法二:使用页面重映射将若干分离的物理页映射成在虚拟存储空间是连续的。优点:支持可变长度的内存分配,没有内存浪费,分配快。,9.1.2 共享缓冲区,假如一群用户共用同一组空闲缓冲区,我们希望共享缓冲区的分配是公平的:这组缓冲区在需要的用户之间近乎均等地分配共享缓冲区的用户是变化的:每个用户分配的缓冲区数量应当能够动态调整当有新用户加入时,应能从老用户那儿夺取一些缓冲区,缓冲器窃取,实现公平分配的一种方法是缓冲区窃取
6、:若所有缓冲区已用完,一个分配较少的用户想多要一些缓冲区,就从当前分配最多的用户那儿窃取。即使一个用户最初攫取了全部缓冲区,其它用户通过缓冲区窃取可以获得他们公平的份额。缓冲区窃取的通用解决方案:使用一个大顶堆,代价O(logn),n为当前活跃的用户数。如何实现得更快?,缓冲区窃取的常数时间算法,如果允许用户一次获取任意数量的缓冲区,那么使用O(logn)的堆是必需的。假设降低要求:一个用户一次只能窃取一个缓冲区每个用户拥有的缓冲区数量是一个小整数采用桶排序:分配了 i 个缓冲区的进程组织在一个链表中,头指针保存在第 i 个桶中一个变量highest指向分配了最多缓冲区的进程链表,Mckenn
7、ey算法的数据结构,窃取一个缓冲区,当进程 P 希望获取一个缓冲区时:算法从highest指向的进程链表头部取进程Q,Q的缓冲区数量减1,P的缓冲区数量加1将P从链表 i 移到链表 i+1将Q从链表 j+1移到链表 j如果highest指向的链表为空,更新highest算法是常数时间的:由于限定了每次只能增加或减少一个缓冲区,算法更新highest指针最多只需移动一个桶。,9.2 TCP头部预测,tcp_input是TCP代码中最长的一部分代码,其中绝大部分代码用于处理不常见的情形。头部预测:快速识别预期的TCP段,避免冗长的状态检查,优化常见情形的处理(P11)。,对TCP头的观察,连接完成
8、后,目的端口和源端口是固定的大部分情况下IP包顺序到达,因此序号域通常等于预期接收的下一个序号连接建立后,ACK标志总为1,其它标志一般为0大多数情况下,接收窗口大小不变当URG标志为0时,紧急指针域不用变数较大的域只有两个:确认序号,检查和,预期情形,大多数时候,TCP连接上的数据传输是单向的:客户从服务器下载一个文件,或客户向服务器上载一个文件。两种预期的情形:收到一个纯ACK段(无数据)收到一个纯数据段(确认序号无更新)其它预期情形:标志位常规设置无窗口更新,接收端头部预测的伪代码,接收端头部预测伪代码(续),第一个子句检查标志位设置是否符合预期第二个子句检查是否无窗口更新第三个子句检查
9、是否是预期接收的段(不是乱序到达或重发的)若以上条件判断为真,这是预期接收的TCP段,再区分是纯ACK段还是纯数据段若以上条件判断为假,不是预期接收的TCP段,执行常规的处理过程(慢路径)标志域以及窗口大小组成一个32位的字,可将这个字的预期值保存到PCB中,头两个子句的检查只需用TCP头的第4个字与PCB中保存的字进行一次比较即可。,发送端头部预测,在发送端发送的一系列 TCP 段中,TCP头部有变化的域只有少数几个。发送端头部预测:发送端在PCB中建立一个TCP头模板每当需要发送一个TCP段时,将模板拷贝到相应的包缓冲区中,填写少数几个有变化的域,9.3 IP分片重组,分片重组的经典实现:
10、各分片按照分片偏移量保存在一个有序链表中一个分片到达时,顺序查找链表,插入到合适的位置在寻找插入位置的过程中,检查分片之前的数据是否全部到达;如果是,在插入分片后继续沿链表向下查找,检查是否全部数据已到达;如果是,重新扫描链表,将数据拷贝到另一个缓冲区中,优化预期情形,重组过程复杂的原因:考虑到IP分片可能乱序到达,且分片之间可能有重叠预期情形:IP分片按序到达,且没有重叠优化预期情形:若判断为预期情形,只需将到来的分片添加到链表尾部(一个常数时间操作),优化的IP分片重组算法,在有序链表的基础上,增加一个指向链表尾部的指针。分片到来时,用分片的起始字节偏移量与链表上最后一个分片的末字节偏移量
11、(存在一个变量中)进行比较。若分片顺序到达且无重叠,将分片添加到链表的尾部,更新指向链表尾部的指针,更新末字节偏移量。如果这是最后一个分片(MF=0),重组结束。寻找插入位置及检查重组是否结束,只需要常数时间。,假设与实际相符吗?,分片重组优化算法隐含的假设:IP分片按照偏移量从小到大的顺序发送多数情况下IP包顺序到达实际测量:许多较新的实现(包括Linux),发送端按照分片偏移量从大到小的顺序发送IP分片!原因:最后一个分片携带了IP包总长度的信息,让最后一个分片最先到达接收端,方便接收端为数据包分配适当大小的缓冲区。,算法调整,使用第一个到来的分片,判断发送端按照什么顺序发送IP分片。如果第一个到来的分片是第一个分片,使用前述实现。如果第一个到来的分片是最后一个分片,跳转到按逆序处理的程序:最后一个分片放在链表头部,其余分片按偏移量降序排列用分片的末字节偏移量与链表尾部分片的起始偏移量进行比较,9.4 总结,缓冲区分配:空间利用率 VS 合并不连续空闲区域的难度缓冲区共享:缓冲区窃取TCP输入处理、IP分片重组:通过优化预期情形的处理,提高大多数情况下的算法性能。,