diff --git a/src/counters.c b/src/counters.c index 0a6ace4bbb..2b2100a364 100644 --- a/src/counters.c +++ b/src/counters.c @@ -512,6 +512,7 @@ static void *StatsWakeupThread(void *arg) /* assuming the assignment of an int to be atomic, and even if it's * not, it should be okay */ tv->perf_public_ctx.perf_flag = 1; + tv->profile_flag = 1; if (tv->inq != NULL) { PacketQueue *q = tv->inq->pq; @@ -532,6 +533,7 @@ static void *StatsWakeupThread(void *arg) /* assuming the assignment of an int to be atomic, and even if it's * not, it should be okay */ tv->perf_public_ctx.perf_flag = 1; + tv->profile_flag = 1; tv = tv->next; } diff --git a/src/flow-worker.c b/src/flow-worker.c index 9ecfe65f29..4a8bd9b506 100644 --- a/src/flow-worker.c +++ b/src/flow-worker.c @@ -614,6 +614,14 @@ housekeeping: /* process local work queue */ FlowWorkerProcessLocalFlows(tv, fw, p); +#ifdef PROFILE_RULES + /* aggregate statistics */ + if (tv->profile_flag == 1) { + SCProfilingRuleThreatAggregate((DetectEngineThreadCtx *)detect_thread); + tv->profile_flag = 0; + } +#endif + return TM_ECODE_OK; } diff --git a/src/threadvars.h b/src/threadvars.h index ea448c0949..6f16349fa2 100644 --- a/src/threadvars.h +++ b/src/threadvars.h @@ -127,6 +127,9 @@ typedef struct ThreadVars_ { /** public counter store: counter syncs update this */ StatsPublicThreadContext perf_public_ctx; + /** profile sync needed */ + uint32_t profile_flag; + /* mutex and condition used by management threads */ SCCtrlMutex *ctrl_mutex; diff --git a/src/unix-manager.c b/src/unix-manager.c index ff4faccb4f..7f43a9a6ea 100644 --- a/src/unix-manager.c +++ b/src/unix-manager.c @@ -40,6 +40,7 @@ #include "util-signal.h" #include "util-buffer.h" #include "util-path.h" +#include "util-profiling.h" #if (defined BUILD_UNIX_SOCKET) && (defined HAVE_SYS_UN_H) && (defined HAVE_SYS_STAT_H) && (defined HAVE_SYS_TYPES_H) #include @@ -779,6 +780,19 @@ static TmEcode UnixManagerRulesetStatsCommand(json_t *cmd, SCReturnInt(retval); } +#ifdef PROFILE_RULES +static TmEcode UnixManagerRulesetProfileCommand(json_t *cmd, json_t *server_msg, void *data) +{ + SCEnter(); + TmEcode retval; + DetectEngineCtx *de_ctx = DetectEngineGetCurrent(); + + retval = SCProfileRuleTriggerDump(de_ctx); + json_object_set_new(server_msg, "message", json_string("OK")); + SCReturnInt(retval); +} +#endif + static TmEcode UnixManagerShowFailedRules(json_t *cmd, json_t *server_msg, void *data) { @@ -1055,6 +1069,9 @@ int UnixManagerInit(void) UnixManagerRegisterCommand("ruleset-reload-time", UnixManagerReloadTimeCommand, NULL, 0); UnixManagerRegisterCommand("ruleset-stats", UnixManagerRulesetStatsCommand, NULL, 0); UnixManagerRegisterCommand("ruleset-failed-rules", UnixManagerShowFailedRules, NULL, 0); +#ifdef PROFILE_RULES + UnixManagerRegisterCommand("ruleset-profile", UnixManagerRulesetProfileCommand, NULL, 0); +#endif UnixManagerRegisterCommand("register-tenant-handler", UnixSocketRegisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS); UnixManagerRegisterCommand("unregister-tenant-handler", UnixSocketUnregisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS); UnixManagerRegisterCommand("register-tenant", UnixSocketRegisterTenant, &command, UNIX_CMD_TAKE_ARGS); diff --git a/src/util-profiling-rules.c b/src/util-profiling-rules.c index 5f5dcc126d..12c370bfe6 100644 --- a/src/util-profiling-rules.c +++ b/src/util-profiling-rules.c @@ -581,10 +581,11 @@ void SCProfilingRuleThreadSetup(SCProfileDetectCtx *ctx, DetectEngineThreadCtx * } } -static void SCProfilingRuleThreadMerge(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx) +static void SCProfilingRuleThreadMerge( + DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, int reset) { if (de_ctx == NULL || de_ctx->profile_ctx == NULL || de_ctx->profile_ctx->data == NULL || - det_ctx == NULL || det_ctx->rule_perf_data == NULL) + det_ctx == NULL || det_ctx->rule_perf_data == NULL) return; int i; @@ -593,6 +594,12 @@ static void SCProfilingRuleThreadMerge(DetectEngineCtx *de_ctx, DetectEngineThre de_ctx->profile_ctx->data[i].matches += det_ctx->rule_perf_data[i].matches; de_ctx->profile_ctx->data[i].ticks_match += det_ctx->rule_perf_data[i].ticks_match; de_ctx->profile_ctx->data[i].ticks_no_match += det_ctx->rule_perf_data[i].ticks_no_match; + if (reset) { + det_ctx->rule_perf_data[i].checks = 0; + det_ctx->rule_perf_data[i].matches = 0; + det_ctx->rule_perf_data[i].ticks_match = 0; + det_ctx->rule_perf_data[i].ticks_no_match = 0; + } if (det_ctx->rule_perf_data[i].max > de_ctx->profile_ctx->data[i].max) de_ctx->profile_ctx->data[i].max = det_ctx->rule_perf_data[i].max; } @@ -604,7 +611,7 @@ void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx *det_ctx) return; pthread_mutex_lock(&det_ctx->de_ctx->profile_ctx->data_m); - SCProfilingRuleThreadMerge(det_ctx->de_ctx, det_ctx); + SCProfilingRuleThreadMerge(det_ctx->de_ctx, det_ctx, 0); pthread_mutex_unlock(&det_ctx->de_ctx->profile_ctx->data_m); SCFree(det_ctx->rule_perf_data); @@ -612,6 +619,16 @@ void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx *det_ctx) det_ctx->rule_perf_data_size = 0; } +void SCProfilingRuleThreatAggregate(DetectEngineThreadCtx *det_ctx) +{ + + if (det_ctx == NULL || det_ctx->de_ctx == NULL || det_ctx->de_ctx->profile_ctx == NULL) + return; + pthread_mutex_lock(&det_ctx->de_ctx->profile_ctx->data_m); + SCProfilingRuleThreadMerge(det_ctx->de_ctx, det_ctx, 1); + pthread_mutex_unlock(&det_ctx->de_ctx->profile_ctx->data_m); +} + /** * \brief Register the rule profiling counters. * @@ -651,5 +668,11 @@ SCProfilingRuleInitCounters(DetectEngineCtx *de_ctx) SCLogPerf("Registered %"PRIu32" rule profiling counters.", count); } +int SCProfileRuleTriggerDump(DetectEngineCtx *de_ctx) +{ + SCProfilingRuleDump(de_ctx->profile_ctx); + return TM_ECODE_OK; +} + #endif /* PROFILING */