From: Victor Julien Date: Thu, 29 Jan 2015 10:20:09 +0000 (+0100) Subject: detect: initial MT lookup logic X-Git-Tag: suricata-3.0RC1~225 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=def2b58725e6876abecceccecb096ba005eb34bc;p=thirdparty%2Fsuricata.git detect: initial MT lookup logic In the DetectEngineThreadCtx, store another DetectEngineThreadCtx per tenant. Currently it's just a simple array indexed by the tenant id. --- diff --git a/src/detect-engine.c b/src/detect-engine.c index 48afc52b6a..b83e5e6475 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -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) { diff --git a/src/detect-engine.h b/src/detect-engine.h index 928f788766..01c0b85876 100644 --- a/src/detect-engine.h +++ b/src/detect-engine.h @@ -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); diff --git a/src/detect.c b/src/detect.c index e98fd311db..66de27ac6c 100644 --- a/src/detect.c +++ b/src/detect.c @@ -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 */ diff --git a/src/detect.h b/src/detect.h index 05c31d65d6..7cca9ffe26 100644 --- a/src/detect.h +++ b/src/detect.h @@ -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: