66 static void ThresholdCacheInit(
void);
74 static int g_threshold_force_alloc_fail = 0;
78 g_threshold_force_alloc_fail = v;
93 #define DF_PORT_BITMAP_SIZE (65536u / 8u)
94 #define DF_PORT_BYTE_IDX(p) ((uint32_t)((p) >> 3))
95 #define DF_PORT_BIT_MASK(p) ((uint8_t)(1u << ((p)&7u)))
101 static int ThresholdsInit(
struct Thresholds *t);
102 static void ThresholdsDestroy(
struct Thresholds *t);
104 static uint64_t ThresholdBitmapAllocFailCounter(
void)
109 static uint64_t ThresholdBitmapMemuseCounter(
void)
114 static uint64_t ThresholdMemuseCounter(
void)
121 static uint64_t ThresholdMemcapCounter(
void)
132 ThresholdsInit(&
ctx);
133 ThresholdCacheInit();
142 "detect.thresholds.bitmap_alloc_fail", ThresholdBitmapAllocFailCounter);
147 ThresholdsDestroy(&
ctx);
179 static int ThresholdEntrySet(
void *
dst,
void *
src)
183 memset(edst, 0,
sizeof(*edst));
198 if (g_threshold_force_alloc_fail) {
235 static inline void ThresholdDistinctAddPort(
ThresholdEntry *te, uint16_t port)
249 static void ThresholdEntryFree(
void *ptr)
267 static inline uint32_t HashAddress(
const Address *a,
const uint32_t seed)
271 if (a->
family == AF_INET) {
272 key =
hashword(a->addr_data32, 1, seed);
273 }
else if (a->
family == AF_INET6) {
274 key =
hashword(a->addr_data32, 4, seed);
281 static inline int CompareAddress(
const Address *a,
const Address *b)
286 return (a->addr_data32[0] == b->addr_data32[0]);
294 static uint32_t ThresholdEntryHash(
const uint32_t seed,
void *ptr)
297 uint32_t hash =
hashword(e->
key,
sizeof(e->
key) /
sizeof(uint32_t), seed);
300 hash += HashAddress(&e->
addr2, seed);
304 hash += HashAddress(&e->
addr, seed);
310 static bool ThresholdEntryCompare(
void *a,
void *b)
316 if (memcmp(e1->
key, e2->
key,
sizeof(e1->
key)) != 0)
320 if (!(CompareAddress(&e1->
addr2, &e2->
addr2)))
325 if (!(CompareAddress(&e1->
addr, &e2->
addr)))
332 static bool ThresholdEntryExpire(
void *data,
const SCTime_t ts)
339 static int ThresholdsInit(
struct Thresholds *t)
342 uint64_t memcap = 16 * 1024 * 1024;
347 SCLogError(
"Error parsing detect.thresholds.memcap from conf file - %s",
str);
353 if ((
SCConfGetInt(
"detect.thresholds.hash-size", &value)) == 1) {
354 if (value < 256 || value > INT_MAX) {
355 SCLogError(
"'detect.thresholds.hash-size' value %" PRIiMAX
356 " out of range. Valid range 256-2147483647.",
364 ThresholdEntryFree, ThresholdEntryHash, ThresholdEntryCompare, ThresholdEntryExpire,
366 if (t->
thash == NULL) {
367 SCLogError(
"failed to initialize thresholds hash table");
373 static void ThresholdsDestroy(
struct Thresholds *t)
417 struct THRESHOLD_CACHE
tree;
433 SCLogPerf(
"threshold thread cache stats: cnt:%" PRIu64
" nosupport:%" PRIu64
434 " miss_expired:%" PRIu64
" miss:%" PRIu64
" hit:%" PRIu64
435 ", housekeeping: checks:%" PRIu64
", expired:%" PRIu64,
442 if (
unlikely(det_ctx->
tv == NULL || thread_storage_id.
id < 0)) {
461 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, iter);
474 static uint32_t ThresholdCacheHashFunc(
HashTable *
ht,
void *data, uint16_t datalen)
483 static char ThresholdCacheHashCompareFunc(
484 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
489 memcmp(tci1->
key, tci2->
key,
sizeof(tci1->
key)) == 0;
492 static void ThresholdCacheHashFreeFunc(
void *data)
499 const int8_t retval,
const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
509 addr =
p->
src.addr_data32[0];
511 addr =
p->
dst.addr_data32[0];
525 .expires_at = expires,
554 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, found);
555 THRESHOLD_CACHE_RB_INSERT(&tctx->
tree, found);
569 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
580 addr =
p->
src.addr_data32[0];
582 addr =
p->
dst.addr_data32[0];
589 ThresholdCacheExpire(det_ctx,
p->
ts);
604 THRESHOLD_CACHE_RB_REMOVE(&tctx->
tree, found);
616 static void ThresholdCacheThreadFree(
void *ptr)
620 DumpCacheStats(tctx);
626 static void ThresholdCacheInit(
void)
634 if (thread_storage_id.
id < 0) {
635 FatalError(
"Failed to register threshold_cache thread storage");
644 if (thread_storage_id.
id < 0)
657 ThresholdCacheHashFreeFunc, seed);
658 if (tctx->
ht == NULL) {
758 Flow *f, uint32_t sid, uint32_t gid, uint32_t rev, uint32_t tenant_id)
765 if (e->threshold.
key[
SID] == sid && e->threshold.
key[
GID] == gid &&
766 e->threshold.
key[
REV] == rev && e->threshold.
key[
TENANT] == tenant_id) {
767 return &e->threshold;
792 static int ThresholdHandlePacketSuppress(
828 static inline void RateFilterSetAction(
PacketAlert *pa, uint8_t new_action)
830 switch (new_action) {
857 static uint32_t BackoffCalcNextValue(
const uint32_t cur,
const uint32_t
m)
872 const uint32_t sid,
const uint32_t gid,
const uint32_t rev)
890 ThresholdDistinctInit(te, td);
897 ThresholdDistinctAddPort(te, port);
917 if (td->
count == 1) {
932 const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
PacketAlert *pa)
949 if (PacketIsIPv4(
p)) {
950 SetupCache(det_ctx,
p, td->
track, (int8_t)ret, sid, gid, rev, entry);
984 if (PacketIsIPv4(
p)) {
985 SetupCache(det_ctx,
p, td->
track, (int8_t)ret, sid, gid, rev, entry);
1006 ThresholdDistinctAddPort(te, port);
1019 ThresholdDistinctReset(te);
1024 ThresholdDistinctAddPort(te, port);
1033 const uint8_t original_action = pa->
action;
1056 te->
tv1 = packet_time;
1063 if (pa->
action == original_action) {
1102 memset(&lookup, 0,
sizeof(lookup));
1114 if (PacketIsIPv4(
p)) {
1140 r = ThresholdSetup(td, te,
p, s->
id, s->
gid, s->
rev);
1143 r = ThresholdCheckUpdate(
de_ctx, det_ctx, td, te,
p, s->
id, s->
gid, s->
rev, pa);
1147 THashDataUnlock(res.
data);
1164 SCLogDebug(
"found %p sid %u gid %u rev %u", found, sid, gid, rev);
1166 if (found == NULL) {
1172 ret = ThresholdSetup(td, &new->threshold,
p, sid, gid, rev);
1174 if (AddEntryToFlow(f,
new,
p->
ts) == -1) {
1180 ret = ThresholdCheckUpdate(
de_ctx, det_ctx, td, found,
p, sid, gid, rev, pa);
1208 ret = ThresholdHandlePacketSuppress(
p, td, s->
id, s->
gid);
1211 int cache_ret = CheckCache(det_ctx,
p, td->
track, s->
id, s->
gid, s->
rev);
1212 if (cache_ret >= 0) {
1217 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1220 int cache_ret = CheckCache(det_ctx,
p, td->
track, s->
id, s->
gid, s->
rev);
1221 if (cache_ret >= 0) {
1226 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1228 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1230 ret = ThresholdGetFromHash(
de_ctx, det_ctx, &
ctx,
p, s, td, pa);
1233 ret = ThresholdHandlePacketFlow(