suricata
flow-manager.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2024 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 
25 #include "suricata-common.h"
26 #include "conf.h"
27 #include "threadvars.h"
28 #include "tm-threads.h"
29 #include "runmodes.h"
30 
31 #include "util-time.h"
32 
33 #include "flow.h"
34 #include "flow-queue.h"
35 #include "flow-hash.h"
36 #include "flow-util.h"
37 #include "flow-private.h"
38 #include "flow-timeout.h"
39 #include "flow-manager.h"
40 #include "flow-storage.h"
41 #include "flow-spare-pool.h"
42 #include "flow-callbacks.h"
43 
44 #include "stream-tcp.h"
45 #include "stream-tcp-cache.h"
46 
47 #include "util-device.h"
48 
49 #include "util-debug.h"
50 
51 #include "threads.h"
53 
54 #include "host-timeout.h"
55 #include "defrag-hash.h"
56 #include "defrag-timeout.h"
57 #include "ippair-timeout.h"
58 #include "app-layer-htp-range.h"
59 
60 #include "output-flow.h"
61 
62 #include "runmode-unix-socket.h"
63 
64 /** queue to pass flows to cleanup/log thread(s) */
66 
67 /* multi flow manager support */
68 static uint32_t flowmgr_number = 1;
69 /* atomic counter for flow managers, to assign instance id */
70 SC_ATOMIC_DECLARE(uint32_t, flowmgr_cnt);
71 
72 /* multi flow recycler support */
73 static uint32_t flowrec_number = 1;
74 /* atomic counter for flow recyclers, to assign instance id */
75 SC_ATOMIC_DECLARE(uint32_t, flowrec_cnt);
76 SC_ATOMIC_DECLARE(uint32_t, flowrec_busy);
77 SC_ATOMIC_EXTERN(unsigned int, flow_flags);
78 
79 static SCCtrlCondT flow_manager_ctrl_cond = PTHREAD_COND_INITIALIZER;
80 static SCCtrlMutex flow_manager_ctrl_mutex = PTHREAD_MUTEX_INITIALIZER;
81 static SCCtrlCondT flow_recycler_ctrl_cond = PTHREAD_COND_INITIALIZER;
82 static SCCtrlMutex flow_recycler_ctrl_mutex = PTHREAD_MUTEX_INITIALIZER;
83 
85 {
86  SCCtrlMutexLock(&flow_manager_ctrl_mutex);
87  SCCtrlCondSignal(&flow_manager_ctrl_cond);
88  SCCtrlMutexUnlock(&flow_manager_ctrl_mutex);
89 }
90 
92 {
93  SCCtrlMutexLock(&flow_recycler_ctrl_mutex);
94  SCCtrlCondSignal(&flow_recycler_ctrl_cond);
95  SCCtrlMutexUnlock(&flow_recycler_ctrl_mutex);
96 }
97 
98 void FlowTimeoutsInit(void)
99 {
100  SC_ATOMIC_SET(flow_timeouts, flow_timeouts_normal);
101 }
102 
104 {
105  SC_ATOMIC_SET(flow_timeouts, flow_timeouts_emerg);
106 }
107 
108 typedef struct FlowTimeoutCounters_ {
109  uint32_t rows_checked;
110  uint32_t rows_skipped;
111  uint32_t rows_empty;
112  uint32_t rows_maxlen;
113 
114  uint32_t flows_checked;
115  uint32_t flows_notimeout;
116  uint32_t flows_timeout;
117  uint32_t flows_removed;
118  uint32_t flows_aside;
120 
121  uint32_t bypassed_count;
122  uint64_t bypassed_pkts;
123  uint64_t bypassed_bytes;
125 
126 /**
127  * \brief Used to disable flow manager thread(s).
128  *
129  * \todo Kinda hackish since it uses the tv name to identify flow manager
130  * thread. We need an all weather identification scheme.
131  */
133 {
135  /* flow manager thread(s) is/are a part of mgmt threads */
136  for (ThreadVars *tv = tv_root[TVT_MGMT]; tv != NULL; tv = tv->next) {
137  if (strncasecmp(tv->name, thread_name_flow_mgr,
138  strlen(thread_name_flow_mgr)) == 0)
139  {
141  }
142  }
144 
145  struct timeval start_ts;
146  struct timeval cur_ts;
147  gettimeofday(&start_ts, NULL);
148 
149 again:
150  gettimeofday(&cur_ts, NULL);
151  if ((cur_ts.tv_sec - start_ts.tv_sec) > 60) {
152  FatalError("unable to get all flow manager "
153  "threads to shutdown in time");
154  }
155 
157  for (ThreadVars *tv = tv_root[TVT_MGMT]; tv != NULL; tv = tv->next) {
158  if (strncasecmp(tv->name, thread_name_flow_mgr,
159  strlen(thread_name_flow_mgr)) == 0)
160  {
163  /* sleep outside lock */
164  SleepMsec(1);
165  goto again;
166  }
167  }
168  }
170 
171  /* reset count, so we can kill and respawn (unix socket) */
172  SC_ATOMIC_SET(flowmgr_cnt, 0);
173 }
174 
175 /** \internal
176  * \brief check if a flow is timed out
177  *
178  * \param f flow
179  * \param ts timestamp
180  *
181  * \retval false not timed out
182  * \retval true timed out
183  */
184 static bool FlowManagerFlowTimeout(Flow *f, SCTime_t ts, uint32_t *next_ts, const bool emerg)
185 {
186  uint32_t flow_times_out_at = f->timeout_at;
187  if (emerg) {
189  flow_times_out_at -= FlowGetFlowTimeoutDirect(flow_timeouts_delta, f->flow_state, f->protomap);
190  }
191  if (*next_ts == 0 || flow_times_out_at < *next_ts)
192  *next_ts = flow_times_out_at;
193 
194  /* do the timeout check */
195  if ((uint64_t)flow_times_out_at >= SCTIME_SECS(ts)) {
196  return false;
197  }
198 
199  return true;
200 }
201 
202 #ifdef CAPTURE_OFFLOAD
203 /** \internal
204  * \brief check timeout of captured bypassed flow by querying capture method
205  *
206  * \param f Flow
207  * \param ts timestamp
208  * \param counters Flow timeout counters
209  *
210  * \retval false not timeout
211  * \retval true timeout (or not capture bypassed)
212  */
213 static inline bool FlowBypassedTimeout(Flow *f, SCTime_t ts, FlowTimeoutCounters *counters)
214 {
215  if (f->flow_state != FLOW_STATE_CAPTURE_BYPASSED) {
216  return true;
217  }
218 
220  if (fc && fc->BypassUpdate) {
221  /* flow will be possibly updated */
222  uint64_t pkts_tosrc = fc->tosrcpktcnt;
223  uint64_t bytes_tosrc = fc->tosrcbytecnt;
224  uint64_t pkts_todst = fc->todstpktcnt;
225  uint64_t bytes_todst = fc->todstbytecnt;
226  bool update = fc->BypassUpdate(f, fc->bypass_data, SCTIME_SECS(ts));
227  if (update) {
228  SCLogDebug("Updated flow: %"PRId64"", FlowGetId(f));
229  pkts_tosrc = fc->tosrcpktcnt - pkts_tosrc;
230  bytes_tosrc = fc->tosrcbytecnt - bytes_tosrc;
231  pkts_todst = fc->todstpktcnt - pkts_todst;
232  bytes_todst = fc->todstbytecnt - bytes_todst;
233  if (f->livedev) {
234  SC_ATOMIC_ADD(f->livedev->bypassed,
235  pkts_tosrc + pkts_todst);
236  }
237  counters->bypassed_pkts += pkts_tosrc + pkts_todst;
238  counters->bypassed_bytes += bytes_tosrc + bytes_todst;
239  return false;
240  }
241  SCLogDebug("No new packet, dead flow %" PRId64 "", FlowGetId(f));
242  if (f->livedev) {
243  if (FLOW_IS_IPV4(f)) {
244  LiveDevSubBypassStats(f->livedev, 1, AF_INET);
245  } else if (FLOW_IS_IPV6(f)) {
246  LiveDevSubBypassStats(f->livedev, 1, AF_INET6);
247  }
248  }
249  counters->bypassed_count++;
250  }
251  return true;
252 }
253 #endif /* CAPTURE_OFFLOAD */
254 
255 typedef struct FlowManagerTimeoutThread {
256  /* used to temporarily store flows that have timed out and are
257  * removed from the hash to reduce locking contention */
260 
261 /**
262  * \internal
263  *
264  * \brief Process the temporary Aside Queue
265  * This means that as long as a flow f is not waiting on detection
266  * engine to finish dealing with it, f will be put in the recycle
267  * queue for further processing later on.
268  *
269  * \param td FM Timeout Thread instance
270  * \param counters Flow Timeout counters to be updated
271  *
272  * \retval Number of flows that were recycled
273  */
274 static uint32_t ProcessAsideQueue(FlowManagerTimeoutThread *td, FlowTimeoutCounters *counters)
275 {
276  FlowQueuePrivate recycle = { NULL, NULL, 0 };
277  counters->flows_aside += td->aside_queue.len;
278 
279  uint32_t cnt = 0;
280  Flow *f;
281  while ((f = FlowQueuePrivateGetFromTop(&td->aside_queue)) != NULL) {
282  /* flow is still locked */
283 
284  if (f->proto == IPPROTO_TCP &&
286  !FlowIsBypassed(f) && FlowNeedsReassembly(f)) {
287  /* Send the flow to its thread */
289  FLOWLOCK_UNLOCK(f);
290  /* flow ownership is already passed to the worker thread */
291 
292  counters->flows_aside_needs_work++;
293  continue;
294  }
295  FLOWLOCK_UNLOCK(f);
296 
297  FlowQueuePrivateAppendFlow(&recycle, f);
298  if (recycle.len == 100) {
301  }
302  cnt++;
303  }
304  if (recycle.len) {
307  }
308  return cnt;
309 }
310 
311 /**
312  * \internal
313  *
314  * \brief check all flows in a hash row for timing out
315  *
316  * \param f last flow in the hash row
317  * \param ts timestamp
318  * \param emergency bool indicating emergency mode
319  * \param counters ptr to FlowTimeoutCounters structure
320  */
321 static void FlowManagerHashRowTimeout(FlowManagerTimeoutThread *td, Flow *f, SCTime_t ts,
322  int emergency, FlowTimeoutCounters *counters, uint32_t *next_ts)
323 {
324  uint32_t checked = 0;
325  Flow *prev_f = NULL;
326 
327  do {
328  checked++;
329 
330  /* check flow timeout based on lastts and state. Both can be
331  * accessed w/o Flow lock as we do have the hash row lock (so flow
332  * can't disappear) and flow_state is atomic. lastts can only
333  * be modified when we have both the flow and hash row lock */
334 
335  /* timeout logic goes here */
336  if (FlowManagerFlowTimeout(f, ts, next_ts, emergency) == false) {
337  counters->flows_notimeout++;
338 
339  prev_f = f;
340  f = f->next;
341  continue;
342  }
343 
344  FLOWLOCK_WRLOCK(f);
345 
346  Flow *next_flow = f->next;
347 
348 #ifdef CAPTURE_OFFLOAD
349  /* never prune a flow that is used by a packet we
350  * are currently processing in one of the threads */
351  if (!FlowBypassedTimeout(f, ts, counters)) {
352  FLOWLOCK_UNLOCK(f);
353  prev_f = f;
354  f = f->next;
355  continue;
356  }
357 #endif
359 
360  counters->flows_timeout++;
361 
362  RemoveFromHash(f, prev_f);
363 
365  /* flow is still locked in the queue */
366 
367  f = next_flow;
368  } while (f != NULL);
369 
370  counters->flows_checked += checked;
371  if (checked > counters->rows_maxlen)
372  counters->rows_maxlen = checked;
373 }
374 
375 /**
376  * \internal
377  *
378  * \brief Clear evicted list from Flow Manager.
379  * All the evicted flows are removed from the Flow bucket and added
380  * to the temporary Aside Queue.
381  *
382  * \param td FM timeout thread instance
383  * \param f head of the evicted list
384  */
385 static void FlowManagerHashRowClearEvictedList(FlowManagerTimeoutThread *td, Flow *f)
386 {
387  do {
388  FLOWLOCK_WRLOCK(f);
389  Flow *next_flow = f->next;
390  f->next = NULL;
391  f->fb = NULL;
392 
394  /* flow is still locked in the queue */
395 
396  f = next_flow;
397  } while (f != NULL);
398 }
399 
400 /**
401  * \brief time out flows from the hash
402  *
403  * \param ts timestamp
404  * \param hash_min min hash index to consider
405  * \param hash_max max hash index to consider
406  * \param counters ptr to FlowTimeoutCounters structure
407  *
408  * \retval cnt number of timed out flow
409  */
410 static uint32_t FlowTimeoutHash(FlowManagerTimeoutThread *td, SCTime_t ts, const uint32_t hash_min,
411  const uint32_t hash_max, FlowTimeoutCounters *counters)
412 {
413  uint32_t cnt = 0;
414  const int emergency = ((SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY));
415  const uint32_t rows_checked = hash_max - hash_min;
416  uint32_t rows_skipped = 0;
417  uint32_t rows_empty = 0;
418 
419 #if __WORDSIZE==64
420 #define BITS 64
421 #define TYPE uint64_t
422 #else
423 #define BITS 32
424 #define TYPE uint32_t
425 #endif
426 
427  const uint32_t ts_secs = (uint32_t)SCTIME_SECS(ts);
428  for (uint32_t idx = hash_min; idx < hash_max; idx+=BITS) {
429  TYPE check_bits = 0;
430  const uint32_t check = MIN(BITS, (hash_max - idx));
431  for (uint32_t i = 0; i < check; i++) {
432  FlowBucket *fb = &flow_hash[idx+i];
433  check_bits |= (TYPE)(SC_ATOMIC_LOAD_EXPLICIT(
434  fb->next_ts, SC_ATOMIC_MEMORY_ORDER_RELAXED) <= ts_secs)
435  << (TYPE)i;
436  }
437  if (check_bits == 0)
438  continue;
439 
440  for (uint32_t i = 0; i < check; i++) {
441  FlowBucket *fb = &flow_hash[idx+i];
442  if ((check_bits & ((TYPE)1 << (TYPE)i)) != 0 && SC_ATOMIC_GET(fb->next_ts) <= ts_secs) {
443  FBLOCK_LOCK(fb);
444  Flow *evicted = NULL;
445  if (fb->evicted != NULL || fb->head != NULL) {
446  if (fb->evicted != NULL) {
447  /* transfer out of bucket so we can do additional work outside
448  * of the bucket lock */
449  evicted = fb->evicted;
450  fb->evicted = NULL;
451  }
452  if (fb->head != NULL) {
453  uint32_t next_ts = 0;
454  FlowManagerHashRowTimeout(td, fb->head, ts, emergency, counters, &next_ts);
455 
456  if (SC_ATOMIC_GET(fb->next_ts) != next_ts)
457  SC_ATOMIC_SET(fb->next_ts, next_ts);
458  }
459  if (fb->evicted == NULL && fb->head == NULL) {
460  /* row is empty */
461  SC_ATOMIC_SET(fb->next_ts, UINT_MAX);
462  }
463  } else {
464  SC_ATOMIC_SET(fb->next_ts, UINT_MAX);
465  rows_empty++;
466  }
467  FBLOCK_UNLOCK(fb);
468  /* processed evicted list */
469  if (evicted) {
470  FlowManagerHashRowClearEvictedList(td, evicted);
471  }
472  } else {
473  rows_skipped++;
474  }
475  }
476  if (td->aside_queue.len) {
477  cnt += ProcessAsideQueue(td, counters);
478  }
479  }
480 
481  counters->rows_checked += rows_checked;
482  counters->rows_skipped += rows_skipped;
483  counters->rows_empty += rows_empty;
484 
485  if (td->aside_queue.len) {
486  cnt += ProcessAsideQueue(td, counters);
487  }
488  counters->flows_removed += cnt;
489  /* coverity[missing_unlock : FALSE] */
490  return cnt;
491 }
492 
493 /** \internal
494  *
495  * \brief handle timeout for a slice of hash rows
496  * If we wrap around we call FlowTimeoutHash twice
497  * \param td FM timeout thread
498  * \param ts timeout in seconds
499  * \param hash_min lower bound of the row slice
500  * \param hash_max upper bound of the row slice
501  * \param counters Flow timeout counters to be passed
502  * \param rows number of rows for this worker unit
503  * \param pos absolute position of the beginning of row slice in the hash table
504  * \param instance instance id of this FM
505  *
506  * \retval number of successfully timed out flows
507  */
508 static uint32_t FlowTimeoutHashInChunks(FlowManagerTimeoutThread *td, SCTime_t ts,
509  const uint32_t hash_min, const uint32_t hash_max, FlowTimeoutCounters *counters,
510  const uint32_t rows, uint32_t *pos, const uint32_t instance)
511 {
512  uint32_t start = 0;
513  uint32_t end = 0;
514  uint32_t cnt = 0;
515  uint32_t rows_left = rows;
516 
517 again:
518  start = (*pos);
519  if (start >= hash_max) {
520  start = hash_min;
521  }
522  end = start + rows_left;
523  if (end > hash_max) {
524  end = hash_max;
525  }
526  *pos = (end == hash_max) ? hash_min : end;
527  rows_left = rows_left - (end - start);
528 
529  SCLogDebug("instance %u: %u:%u (hash_min %u, hash_max %u *pos %u)", instance, start, end,
530  hash_min, hash_max, *pos);
531 
532  cnt += FlowTimeoutHash(td, ts, start, end, counters);
533  if (rows_left) {
534  goto again;
535  }
536  return cnt;
537 }
538 
539 /**
540  * \internal
541  *
542  * \brief move all flows out of a hash row
543  *
544  * \param f last flow in the hash row
545  * \param recycle_q Flow recycle queue
546  * \param mode emergency or not
547  *
548  * \retval cnt number of flows removed from the hash and added to the recycle queue
549  */
550 static uint32_t FlowManagerHashRowCleanup(Flow *f, FlowQueuePrivate *recycle_q, const int mode)
551 {
552  uint32_t cnt = 0;
553 
554  do {
555  FLOWLOCK_WRLOCK(f);
556 
557  Flow *next_flow = f->next;
558 
559  /* remove from the hash */
560  if (mode == 0) {
561  RemoveFromHash(f, NULL);
562  } else {
563  FlowBucket *fb = f->fb;
564  fb->evicted = f->next;
565  f->next = NULL;
566  f->fb = NULL;
567  }
569 
570  /* no one is referring to this flow, removed from hash
571  * so we can unlock it and move it to the recycle queue. */
572  FLOWLOCK_UNLOCK(f);
573  FlowQueuePrivateAppendFlow(recycle_q, f);
574 
575  cnt++;
576 
577  f = next_flow;
578  } while (f != NULL);
579 
580  return cnt;
581 }
582 
583 #define RECYCLE_MAX_QUEUE_ITEMS 25
584 /**
585  * \brief remove all flows from the hash
586  *
587  * \retval cnt number of removes out flows
588  */
589 static uint32_t FlowCleanupHash(void)
590 {
591  FlowQueuePrivate local_queue = { NULL, NULL, 0 };
592  uint32_t cnt = 0;
593 
594  for (uint32_t idx = 0; idx < flow_config.hash_size; idx++) {
595  FlowBucket *fb = &flow_hash[idx];
596 
597  FBLOCK_LOCK(fb);
598 
599  if (fb->head != NULL) {
600  /* we have a flow, or more than one */
601  cnt += FlowManagerHashRowCleanup(fb->head, &local_queue, 0);
602  }
603  if (fb->evicted != NULL) {
604  /* we have a flow, or more than one */
605  cnt += FlowManagerHashRowCleanup(fb->evicted, &local_queue, 1);
606  }
607 
608  FBLOCK_UNLOCK(fb);
609  if (local_queue.len >= RECYCLE_MAX_QUEUE_ITEMS) {
610  FlowQueueAppendPrivate(&flow_recycle_q, &local_queue);
612  }
613  }
615  FlowQueueAppendPrivate(&flow_recycle_q, &local_queue);
617 
618  return cnt;
619 }
620 
621 typedef struct FlowCounters_ {
624 
625  uint16_t flow_mgr_spare;
628 
634 
636 
640 
641  uint16_t memcap_pressure;
644 
645 typedef struct FlowManagerThreadData_ {
646  uint32_t instance;
647  uint32_t min;
648  uint32_t max;
649 
651 
656 
657 static void FlowCountersInit(ThreadVars *t, FlowCounters *fc)
658 {
659  fc->flow_mgr_full_pass = StatsRegisterCounter("flow.mgr.full_hash_pass", t);
660  fc->flow_mgr_rows_sec = StatsRegisterCounter("flow.mgr.rows_per_sec", t);
661 
662  fc->flow_mgr_spare = StatsRegisterCounter("flow.spare", t);
663  fc->flow_emerg_mode_enter = StatsRegisterCounter("flow.emerg_mode_entered", t);
664  fc->flow_emerg_mode_over = StatsRegisterCounter("flow.emerg_mode_over", t);
665 
666  fc->flow_mgr_rows_maxlen = StatsRegisterMaxCounter("flow.mgr.rows_maxlen", t);
667  fc->flow_mgr_flows_checked = StatsRegisterCounter("flow.mgr.flows_checked", t);
668  fc->flow_mgr_flows_notimeout = StatsRegisterCounter("flow.mgr.flows_notimeout", t);
669  fc->flow_mgr_flows_timeout = StatsRegisterCounter("flow.mgr.flows_timeout", t);
670  fc->flow_mgr_flows_aside = StatsRegisterCounter("flow.mgr.flows_evicted", t);
671  fc->flow_mgr_flows_aside_needs_work = StatsRegisterCounter("flow.mgr.flows_evicted_needs_work", t);
672 
673  fc->flow_bypassed_cnt_clo = StatsRegisterCounter("flow_bypassed.closed", t);
674  fc->flow_bypassed_pkts = StatsRegisterCounter("flow_bypassed.pkts", t);
675  fc->flow_bypassed_bytes = StatsRegisterCounter("flow_bypassed.bytes", t);
676 
677  fc->memcap_pressure = StatsRegisterCounter("memcap.pressure", t);
678  fc->memcap_pressure_max = StatsRegisterMaxCounter("memcap.pressure_max", t);
679 }
680 
681 static void FlowCountersUpdate(
682  ThreadVars *th_v, const FlowManagerThreadData *ftd, const FlowTimeoutCounters *counters)
683 {
684  StatsAddUI64(th_v, ftd->cnt.flow_mgr_flows_checked, (uint64_t)counters->flows_checked);
685  StatsAddUI64(th_v, ftd->cnt.flow_mgr_flows_notimeout, (uint64_t)counters->flows_notimeout);
686 
687  StatsAddUI64(th_v, ftd->cnt.flow_mgr_flows_timeout, (uint64_t)counters->flows_timeout);
688  StatsAddUI64(th_v, ftd->cnt.flow_mgr_flows_aside, (uint64_t)counters->flows_aside);
690  (uint64_t)counters->flows_aside_needs_work);
691 
692  StatsAddUI64(th_v, ftd->cnt.flow_bypassed_cnt_clo, (uint64_t)counters->bypassed_count);
693  StatsAddUI64(th_v, ftd->cnt.flow_bypassed_pkts, (uint64_t)counters->bypassed_pkts);
694  StatsAddUI64(th_v, ftd->cnt.flow_bypassed_bytes, (uint64_t)counters->bypassed_bytes);
695 
696  StatsSetUI64(th_v, ftd->cnt.flow_mgr_rows_maxlen, (uint64_t)counters->rows_maxlen);
697 }
698 
699 static TmEcode FlowManagerThreadInit(ThreadVars *t, const void *initdata, void **data)
700 {
702  if (ftd == NULL)
703  return TM_ECODE_FAILED;
704 
705  ftd->instance = SC_ATOMIC_ADD(flowmgr_cnt, 1);
706  SCLogDebug("flow manager instance %u", ftd->instance);
707 
708  /* set the min and max value used for hash row walking
709  * each thread has it's own section of the flow hash */
710  uint32_t range = flow_config.hash_size / flowmgr_number;
711 
712  ftd->min = ftd->instance * range;
713  ftd->max = (ftd->instance + 1) * range;
714 
715  /* last flow-manager takes on hash_size % flowmgr_number extra rows */
716  if ((ftd->instance + 1) == flowmgr_number) {
717  ftd->max = flow_config.hash_size;
718  }
720 
721  SCLogDebug("instance %u hash range %u %u", ftd->instance, ftd->min, ftd->max);
722 
723  /* pass thread data back to caller */
724  *data = ftd;
725 
726  FlowCountersInit(t, &ftd->cnt);
727  ftd->counter_defrag_timeout = StatsRegisterCounter("defrag.mgr.tracker_timeout", t);
728  ftd->counter_defrag_memuse = StatsRegisterCounter("defrag.memuse", t);
729 
730  PacketPoolInit();
731  return TM_ECODE_OK;
732 }
733 
734 static TmEcode FlowManagerThreadDeinit(ThreadVars *t, void *data)
735 {
738  SCFree(data);
739  return TM_ECODE_OK;
740 }
741 
742 /** \internal
743  * \brief calculate number of rows to scan and how much time to sleep
744  * based on the busy score `mp` (0 idle, 100 max busy).
745  *
746  * We try to to make sure we scan the hash once a second. The number size
747  * of the slice of the hash scanned is determined by our busy score 'mp'.
748  * We sleep for the remainder of the second after processing the slice,
749  * or at least an approximation of it.
750  * A minimum busy score of 10 is assumed to avoid a longer than 10 second
751  * full hash pass. This is to avoid burstiness in scanning when there is
752  * a rapid increase of the busy score, which could lead to the flow manager
753  * suddenly scanning a much larger slice of the hash leading to a burst
754  * in scan/eviction work.
755  *
756  * \param rows number of rows for the work unit
757  * \param mp current memcap pressure value
758  * \param emergency emergency mode is set or not
759  * \param wu_sleep holds value of sleep time per worker unit
760  * \param wu_rows holds value of calculated rows to be processed per second
761  * \param rows_sec same as wu_rows, only used for counter updates
762  */
763 static void GetWorkUnitSizing(const uint32_t rows, const uint32_t mp, const bool emergency,
764  uint64_t *wu_sleep, uint32_t *wu_rows, uint32_t *rows_sec)
765 {
766  if (emergency) {
767  *wu_rows = rows;
768  *wu_sleep = 250;
769  return;
770  }
771  /* minimum busy score is 10 */
772  const uint32_t emp = MAX(mp, 10);
773  const uint32_t rows_per_sec = (uint32_t)((float)rows * (float)((float)emp / (float)100));
774  /* calc how much time we estimate the work will take, in ms. We assume
775  * each row takes an average of 1usec. Maxing out at 1sec. */
776  const uint32_t work_per_unit = MIN(rows_per_sec / 1000, 1000);
777  /* calc how much time we need to sleep to get to the per second cadence
778  * but sleeping for at least 250ms. */
779  const uint32_t sleep_per_unit = MAX(250, 1000 - work_per_unit);
780  SCLogDebug("mp %u emp %u rows %u rows_sec %u sleep %ums", mp, emp, rows, rows_per_sec,
781  sleep_per_unit);
782 
783  *wu_sleep = sleep_per_unit;
784  *wu_rows = rows_per_sec;
785  *rows_sec = rows_per_sec;
786 }
787 
788 /** \brief Thread that manages the flow table and times out flows.
789  *
790  * \param td ThreadVars cast to void ptr
791  *
792  * Keeps an eye on the spare list, alloc flows if needed...
793  */
794 static TmEcode FlowManager(ThreadVars *th_v, void *thread_data)
795 {
796  FlowManagerThreadData *ftd = thread_data;
797  const uint32_t rows = ftd->max - ftd->min;
798  const bool time_is_live = TimeModeIsLive();
799 
800  uint32_t emerg_over_cnt = 0;
801  uint64_t next_run_ms = 0;
802  uint32_t pos = ftd->min;
803  uint32_t rows_sec = 0;
804  uint32_t rows_per_wu = 0;
805  uint64_t sleep_per_wu = 0;
806  bool prev_emerg = false;
807  uint32_t other_last_sec = 0; /**< last sec stamp when defrag etc ran */
808  SCTime_t ts;
809 
810  /* don't start our activities until time is setup */
811  while (!TimeModeIsReady()) {
812  if (suricata_ctl_flags != 0)
813  return TM_ECODE_OK;
814  usleep(10);
815  }
816 
817  uint32_t mp = MemcapsGetPressure() * 100;
818  if (ftd->instance == 0) {
819  StatsSetUI64(th_v, ftd->cnt.memcap_pressure, mp);
820  StatsSetUI64(th_v, ftd->cnt.memcap_pressure_max, mp);
821  }
822  GetWorkUnitSizing(rows, mp, false, &sleep_per_wu, &rows_per_wu, &rows_sec);
823  StatsSetUI64(th_v, ftd->cnt.flow_mgr_rows_sec, rows_sec);
824 
826  bool run = TmThreadsWaitForUnpause(th_v);
827 
828  while (run) {
829  bool emerg = ((SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) != 0);
830 
831  /* Get the time */
832  ts = TimeGet();
833  SCLogDebug("ts %" PRIdMAX "", (intmax_t)SCTIME_SECS(ts));
834  uint64_t ts_ms = SCTIME_MSECS(ts);
835  const bool emerge_p = (emerg && !prev_emerg);
836  if (emerge_p) {
837  next_run_ms = 0;
838  prev_emerg = true;
839  SCLogNotice("Flow emergency mode entered...");
840  StatsIncr(th_v, ftd->cnt.flow_emerg_mode_enter);
841  }
842  if (ts_ms >= next_run_ms) {
843  if (ftd->instance == 0) {
844  const uint32_t sq_len = FlowSpareGetPoolSize();
845  const uint32_t spare_perc = sq_len * 100 / MAX(flow_config.prealloc, 1);
846  /* see if we still have enough spare flows */
847  if (spare_perc < 90 || spare_perc > 110) {
848  FlowSparePoolUpdate(sq_len);
849  }
850  }
851 
852  /* try to time out flows */
853  // clang-format off
854  FlowTimeoutCounters counters = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
855  // clang-format on
856 
857  if (emerg) {
858  /* in emergency mode, do a full pass of the hash table */
859  FlowTimeoutHash(&ftd->timeout, ts, ftd->min, ftd->max, &counters);
860  StatsIncr(th_v, ftd->cnt.flow_mgr_full_pass);
861  } else {
862  SCLogDebug("hash %u:%u slice starting at %u with %u rows", ftd->min, ftd->max, pos,
863  rows_per_wu);
864 
865  const uint32_t ppos = pos;
866  FlowTimeoutHashInChunks(&ftd->timeout, ts, ftd->min, ftd->max, &counters,
867  rows_per_wu, &pos, ftd->instance);
868  if (ppos > pos) {
869  StatsIncr(th_v, ftd->cnt.flow_mgr_full_pass);
870  }
871  }
872 
873  const uint32_t spare_pool_len = FlowSpareGetPoolSize();
874  StatsSetUI64(th_v, ftd->cnt.flow_mgr_spare, (uint64_t)spare_pool_len);
875 
876  FlowCountersUpdate(th_v, ftd, &counters);
877 
878  if (emerg == true) {
879  SCLogDebug("flow_sparse_q.len = %" PRIu32 " prealloc: %" PRIu32
880  "flow_spare_q status: %" PRIu32 "%% flows at the queue",
881  spare_pool_len, flow_config.prealloc,
882  spare_pool_len * 100 / MAX(flow_config.prealloc, 1));
883 
884  /* only if we have pruned this "emergency_recovery" percentage
885  * of flows, we will unset the emergency bit */
886  if ((spare_pool_len * 100 / MAX(flow_config.prealloc, 1)) >
888  emerg_over_cnt++;
889  } else {
890  emerg_over_cnt = 0;
891  }
892 
893  if (emerg_over_cnt >= 30) {
894  SC_ATOMIC_AND(flow_flags, ~FLOW_EMERGENCY);
896 
897  emerg = false;
898  prev_emerg = false;
899  emerg_over_cnt = 0;
900  SCLogNotice("Flow emergency mode over, back to normal... unsetting"
901  " FLOW_EMERGENCY bit (ts.tv_sec: %" PRIuMAX ", "
902  "ts.tv_usec:%" PRIuMAX ") flow_spare_q status(): %" PRIu32
903  "%% flows at the queue",
904  (uintmax_t)SCTIME_SECS(ts), (uintmax_t)SCTIME_USECS(ts),
905  spare_pool_len * 100 / MAX(flow_config.prealloc, 1));
906 
907  StatsIncr(th_v, ftd->cnt.flow_emerg_mode_over);
908  }
909  }
910 
911  /* update work units */
912  const uint32_t pmp = mp;
913  mp = MemcapsGetPressure() * 100;
914  if (ftd->instance == 0) {
915  StatsSetUI64(th_v, ftd->cnt.memcap_pressure, mp);
916  StatsSetUI64(th_v, ftd->cnt.memcap_pressure_max, mp);
917  }
918  GetWorkUnitSizing(rows, mp, emerg, &sleep_per_wu, &rows_per_wu, &rows_sec);
919  if (pmp != mp) {
920  StatsSetUI64(th_v, ftd->cnt.flow_mgr_rows_sec, rows_sec);
921  }
922 
923  next_run_ms = ts_ms + sleep_per_wu;
924  }
925  if (other_last_sec == 0 || other_last_sec < (uint32_t)SCTIME_SECS(ts)) {
926  if (ftd->instance == 0) {
928  uint32_t defrag_cnt = DefragTimeoutHash(ts);
929  if (defrag_cnt) {
930  StatsAddUI64(th_v, ftd->counter_defrag_timeout, defrag_cnt);
931  }
936  other_last_sec = (uint32_t)SCTIME_SECS(ts);
937  }
938  }
939 
940  if (TmThreadsCheckFlag(th_v, THV_KILL)) {
941  StatsSyncCounters(th_v);
942  break;
943  }
944 
945  if (emerg || !time_is_live) {
946  usleep(250);
947  } else {
948  struct timeval cond_tv;
949  gettimeofday(&cond_tv, NULL);
950  struct timeval add_tv;
951  add_tv.tv_sec = sleep_per_wu / 1000;
952  add_tv.tv_usec = (sleep_per_wu % 1000) * 1000;
953  timeradd(&cond_tv, &add_tv, &cond_tv);
954 
955  struct timespec cond_time = FROM_TIMEVAL(cond_tv);
956  SCCtrlMutexLock(&flow_manager_ctrl_mutex);
957  while (1) {
958  int rc = SCCtrlCondTimedwait(
959  &flow_manager_ctrl_cond, &flow_manager_ctrl_mutex, &cond_time);
960  if (rc == ETIMEDOUT || rc < 0)
961  break;
962  if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) {
963  break;
964  }
965  }
966  SCCtrlMutexUnlock(&flow_manager_ctrl_mutex);
967  }
968 
969  SCLogDebug("woke up... %s", SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY ? "emergency":"");
970 
972  }
973  return TM_ECODE_OK;
974 }
975 
976 /** \brief spawn the flow manager thread */
978 {
979  intmax_t setting = 1;
980  (void)ConfGetInt("flow.managers", &setting);
981 
982  if (setting < 1 || setting > 1024) {
983  FatalError("invalid flow.managers setting %" PRIdMAX, setting);
984  }
985  flowmgr_number = (uint32_t)setting;
986 
987  SCLogConfig("using %u flow manager threads", flowmgr_number);
989 
990  for (uint32_t u = 0; u < flowmgr_number; u++) {
991  char name[TM_THREAD_NAME_MAX];
992  snprintf(name, sizeof(name), "%s#%02u", thread_name_flow_mgr, u+1);
993 
994  ThreadVars *tv_flowmgr = TmThreadCreateMgmtThreadByName(name,
995  "FlowManager", 0);
996  BUG_ON(tv_flowmgr == NULL);
997 
998  if (tv_flowmgr == NULL) {
999  FatalError("flow manager thread creation failed");
1000  }
1001  if (TmThreadSpawn(tv_flowmgr) != TM_ECODE_OK) {
1002  FatalError("flow manager thread spawn failed");
1003  }
1004  }
1005 }
1006 
1007 typedef struct FlowRecyclerThreadData_ {
1009 
1010  uint16_t counter_flows;
1013 
1018 
1019 static TmEcode FlowRecyclerThreadInit(ThreadVars *t, const void *initdata, void **data)
1020 {
1022  if (ftd == NULL)
1023  return TM_ECODE_FAILED;
1025  SCLogError("initializing flow log API for thread failed");
1026  SCFree(ftd);
1027  return TM_ECODE_FAILED;
1028  }
1029  SCLogDebug("output_thread_data %p", ftd->output_thread_data);
1030 
1031  ftd->counter_flows = StatsRegisterCounter("flow.recycler.recycled", t);
1032  ftd->counter_queue_avg = StatsRegisterAvgCounter("flow.recycler.queue_avg", t);
1033  ftd->counter_queue_max = StatsRegisterMaxCounter("flow.recycler.queue_max", t);
1034 
1035  ftd->counter_flow_active = StatsRegisterCounter("flow.active", t);
1036  ftd->counter_tcp_active_sessions = StatsRegisterCounter("tcp.active_sessions", t);
1037 
1038  FlowEndCountersRegister(t, &ftd->fec);
1039 
1040  *data = ftd;
1041  return TM_ECODE_OK;
1042 }
1043 
1044 static TmEcode FlowRecyclerThreadDeinit(ThreadVars *t, void *data)
1045 {
1047 
1049  if (ftd->output_thread_data != NULL)
1051 
1052  SCFree(data);
1053  return TM_ECODE_OK;
1054 }
1055 
1056 static void Recycler(ThreadVars *tv, FlowRecyclerThreadData *ftd, Flow *f)
1057 {
1058  FLOWLOCK_WRLOCK(f);
1059 
1060  (void)OutputFlowLog(tv, ftd->output_thread_data, f);
1061 
1062  FlowEndCountersUpdate(tv, &ftd->fec, f);
1063  if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1065  }
1068  FlowClearMemory(f, f->protomap);
1069  FLOWLOCK_UNLOCK(f);
1070 }
1071 
1072 /** \brief Thread that manages timed out flows.
1073  *
1074  * \param td ThreadVars cast to void ptr
1075  */
1076 static TmEcode FlowRecycler(ThreadVars *th_v, void *thread_data)
1077 {
1078  FlowRecyclerThreadData *ftd = (FlowRecyclerThreadData *)thread_data;
1079  BUG_ON(ftd == NULL);
1080  const bool time_is_live = TimeModeIsLive();
1081  uint64_t recycled_cnt = 0;
1082  FlowQueuePrivate ret_queue = { NULL, NULL, 0 };
1083 
1085  bool run = TmThreadsWaitForUnpause(th_v);
1086 
1087  while (run) {
1088  SC_ATOMIC_ADD(flowrec_busy,1);
1090 
1091  StatsAddUI64(th_v, ftd->counter_queue_avg, list.len);
1092  StatsSetUI64(th_v, ftd->counter_queue_max, list.len);
1093 
1094  const int bail = (TmThreadsCheckFlag(th_v, THV_KILL));
1095 
1096  /* Get the time */
1097  SCLogDebug("ts %" PRIdMAX "", (intmax_t)SCTIME_SECS(TimeGet()));
1098 
1099  uint64_t cnt = 0;
1100  Flow *f;
1101  while ((f = FlowQueuePrivateGetFromTop(&list)) != NULL) {
1102  Recycler(th_v, ftd, f);
1103  cnt++;
1104 
1105  /* for every full sized block, add it to the spare pool */
1106  FlowQueuePrivateAppendFlow(&ret_queue, f);
1107  if (ret_queue.len == FLOW_SPARE_POOL_BLOCK_SIZE) {
1108  FlowSparePoolReturnFlows(&ret_queue);
1109  }
1110  }
1111  if (ret_queue.len > 0) {
1112  FlowSparePoolReturnFlows(&ret_queue);
1113  }
1114  if (cnt > 0) {
1115  recycled_cnt += cnt;
1116  StatsAddUI64(th_v, ftd->counter_flows, cnt);
1117  }
1118  SC_ATOMIC_SUB(flowrec_busy,1);
1119 
1120  if (bail) {
1121  break;
1122  }
1123 
1124  const bool emerg = (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY);
1125  if (emerg || !time_is_live) {
1126  usleep(250);
1127  } else {
1128  struct timeval cond_tv;
1129  gettimeofday(&cond_tv, NULL);
1130  cond_tv.tv_sec += 1;
1131  struct timespec cond_time = FROM_TIMEVAL(cond_tv);
1132  SCCtrlMutexLock(&flow_recycler_ctrl_mutex);
1133  while (1) {
1134  int rc = SCCtrlCondTimedwait(
1135  &flow_recycler_ctrl_cond, &flow_recycler_ctrl_mutex, &cond_time);
1136  if (rc == ETIMEDOUT || rc < 0) {
1137  break;
1138  }
1139  if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) {
1140  break;
1141  }
1142  if (SC_ATOMIC_GET(flow_recycle_q.non_empty) == true) {
1143  break;
1144  }
1145  }
1146  SCCtrlMutexUnlock(&flow_recycler_ctrl_mutex);
1147  }
1148 
1149  SCLogDebug("woke up...");
1150 
1152  }
1153  StatsSyncCounters(th_v);
1154  SCLogPerf("%"PRIu64" flows processed", recycled_cnt);
1155  return TM_ECODE_OK;
1156 }
1157 
1158 static bool FlowRecyclerReadyToShutdown(void)
1159 {
1160  if (SC_ATOMIC_GET(flowrec_busy) != 0) {
1161  return false;
1162  }
1163  uint32_t len = 0;
1165  len = flow_recycle_q.qlen;
1167 
1168  return ((len == 0));
1169 }
1170 
1171 /** \brief spawn the flow recycler thread */
1173 {
1174  intmax_t setting = 1;
1175  (void)ConfGetInt("flow.recyclers", &setting);
1176 
1177  if (setting < 1 || setting > 1024) {
1178  FatalError("invalid flow.recyclers setting %" PRIdMAX, setting);
1179  }
1180  flowrec_number = (uint32_t)setting;
1181 
1182  SCLogConfig("using %u flow recycler threads", flowrec_number);
1183 
1184  for (uint32_t u = 0; u < flowrec_number; u++) {
1185  char name[TM_THREAD_NAME_MAX];
1186  snprintf(name, sizeof(name), "%s#%02u", thread_name_flow_rec, u+1);
1187 
1188  ThreadVars *tv_flowrec = TmThreadCreateMgmtThreadByName(name,
1189  "FlowRecycler", 0);
1190 
1191  if (tv_flowrec == NULL) {
1192  FatalError("flow recycler thread creation failed");
1193  }
1194  if (TmThreadSpawn(tv_flowrec) != TM_ECODE_OK) {
1195  FatalError("flow recycler thread spawn failed");
1196  }
1197  }
1198 }
1199 
1200 /**
1201  * \brief Used to disable flow recycler thread(s).
1202  *
1203  * \note this should only be called when the flow manager is already gone
1204  *
1205  * \todo Kinda hackish since it uses the tv name to identify flow recycler
1206  * thread. We need an all weather identification scheme.
1207  */
1209 {
1210  /* move all flows still in the hash to the recycler queue */
1211 #ifndef DEBUG
1212  (void)FlowCleanupHash();
1213 #else
1214  uint32_t flows = FlowCleanupHash();
1215  SCLogDebug("flows to progress: %u", flows);
1216 #endif
1217 
1218  /* make sure all flows are processed */
1219  do {
1221  usleep(10);
1222  } while (FlowRecyclerReadyToShutdown() == false);
1223 
1225  /* flow recycler thread(s) is/are a part of mgmt threads */
1226  for (ThreadVars *tv = tv_root[TVT_MGMT]; tv != NULL; tv = tv->next) {
1227  if (strncasecmp(tv->name, thread_name_flow_rec,
1228  strlen(thread_name_flow_rec)) == 0)
1229  {
1231  }
1232  }
1234 
1235  struct timeval start_ts;
1236  struct timeval cur_ts;
1237  gettimeofday(&start_ts, NULL);
1238 
1239 again:
1240  gettimeofday(&cur_ts, NULL);
1241  if ((cur_ts.tv_sec - start_ts.tv_sec) > 60) {
1242  FatalError("unable to get all flow recycler "
1243  "threads to shutdown in time");
1244  }
1245 
1247  for (ThreadVars *tv = tv_root[TVT_MGMT]; tv != NULL; tv = tv->next) {
1248  if (strncasecmp(tv->name, thread_name_flow_rec,
1249  strlen(thread_name_flow_rec)) == 0)
1250  {
1254  /* sleep outside lock */
1255  SleepMsec(1);
1256  goto again;
1257  }
1258  }
1259  }
1261 
1262  /* reset count, so we can kill and respawn (unix socket) */
1263  SC_ATOMIC_SET(flowrec_cnt, 0);
1264 }
1265 
1267 {
1268  tmm_modules[TMM_FLOWMANAGER].name = "FlowManager";
1269  tmm_modules[TMM_FLOWMANAGER].ThreadInit = FlowManagerThreadInit;
1270  tmm_modules[TMM_FLOWMANAGER].ThreadDeinit = FlowManagerThreadDeinit;
1271  tmm_modules[TMM_FLOWMANAGER].Management = FlowManager;
1274  SCLogDebug("%s registered", tmm_modules[TMM_FLOWMANAGER].name);
1275 
1276  SC_ATOMIC_INIT(flowmgr_cnt);
1277  SC_ATOMIC_INITPTR(flow_timeouts);
1278 }
1279 
1281 {
1282  tmm_modules[TMM_FLOWRECYCLER].name = "FlowRecycler";
1283  tmm_modules[TMM_FLOWRECYCLER].ThreadInit = FlowRecyclerThreadInit;
1284  tmm_modules[TMM_FLOWRECYCLER].ThreadDeinit = FlowRecyclerThreadDeinit;
1285  tmm_modules[TMM_FLOWRECYCLER].Management = FlowRecycler;
1288  SCLogDebug("%s registered", tmm_modules[TMM_FLOWRECYCLER].name);
1289 
1290  SC_ATOMIC_INIT(flowrec_cnt);
1291  SC_ATOMIC_INIT(flowrec_busy);
1292 }
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:73
FlowTimeoutCounters_::rows_empty
uint32_t rows_empty
Definition: flow-manager.c:111
FlowSparePoolUpdate
void FlowSparePoolUpdate(uint32_t size)
Definition: flow-spare-pool.c:217
FlowManagerThreadSpawn
void FlowManagerThreadSpawn(void)
spawn the flow manager thread
Definition: flow-manager.c:977
tm-threads.h
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:399
FROM_TIMEVAL
#define FROM_TIMEVAL(timev)
initialize a 'struct timespec' from a 'struct timeval'.
Definition: util-time.h:124
OutputFlowLog
TmEcode OutputFlowLog(ThreadVars *tv, void *thread_data, Flow *f)
Run flow logger(s)
Definition: output-flow.c:87
FlowRecyclerThreadData_::fec
FlowEndCounters fec
Definition: flow-manager.c:1016
len
uint8_t len
Definition: app-layer-dnp3.h:2
ts
uint64_t ts
Definition: source-erf-file.c:55
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1663
app-layer-htp-range.h
FlowTimeoutCounters
Definition: flow-worker.c:61
TmThreadCreateMgmtThreadByName
ThreadVars * TmThreadCreateMgmtThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
Definition: tm-threads.c:1101
FlowBucket_::evicted
Flow * evicted
Definition: flow-hash.h:48
OutputFlowLogThreadInit
TmEcode OutputFlowLogThreadInit(ThreadVars *tv, void **data)
thread init for the flow logger This will run the thread init functions for the individual registered...
Definition: output-flow.c:123
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:166
FLOW_IS_IPV6
#define FLOW_IS_IPV6(f)
Definition: flow.h:171
FlowManagerThreadData_::max
uint32_t max
Definition: flow-manager.c:648
FlowManagerTimeoutThread
Definition: flow-manager.c:255
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
thread_name_flow_mgr
const char * thread_name_flow_mgr
Definition: runmodes.c:68
FlowSpareGetPoolSize
uint32_t FlowSpareGetPoolSize(void)
Definition: flow-spare-pool.c:46
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
FlowManagerThreadData_::cnt
FlowCounters cnt
Definition: flow-manager.c:650
FBLOCK_LOCK
#define FBLOCK_LOCK(fb)
Definition: flow-hash.h:73
SCTIME_MSECS
#define SCTIME_MSECS(t)
Definition: util-time.h:58
TMM_FLOWRECYCLER
@ TMM_FLOWRECYCLER
Definition: tm-threads-common.h:69
stream-tcp.h
GetFlowBypassInfoID
FlowStorageId GetFlowBypassInfoID(void)
Definition: flow-util.c:214
FlowBypassInfo_
Definition: flow.h:531
FlowCnf_::emergency_recovery
uint32_t emergency_recovery
Definition: flow.h:300
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
FlowCnf_::hash_size
uint32_t hash_size
Definition: flow.h:294
FlowManagerThreadData_::instance
uint32_t instance
Definition: flow-manager.c:646
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
IPPairTimeoutHash
uint32_t IPPairTimeoutHash(SCTime_t ts)
time out ippairs from the hash
Definition: ippair-timeout.c:124
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:101
StatsRegisterGlobalCounter
uint16_t StatsRegisterGlobalCounter(const char *name, uint64_t(*Func)(void))
Registers a counter, which represents a global value.
Definition: counters.c:1009
Flow_::proto
uint8_t proto
Definition: flow.h:378
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint32_t, flowmgr_cnt)
threads.h
FlowSendToLocalThread
void FlowSendToLocalThread(Flow *f)
Definition: flow-timeout.c:353
flow-private.h
FlowCounters_::flow_mgr_flows_notimeout
uint16_t flow_mgr_flows_notimeout
Definition: flow-manager.c:630
Flow_
Flow data structure.
Definition: flow.h:356
TYPE
#define TYPE
Flow_::protomap
uint8_t protomap
Definition: flow.h:450
SC_ATOMIC_EXTERN
SC_ATOMIC_EXTERN(unsigned int, flow_flags)
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
thread_name_flow_rec
const char * thread_name_flow_rec
Definition: runmodes.c:69
FlowProtoTimeout_
Definition: flow.h:520
StatsSetUI64
void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Sets a value of type double to the local counter.
Definition: counters.c:207
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:55
flow-hash.h
TmModuleFlowRecyclerRegister
void TmModuleFlowRecyclerRegister(void)
Definition: flow-manager.c:1280
FlowTimeoutCounters_::flows_removed
uint32_t flows_removed
Definition: flow-manager.c:117
FlowBypassInfo_::tosrcbytecnt
uint64_t tosrcbytecnt
Definition: flow.h:536
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
FlowGetMemuse
uint64_t FlowGetMemuse(void)
Definition: flow.c:126
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:82
FlowTimeoutCounters_::flows_timeout
uint32_t flows_timeout
Definition: flow-manager.c:116
defrag-timeout.h
FlowRecyclerThreadData_::counter_flows
uint16_t counter_flows
Definition: flow-manager.c:1010
FlowManagerThreadData_::counter_defrag_memuse
uint16_t counter_defrag_memuse
Definition: flow-manager.c:654
FLOW_ACTION_DROP
#define FLOW_ACTION_DROP
Definition: flow.h:69
FLOW_PROTO_MAX
@ FLOW_PROTO_MAX
Definition: flow-private.h:74
LiveDevSubBypassStats
void LiveDevSubBypassStats(LiveDevice *dev, uint64_t cnt, int family)
Definition: util-device.c:515
MAX
#define MAX(x, y)
Definition: suricata-common.h:395
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
FlowQueuePrivate_::len
uint32_t len
Definition: flow-queue.h:44
Flow_::protoctx
void * protoctx
Definition: flow.h:446
FlowCounters_
Definition: flow-manager.c:621
FlowManagerTimeoutThread
struct FlowManagerTimeoutThread FlowManagerTimeoutThread
SCCtrlCondSignal
#define SCCtrlCondSignal
Definition: threads-debug.h:384
FlowCounters_::flow_mgr_flows_aside
uint16_t flow_mgr_flows_aside
Definition: flow-manager.c:632
FLOW_TIMEOUT_REASSEMBLY_DONE
#define FLOW_TIMEOUT_REASSEMBLY_DONE
Definition: flow.h:96
runmode-unix-socket.h
FlowTimeoutCounters_::bypassed_count
uint32_t bypassed_count
Definition: flow-manager.c:121
FlowSparePoolReturnFlows
void FlowSparePoolReturnFlows(FlowQueuePrivate *fqp)
Definition: flow-spare-pool.c:120
TM_THREAD_NAME_MAX
#define TM_THREAD_NAME_MAX
Definition: tm-threads.h:49
FlowCnf_::prealloc
uint32_t prealloc
Definition: flow.h:295
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:273
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
PacketPoolInit
void PacketPoolInit(void)
Definition: tmqh-packetpool.c:244
Flow_::flow_state
FlowStateType flow_state
Definition: flow.h:417
FQLOCK_LOCK
#define FQLOCK_LOCK(q)
Definition: flow-queue.h:73
FlowWakeupFlowManagerThread
void FlowWakeupFlowManagerThread(void)
Definition: flow-manager.c:84
FlowDisableFlowRecyclerThread
void FlowDisableFlowRecyclerThread(void)
Used to disable flow recycler thread(s).
Definition: flow-manager.c:1208
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
FlowTimeoutCounters_::rows_maxlen
uint32_t rows_maxlen
Definition: flow-manager.c:112
FlowCounters_::flow_bypassed_bytes
uint16_t flow_bypassed_bytes
Definition: flow-manager.c:639
FlowTimeoutCounters_::flows_checked
uint32_t flows_checked
Definition: flow-manager.c:114
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:46
flow-spare-pool.h
StatsDecr
void StatsDecr(ThreadVars *tv, uint16_t id)
Decrements the local counter.
Definition: counters.c:186
Flow_::fb
struct FlowBucket_ * fb
Definition: flow.h:493
FlowCounters_::flow_mgr_full_pass
uint16_t flow_mgr_full_pass
Definition: flow-manager.c:622
StatsRegisterMaxCounter
uint16_t StatsRegisterMaxCounter(const char *name, struct ThreadVars_ *tv)
Registers a counter, whose value holds the maximum of all the values assigned to it.
Definition: counters.c:991
SC_ATOMIC_MEMORY_ORDER_RELAXED
#define SC_ATOMIC_MEMORY_ORDER_RELAXED
Definition: util-atomic.h:165
util-device.h
util-debug.h
FlowWakeupFlowRecyclerThread
void FlowWakeupFlowRecyclerThread(void)
Definition: flow-manager.c:91
FlowBypassInfo_::todstbytecnt
uint64_t todstbytecnt
Definition: flow.h:538
SCFlowRunFinishCallbacks
void SCFlowRunFinishCallbacks(ThreadVars *tv, Flow *f)
Definition: flow-callbacks.c:122
FlowBypassInfo_::BypassUpdate
bool(* BypassUpdate)(Flow *f, void *data, time_t tsec)
Definition: flow.h:532
FlowRecyclerThreadData_::counter_queue_avg
uint16_t counter_queue_avg
Definition: flow-manager.c:1011
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
FlowCounters_::flow_mgr_rows_maxlen
uint16_t flow_mgr_rows_maxlen
Definition: flow-manager.c:635
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:270
FlowTimeoutsReset
#define FlowTimeoutsReset()
Definition: flow-manager.h:30
FlowDisableFlowManagerThread
void FlowDisableFlowManagerThread(void)
Used to disable flow manager thread(s).
Definition: flow-manager.c:132
SCCtrlCondT
#define SCCtrlCondT
Definition: threads-debug.h:382
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
TmModule_::Management
TmEcode(* Management)(ThreadVars *, void *)
Definition: tm-modules.h:65
TimeModeIsReady
bool TimeModeIsReady(void)
Definition: util-time.c:92
Flow_::flow_end_flags
uint8_t flow_end_flags
Definition: flow.h:452
THV_KILL
#define THV_KILL
Definition: threadvars.h:40
MemcapsGetPressure
float MemcapsGetPressure(void)
Definition: runmode-unix-socket.c:110
FlowBypassInfo_::todstpktcnt
uint64_t todstpktcnt
Definition: flow.h:537
util-time.h
FlowQueuePrivateGetFromTop
Flow * FlowQueuePrivateGetFromTop(FlowQueuePrivate *fqc)
Definition: flow-queue.c:151
FlowBypassInfo_::bypass_data
void * bypass_data
Definition: flow.h:534
FlowQueueAppendPrivate
void FlowQueueAppendPrivate(FlowQueue *fq, FlowQueuePrivate *fqc)
Definition: flow-queue.c:119
FlowCounters_::flow_mgr_flows_aside_needs_work
uint16_t flow_mgr_flows_aside_needs_work
Definition: flow-manager.c:633
DefragTrackerGetMemcap
uint64_t DefragTrackerGetMemcap(void)
Return memcap value.
Definition: defrag-hash.c:63
TVT_MGMT
@ TVT_MGMT
Definition: tm-threads-common.h:88
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:125
FlowRecyclerThreadData_
Definition: flow-manager.c:1007
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:169
FlowRecyclerThreadData_::counter_tcp_active_sessions
uint16_t counter_tcp_active_sessions
Definition: flow-manager.c:1015
FlowCounters_::flow_bypassed_cnt_clo
uint16_t flow_bypassed_cnt_clo
Definition: flow-manager.c:637
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:85
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
flow_timeouts_emerg
FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX]
Definition: flow.c:87
TimeModeIsLive
bool TimeModeIsLive(void)
Definition: util-time.c:111
SCCtrlMutexLock
#define SCCtrlMutexLock(mut)
Definition: threads-debug.h:376
FlowTimeoutsEmergency
void FlowTimeoutsEmergency(void)
Definition: flow-manager.c:103
FlowTimeoutCounters
struct FlowTimeoutCounters_ FlowTimeoutCounters
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:29
TimeGet
SCTime_t TimeGet(void)
Definition: util-time.c:152
conf.h
FlowRecyclerThreadData_::output_thread_data
void * output_thread_data
Definition: flow-manager.c:1008
FlowTimeoutCounters_::rows_checked
uint32_t rows_checked
Definition: flow-manager.c:109
FBLOCK_UNLOCK
#define FBLOCK_UNLOCK(fb)
Definition: flow-hash.h:75
SCTime_t
Definition: util-time.h:40
TmEcode
TmEcode
Definition: tm-threads-common.h:79
FlowClearMemory
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
Definition: flow.c:1096
flow_timeouts_delta
FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX]
Definition: flow.c:88
FlowRecyclerThreadSpawn
void FlowRecyclerThreadSpawn(void)
spawn the flow recycler thread
Definition: flow-manager.c:1172
output-flow.h
flow-timeout.h
flow-queue.h
FlowManagerThreadData_::counter_defrag_timeout
uint16_t counter_defrag_timeout
Definition: flow-manager.c:653
TmModule_::name
const char * name
Definition: tm-modules.h:44
FlowRecyclerThreadData
struct FlowRecyclerThreadData_ FlowRecyclerThreadData
FlowBypassInfo_::tosrcpktcnt
uint64_t tosrcpktcnt
Definition: flow.h:535
host-timeout.h
SCCtrlCondTimedwait
#define SCCtrlCondTimedwait
Definition: threads-debug.h:385
StreamTcpThreadCacheCleanup
void StreamTcpThreadCacheCleanup(void)
Definition: stream-tcp-cache.c:134
runmodes.h
FlowTimeoutCounters_::flows_aside_needs_work
uint32_t flows_aside_needs_work
Definition: flow-manager.c:119
FlowGetStorageById
void * FlowGetStorageById(const Flow *f, FlowStorageId id)
Definition: flow-storage.c:40
Flow_::next
struct Flow_ * next
Definition: flow.h:401
FlowQueue_
Definition: flow-queue.h:49
FlowCounters_::flow_bypassed_pkts
uint16_t flow_bypassed_pkts
Definition: flow-manager.c:638
TMM_FLOWMANAGER
@ TMM_FLOWMANAGER
Definition: tm-threads-common.h:68
RECYCLE_MAX_QUEUE_ITEMS
#define RECYCLE_MAX_QUEUE_ITEMS
Definition: flow-manager.c:583
flow_hash
FlowBucket * flow_hash
Definition: flow-hash.c:59
SCCtrlMutexUnlock
#define SCCtrlMutexUnlock(mut)
Definition: threads-debug.h:378
FlowQueueExtractPrivate
FlowQueuePrivate FlowQueueExtractPrivate(FlowQueue *fq)
Definition: flow-queue.c:140
flow-storage.h
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
FlowTimeoutCounters_
Definition: flow-manager.c:108
FlowManagerThreadData_
Definition: flow-manager.c:645
SleepMsec
#define SleepMsec(msec)
Definition: tm-threads.h:45
flow-manager.h
suricata-common.h
SCCtrlMutex
#define SCCtrlMutex
Definition: threads-debug.h:373
DefragTimeoutHash
uint32_t DefragTimeoutHash(SCTime_t ts)
time out tracker from the hash
Definition: defrag-timeout.c:122
FlowManagerThreadData
struct FlowManagerThreadData_ FlowManagerThreadData
flow_config
FlowConfig flow_config
Definition: flow.c:91
TmThreadsWaitForUnpause
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition: tm-threads.c:364
TmModuleFlowManagerRegister
void TmModuleFlowManagerRegister(void)
Definition: flow-manager.c:1266
FlowCounters_::memcap_pressure
uint16_t memcap_pressure
Definition: flow-manager.c:641
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:230
FlowTimeoutsInit
void FlowTimeoutsInit(void)
Definition: flow-manager.c:98
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
SC_ATOMIC_LOAD_EXPLICIT
#define SC_ATOMIC_LOAD_EXPLICIT(name, order)
Definition: util-atomic.h:378
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
FatalError
#define FatalError(...)
Definition: util-debug.h:502
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
StatsSyncCounters
void StatsSyncCounters(ThreadVars *tv)
Definition: counters.c:444
Flow_::livedev
struct LiveDevice_ * livedev
Definition: flow.h:403
threadvars.h
FlowQueuePrivate_
Definition: flow-queue.h:41
StatsAddUI64
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:146
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
FlowRecyclerThreadData_::counter_queue_max
uint16_t counter_queue_max
Definition: flow-manager.c:1012
FlowTimeoutCounters_::bypassed_bytes
uint64_t bypassed_bytes
Definition: flow-manager.c:123
FlowManagerThreadData_::min
uint32_t min
Definition: flow-manager.c:647
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
OutputFlowLogThreadDeinit
TmEcode OutputFlowLogThreadDeinit(ThreadVars *tv, void *thread_data)
Definition: output-flow.c:163
flow_recycle_q
FlowQueue flow_recycle_q
Definition: flow-manager.c:65
flow-callbacks.h
SCFree
#define SCFree(p)
Definition: util-mem.h:61
FlowTimeoutCounters_::bypassed_pkts
uint64_t bypassed_pkts
Definition: flow-manager.c:122
FlowCounters_::memcap_pressure_max
uint16_t memcap_pressure_max
Definition: flow-manager.c:642
Flow_::flags
uint32_t flags
Definition: flow.h:426
HostTimeoutHash
uint32_t HostTimeoutHash(SCTime_t ts)
time out hosts from the hash
Definition: host-timeout.c:126
SC_ATOMIC_INITPTR
#define SC_ATOMIC_INITPTR(name)
Definition: util-atomic.h:317
stream-tcp-cache.h
FlowManagerThreadData_::timeout
FlowManagerTimeoutThread timeout
Definition: flow-manager.c:652
FlowCounters
struct FlowCounters_ FlowCounters
FlowCounters_::flow_emerg_mode_enter
uint16_t flow_emerg_mode_enter
Definition: flow-manager.c:626
FLOW_END_FLAG_SHUTDOWN
#define FLOW_END_FLAG_SHUTDOWN
Definition: flow.h:246
FLOW_EMERGENCY
#define FLOW_EMERGENCY
Definition: flow-private.h:37
defrag-hash.h
ippair-timeout.h
FlowRecyclerThreadData_::counter_flow_active
uint16_t counter_flow_active
Definition: flow-manager.c:1014
FlowCounters_::flow_mgr_flows_timeout
uint16_t flow_mgr_flows_timeout
Definition: flow-manager.c:631
FlowManagerTimeoutThread::aside_queue
FlowQueuePrivate aside_queue
Definition: flow-manager.c:258
timeradd
#define timeradd(a, b, r)
Definition: util-time.h:127
FLOW_END_FLAG_TIMEOUT
#define FLOW_END_FLAG_TIMEOUT
Definition: flow.h:244
FlowTimeoutCounters_::flows_notimeout
uint32_t flows_notimeout
Definition: flow-manager.c:115
flow_timeouts_normal
FlowProtoTimeout flow_timeouts_normal[FLOW_PROTO_MAX]
Definition: flow.c:86
FlowNeedsReassembly
bool FlowNeedsReassembly(Flow *f)
Check if a flow needs forced reassembly, or any other processing.
Definition: flow-timeout.c:289
StatsRegisterAvgCounter
uint16_t StatsRegisterAvgCounter(const char *name, struct ThreadVars_ *tv)
Registers a counter, whose value holds the average of all the values assigned to it.
Definition: counters.c:971
StatsSyncCountersIfSignalled
void StatsSyncCountersIfSignalled(ThreadVars *tv)
Definition: counters.c:449
FlowCounters_::flow_mgr_spare
uint16_t flow_mgr_spare
Definition: flow-manager.c:625
FlowTimeoutCounters_::flows_aside
uint32_t flows_aside
Definition: flow-manager.c:118
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
PacketPoolDestroy
void PacketPoolDestroy(void)
Definition: tmqh-packetpool.c:274
flow.h
FlowQueuePrivateAppendFlow
void FlowQueuePrivateAppendFlow(FlowQueuePrivate *fqc, Flow *f)
Definition: flow-queue.c:65
FlowEndCountersRegister
void FlowEndCountersRegister(ThreadVars *t, FlowEndCounters *fec)
Definition: flow-util.c:238
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:93
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:237
evicted
Flow * evicted
Definition: flow-hash.h:4
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:951
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
BITS
#define BITS
Flow_::timeout_at
uint32_t timeout_at
Definition: flow.h:396
FlowEndCounters_
Definition: flow-util.h:148
FLOW_SPARE_POOL_BLOCK_SIZE
#define FLOW_SPARE_POOL_BLOCK_SIZE
Definition: flow-spare-pool.h:30
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:76
SC_ATOMIC_AND
#define SC_ATOMIC_AND(name, val)
Bitwise AND a value to our atomic variable.
Definition: util-atomic.h:359
FlowCounters_::flow_emerg_mode_over
uint16_t flow_emerg_mode_over
Definition: flow-manager.c:627
TM_FLAG_MANAGEMENT_TM
#define TM_FLAG_MANAGEMENT_TM
Definition: tm-modules.h:36
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:169
detect-engine-threshold.h
FlowTimeoutCounters_::rows_skipped
uint32_t rows_skipped
Definition: flow-manager.c:110
FlowCounters_::flow_mgr_flows_checked
uint16_t flow_mgr_flows_checked
Definition: flow-manager.c:629
ThresholdsExpire
uint32_t ThresholdsExpire(const SCTime_t ts)
Definition: detect-engine-threshold.c:233
SCTIME_USECS
#define SCTIME_USECS(t)
Definition: util-time.h:56
FlowCounters_::flow_mgr_rows_sec
uint16_t flow_mgr_rows_sec
Definition: flow-manager.c:623
FlowTimeoutCounters::flows_aside_needs_work
uint32_t flows_aside_needs_work
Definition: flow-worker.c:62
FQLOCK_UNLOCK
#define FQLOCK_UNLOCK(q)
Definition: flow-queue.h:75
HttpRangeContainersTimeoutHash
uint32_t HttpRangeContainersTimeoutHash(const SCTime_t ts)
Definition: app-layer-htp-range.c:209