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)
333 static int ThresholdsInit(
struct Thresholds *t)
336 uint64_t memcap = 16 * 1024 * 1024;
341 SCLogError(
"Error parsing detect.thresholds.memcap from conf file - %s",
str);
347 if ((
SCConfGetInt(
"detect.thresholds.hash-size", &value)) == 1) {
348 if (value < 256 || value > INT_MAX) {
349 SCLogError(
"'detect.thresholds.hash-size' value %" PRIiMAX
350 " out of range. Valid range 256-2147483647.",
358 ThresholdEntryFree, ThresholdEntryHash, ThresholdEntryCompare, ThresholdEntryExpire,
360 if (t->
thash == NULL) {
361 SCLogError(
"failed to initialize thresholds hash table");
367 static void ThresholdsDestroy(
struct Thresholds *t)
394 static thread_local
HashTable *threshold_cache_ht = NULL;
405 static void DumpCacheStats(
void)
407 SCLogPerf(
"threshold thread cache stats: cnt:%" PRIu64
" notinit:%" PRIu64
" nosupport:%" PRIu64
408 " miss_expired:%" PRIu64
" miss:%" PRIu64
" hit:%" PRIu64
409 ", housekeeping: checks:%" PRIu64
", expired:%" PRIu64,
432 static void ThresholdCacheExpire(
SCTime_t now)
455 static uint32_t ThresholdCacheHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
463 static char ThresholdCacheHashCompareFunc(
464 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
469 memcmp(tci1->
key, tci2->
key,
sizeof(tci1->
key)) == 0;
472 static void ThresholdCacheHashFreeFunc(
void *data)
478 static int SetupCache(
const Packet *p,
const int8_t track,
const int8_t retval,
const uint32_t sid,
479 const uint32_t gid,
const uint32_t rev,
SCTime_t expires)
481 if (!threshold_cache_ht) {
482 threshold_cache_ht =
HashTableInit(256, ThresholdCacheHashFunc,
483 ThresholdCacheHashCompareFunc, ThresholdCacheHashFreeFunc);
488 addr = p->
src.addr_data32[0];
490 addr = p->
dst.addr_data32[0];
504 .expires_at = expires,
547 static int CheckCache(
const Packet *p,
const int8_t track,
const uint32_t sid,
const uint32_t gid,
552 if (!threshold_cache_ht) {
559 addr = p->
src.addr_data32[0];
561 addr = p->
dst.addr_data32[0];
568 ThresholdCacheExpire(p->
ts);
597 if (threshold_cache_ht) {
599 threshold_cache_ht = NULL;
695 Flow *f, uint32_t sid, uint32_t gid, uint32_t rev, uint32_t tenant_id)
702 if (e->threshold.
key[
SID] == sid && e->threshold.
key[
GID] == gid &&
703 e->threshold.
key[
REV] == rev && e->threshold.
key[
TENANT] == tenant_id) {
704 return &e->threshold;
729 static int ThresholdHandlePacketSuppress(
765 static inline void RateFilterSetAction(
PacketAlert *pa, uint8_t new_action)
767 switch (new_action) {
794 static uint32_t BackoffCalcNextValue(
const uint32_t cur,
const uint32_t
m)
809 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
827 ThresholdDistinctInit(te, td);
834 ThresholdDistinctAddPort(te, port);
854 if (td->
count == 1) {
869 const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
PacketAlert *pa)
886 if (PacketIsIPv4(p)) {
887 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
921 if (PacketIsIPv4(p)) {
922 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
943 ThresholdDistinctAddPort(te, port);
956 ThresholdDistinctReset(te);
961 ThresholdDistinctAddPort(te, port);
970 const uint8_t original_action = pa->
action;
993 te->
tv1 = packet_time;
1000 if (pa->
action == original_action) {
1038 memset(&lookup, 0,
sizeof(lookup));
1050 if (PacketIsIPv4(p)) {
1076 r = ThresholdSetup(td, te, p, s->
id, s->
gid, s->
rev);
1079 r = ThresholdCheckUpdate(
de_ctx, td, te, p, s->
id, s->
gid, s->
rev, pa);
1083 THashDataUnlock(res.
data);
1099 SCLogDebug(
"found %p sid %u gid %u rev %u", found, sid, gid, rev);
1101 if (found == NULL) {
1107 ret = ThresholdSetup(td, &new->threshold, p, sid, gid, rev);
1109 if (AddEntryToFlow(f,
new, p->
ts) == -1) {
1115 ret = ThresholdCheckUpdate(
de_ctx, td, found, p, sid, gid, rev, pa);
1143 ret = ThresholdHandlePacketSuppress(p, td, s->
id, s->
gid);
1146 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
1147 if (cache_ret >= 0) {
1152 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1155 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
1156 if (cache_ret >= 0) {
1161 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1163 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);
1165 ret = ThresholdGetFromHash(
de_ctx, &
ctx, p, s, td, pa);