hyperscan多核dpdk场景适配

553 阅读2分钟

简介

hyperscan是intel维护开发的一套正则匹配库,用于高性能的进行正则规则匹配;本文主要介绍hyperscan的编译安装和单测,另外包括多核情况下如何适配使用。

编译安装

  • mkdir build
  • cd build
  • cmake --install-prefix=/usr/local/hyperscan/ -DBUILD_STATIC_AND_SHARED=ON -DFAT_RUNTIME=ON -DCMAKE_BUILD_TYPE=Release ../hs_src
  • make -j8
  • make install

编译参数说明:

  1. BUILD_STATIC_AND_SHARED 表示静态库和动态库都进行编译
  2. FAT_RUNTIME 表示编译通用兼容类型,可在更多硬件型号上运行使用
  3. CMAKE_BUILD_TYPE 表示编译的类型,Release为发布类型

Very Quick Start

  1. Clone Hyperscan

    cd <where-you-want-hyperscan-source>
    git clone git://github.com/intel/hyperscan
    
  2. Configure Hyperscan

    Ensure that you have the correct dependencies present, and then:

    cd <where-you-want-to-build-hyperscan>
    mkdir <build-dir>
    cd <build-dir>
    cmake [-G <generator>] [options] <hyperscan-source-path>
    
    • Known working generators:

      • Unix Makefiles — make-compatible makefiles (default on Linux/FreeBSD/Mac OS X)
      • Ninja — Ninja build files.
      • Visual Studio 15 2017 — Visual Studio projects
    • Generators that might work include:

      • Xcode — OS X Xcode projects.
  3. Build Hyperscan

    • Depending on the generator used:

      • cmake --build . — will build everything
      • make -j<jobs> — use makefiles in parallel
      • ninja — use Ninja build
      • MsBuild.exe — use Visual Studio MsBuild
      • etc.
  4. Check Hyperscan

    Run the Hyperscan unit tests:

    bin/unit-hyperscan
    

单测

源码

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <hs/hs.h>

//打印
#define XFTEST_DBG(fmt, argc...) printf("[file:%s,line:%d,func:%s]" fmt, __FILE__, __LINE__, __FUNCTION__, ##argc)
#define XFTEST_ERR(fmt, argc...) printf("[file:%s,line:%d,func:%s]" fmt, __FILE__, __LINE__, __FUNCTION__, ##argc)

//正则匹配回调函数
static int eventHandler(unsigned int id, unsigned long long from,
                        unsigned long long to, unsigned int flags, void *ctx) {
    id = id;
    from = from;
    to = to;
    flags = flags;
    printf("Match for pattern at offset %llu\n", to);
    //set matched flag
    *(int*)ctx = 1;
    return 0;
}

static void
lib_hyperscan_module_test(void)
{
    hs_database_t *database;
    hs_compile_error_t *compile_err;
    const char *pattern = "[f|F]ile";

    //默认是大小写敏感的
    if (hs_compile(pattern, HS_FLAG_DOTALL|HS_FLAG_CASELESS, HS_MODE_BLOCK, NULL, &database, &compile_err) != HS_SUCCESS) {
        fprintf(stderr, "ERROR: Unable to compile pattern \"%s\": %s\n", pattern, compile_err->message);
        hs_free_compile_error(compile_err);
        return;
    }

    hs_scratch_t *scratch = NULL;
    if (hs_alloc_scratch(database, &scratch) != HS_SUCCESS) {
        fprintf(stderr, "ERROR: Unable to allocate scratch space. Exiting.\n");
        hs_free_database(database);
        return;
    }

    
    int hs_ret = 0;
    char inputdata[64] = {0};
    strcpy(inputdata, "file fIle");
    //66, 69, 6c, 65, 20, 66 //file
    if (hs_scan(database, inputdata, sizeof(inputdata), 0, scratch, eventHandler, &hs_ret) != HS_SUCCESS) {
        fprintf(stderr, "ERROR: Unable to scan input buffer. Exiting.\n");
        hs_free_scratch(scratch);
        hs_free_database(database);
        return;
    }
    if (hs_ret == 1) {
        XFTEST_DBG("[hyperscan] [hs_scan] test success.\n");
    } else {
        XFTEST_ERR("[hyperscan] [hs_scan] test failed.\n");
    }

    hs_free_scratch(scratch);
    hs_free_database(database);
}

int main()
{
        lib_hyperscan_module_test();
}

编译运行

[xiaofeng@localhost test]$ gcc main.c -I /usr/local/hyperscan/include/ -L /usr/local/hyperscan/lib64/  -lstdc++ -lhs -lm
[xiaofeng@localhost test]$ ./a.out 
Match for pattern at offset 4
Match for pattern at offset 9
[file:main.c,line:55,func:lib_hyperscan_module_test][hyperscan] [hs_scan] test success.

dpdk多核适配

将allocator系列函数的内存分配和释放函数,指定为dpdk中巨页内存的分配和释放函数,保证多核情况下内存访问正常,否则会段错误。

image.png

#include <rte_common.h>
#include <rte_malloc.h>
#include "hs/hs.h"

static
void *__hs_alloc(size_t size)
{
	return rte_zmalloc("hs_mem_chunk", size, 64);
}

static
void __hs_free(void *ptr)
{
	rte_free(ptr);
}


/**
 * @brief - hyperscan allocator adapt fo multicore init.
 * @void: 
 *
 * return: 0 for success. otherwise -1.
 */
int dp_hs_allocator_init(void)
{
	hs_set_allocator(__hs_alloc, __hs_free);
	hs_set_database_allocator(__hs_alloc, __hs_free);
	hs_set_misc_allocator(__hs_alloc, __hs_free);
	hs_set_scratch_allocator(__hs_alloc, __hs_free);
	hs_set_stream_allocator(__hs_alloc, __hs_free);
	
	return 0;
}

参考