suricata
counters.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  * \author Victor Julien <victor@inliniac.net>
23  *
24  * Engine stats API
25  */
26 
27 #include "suricata-common.h"
28 #include "counters.h"
29 
30 #include "suricata.h"
31 #include "threadvars.h"
32 
33 #include "output.h"
34 #include "output-json-stats.h"
35 
36 #include "util-byte.h"
37 #include "util-conf.h"
38 #include "util-hash.h"
39 #include "util-time.h"
40 
41 #include "tm-threads.h"
42 #include "util-privs.h"
43 
44 /* Time interval for syncing the local counters with the global ones */
45 #define STATS_WUT_TTS 3
46 
47 /* Time interval at which the mgmt thread o/p the stats */
48 #define STATS_MGMTT_TTS 8
49 
50 /**
51  * \brief Different kinds of qualifier that can be used to modify the behaviour
52  * of the counter to be registered
53  */
54 enum StatsType {
60 
62 };
63 
64 /**
65  * \brief per thread store of counters
66  */
67 typedef struct StatsThreadStore_ {
68  /** thread name used in output */
69  const char *name;
70 
72 
75 
76 /**
77  * \brief Holds the output interface context for the counter api
78  */
79 typedef struct StatsGlobalContext_ {
80  /** list of thread stores: one per thread plus one global */
83  int sts_cnt;
84 
86 
89 
90 static void *stats_thread_data = NULL;
91 static StatsGlobalContext *stats_ctx = NULL;
92 static time_t stats_start_time;
93 /** refresh interval in seconds */
94 static uint32_t stats_tts = STATS_MGMTT_TTS;
95 /** is the stats counter enabled? */
96 static bool stats_enabled = true;
97 
98 /**< add decoder events as stats? enabled by default */
100 const char *stats_decoder_events_prefix = "decoder.event";
101 /**< add stream events as stats? disabled by default */
102 bool stats_stream_events = false;
103 
104 static int StatsOutput(ThreadVars *tv);
105 static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *);
106 static void StatsReleaseCounters(StatsCounter *head);
107 static int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx);
108 
109 /** stats table is filled each interval and passed to the
110  * loggers. Initialized at first use. */
111 static StatsTable stats_table = { NULL, NULL, 0, 0, 0, {0 , 0}};
112 static SCMutex stats_table_mutex = SCMUTEX_INITIALIZER;
113 static int stats_loggers_active = 1;
114 
115 static uint16_t counters_global_id = 0;
116 
117 bool StatsEnabled(void)
118 {
119  return stats_enabled;
120 }
121 
122 static void StatsPublicThreadContextInit(StatsPublicThreadContext *t)
123 {
124  SCSpinInit(&t->lock, 0);
125 }
126 
127 static void StatsPublicThreadContextCleanup(StatsPublicThreadContext *t)
128 {
129  SCSpinLock(&t->lock);
131  SCFree(t->pc_array);
132  StatsReleaseCounters(t->head);
133  t->head = NULL;
134  SC_ATOMIC_SET(t->sync_now, false);
135  t->curr_id = 0;
136  SCSpinUnlock(&t->lock);
137  SCSpinDestroy(&t->lock);
138 }
139 
140 /**
141  * \brief Adds a value of type uint64_t to the local counter.
142  *
143  * \param id ID of the counter as set by the API
144  * \param pca Counter array that holds the local counter for this TM
145  * \param x Value to add to this local counter
146  */
148 {
149  StatsPrivateThreadContext *pca = &stats->priv;
150 #if defined (UNITTESTS) || defined (FUZZ)
151  if (pca->initialized == 0)
152  return;
153 #endif
154 #ifdef DEBUG
155  BUG_ON((id.id < 1) || (id.id > pca->size));
156 #endif
157  pca->head[id.id].v += x;
158 }
159 
160 /**
161  * \brief Increments the local counter
162  *
163  * \param id Index of the counter in the counter array
164  * \param pca Counter array that holds the local counters for this TM
165  */
167 {
168  StatsPrivateThreadContext *pca = &stats->priv;
169 #if defined (UNITTESTS) || defined (FUZZ)
170  if (pca->initialized == 0)
171  return;
172 #endif
173 #ifdef DEBUG
174  BUG_ON((id.id < 1) || (id.id > pca->size));
175 #endif
176  pca->head[id.id].v++;
177 }
178 
179 /**
180  * \brief Decrements the local counter
181  *
182  * \param stats per thread counter structure
183  * \param id Index of the counter in the counter array
184  */
186 {
187  StatsPrivateThreadContext *pca = &stats->priv;
188 #if defined(UNITTESTS) || defined(FUZZ)
189  if (pca->initialized == 0)
190  return;
191 #endif
192 #ifdef DEBUG
193  BUG_ON((id.id < 1) || (id.id > pca->size));
194 #endif
195  pca->head[id.id].v--;
196 }
197 
198 /**
199  * \brief set, so overwrite, the value of the local counter
200  *
201  * \param stats per thread counter structure
202  * \param id Index of the local counter in the counter array
203  * \param x The value to set for the counter
204  */
206 {
207  StatsPrivateThreadContext *pca = &stats->priv;
208 #if defined (UNITTESTS) || defined (FUZZ)
209  if (pca->initialized == 0)
210  return;
211 #endif
212 #ifdef DEBUG
213  BUG_ON((id.id < 1) || (id.id > pca->size));
214 #endif
215  pca->head[id.id].v = x;
216 }
217 
218 /**
219  * \brief update the value of the localmax counter
220  *
221  * \param stats per thread counter structure
222  * \param id Index of the local counter in the counter array
223  * \param x The value to set for the counter
224  */
226 {
227  StatsPrivateThreadContext *pca = &stats->priv;
228 #if defined(UNITTESTS) || defined(FUZZ)
229  if (pca->initialized == 0)
230  return;
231 #endif
232 #ifdef DEBUG
233  BUG_ON((id.id < 1) || (id.id > pca->size));
234 #endif
235 
236  if ((int64_t)x > pca->head[id.id].v) {
237  pca->head[id.id].v = x;
238  }
239 }
240 
242 {
243  StatsPrivateThreadContext *pca = &stats->priv;
244 #if defined(UNITTESTS) || defined(FUZZ)
245  if (pca->initialized == 0)
246  return;
247 #endif
248 #ifdef DEBUG
249  BUG_ON((id.id < 1) || (id.id > pca->size));
250 #endif
251 
252  pca->head[id.id].v += x;
253  pca->head[id.id + 1].v++;
254 }
255 
256 static SCConfNode *GetConfig(void)
257 {
258  SCConfNode *stats = SCConfGetNode("stats");
259  if (stats != NULL)
260  return stats;
261 
262  SCConfNode *root = SCConfGetNode("outputs");
263  SCConfNode *node = NULL;
264  if (root != NULL) {
265  TAILQ_FOREACH(node, &root->head, next) {
266  if (strcmp(node->val, "stats") == 0) {
267  return node->head.tqh_first;
268  }
269  }
270  }
271  return NULL;
272 }
273 
274 /**
275  * \brief Initializes stats context
276  */
277 static void StatsInitCtxPreOutput(void)
278 {
279  SCEnter();
280  SCConfNode *stats = GetConfig();
281  if (stats != NULL) {
282  const char *enabled = SCConfNodeLookupChildValue(stats, "enabled");
283  if (enabled != NULL && SCConfValIsFalse(enabled)) {
284  stats_enabled = false;
285  SCLogDebug("Stats module has been disabled");
286  SCReturn;
287  }
288  /* warn if we are using legacy config to enable stats */
289  SCConfNode *gstats = SCConfGetNode("stats");
290  if (gstats == NULL) {
291  SCLogWarning("global stats config is missing. "
292  "Stats enabled through legacy stats.log. "
293  "See %s/configuration/suricata-yaml.html#stats",
294  GetDocURL());
295  }
296 
297  const char *interval = SCConfNodeLookupChildValue(stats, "interval");
298  if (interval != NULL)
299  if (StringParseUint32(&stats_tts, 10, 0, interval) < 0) {
300  SCLogWarning("Invalid value for "
301  "interval: \"%s\". Resetting to %d.",
302  interval, STATS_MGMTT_TTS);
303  stats_tts = STATS_MGMTT_TTS;
304  }
305 
306  int b;
307  int ret = SCConfGetChildValueBool(stats, "decoder-events", &b);
308  if (ret) {
309  stats_decoder_events = (b == 1);
310  }
311  ret = SCConfGetChildValueBool(stats, "stream-events", &b);
312  if (ret) {
313  stats_stream_events = (b == 1);
314  }
315 
316  const char *prefix = NULL;
317  if (SCConfGet("stats.decoder-events-prefix", &prefix) != 1) {
318  prefix = "decoder.event";
319  }
321  }
322  SCReturn;
323 }
324 
325 static void StatsInitCtxPostOutput(void)
326 {
327  SCEnter();
328  /* Store the engine start time */
329  time(&stats_start_time);
330 
331  /* init the lock used by StatsThreadStore */
332  if (SCMutexInit(&stats_ctx->sts_lock, NULL) != 0) {
333  FatalError("error initializing sts mutex");
334  }
335 
336  if (stats_enabled && !OutputStatsLoggersRegistered()) {
337  stats_loggers_active = 0;
338 
339  /* if the unix command socket is enabled we do the background
340  * stats sync just in case someone runs 'dump-counters' */
341  if (!ConfUnixSocketIsEnable()) {
342  SCLogWarning("stats are enabled but no loggers are active");
343  stats_enabled = false;
344  SCReturn;
345  }
346  }
347 
348  SCReturn;
349 }
350 
351 /**
352  * \brief Releases the resources allotted to the output context of the
353  * Stats API
354  */
355 static void StatsReleaseCtx(void)
356 {
357  if (stats_ctx == NULL) {
358  SCLogDebug("Counter module has been disabled");
359  return;
360  }
361 
362  StatsThreadStore *sts = NULL;
363  StatsThreadStore *temp = NULL;
364  sts = stats_ctx->sts;
365 
366  while (sts != NULL) {
367  temp = sts->next;
368  SCFree(sts);
369  sts = temp;
370  }
371 
372  if (stats_ctx->counters_id_hash != NULL) {
373  HashTableFree(stats_ctx->counters_id_hash);
374  stats_ctx->counters_id_hash = NULL;
375  counters_global_id = 0;
376  }
377 
378  StatsPublicThreadContextCleanup(&stats_ctx->global_counter_ctx);
379  SCFree(stats_ctx);
380  stats_ctx = NULL;
381 
382  SCMutexLock(&stats_table_mutex);
383  /* free stats table */
384  if (stats_table.tstats != NULL) {
385  SCFree(stats_table.tstats);
386  stats_table.tstats = NULL;
387  }
388 
389  if (stats_table.stats != NULL) {
390  SCFree(stats_table.stats);
391  stats_table.stats = NULL;
392  }
393  memset(&stats_table, 0, sizeof(stats_table));
394  SCMutexUnlock(&stats_table_mutex);
395 }
396 
397 /**
398  * \brief management thread. This thread is responsible for writing the stats
399  *
400  * \param arg thread var
401  *
402  * \retval NULL This is the value that is always returned
403  */
404 static void *StatsMgmtThread(void *arg)
405 {
406  ThreadVars *tv_local = (ThreadVars *)arg;
407 
408  SCSetThreadName(tv_local->name);
409 
410  if (tv_local->thread_setup_flags != 0)
411  TmThreadSetupOptions(tv_local);
412 
413  /* Set the threads capability */
414  tv_local->cap_flags = 0;
415  SCDropCaps(tv_local);
416 
417  if (stats_ctx == NULL) {
418  SCLogError("Stats API not init"
419  "StatsInitCounterApi() has to be called first");
421  return NULL;
422  }
423 
425  BUG_ON(tm->ThreadInit == NULL);
426  int r = tm->ThreadInit(tv_local, NULL, &stats_thread_data);
427  if (r != 0 || stats_thread_data == NULL) {
428  SCLogError("Stats API "
429  "ThreadInit failed");
431  return NULL;
432  }
433  SCLogDebug("stats_thread_data %p", &stats_thread_data);
434 
436  bool run = TmThreadsWaitForUnpause(tv_local);
437  while (run) {
438  struct timeval cur_timev;
439  gettimeofday(&cur_timev, NULL);
440  struct timespec cond_time = FROM_TIMEVAL(cur_timev);
441  cond_time.tv_sec += (stats_tts);
442 
443  /* wait for the set time, or until we are woken up by
444  * the shutdown procedure */
445  SCCtrlMutexLock(tv_local->ctrl_mutex);
446  while (1) {
447  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
448  break;
449  }
450  int rc = SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
451  if (rc == ETIMEDOUT || rc < 0) {
452  break;
453  }
454  }
455  SCCtrlMutexUnlock(tv_local->ctrl_mutex);
456 
457  SCMutexLock(&stats_table_mutex);
458  StatsOutput(tv_local);
459  SCMutexUnlock(&stats_table_mutex);
460 
461  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
462  break;
463  }
464  }
465 
467  TmThreadWaitForFlag(tv_local, THV_DEINIT);
468 
469  r = tm->ThreadDeinit(tv_local, stats_thread_data);
470  if (r != TM_ECODE_OK) {
471  SCLogError("Stats Counter API "
472  "ThreadDeinit failed");
473  }
474 
475  TmThreadsSetFlag(tv_local, THV_CLOSED);
476  return NULL;
477 }
478 
480 {
481  StatsUpdateCounterArray(&stats->priv, &stats->pub);
482 }
483 
485 {
486  if (SC_ATOMIC_GET(stats->pub.sync_now)) {
487  StatsUpdateCounterArray(&stats->priv, &stats->pub);
488  }
489 }
490 
491 /**
492  * \brief Wake up thread. This thread wakes up every TTS(time to sleep) seconds
493  * and sets the flag for every ThreadVars' StatsPublicThreadContext
494  *
495  * \param arg is NULL always
496  *
497  * \retval NULL This is the value that is always returned
498  */
499 static void *StatsWakeupThread(void *arg)
500 {
501  ThreadVars *tv_local = (ThreadVars *)arg;
502 
503  SCSetThreadName(tv_local->name);
504 
505  if (tv_local->thread_setup_flags != 0)
506  TmThreadSetupOptions(tv_local);
507 
508  /* Set the threads capability */
509  tv_local->cap_flags = 0;
510  SCDropCaps(tv_local);
511 
512  if (stats_ctx == NULL) {
513  SCLogError("Stats API not init"
514  "StatsInitCounterApi() has to be called first");
516  return NULL;
517  }
518 
520  bool run = TmThreadsWaitForUnpause(tv_local);
521 
522  while (run) {
523  struct timeval cur_timev;
524  gettimeofday(&cur_timev, NULL);
525  struct timespec cond_time = FROM_TIMEVAL(cur_timev);
526  cond_time.tv_sec += STATS_WUT_TTS;
527 
528  /* wait for the set time, or until we are woken up by
529  * the shutdown procedure */
530  SCCtrlMutexLock(tv_local->ctrl_mutex);
531  while (1) {
532  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
533  break;
534  }
535  int rc = SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
536  if (rc == ETIMEDOUT || rc < 0) {
537  break;
538  }
539  }
540  SCCtrlMutexUnlock(tv_local->ctrl_mutex);
541 
544  while (tv != NULL) {
545  if (tv->stats.pub.head == NULL) {
546  tv = tv->next;
547  continue;
548  }
549 
550  SC_ATOMIC_SET(tv->stats.pub.sync_now, true);
551 
552  if (tv->inq != NULL) {
553  PacketQueue *q = tv->inq->pq;
554  SCMutexLock(&q->mutex_q);
555  SCCondSignal(&q->cond_q);
556  SCMutexUnlock(&q->mutex_q);
557  }
558 
559  tv = tv->next;
560  }
561 
562  /* mgt threads for flow manager */
563  tv = tv_root[TVT_MGMT];
564  while (tv != NULL) {
565  if (tv->stats.pub.head == NULL) {
566  tv = tv->next;
567  continue;
568  }
569 
570  SC_ATOMIC_SET(tv->stats.pub.sync_now, true);
571 
572  tv = tv->next;
573  }
575 
576  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
577  break;
578  }
579  }
580 
582  TmThreadWaitForFlag(tv_local, THV_DEINIT);
583  TmThreadsSetFlag(tv_local, THV_CLOSED);
584  return NULL;
585 }
586 
587 /**
588  * \brief Releases a counter
589  *
590  * \param pc Pointer to the StatsCounter to be freed
591  */
592 static void StatsReleaseCounter(StatsCounter *pc)
593 {
594  if (pc != NULL) {
595  SCFree(pc);
596  }
597 }
598 
599 /** \internal
600  * \brief Get ID for counters referenced in a derive counter
601  * \retval id (>=1) or 0 on error
602  */
603 static uint16_t GetIdByName(const StatsPublicThreadContext *pctx, const char *name)
604 {
605  for (const StatsCounter *c = pctx->head; c != NULL; c = c->next) {
606  if (strcmp(name, c->name) == 0) {
607  return c->id;
608  }
609  }
610  return 0;
611 }
612 
613 /**
614  * \brief Registers a counter.
615  *
616  * \param name Name of the counter, to be registered
617  * \param pctx StatsPublicThreadContext for this tm-tv instance
618  * \param type_q Qualifier describing the type of counter to be registered
619  *
620  * \retval the counter id for the newly registered counter, or the already
621  * present counter on success
622  * \retval 0 on failure
623  */
624 static uint16_t StatsRegisterQualifiedCounter(const char *name, StatsPublicThreadContext *pctx,
625  enum StatsType type_q, uint64_t (*Func)(void), const char *dname1, const char *dname2)
626 {
627  StatsCounter **head = &pctx->head;
628  StatsCounter *temp = NULL;
629  StatsCounter *prev = NULL;
630  StatsCounter *pc = NULL;
631 
632  if (name == NULL || pctx == NULL) {
633  SCLogDebug("Counter name, StatsPublicThreadContext NULL");
634  return 0;
635  }
636 
637  temp = prev = *head;
638  while (temp != NULL) {
639  prev = temp;
640 
641  if (strcmp(name, temp->name) == 0) {
642  break;
643  }
644 
645  temp = temp->next;
646  }
647 
648  /* We already have a counter registered by this name */
649  if (temp != NULL)
650  return(temp->id);
651 
652  uint16_t did1 = 0;
653  uint16_t did2 = 0;
654  if (type_q == STATS_TYPE_DERIVE_DIV) {
655  did1 = GetIdByName(pctx, dname1);
656  did2 = GetIdByName(pctx, dname2);
657  if (did1 == 0 || did2 == 0) {
658  return 0;
659  }
660  }
661 
662  /* if we reach this point we don't have a counter registered by this name */
663  if ((pc = SCCalloc(1, sizeof(StatsCounter))) == NULL)
664  return 0;
665 
666  /* assign a unique id to this StatsCounter. The id is local to this
667  * thread context. Please note that the id start from 1, and not 0 */
668  if (type_q == STATS_TYPE_DERIVE_DIV) {
669  pc->id = ++pctx->derive_id;
670  } else {
671  pc->id = ++(pctx->curr_id);
672  }
673  /* for AVG counters we use 2 indices into the tables: one for values,
674  * the other to track updates. */
675  if (type_q == STATS_TYPE_AVERAGE)
676  ++(pctx->curr_id);
677  pc->name = name;
678 
679  /* Precalculate the short name */
680  if (strrchr(name, '.') != NULL) {
681  pc->short_name = &name[strrchr(name, '.') - name + 1];
682  }
683 
684  pc->type = type_q;
685  pc->Func = Func;
686  pc->did1 = did1;
687  pc->did2 = did2;
688 
689  /* we now add the counter to the list */
690  if (prev == NULL)
691  *head = pc;
692  else
693  prev->next = pc;
694 
695  return pc->id;
696 }
697 
698 /**
699  * \brief The output interface for the Stats API
700  */
701 static int StatsOutput(ThreadVars *tv)
702 {
703  const StatsThreadStore *sts = NULL;
704  void *td = stats_thread_data;
705 
706  if (counters_global_id == 0)
707  return -1;
708 
709  if (stats_table.nstats == 0) {
710  StatsThreadRegister("Global", &stats_ctx->global_counter_ctx);
711 
712  uint32_t nstats = counters_global_id;
713 
714  stats_table.nstats = nstats;
715  stats_table.stats = SCCalloc(stats_table.nstats, sizeof(StatsRecord));
716  if (stats_table.stats == NULL) {
717  stats_table.nstats = 0;
718  SCLogError("could not alloc memory for stats");
719  return -1;
720  }
721 
722  stats_table.ntstats = stats_ctx->sts_cnt;
723  uint32_t array_size = stats_table.nstats * sizeof(StatsRecord);
724  stats_table.tstats = SCCalloc(stats_table.ntstats, array_size);
725  if (stats_table.tstats == NULL) {
726  stats_table.ntstats = 0;
727  SCLogError("could not alloc memory for stats");
728  return -1;
729  }
730 
731  stats_table.start_time = stats_start_time;
732  }
733 
734  const uint16_t max_id = counters_global_id;
735  if (max_id == 0)
736  return -1;
737 
738  /** temporary local table to merge the per thread counters,
739  * especially needed for the average counters */
740  struct CountersMergeTable {
741  enum StatsType type;
742  int64_t value;
743  uint64_t updates;
744  } merge_table[max_id];
745  memset(&merge_table, 0x00,
746  max_id * sizeof(struct CountersMergeTable));
747 
748  int thread = stats_ctx->sts_cnt - 1;
749  StatsRecord *table = stats_table.stats;
750 
751  /* Loop through the thread counter stores. The global counters
752  * are in a separate store inside this list. */
753  sts = stats_ctx->sts;
754  SCLogDebug("sts %p", sts);
755  while (sts != NULL) {
756  DEBUG_VALIDATE_BUG_ON(thread < 0);
757 
758  SCLogDebug("Thread %d %s ctx %p", thread, sts->name, sts->ctx);
759 
760  /* temporary table for quickly storing the counters for this
761  * thread store, so that we can post process them outside
762  * of the thread store lock */
763  struct CountersMergeTable thread_table[max_id];
764  memset(&thread_table, 0x00,
765  max_id * sizeof(struct CountersMergeTable));
766 
767  StatsLocalCounter thread_table_from_private[max_id];
768  memset(&thread_table_from_private, 0x00, max_id * sizeof(StatsLocalCounter));
769 
770  /* copy private table to a local variable to loop it w/o lock */
771  bool skip = false;
772  SCSpinLock(&sts->ctx->lock);
773  const uint16_t table_size = sts->ctx->curr_id + sts->ctx->derive_id + 1;
774  if (sts->ctx->copy_of_private == NULL) {
775  skip = true;
776  } else {
777  memcpy(&thread_table_from_private, sts->ctx->copy_of_private,
778  table_size * sizeof(StatsLocalCounter));
779  }
780  SCSpinUnlock(&sts->ctx->lock);
781  if (skip)
782  goto next;
783 
784  /* loop counters and handle them. This includes the global counters, which
785  * access the StatsCounters but don't modify them. */
786  for (uint16_t i = 1; i < table_size; i++) {
787  const StatsCounter *pc = sts->ctx->pc_array[i];
788  thread_table[pc->gid].type = pc->type;
789 
790  table[pc->gid].name = pc->name;
791  table[pc->gid].short_name = pc->short_name;
792 
793  switch (pc->type) {
794  case STATS_TYPE_FUNC:
795  if (pc->Func != NULL)
796  thread_table[pc->gid].value = pc->Func();
797  break;
798  case STATS_TYPE_AVERAGE:
799  thread_table[pc->gid].value = thread_table_from_private[i].v;
800  thread_table[pc->gid].updates = thread_table_from_private[i + 1].v;
801  /* skip updates row */
802  i++;
803  break;
805  SCLogDebug("counter %u/%u is derived from counters %u / %u", pc->id, pc->gid,
806  pc->did1, pc->did2);
807  thread_table[pc->gid].value = thread_table_from_private[pc->did1].v;
808  thread_table[pc->gid].updates = thread_table_from_private[pc->did2].v;
809  break;
810  default:
811  SCLogDebug("Counter %s (%u:%u) value %" PRIu64, pc->name, pc->id, pc->gid,
812  thread_table_from_private[i].v);
813 
814  thread_table[pc->gid].value = thread_table_from_private[i].v;
815  break;
816  }
817  }
818 
819  /* update merge table */
820  for (uint16_t c = 0; c < max_id; c++) {
821  const struct CountersMergeTable *e = &thread_table[c];
822  /* thread only sets type if it has a counter
823  * of this type. */
824  if (e->type == 0)
825  continue;
826 
827  switch (e->type) {
828  case STATS_TYPE_MAXIMUM:
829  if (e->value > merge_table[c].value)
830  merge_table[c].value = e->value;
831  break;
832  case STATS_TYPE_FUNC:
833  merge_table[c].value = e->value;
834  break;
835  case STATS_TYPE_AVERAGE:
836  default:
837  merge_table[c].value += e->value;
838  break;
839  }
840  merge_table[c].updates += e->updates;
841  merge_table[c].type = e->type;
842  }
843 
844  /* update per thread stats table */
845  for (uint16_t c = 0; c < max_id; c++) {
846  const struct CountersMergeTable *e = &thread_table[c];
847  /* thread only sets type if it has a counter
848  * of this type. */
849  if (e->type == 0)
850  continue;
851 
852  uint32_t offset = (thread * stats_table.nstats) + c;
853  StatsRecord *r = &stats_table.tstats[offset];
854  /* xfer previous value to pvalue and reset value */
855  r->pvalue = r->value;
856  r->value = 0;
857  r->name = table[c].name;
858  r->short_name = table[c].short_name;
859  r->tm_name = sts->name;
860 
861  switch (e->type) {
862  case STATS_TYPE_AVERAGE:
864  if (e->value > 0 && e->updates > 0) {
865  r->value = (uint64_t)(e->value / e->updates);
866  }
867  break;
868  default:
869  r->value = e->value;
870  break;
871  }
872  }
873 
874  next:
875  sts = sts->next;
876  thread--;
877  }
878 
879  /* transfer 'merge table' to final stats table */
880  for (uint16_t x = 0; x < max_id; x++) {
881  /* xfer previous value to pvalue and reset value */
882  table[x].pvalue = table[x].value;
883  table[x].value = 0;
884  table[x].tm_name = "Total";
885 
886  const struct CountersMergeTable *m = &merge_table[x];
887  switch (m->type) {
888  case STATS_TYPE_MAXIMUM:
889  if (m->value > table[x].value)
890  table[x].value = m->value;
891  break;
892  case STATS_TYPE_AVERAGE:
894  if (m->value > 0 && m->updates > 0) {
895  table[x].value = (uint64_t)(m->value / m->updates);
896  }
897  break;
898  default:
899  table[x].value += m->value;
900  break;
901  }
902  }
903 
904  /* invoke logger(s) */
905  if (stats_loggers_active) {
906  OutputStatsLog(tv, td, &stats_table);
907  }
908  return 1;
909 }
910 
911 #ifdef BUILD_UNIX_SOCKET
912 /** \brief callback for getting stats into unix socket
913  */
914 TmEcode StatsOutputCounterSocket(json_t *cmd,
915  json_t *answer, void *data)
916 {
917  json_t *message = NULL;
918  TmEcode r = TM_ECODE_OK;
919 
920  if (!stats_enabled) {
921  r = TM_ECODE_FAILED;
922  message = json_string("stats are disabled in the config");
923  } else {
924  SCMutexLock(&stats_table_mutex);
925  if (stats_table.start_time == 0) {
926  r = TM_ECODE_FAILED;
927  message = json_string("stats not yet synchronized");
928  } else {
929  message = StatsToJSON(&stats_table, JSON_STATS_TOTALS|JSON_STATS_THREADS);
930  }
931  SCMutexUnlock(&stats_table_mutex);
932  }
933  json_object_set_new(answer, "message", message);
934  return r;
935 }
936 #endif /* BUILD_UNIX_SOCKET */
937 
938 static void StatsLogSummary(void)
939 {
940  if (!stats_enabled) {
941  return;
942  }
943  uint64_t alerts = 0;
944  SCMutexLock(&stats_table_mutex);
945  if (stats_table.start_time != 0) {
946  const StatsTable *st = &stats_table;
947  for (uint32_t u = 0; u < st->nstats; u++) {
948  const char *name = st->stats[u].name;
949  if (name == NULL || strcmp(name, "detect.alert") != 0)
950  continue;
951  alerts = st->stats[u].value;
952  break;
953  }
954  }
955  SCMutexUnlock(&stats_table_mutex);
956  SCLogInfo("Alerts: %"PRIu64, alerts);
957 }
958 
959 /**
960  * \brief Initializes the perf counter api. Things are hard coded currently.
961  * More work to be done when we implement multiple interfaces
962  */
963 void StatsInit(void)
964 {
965  BUG_ON(stats_ctx != NULL);
966  if ((stats_ctx = SCCalloc(1, sizeof(StatsGlobalContext))) == NULL) {
967  FatalError("Fatal error encountered in StatsInitCtx. Exiting...");
968  }
969 
970  StatsPublicThreadContextInit(&stats_ctx->global_counter_ctx);
971 }
972 
974 {
975  StatsInitCtxPreOutput();
976 }
977 
979 {
980  StatsInitCtxPostOutput();
981 }
982 
983 
984 /**
985  * \brief Spawns the wakeup, and the management thread used by the stats api
986  *
987  * The threads use the condition variable in the thread vars to control
988  * their wait loops to make sure the main thread can quickly kill them.
989  */
991 {
992  SCEnter();
993 
994  if (!stats_enabled) {
995  SCReturn;
996  }
997 
998  ThreadVars *tv_wakeup = NULL;
999  ThreadVars *tv_mgmt = NULL;
1000 
1001  /* spawn the stats wakeup thread */
1003  StatsWakeupThread, 1);
1004  if (tv_wakeup == NULL) {
1005  FatalError("TmThreadCreateMgmtThread "
1006  "failed");
1007  }
1008 
1009  if (TmThreadSpawn(tv_wakeup) != 0) {
1010  FatalError("TmThreadSpawn failed for "
1011  "StatsWakeupThread");
1012  }
1013 
1014  /* spawn the stats mgmt thread */
1016  StatsMgmtThread, 1);
1017  if (tv_mgmt == NULL) {
1018  FatalError("TmThreadCreateMgmtThread failed");
1019  }
1020 
1021  if (TmThreadSpawn(tv_mgmt) != 0) {
1022  FatalError("TmThreadSpawn failed for "
1023  "StatsWakeupThread");
1024  }
1025 
1026  SCReturn;
1027 }
1028 
1029 /**
1030  * \brief Registers a normal, unqualified counter
1031  *
1032  * \param name Name of the counter, to be registered
1033  * \param tv Pointer to the ThreadVars instance for which the counter would
1034  * be registered
1035  *
1036  * \retval id Counter id for the newly registered counter, or the already
1037  * present counter
1038  */
1040 {
1041  uint16_t id =
1042  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_NORMAL, NULL, NULL, NULL);
1043  StatsCounterId s = { .id = id };
1044  return s;
1045 }
1046 
1047 /**
1048  * \brief Registers a counter, whose value holds the average of all the values
1049  * assigned to it.
1050  *
1051  * \param name Name of the counter, to be registered
1052  * \param tv Pointer to the ThreadVars instance for which the counter would
1053  * be registered
1054  *
1055  * \retval id Counter id for the newly registered counter, or the already
1056  * present counter
1057  */
1059 {
1060  uint16_t id =
1061  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_AVERAGE, NULL, NULL, NULL);
1062  StatsCounterAvgId s = { .id = id };
1063  return s;
1064 }
1065 
1066 /**
1067  * \brief Registers a counter, whose value holds the maximum of all the values
1068  * assigned to it.
1069  *
1070  * \param name Name of the counter, to be registered
1071  * \param tv Pointer to the ThreadVars instance for which the counter would
1072  * be registered
1073  *
1074  * \retval the counter id for the newly registered counter, or the already
1075  * present counter
1076  */
1078 {
1079  uint16_t id =
1080  StatsRegisterQualifiedCounter(name, &stats->pub, STATS_TYPE_MAXIMUM, NULL, NULL, NULL);
1081  StatsCounterMaxId s = { .id = id };
1082  return s;
1083 }
1084 
1085 /**
1086  * \brief Registers a counter, which represents a global value
1087  *
1088  * \param name Name of the counter, to be registered
1089  * \param Func Function Pointer returning a uint64_t
1090  *
1091  * \retval id Counter id for the newly registered counter, or the already
1092  * present counter
1093  */
1094 StatsCounterGlobalId StatsRegisterGlobalCounter(const char *name, uint64_t (*Func)(void))
1095 {
1096  StatsCounterGlobalId s = { .id = 0 };
1097 #if defined (UNITTESTS) || defined (FUZZ)
1098  if (stats_ctx == NULL)
1099  return s;
1100 #else
1101  BUG_ON(stats_ctx == NULL);
1102 #endif
1103  uint16_t id = StatsRegisterQualifiedCounter(
1104  name, &(stats_ctx->global_counter_ctx), STATS_TYPE_FUNC, Func, NULL, NULL);
1105  s.id = id;
1106  return s;
1107 }
1108 
1109 /**
1110  * \brief Registers a counter which tracks the result of the calculating the value
1111  * of counter dname1 divided by the value of the counter dname2
1112  *
1113  * \param name Name of the counter, to be registered
1114  * \param dname1 First counter name
1115  * \param dname2 Second counter name
1116  *
1117  * Both counters need to already be registered in this thread.
1118  *
1119  * \retval id Counter id for the newly registered counter, or the already
1120  * present counter
1121  */
1123  const char *name, const char *dname1, const char *dname2, StatsThreadContext *stats)
1124 {
1125  StatsCounterDeriveId s = { .id = 0 };
1126 #if defined(UNITTESTS) || defined(FUZZ)
1127  if (stats_ctx == NULL)
1128  return s;
1129 #else
1130  BUG_ON(stats_ctx == NULL);
1131 #endif
1132  uint16_t id = StatsRegisterQualifiedCounter(
1133  name, &stats->pub, STATS_TYPE_DERIVE_DIV, NULL, dname1, dname2);
1134  s.id = id;
1135  return s;
1136 }
1137 
1138 typedef struct CountersIdType_ {
1139  uint16_t id;
1140  const char *string;
1142 
1143 static uint32_t CountersIdHashFunc(HashTable *ht, void *data, uint16_t datalen)
1144 {
1145  CountersIdType *t = (CountersIdType *)data;
1146  uint32_t hash = 0;
1147  size_t len = strlen(t->string);
1148 
1149  for (size_t i = 0; i < len; i++)
1150  hash += u8_tolower((unsigned char)t->string[i]);
1151 
1152  hash = hash % ht->array_size;
1153  return hash;
1154 }
1155 
1156 static char CountersIdHashCompareFunc(void *data1, uint16_t datalen1,
1157  void *data2, uint16_t datalen2)
1158 {
1159  CountersIdType *t1 = (CountersIdType *)data1;
1160  CountersIdType *t2 = (CountersIdType *)data2;
1161 
1162  if (t1 == NULL || t2 == NULL)
1163  return 0;
1164 
1165  if (t1->string == NULL || t2->string == NULL)
1166  return 0;
1167 
1168  return strcmp(t1->string, t2->string) == 0;
1169 }
1170 
1171 static void CountersIdHashFreeFunc(void *data)
1172 {
1173  SCFree(data);
1174 }
1175 
1176 static int StatsThreadSetupPublic(StatsPublicThreadContext *pctx)
1177 {
1178  size_t array_size = pctx->curr_id + pctx->derive_id + 1;
1179  pctx->pc_array = SCCalloc(array_size, sizeof(StatsCounter *));
1180  if (pctx->pc_array == NULL) {
1181  return -1;
1182  }
1183  /* regular counters that get direct updates by their id as idx */
1184  for (StatsCounter *pc = pctx->head; pc != NULL; pc = pc->next) {
1185  if (pc->type != STATS_TYPE_DERIVE_DIV) {
1186  SCLogDebug("pc %s gid %u id %u", pc->name, pc->gid, pc->id);
1187  BUG_ON(pctx->pc_array[pc->id] != NULL);
1188  pctx->pc_array[pc->id] = pc;
1189  }
1190  }
1191  /* derive counters are not updated by the thread itself and will be put
1192  * at the end of the array */
1193  for (StatsCounter *pc = pctx->head; pc != NULL; pc = pc->next) {
1194  if (pc->type == STATS_TYPE_DERIVE_DIV) {
1195  uint16_t id = pctx->curr_id + pc->id;
1196  SCLogDebug("STATS_TYPE_DERIVE_DIV: pc %s gid %u pc->id %u id %u", pc->name, pc->gid,
1197  pc->id, id);
1198  BUG_ON(pctx->pc_array[id] != NULL);
1199  pctx->pc_array[id] = pc;
1200  }
1201  }
1202 
1203  SCLogDebug("array_size %u memory %" PRIu64, (uint32_t)array_size,
1204  (uint64_t)(array_size * sizeof(StatsLocalCounter)));
1205  pctx->copy_of_private = SCCalloc(array_size, sizeof(StatsLocalCounter));
1206  if (pctx->copy_of_private == NULL) {
1207  return -1;
1208  }
1209  return 0;
1210 }
1211 
1212 /** \internal
1213  * \brief Adds a TM to the clubbed TM table. Multiple instances of the same TM
1214  * are stacked together in a PCTMI container.
1215  *
1216  * \param tm_name Name of the tm to be added to the table
1217  * \param pctx StatsPublicThreadContext associated with the TM tm_name
1218  *
1219  * \retval 1 on success, 0 on failure
1220  */
1221 static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *pctx)
1222 {
1223  if (stats_ctx == NULL) {
1224  return 1;
1225  }
1226 
1227  if (thread_name == NULL || pctx == NULL) {
1228  SCLogDebug("supplied argument(s) to StatsThreadRegister NULL");
1229  return 0;
1230  }
1231 
1232  SCMutexLock(&stats_ctx->sts_lock);
1233  SCLogDebug("thread %s", thread_name);
1234  if (stats_ctx->counters_id_hash == NULL) {
1235  stats_ctx->counters_id_hash = HashTableInit(256, CountersIdHashFunc,
1236  CountersIdHashCompareFunc,
1237  CountersIdHashFreeFunc);
1238  if (stats_ctx->counters_id_hash == NULL) {
1239  SCMutexUnlock(&stats_ctx->sts_lock);
1240  return 0;
1241  }
1242  }
1243  StatsCounter *pc = pctx->head;
1244  while (pc != NULL) {
1245  CountersIdType t = { 0, pc->name }, *id = NULL;
1246  id = HashTableLookup(stats_ctx->counters_id_hash, &t, sizeof(t));
1247  if (id == NULL) {
1248  id = SCCalloc(1, sizeof(*id));
1249  BUG_ON(id == NULL);
1250  id->id = counters_global_id++;
1251  id->string = pc->name;
1252  int r = HashTableAdd(stats_ctx->counters_id_hash, id, sizeof(*id));
1253  DEBUG_VALIDATE_BUG_ON(r < 0);
1254  if (r < 0) {
1255  SCMutexUnlock(&stats_ctx->sts_lock);
1256  return 0;
1257  }
1258  }
1259  pc->gid = id->id;
1260  pc = pc->next;
1261  }
1262 
1263  if (StatsThreadSetupPublic(pctx) != 0) {
1264  SCLogDebug("failed to setup StatsThreadSetupPublic");
1265  SCMutexUnlock(&stats_ctx->sts_lock);
1266  return 0;
1267  }
1268 
1269  StatsThreadStore *temp = NULL;
1270  if ((temp = SCCalloc(1, sizeof(StatsThreadStore))) == NULL) {
1271  SCMutexUnlock(&stats_ctx->sts_lock);
1272  return 0;
1273  }
1274 
1275  temp->ctx = pctx;
1276  temp->name = thread_name;
1277 
1278  temp->next = stats_ctx->sts;
1279  stats_ctx->sts = temp;
1280  stats_ctx->sts_cnt++;
1281  SCLogDebug("stats_ctx->sts %p", stats_ctx->sts);
1282 
1283  SCMutexUnlock(&stats_ctx->sts_lock);
1284  return 1;
1285 }
1286 
1287 /** \internal
1288  * \brief Returns a counter array for all counters registered for this tm
1289  * instance
1290  *
1291  * \param pctx Pointer to the tv's StatsPublicThreadContext
1292  *
1293  * \retval pca Pointer to a counter-array for all counter of this tm instance
1294  * on success; NULL on failure
1295  */
1296 static int StatsGetAllCountersArray(
1298 {
1299  if (pctx == NULL || private == NULL)
1300  return -1;
1301 
1302  private->size = pctx->curr_id + 1;
1303 
1304  private->head = SCCalloc(private->size, sizeof(StatsLocalCounter));
1305  if (private->head == NULL) {
1306  return -1;
1307  }
1308 
1309  private->initialized = 1;
1310  return 0;
1311 }
1312 
1313 int StatsSetupPrivate(StatsThreadContext *stats, const char *thread_name)
1314 {
1315  int r = StatsGetAllCountersArray(&stats->pub, &stats->priv);
1316  if (r < 0) {
1317  return -1;
1318  }
1319 
1320  r = StatsThreadRegister(thread_name, &stats->pub);
1321  if (r != 1) {
1322  return -2;
1323  }
1324  return 0;
1325 }
1326 
1327 static void StatsThreadInitPublic(StatsPublicThreadContext *pctx)
1328 {
1329  memset(pctx, 0x00, sizeof(*pctx));
1330  SCSpinInit(&pctx->lock, 0);
1331 }
1332 
1334 {
1335  StatsThreadInitPublic(&stats->pub);
1336 }
1337 
1338 /**
1339  * \brief the private stats store with the public stats store
1340  *
1341  * \param pca Pointer to the StatsPrivateThreadContext
1342  * \param pctx Pointer the tv's StatsPublicThreadContext
1343  *
1344  * \retval 1 on success
1345  * \retval -1 on error
1346  */
1347 static int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx)
1348 {
1349 
1350  if (pca == NULL || pctx == NULL) {
1351  SCLogDebug("pca or pctx is NULL inside StatsUpdateCounterArray");
1352  return -1;
1353  }
1354 
1355  if (pca->size > 0 && pctx->copy_of_private != NULL) {
1356  /* copy the whole table under lock to the public section
1357  * and release the lock. The stats thread will copy it from
1358  * there. */
1359  SCSpinLock(&pctx->lock);
1360  memcpy(pctx->copy_of_private, pca->head, pca->size * sizeof(StatsLocalCounter));
1361  SCSpinUnlock(&pctx->lock);
1362  }
1363  SC_ATOMIC_SET(pctx->sync_now, false);
1364  return 1;
1365 }
1366 
1367 /**
1368  * \brief Get the value of the local copy of the counter that hold this id.
1369  *
1370  * \param tv threadvars
1371  * \param id The counter id.
1372  *
1373  * \retval 0 on success.
1374  * \retval -1 on error.
1375  */
1377 {
1378  StatsPrivateThreadContext *pca = &stats->priv;
1379 #ifdef DEBUG
1380  BUG_ON((id.id < 1) || (id.id > pca->size));
1381 #endif
1382  return pca->head[id.id].v;
1383 }
1384 
1385 /**
1386  * \brief Releases the resources allotted by the Stats API
1387  */
1389 {
1390  StatsLogSummary();
1391  StatsReleaseCtx();
1392 }
1393 
1394 /**
1395  * \brief Releases counters
1396  *
1397  * \param head Pointer to the head of the list of perf counters that have to
1398  * be freed
1399  */
1400 static void StatsReleaseCounters(StatsCounter *head)
1401 {
1402  StatsCounter *pc = NULL;
1403 
1404  while (head != NULL) {
1405  pc = head;
1406  head = head->next;
1407  StatsReleaseCounter(pc);
1408  }
1409 }
1410 
1411 /** \internal
1412  * \brief Releases the StatsPrivateThreadContext allocated by the user,
1413  * for storing and updating local counter values
1414  *
1415  * \param pca Pointer to the StatsPrivateThreadContext
1416  */
1417 static void StatsReleasePrivateThreadContext(StatsPrivateThreadContext *pca)
1418 {
1419  if (pca != NULL) {
1420  if (pca->head != NULL) {
1421  SCFree(pca->head);
1422  pca->head = NULL;
1423  pca->size = 0;
1424  }
1425  pca->initialized = 0;
1426  }
1427 }
1428 
1430 {
1431  StatsPublicThreadContextCleanup(&stats->pub);
1432  StatsReleasePrivateThreadContext(&stats->priv);
1433 }
1434 
1435 /*----------------------------------Unit_Tests--------------------------------*/
1436 
1437 #ifdef UNITTESTS
1438 /** \internal
1439  * \brief Registers a normal, unqualified counter
1440  *
1441  * \param name Name of the counter, to be registered
1442  * \param type Datatype of this counter variable
1443  * \param pctx StatsPublicThreadContext corresponding to the tm_name key under which the
1444  * key has to be registered
1445  *
1446  * \retval id Counter id for the newly registered counter, or the already
1447  * present counter
1448  */
1449 static StatsCounterId RegisterCounter(
1450  const char *name, const char *tm_name, StatsPublicThreadContext *pctx)
1451 {
1452  uint16_t id = StatsRegisterQualifiedCounter(name, pctx, STATS_TYPE_NORMAL, NULL, NULL, NULL);
1453  StatsCounterId s = { .id = id };
1454  return s;
1455 }
1456 
1457 static int StatsTestCounterReg02(void)
1458 {
1460  StatsThreadInitPublic(&pctx);
1461 
1462  StatsCounterId id = RegisterCounter(NULL, NULL, &pctx);
1463  FAIL_IF_NOT(id.id == 0);
1464  PASS;
1465 }
1466 
1467 static int StatsTestCounterReg03(void)
1468 {
1470  StatsThreadInitPublic(&pctx);
1471 
1472  StatsCounterId id = RegisterCounter("t1", "c1", &pctx);
1473  FAIL_IF_NOT(id.id == 1);
1474 
1475  StatsReleaseCounters(pctx.head);
1476  PASS;
1477 }
1478 
1479 static int StatsTestCounterReg04(void)
1480 {
1482  StatsThreadInitPublic(&pctx);
1483 
1484  StatsCounterId c1 = RegisterCounter("t1", "c1", &pctx);
1485  FAIL_IF_NOT(c1.id == 1);
1486  StatsCounterId c2 = RegisterCounter("t2", "c2", &pctx);
1487  FAIL_IF_NOT(c2.id == 2);
1488  StatsCounterId c3 = RegisterCounter("t3", "c3", &pctx);
1489  FAIL_IF_NOT(c3.id == 3);
1490  StatsCounterId id = RegisterCounter("t1", "c1", &pctx);
1491  FAIL_IF_NOT(id.id == 1);
1492 
1493  StatsReleaseCounters(pctx.head);
1494  PASS;
1495 }
1496 
1497 static int StatsTestGetCntArray05(void)
1498 {
1499  ThreadVars tv;
1500  memset(&tv, 0, sizeof(ThreadVars));
1502  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1503  FAIL_IF(c1.id != 1);
1504  int r = StatsGetAllCountersArray(NULL, &tv.stats.priv);
1505  FAIL_IF_NOT(r == -1);
1507  PASS;
1508 }
1509 
1510 static int StatsTestGetCntArray06(void)
1511 {
1512  ThreadVars tv;
1513  memset(&tv, 0, sizeof(ThreadVars));
1515  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1516  FAIL_IF(c1.id != 1);
1517  StatsThreadSetupPublic(&tv.stats.pub);
1518  int r = StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1519  FAIL_IF_NOT(r == 0);
1521  PASS;
1522 }
1523 
1524 static int StatsTestCntArraySize07(void)
1525 {
1526  ThreadVars tv;
1527  memset(&tv, 0, sizeof(ThreadVars));
1529  StatsPrivateThreadContext *pca = NULL;
1530 
1531  StatsCounterId id1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1532  StatsCounterId id2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1533 
1534  StatsThreadSetupPublic(&tv.stats.pub);
1535  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1536  pca = &tv.stats.priv;
1537 
1538  StatsCounterIncr(&tv.stats, id1);
1539  StatsCounterIncr(&tv.stats, id2);
1540 
1541  FAIL_IF_NOT(pca->size == 3);
1542 
1544  PASS;
1545 }
1546 
1547 static int StatsTestUpdateCounter08(void)
1548 {
1549  ThreadVars tv;
1550  memset(&tv, 0, sizeof(ThreadVars));
1552  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1553  StatsThreadSetupPublic(&tv.stats.pub);
1554  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1556 
1557  StatsCounterIncr(&tv.stats, c1);
1558  StatsCounterAddI64(&tv.stats, c1, 100);
1559  FAIL_IF_NOT(pca->head[c1.id].v == 101);
1560 
1562  PASS;
1563 }
1564 
1565 static int StatsTestUpdateCounter09(void)
1566 {
1567  ThreadVars tv;
1568  memset(&tv, 0, sizeof(ThreadVars));
1570 
1571  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1572  RegisterCounter("t2", "c2", &tv.stats.pub);
1573  RegisterCounter("t3", "c3", &tv.stats.pub);
1574  RegisterCounter("t4", "c4", &tv.stats.pub);
1575  StatsCounterId c5 = RegisterCounter("t5", "c5", &tv.stats.pub);
1576 
1577  StatsThreadSetupPublic(&tv.stats.pub);
1578  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1580 
1581  StatsCounterIncr(&tv.stats, c5);
1582  StatsCounterAddI64(&tv.stats, c5, 100);
1583 
1584  FAIL_IF_NOT(pca->head[c1.id].v == 0);
1585  FAIL_IF_NOT(pca->head[c5.id].v == 101);
1586 
1588  PASS;
1589 }
1590 
1591 static int StatsTestUpdateGlobalCounter10(void)
1592 {
1593  ThreadVars tv;
1594  memset(&tv, 0, sizeof(ThreadVars));
1596 
1597  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1598  StatsCounterId c2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1599  StatsCounterId c3 = RegisterCounter("t3", "c3", &tv.stats.pub);
1600 
1601  StatsThreadSetupPublic(&tv.stats.pub);
1602  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1604 
1605  StatsCounterIncr(&tv.stats, c1);
1606  StatsCounterAddI64(&tv.stats, c2, 100);
1607  StatsCounterIncr(&tv.stats, c3);
1608  StatsCounterAddI64(&tv.stats, c3, 100);
1609 
1610  StatsUpdateCounterArray(pca, &tv.stats.pub);
1611 
1613  FAIL_IF_NOT(100 == tv.stats.pub.copy_of_private[c2.id].v);
1614  FAIL_IF_NOT(101 == tv.stats.pub.copy_of_private[c3.id].v);
1615 
1617  PASS;
1618 }
1619 
1620 static int StatsTestCounterValues11(void)
1621 {
1622  ThreadVars tv;
1623  memset(&tv, 0, sizeof(ThreadVars));
1625 
1626  StatsCounterId c1 = RegisterCounter("t1", "c1", &tv.stats.pub);
1627  StatsCounterId c2 = RegisterCounter("t2", "c2", &tv.stats.pub);
1628  StatsCounterId c3 = RegisterCounter("t3", "c3", &tv.stats.pub);
1629  StatsCounterId c4 = RegisterCounter("t4", "c4", &tv.stats.pub);
1630 
1631  StatsThreadSetupPublic(&tv.stats.pub);
1632  StatsGetAllCountersArray(&tv.stats.pub, &tv.stats.priv);
1634 
1635  StatsCounterIncr(&tv.stats, c1);
1636  StatsCounterAddI64(&tv.stats, c2, 256);
1637  StatsCounterAddI64(&tv.stats, c3, 257);
1638  StatsCounterAddI64(&tv.stats, c4, 16843024);
1639 
1640  StatsUpdateCounterArray(pca, &tv.stats.pub);
1641 
1643  FAIL_IF_NOT(256 == tv.stats.pub.copy_of_private[c2.id].v);
1644  FAIL_IF_NOT(257 == tv.stats.pub.copy_of_private[c3.id].v);
1645  FAIL_IF_NOT(16843024 == tv.stats.pub.copy_of_private[c4.id].v);
1646 
1648  PASS;
1649 }
1650 
1651 #endif
1652 
1654 {
1655 #ifdef UNITTESTS
1656  UtRegisterTest("StatsTestCounterReg02", StatsTestCounterReg02);
1657  UtRegisterTest("StatsTestCounterReg03", StatsTestCounterReg03);
1658  UtRegisterTest("StatsTestCounterReg04", StatsTestCounterReg04);
1659  UtRegisterTest("StatsTestGetCntArray05", StatsTestGetCntArray05);
1660  UtRegisterTest("StatsTestGetCntArray06", StatsTestGetCntArray06);
1661  UtRegisterTest("StatsTestCntArraySize07", StatsTestCntArraySize07);
1662  UtRegisterTest("StatsTestUpdateCounter08", StatsTestUpdateCounter08);
1663  UtRegisterTest("StatsTestUpdateCounter09", StatsTestUpdateCounter09);
1664  UtRegisterTest("StatsTestUpdateGlobalCounter10",
1665  StatsTestUpdateGlobalCounter10);
1666  UtRegisterTest("StatsTestCounterValues11", StatsTestCounterValues11);
1667 #endif
1668 }
StatsPublicThreadContext_::lock
SCSpinlock lock
Definition: counters.h:115
util-byte.h
tm-threads.h
FROM_TIMEVAL
#define FROM_TIMEVAL(timev)
initialize a 'struct timespec' from a 'struct timeval'.
Definition: util-time.h:124
StatsReleaseResources
void StatsReleaseResources(void)
Releases the resources allotted by the Stats API.
Definition: counters.c:1388
StatsRegisterGlobalCounter
StatsCounterGlobalId StatsRegisterGlobalCounter(const char *name, uint64_t(*Func)(void))
Registers a counter, which represents a global value.
Definition: counters.c:1094
thread_name_counter_wakeup
const char * thread_name_counter_wakeup
Definition: runmodes.c:76
StatsTable_::ntstats
uint32_t ntstats
Definition: output-stats.h:43
len
uint8_t len
Definition: app-layer-dnp3.h:2
StatsCounterMaxUpdateI64
void StatsCounterMaxUpdateI64(StatsThreadContext *stats, StatsCounterMaxId id, int64_t x)
update the value of the localmax counter
Definition: counters.c:225
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1702
SCSpinDestroy
#define SCSpinDestroy
Definition: threads-debug.h:240
TmThreadSetupOptions
TmEcode TmThreadSetupOptions(ThreadVars *tv)
Set the thread options (cpu affinitythread). Priority should be already set by pthread_create.
Definition: tm-threads.c:863
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
StatsSyncCountersIfSignalled
void StatsSyncCountersIfSignalled(StatsThreadContext *stats)
Definition: counters.c:484
StatsThreadStore_
per thread store of counters
Definition: counters.c:67
StatsGlobalContext_
Holds the output interface context for the counter api.
Definition: counters.c:79
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
StatsRecord
struct StatsRecord_ StatsRecord
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
StatsRegisterCounter
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
Definition: counters.c:1039
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:101
StatsSetupPostConfigPreOutput
void StatsSetupPostConfigPreOutput(void)
Definition: counters.c:973
TmThreadWaitForFlag
void TmThreadWaitForFlag(ThreadVars *tv, uint32_t flags)
Waits till the specified flag(s) is(are) set. We don't bother if the kill flag has been set or not on...
Definition: tm-threads.c:1820
STATS_MGMTT_TTS
#define STATS_MGMTT_TTS
Definition: counters.c:48
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
StatsCounter_::type
int type
Definition: counters.h:56
stats_stream_events
bool stats_stream_events
Definition: counters.c:102
name
const char * name
Definition: detect-engine-proto.c:48
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:49
TMM_STATSLOGGER
@ TMM_STATSLOGGER
Definition: tm-threads-common.h:61
THV_DEINIT
#define THV_DEINIT
Definition: threadvars.h:45
CountersIdType
struct CountersIdType_ CountersIdType
StatsCounter_
Container to hold the counter variable.
Definition: counters.h:55
thread_name_counter_stats
const char * thread_name_counter_stats
Definition: runmodes.c:75
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:35
SCSetThreadName
#define SCSetThreadName(n)
Definition: threads.h:305
util-hash.h
StatsRecord_
Definition: output-stats.h:31
StatsPublicThreadContext_::copy_of_private
StatsLocalCounter * copy_of_private
Definition: counters.h:112
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:351
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:55
StatsCounter_::name
const char * name
Definition: counters.h:74
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
SCConfGetChildValueBool
int SCConfGetChildValueBool(const SCConfNode *base, const char *name, int *val)
Definition: conf.c:516
StatsCounter_::did1
uint16_t did1
Definition: counters.h:66
StatsCounter_::Func
uint64_t(* Func)(void)
Definition: counters.h:71
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
HashTable_
Definition: util-hash.h:35
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:453
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:82
SCSpinLock
#define SCSpinLock
Definition: threads-debug.h:236
SCConfValIsFalse
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:577
StatsInit
void StatsInit(void)
Initializes the perf counter api. Things are hard coded currently. More work to be done when we imple...
Definition: counters.c:963
STATS_TYPE_AVERAGE
@ STATS_TYPE_AVERAGE
Definition: counters.c:56
util-privs.h
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
CountersIdType_::string
const char * string
Definition: counters.c:1140
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:89
StatsCounterId
Definition: counters.h:30
m
SCMutex m
Definition: flow-hash.h:6
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:855
JSON_STATS_TOTALS
#define JSON_STATS_TOTALS
Definition: output-json-stats.h:29
StatsRecord_::pvalue
int64_t pvalue
Definition: output-stats.h:36
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
STATS_TYPE_FUNC
@ STATS_TYPE_FUNC
Definition: counters.c:58
StatsRegisterAvgCounter
StatsCounterAvgId StatsRegisterAvgCounter(const char *name, StatsThreadContext *stats)
Registers a counter, whose value holds the average of all the values assigned to it.
Definition: counters.c:1058
StatsCounterDecr
void StatsCounterDecr(StatsThreadContext *stats, StatsCounterId id)
Decrements the local counter.
Definition: counters.c:185
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
HashTableFree
void HashTableFree(HashTable *ht)
Free a HashTable and all its contents.
Definition: util-hash.c:100
ThreadVars_::cap_flags
uint8_t cap_flags
Definition: threadvars.h:80
HashTable_::array_size
uint32_t array_size
Definition: util-hash.h:37
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:53
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:56
StatsThreadStore_::next
struct StatsThreadStore_ * next
Definition: counters.c:73
stats_decoder_events_prefix
const char * stats_decoder_events_prefix
Definition: counters.c:100
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:46
StatsCounterAvgAddI64
void StatsCounterAvgAddI64(StatsThreadContext *stats, StatsCounterAvgId id, int64_t x)
Definition: counters.c:241
STATS_TYPE_MAX
@ STATS_TYPE_MAX
Definition: counters.c:61
STATS_TYPE_MAXIMUM
@ STATS_TYPE_MAXIMUM
Definition: counters.c:57
counters.h
StatsCounter_::short_name
const char * short_name
Definition: counters.h:75
CountersIdType_
Definition: counters.c:1138
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:88
StatsCounter_::next
struct StatsCounter_ * next
Definition: counters.h:78
StatsCounterMaxId
Definition: counters.h:38
StatsSetupPostConfigPostOutput
void StatsSetupPostConfigPostOutput(void)
Definition: counters.c:978
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
StatsGlobalContext_::counters_id_hash
HashTable * counters_id_hash
Definition: counters.c:85
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:182
StatsRecord_::name
const char * name
Definition: output-stats.h:32
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
StatsThreadStore_::name
const char * name
Definition: counters.c:69
THV_KILL
#define THV_KILL
Definition: threadvars.h:40
StatsThreadContext_::pub
StatsPublicThreadContext pub
Definition: counters.h:132
StatsCounterIncr
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
Definition: counters.c:166
SCSpinUnlock
#define SCSpinUnlock
Definition: threads-debug.h:238
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:269
util-time.h
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:120
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:124
StatsPublicThreadContext_
Stats Context for a ThreadVars instance.
Definition: counters.h:92
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
StatsTable_
Definition: output-stats.h:39
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:85
StatsRecord_::value
int64_t value
Definition: output-stats.h:35
SCReturn
#define SCReturn
Definition: util-debug.h:286
SCCtrlMutexLock
#define SCCtrlMutexLock(mut)
Definition: threads-debug.h:377
StatsToJSON
json_t * StatsToJSON(const StatsTable *st, uint8_t flags)
turn StatsTable into a json object
Definition: output-json-stats.c:211
CountersIdType_::id
uint16_t id
Definition: counters.c:1139
type
uint16_t type
Definition: decode-vlan.c:106
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
ThreadVars_::ctrl_cond
SCCtrlCondT * ctrl_cond
Definition: threadvars.h:129
StatsCounterGlobalId::id
uint16_t id
Definition: counters.h:43
StatsCounter_::id
uint16_t id
Definition: counters.h:59
ThreadVars_::thread_setup_flags
uint8_t thread_setup_flags
Definition: threadvars.h:68
TmEcode
TmEcode
Definition: tm-threads-common.h:80
STATS_TYPE_DERIVE_DIV
@ STATS_TYPE_DERIVE_DIV
Definition: counters.c:59
StatsTable_::start_time
time_t start_time
Definition: output-stats.h:44
StatsPrivateThreadContext_
used to hold the private version of the counters registered
Definition: counters.h:121
SCCtrlCondTimedwait
#define SCCtrlCondTimedwait
Definition: threads-debug.h:386
StatsSetupPrivate
int StatsSetupPrivate(StatsThreadContext *stats, const char *thread_name)
Definition: counters.c:1313
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:57
TmThreadCreateMgmtThread
ThreadVars * TmThreadCreateMgmtThread(const char *name, void *(fn_p)(void *), int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
Definition: tm-threads.c:1097
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
STATS_WUT_TTS
#define STATS_WUT_TTS
Definition: counters.c:45
Flow_::next
struct Flow_ * next
Definition: flow.h:387
StatsGlobalContext_::global_counter_ctx
StatsPublicThreadContext global_counter_ctx
Definition: counters.c:87
StatsTable_::stats
StatsRecord * stats
Definition: output-stats.h:40
TmModule_
Definition: tm-modules.h:47
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1333
StatsCounterGlobalId
Definition: counters.h:42
StatsGlobalContext_::sts_lock
SCMutex sts_lock
Definition: counters.c:82
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:37
StatsLocalCounter_
counter type for local (private) increments. For AVG counters we use 2 to track values and updates.
Definition: counters.h:85
SCCtrlMutexUnlock
#define SCCtrlMutexUnlock(mut)
Definition: threads-debug.h:379
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:140
ThreadVars_::inq
Tmq * inq
Definition: threadvars.h:89
util-conf.h
StatsGlobalContext_::sts_cnt
int sts_cnt
Definition: counters.c:83
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
output-json-stats.h
TmThreadsWaitForUnpause
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition: tm-threads.c:363
StatsCounterMaxId::id
uint16_t id
Definition: counters.h:39
StatsPublicThreadContext_::pc_array
const StatsCounter ** pc_array
Definition: counters.h:110
StatsThreadStore_::ctx
StatsPublicThreadContext * ctx
Definition: counters.c:71
StatsEnabled
bool StatsEnabled(void)
Definition: counters.c:117
StatsSpawnThreads
void StatsSpawnThreads(void)
Spawns the wakeup, and the management thread used by the stats api.
Definition: counters.c:990
StatsRecord_::tm_name
const char * tm_name
Definition: output-stats.h:34
StatsSyncCounters
void StatsSyncCounters(StatsThreadContext *stats)
Definition: counters.c:479
StatsCounterGetLocalValue
int64_t StatsCounterGetLocalValue(StatsThreadContext *stats, StatsCounterId id)
Get the value of the local copy of the counter that hold this id.
Definition: counters.c:1376
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
STATS_TYPE_NORMAL
@ STATS_TYPE_NORMAL
Definition: counters.c:55
JSON_STATS_THREADS
#define JSON_STATS_THREADS
Definition: output-json-stats.h:30
StatsCounterAvgId::id
uint16_t id
Definition: counters.h:35
StatsThreadContext_
Definition: counters.h:131
FatalError
#define FatalError(...)
Definition: util-debug.h:517
StatsTable_::tstats
StatsRecord * tstats
Definition: output-stats.h:41
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
threadvars.h
ConfUnixSocketIsEnable
int ConfUnixSocketIsEnable(void)
Definition: util-conf.c:136
SCSpinInit
#define SCSpinInit
Definition: threads-debug.h:239
StatsCounterSetI64
void StatsCounterSetI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
set, so overwrite, the value of the local counter
Definition: counters.c:205
StatsCounter_::gid
uint16_t gid
Definition: counters.h:62
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:182
OutputStatsLoggersRegistered
int OutputStatsLoggersRegistered(void)
Definition: output-stats.c:177
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
head
Flow * head
Definition: flow-hash.h:1
StatsCounterAvgId
Definition: counters.h:34
SCFree
#define SCFree(p)
Definition: util-mem.h:61
StatsPrivateThreadContext_::initialized
int initialized
Definition: counters.h:128
StatsPrivateThreadContext_::size
uint32_t size
Definition: counters.h:126
StatsCounterId::id
uint16_t id
Definition: counters.h:31
StatsRegisterMaxCounter
StatsCounterMaxId StatsRegisterMaxCounter(const char *name, StatsThreadContext *stats)
Registers a counter, whose value holds the maximum of all the values assigned to it.
Definition: counters.c:1077
StatsRecord_::short_name
const char * short_name
Definition: output-stats.h:33
StatsRegisterDeriveDivCounter
StatsCounterDeriveId StatsRegisterDeriveDivCounter(const char *name, const char *dname1, const char *dname2, StatsThreadContext *stats)
Registers a counter which tracks the result of the calculating the value of counter dname1 divided by...
Definition: counters.c:1122
HashTableInit
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hash.c:35
TVT_MGMT
@ TVT_MGMT
Definition: tm-threads-common.h:89
suricata.h
StatsPublicThreadContext_::head
StatsCounter * head
Definition: counters.h:94
GetDocURL
const char * GetDocURL(void)
Definition: suricata.c:1175
StatsGlobalContext_::sts
StatsThreadStore * sts
Definition: counters.c:81
StatsGlobalContext
struct StatsGlobalContext_ StatsGlobalContext
Holds the output interface context for the counter api.
id
uint32_t id
Definition: detect-flowbits.c:944
ThreadVars_::ctrl_mutex
SCCtrlMutex * ctrl_mutex
Definition: threadvars.h:128
StatsThreadStore
struct StatsThreadStore_ StatsThreadStore
per thread store of counters
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
StatsCounter_::did2
uint16_t did2
Definition: counters.h:67
StatsCounterDeriveId
Definition: counters.h:48
stats_decoder_events
bool stats_decoder_events
Definition: counters.c:99
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:93
StatsType
StatsType
Different kinds of qualifier that can be used to modify the behaviour of the counter to be registered...
Definition: counters.c:54
StatsPublicThreadContext_::derive_id
uint16_t derive_id
Definition: counters.h:104
StatsPublicThreadContext_::curr_id
uint16_t curr_id
Definition: counters.h:100
THV_CLOSED
#define THV_CLOSED
Definition: threadvars.h:42
StatsCounterDeriveId::id
uint16_t id
Definition: counters.h:49
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
SCConfNode_
Definition: conf.h:37
StatsCounterAddI64
void StatsCounterAddI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:147
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1429
SCConfNode_::val
char * val
Definition: conf.h:39
StatsTable_::nstats
uint32_t nstats
Definition: output-stats.h:42
SCMutex
#define SCMutex
Definition: threads-debug.h:114
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
StatsPrivateThreadContext_::head
StatsLocalCounter * head
Definition: counters.h:123
OutputStatsLog
TmEcode OutputStatsLog(ThreadVars *tv, void *thread_data, StatsTable *st)
Definition: output-stats.c:77
StatsLocalCounter_::v
int64_t v
Definition: counters.h:86
StatsRegisterTests
void StatsRegisterTests(void)
Definition: counters.c:1653
StatsThreadContext_::priv
StatsPrivateThreadContext priv
Definition: counters.h:133
output.h