]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stats: Do not expand dots of tm_name
authorArne Welzel <arne.welzel@corelight.com>
Mon, 5 Feb 2024 16:45:30 +0000 (17:45 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Feb 2024 20:20:52 +0000 (21:20 +0100)
When an interface with dots is used, per worker stats are nested by the
dot-separated-components of the interface due to the usage of
OutputStats2Json().

Prevent this by using OutputStats2Json() on a per-thread specific object
and setting this object into the threads object using the
json_object_set_new() which won't do the dot expansion.

This was tested by creating an interface with dots in the name
and checking the stats.

    ip link add name a.b.c type dummy

With Suricata 7.0.2, sniffing on the a.b.c interface results in the
following worker stats format:

    "threads": {
      "W#01-a": {
        "b": {
          "c": {
            "capture": {
              "kernel_packets": 0,

After this fix, the output looks as follows:

    "threads": {
      "W#01-a.b.c": {
        "capture": {
          "kernel_packets": 0,

Ticket: #6732

src/output-json-stats.c

index 718298e4859293caae590dcc779ca82baba92ebc..0e0f7f7680c480b61dcc8b582292209dcfc184d7 100644 (file)
@@ -36,6 +36,7 @@
 #include "util-print.h"
 #include "util-time.h"
 #include "util-unittest.h"
+#include "util-validate.h"
 
 #include "util-debug.h"
 #include "output.h"
@@ -265,20 +266,30 @@ json_t *StatsToJSON(const StatsTable *st, uint8_t flags)
         for (x = 0; x < st->ntstats; x++) {
             uint32_t offset = x * st->nstats;
 
+            // Stats for for this thread.
+            json_t *thread = json_object();
+            if (unlikely(thread == NULL)) {
+                json_decref(js_stats);
+                json_decref(threads);
+                return NULL;
+            }
+
             /* for each counter */
             for (u = offset; u < (offset + st->nstats); u++) {
                 if (st->tstats[u].name == NULL)
                     continue;
 
+                // Seems this holds, but assert in debug builds.
+                DEBUG_VALIDATE_BUG_ON(
+                        strcmp(st->tstats[offset].tm_name, st->tstats[u].tm_name) != 0);
+
                 json_t *js_type = NULL;
                 const char *stat_name = st->tstats[u].short_name;
                 if (st->tstats[u].short_name == NULL) {
                     stat_name = st->tstats[u].name;
                     js_type = threads;
                 } else {
-                    char str[256];
-                    snprintf(str, sizeof(str), "%s.%s", st->tstats[u].tm_name, st->tstats[u].name);
-                    js_type = OutputStats2Json(threads, str);
+                    js_type = OutputStats2Json(thread, st->tstats[u].name);
                 }
 
                 if (js_type != NULL) {
@@ -292,6 +303,7 @@ json_t *StatsToJSON(const StatsTable *st, uint8_t flags)
                     }
                 }
             }
+            json_object_set_new(threads, st->tstats[offset].tm_name, thread);
         }
         json_object_set_new(js_stats, "threads", threads);
     }