采用标记值的多样本包内容检测机制的制作方法

文档序号:7638430阅读:379来源:国知局

专利名称::采用标记值的多样本包内容检测机制的制作方法
技术领域
:本发明通常涉及网络设备领域,并且尤其但不排它地涉及使用标记值执行包内容检测的技术。
背景技术
:企业日益地受到了各种安全问题的威胁。这种威胁可以是内部的或外部的。内部威胁包括恶意员工的入侵企图、员工带入的病毒或蠕虫或仅仅是根据每个企业的安全策略而被认为是不可接受的员工网络访问行为。外部威胁包括为窃取知识产权信息而对企业网络进行的专门攻击、拒绝服务攻击、未授权入侵、病毒和蠕虫等。在所有这些情况中,包防火墙是网络管理员的首选防御形式。包防火墙与网络流量保持-致,截取到来的包并将每个包按一组防火墙规则进行验证以接受或拒绝包、或可选地对包进行日志记录。除了包过滤外,网络管理员有时还使用包过滤来实现流量管理策略。这种策略用于限制或控制攻击性行为。由于包防火墙与所有的网络流量保持一致并检测所有的网络流量的事实,因此很重要的是,防火墙应该能够提供足够的网络吞吐量来满足网络流量需求。在当今的企业网络中,防火墙规则通常限于2500CiscoACL(访问控制列表)规则。这些规则相当具体,用于允许或拒绝具体的活动或主机。由于性能和管理原因,ACL规则限于此数量。规则的数量直接影响路由器性能,因此这些规则维持在较低的数量上。此外,大量的规则还使得规则管理更易于出错并难于验证或修改。在较大的组织中,规则跨越防火墙分布在不同的地点,并且在需要时要对所述规则进行修改,这就增加了出错的机会。由于这些原因,必须将规则的数量维持在可管理的级别上。在典型的高级防火墙实现中,采用了两级过滤。在第一级别上,基于可应用的ACL规则来执行过滤。在这种情况下,基于包头信息来识别与ACL数据库相对应的最高优先级规则。例如,可以基于与源和目的地址的值、源和目的端口、以及使用公知分类算法的协议相对应的五元组输入来识别规则。由于许多攻击(特别是拒绝服务攻击)都源于使用特定端口的已知源地址,因此可以容易地识别与这些攻击相对应的包,并采用适当的规则(例如丢弃包)来实现期望的防火墙策略。可以使用现代网络设备以线速速度来实现第一级别的过滤。在某些实现中,采用了专用的部件或单独的计算机来执行这些过滤操作。第二级别的过滤涉及包检测。在这种情况中,搜索实际的包的有效负载以寻找特定的字符串或字符串集。例如,防火墙应用可能需要寻找表示存在于包中的病毒或因特网蠕虫的特定字符串。此外,其他的非安全应用同样需要窥视包的有效负载,以例如用于负载均衡或负载计费的目的。这些操作被称为"内容检测"或"(深度)包检测",涉及检测包的有效负载以寻找竞争样本,并基于这些样本是否存在而采取行动。在某些防火墙实现中,包/内容检测可能由不支持线速速度的单独应用或子系统来实现。例如,这些操作可以由单独的计算机主机或与网络装置耦合或由网络装置提供的嵌入式通用处理器来执行。由于这些操作不是以线速执行的(因此并不受对应的处理延迟的限制),因此它们可以采用较大但较慢、价格较便宜的存储器(例如DRAM(动态随机存取存储器)),并采用常规的字符串搜索技术。由于网络处理器(也被称作网络处理器单元(NPU))的成本效益、处理速度、灵活性和可升级性,其日益用于多种网络设备中。在构造下一代网络平台中,人们期望在添加具鲁棒性的防火墙功能的同时而无需添加专门的防火墙部件,取而代之的是利用网络处理器技术,并以可复用、可伸縮的方式将防火墙功能加入到NPU代码中。内容检测是资源密集型活动,这是因为其涉及扫描整个包的有效负载以寻找一组样本。检测算法消耗了大量的存储带宽及计算资源,极大地影响了整体性能。如果我们减少包中扫描的数据量,则可以提升内容检测算法的性能。减少扫描的数据量的一种技术是使用与样本相关的启发式信息。在很多情况下,包中的样本仅在存在于包的特定部分中时才具有特殊的重要性。例如,如果内容检测模块扫描寻找URL,则将包中ULR字符串有效的大致位置特定为先验(priori)。可用于限制包搜索空间的信息是偏移(offset)和深度(depth)。偏移参数表示包中搜索字符串的初始位置,而深度参数标识包中搜索字符串的截至位置。偏移和深度通常根据单独的字数串而定。但是,内容检测系统需要同时搜索包中的多个样本。在常规技术中,其无法以线速速度实现,其可伸縮性是有限的。通过参考下面的详细描述,并结合附图,本发明的上述方面和其内在的优点会变得显而易见且更易于理解。在附图中,除非另有指明,各个示图中相似的参考标记指代相似的部分图1的示意图示出了通过使用上下文管线的多个计算引擎来处理多个功能的技术;图2的示意图示出了用于实现本文所述发明的实施例的多个方面的软件模块结构;图3的流程图示出了由一个实施例执行的、确定是否对包执行内容检测的操作和逻辑;图4a示出了为流分类采用的包的各个部分;图4b示出了一组分类规则和相关的流;图5示出了采用主次散列表的散列表查找方案的一个实施例;图6的流程图示出了在生成样本数据结构的预处理操作期间执行的操作和逻辑;图7的示意图示出了由网络线卡采用的数据流和功能块,所述网络线卡包括具有用于执行指令线程的多个计算引擎的NPU,以执行包括内容检测的包处理操作;图8a的流程图示出了在流中的第一个包的内容检测期间执行的操作和逻辑;图8b的流程图示出了在流中的非第一个包的内容检测期间执行的操作和逻辑;图9的流程图示出了采用偏移和深度搜索信息的内容检测操作;图IO示出了与示例性AC状态机数据结构相对应的转向(goto)函数、失败函数和输出函数;图11示出了在存储器中存储的样本数据结构的一个实施例;图12示出了AC机节点存储器数据结构的一个实施例;图13示出了AC机变址存储器数据结构的一个实施例;图14示出了存储在存储器中的DAWG数据结构的一个实施例;图15示出了后缀树存储器数据结构的一个实施例;图16示出了移位表存储器数据结构的一个实施例;图17示出了散列表存储器数据结构的一个实施例;图18示出了前缀表存储器数据结构的一个实施例;图19示出了根节点存储器数据结构的一个实施例;图20示出了子节点存储器数据结构的一个实施例;图21示出了条件行为规则存储器数据结构的一个实施例。具体实施方式下面描述执行字符串搜索的方法和装置的实施例,所述字符串搜索使用标记偏移和深度信息以进行多样本搜索。在以下描述中,阐述了大量的细节,以实现对本发明实施例的透彻理解。但相关领域技术人员可以理解的是,不使用这些特定细节中的一个或多个,或使用其他的方法、部件和材料等,也可以实践本发明。在其他示例中,未详细示出或描述公知的结构、材料或操作,以避免对本发明的各个方面造成模糊。在本文全文中对"一个实施例"或"实施例"的引用表示结合本发明至少一个实施例中包括的实施例而描述的特定特征、结构或特点。因此,在本文的各个位置中出现的词语"在一个实施例中"或"在实施例中"并不一定指代同一个实施例。此外,在一个或多个实施例中,可以任何适当的方式将特定的特征、结构或特点予以组合。根据本文中描述的实施例的各个方面,披露了便于使用偏移和深度标记值、以进行多样本搜索并同时保持线速速度且提供可伸縮的解决方案的内容检测的机制。这些机制采用了基于状态的内容检测算法,其允许内容检测停止并在包的边界处重新开始,而同时保持与部分字符串搜索的结果相关的信息。与此同时,可以使用最小的缓冲来实现所述机制,并支持使用NPU的线速速度。为了更好地理解和领悟现代网络处理器上机制的实现,首先描述典型的基于管线(pipe)的NPU处理操作,再下面将具体论述各个实施例。现代网络处理器,例如英特尔⑧(Intel)的IXP2xxx家族的网络处理器,采用了多个多线程的处理元件(例如微引擎)来便于实现线速包处理操作。为了处理包,网络处理器(和/或采用了网络处理器的网络设备)需要从指示包目的地、服务类别等的包头中获取数据,将有效负载数据存储到存储器中,执行包分类和排队操作,确定包的下一跳跃,选择经由其转发包的适当的网络端口等。这些操作通常被称为"包处理"操作。对包的一些操作已被良好定义,其具有到其他功能的最小接口或严格的顺序实现。这种例子包括更新包的状态(update-of-packet-state)信息(例如在DRAM缓冲器中用于包的顺序分段的的包数据的当前地址)、在入队/出队以进行传输时更新链表指针、以及管理或标记连接流的包。在这些情况下,可以在预定义的循环阶段预算中执行操作。与此相对应,在以严格顺序对连续的包持续操作并在同时实现跨越多个阶段的周期预算方面会出现困难。执行这种功能的代码块被称为上下文(context)管道阶段。如图l所示,在上下文管线中,随着时间的推移不同的功能在不同的微引擎(ME)上执行,并且在多个功能或ME之间传递包的上下文。在如图所示的配置下,z个ME100。—,用于包处理操作,每个ME运行"个线程。每个ME组成与由该ME执行的相应功能相对应的上下文管道阶段。级联两个或更多个上下文管道阶段就组成了上下文管线。之所以将其称为上下文管线是因为观察到其是通过管线移动的上下文。在上下文管线下,为ME中的每一线程分配包,并且每一线程对不同的包执行相同的功能。当包到达时,以严格的顺序将其分配给ME线程。例如,在英特尔IXP2800⑧ME上下文管道阶段中,通常有八个线程用于分配。分配给八个线程的八个包中的每一个必须在所有八个包的到达速率内完成其第一管道阶段。在图1所示的命名法下,ME/./中的/对应于第f个ME号,而/对应于运行在该第/个ME上的第/个线程。更先进的上下文管线技术采用了交织的阶段管线。该技术交织同一线程上的多个包,将八个包分隔开。例如MEO.l,其对包l完成管线阶段O的处理,而在同时对包9开始管线阶段0的处理。类似地,ME0.2对包2和10进行处理。在效果上,可以同时在一个管线阶段中对16个包进行处理。管道阶段0仍必须推进每8个包的到达速率。这种交织的优点在于存储器延迟由完整的8个包的到达速率所覆盖。根据所述的实施例的方面,使用采用多个多线程处理原件的NPU可以实现新颖的内容检测方案和机制。这些方案可以经由上下文管线技术来实现,在所述上下文管线技术中,分配给共同的流的相应的包的内容检测是使用在一个或多个计算引擎(例如微引擎)上执行的不同的指令线程来实现的。为了便于实现方案,将内容检测状态信息维持在可由指令线程和计算引擎访问的数据结构中。例如,在第一计算引擎上执行的第一线程用于对多个包中的第一个执行字符串搜索,所述多个包共同地包含匹配候选样本的字符串,而所述字符串并不被完整地包含在单独的一个包中(即字符串的各个部分被包含在各个包中)。第一线程维持与字符串搜索相关的状态信息,当到达第一个包的末尾时,对应的信息识别部分匹配。期间,采用了在相同或不同计算引擎上执行的第二线程,来对在其初始处包含候选样本的剩余部分的第二个包实施字符串搜索。第二线程采用由第一线程生成的状态信息以在第一线程停止的点继续搜索。当识别到匹配时,可以基于对应的预定义规则或动作(也被称为"动作目标")来采取适当的动作。整个的内容检测处理是以与常规NPU包处理操作并行的方式执行的,所述常规NPU包处理操作是以支持线速速度的方式执行的。此外,该机制可以轻易地扩展,以支持大量的同时的流。图2示出了用于实现本文所述的包处理操作的各个方面的软件结构200的各种部件、数据结构和处理块。部件包括深度包检测器(DPI)模块202、流管理器模块204、规则引擎模块206、录志器模块208和目标处理(handler)模块210。数据结构包括流表212和规则表214。处理块包括输入验证块216、流确认块218、规则匹配块220、日志异常块222、异常生成块224、策略执行块226以及响应生成块228。深度包检测模块202用于执行基于可应用的搜索样本的各种字符串搜索操作,下面将对其进行详细描述。流管理器204提供了API(应用程序接口)以访问和管理流表212。规则引擎206向规则表214提供了API,实现一定级别的转换。例如,用户指定的规则在成为可由快速路径(例如计算引擎)处理代码使用的形式之前要经历多个级别的转换。DPI模块202实际上并不是单个模块(图中如此示出是出于简化的目的),应将其视为经由在NPU计算引擎上运行的对应线程而实现的多个特定协议功能的集合。录志器模块208管理日志功能。该模块可以直接管理日志或使用来自不同处理器(例如NPU中的通用处理器,或分离的计算机主机中的处理器)中的另一个部件的服务以实现日志功能。通常,防火墙中的日志功能包括从简单的基于文本的日志记录到将数据转储到关系数据库以用于生成详尽的报告。该模块的复杂度取决于所提供的功能。当包进入系统时,首先由输入验证块216进行协议一致性、校验和等验证。一旦执行了该完整性检查后,流确认块218验证包是属于已知(例如现存)的流还是需要新的流。如果包不属于任何已知的流,则在流表212中添加新的-,,并将包元数据(例如头数据)传递给规则匹配模块220。该块将对一组匹配结构进行循环,评估每个匹配的情况。当目标动作匹配时,将这些目标动作编码到包元数据中。因此,包可以具有与其相关的多于一个的目标动作。例如,可能需要对包进行日志记录并将其转发。一旦包根据规则匹配,则将其传递给目标处理程序块210以进行进一步的处理。该块执行与包元数据相关的动作。如果到来的包属于已知的流,则其再次不匹配于访问规则。取而代之的是,将其直接传递给目标处理程序块210,该块对可应用动作执行任何必要的处理。需要对流的包执行的动作被存储在流专用的对应的流表中,或者由流专用的对应的流表指向。参见图3的流程图,在每一输入包的处理期间执行下述操作。该处理开始于块300,其中执行流分类。一般来说,可以使用为此目的而通常采用的多种方案之一来执行流分类。典型地,可以基于ACL规则数据库来对流进行分类;但是,也可以采用其他的分类机制。流分类的目的是将包分配给对应的流。传统上,对消息(例如包)进行分类的规则被称为过滤器(或在防火墙术语中被称为规则),包或流分类的问题是为在网络元件上的每一到来消息确定最低成本匹配过滤器或规则。相关信息被包含在每一消息(包)的《个不同的字段中。例如,IPv4包的相关字段可以包括目的地址(32位)、源地址(32位)、协议字段(8位)、目的端口(16位)、源端口(16位)和可选的TCP标志(8位)。由于标志(flag)的数量是有限的,因此在某些实现中可以将协议和标志组合存储到一个字段中。图4a示出了描述5元组流分类方案所使用的示例性包结构。一般来说,可以将该方案扩展以用于任何《-元组分类。每个包在其头中包括各种字段,其数量和特定字段取决于其传输机制(例如TCP/IP包与UDP包的字段不同)。包的有效负载数据(其通常也被称为包数据或有效负载)在包的头数据之后。可选的包脚注(footer)可以被包括在包的末尾。在图4a所示的实施例中,选择了五个字段(如图所示的FLD1-5)用于对其执行分类。每一包字段包含对应的字段值(Vl-VN)。FLDl-5表示头信息,例如源和目的地址、源和目的端口、协议信息以及错误校验信息等。有效负载字段400定义了包含有效负载数据的包部分。如图FLDN所示,在某些情况下,脚注中的信息也被用于进行流分类。在大多数分类方案下,仅头信息被用于执行分类。但是,取决于特定的ACL规则,可能需要包括在包有效负载和/或脚注中包含的附加信息。为了简洁起见,下面仅基于头信息来论述包的分类。当接收到包时,对其进行分析,以基于分类方案从其头中提取出所选择的字段值。对于所示的示例而言,可以是来自FLD1-5的值Vl-V5。所提取的字段值随后被用于搜索规则数据库以确定包匹配的一组分类规则以及相关组的结果流。如图4b所示,过滤器(ACL)数据库由有限组的过滤器_/^,,/^2...力/~组成,每一过滤器相关于对应的分类规则和流。每一过滤器是)fc个值的组合,每一个值针对可应用于分类方案的每一字段(或部分字段)。允许过滤器中的每个字段具有三种类型的匹配精确匹配、前缀匹配或范围匹配。在精确匹配中,包的头字段应精确匹配过滤器字段。在前缀匹配中,过滤器字段应是头字段的前缀。在范围匹配中,头值应在过滤器所指定的范围中。每一过滤器_///,具有相关的指示(即动作),其指定如何处理匹配过滤器的包。一般来说,可以使用多种已知技术之一来执行分类规则匹配。例如,在一个实施例中,采用聚集的位向量方案,其中每一字段值相关于标识ACL表中匹配规则的对应的位向量。(在实践中,使用聚集或分级的方案来存储位向量以减少每一位向量的存储大小,这是因为许多(如果不是大多数)位值是0的话,则表示不匹配。)随后将位向量进行逻辑与(AND),其结果标识匹配规则。随后可以容易地识别最高优先级的匹配规则。也可以采用其他方案,例如但不限于递归流分类(RFC)(PankajGuptaandNickMcKeown,尸"cA:efC7咖折ca"owMw/印/eF/eWs,ACMSIGCOMM1999)。返回到图3,一旦包被分类给了流,则在决定块302中确定在流表212中是否存在对应的流数据结构(即流表项)。如果流表项已经存在,则逻辑继续到块304,在块304中,获得流结构和对应的状态信息。如果流表项不存在,则在流表中分配新的流结构,其状态被初始化,如块306中所示。下面进一步详细论述流数据结构和状态信息。在一个实施例中,流表项被保持在使用双散列方案的散列表中。如图5所示,散列表被组织为两个表,主表被保持在SRAM(同步随机存取存储器)中,而次表被保持在DRAM(动态随机存取存储器)中。将主表划分成一组间隙,而每一间隙项对应于次表中的流项。主表由两个指数索引第一值标识间隙词(间隙是8位值-7位签名和1个标志位),而第二值(签名)被存储到间隙中并用于标识间隙。次表中的流项由间隙词指数和具有匹配的签名值的间隙号索引。将流表维持为两组散列表;如果在第一个表中的流项搜索失败的话,则在第二个表中执行该项的搜索。可能需要或不需要内容检测,这取决于相关的流。例如,规则数据库可以将从"可信"源地址发送的包或发送到特定目的端口的包视为是可信赖的,并将所述包分配给具有"转发"的相关策略(即动作)的对应的可信流。相反,可以将从非可信的源地址发送的包分配给具有"丢弃"的相关策略的非可信的流。在其他情况中,流可以具有"检测内容"的相关策略,其需要待执行的内容检测。如决定块308所示,如果需要内容检测,则使用块312中获得的状态信息来初始内容检测操作。针对无需进行内容检测的包,继续执行包处理,如继续块310所示。总体而言,搜索机制的实施涉及两个阶段构造或预处理阶段,和运行阶段。在构造阶段中,构造并保存了各种数据结构和表,以在后面的相关的初始操作期间将其保存到存储器中。在通常处于进行中的运行阶段,使用数据结构和表对接收到的包执行搜索。图6具体示出了构造阶段的一个实施例。处理开始于块600,其中定义了搜索标准。可以非常普通的方式将其陈述为在另一个字符串(在本例中为包数据)中搜索样本(字符串)的出现的问题。此问题相同于经典的字符串匹配问题,其正式定义如下给定由"n"个字符构成的文本字符串T以及由"m"个字符构成的样本字符串P,在T中寻找出现P的所有位置。在使用防火墙的环境中,可以将上述问题映射到在包数据中寻找病毒或蠕虫签名、协议命令或已知可执行程序的名称的出现的问题。通常仅在T中搜索P的出现就是足够的了,而无需寻找所有的出现(其并没有真正简化问题,因为在理论上,找到第一次出现通常和找到多次出现一样困难)。在大多数实际的防火墙和IDS应用中,所搜索的签名字符串可能事先并不是已知的;在特定流的上下文中,最佳方式就是将字段縮窄到需要被搜索的一组样本。因此,更普遍的问题是在给定文本T内搜索一组样本(P)中任何一个样本或所有样本的出现。有吋,待匹配的一个或多个精确字符串在事先并不是已知的。签名还可以变体的形式出现,其中变体通常是对原始样本迸行了较小的修改。在这种情况下,就还需要处理字符串的近似匹配。有时,还需要匹配正则表达式而不是已知的字符串。当前在数据挖掘和搜索应用中采用了所有这些技术。一般来说,这些算法在一定程度上比简单的字符串搜索算法要复杂,也具有更高的存储器和周期要求。在上述策略(条件)上下文中,不同的样本集(P)可以应用于不同的策略。例如,仅针对特定的样本组才需要搜索某些流,而其他流可以包括搜索更广阔的或完全不同的样本集。因此,针对每一策略指定适当的样本集。一般来说,且取决于采用的搜索算法,样本集可以包括精确匹配和/或近似匹配(例如使用通配符进行匹配)。接下来,在块602中,基于所采用的选择的搜索算法,构造数据结构和相关的表(将其统称为样本数据结构DS)。下面将进一步对这一方面进行详细地描述。如决定块604所示,偏移和/或深度信息也可以相关于搜索标准。经常的情况是,对特定样本了解更多的信息,而不止是组成所述特定样本的字节字符串。这种信息有助于縮窄包(或相关的位流)中可能会出现样本的范围。本文中所用的这种信息包括偏移和深度。偏移值表示在开始搜索之前从包(或位流)的开头可以跳过的字节的数量。而深度值表示包(或位流)中存在找到样本可能的需要搜索的最大字节数。偏移和深度值也被称为"标记"值。虽然在单一样本的情况下这种信息相当有用,但在将其扩展到每一样本可能均具有不同的偏移和深度的多样本的情况下却存在一些困难。使用这种信息的最想当然的方法是,一旦我们在可应用状态机中到达了接受状态,就简单地检查这些标记值,但这样可能既是低效又是错误的;如果当我们到达接受状态时偏移或深度不匹配,我们可能会因为选择(状态机中)不同的路径而错过其他(有效的)样本。因此,我们需要将偏移和深度检查集成到算法的每一步骤中,从而实现正确的状态转换。对此进行实现的一种方式是,如块606所述,在可应用样本数据结构中集成(例如添加)适当的标记值信息,下面将对其进行进一步地详细描述。在样本数据结构被完全构造后,在块608中,将所述样本结构保存到文件等中。在后续的初始化操作期间,如块610所示,样本数据结构将被加载到存储器和/或代码存储中,并且如块612所示,对应的样本数据査询数据将被加载到存储器中。为了说明如何以及在哪里存储数据,将对图7所示的执行环境进行描述。执行环境关联于网络线卡700,所述线卡700包括经由SRAM接口(I/F)705与SRAM存储(SRAM)704耦合的NPU702,所述NPU702还经由DRAM接口707与DRAM存储(DRAM)706耦合。还为NPU702示出了所选择的模块,包括深度包检测模块202、流管理器模块204、队列管理器708、接收引擎710以及缓冲管理器712。在如上所示的方式中,通过在ME714中执行对应的指令线程来促进与这些模块中每一个相关的操作。在一个实施例中,指令线程初始存储在指令存储715中,所述指令存储715包括诸如闪速存储器或大容量存储设备之类的非易失性存储设备。如图7所示,将各种数据结构和表存储在SRAM704中。这包括流表212、策略数据结构表716和样本数据结构表718。同样,包元数据720也通常存储在SRAM中。如上面参考图5所述,流表的相应部分可以在SRAM704和DRAM706之间分开。为简单起见,在图7的SRAM704中示出了所有的流表212数据。通常将用于包处理的频繁访问的信息(例如元数据720)存储在SRAM中,而大量的包数据(所有的包或包的有效负载)被存储在DRAM中,后者的访问延迟较大但也相当有效地降低了成本。因此,在典型的实施中,DRAM存储中所提供的存储空间远远大于SRAM存储所提供的存储空间。如图7中左下角所示,每一ME714包括本地存储器722、本地寄存器724、分开的SRAM和DRAM读取和写入缓冲器726(为方便起见,将其示为单一的块)、代码存储728和计算内核(例如算术逻辑单元(ALU))730。一般来说,可以经由相应的SRAM和DRAM写入和读取缓冲器,向ME或从ME传递信息。此外,在一个实施例中,提供下一个相邻的缓冲器(未示出),使数据在以链或簇配置的ME之间有效传递。如下所述,每一样本数据结构将提供用于实现对应的状态机或基于表的机器的信息。如图7所示,各种样本数据结构将通常被存储在样本数据结构表718中。但是,在某些情况下,所选择的样本数据结构被存储在用于存储指令代码和数据的所选择的代码存储中。如上面对图6所描述的,除了存储样本数据结构之外,相关的样本数据结构査找数据也同样被存储在块612中。在图7所示的实施例中,查找数据作为与策略数据结构表716中对应的策略相关的指针而被存储。也可以采用其他的方案。以如下所述方式,部分地使用样本数据结构查找数据来构造流表项。在图8a和8b所示的运行内容检测阶段期间,执行总体的操作,其中,图8a示出了在流中的第一个包的处理期间所执行的操作,而图8b示出了在流中任何后续包(由第i个包表示)的处理期间所执行的操作。如图8a和8b中的块800所示,响应于接收输入包,经由在一个或多个ME714上执行一个或多个线程来执行初始的包处理操作。为了将这些线程与用于内容检测的其他线程区分开,在图8a和8b中这些线程被标记为预搜索线程。参见图7并进行进一步地详细描述,当在线卡700处接收到输入包732时,由接收引擎710处理这些输入包732,所述接收引擎710暂时将输入包732存储在与正在进行的上下文管线包处理操作相关的接收(Rx)缓冲器734中。这些包头被提取,对应的包元数据720被存储在SRAM704中。还可以上面论述的方式来对包进行分类,并将包分配给存在的或新的流。如流队列736所示,每个流均具有存储在DRAM706中的相关的队列。队列通常由队列管理器708和/或流管理器204进行管理。在创建流队列时,将相关的信息添加到元数据720中,从而队列中的第一个(头)和最后一个(尾)包可以轻易地被识别出来以进行后续的操作,例如出队。基于流策略和其他标准以及较少的可预测网络操作,可以异步方式从各个网络节点接收包的流。因此,如图7所示,可能以混合的方式连续地从不同的流接收基础包。例如,每一个输入包732被标记为F#-#,其中Ftf标识流,-#标识给定流的连续的包。可以理解的是,包不包含特别识别所述包被分配给的流的信息,而这种信息在流分类期间被确定。但是,在诸如TCP头之类的可应用包头中提供包序列数据(例如TCP包序列弁)。在图7中,流队列736在流#1(Flow#l)中包含第一组五个包。和之前的情况一样,在块800中执行入队操作期间,在对包进行分类之后,将所述包加入相关的流队列中。在块800的操作之后,将执行与图3所示相类似的操作,从而需要进行内容搜索。如上所述,如果将包分配给新的流,则在块306中将创建对应的流表项。在图7所示的实施例中,每一流表项包括流ID、缓冲器指针、策略指针、样本数据结构指针、状态信息和统计信息。(流表项还可以包括未示出的其他信息。)流ID用于流表项査找,根据图5所示的流表索引方案,在一个实施例中,包括散列索引。在一个实施例中,缓冲器指针指向可应用元数据720,其继而包括指向与流表项相关的流队列中的头包和尾包。策略指针指向策略数据结构表716中的策略数据结构。如上所述,每一个流相关于策略。在流分类中,策略被识别,且将对应的策略指针提供给流管理器204。如上所述,需要内容检测的每一策略还相关于样本数据结构。因此,在一个实施例中,还可以从策略数据结构中提取样本数据结构指针。状态信息还用于存储由深度包检测模块202使用的对应的算法状态的状态,下面将对状态信息进行详细描述。统计信息用于各种目的,包括识别流中己经完成内容检测的最后一个包的当前序列号。在这种方式中,可以基于下一个待检测的包与相关流队列中头包的相对位置,来识别给定流的下一个待检测的包。如图8a的块802A所示,如果包是流中的第一个包,则将在ME714上发射第一个线程以执行包的样本搜索,来识别考虑了可应用样本集(P)的任何匹配。因此,由线程来读取与该包的新流表项相对应的数据,包括状态信息,所述状态信息表示状态机处于初始状态。在块804中,使用缓冲器指针和元数据来识别相关流队列中包的位置,并将包拷贝到ME的本地存储器722中。在块806B中,从样本数据结构表718获取(由样本数据结构指针标识的)可应用样本数据结构,并将其拷贝到本地存储器722。将对应的搜索算法的存在状态738初始化到初始状态,所述初始状态表示当前不存在部分匹配。样本搜索操作开始于包的起始处(例如包有效负载数据的起始处),并以重复的方式执行,直到到达包的末尾位置为止。如开始和结束循环的块808和816所示,可应用算法机采用的搜索增量可以包括取决于特定搜索算法的一个或多个字符。响应于每一增量,更新机器的存在状态738。在块812中,确定机器是否识别完全匹配。如果是的话,则执行搜索条件的相关动作,如继续块814所示,并且线程终结。通常,可由同一或另一个ME上的同一或另一(较相似)的线程来执行相关动作。可选地,可由NPU的通用目的处理器(为清晰起见未在图中示出)来执行相关动作。在匹配字符串识别出了恶意的蠕虫等存在的情况下,通常的相关动作为丢弃流中所有的剩余包,并在可能的情况下更新对于源地址的ACL数据库动作。可以通过更新相关流表中的策略指针,使流的策略从"检测内容"有效地切换到"丢弃",以实现剩余包的丢弃。一旦样本搜索算法到达了包的末尾(未发现匹配),则在块818中更新相关流表中的状态和统计信息。至此,第一线程的执行就终结了。转向图8b,当接收到被分类给同一流的后续包时,执行类似地操作,如图8a和8b中的相似编号的块所示。在块802B中,第i个线程在同一或另一个ME714上启动,其中/表示包序列号(其根据头中的实际序列号而被标准化)。在处理第一个包之后,读取的流表项将成为存在项,所述存在项包括由之前的包更新的存在状态。和前面一样,将包括统计信息的流表项信息用于在流队列中为包定位,从而在块804中将其拷贝到ME本地存储器722。在块806B,可应用样本数据结构由ME以类似于图8a的块806A的方式而获取。但是,作为处理前一个包(例如第一个包)的结果,机器的状态将被初始化到前一个包所更新的存在状态。如果在前一个包的末尾处出现了部分匹配,则机器中的存在状态将不是初始状态(例如0)。如果未出现部分匹配,则存在状态将为初始状态。以与应用于第一个包相类似的方式来执行块808、810、812、814和816的样本搜索操作,唯一的差别在于机器的初始状态。因此,如果在前一个包的末尾存在部分匹配,则样本搜索开始于状态机离开的点,在样本集(P)中寻找第二部分(剩余匹配部分)的一个或多个字符串(取决于存在状态)。和上面的情况一样,如果识别出了完全匹配,则在继续块814中执行相关的动作。如上所述,搜索标准将为相应的样本字符串指定偏移和深度值。在本例中,将样本搜索处理增大,以考虑该附加的搜索信息。如图9所示,我们开始于包的起始处,图8a或8b的(可应用的)先前操作已经完成。在块900中,跳跃(skip)了包的一部分以到达偏移,在该偏移点上开始搜索。在下面进一步的详细描述中,该操作可以基于单独的样本搜索来实现,从而在与采用多样本搜索时的不同点偏移某些样本。如果包是流中的第一个包,则将从包的开始处跳跃与偏移相对应的字节数。在理论上,可能会出现一个或多个搜索样本的偏移大于第一个包的整体长度的情况。因此,在这种情况下,针对这些搜索样本跨越整个的包,第一个包的长度将从偏移值扣除,从而后一个包的待跳跃的偏移部分将考虑已经跳跃了多少位流。例如,在给定协议下考虑特定搜索样本的偏移大于包有效负载的最大尺寸的情况。针对该特定的搜索样本,整个的第一个包将被跳过,搜索将开始于第二个包中的偏移,所述偏移等于原始的偏移与第一个包的大小之差。在一个实施例中,述的,通过在相关的流表项中更新适当的统计信息,来促进该多包偏移方案。如开始和结束循环块902和914所示,样本搜索涉及包有效负载数据上的重复,其位于搜索算法采用的可应用搜索增量增加的数据中。样本集(P)中每一搜索样本的开始点是该搜索样本的有效偏移。响应于移动每一搜索增量,在块904中更新机器状态。如决定块906所示,如果搜索字符串匹配由机器指示,则在继续块908中执行相关的动作。如果不存在匹配,则逻辑继续到决定块910以确定是否到达了可应用搜索字符串的深度。如果是的话,则完成了对该字符串的搜索,如结束块912所示。如果不是的话,则处理返回到开始循环902以开始下一次重复。当到达包的末尾时,取决于实施,会出现两个动作,如决定块916所示。对仅在流中搜索第一个包的实施例来说,流的搜索处理就完成了,且没有发现匹配。因此,流表项中的策略指针在块918中更新以指向不执行内容搜索的策略,从而不对流中的剩余包执行搜索。如果支持多包搜索(相关于偏移方面),在流表项中更新统计信息以考虑为下一个包采用的偏移中的跳跃的包的大小,如块920所示。在一个实施例中,可以调整为给定搜索样本采用的有效深度以支持多包搜索。例如,考虑偏移小于第一个包的大小、而深度大于第一个包的大小的情况。可以通过将第二个包的深度值减少第一个包的大小来处置这种情况。该操作还可以在块920中执行。还应注意的是,在这种情况下,还可以上述的相同方式来更新流表项中的状态信息,以反映在第一个包的末尾处的状态机的状态。在一个实施例中,可以经由在可应用样本数据结构中包含的数据来提供实现偏移和深度操作的机制。因此,图9中包括的块922示出了调整样本数据结构以在多包实施中考虑偏移和/或深度。可以由使用在块920中更新的统计信息的另一个线程(启动以处理流中的下一个包)来执行该操作。多样本搜索算法搜索多样本出现的最简单的方式是通过每一样本的多个公知单样本算法中的任何算法的重复应用来实现。从20世纪70年代末期以来,人们已提出了多个多样本算法。在传统上FSM(有限状态机)算法是研究的重点,但也存在不使用FSM的其他高效算法,例如Wu和Manber所提出的算法。FSM算法基于下面的考虑。给定有限字母表和样本,可以高效的方式构造有限状态自动机,所述自动机处理文本字符串以返回出现的样本。机器中的每一状态(由一个数字表示)对应于到目前为止匹配的样本的最长前缀。这具有需要仅一次地扫描文本中的每个字符的属性。该预处理主要涉及计算机器转换函数。算法的运行涉及将搜索文本馈送给FSM作为输入。一旦到达接受状态时就检测到了P的出现。通常,针对本文所述实施例所采用的样本索索,可以实现任何类型的FSM算法。为了更好地理解FSM算法是如何工作的,下面将简要论述公知的Aho-Corasick(AC)算法(A.V.Aho,M.Corasick,"Efficientstringmatching:anaidtobibliographicsearch",CommunicationsoftheACM,vol.18(1975)333-340)。下面的描述摘抄自上述文献中。设《=",;;2...,^是被称作关键字的有限组字符串,并设x是被称为文本字符串的任意字符串。我们的问题是定位并识别:c的所有子字符串,所述子字符串是/C中的关键字。子字符串可能相互交叠。《的样本匹配机是一个程序,其将文本字符串;c作为输入,并产生在;c中《的关键字作为子字符串而出现的位置作为输出。样本匹配机包括一组状态。每一状态由一个数字表示。通过连续地读取x中的符号、进行状态转换并间或进行输出,机器处理文本字符串x。样本匹配机的行为由三个函数确定,所述三个函数为goto函数g、failure函数/和输出函数w^W。图10示出了样本匹配机针对关键字集(he,she,his,hers)所使用的函数,其中状态是0,1....,9。goto函数g将由状态和输入符号组成的对映射到状态或消息失败(fail)。有向图表示对于非e或i的所有的输入符号",g(l,力^失败。对于所有的输入符号",所有的样本匹配机具有g(0,W-失败的属性。状态O上goto函数的该属性确保了一个输入符号将由每个机器周期中的机器处理。失败函数/将状态映射到状态。一旦goto函数报告失败,则参考失败函数。指定特定的状态作为输出状态,以表示找到了一组关键字。输出函数通过将一组关键字(可能为空)与每一状态相关联来形式化这一概念。下面定义样本匹配机的操作周期。设s是机器的当前状态,《是输入字符串x的当前符号。1.如果g(s,a)-,则机器进行goto转移。其进入状态s',下一个符号;c变成当前的输入符号。此外,如果输出(s')-空,则机器发出一组输出(s')(output(s,))以及当前输入符号的位置。操作周期结束。2.如果^&。)=失败,则机器参考失败函数/并因此进行失败转移。如果/(力W,则机器以W作为当前的状态、"乍为当前的输入符号来重复此周期。初始地,机器的当前状态是开始状态,文本字符串的第一个符号是当前的输入符号。机器随后通过对文本字符串的每一符号进行一个操作周期来处理文本字符串。DAWG匹配实现在一个实施例中,采用了被称为DAWG匹配算法的基于FSM的算法(M.Crochemore,A.Czumaj,L.Gasieniec,T.Lecroq,W.Plandowski,andW.Rytter,"Fastpracticalmulti-patternmatching",Inf.Process.Lett"71((3画4)):107-113,1999)。该算法将Aho-Corasick与Boyer-Moore的思想相组合以获得更好的平均运行时间。这需要AC状态机和DAWG(有向非循环字图)针对给定样本集的逆样本的计算。当计算AC状态转换函数时,还计算转移(shift)表,其存储特定状态,所述特定状态确保在跳跃区域中不出现样本(状态对应于与当前已扫描的文本后缀相匹配的样本的最长前缀);该函数对应于Apotolico-Giancarlo的跳跃函数。在算法的步骤了中,DAWG用于首先从右侧到左侧进行扫描直到不匹配为止,在这种情况下,将AC机用于从左侧到右侧进行扫描以识别前缀,并决定转移值。如果该组字符使用DAWG交叠与前缀匹配,所述前缀由上一阶段中的AC匹配,则报告一个匹配。下面给出的是DAWG匹配算法的样本数据结构的一个实施例,其对应的存储器数据结构由图11示出。structPattern{char*string;/*Pointertostringofbytes*/intlength;/*NumberofbytesinstringV/*stringMUSTNOToccurwithinfirstoffsetbytesofintoffset;text*/intdepth;cmrfcass/*stringMUSToccurwithinfirstdepthbytesoftext*//*Flag(0=caseindependent;l=casedependent)*/structPattern*prev;/*Pointertopreviouspattern(forconditionalsearch;searchforstringonlyifprevhasbeenfound*/structPattern*next;/*Pointertonextpattern(nextmustfollowstringinthetextforconditiontobesatisfied(ormodificationofaRegEx)*/intprev_pat—num;/*Patternnumberofprevinapre-orderedlist*/intnext_pat—num;/*Patternnumberofnextinapre-orderedlist*/intdistance;/*Samemeaningasoffset;startpositionoftextisfirstbyteafterendofprev(iffound)*/intwithin;/*Samemeaningasdepth;startpositionoftextisfirstbyteafterendofprev(iffound)*/intexact;/*Exactstartpositionofstringintext*/intrelative;/*Samemeaningasexact;startpositionoftextisfirstbyteafterendofprev(iffound)*/};如果未定义,Prev和Next的值将为空(NULL)。除非另有明确的定义,Offset和distance的默认值是0。除非另有明确的定义,depth、within、exact、和relative的默认值是-1。对于预处理,使用了指针值prev和next。对于微代码形式的算法实现,采用prev_pat_num和neXt_pat—num作为样本索引值的情况更普遍(可以根据这些值计算实际的样本地址作为恒定大小的样本结构)。在图11的存储器映射数据结构中,将地址对齐到字(4字节)边界。实际的样本字符串是字节序列,所述字节序列开始于在数据结构的第一字段中指示的字节地址处。在实践中,样本字符串紧接地连续存储在最后的样本数据结构结尾之后。这实现了预处理期间的存储器的预分配以及相关地址的计算、并仅需要保持一个指针(第一样本结构的地址)。AC机采用了确定性的有限状态automaton(自动机)(g,A/,vr),其中^是状态集,^是转换函数,/是失败函数,是开始状态,r是接受状态集。转换函数确定基于给定输入从特定状态移动哪个状态。失败函数为(状态,输入)对指示异常转换,所述(状态,输入)对没有被转换函数定义。AC机被构造为节点的特里结构(trie),并通过指向开始状态的指针而被指定。在一个实施例中,采用下面的数据结构,而图12中示出了对应的存储器数据结构。structtransition{charinput;/*Bytevaluethattriggersstatetransition*/structAC一node*destination;/*PointertodestinationAC-machinestate(node)*/};structAC—node{intnode—id;/*Uniqueintegerasstateid*/intshift;/*Maximumsafeshiftvalue(forDAWG-Match):shiftistheminimaldistancethatcanbeskippedwithaguaranteethatnopatterncanoccurintheskippedarea*/intoffset;/*Prefixindicatedbythisstatemustendonorafterfirstoffsetbytesoftext*/intdepth;/*Prefixindicatedbythisstatemustendwithindepthbytesoftext*/structAC—node*fail;/*Pointertofaistate*/intnum一transitions;/*Numberoftransitionsfromthisstate*/structtransition*next;/*Listoftransitionsfromthisstate,orderedbyASCIIvalueofinputbyte*/charfaccepting;/*Flag(1=accepting;0=notaccepting)*/intnum一outputs;/*Numberofpatternsrecognized,ifstateisacceptingstructPattern"output;/*Pattern(s)recognized,ifstateisacceptingVint*pattern—numbers;/*Listofpatternsrecognized,asindexvaluesinapre-orderedlistofpatterns*/};除非另有明确定义或计算,offset、faccepting、num—transitions和num_0UtpUts的默认值是0。除非另有明确的定义或计算,深度的默认值是-1。仅在预处理(机器的计算)期间,指针被用于destination、fail和output。微代码实现使用状态的pattern—numbers和node—id(据此计算实际的存储器地址)。在一个实施例中,采用AC机索引结构,如图13所示。尽管索引和每一AC机节点在存储器中可以独立重定位,但以连续的方式使用状态ID排序来存储状态信息是有利的,以及在索引之后紧接着存储结构信息也是有利的。这使得可以在预处理期间计算不同的(相关)地址,并将需保持的指针数量减少到了一(索引结构的基地址),并实现了存储器的预分配。有向非循环字图或后缀自动机识别了给定集中的所有样本后缀(DAWG匹配算法将逆样本作为输入)。DAWG不具有失败函数,状态不需要具有与其相关的输出样本。下面给出DAWG数据结构的一个实施例,在图14中示出对应的存储器数据结构structsuf—transition{charinput;/*Bytevaluethattriggersstatetransition*/charflag;/*Flag(0=primaryedge;l=secondaryedge)*/structDAWG—node*destination;/*PointertodestinationDAWGstate(node)*/};structDAWGnode{intnode—id;/*Uniqueintegerasstateid*/intnum一transitions;/*Numberoftransitionsfromthisstate*/structsuf_transition*next;/*Listoftransitionsfromthisstate,orderedbyASCIIvalueofinputbyte*/structDAWG一node*suffix_pointer;/*PointertoparentinavirtualtreethatisusedforcomputationoftheDAWG*/};除非另有明确定义或计算,flag和num一transitions的默认值是0。flag仅用于构造DAWG,而在实际的字符串匹配中不发挥作用。仅在预处理(机器的计算)期间对destination使用指针。微代码实现对状态使用node—id(据此计算实际的存储器地址)。DAWG机索引结构相同于AC机索引结构。将DAWG索引和结构以和上述AC机相类似的方式进行连续存储。诸如DAWG之类的后缀树识别给定集中的所有样本后缀(AC后缀树(AC-SuffDc-Tree)算法采用逆样本作为输入)。该结构在实质上是分解成树的DAWG,因此具有从源到任何其他状态的唯一路径。下面具体给出后缀树数据结构的一个实施例,图15示出对应的存储器数据结构structtree—transition{charinput;/*Bytevaluethattriggersstatetransition*/structsuffix—node*destination;/*Pointertodestinationsuffixtreestate(node)*/structsuffix_node{intnode—id;/*Uniqueintegerasstateid*/intnum一transitions;/*Numberoftransitionsfromthisstate*/structtree—transition*next;/*Listoftransitionsfromthisstate,orderedbyASCIIvalueofinputbyte*/structAC—node*ACnode;/*AC-machinestatewherescanwillend,startingfromthesourceandthereverseofthepatternrecognizedbythissuffixtreestateasinput*/};除非另有明确定义或计算,num—transitions的默认值是0。ACnode用于区分DAWG和后缀树。在后者中,每一状态是从开始状态通过字节(样本的子字符串)的唯一路径到达的。因此,每一状态具有表示该遍历字符串的唯一的AC机节点。例如,设后缀树中的状态s从开始状态通过字符串c,cA....c"是可到达的。将此字符串作为AC机的输入。如果AC机扫描停止在状态d,则将s-"O7^的值设置为d。仅在预处理(机器的计算)期间对destination和ACnode使用指针。微代码实现对状态使用node—id(据此计算实际的存储器地址)。后缀数机所采用的索引结构相同于AC机索引结构,将后缀树索引和结构以和上述AC机相类似的方式进行连续存储。在用于构建样本数据结构的预处理操作期间,扫描样本列表以査找大小写无关(case-independent)样本。为了保持状态机的确定性并能够识别这种样本,不论在它们出现在(包有效负载的)什么样的情况组合中,特定样本可能出现的字节字符串的所有组合都在一个实施例中生成。所有这些新的组合被添加到样本列表,而prev指针用于指向原始样本,从而没有浪费存储器空间,以存储新样本的这些指数。在实践中,可以采用人工或编程选择操作来生成和/或移除大小写无关样本。例如,尽管可以使用所有小写、大写和仅首字母大写的形式来存储基本相同字符的组合,但通常来说,生成包括随机大写的字符串形式的益处是少得多的。上面的实现为Aho和Comsick提出的基本AC机构造算法提供了几点补充,参考以上所述,包括转移计算这对于由Crochemore等人提出的DAWG匹配算法是必要的;偏移和深度计算如果样本具有相关的偏移的深度,且其不等于默认的包的默认的开头和末尾,则我们需要计算每一状态的值。如果我们不计算每一状态的这些值,则我们可能会进行不必要的状态转换;仅当发现接受状态时,我们才知道输出样本是否正确,在处理中,我们可能会错过一些正确的样本;以及集成大小写无关样本通过为大小写无关样本计算字符串的所有可能的组合,我们确保总能识别大小写无关样本。在一个实施例中,标记在任何接受状态作为原始样本的输出,而不是必须存储样本的非必要组合。参考图6、7、8a、8b和9的实施例以及以上描述,经由在选择的ME上执行微代码线程来实现DAWG和后缀树算法。除了以上描述外,将这些操作总结如下。首先,尝试将样本集(P)中的任何样本的可能最长前缀匹配到T的后缀。对于上述的DAWG和后缀树算法,前缀值可以由在集(P)中识别样本的AC机的对等状态来表示。对于流中的第一个包,前一个样本中匹配的样本前缀是空字符串,因此prev—state输入将是AC机的开始状态。如果,对于任何包,该值并不等于开始状态,则使用AC机从其第一个字符开始以正向方向扫描T,从prev—state幵始,直到获得适当的转移值为止,DAWG可以幵始其扫描。朝着包扫描末尾的方向,在循环重复中,由DAWG扫描的包内容的子字符串将跨越包的末尾(即位置(pos)>=包的大小)。当出现此情况时,我们需要打破循环并在最后一次循环重复中AC机的位置(即在包中的同一状态和同一字符位置)继续对包进行扫描。AC机的扫描继续,直到到达包的末尾为止,在该点上,将该AC机状态作为prev—state记录在相关的流表项中,使用该相关的流表项来初始序列中下一个包的处理的状态。该用于跨越多个包检测样本的机制仅在流的包到达序列时才有效。仅在当前的包的序列号比流中的前一个到达的包的序列号大一时,prev—state值才有意义。如果包没有按顺序到达(这应用于TCP和其他面向连接的协议),无法通过在流项中存储一个prev一state值来执行这种样本检测。在一些情况下,可以通过存储这种状态值的多个实例以及相关的包序列号来解决这个问题。但是,在到达的包的在序列上的前一个包没有被扫描的情况下,这个解决方案也是无效的(这是因为,我们的机器数据结构的特性使得其难于在包的开头处检测样本后缀;相比之下,在包的末尾处检测样本前缀要容易的多)。另一种方法是使用缓冲和存储状态值的组合。在该实现中,如果包不是按照顺序到达的,则可以对其进行缓冲存储,直到其在顺序上之前的包到达并被扫描为止。如上所述,可以提供偏移和深度标记值来减少需要被搜索的一个包或多个包的部分。其思想是,在AC机扫描的每一步骤期间,我们需要检査待扫描的字符串位置的偏移和深度值,并确定我们当前是否处于正确的路径上。如果与当前状态相关的值不匹配当前的文本位置,将进行失败转换。AC机状态表示我们正在搜索的一个或多个样本的前缀。因此,为了确保我们不会错过任何样本,我们需要为该状态设置最保守的偏移和深度值。如Crochemore等人的著作及上面的预处理算法所述,我们对此所使用的规则相同于计算转移值所使用的规则。当处理完一个样本后,基于相应的从开始状态的距离和到样本末尾的距离,计算该状态的偏移和深度。当在下一个样本的处理期间到达该状态时,计算偏移作为当前计算值和之前设定值中的最小值;计算深度作为当前计算值和之前设定值中的最大值(非特定的深度是无限,其值大于所有的特定值)。在失败(fail)状态计算期间无需改变偏移和深度。如果我们在包扫描期间遇到具有不正确的偏移或深度的状态,将自动跳转到失败状态。上述方案对于搜索单个包的情况有效。如上所述,在一个实施例中还提供了处置将偏移和/或深度应用于多个包的情况的方法。为了实现此方案,需要在将应用样本数据结构拷贝到本地存储器时修改应用样本数据结构,以调整偏移和/或深度值。同时,需要将对应的数据存储在相关的流表项中(例如统计信息中)以反应1)需要调整的样本数据结构;以及2)需要进行怎样的调整。在大多数情况下,无需对多个包进行偏移和深度搜索。在应用样本集包括大量的搜索字符串的情况下,在统计信息中为每个样本保持偏移和/或深度状态信息通常也是不实际的。同时,通常采用偏移和深度搜索来查找特定的签名(或仅一些签名)。因此,与这(这些)签名相对应的信息可以被保持在流表项中而无需消耗过多的存储器资源。是否支持对多个包进行偏移和深度搜索取决于特定的实现。Wu-Manber算法实现在一些实施例中,采用基于Wu-Manber算法([WM92]S.Wu,U.Manber,"FastTextSearchingAllowingErrors",CommunicationsoftheACM35(10):83-91(1992);and[WM94]S.WuandU.Manber."Afastalgorithmformulti-patternsearching".TechnicalReportTR-94-17,UniversityofArizona,1994)的搜索方案。Wu和Manber的方法非常不同于上述基于状态机的算法。这些算法还由于有时匹配字符块而不是单个字符而不同于其他方法。如果所有样本的总长度是M,则块(block)(B)的建议大小是/。^2M。该算法预计算三个查找表SHIFT、HASH和PREFIX。SHIFT表由整数索引,该整数是字符快的散列映射;该表等同Boyer-Moore算法(BoyerandJ.Moore."Afaststringsearchingalgorithm".CommunicationsoftheACM,20:762-772,1977.)中公知的坏字符(badcharacter)表。对多个样本常见的子字符串的项包含更保守的可能的最小转移值。对于较大的值B,可以通过将几个字符串映射到同一位置、在每一情况中设置最小的转移值来压縮表。用于索引SHIFT的整数还用于索引HASH,其存储指向映射该整数的字符串的指针。PREFIX表包含每一样本前缀的散列值,前缀大小是独立实现的。在每一算法步骤中,由B个字符组成的集(在被扫描的文本字符串的右端处)被混编成整数,该整数用于査找SHIFT值。如果该值大于0,文本被转移。否则,计算(^大小的,其中m,是最短样本的长度)该子字符串的前缀的散列,比(使用PREFIX表)将其匹配到对应HASH项中每一字符串的前缀。如果前缀匹配,则实际的文本匹配发生。该算法取决于最一致的样本大小,这是因为在匹配期间仅考虑最短的样本长度。该样本数据结构和其对应的存储器数据结构与DAWG匹配算法所使用的相同。标准化该样本数据以易于扩展内容检测框架并实现到不同的搜索算法。将转移表构造为2维的整数阵列S[n][4]。如图16的示例性转移表的存储器数据结构和如下所示,每一表项S[k]包括指向整数阵列的指针,其具有下列构造-S[k]:int;/*Primaryshiftvalue*/S[k][l]:int;/*Secondaryshiftvalue*/S[k][2〗int;/*Offset*/S[k][3]:int;/*Depth*/"k"是用于对转移表进行索引的值(通常是长整数)。如果字母表的大小是A,而我们作为散列值使用的子字符串(字符串块)的大小是B,则表的最大尺寸是AB。"k"是从B个字符的块获得的(唯一的)散列值(最简单的散列函数考虑的块是B个数位的基数为A的数)。primaryshift(主移动)是指扫描位置必须向右转移的距离。仅在扫描的子字符串匹配多个模板之一中的适当位置处的子字符串时,该值才是O。secondaryshift(次移动)是指仅当主值为0时扫描位置必须向右转移的距离。在处理primary—shiftK)的文本位置后,该转移值替换默认的转移1。该值的值将总是大于0(因此当其等于0时大于primary—shift)。偏移是从包内容的开头的最小距离,其中,可能会出现正确样本结束于正在处理(假定所有样本都被截断到最小样本大小)的当前子字符串的情况。深度是从包内容的开头的最大距离,其中,正确的样本结束于必须结束的正在处理(假定所有样本都被截断到最小样本大小)的当前子字符串。仅当primaryshiftvalue等于0时,即当文本(包内容)中的子字符串匹配正在处理的多个样本之一的末尾时,offset、depth和secondary—shift值才有意义并被使用。将HASH表构造为一维的指针阵列H[n]。如图17的示例性HASH表存储器数据结构所示,每一表项H[k]包括指向样本数据结构的指针。该表的索引相同于转移表的索引。通过样本结束的B个字符的块的散列值,对样本(被截断到最小样本大小)进行分类。H[k]的值是具有大于或等于"k"的散列值的该分类表中的第一样本。由于样本数据结构具有固定的大小,可以从存储器以随机方式对其进行访问。因为,可以使用阵列中的样本的序列号来计算样本数据结构的地址。从而,在存储器的HASH表中存储的值将包括样本索引号(范围从0到number一ofjatterns-l)而不是实际地址,以可重新定位样本。将PREFIX表构造为一维整数(通常为长整数)阵列。表的大小等于样本集中的样本数量,且将样本(或样本索引号)用作PrefDc(前缀)表的任何项的索引。值Prefix[k]是样本数"k"("k"的范围从O到number—ofjattems-O中的第一个B字符的散列。散列的通常以与移动表的计算方式相同的方式计算(考虑前缀是B个数位组成的基数为A的数的前缀)。在存储器表示(在图18中示出了其一个实施例)中,每一表项是未修改的前缀值,这是因为采用的字母表包括整个ASCII集。SHIFT和HASH表均包含大量的冗余信息。这些表的大小是指数级的,而样本集的数量一般会小得多。因此,我们可以认为,大多数SHIFT表值等于默认值,类似地,大量的HASH表项可能包含不会被查询的无用信息。另一方面,对存储器的这种严重浪费可以由以恒定时间查询信息的性能优点来补偿。对于较大的B值(3或者更大),存储器的使用受到了抑制,因此我们使用B+树作为压縮数据结构,其在获取任何信息片段时需要査询的次数相对较小。将该B+树构造为节点树,其中每一叶子具有恒定的到根的距离。尽管级别的数量可以是任意的,但我们选择了二级深度,这对于大多数实际应用就足够了。每一子节点是下述结构的阵列.-structhash—record{longkey_value;/*Hashvalue(indextoSHIFTandHASHtables)*/intprimary—shift;/*Primaryshift(asintheSHIFTtable)*/intsecondary—shift;/*Secondaryshift(asintheSHIFTtable)*/intoffset;/*Offset(asintheSHIFTtable)*/intdepth;/*Depth(asintheSHIFTtable)*/structPattern*patlist—start;/*Pointertostartofpatternlist(HASHtableentry)*/structPattern*patlist—end;/*Pointertoendofpatternlist(nextHASHtableentry)*/intpstart;/*Patternnumberinsortedlistofpatlist—start*/intpend;/*Patternnumberinsortedlistofpatlist—end*/};根节点是特别的且是恒定大小的阵列,将每一个元素(dement)构造为structbplus一tree一node{structhash—record*list;/*Pointertochildnode*/int加m一elements;/*Numberofelementsinlist*/};structbplus—tree—noderoot[A];在图19中示出了根节点的示例性存储器结构。根具有类型为structbplus—tree—node的"A"个元素,其中A是字母表大小(在ASCII集的情况下是256)。考虑SHIFT表。如果索引值是B个字符c^.&的块的散列,则通过计算该块c,的最高有效字节的散列值来随机访问根的每一元素。将剩余的该块(—0映射到子节点的元素的key一value。每一子节点(/的无需包含大小为B-1的多个字符串的所有可能散列值的项;其仅包含不具有相关的默认主移动值的那些元素的项(其等于Minimum_pattem—size-B+l)。为了访问位于SHIFT一table[c,cv.cJ中的信息,我们查询roof[c,].fc/(A:)(其中,//w("是指rao/[c,中具有keyvalue=hashvalueofc2..csC2,f丑的散列值)的元素)。以相同方式査询HASH表值。上述结构中各项的含义通常是自明性的。patlist一end和pend参数不表示从特定HASH表项中获取的样本列表中最后的样本;而是表示由下一个HASH项所指向的样本,或者在全局分类样本列表中该样本的列表之后的样本。图20示出了子节点存储器数据结构的一个实施例。尽管根节点和每一子节点在存储器中是可以独立重定位的,但在图20的实施例的实现方式中,子节点紧跟着根结构。同样,子节点以连续方式被写入存储器,其顺序由父元素的索引值来决定。以连续方式存储该数据使存储器预分配变得容易,仅需要明确指定一个指针(根的第一个词的地址)。Wu-Manber算法假定所有的样本的长度相等;在这一假定条件下,其是正确的。但由于这不是一个实际的假设,因此我们需要将所有字符串截断到最短样本的大小。在算法运行过程中,当发现竞争位置时,匹配完整的样本。传适给预处理函数的样本被截断。在本说明书的结尾部分的附录中,提供了用于构造SHIFT、HASH、PREFIX和B+树的伪代码示例。此外,在附录中还提供了实现Wu-Manber算法的各种变体的伪代码。附录中的Wu-Manber算法非常不同于[WM94]中所描述的算法。该算法支持样本的额外特征,例如偏移、深度、大小写无关等。次偏移值是基本算法中的更主要的不同。在由Wu和Manber[WM94]所提出的原始算法中,如果主偏移值是0,则总是强制跳跃值为1。这样当然确保了正确的操作,但跳跃1过于保守。次偏移表示为了匹配被考虑的、子字符串(大小为B的块)所需跳跃的最小距离。此跳跃的最大安全值是在SHIFT表计算期间计算的第二最低偏移,其正是我们对次偏移的定义。根据Wu-Manber算法描述显而易见的是,在为下一个包执行算法时,将在上一个包的末尾(后缀)处匹配的任何样本的最大前缀作为该算法的输入提供。该信息分两部分提供prefiX_addreSS,即前缀匹配的样本字符串的第一字节的地址,以及prefixjength,即前缀的大小(或者成功匹配的样本的字节数量)。对于流中的第一个包而言,在上一个样本匹配的样本的前缀是空字符串,因此prefixjength参数值是0,而prefix_address未被初始化。朝向包扫描的末尾,在循环重复期间,用作表项索引的块将跨过包的末尾(即,位置>=包大小)。当出现此情况时,我们必须部分回复到原本的字符串匹配算法。当在包的末尾仍旧留有一些未被检测的字符时,将这些字符匹配到我们的样本集中的(相同大小的)每个样本的前缀。一旦获得匹配,就相应地在prefix—length和prefix—address中记录匹配的长度和地址。当将扫描序列的下一个包时,将该前缀匹配附加到包内容,扫描以正常方式继续。当到达的包的顺序颠倒时,用于匹配跨越多个包的样本的技术就失败了。在包的开头匹配任意的后缀、并期望其是在前一个包中开始的样本的一部分都是不起作用的。如对DAWG匹配的情况所述,缓冲和状态维持的组合可以提供全面的解决方案。在某些实施例中,还可以采用上述的Wu-Manber算法来进行偏移/深度搜索。当试图匹配样本时,我们还需要确保符合偏移和深度的限制,我们不会将循环浪费在企图匹配可能会出现但却被证实是不正确的限制值的样本的情况中。因此,我们将正确的偏移和深度值与每一SHIFT表项相结合。通过选择最安全的可能值,以与偏移值相同的方式来设置偏移和深度值。如果将字节S的块用于索引进入SHIFT表,则将对应的偏移设置为以该块结尾的任何样本的最小偏移(首先将该样本截断为最短样本长度)。相似地,将深度设置为(depth—length+minimum_pattern—size)的最大值,因为其指示被截断的样本在文本中必须结束的位置。在包扫描期间,当观测到主偏移值为0时,我们首先检査偏移和深度(从表中查询),并将它们匹配到当前的文本位置。仅在符合限制时,我们才继续通过HASH表指示的样本列表进行循环。在此过程中,在成功的PREFIX表匹配之后以及逐字节地试图匹配整个样本之前,与这些样本自身相关的偏移和深度与当前的文本位置匹配。如果当前的位置是在限制内,则尝试完整的样本匹配。如果上述偏移和深度检查中的任何一个失败,则将位置的值增加等于次转移的值,搜索继续。幸运的是,与DAWG匹配算法相比,Wu-Manber算法可以更具存储器效率地处置大小写无关。所需进行的额外工作大部分被转移到了预处理阶段。当更新SHIFT表时,如果大小写无关样本被处理,则计算被考虑的B长度的块的所有大小写相关组合,并调整与这些组合中的每一个相对应的SHIFT表项。对于HASH和PREFIX表而言,根据大小写无关样本的小写对等体计算索引和前缀值。在包扫描期间,直接进行SHIFT表查询,而无需对由Wu和Ma油er所提出的原始算法进行添加,这是因为对所有潜在的大小写组合均存在正确的SHIFT项。但对于HASH表查询,我们需要计算两个不同的索引值使用原本的块的字符的正常索引;以及通过将B块中的所有大写字符转换为小写字符而计算的小写索引。由于大小写无关样本的HASH项是仅基于小写字符而被计算的,因此第二索引是必要的。检査前缀、并在随后匹配完整样本的整个循环被重复两次,一次用于正常索引值,而另一次用于小写索引值。同样,计算样本前缀的正常和小写版本。如果被考虑的样本的是大小写无关的,则匹配小写前缀,否则匹配正常前缀。一旦算法开始将样本与包内容逐字节地匹配,就可以直接进行大小写无关的匹配了。在一个实施例中,内容检测框架是可以被插入之前实现的有状态防火墙框架的模块。在英特尔IXP处理模型中,可以将内容检测框架作为单独的微块插入任何包处理管线中。在一个实施例中,防火墙使用CA(条件动作)对以迸行规则处理。例如,特定的CA规则可能相关于内容检测,例如使用包内容检査特定的恶意样本(条件)并在检测到样本时丢弃包(动作)。图21中示出了典型的内容检测CA规则的存储器映射。前两个字(或第一个长字被保留),实际的信息开始于8字节的偏移。每一字段的含义如下所示-1.算法代码其表示使用的搜索算法的类型。l-DAWG匹配算法2=后缀树匹配算法3=Wu-Manber算法4=使用替换SHIFT和HASH表的B+树结构的Wu-Manber算法5=给定精确开始位置的匹配样本(即假定样本开始于指定位置或根本就不出现)2.SRAM地址其表示用于样本搜索的数据结构的地址(或指向地址索引的指针)。对于前4个算法,该地址指向主索引的第一个字;这包含与用于检测的各种数据结构的地址相关的信息。3."跨越样本检査"策略对于前4个算法,其仅仅是具有值0(其表示不应对可能跨越多个包的样本进行检查)或值l(其表示应进行这种检查)的标记。对于精确的位置匹配,该字段表示应执行样本匹配的(作为从第一字节的偏移的)包内容中的位置。为了检查跨越多个包的样本,我们需要在流表内与当前流相对应的项中存储部分匹配信息(DAWG匹配的AC状态,Wu-Manber的样本地址和前缀长度)。当待处理的下一个包到达时,我们还需要存储与所存储的信息的正确性相关的一些信息。因此对于TCP流,我们存储下一个期望的偏移的序列号以及状态信息。还可以对任何其他面向连接的协议存储相似类型的序列信息。在流表项的一个实施例中,通过以下方式存储该信息第一个字是下一个包中的第一字节的期望的序列号,第二个字是从上次扫描的末尾(用于算法代码1和2)或前缀长度(用于算法代码3和4)开始的AC机状态,第三个字是部分匹配的样本地址(仅用于算法代码3和4)。初始化和代码加载返回到图7,在网络线卡或网络设备的初始化期间,将便于实现各种包处理和内容检测功能以及本文所述操作的代码指令(例如微代码)加载到所选择的ME的控制存储728中。一般来说,可以从包括非易失存储设备(例如闪速存储器设备)的指令存储715加载指令。非易失存储的其他示例包括只读存储器(ROM)、可编程ROM(PROM)和电可擦除PROM(EEPROM)。除了从本地存储设备加载指令(到线卡700)之外,还可以从外部源加载指令。例如,在一个实施例中,指令被存储在由另一个线卡(未示出)管理的盘片驱动器中,或由其中安装了线卡700的网络元件来提供所述指令。在另一个实施例中,指令是经由作为载波的网络从远程服务器等上下载的。一般来说,可以经由在一个或多个计算引擎上执行对应的线程,使用硬件的可编程逻辑或固件/软件的可编程逻辑或这两者的组合来实现本文中所论述的和图中所示的每一功能块。例如,在一个实施例中,以集成到用于包处理的上下文管线的方式,通过在NPU的一个或多个计算引擎上执行对应的指令线程,来便于实现对每一深度包检测模块202、流管理器204、队列管理器708和接收引擎710所示的操作。可选地,由上述功能块提供的全部各种操作或这些操作中的一部分可以由在NPU等上嵌入的适当编程的逻辑来实现。因此,本发明的实施例可以被用作或支持固件/软件模块、和/或在某些形式的处理内核上执行的或否则在机器可读介质上实现或实施的程序。机器可读介质包括以机器(例如计算机)可读形式存储或发送信息的任何机制。例如,机器可读介质可以包括例如只读存储器(ROM);随机存取存储器(RAM);磁盘存储介质;光存储介质和闪速存储设备等。此外,机器可读介质可以包括诸如电、光、声或其他形式的传播信号(例如载波、红外信号、数字信号等)之类的传播信号。以上对本发明所示实施例的描述,包括摘要中的描述,并不是穷举性的或用于将本发明限定在所公开的具体形式上。尽管给出了本发明的具体示例和实施例,但本文中的这些描述是说明性的,对本领域技术人员来说,可以在本发明的范围内对其进行各种各样的等效修改。根据以上的具体描述,可以对本发明进行各种各样的修改。在所附权利要求书中使用的词语并不是为了将本发明限制在说明书和附图所披露的特定实施例中。取而代之的是,本发明的范围完全由所附权利要求书来确定,所附权利要求书是根据所建立的权利要求解释的含义而构造的。附录1.下面以伪C代码的形式给出SHIFT表的构造算法。输入样本阵列,用于散列进入表的块大小(B),字母表大小(A)输出指向SHIFT表的指针int**build—SHIFT—table(structPattern*P,intnum_pat,intB,ini/^Initialization*/table—size=AB;min_pattern—size=minimum(Pj.length);default_offset=minimum(Pi.offset);default—depth=minimum(Pj.depth);for(eachentryoftheSHIFT—table,i:0totable一size-l)/*Initializeeachentrytothedefaultvaluebeforepatternprocessing*/SHIFT一table[O][O]=min_pattern—size-B+l;SHIFT一table[O][l]=min_pattem_size-B+l;SHIFT—table[2]=defaultoffset;SHIFT一table[O][3]=default_depth;/*processpatternsandupdateSHIFT—tablevalues*/for(eachpatterni:0tonum_pat-l)for(eachsubstringS=Pi.string[j…j+B-1],j:0tomin_pattem_size-B)/*ComputehashvaluetoindexintoSHIFT—table*/Sval=HASH—value(S);"Computeprimaryshiiiasleastoffsetfromstartpositionofsubstringtoendofpattern*/SHIFT一table[Sval][O]=minimum(SHIFT一table[Sval][O],min_pattern—size-j-B);/*Computesecondaryshiftassecondleastshiftvaluefortheparticularsubstring*/SHIFT一table[Sval][l]=leastvalueof(min—size-j-B)thatisstrictlygreaterthanSHIFT—table[Sval][O];"Computeoffsetasleastoffsetamongallpatternscontainingthissubstring*/SHIFT一table[Sva1][2]=minimum(SHIFT一table[Sva1][2],P卜offset);/*Computedepthasmaximumdepthamongallpatternscontainingthissubstring*/SHIFT_table[Sval][3]=maximum(SHIFT一table[Sva1][3〗,Pi.depth-Pi,length+min_pattern—size);/^UpdateSHIFT—tableforcaseindependentpatterns*/if(Pi.fcase=0)For(eachpossiblecasecombinationofS)val=HASH—value(instanceofS);/*Updateallfourfields:bothshifts,offsetanddepthinthesamewayasabove*/update(SHIFT—table[val]);}returnSHIFT一table;2.下面以伪C代码的形式给出HASH表的构造算法。输入样本阵列,用于散列进入表的块大小(B),字母表大小(A)输出指向HASH表的指针structPattern**build—HASH—table(structPattern*P,intnum_pat,intBintA)"Initialization*/table—size=AB;min_pattern—size—minimum(Pi.length);sort(P,inascendingorderbasedonhashvaluecomputedfromeachPi.string[min_pattem—size-B...min_pattern—size-l]);/*InitializeindexvalueintoHASH—table"index=0jfor(eachpatternPj,i:Otonum_pat-l)/*ObtainsubstringofBcharactersthateachpatternendswith*/S=Pi.string[min_pattern—size-B..,min_pattern—size-1];/*Ifpatterniscaseindependent,mapittoitslowercaseequivalent*/if(Pi.fcase==0)S=convert一to一lower—case(S);Sval=HASH一value(S);while(Sval<count)/*Keepupdatingtablevaluesandpointersuntilhashvaluegetslargeenough*/HASH一table[index]=Pi;HASH—table_pattem—number[index]=i;index++;/*Forhigherindexvalues,fillupwithnon-existentpointerentry;thisdoesnotmatterassuchindexvalueswillneverbelookedup*/for(eachi:indextotable—size-1)HASH一table[index]=P;HASH—table_pattern—number[index]=num_pat;returnHASH—table;3.下面以伪C代码的形式给出PREFIX表的构造算法。输入样本阵列,前缀大小(B'),字母表大小(A)输出指向PREFIX表的指针longint*build—PREFIX—table(structPattern*P,intnum_pat,intB',intA)/^Initialization*/table—size=num_pat;for(eachpatternPi,i:Otonum_pat-l)Z*Computehashofprefixvalue;ifpatterniscaseindependent:convertprefixintolowercaseandcomputehash*/S=Pi.string;if(Pi.fcase==0)S=convert—to—lower一case(S);PREFIX—table卩]=HASH—value(S);returnPREFIX—table;}4.下面以伪C代码的形式给出B+树(B+tree)的构造算法。输入通过散列值分类的样本阵列(以和SHIFT表和HASH表相同的方式计算的散列),前缀大小(B,),字母表大小(A),SHIFT表,HASH表输出指向B+数根的指针structbplus—tree—node*build—Bplus—tree(int**SHIFT—table,structPattern**HASH—table,int*HASH—table_pattern—number,structPattern*P,intnum_pat,intB',intA)/*Computedefaultprimaryshift;thesearetheentrieswewilleliminate*/min_pattern_size=minimum(Pj.length);default_primary—shift=min_pattern—size-B+1;start—0;/*InitializeSHIFi,tableentrypositiontoscanfrom*/"Generateachildnodeperiteration*/for(i:OtoA-I)"ProcessAB-1SHIFTandHASHtableentriesduringeachloopiterationandgeneratehashrecordsforeach.entrywithanon-defaultprimaryshift*/counter=0jfor(j:starttostart+AB-1)if(SHIFT—table[j][O]!=default_primary—shift)/*AddallSHIFTandHASHtableinformationandsetkey*/root[i].list[counter].primary—shift=SHIFT—table[j][O];root[i].list[counter].secondary—shift=SHIFT一table[j][l];root[i].list[counter].offset=SHIFT一table[j][2];root[i].list[counter].depth=SHIFT一tableG][3〗;root[i],list[counter].patlist一start=HASH一table[j];root[i].list[counter].patlist一end=HASH一table[j+l];root[i].Iist[counter].pstart=HASH—table_pattem—number{j];root[i].list[counter].pend=HASH—table_pattern—number[j+l];root[i].list[counter].key—value=j-start;counterH";root[i].num—elements=count;start=start+AB1;returnroog如果添加所有记录(包括默认转移值的记录),字段key—value实际上是hash—record结构列表的索引。因此,上述算法确保了以key—value的升序对(每一树的子节点的)该列表进行分类。Wu-Manber算法输入包内容(字节字符串)T[O...n-1]、SHIFT表、HASH表、PREFIX表、最短样本的长度、样本数量、块大小(B)、前缀大小(B')、指示我们是否需要检查跨越包边界的样本的标志(策略)、在前一个包的末尾匹配的样本前缀的长度、其前缀在前一个包的末尾匹配的样本字符串的地址输出检测到的样本的标识(如果未检测到则为-l),样本开头的位置作为从字符串T的开头的偏移下面以伪C代码的形式给出该算法。Wu一Manber(int**SHIFT—table,structPattern**HASH—table,longint*PREFIX—table,char*T,intspan_poicy,int*prefix—length,char*prefix—address,intMINPATTERNSIZE,intNUMPATTERNS,intB,intB')"Initializepositiontoearliestpossibleendpositionofatruncatedpattern"position=MIN一PATTERN一SIZE-1;/*Ifpatternoverlapcheckneedstobemade,appendprefixmatchedinpreviouspacketotthebeginningofthepacketcontent*/if(span_policy———CHECK—SPANNING—PATTERN)S=Prefix(patternataddressprefix—address,length=prefix一len)T=append(StothebeginningofT);while(position<PACKET—SIZE)/*Getchunkendingat'position'andcomputetableindexvalue*/chunk=T[position-B.....position];chunk—val—HASH一value(chunk);/*Converttolowercaseandcomputeindex;thiswillbeusedlater*/chunkjower一case=convert_to—lower_case(chunk);chunk_val_lower—case=HASH—value(chunk—lower—case);if(SHIFT—table[chunk一val][O]〉0)/*Nopatterncanbefoundatthisposition,soshiftandtrytomatchatthenextposition*/position二position+SHIFT一table[chunk一val][O];continue;"Primaryshiftvaueis0,sowehaveapotentialmatchstartingat'poskion-MIN—PATTERN—SIZE+1'*//*Checkoffsetforcandidateposition*/if(position-MIN—PATTERN—SIZE+1<SHIFT—table[2])/*Nopatternendingwithchunksatisfiesoffsetlimitatcurrentposition,soskipusingsecondaryshiftvalueandtrytomatchatthenextposition*/position=position+SHIFT—table[chunk一val][l];continue;/*Checkdepthforcandidateposition*/if(position>=SHIFT—table[3])/*NopatternendingWithchunksatisfiesdepthlimitatcurrentposition,soskipusingsecondaryshiftvalueandtrytomatchatthenextposition*/position=position+SHIFT—table[chunk一val][l];continue;/*Computeprefixvalues(normalandlowercase)forcandidatestring*/prefix=T[position-MIN—PATTERN—SIZE+1....position-MIN—PATTERN一SIZE+B'];prefix—val=HASH一value(prefix);prefix—lower—case—val=HASH—value(convert—to一lower一case(prefix));/*Candidatepatterns:pointertopatternsareinascendingorder*/for(eachpatternHASH—table[chunk—val]<=Pj<HASH—table[chunk一val+l])if(Pi.fcase=0&&prefix—lower—case—val=PREFIX一TABLE[i])/*Convertbothstringstobematchedtolowercase*/Stringl=convert—to—lower—case(Pi.string);String2=convert—to—lower—case(T[position-MIN—PATTERN一SIZE+1........position-MIN—PATTERN—SIZE+P;.length);if(Stringl=String2)RecordP;;/*Patternmatch*/Record'position';Dependingonpolicy,returnorcontinuescanningT;elseif(Pi.fcase=1&&prefix—val==PREFIX一TABLE[i])if(Pj.string==T[position-MIN_PATTERN—SIZE+1.....position-MIN一PATTERN一SIZE+Pi.length)RecordP;;/*Patternmatch*/Record'position';Dependingonpolicy,returnorcontinuescanningT;}/*NowreplacechunkmatchedtoindexintoSHIFT一tablewithitslowercaseequivalent*/Repeat(above'for'loopreplacing'chunk—val'by'chunk—val一lower一case');/*Skipusingsecondaryshiftvalueandcontinuescanning*/position=position+SHIFT一table[chunk—val][l];/*Ifwedon'tneedtocheckifapatternmightspanmultiplepackets,return*/if(span_policy=CHECK—SPANNING—PATTERN)return;/*Calculatestartpositionofacandidatepatternthatcouldoverflowintothenextpacket*/position=position画MINPATTERN—SIZE+1;<formula>formulaseeoriginaldocumentpage52</formula>使用B+树的Wu-Manber算法输入包内容(字节字符串)T[O...n-l]、B+数根指针、PREFIX表、最短样本的长度、样本数量、块大小(B)、前缀大小(B')、指示我们是否需要检查跨越包边界的样本的标志(策略)、在前一个包的末尾匹配的样本前缀的长度、其前缀在前一个包的末尾匹配的样本字符串的地址输出检测到的样本的标识(如果未检测到则为-l),样本开头的位置作为从字符串T的开头的偏移该算法相同于上述的Wu-Manber算法,唯一的区别在于转移(shift)值和指针查询所使用的数据结构。现在从B+树的子项(从hash—record结构)而不是SHIFT表査询主次转移值以及偏移和深度值。也从同一B+数子节点项而不是HASH表获得指向可能在给定位置出现竞争样本的指针。但和SHIFT或HASH表不同的是,(在恒定时间内)无法直接查询这些值。序列扫描也是低效的。因此,我们使用折半査找来定位适当的记录;下面给出查询步骤1.获得用于计算散列值的块(子字符串)^2.A2.使用最高有效字节(O来定位适当的子节点指针和子节点的数量(root[c,].list禾口root[].num一elements)。3.使用映射到整数的剩余的块q..、以定位适当的hash—record结构。该整数是任何匹配结构的key—value。由于所有的结构是基于key—value以升序进行分类的,因此简单的折半查找将返回需要的数据。对于大小为256的字母表而言,至多需要8次查找以定位一个记录。数据査找之外的所有算法步骤都相同于上述Wu-Manber的算法步骤。B的实际值可以为2和3(虽然B-1也是有效的,但这与构造树的目的相背)。B,的实际值可以为4或更小。B和B'都必须小于最短样本的长度。权利要求1、一种方法,包括通过使用多样本搜索并对至少一个搜索样本采用至少一个标记值来执行内容检测,所述至少一个标记值包括下列各项中的至少一项数据流中的偏移,搜索样本可以开始于所述偏移处;以及所述数据流中的深度,所述深度是在所述数据流中搜索所述搜索样本的深度,其中,在所述多样本搜索中,对于至少两个搜索样本,偏移和深度中的至少一个是不同的。2、如权利要求l所述的方法,其中,使用单独的多样本字符串搜索算法的计算机实现来执行所述内容检测。3、如权利要求2所述的方法,其中,经由基于DAWG(有向非循环字图)匹配算法的字符串搜索算法的计算机实现来执行所述内容4、如权利要求2所述的方法,其中,经由基于Wu-Manber算法的字符串搜索算法的计算机实现来执行所述内容检测。5、如权利要求1所述的方法,还包括通过使用所述至少一个标记值来搜索跨越多个包的数据流,以实现内容检测。6、如权利要求5所述的方法,还包括识别具有第一部分和第二部分的搜索样本匹配,所述第一部分包括朝向先前的包的末尾而定位的前缀匹配,所述第二部分包括朝向后面的包的开头而定位的后缀匹配。7、如权利要求6所述的方法,还包括接收第一包;对所述第一包进行分类以将其分配给流;在分配给所述流的包中识别将被搜索的搜索字符串的样本集,所述搜索字符串中的至少一个具有与另一个字符串的偏移标记值不同的偏移标记值;使用第一指令线程执行所述第一包的内容检测,所述内容检测采用了一机制,以在考虑与每一搜索字符串相关的偏移标记值的情况下来有效地跳过所述第一包的相应部分;检测朝向所述第一包的末尾而定位的所述一个或多个搜索字符串中的一个搜索字符串的部分匹配;保存与所述部分匹配相对应的字符串搜索状态信息;接收第二包;对所述第二包进行分类以将其分配给所述流;获取所述字符串搜索状态信息;采用所述字符串搜索状态信息来检测所述搜索字符串的第二部分以指示全匹配,所述搜索字符串的第二部分开始于所述第二包的开头。8、如权利要求1所述的方法,还包括将包分配给流;经由所述包的内容检测来识别已出现的字符串匹配情况;以及对所述情况执行相关的动作,以处理分配给同一个流的后续接收到的包。9、如权利要求1所述的方法,还包括执行包括标记值的多样本搜索,所述标记值包括至少一个大小写无关搜索样本。10、如权利要求l所述的方法,其中,所述内容检测包括在多个操作的上下文管线中的操作,所述多个操作被执行以在网络设备上处理包,经由在多个计算引擎上执行多个指令线程来执行所述多个操作的上下文管线。11、一种提供指令的机器可读介质,如果在多线程网络处理器上执行所述指令,则执行以下操作-通过使用多样本搜索并对至少一个搜索样本采用至少一个标记值来执行内容检测,所述至少一个标记值包括下列各项中的至少一项数据流中的偏移,搜索样本可以开始于所述偏移处;以及所述数据流中的深度,所述深度是在所述数据流中搜索所述搜索样本的深度,其中,在所述多样本搜索中,对于至少两个搜索样本,偏移和深度中的至少一个是不同的。12、如权利要求11所述的机器可读介质,其中,执行所述指令还执行以下操作通过使用所述至少一个标记值来搜索跨越多个包的数据流,以实现多样本搜索内容检测。13、如权利要求11所述的机器可读介质,其中,执行所述指令还执行以下操作在至少一个共享存储器资源中保持流表,所述流表包括与相应的流相关的多个项,每一流表项包括,标识样本数据结构的信息,所述样本数据结构用于与所述相应的流相关的多样本搜索;以及标识所述多样本搜索的状态的状态信息;响应于接收包,将所述包分类给流;使所述包入队到分配给所述流的流队列中;对与所述流相对应的所述流表项进行定位;将所述包拷贝到所述网络处理器上的计算引擎的本地存储器中;将由所述流表项标识的所述样本数据结构拷贝到所述计算引擎的本地存储器中,所述样本数据结构包括至少一个标记值;以及使用所述样本数据结构在所述计算引擎上执行所述包的多样本字符串搜索。14、如权利要求13所述的机器可读介质,其中,执行所述指令还执行以下操作通过使用所述至少一个标记值来对跨越多个包的数据流执行多样本搜索,从而实现内容检测。15、如权利要求11所述的机器可读介质,其中,经由基于DAWG(有向非循环字图)匹配算法的字符串搜索算法的计算机实现来执行所述内容检测。16、如权利要求11所述的机器可读介质,其中,经由基于Wu-Manber算法的字符串搜索算法的计算机实现来执行所述内容检测。17、一种网络线卡,包括-具有多个多线程计算引擎的网络处理器单元(NPU);可通信地耦合到所述NPU的动态随机存取存储器(DRAM)存储;可通信地耦合到所述NPU的静态随机存取存储器(SRAM)存储;可通信地耦合到所述NPU的存储设备,所述存储设备中存储有在所述NPU上执行的指令,所述指令被执行以实现以下操作将所接收的包分类给相关的流;以及通过使用多样本搜索并对至少一个搜索样本采用至少一个标记值集来对一个或多个包执行内容检测,所述至少一个标记值集包括下列各项数据流中的偏移,搜索样本可以开始于所述偏移处;以及所述数据流中的深度,所述深度是在所述数据流中搜索所述搜索样本的深度,其中,在所述多样本搜索中,对于至少两个搜索样本,偏移和深度中的至少一个是不同的。18、如权利要求17所述的网络线卡,其中,所述NPU包括英特尔的基于IPX的NPU。19、如权利要求17所述的网络线卡,其中,经由基于DAWG(有向非循环字图)匹配算法的字符串搜索算法的计算机实现来执行所述内容检测。20、如权利要求17所述的网络线卡,其中,经由基于Wu-Manber算法的字符串搜索算法的计算机实现来执行所述内容检测。全文摘要内容检测系统需要同时搜索包中的多个样本,这往往难于实现。采用样本数据结构以便于实现经由对应的字符串搜索算法机的多样本搜索。样本数据结构包括定义搜索偏移的标记值和对应搜索样本的深度。将到来的包分类成流,并将其存储在对应的流队列中。使用流表项来识别给定流的样本数据结构。在内容检测期间,算法机采用标记值来有效地跳跃到每一搜索样本的偏移的数据流的部分,并在到达样本的深度时停止样本搜索。文档编号H04L29/06GK101213811SQ200680023561公开日2008年7月2日申请日期2006年6月29日优先权日2005年6月30日发明者S·巴拉克夏南,V·拉马克夏纳申请人:英特尔公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1