New Multi-pattern matcher, ac-tile, optimized for Tile architecture.

Aho-Corasick mpm optimized for Tilera Tile-Gx architecture. Based on the
util-mpm-ac.c code base. The primary optimizations are:
1) Matching function used Tilera specific instructions.
2) Alphabet compression to reduce delta table size to increase cache
   utilization  and performance.

The basic observation is that not all 256 ASCII characters are used by
the set of multiple patterns in a group for which a DFA is
created. The first reason is that Suricata's pattern matching is
case-insensitive, so all uppercase characters are converted to
lowercase, leaving a hole of 26 characters in the
alphabet. Previously, this hole was simply left in the middle of the
alphabet and thus in the generated Next State (delta) tables.

A new, smaller, alphabet is created using a translation table of 256
bytes per mpm group. Previously, there was one global translation
table for converting upper case to lowercase.

Additional, unused characters are found by creating a histogram of all
the characters in all the patterns. Then all the characters with zero
counts are mapped to one character (0) in the new alphabet. Since
These characters appear in no pattern, they can all be mapped to a
single character and still result in the same matches being
found. Zero was chosen for the value in the new alphabet since this
"character" is more likely to appear in the input. The unused
character always results in the next state being state zero, but that
fact is not currently used by the code, since special casing takes
additional instructions.

The characters that do appear in some pattern are mapped to
consecutive characters in the new alphabet, starting at 1. This
results in a dense packing of next state values in the delta tables
and additionally can allow for a smaller number of columns in that
table, thus using less memory and better packing into the cache. The
size of the new alphabet is the number of used characters plus 1 for
the unused catch-all character.

The alphabet size is rounded up to the next larger power-of-2 so that
multiplication by the alphabet size can be done with a shift.  It
might be possible to use a multiply instruction, so that the exact
alphabet size could be used, which would further reduce the size of
the delta tables, increase cache density and not require the
specialized search functions. The multiply would likely add 1 cycle to
the inner search loop.

Since the multiply by alphabet-size is cleverly merged with a mask
instruction (in the SINDEX macro), specialized versions of the
SCACSearch function are generated for alphabet sizes 256, 128, 64, 32
and 16.  This is done by including the file util-mpm-ac-small.c
multiple times with a redefined SINDEX macro. A function pointer is
then stored in the mpm context for the search function. For alpha bit
sizes of 8 or smaller, the number of states usually small, so the DFA
is already very small, so there is little difference using the 16
state search function.

The SCACSearch function is also specialized by the size of the value
stored in the next state (delta) tables, either 16-bits or 32-bits.
This removes a conditional inside the Search function. That
conditional is only called once, but doesn't hurt to remove
it. 16-bits are used for up to 32K states, with the sign bit set for
states with matches.

Future optimization:

The state-has-match values is only needed per state, not per next
state, so checking the next-state sign bit could be replaced with
reading a different value, at the cost of an additional load, but
increasing the 16-bit next state span to 64K.

Since the order of the characters in the new alphabet doesn't matter,
the new alphabet could be sorted by the frequency of the characters in
the expected input stream for that multi-pattern matcher. This would
group more frequent characters into the same cache lines, thus
increasing the probability of reusing a cache-line.

All the next state values for each state live in their own set of
cache-lines. With power-of-two sizes alphabets, these don't overlap.
So either 32 or 16 character's next states are loaded in each cache
line load. If the alphabet size is not an exact power-of-2, then the
last cache-line is not completely full and up to 31*2 bytes of that
line could be wasted per state.

The next state table could be transposed, so that all the next states
for a specific character are stored sequentially, this could be better
if some characters, for example the unused character, are much more
frequent.
pull/549/merge
Ken Steele 12 years ago committed by Victor Julien
parent 77b429c402
commit e05034f5dd

@ -297,6 +297,7 @@ util-misc.c util-misc.h \
util-mpm-ac-bs.c util-mpm-ac-bs.h \
util-mpm-ac.c util-mpm-ac.h \
util-mpm-ac-gfbs.c util-mpm-ac-gfbs.h \
util-mpm-ac-tile.c util-mpm-ac-tile.h \
util-mpm-b2gc.c util-mpm-b2gc.h \
util-mpm-b2g.c util-mpm-b2g.h \
util-mpm-b2gm.c util-mpm-b2gm.h \

@ -113,7 +113,7 @@ SCEnumCharMap smtp_decoder_event_table[ ] = {
{ NULL, -1 },
};
#define SMTP_MPM MPM_AC
#define SMTP_MPM DEFAULT_MPM
static MpmCtx *smtp_mpm_ctx = NULL;
MpmThreadCtx *smtp_mpm_thread_ctx;

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -1530,7 +1530,7 @@ int DetectCsumICMPV6Test01(void)
printf("DetectEngineCtxInit failure\n");
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any any "

@ -163,7 +163,7 @@ static int DetectDnsQueryTest01(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -284,7 +284,7 @@ static int DetectDnsQueryTest02(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -429,7 +429,7 @@ static int DetectDnsQueryTest03(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -526,7 +526,7 @@ static int DetectDnsQueryTest04(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -677,7 +677,7 @@ static int DetectDnsQueryTest05(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -839,7 +839,7 @@ static int DetectDnsQueryTest06(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@ -974,7 +974,7 @@ static int DetectDnsQueryTest07(void) {
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -58,8 +58,7 @@
#endif
/** \todo make it possible to use multiple pattern matcher algorithms next to
eachother. */
#define PM MPM_AC
each other. */
#define POPULATE_MPM_AVOID_PACKET_MPM_PATTERNS 0x01
#define POPULATE_MPM_AVOID_STREAM_MPM_PATTERNS 0x02
@ -134,13 +133,13 @@ int SignatureHasStreamContent(Signature *s) {
/**
* \brief Function to return the multi pattern matcher algorithm to be
* used by the engine, based on the mpm-algo setting in yaml
* Use the default mpm non is found in yaml.
* Use the default mpm if none is specified in the yaml file.
*
* \retval mpm algo value
*/
uint16_t PatternMatchDefaultMatcher(void) {
char *mpm_algo;
uint16_t mpm_algo_val = PM;
uint16_t mpm_algo_val = DEFAULT_MPM;
/* Get the mpm algo defined in config file by the user */
if ((ConfGet("mpm-algo", &mpm_algo)) == 1) {
@ -152,7 +151,8 @@ uint16_t PatternMatchDefaultMatcher(void) {
continue;
if (strcmp(mpm_table[u].name, mpm_algo) == 0) {
return u;
mpm_algo_val = u;
goto done;
}
}
}
@ -162,6 +162,12 @@ uint16_t PatternMatchDefaultMatcher(void) {
exit(EXIT_FAILURE);
}
done:
#ifdef __tile__
if (mpm_algo_val == MPM_AC)
mpm_algo_val = MPM_AC_TILE;
#endif
return mpm_algo_val;
}

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -625,7 +625,7 @@ static int PayloadTestSig18(void)
"byte_extract:1,2,one,string,dec,relative; "
"content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -654,7 +654,7 @@ static int PayloadTestSig19(void)
"byte_extract:1,2,one,string,hex,relative; "
"content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -683,7 +683,7 @@ static int PayloadTestSig20(void)
"byte_extract:1,2,one,string,dec,relative; "
"content:\"|06 35 07 08|\"; offset:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -712,7 +712,7 @@ static int PayloadTestSig21(void)
"byte_extract:1,2,one,string,dec,relative; "
"content:\"|03 04 05 06|\"; depth:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -741,7 +741,7 @@ static int PayloadTestSig22(void)
"byte_extract:1,2,one,string,dec,relative; "
"content:\"|09 0A 0B 0C|\"; within:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -771,7 +771,7 @@ static int PayloadTestSig23(void)
"byte_extract:1,3,two,string,dec,relative; "
"byte_test:1,=,one,two,string,dec,relative; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -801,7 +801,7 @@ static int PayloadTestSig24(void)
"byte_jump:1,one,string,dec,relative; "
"content:\"|0D 0E 0F|\"; distance:0; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -833,7 +833,7 @@ static int PayloadTestSig25(void)
"byte_extract:1,-4,one,string,dec,relative; "
"content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
result = 0;
goto end;
}
@ -865,7 +865,7 @@ static int PayloadTestSig26(void)
"byte_extract:1,-3000,one,string,dec,relative; "
"content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) != 0) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 0) {
result = 0;
goto end;
}
@ -893,7 +893,7 @@ static int PayloadTestSig27(void)
"depth:5; sid:1;)";
p->flags |= PKT_STREAM_ADD;
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) != 1)
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 1)
goto end;
result = 1;
@ -919,7 +919,7 @@ static int PayloadTestSig28(void)
"offset:4; depth:12; sid:1;)";
p->flags |= PKT_STREAM_ADD;
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) != 1)
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 1)
goto end;
result = 1;
@ -943,7 +943,7 @@ static int PayloadTestSig29(void)
char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
"pcre:/^.{4}/; content:\"nova\"; within:4; sid:1;)";
if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 1) {
if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
result = 0;
goto end;
}

@ -925,7 +925,7 @@ static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx) {
if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context, "auto") == 0) {
/* for now, since we still haven't implemented any intelligence into
* understanding the patterns and distributing mpm_ctx across sgh */
if (de_ctx->mpm_matcher == MPM_AC || de_ctx->mpm_matcher == MPM_AC_GFBS ||
if (de_ctx->mpm_matcher == DEFAULT_MPM || de_ctx->mpm_matcher == MPM_AC_GFBS ||
#ifdef __SC_CUDA_SUPPORT__
de_ctx->mpm_matcher == MPM_AC_BS || de_ctx->mpm_matcher == MPM_AC_CUDA) {
#else

@ -690,7 +690,7 @@ static int DetectHttpHeaderTest09(void)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
"(msg:\"http header test\"; "

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -8890,7 +8890,7 @@ static int DetectIPProtoTestSig2(void)
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
@ -8978,7 +8978,7 @@ static int DetectIPProtoTestSig3(void)
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->mpm_matcher = DEFAULT_MPM;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,

@ -0,0 +1,91 @@
/* Copyright (C) 2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Ken Steele <suricata@tilera.com>
* Included by util-mpm-ac-tile.c with different SLOAD, SINDEX and
* FUNC_NAME
*
*/
/* This function handles (ctx->state_count < 32767) */
uint32_t FUNC_NAME(SCACTileCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
PatternMatcherQueue *pmq, uint8_t *buf, uint16_t buflen)
{
int i = 0;
int matches = 0;
uint8_t* restrict xlate = ctx->translate_table;
char *state_table = (char*)ctx->state_table_u16;
STYPE state = 0;
int c = xlate[buf[0]];
/* If buflen at least 4 bytes and buf 4-byte aligned. */
if (buflen >= 4 && ((uint64_t)buf & 0x3) == 0) {
BTYPE data = *(BTYPE* restrict)(&buf[0]);
uint64_t index = 0;
/* Process 4*floor(buflen/4) bytes. */
i = 0;
while (i < (buflen & ~0x3)) {
BTYPE data1 = *(BTYPE* restrict)(&buf[i + 4]);
index = SINDEX(index, state);
state = SLOAD(state_table + index + 2 * c);
c = xlate[BYTE1(data)];
if (unlikely(SCHECK(state))) {
matches = CheckMatch(ctx, pmq, buf, buflen, state, i, matches);
}
i++;
index = SINDEX(index, state);
state = SLOAD(state_table + index + 2*c);
c = xlate[BYTE2(data)];
if (unlikely(SCHECK(state))) {
matches = CheckMatch(ctx, pmq, buf, buflen, state, i, matches);
}
i++;
index = SINDEX(index, state);
state = SLOAD(state_table + index + 2*c);
c = xlate[BYTE3(data)];
if (unlikely(SCHECK(state))) {
matches = CheckMatch(ctx, pmq, buf, buflen, state, i, matches);
}
data = data1;
i++;
index = SINDEX(index, state);
state = SLOAD(state_table + index + 2*c);
c = xlate[BYTE0(data)];
if (unlikely(SCHECK(state))) {
matches = CheckMatch(ctx, pmq, buf, buflen, state, i, matches);
}
i++;
}
}
/* Process buflen % 4 bytes. */
for (; i < buflen; i++) {
uint64_t index = 0 ;
index = SINDEX(index, state);
state = SLOAD(state_table + index + 2*c);
c = xlate[buf[i+1]];
if (unlikely(SCHECK(state))) {
matches = CheckMatch(ctx, pmq, buf, buflen, state, i, matches);
}
} /* for (i = 0; i < buflen; i++) */
return matches;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,121 @@
/* Copyright (C) 2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
* \author Ken Steele <suricata@tilera.com>
*
*/
#ifndef __UTIL_MPM_AC_TILE__H__
#define __UTIL_MPM_AC_TILE__H__
#define SC_AC_TILE_STATE_TYPE_U16 uint16_t
#define SC_AC_TILE_STATE_TYPE_U32 uint32_t
typedef struct SCACTilePattern_ {
/* length of the pattern */
uint16_t len;
/* flags decribing the pattern */
uint8_t flags;
/* holds the original pattern that was added */
uint8_t *original_pat;
/* case sensitive */
uint8_t *cs;
/* case INsensitive */
uint8_t *ci;
/* pattern id */
uint32_t id;
struct SCACTilePattern_ *next;
} SCACTilePattern;
typedef struct SCACTilePatternList_ {
uint8_t *cs;
uint16_t patlen;
uint16_t case_state;
} SCACTilePatternList;
typedef struct SCACTileOutputTable_ {
/* list of pattern sids */
uint32_t *pids;
/* no of entries we have in pids */
uint32_t no_of_entries;
} SCACTileOutputTable;
/* Reordered for Tilera cache */
typedef struct SCACTileCtx_ {
/* This stuff is used at search time */
/* Convert input character to matching alphabet */
uint8_t translate_table[256];
/* the all important memory hungry state_table */
SC_AC_TILE_STATE_TYPE_U16 *state_table_u16;
/* the all important memory hungry state_table */
SC_AC_TILE_STATE_TYPE_U32 (*state_table_u32)[256];
/* Specialized search function based on size of data in delta
* tables. The alphabet size determines address shifting and the
* number of states could make the next state could be 16 bits or
* 32 bits.
*/
uint32_t (*search)(struct SCACTileCtx_ *ctx, struct MpmThreadCtx_ *,
PatternMatcherQueue *, uint8_t *, uint16_t);
SCACTileOutputTable *output_table;
SCACTilePatternList *pid_pat_list;
/* the stuff below is only used at initialization time */
/* hash used during ctx initialization */
SCACTilePattern **init_hash;
/* pattern arrays. We need this only during the goto table
creation phase */
SCACTilePattern **parray;
/* goto_table, failure table and output table. Needed to create
* state_table. Will be freed, once we have created the
* state_table */
int32_t (*goto_table)[256];
int32_t *failure_table;
/* no of states used by ac */
uint32_t state_count;
/* the size of each state */
uint16_t max_pat_id;
uint32_t alpha_hist[256];
uint16_t alphabet_size;
} SCACTileCtx;
typedef struct SCACTileThreadCtx_ {
/* the total calls we make to the search function */
uint32_t total_calls;
/* the total patterns that we ended up matching against */
uint64_t total_matches;
} SCACTileThreadCtx;
void MpmACTileRegister(void);
#endif /* __UTIL_MPM_AC_TILE__H__ */

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 Open Information Security Foundation
/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -36,6 +36,7 @@
#include "util-mpm-ac.h"
#include "util-mpm-ac-gfbs.h"
#include "util-mpm-ac-bs.h"
#include "util-mpm-ac-tile.h"
#include "util-hashlist.h"
#include "detect-engine.h"
@ -589,6 +590,7 @@ void MpmTableSetup(void) {
MpmACRegister();
MpmACBSRegister();
MpmACGfbsRegister();
MpmACTileRegister();
#ifdef __SC_CUDA_SUPPORT__
MpmACCudaRegister();
#endif /* __SC_CUDA_SUPPORT__ */

@ -71,10 +71,17 @@ enum {
/* aho-corasick-goto-failure state based */
MPM_AC_GFBS,
MPM_AC_BS,
MPM_AC_TILE,
/* table size */
MPM_TABLE_SIZE,
};
#ifdef __tile__
#define DEFAULT_MPM MPM_AC_TILE
#else
#define DEFAULT_MPM MPM_AC
#endif
typedef struct MpmMatchBucket_ {
uint32_t len;
} MpmMatchBucket;

Loading…
Cancel
Save