69 static int g_threshold_force_alloc_fail = 0;
73 g_threshold_force_alloc_fail = v;
88 #define DF_PORT_BITMAP_SIZE (65536u / 8u)
89 #define DF_PORT_BYTE_IDX(p) ((uint32_t)((p) >> 3))
90 #define DF_PORT_BIT_MASK(p) ((uint8_t)(1u << ((p)&7u)))
96 static int ThresholdsInit(
struct Thresholds *t);
97 static void ThresholdsDestroy(
struct Thresholds *t);
99 static uint64_t ThresholdBitmapAllocFailCounter(
void)
104 static uint64_t ThresholdBitmapMemuseCounter(
void)
109 static uint64_t ThresholdMemuseCounter(
void)
116 static uint64_t ThresholdMemcapCounter(
void)
127 ThresholdsInit(&
ctx);
136 "detect.thresholds.bitmap_alloc_fail", ThresholdBitmapAllocFailCounter);
141 ThresholdsDestroy(&
ctx);
173 static int ThresholdEntrySet(
void *
dst,
void *
src)
177 memset(edst, 0,
sizeof(*edst));
192 if (g_threshold_force_alloc_fail) {
229 static inline void ThresholdDistinctAddPort(
ThresholdEntry *te, uint16_t port)
243 static void ThresholdEntryFree(
void *ptr)
261 static inline uint32_t HashAddress(
const Address *a)
265 if (a->
family == AF_INET) {
266 key = a->addr_data32[0];
267 }
else if (a->
family == AF_INET6) {
268 key =
hashword(a->addr_data32, 4, 0);
275 static inline int CompareAddress(
const Address *a,
const Address *b)
280 return (a->addr_data32[0] == b->addr_data32[0]);
288 static uint32_t ThresholdEntryHash(uint32_t seed,
void *ptr)
291 uint32_t hash =
hashword(e->
key,
sizeof(e->
key) /
sizeof(uint32_t), seed);
294 hash += HashAddress(&e->
addr2);
298 hash += HashAddress(&e->
addr);
304 static bool ThresholdEntryCompare(
void *a,
void *b)
310 if (memcmp(e1->
key, e2->
key,
sizeof(e1->
key)) != 0)
314 if (!(CompareAddress(&e1->
addr2, &e2->
addr2)))
319 if (!(CompareAddress(&e1->
addr, &e2->
addr)))
326 static bool ThresholdEntryExpire(
void *data,
const SCTime_t ts)
336 static int ThresholdsInit(
struct Thresholds *t)
339 uint64_t memcap = 16 * 1024 * 1024;
344 SCLogError(
"Error parsing detect.thresholds.memcap from conf file - %s",
str);
350 if ((
SCConfGetInt(
"detect.thresholds.hash-size", &value)) == 1) {
351 if (value < 256 || value > INT_MAX) {
352 SCLogError(
"'detect.thresholds.hash-size' value %" PRIiMAX
353 " out of range. Valid range 256-2147483647.",
361 ThresholdEntryFree, ThresholdEntryHash, ThresholdEntryCompare, ThresholdEntryExpire,
363 if (t->
thash == NULL) {
364 SCLogError(
"failed to initialize thresholds hash table");
370 static void ThresholdsDestroy(
struct Thresholds *t)
397 static thread_local
HashTable *threshold_cache_ht = NULL;
408 static void DumpCacheStats(
void)
410 SCLogPerf(
"threshold thread cache stats: cnt:%" PRIu64
" notinit:%" PRIu64
" nosupport:%" PRIu64
411 " miss_expired:%" PRIu64
" miss:%" PRIu64
" hit:%" PRIu64
412 ", housekeeping: checks:%" PRIu64
", expired:%" PRIu64,
435 static void ThresholdCacheExpire(
SCTime_t now)
458 static uint32_t ThresholdCacheHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
466 static char ThresholdCacheHashCompareFunc(
467 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
472 memcmp(tci1->
key, tci2->
key,
sizeof(tci1->
key)) == 0;
475 static void ThresholdCacheHashFreeFunc(
void *data)
481 static int SetupCache(
const Packet *p,
const int8_t track,
const int8_t retval,
const uint32_t sid,
482 const uint32_t gid,
const uint32_t rev,
SCTime_t expires)
484 if (!threshold_cache_ht) {
485 threshold_cache_ht =
HashTableInit(256, ThresholdCacheHashFunc,
486 ThresholdCacheHashCompareFunc, ThresholdCacheHashFreeFunc);
491 addr = p->
src.addr_data32[0];
493 addr = p->
dst.addr_data32[0];
507 .expires_at = expires,
550 static int CheckCache(
const Packet *p,
const int8_t track,
const uint32_t sid,
const uint32_t gid,
555 if (!threshold_cache_ht) {
562 addr = p->
src.addr_data32[0];
564 addr = p->
dst.addr_data32[0];
571 ThresholdCacheExpire(p->
ts);
600 if (threshold_cache_ht) {
602 threshold_cache_ht = NULL;
698 Flow *f, uint32_t sid, uint32_t gid, uint32_t rev, uint32_t tenant_id)
705 if (e->threshold.
key[
SID] == sid && e->threshold.
key[
GID] == gid &&
706 e->threshold.
key[
REV] == rev && e->threshold.
key[
TENANT] == tenant_id) {
707 return &e->threshold;
732 static int ThresholdHandlePacketSuppress(
768 static inline void RateFilterSetAction(
PacketAlert *pa, uint8_t new_action)
770 switch (new_action) {
797 static uint32_t BackoffCalcNextValue(
const uint32_t cur,
const uint32_t
m)
812 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
830 ThresholdDistinctInit(te, td);
837 ThresholdDistinctAddPort(te, port);
857 if (td->
count == 1) {
872 const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
PacketAlert *pa)
889 if (PacketIsIPv4(p)) {
890 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
924 if (PacketIsIPv4(p)) {
925 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
946 ThresholdDistinctAddPort(te, port);
959 ThresholdDistinctReset(te);
964 ThresholdDistinctAddPort(te, port);
973 const uint8_t original_action = pa->
action;
996 te->
tv1 = packet_time;
1003 if (pa->
action == original_action) {
1041 memset(&lookup, 0,
sizeof(lookup));
1053 if (PacketIsIPv4(p)) {
1079 r = ThresholdSetup(td, te, p, s->
id, s->
gid, s->
rev);
1082 r = ThresholdCheckUpdate(
de_ctx, td, te, p, s->
id, s->
gid, s->
rev, pa);
1086 THashDataUnlock(res.
data);
1102 SCLogDebug(
"found %p sid %u gid %u rev %u", found, sid, gid, rev);
1104 if (found == NULL) {
1110 ret = ThresholdSetup(td, &new->threshold, p, sid, gid, rev);
1112 if (AddEntryToFlow(f,
new, p->
ts) == -1) {
1118 ret = ThresholdCheckUpdate(
de_ctx, td, found, p, sid, gid, rev, pa);
1146 ret = ThresholdHandlePacketSuppress(p, td, s->
id, s->
gid);
1149 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
1150 if (cache_ret >= 0) {
1155 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1158 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
1159 if (cache_ret >= 0) {
1164 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1166 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1168 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);