]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: initialization optimization
authorVictor Julien <vjulien@oisf.net>
Thu, 31 Mar 2022 16:00:57 +0000 (18:00 +0200)
committerVictor Julien <vjulien@oisf.net>
Mon, 4 Apr 2022 15:15:33 +0000 (17:15 +0200)
A lot of time was spent in `SigMatchListSMBelongsTo` for the `mpm_sm`.

Optimize this by keeping the value at hand during Signature parsing and
detection engine setup.

src/detect-engine-analyzer.c
src/detect-engine-build.c
src/detect-engine-mpm.c
src/detect-engine.c
src/detect-parse.c
src/detect.h

index 8a95481ded2bb94ab751115602d7ca7e7db3b267..dce2f8061a8e4bd222553caec2f613c916d9006f 100644 (file)
@@ -153,8 +153,9 @@ void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *l
     int fast_pattern_set = 0;
     int fast_pattern_only_set = 0;
     int fast_pattern_chop_set = 0;
-    DetectContentData *fp_cd = NULL;
-    SigMatch *mpm_sm = s->init_data->mpm_sm;
+    const DetectContentData *fp_cd = NULL;
+    const SigMatch *mpm_sm = s->init_data->mpm_sm;
+    const int mpm_sm_list = s->init_data->mpm_sm_list;
 
     if (mpm_sm != NULL) {
         fp_cd = (DetectContentData *)mpm_sm->ctx;
@@ -186,7 +187,7 @@ void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *l
     }
 
     fprintf(fp_engine_analysis_FD, "        Fast pattern matcher: ");
-    int list_type = SigMatchListSMBelongsTo(s, mpm_sm);
+    int list_type = mpm_sm_list;
     if (list_type == DETECT_SM_LIST_PMATCH)
         fprintf(fp_engine_analysis_FD, "content\n");
     else {
@@ -473,8 +474,9 @@ int PerCentEncodingMatch (uint8_t *content, uint8_t content_len)
 
 static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Signature *s)
 {
-    DetectContentData *fp_cd = NULL;
-    SigMatch *mpm_sm = s->init_data->mpm_sm;
+    const DetectContentData *fp_cd = NULL;
+    const SigMatch *mpm_sm = s->init_data->mpm_sm;
+    const int mpm_sm_list = s->init_data->mpm_sm_list;
 
     if (mpm_sm != NULL) {
         fp_cd = (DetectContentData *)mpm_sm->ctx;
@@ -511,7 +513,7 @@ static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Sign
 
     fprintf(rule_engine_analysis_FD, "\" on \"");
 
-    int list_type = SigMatchListSMBelongsTo(s, mpm_sm);
+    const int list_type = mpm_sm_list;
     if (list_type == DETECT_SM_LIST_PMATCH) {
         int payload = 0;
         int stream = 0;
@@ -1559,7 +1561,7 @@ void EngineAnalysisRules(const DetectEngineCtx *de_ctx,
         warn_offset_depth_alproto = 1;
     }
     if (s->init_data->mpm_sm != NULL && s->alproto == ALPROTO_HTTP1 &&
-            SigMatchListSMBelongsTo(s, s->init_data->mpm_sm) == DETECT_SM_LIST_PMATCH) {
+            s->init_data->mpm_sm_list == DETECT_SM_LIST_PMATCH) {
         rule_warning += 1;
         warn_non_alproto_fp_for_alproto_sig = 1;
     }
index 594e996087edbefa5d7ddbea4c0034983b7930e4..0c969f02337741098ad99677a257277882420d61 100644 (file)
@@ -607,7 +607,7 @@ static int RuleGetMpmPatternSize(const Signature *s)
 {
     if (s->init_data->mpm_sm == NULL)
         return -1;
-    int mpm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+    int mpm_list = s->init_data->mpm_sm_list;
     if (mpm_list < 0)
         return -1;
     const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
@@ -620,7 +620,7 @@ static int RuleMpmIsNegated(const Signature *s)
 {
     if (s->init_data->mpm_sm == NULL)
         return 0;
-    int mpm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+    int mpm_list = s->init_data->mpm_sm_list;
     if (mpm_list < 0)
         return 0;
     const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
@@ -723,7 +723,7 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG
             }
 
         } else {
-            int mpm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+            int mpm_list = s->init_data->mpm_sm_list;
             BUG_ON(mpm_list < 0);
             const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
             uint32_t size = cd->content_len < 256 ? cd->content_len : 255;
@@ -1150,15 +1150,13 @@ static int RuleSetWhitelist(Signature *s)
 
             /* one byte pattern in packet/stream payloads */
         } else if (s->init_data->mpm_sm != NULL &&
-                   SigMatchListSMBelongsTo(s, s->init_data->mpm_sm) == DETECT_SM_LIST_PMATCH &&
-                   RuleGetMpmPatternSize(s) == 1)
-        {
+                   s->init_data->mpm_sm_list == DETECT_SM_LIST_PMATCH &&
+                   RuleGetMpmPatternSize(s) == 1) {
             SCLogDebug("Rule %u No MPM. Payload inspecting. Whitelisting SGH's.", s->id);
             wl = 55;
 
         } else if (DetectFlagsSignatureNeedsSynPackets(s) &&
-                   DetectFlagsSignatureNeedsSynOnlyPackets(s))
-        {
+                   DetectFlagsSignatureNeedsSynOnlyPackets(s)) {
             SCLogDebug("Rule %u Needs SYN, so inspected often. Whitelisting SGH's.", s->id);
             wl = 33;
         }
index 5b11b88f64f9e6eb975b2ef6e720d4678d852290..2af7df9439dffc295fa1b69e48102121ca641d46 100644 (file)
@@ -1012,7 +1012,7 @@ static void PopulateMpmHelperAddPattern(MpmCtx *mpm_ctx,
 #define SGH_DIRECTION_TS(sgh) ((sgh)->init->direction & SIG_FLAG_TOSERVER)
 #define SGH_DIRECTION_TC(sgh) ((sgh)->init->direction & SIG_FLAG_TOCLIENT)
 
-static void SetMpm(Signature *s, SigMatch *mpm_sm)
+static void SetMpm(Signature *s, SigMatch *mpm_sm, const int mpm_sm_list)
 {
     if (s == NULL || mpm_sm == NULL)
         return;
@@ -1035,6 +1035,7 @@ static void SetMpm(Signature *s, SigMatch *mpm_sm)
         }
     }
     cd->flags |= DETECT_CONTENT_MPM;
+    s->init_data->mpm_sm_list = mpm_sm_list;
     s->init_data->mpm_sm = mpm_sm;
     return;
 }
@@ -1080,7 +1081,7 @@ void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
     if (s->init_data->mpm_sm != NULL)
         return;
 
-    SigMatch *mpm_sm = NULL, *sm = NULL;
+    SigMatch *sm = NULL;
     const int nlists = s->init_data->smlists_array_size;
     int nn_sm_list[nlists];
     int n_sm_list[nlists];
@@ -1105,7 +1106,7 @@ void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
             const DetectContentData *cd = (DetectContentData *)sm->ctx;
             /* fast_pattern set in rule, so using this pattern */
             if ((cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
-                SetMpm(s, sm);
+                SetMpm(s, sm, list_id);
                 return;
             }
 
@@ -1175,15 +1176,29 @@ void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
         }
     }
 
+    SigMatch *mpm_sm = NULL;
+    int mpm_sm_list = -1;
     for (int i = 0; i < count_final_sm_list; i++) {
         if (final_sm_list[i] >= (int)s->init_data->smlists_array_size)
             continue;
 
+        /* GetMpmForList may keep `mpm_sm` the same, so track if it changed */
+        SigMatch *prev_mpm_sm = mpm_sm;
         mpm_sm = GetMpmForList(s, final_sm_list[i], mpm_sm, max_len, skip_negated_content);
+        if (mpm_sm != prev_mpm_sm) {
+            mpm_sm_list = final_sm_list[i];
+        }
     }
 
+#ifdef DEBUG
+    if (mpm_sm != NULL) {
+        BUG_ON(mpm_sm_list == -1);
+        int check_list = SigMatchListSMBelongsTo(s, mpm_sm);
+        BUG_ON(check_list != mpm_sm_list);
+    }
+#endif
     /* assign to signature */
-    SetMpm(s, mpm_sm);
+    SetMpm(s, mpm_sm, mpm_sm_list);
     return;
 }
 
@@ -1500,7 +1515,7 @@ static void MpmStoreSetup(const DetectEngineCtx *de_ctx, MpmStore *ms)
             }
             if (s->init_data->mpm_sm == NULL)
                 continue;
-            int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+            int list = s->init_data->mpm_sm_list;
             if (list < 0)
                 continue;
             if (list != ms->sm_list)
@@ -1609,7 +1624,7 @@ MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
         if (s->init_data->mpm_sm == NULL)
             continue;
 
-        int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+        int list = s->init_data->mpm_sm_list;
         if (list < 0)
             continue;
 
@@ -1704,7 +1719,7 @@ static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx,
         if ((s->flags & am->direction) == 0)
             continue;
 
-        int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+        int list = s->init_data->mpm_sm_list;
         if (list < 0)
             continue;
 
@@ -1778,7 +1793,7 @@ static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx,
         if (s->init_data->mpm_sm == NULL)
             continue;
 
-        int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+        int list = s->init_data->mpm_sm_list;
         if (list < 0)
             continue;
 
@@ -1851,7 +1866,7 @@ static MpmStore *MpmStorePrepareBufferFrame(
         if ((s->flags & am->direction) == 0)
             continue;
 
-        int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+        int list = s->init_data->mpm_sm_list;
         if (list < 0)
             continue;
 
@@ -2134,7 +2149,7 @@ int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx)
 
     for (s = de_ctx->sig_list; s != NULL; s = s->next) {
         if (s->init_data->mpm_sm != NULL) {
-            int sm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
+            int sm_list = s->init_data->mpm_sm_list;
             BUG_ON(sm_list == -1);
 
             DetectContentData *cd = (DetectContentData *)s->init_data->mpm_sm->ctx;
index c4cad38678d272cba90f4debcd5dd2c3b5566d78..085b400ae274f84f652358d8d25753bca485e9e0 100644 (file)
@@ -538,7 +538,7 @@ static void AppendStreamInspectEngine(Signature *s, SigMatchData *stream, int di
     if (unlikely(new_engine == NULL)) {
         exit(EXIT_FAILURE);
     }
-    if (SigMatchListSMBelongsTo(s, s->init_data->mpm_sm) == DETECT_SM_LIST_PMATCH) {
+    if (s->init_data->mpm_sm_list == DETECT_SM_LIST_PMATCH) {
         SCLogDebug("stream is mpm");
         prepend = true;
         new_engine->mpm = true;
@@ -583,9 +583,7 @@ int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature
     SigMatchData *ptrs[nlists];
     memset(&ptrs, 0, (nlists * sizeof(SigMatchData *)));
 
-    const int mpm_list = s->init_data->mpm_sm ?
-        SigMatchListSMBelongsTo(s, s->init_data->mpm_sm) :
-        -1;
+    const int mpm_list = s->init_data->mpm_sm ? s->init_data->mpm_sm_list : -1;
 
     const int files_id = DetectBufferTypeGetByName("files");
 
@@ -1830,7 +1828,7 @@ static int DetectEnginePktInspectionAppend(Signature *s, InspectionBufferPktInsp
     if (e == NULL)
         return -1;
 
-    e->mpm = (SigMatchListSMBelongsTo(s, s->init_data->mpm_sm) == list_id);
+    e->mpm = s->init_data->mpm_sm_list == list_id;
     e->sm_list = list_id;
     e->sm_list_base = list_id;
     e->v1.Callback = Callback;
index e52a20aae121335c9679560c2b284c46177f1f0c..c0cc098b6ed81d55eca2f6e53d6408eb25261583 100644 (file)
@@ -1273,6 +1273,7 @@ Signature *SigAlloc (void)
         SCFree(sig);
         return NULL;
     }
+    sig->init_data->mpm_sm_list = -1;
 
     sig->init_data->smlists_array_size = DetectBufferTypeMaxId();
     SCLogDebug("smlists size %u", sig->init_data->smlists_array_size);
index 215118db4d6d855e835159cb8b02258feb3c255d..c55c48ddee564698da7ddaec1bf5d02875c07bad 100644 (file)
@@ -514,6 +514,8 @@ typedef struct SignatureInitData_ {
     /* used at init to determine max dsize */
     SigMatch *dsize_sm;
 
+    /* list id for `mpm_sm`. Should always match `SigMatchListSMBelongsTo(s, mpm_sm)`. */
+    int mpm_sm_list;
     /* the fast pattern added from this signature */
     SigMatch *mpm_sm;
     /* used to speed up init of prefilter */