detect: split non-mpm list into syn/nosyn

Since SYN inspecting rules are expensive, this patch splits the
'non-mpm' list (i.e. the rules that are always considered) into
a 'syn' and 'non-syn' list. The SYN list is only inspected if the
packet has the SYN flag set, otherwise the non-syn list is used.

The syn-list contains _all_ rules. The non-syn list contains all
minus the rules requiring the SYN bit in a packet.
pull/1980/head
Victor Julien 10 years ago
parent e48d745ed7
commit 2ce03fbabb

@ -39,6 +39,7 @@
#include "detect-content.h" #include "detect-content.h"
#include "detect-uricontent.h" #include "detect-uricontent.h"
#include "detect-flags.h"
#include "util-hash.h" #include "util-hash.h"
#include "util-hashlist.h" #include "util-hashlist.h"
@ -180,10 +181,16 @@ void SigGroupHeadFree(SigGroupHead *sgh)
sgh->match_array = NULL; sgh->match_array = NULL;
} }
if (sgh->non_mpm_store_array != NULL) { if (sgh->non_mpm_other_store_array != NULL) {
SCFree(sgh->non_mpm_store_array); SCFree(sgh->non_mpm_other_store_array);
sgh->non_mpm_store_array = NULL; sgh->non_mpm_other_store_array = NULL;
sgh->non_mpm_store_cnt = 0; sgh->non_mpm_other_store_cnt = 0;
}
if (sgh->non_mpm_syn_store_array != NULL) {
SCFree(sgh->non_mpm_syn_store_array);
sgh->non_mpm_syn_store_array = NULL;
sgh->non_mpm_syn_store_cnt = 0;
} }
sgh->sig_cnt = 0; sgh->sig_cnt = 0;
@ -957,53 +964,64 @@ int SigGroupHeadBuildNonMpmArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Signature *s = NULL; Signature *s = NULL;
uint32_t sig = 0; uint32_t sig = 0;
uint32_t non_mpm = 0; uint32_t non_mpm = 0;
uint32_t non_mpm_syn = 0;
if (sgh == NULL) if (sgh == NULL)
return 0; return 0;
BUG_ON(sgh->non_mpm_store_array != NULL); BUG_ON(sgh->non_mpm_other_store_array != NULL);
for (sig = 0; sig < sgh->sig_cnt; sig++) { for (sig = 0; sig < sgh->sig_cnt; sig++) {
s = sgh->match_array[sig]; s = sgh->match_array[sig];
if (s == NULL) if (s == NULL)
continue; continue;
if (s->mpm_sm == NULL) if (s->mpm_sm == NULL || (s->flags & (SIG_FLAG_MPM_PACKET_NEG|SIG_FLAG_MPM_STREAM_NEG|SIG_FLAG_MPM_APPLAYER_NEG))) {
non_mpm++; if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
else if (s->flags & (SIG_FLAG_MPM_PACKET_NEG|SIG_FLAG_MPM_STREAM_NEG|SIG_FLAG_MPM_APPLAYER_NEG)) non_mpm++;
non_mpm++; }
non_mpm_syn++;
}
} }
if (non_mpm == 0) { if (non_mpm == 0 && non_mpm_syn == 0) {
sgh->non_mpm_store_array = NULL; sgh->non_mpm_other_store_array = NULL;
sgh->non_mpm_syn_store_array = NULL;
return 0; return 0;
} }
sgh->non_mpm_store_array = SCMalloc(non_mpm * sizeof(SignatureNonMpmStore)); sgh->non_mpm_other_store_array = SCMalloc(non_mpm * sizeof(SignatureNonMpmStore));
BUG_ON(sgh->non_mpm_store_array == NULL); BUG_ON(sgh->non_mpm_other_store_array == NULL);
memset(sgh->non_mpm_store_array, 0, non_mpm * sizeof(SignatureNonMpmStore)); memset(sgh->non_mpm_other_store_array, 0, non_mpm * sizeof(SignatureNonMpmStore));
sgh->non_mpm_syn_store_array = SCMalloc(non_mpm_syn * sizeof(SignatureNonMpmStore));
BUG_ON(sgh->non_mpm_syn_store_array == NULL);
memset(sgh->non_mpm_syn_store_array, 0, non_mpm_syn * sizeof(SignatureNonMpmStore));
for (sig = 0; sig < sgh->sig_cnt; sig++) { for (sig = 0; sig < sgh->sig_cnt; sig++) {
s = sgh->match_array[sig]; s = sgh->match_array[sig];
if (s == NULL) if (s == NULL)
continue; continue;
if (s->mpm_sm == NULL) { if (s->mpm_sm == NULL || (s->flags & (SIG_FLAG_MPM_PACKET_NEG|SIG_FLAG_MPM_STREAM_NEG|SIG_FLAG_MPM_APPLAYER_NEG))) {
BUG_ON(sgh->non_mpm_store_cnt >= non_mpm); if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
sgh->non_mpm_store_array[sgh->non_mpm_store_cnt].id = s->num; BUG_ON(sgh->non_mpm_other_store_cnt >= non_mpm);
sgh->non_mpm_store_array[sgh->non_mpm_store_cnt].mask = s->mask; sgh->non_mpm_other_store_array[sgh->non_mpm_other_store_cnt].id = s->num;
sgh->non_mpm_store_cnt++; sgh->non_mpm_other_store_array[sgh->non_mpm_other_store_cnt].mask = s->mask;
} else if (s->flags & (SIG_FLAG_MPM_PACKET_NEG|SIG_FLAG_MPM_STREAM_NEG|SIG_FLAG_MPM_APPLAYER_NEG)) { sgh->non_mpm_other_store_cnt++;
BUG_ON(sgh->non_mpm_store_cnt >= non_mpm); }
sgh->non_mpm_store_array[sgh->non_mpm_store_cnt].id = s->num;
sgh->non_mpm_store_array[sgh->non_mpm_store_cnt].mask = s->mask; BUG_ON(sgh->non_mpm_syn_store_cnt >= non_mpm_syn);
sgh->non_mpm_store_cnt++; sgh->non_mpm_syn_store_array[sgh->non_mpm_syn_store_cnt].id = s->num;
sgh->non_mpm_syn_store_array[sgh->non_mpm_syn_store_cnt].mask = s->mask;
sgh->non_mpm_syn_store_cnt++;
} }
} }
/* track highest cnt for any sgh in our de_ctx */ /* track highest cnt for any sgh in our de_ctx */
if (sgh->non_mpm_store_cnt > de_ctx->non_mpm_store_cnt_max) uint32_t max = MAX(sgh->non_mpm_other_store_cnt, sgh->non_mpm_syn_store_cnt);
de_ctx->non_mpm_store_cnt_max = sgh->non_mpm_store_cnt; if (max > de_ctx->non_mpm_store_cnt_max)
de_ctx->non_mpm_store_cnt_max = max;
return 0; return 0;
} }

@ -1213,16 +1213,34 @@ static void AlertDebugLogModeSyncFlowbitsNamesToPacketStruct(Packet *p, DetectEn
static inline void DetectPrefilterBuildNonMpmList(DetectEngineThreadCtx *det_ctx, SignatureMask mask) static inline void DetectPrefilterBuildNonMpmList(DetectEngineThreadCtx *det_ctx, SignatureMask mask)
{ {
uint32_t x = 0; uint32_t x = 0;
for (x = 0; x < det_ctx->sgh->non_mpm_store_cnt; x++) { for (x = 0; x < det_ctx->non_mpm_store_cnt; x++) {
/* only if the mask matches this rule can possibly match, /* only if the mask matches this rule can possibly match,
* so build the non_mpm array only for match candidates */ * so build the non_mpm array only for match candidates */
SignatureMask rule_mask = det_ctx->sgh->non_mpm_store_array[x].mask; SignatureMask rule_mask = det_ctx->non_mpm_store_ptr[x].mask;
if ((rule_mask & mask) == rule_mask) { if ((rule_mask & mask) == rule_mask) {
det_ctx->non_mpm_id_array[det_ctx->non_mpm_id_cnt++] = det_ctx->sgh->non_mpm_store_array[x].id; det_ctx->non_mpm_id_array[det_ctx->non_mpm_id_cnt++] = det_ctx->non_mpm_store_ptr[x].id;
} }
} }
} }
/** \internal
* \brief select non-mpm list
* Based on the packet properties, select the non-mpm list to use */
static inline void DetectPrefilterSetNonMpmList(const Packet *p, DetectEngineThreadCtx *det_ctx)
{
if ((p->proto == IPPROTO_TCP) && (p->tcph != NULL) && (p->tcph->th_flags & TH_SYN)) {
det_ctx->non_mpm_store_ptr = det_ctx->sgh->non_mpm_syn_store_array;
det_ctx->non_mpm_store_cnt = det_ctx->sgh->non_mpm_syn_store_cnt;
} else {
det_ctx->non_mpm_store_ptr = det_ctx->sgh->non_mpm_other_store_array;
det_ctx->non_mpm_store_cnt = det_ctx->sgh->non_mpm_other_store_cnt;
}
SCLogDebug("sgh non_mpm ptr %p cnt %u (syn %p/%u, other %p/%u)",
det_ctx->non_mpm_store_ptr, det_ctx->non_mpm_store_cnt,
det_ctx->sgh->non_mpm_syn_store_array, det_ctx->sgh->non_mpm_syn_store_cnt,
det_ctx->sgh->non_mpm_other_store_array, det_ctx->sgh->non_mpm_other_store_cnt);
}
/** /**
* \brief Signature match function * \brief Signature match function
* *
@ -1429,6 +1447,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
goto end; goto end;
} }
DetectPrefilterSetNonMpmList(p, det_ctx);
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_STATEFUL); PACKET_PROFILING_DETECT_START(p, PROF_DETECT_STATEFUL);
/* stateful app layer detection */ /* stateful app layer detection */
if ((p->flags & PKT_HAS_FLOW) && has_state) { if ((p->flags & PKT_HAS_FLOW) && has_state) {
@ -1452,7 +1472,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
/* build and prefilter non_mpm list against the mask of the packet */ /* build and prefilter non_mpm list against the mask of the packet */
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_NONMPMLIST); PACKET_PROFILING_DETECT_START(p, PROF_DETECT_NONMPMLIST);
det_ctx->non_mpm_id_cnt = 0; det_ctx->non_mpm_id_cnt = 0;
if (likely(det_ctx->sgh->non_mpm_store_cnt > 0)) { if (likely(det_ctx->non_mpm_store_cnt > 0)) {
DetectPrefilterBuildNonMpmList(det_ctx, mask); DetectPrefilterBuildNonMpmList(det_ctx, mask);
} }
PACKET_PROFILING_DETECT_END(p, PROF_DETECT_NONMPMLIST); PACKET_PROFILING_DETECT_END(p, PROF_DETECT_NONMPMLIST);
@ -1466,7 +1486,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
StatsAddUI64(th_v, det_ctx->counter_mpm_list, StatsAddUI64(th_v, det_ctx->counter_mpm_list,
(uint64_t)det_ctx->pmq.rule_id_array_cnt); (uint64_t)det_ctx->pmq.rule_id_array_cnt);
StatsAddUI64(th_v, det_ctx->counter_nonmpm_list, StatsAddUI64(th_v, det_ctx->counter_nonmpm_list,
(uint64_t)det_ctx->sgh->non_mpm_store_cnt); (uint64_t)det_ctx->non_mpm_store_cnt);
/* non mpm sigs after mask prefilter */ /* non mpm sigs after mask prefilter */
StatsAddUI64(th_v, det_ctx->counter_fnonmpm_list, StatsAddUI64(th_v, det_ctx->counter_fnonmpm_list,
(uint64_t)det_ctx->non_mpm_id_cnt); (uint64_t)det_ctx->non_mpm_id_cnt);

@ -736,6 +736,11 @@ typedef struct FiledataReassembledBody_ {
/** \todo review how many we actually need here */ /** \todo review how many we actually need here */
#define DETECT_SMSG_PMQ_NUM 256 #define DETECT_SMSG_PMQ_NUM 256
typedef struct SignatureNonMpmStore_ {
SigIntId id;
SignatureMask mask;
} SignatureNonMpmStore;
/** /**
* Detection engine thread data. * Detection engine thread data.
*/ */
@ -832,6 +837,10 @@ typedef struct DetectEngineThreadCtx_ {
uint8_t *de_state_sig_array; uint8_t *de_state_sig_array;
struct SigGroupHead_ *sgh; struct SigGroupHead_ *sgh;
SignatureNonMpmStore *non_mpm_store_ptr;
uint32_t non_mpm_store_cnt;
/** pointer to the current mpm ctx that is stored /** pointer to the current mpm ctx that is stored
* in a rule group head -- can be either a content * in a rule group head -- can be either a content
* or uricontent ctx. */ * or uricontent ctx. */
@ -983,11 +992,6 @@ typedef struct SigGroupHeadInitData_ {
struct DetectPort_ *port; struct DetectPort_ *port;
} SigGroupHeadInitData; } SigGroupHeadInitData;
typedef struct SignatureNonMpmStore_ {
SigIntId id;
SignatureMask mask;
} SignatureNonMpmStore;
/** \brief Container for matching data for a signature group */ /** \brief Container for matching data for a signature group */
typedef struct SigGroupHead_ { typedef struct SigGroupHead_ {
uint32_t flags; uint32_t flags;
@ -1003,8 +1007,12 @@ typedef struct SigGroupHead_ {
SignatureMask *mask_array; SignatureMask *mask_array;
#endif #endif
SignatureNonMpmStore *non_mpm_store_array; // size is non_mpm_store_cnt * sizeof(SignatureNonMpmStore) /* non mpm list excluding SYN rules */
uint32_t non_mpm_store_cnt; SignatureNonMpmStore *non_mpm_other_store_array; // size is non_mpm_store_cnt * sizeof(SignatureNonMpmStore)
uint32_t non_mpm_other_store_cnt;
/* non mpm list including SYN rules */
SignatureNonMpmStore *non_mpm_syn_store_array; // size is non_mpm_syn_store_cnt * sizeof(SignatureNonMpmStore)
uint32_t non_mpm_syn_store_cnt;
/* pattern matcher instances */ /* pattern matcher instances */
const MpmCtx *mpm_proto_other_ctx; const MpmCtx *mpm_proto_other_ctx;

Loading…
Cancel
Save