网络设备的两种基本类型

网络设备的两种基本类型
    那么网络设备都有些什么性能瓶颈呢?这里,我们首先要对网络设备做一个分类,因为不同的网络设备,性能瓶颈产生的原因及解决方案都是不同的。本书的作者将网络设备分为端节点和路由器两种基本类型。
端节点性能瓶颈的产生
    下面我们看一下端节点和路由器的性能瓶颈分别是怎么产生的?
对于为通用计算而设计的端节点来说,主要的性能瓶颈来自结构化开销。(1)为方便软件开发,大多数操作系统都按照分层原则来组织,比如硬件抽象层、资源管理层、资源分配及调度等。(2)为了保护操作系统不受应用程序的破坏,操作系统都实现了一组保护机制。(3)为适应尽可能多的应用,核心操作系统的例程(如调度器、内存分配器等)使用一般机制来写成。
软件分层、保护机制和过度一般化这三者结合起来,就使得网络软件运行很慢,哪怕是运行在一个高速处理器上。
    对于提供网络服务的服务器(如web服务器)来说,性能瓶颈还来自用户规模。许多操作系统使用的是只能支持少量连接的低效的数据结构和算法,而现在一台服务器要求同时服务一百万个并发客户,低效的实现使其运行很慢。
路由器性能瓶颈的产生
    和端节点不同,路由器是网络专用设备,因此路由器内部的结构开销很少。它只使用一个非常轻量级的操作系统,以及一个完全由硬件实现的转发路径。路由器瓶颈一般由规模和服务引起。
    规模主要指链路带宽(流量)和网络规模(网络数量、用户数量)。80年代到90年代之间,网络设备厂商主要解决这两个规模问题,因为越来越多的商业应用搬到了网络上,越来越多的网络加入因特网中。
接下来的十年甚至更长时间,关注点开始转向为这些网络应用提供服务质量、安全性和可靠性方面的保证,如实时流媒体、入侵检测、内容过滤等。这些服务都要求复杂的网络包处理。高速实现这些新的服务是路由器制造商面临的主要挑战。
现在,以上挑战并存,链路速率已达到40Gbps甚至更高。
解决瓶颈的技术:网络算法学
如何解决以上瓶颈?本课程会谈及许多具体的技术,如减少中断开销、消除拷贝、时间轮等。但是,我们不能仅停留在这些技术的表面,而要去领会和掌握这些技术后面更重要的观念-网络算法学,即运用系统的方法去组织网络实现。
系统方法中一个重要的观察是,我们通常可以通过在时间及空间上移动一个子系统中的某些功能来设计出高效的子系统。比如,可以将协议处理从CPU转移到网卡,包缓冲区可以被预分配。
在某种程度上说,网络算法学的执行者是一个不择手段的机会主义者,他可以改变游戏规则,唯一的约束就是整个系统提供的功能是满足用户需要的。
考虑一下网络实现者面对的问题:越来越高的链路速度,越来越复杂的处理任务,越来越大的网络规模,少量的高速内存(cache),比计算时间长得多的访存延迟。设计者必须使用各种可能的手段(使用硬件、改变系统假设、设计新算法),只要能够解决问题。
一个热身的例子
    下面我们通过一个热身的例子来直观地感受一下网络算法学。
有一种常见的攻击类型—内存溢出攻击,入侵者将恶意代码放置在数据包头中的某个域。如果目标计算机为该域分配的存储空间太小,又没有进行边界检查,就会发生数据溢出,恶意代码溢出到目标机器的堆栈中。通过一些巧妙的设计,入侵者可以使得目标机器去执行恶意代码。
入侵者经常使用的域是HTTP消息中的URL域。我想原因可能是三个:一是Web应用很普遍,防火墙一般开放端口80;二是URL域可以放置任意的字符串,服务器一般不会进行有效性检查;三是很长的URL也很普遍,不太容易引起怀疑。
IDS如何检测一个URL可能携带了恶意代码呢?通过观察发现包含恶意代码的URL通常很长,并且包含大量在URL中不常出现的字符,如#。假定安全分析员以URL太长、并且字符出现比例异常作为攻击特征,要求芯片设计师设计一个硬件来对包含可疑URL的包作标记。
一个简单的方案
aaaaaaaaaaaaaaaaaa
    检查URL的长度很简单,我们重点研究如何检测可疑字符的出现比例。
一种简单的方法是维护两个长度为256的数组T和C,数组中的每一个元素对应一个ASCII字符。T数组保存各个字符在一个URL中可接受的出现比例,如果某个字符在一个URL中出现的比例超过了设定的门限,该分组应被标记。C数组记录每个字符在一个URL中出现的次数。直流系统绝缘监测装置
算法分析
    在分析算法之前,我们先来看一下对这个硬件有什么性能上的要求。一个最基本的要求是必须来得及处理按链路速率到来的流量,这称为线速处理要求。线速处理要求在网络中是非常常见的,即一个分组必须在下一个分组到来之前处理完,否则在最坏情况下会丢包。
为满足线速处理要求,理想情况下,芯片对于每个扫描的字节应当只做少量的操作。假定C[i]加1可以在每个字节到来的时间内完成。
注意到这个算法对数组有两次遍历,一次是扫描新包前的初始化,另一次是扫描完URL后检查各个字符的出现比例是否超限,两次遍历至少需要768次读/写操作(C数组读、写各一次,T数组读一次)。
    考虑最坏情况:仅包含HTTP请求头的包连续到来。在当前URL结束至下一个包的URL开始,只有几十个字节的时间,每个字节的时间内需要完成一百多次的读/写操作,这是不可能完成的,即达不到线速处理的要求。因此,优化的关键是减少或消除这两次遍历。
算法优化:取消URL风刀干燥机结束后的一次遍历
    直观上看,在扫描完URL后对C和T数组的遍历是不必要的。因为芯片只是要标记数据包中是否有任何字符的出现比例过高,并不需要给出究竟是哪些字符超标,所以为什么要检查所有的字符呢?
    一种想法是我们只需跟踪最高的相对出现次数,看它是否超标。注意,这里不是跟踪最高出现次数,因为不同字符的出现比例上限是不同的。这样当URL扫描结束,处理也完成了。
我们看到,该方法消除了一次遍历,其代价是每个字节时间内的处理增加了。
这个方案存在什么问题呢?
利用硬件特性:消除除法运算
白术提取物
    新的算法消除了URL扫描结束后的遍历,但是扫描每个字节时需要一次除法运算。除法运算不管是软件实现还是硬件实现,都是开销比较大的。因此,这里的问题是能否消除这个除法运算?
我们知道有一种特殊的情形,除法的实现非常简单,即是除数为2的幂次的情况,这时除法可以用移位来实现。然而,T[i]不一定是2的幂次。
网络分配器
    再回到问题的开始。我们认为每个字符的门限值不见得必须是一个精确的浮点数,安全分析员不太可能精确地估计这个值,因此完全可以用一个小于给定值的近似值来代替。比如,用1/32来代替1/29。当然这个改变必须征得安全分析员的同意。
当做了这样的改变后,除法运算可以转化为简单的移位运算。比如,若T[i]=1/32,则C[i]/T[
i]只需要将C[i]向左移5位。同时,数组T可以存放移位的次数(整数),而不是一个分数。
改进后的处理过程如下:读入一个新字符“i”后,C[i]加1,然后左移T[i]位,若移位后的值大于Max, 更新Max。当URL扫描结束后,如果Max≥ L,标记分组。
大家看看这个改进后的方案,还有什么地方可以改进?
    提示:与朴素的方案相比,在每个字节的时间内增加了一次读T[i]的操作(朴素的方案对C[i]分别读、写一次)。
目前最快的片上存储器访问耗时1-2ns, 慢的需要10ns,都比硬件逻辑慢。单个门电路的延迟在ps量级,移位逻辑不需要太多的门延迟,因此处理瓶颈在于访存次数。当我们在提出一种优化措施时,一般不希望引入新的问题。
问题:能否不增加读/写内存的次数呢?
利用硬件特性:合并对TC的读操作
方法是使用较长宽度的字,每个字中保存C[i]和T[i],比如用15比特统计字符的出现次数(
可允许32K的URL),用14比特表示移位次数。
需要注意的是,用软件方法抽取出合并到一个字中的域很烦人,但用硬件实现很容易,只需在寄存器之间合理连线或使用多路复用器。
到目前为止,我们成功地消除了URL扫描结束后对数组T和C的遍历,并消除了该方法产生的除法问题以及URL扫描过程中多一次访问T数组的问题。
Lazy Evaluation:消除对C的初始化
滤油机滤布    我们现在还剩下一个初始化C数组的循环。注意到,在相邻两个URL之间只有几十个字节,若以40字节(UDP头+IP头)计算,在该空闲时间内初始化256字节的数组,平均每个字节时间需要完成6次以上的操作(256/40 > 6)。
    大家考虑一下这个问题:我们是否有必要在每开始一个新的数据包时,清除整个C数组?比如,一个URL可能只有几十种字符,清除那些未使用的字符计数器是否多余?
    从道理上说,芯片不需要初始化C[i],直到一个新的数据包需要使用该C[i]时(第一次访
问该C[i])。也就是说,从道理上我们可以仅在需要使用一个字符计数器时再去清除该计数器。这种将工作拖到不得不做的时候才去做(寄希望于可能不要做)的方法叫做lazy evaluation。
如果以上想法可以实现,那么当芯片扫描到一个新的URL、并且第一次遇到字符”i”时,设置C[i]=1,此后再扫描到字符”i”时,只需将C[i]加1。
但是,芯片如何知道它是第一次看到字符“i”呢?换句话说,当芯片根据”i”到C[i]时,它怎么知道这个计数器统计的是当前URL中的”i”,还是之前某个URL中的”i”?为此,我们可以给每个数据包赋一个代号,该数据包使用的计数器具有与数据包相同的代号。
这么做有问题吗?
使用长周期的清洗循环清理C
    为避免g回绕产生歧义,所有未被使用的计数器在其世代号发生回绕前必须被清除。也就是说,芯片需要有一个主动清洗的循环,依次读入数组的表项,将那些代号过时的C[i]置0。为保证正确性,每处理8个分组,芯片必须执行完一次完整的清洗循环。
假定每个分组有40个非URL字节,8个分组就有320个非URL字节,这些时间完全够用来初始化256个元素的数组(每个字节完成一次读和一次写操作)。如果需要的话,可以通过增大世代号的长度来获得更宽松的处理时间,代价是增大了一点点数组的存储空间。
    改进的方法如下……。这是最终的改进方案。
分析:每个表项中增加3比特的世代号后,减少了初始化处理的周期数(用存储换计算)。在URL字节的处理过程中,增加的初始化检查(对G[i]的检查)不会增加访存(三个域一次读入),只是增加了一些处理逻辑(判断G[i])。另外,芯片需要2个寄存器用来保存g和s,增加了一点点空间开销。
比较一下最初的简单方案(普通人的方案)和最终的方案(技术专家的方案),差距一目了然。如果抽去中间的过程,直接给出最终方案,估计很少有人能够理解为什么要这么设计?设计者是怎么想到这个方案的?

本文发布于:2024-09-23 07:21:01,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/337356.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:处理   字符   网络   使用   瓶颈   要求   数组   实现
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议