【hyperscan】hyperscan开源了!

hyperscan开源了!

官网:https://01.org/zh/hyperscan

1. 新闻背景

    当地时间10月19日,intel将它的高速正则表达式匹配引擎hyperscan开源了,版本4.0,基于BSD许可。这个基于自动机(Automata)的引擎经过了多年开发(2008年起),经过不断优化与完善,效率非常之高,虽然没有pcre等对正则语法支持全面,但非常适用于网络设备。用户可以在网络设备数据面(Data Plane)使用hyperscan进行规则匹配,实现高性能DPI/lPS/IDS等应用。之前开源的dpdk,搭配hyperscan,简直是双剑合璧。

    从此之后,DPI/IPS/IDS/NGFW开发人员可以把精力更多地放在业务上,而不需要苦于优化报文转发(dpdk之功)和规则匹配(hyperscan之力)的性能。对于DPI来说,从此之后,也许特征/规则才是核心价值,软件本身已经不重要了。而基于dpdk的软件产品,凭借其不输太多的性能、较低的成本、较低的开发门槛和灵活性,也对相同功能的硬件产品发起了挑战。

2. 技术细节

    hyperscan的实现基于自动机(automata,  如NFA/DFA)而不是回溯(back-tracking)。这么做有好有坏。好处是可以支持流模式(streaming)和多模正则表达式;坏处是,基于自动机的正则匹配无法很容易地处理某些正则构造 -  backreferences and arbitrary lookaround asserts(好吧,我也不知道这俩到底啥意思)是不支持的两个主要特性。

    hyperscan所使用的一些技术包括:

Discovery of literal (fixed string) factors and decomposition of regular expressions into smaller chunks (which we call "engines") separated by these literal factors.
  These engines can be of many different types:
    Deterministic Finite Automata (DFA)
    Bit-parallel Glushkov Non-deterministic Finite Automata (NFA) engines
    Custom engines for special cases (such as large bounded repeats).
      These engines can take many different roles:
        "Prefix" engines that precede our literal factors
        "Suffix" engines that follow our literal factors
        "Infix" engines that lie between two literal factors
        "Outfix" engines that aren’t connected at all with literal factors (when no satisfactory factors can be found in a regular expression)
      These engines can often run lazily or not at all to reduce overhead.
  We merge smaller DFA/NFA engines into larger ones, where this can be done without performance loss.
  SIMD "acceleration" of automata based scanning: where we can substitute relatively simple SIMD tests of our input for complex automata execution, we do it.
  We use Intel SIMD instructions to handle larger-scale NFA and literal matching tasks: having 128 or 256 (or more) bits for a bit-parallel automaton is often helpful.
  ... and many more short-cuts to attempt to avoid doing expensive automata calculations that we ultimately won’t need.

 hyperscan设计目标:

  • 高性能,包括正常应用场景和边界条件下
  • 较小的database(正则表达式编译后形成的数据)
  • 运行于流模式时,较小的流状态数据(stream state) 。这种模式下每条流都要维护自己的流状态。

另外,还有一些设计要求或限制:

  • 运行库必须以C实现,因为一些数据面环境不支持C++
  • 不可以在运行时任意请求内存,用到的内存仅包括database、匹配临时数据(scratch)和流状态(在流模式下)。
  • database必须是平面化(flat)的内存布局,以便可以序列化/反序列化,或者可以内存中的一处移动到另一处(这意味着内部不能含有指针)

3. API介绍

    hyperscan以C++实现,使用了boost库和C++11特性,但它的API却以简洁的C形式提供。hyperscan API主要分为两个部分:编译与匹配 (compile & scan)。用户提供的多个正则表达式先要经过编译,生成database,然后才可以调用匹配接口,使用此database进行匹配。

    编译就是将多个正则表达式编译为hyperscan database,调用编译接口时可以传入一些flags和mode等参数,控制匹配行为和运行模式。hyperscan的运行模式主要有3个:BLOCK、STREAM和VECTORED。BLOCK模式就是对多个数据块分别进行匹配;STREAM模式将特定的一组数据库视为一个STREAM,为每一个STREAM维护状态信息,它可以跨数据块进行匹配;VECTORED模式可以一次匹配多个数据块。使用不同模式参数编译的database在匹配时不能混用。

    hyperscan的database可以序列化成文件(当然也可以反序列化),也可以在不同机器间进行传递。

    编译的API主要有

hs_compile()
hs_compile_multi()
hs_compile_ext_multi()

   匹配就是基于编译好的database,对数据进行匹配,并得到匹配结果。 hyperscan在进行匹配时需要有一个临时数据(scratch),这块数据需要在数据面运行前就分配(不在运行时分配和释放,保证性能),且需要保证同一时刻仅有一个匹配过程在使用同一块临时数据。如果使用流模式,还需要预先为每个流分配流状态数据。

    匹配结果是通过用户自定义的回调函数获取的。匹配过程中只要发生命中,就会调用此函数。此函数返回0表示继续匹配,非0表示停止匹配。此函数的原型由hyperscan约定,用户通过实参,可以获得命中正则表达式对应的ID、匹配位置等信息。

    匹配回调函数的原型:

typedef (* match_event_handler)(unsigned int id, 
                                unsigned long long from, 
                                unsigned long long to, 
                                unsigned int flags, 
                                void *context)

    匹配的API主要有

hs_scan()
hs_scan_vector()
hs_scan_stream()

流模式的匹配较为复杂,这里不提及,下文有相关示例解读。

 

posted @ 2015-10-21 18:20  赵子清  阅读(12229)  评论(2编辑  收藏  举报