67 static void ThresholdCacheInit(
void);
75 static int g_threshold_force_alloc_fail = 0;
79 g_threshold_force_alloc_fail = v;
94 #define DF_PORT_BITMAP_SIZE (65536u / 8u)
95 #define DF_PORT_BYTE_IDX(p) ((uint32_t)((p) >> 3))
96 #define DF_PORT_BIT_MASK(p) ((uint8_t)(1u << ((p)&7u)))
102 static int ThresholdsInit(
struct Thresholds *t);
103 static void ThresholdsDestroy(
struct Thresholds *t);
105 static uint64_t ThresholdBitmapAllocFailCounter(
void)
110 static uint64_t ThresholdBitmapMemuseCounter(
void)
115 static uint64_t ThresholdCacheMemuseCounter(
void)
120 static uint64_t ThresholdMemuseCounter(
void)
127 static uint64_t ThresholdMemcapCounter(
void)
140 if (ThresholdsInit(&
ctx) < 0) {
141 FatalError(
"Failed to initialize threshold table");
143 ThresholdCacheInit();
153 "detect.thresholds.bitmap_alloc_fail", ThresholdBitmapAllocFailCounter);
158 ThresholdsDestroy(&
ctx);
190 static int ThresholdEntrySet(
void *
dst,
void *
src)
194 memset(edst, 0,
sizeof(*edst));
209 if (g_threshold_force_alloc_fail) {
246 static inline void ThresholdDistinctAddPort(
ThresholdEntry *te, uint16_t port)
260 static void ThresholdEntryFree(
void *ptr)
278 static inline uint32_t HashAddress(
const Address *a,
const uint32_t seed)
282 if (a->
family == AF_INET) {
283 key =
hashword(a->addr_data32, 1, seed);
284 }
else if (a->
family == AF_INET6) {
285 key =
hashword(a->addr_data32, 4, seed);
292 static inline int CompareAddress(
const Address *a,
const Address *b)
297 return (a->addr_data32[0] == b->addr_data32[0]);
305 static uint32_t ThresholdEntryHash(
const uint32_t seed,
void *ptr)
308 uint32_t hash =
hashword(e->
key,
sizeof(e->
key) /
sizeof(uint32_t), seed);
311 hash += HashAddress(&e->
addr2, seed);
315 hash += HashAddress(&e->
addr, seed);
321 static bool ThresholdEntryCompare(
void *a,
void *b)
327 if (memcmp(e1->
key, e2->
key,
sizeof(e1->
key)) != 0)
331 if (!(CompareAddress(&e1->
addr2, &e2->
addr2)))
336 if (!(CompareAddress(&e1->
addr, &e2->
addr)))
343 static bool ThresholdEntryExpire(
void *data,
const SCTime_t ts)
350 static int ThresholdsInit(
struct Thresholds *t)
353 uint64_t memcap = 16 * 1024 * 1024;
358 SCLogError(
"Error parsing detect.thresholds.memcap from conf file - %s",
str);
364 if ((
SCConfGetInt(
"detect.thresholds.hash-size", &value)) == 1) {
365 if (value < 256 || value > INT_MAX) {
366 SCLogError(
"'detect.thresholds.hash-size' value %" PRIiMAX
367 " out of range. Valid range 256-2147483647.",
375 ThresholdEntryFree, ThresholdEntryHash, ThresholdEntryCompare, ThresholdEntryExpire,
377 if (t->
thash == NULL) {
378 SCLogError(
"failed to initialize thresholds hash table");
384 static void ThresholdsDestroy(
struct Thresholds *t)
428 struct THRESHOLD_CACHE
tree;
444 #define THRESHOLD_CACHE_MAX_ENTRIES_DEFAULT 256
445 #define THRESHOLD_CACHE_MAX_ENTRIES_MIN 256
446 #define THRESHOLD_CACHE_MAX_ENTRIES_MAX 1048576
451 #define THRESHOLD_CACHE_ENTRY_MEM (sizeof(ThresholdCacheItem) + sizeof(HashTableBucket))
457 SCLogPerf(
"threshold thread cache stats: cnt:%" PRIu64
" nosupport:%" PRIu64
458 " miss_expired:%" PRIu64
" miss:%" PRIu64
" hit:%" PRIu64
", entries:%" PRIu32
459 ", housekeeping: checks:%" PRIu64
", expired:%" PRIu64,
466 if (
unlikely(det_ctx->
tv == NULL || thread_storage_id.
id < 0)) {
485 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, iter);
500 static uint32_t ThresholdCacheHashFunc(
HashTable *
ht,
void *data, uint16_t datalen)
509 static char ThresholdCacheHashCompareFunc(
510 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
515 memcmp(tci1->
key, tci2->
key,
sizeof(tci1->
key)) == 0;
518 static void ThresholdCacheHashFreeFunc(
void *data)
525 const int8_t retval,
const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
535 addr =
p->
src.addr_data32[0];
537 addr =
p->
dst.addr_data32[0];
551 .expires_at = expires,
558 if (tctx->
entries >= cache_max_entries) {
560 if (victim == NULL) {
565 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, victim);
598 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, found);
599 THRESHOLD_CACHE_RB_INSERT(&tctx->
tree, found);
613 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
624 addr =
p->
src.addr_data32[0];
626 addr =
p->
dst.addr_data32[0];
633 ThresholdCacheExpire(det_ctx,
p->
ts);
648 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, found);
662 static void ThresholdCacheThreadFree(
void *ptr)
666 DumpCacheStats(tctx);
674 static void ThresholdCacheInit(
void)
681 if (
SCConfGetInt(
"detect.thresholds.cache.max-entries", &value) == 1) {
684 SCLogError(
"'detect.thresholds.cache.max-entries' value %" PRIdMAX
685 " out of range. Valid range %d-%d.",
687 FatalError(
"Invalid value for detect.thresholds.cache.max-entries");
689 cache_max_entries = (uint32_t)value;
694 if (thread_storage_id.
id < 0) {
695 FatalError(
"Failed to register threshold_cache thread storage");
704 if (thread_storage_id.
id < 0)
716 uint32_t
hashsize = cache_max_entries;
718 uint32_t hashpow = 1;
723 ThresholdCacheHashFreeFunc, seed);
724 if (tctx->
ht == NULL) {
736 sizeof(*tctx) +
sizeof(*tctx->
ht) + (uint64_t)hashpow *
sizeof(
HashTableBucket *);
832 Flow *f, uint32_t sid, uint32_t gid, uint32_t rev, uint32_t tenant_id)
839 if (e->threshold.
key[
SID] == sid && e->threshold.
key[
GID] == gid &&
840 e->threshold.
key[
REV] == rev && e->threshold.
key[
TENANT] == tenant_id) {
841 return &e->threshold;
866 static int ThresholdHandlePacketSuppress(
902 static inline void RateFilterSetAction(
PacketAlert *pa, uint8_t new_action)
904 switch (new_action) {
931 static uint32_t BackoffCalcNextValue(
const uint32_t cur,
const uint32_t
m)
946 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
964 ThresholdDistinctInit(te, td);
971 ThresholdDistinctAddPort(te, port);
991 if (td->
count == 1) {
1006 const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
PacketAlert *pa)
1023 if (PacketIsIPv4(
p)) {
1024 SetupCache(det_ctx,
p, td->
track, (int8_t)ret, sid, gid, rev, entry);
1058 if (PacketIsIPv4(
p)) {
1059 SetupCache(det_ctx,
p, td->
track, (int8_t)ret, sid, gid, rev, entry);
1080 ThresholdDistinctAddPort(te, port);
1093 ThresholdDistinctReset(te);
1098 ThresholdDistinctAddPort(te, port);
1107 const uint8_t original_action = pa->
action;
1130 te->
tv1 = packet_time;
1137 if (pa->
action == original_action) {
1176 memset(&lookup, 0,
sizeof(lookup));
1188 if (PacketIsIPv4(
p)) {
1214 r = ThresholdSetup(td, te,
p, s->
id, s->
gid, s->
rev);
1217 r = ThresholdCheckUpdate(
de_ctx, det_ctx, td, te,
p, s->
id, s->
gid, s->
rev, pa);
1221 THashDataUnlock(res.
data);
1238 SCLogDebug(
"found %p sid %u gid %u rev %u", found, sid, gid, rev);
1240 if (found == NULL) {
1246 ret = ThresholdSetup(td, &new->threshold,
p, sid, gid, rev);
1248 if (AddEntryToFlow(f,
new,
p->
ts) == -1) {
1254 ret = ThresholdCheckUpdate(
de_ctx, det_ctx, td, found,
p, sid, gid, rev, pa);
1282 ret = ThresholdHandlePacketSuppress(
p, td, s->
id, s->
gid);
1285 int cache_ret = CheckCache(det_ctx,
p, td->
track, s->
id, s->
gid, s->
rev);
1286 if (cache_ret >= 0) {
1291 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1294 int cache_ret = CheckCache(det_ctx,
p, td->
track, s->
id, s->
gid, s->
rev);
1295 if (cache_ret >= 0) {
1300 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1302 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1304 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1307 ret = ThresholdHandlePacketFlow(