63 static int ThresholdsInit(
struct Thresholds *t);
64 static void ThresholdsDestroy(
struct Thresholds *t);
73 ThresholdsDestroy(&
ctx);
103 static int ThresholdEntrySet(
void *
dst,
void *
src)
107 memset(edst, 0,
sizeof(*edst));
112 static void ThresholdEntryFree(
void *ptr)
117 static inline uint32_t HashAddress(
const Address *a)
121 if (a->
family == AF_INET) {
122 key = a->addr_data32[0];
123 }
else if (a->
family == AF_INET6) {
124 key =
hashword(a->addr_data32, 4, 0);
131 static inline int CompareAddress(
const Address *a,
const Address *b)
136 return (a->addr_data32[0] == b->addr_data32[0]);
144 static uint32_t ThresholdEntryHash(uint32_t seed,
void *ptr)
147 uint32_t hash =
hashword(e->
key,
sizeof(e->
key) /
sizeof(uint32_t), seed);
150 hash += HashAddress(&e->
addr2);
154 hash += HashAddress(&e->
addr);
160 static bool ThresholdEntryCompare(
void *a,
void *b)
166 if (memcmp(e1->
key, e2->
key,
sizeof(e1->
key)) != 0)
170 if (!(CompareAddress(&e1->
addr2, &e2->
addr2)))
175 if (!(CompareAddress(&e1->
addr, &e2->
addr)))
182 static bool ThresholdEntryExpire(
void *data,
const SCTime_t ts)
192 static int ThresholdsInit(
struct Thresholds *t)
195 uint64_t memcap = 16 * 1024 * 1024;
198 if (
ConfGet(
"detect.thresholds.memcap", &
str) == 1) {
200 SCLogError(
"Error parsing detect.thresholds.memcap from conf file - %s",
str);
206 if ((
ConfGetInt(
"detect.thresholds.hash-size", &value)) == 1) {
207 if (value < 256 || value > INT_MAX) {
208 SCLogError(
"'detect.thresholds.hash-size' value %" PRIiMAX
209 " out of range. Valid range 256-2147483647.",
217 ThresholdEntryFree, ThresholdEntryHash, ThresholdEntryCompare, ThresholdEntryExpire,
219 if (t->
thash == NULL) {
220 SCLogError(
"failed to initialize thresholds hash table");
226 static void ThresholdsDestroy(
struct Thresholds *t)
253 static thread_local
HashTable *threshold_cache_ht = NULL;
264 static void DumpCacheStats(
void)
266 SCLogPerf(
"threshold thread cache stats: cnt:%" PRIu64
" notinit:%" PRIu64
" nosupport:%" PRIu64
267 " miss_expired:%" PRIu64
" miss:%" PRIu64
" hit:%" PRIu64
268 ", housekeeping: checks:%" PRIu64
", expired:%" PRIu64,
291 static void ThresholdCacheExpire(
SCTime_t now)
314 static uint32_t ThresholdCacheHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
322 static char ThresholdCacheHashCompareFunc(
323 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
328 memcmp(tci1->
key, tci2->
key,
sizeof(tci1->
key)) == 0;
331 static void ThresholdCacheHashFreeFunc(
void *data)
337 static int SetupCache(
const Packet *p,
const int8_t track,
const int8_t retval,
const uint32_t sid,
338 const uint32_t gid,
const uint32_t rev,
SCTime_t expires)
340 if (!threshold_cache_ht) {
341 threshold_cache_ht =
HashTableInit(256, ThresholdCacheHashFunc,
342 ThresholdCacheHashCompareFunc, ThresholdCacheHashFreeFunc);
347 addr = p->
src.addr_data32[0];
349 addr = p->
dst.addr_data32[0];
363 .expires_at = expires,
406 static int CheckCache(
const Packet *p,
const int8_t track,
const uint32_t sid,
const uint32_t gid,
411 if (!threshold_cache_ht) {
418 addr = p->
src.addr_data32[0];
420 addr = p->
dst.addr_data32[0];
427 ThresholdCacheExpire(p->
ts);
456 if (threshold_cache_ht) {
458 threshold_cache_ht = NULL;
554 Flow *f, uint32_t sid, uint32_t gid, uint32_t rev, uint32_t tenant_id)
561 if (e->threshold.
key[
SID] == sid && e->threshold.
key[
GID] == gid &&
562 e->threshold.
key[
REV] == rev && e->threshold.
key[
TENANT] == tenant_id) {
563 return &e->threshold;
588 static int ThresholdHandlePacketSuppress(
Packet *p,
624 static inline void RateFilterSetAction(
PacketAlert *pa, uint8_t new_action)
626 switch (new_action) {
653 static uint32_t BackoffCalcNextValue(
const uint32_t cur,
const uint32_t
m)
668 const SCTime_t packet_time,
const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
669 const uint32_t tenant_id)
685 te->
tv1 = packet_time;
700 if (td->
count == 1) {
714 const uint32_t sid,
const uint32_t gid,
const uint32_t rev,
PacketAlert *pa)
731 if (PacketIsIPv4(p)) {
732 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
766 if (PacketIsIPv4(p)) {
767 SetupCache(p, td->
track, (int8_t)ret, sid, gid, rev, entry);
820 te->
tv1 = packet_time;
856 memset(&lookup, 0,
sizeof(lookup));
868 if (PacketIsIPv4(p)) {
897 r = ThresholdCheckUpdate(td, te, p, s->
id, s->
gid, s->
rev, pa);
901 THashDataUnlock(res.
data);
913 uint32_t sid, uint32_t gid, uint32_t rev,
PacketAlert *pa)
917 SCLogDebug(
"found %p sid %u gid %u rev %u", found, sid, gid, rev);
925 ret = ThresholdSetup(td, &new->threshold, p->
ts, sid, gid, rev, p->
tenant_id);
927 if (AddEntryToFlow(f,
new, p->
ts) == -1) {
933 ret = ThresholdCheckUpdate(td, found, p, sid, gid, rev, pa);
961 ret = ThresholdHandlePacketSuppress(p,td,s->
id,s->
gid);
964 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
965 if (cache_ret >= 0) {
970 ret = ThresholdGetFromHash(&
ctx, p, s, td, pa);
973 int cache_ret = CheckCache(p, td->
track, s->
id, s->
gid, s->
rev);
974 if (cache_ret >= 0) {
979 ret = ThresholdGetFromHash(&
ctx, p, s, td, pa);
981 ret = ThresholdGetFromHash(&
ctx, p, s, td, pa);
983 ret = ThresholdGetFromHash(&
ctx, p, s, td, pa);
986 ret = ThresholdHandlePacketFlow(p->
flow, p, td, s->
id, s->
gid, s->
rev, pa);