]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
profiling: add 'ruleset-profile' unix command
authorEric Leblond <el@stamus-networks.com>
Fri, 11 Nov 2022 13:40:27 +0000 (14:40 +0100)
committerVictor Julien <vjulien@oisf.net>
Fri, 12 May 2023 17:52:15 +0000 (19:52 +0200)
This patch adds a new unix command that allows the user to trigger
a dump of the ruleset profile to the file without having to stop
Suricata.

This will be really useful to debug performance issue related to
signatures in production environment.

src/counters.c
src/flow-worker.c
src/threadvars.h
src/unix-manager.c
src/util-profiling-rules.c

index 0a6ace4bbb01b164aa30821f27d7b5762aee0f69..2b2100a3649f06e8e0d5fd351e46bb5aca551d8d 100644 (file)
@@ -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;
         }
index 9ecfe65f299ad46e24c7ee4197ef9693e302788c..4a8bd9b506b0eff52ebab7c3a3bfdfa60800b79b 100644 (file)
@@ -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;
 }
 
index ea448c0949864c0979867aa64e3790033f2b2196..6f16349fa28a61c37e64047e010c709f08d8720d 100644 (file)
@@ -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;
index ff4faccb4f8c91b094f20b84de85247725797833..7f43a9a6eae97715fa14e43c706a90479b9762cd 100644 (file)
@@ -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 <sys/un.h>
@@ -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);
index 5f5dcc126d50e7ddf035c489c6f93c090ecd7448..12c370bfe6df6aecabd517699e3bcee8cd56aff3 100644 (file)
@@ -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 */