]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: initial MT lookup logic
authorVictor Julien <victor@inliniac.net>
Thu, 29 Jan 2015 10:20:09 +0000 (11:20 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 23 Jul 2015 17:36:14 +0000 (19:36 +0200)
In the DetectEngineThreadCtx, store another DetectEngineThreadCtx per
tenant.

Currently it's just a simple array indexed by the tenant id.

src/detect-engine.c
src/detect-engine.h
src/detect.c
src/detect.h

index 48afc52b6a703c58baf5af5ffed3d8ce8ebf783f..b83e5e64759a03cd3d6d9e1285878d2fc27f36da 100644 (file)
@@ -105,6 +105,8 @@ static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *);
 
 static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER, NULL, NULL, };
 
+static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv);
+
 /* 2 - for each direction */
 DetectEngineAppInspectionEngine *app_inspection_engine[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
 
@@ -604,7 +606,10 @@ static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
 
             old_det_ctx[i] = SC_ATOMIC_GET(slots->slot_data);
             detect_tvs[i] = tv;
-            new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx);
+            if (new_de_ctx != NULL)
+                new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx);
+            else
+                new_det_ctx[i] = DetectEngineThreadCtxInitForMT(tv);
             if (new_det_ctx[i] == NULL) {
                 SCLogError(SC_ERR_LIVE_RULE_SWAP, "Detect engine thread init "
                            "failure in live rule swap.  Let's get out of here");
@@ -1450,6 +1455,19 @@ TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
         return TM_ECODE_OK;
     }
 
+    if (det_ctx->mt_det_ctxs != NULL) {
+        uint32_t x;
+        for (x = 0; x < det_ctx->mt_det_ctxs_cnt; x++) {
+            if (det_ctx->mt_det_ctxs[x] == NULL)
+                continue;
+
+            DetectEngineThreadCtxDeinit(tv, det_ctx->mt_det_ctxs[x]);
+            det_ctx->mt_det_ctxs[x] = NULL;
+        }
+        SCFree(det_ctx->mt_det_ctxs);
+        det_ctx->mt_det_ctxs = NULL;
+    }
+
 #ifdef PROFILING
     SCProfilingRuleThreadCleanup(det_ctx);
     SCProfilingKeywordThreadCleanup(det_ctx);
@@ -1858,6 +1876,81 @@ int DetectEngineReload(const char *filename)
     return 0;
 }
 
+/** NOTE: master MUST be locked before calling this */
+static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv)
+{
+    DetectEngineMasterCtx *master = &g_master_de_ctx;
+    int max_tenant_id = 0;
+    DetectEngineCtx *list = master->list;
+    while (list) {
+        if (list->tenant_id > max_tenant_id)
+            max_tenant_id = list->tenant_id;
+
+        list = list->next;
+    }
+
+    if (max_tenant_id == 0) {
+        SCLogInfo("no tenants left");
+        return NULL;
+    }
+
+    max_tenant_id++;
+
+    DetectEngineThreadCtx **tenant_det_ctxs = SCCalloc(max_tenant_id, sizeof(DetectEngineThreadCtx *));
+    BUG_ON(tenant_det_ctxs == NULL);
+
+    list = master->list;
+    while (list) {
+        if (list->tenant_id != 0) {
+            tenant_det_ctxs[list->tenant_id] = DetectEngineThreadCtxInitForReload(tv, list);
+            if (tenant_det_ctxs[list->tenant_id] == NULL)
+                goto error;
+        }
+        list = list->next;
+    }
+
+    DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
+    if (det_ctx == NULL) {
+        goto error;
+    }
+
+    det_ctx->mt_det_ctxs = tenant_det_ctxs;
+    det_ctx->mt_det_ctxs_cnt = max_tenant_id;
+
+    return det_ctx;
+error:
+    return NULL;
+}
+
+int DetectEngineMTApply(void)
+{
+    DetectEngineMasterCtx *master = &g_master_de_ctx;
+    SCMutexLock(&master->lock);
+
+    DetectEngineCtx *minimal_de_ctx = NULL;
+    /* if we have no tenants, we need a minimal on */
+    if (master->list == NULL) {
+        minimal_de_ctx = master->list = DetectEngineCtxInitMinimal();
+        SCLogDebug("no tenants, using minimal %p", minimal_de_ctx);
+    } else if (master->list->next == NULL && master->list->tenant_id == 0) {
+        minimal_de_ctx = master->list;
+        SCLogDebug("no tenants, using original %p", minimal_de_ctx);
+    }
+
+    /* update the threads */
+    SCLogDebug("MT reload starting");
+    DetectEngineReloadThreads(minimal_de_ctx);
+    SCLogDebug("MT reload done");
+
+    SCMutexUnlock(&master->lock);
+
+    /* walk free list, freeing the old_de_ctx */
+    DetectEnginePruneFreeList();
+
+    SCLogDebug("old_de_ctx should have been freed");
+    return 0;
+}
+
 const char *DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
 {
     switch (type) {
index 928f7887669e6314b8d6058ad9251120debaa6f3..01c0b858769ba705c1152d6fb1eb7bdeff831e44 100644 (file)
@@ -77,6 +77,7 @@ DetectEngineCtx *DetectEngineReference(DetectEngineCtx *);
 void DetectEngineDeReference(DetectEngineCtx **de_ctx);
 int DetectEngineReload(const char *filename);
 int DetectEngineEnabled(void);
+int DetectEngineMTApply(void);
 
 int DetectEngineReloadStart(void);
 int DetectEngineReloadIsStart(void);
index e98fd311db286665c7d885daa6f7e2aa51017ad7..66de27ac6c0f374adb18d9bf50d802a88c9118af 100644 (file)
@@ -1970,16 +1970,27 @@ TmEcode Detect(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQue
         goto error;
     }
 
+    if (SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0) {
+        (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
+        SCLogDebug("Detect Engine using new det_ctx - %p",
+                  det_ctx);
+    }
+
     DetectEngineCtx *de_ctx = det_ctx->de_ctx;
     if (de_ctx == NULL) {
-        printf("ERROR: Detect has no detection engine ctx\n");
-        goto error;
-    }
+        if (det_ctx->mt_det_ctxs == 0) {
+            printf("ERROR: Detect has no detection engine ctx\n");
+            goto error;
+        }
 
-    if (SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0) {
-        (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
-        SCLogDebug("Detect Engine using new det_ctx - %p and de_ctx - %p",
-                  det_ctx, de_ctx);
+        det_ctx = det_ctx->mt_det_ctxs[1];
+        BUG_ON(det_ctx == NULL);
+        de_ctx = det_ctx->de_ctx;
+        BUG_ON(de_ctx == NULL);
+        if (SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0) {
+            (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
+            SCLogDebug("MT de_ctx %p det_ctx %p", de_ctx, det_ctx);
+        }
     }
 
     /* see if the packet matches one or more of the sigs */
index 05c31d65d6c28433ba4c4552981613820de9dc39..7cca9ffe265028c10fe5ff42d0d341db84b8151a 100644 (file)
@@ -766,6 +766,9 @@ typedef struct DetectEngineThreadCtx_ {
     SigIntId *non_mpm_id_array;
     uint32_t non_mpm_id_cnt; // size is cnt * sizeof(uint32_t)
 
+    uint32_t mt_det_ctxs_cnt;
+    struct DetectEngineThreadCtx_ **mt_det_ctxs;
+
     /* detection engine variables */
 
     /** offset into the payload of the last match by: