diff --git a/etc/schema.json b/etc/schema.json index 8aa3a028f3..587135d8bc 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -4907,6 +4907,11 @@ "max_frag_hits": { "type": "integer" }, + "memcap_exception_policy": { + "description": + "How many times defrag memcap exception policy was applied, and which one", + "$ref": "#/$defs/exceptionPolicy" + }, "ipv4": { "type": "object", "properties": { diff --git a/src/decode.c b/src/decode.c index 64a6d43d56..9fa3991157 100644 --- a/src/decode.c +++ b/src/decode.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2023 Open Information Security Foundation +/* Copyright (C) 2007-2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -62,11 +62,15 @@ #include "decode-erspan.h" #include "decode-teredo.h" +#include "defrag-hash.h" + #include "util-hash.h" #include "util-hash-string.h" #include "util-print.h" #include "util-profiling.h" #include "util-validate.h" +#include "util-debug.h" +#include "util-exception-policy.h" #include "action-globals.h" uint32_t default_packet_size = 0; @@ -76,6 +80,32 @@ extern bool stats_stream_events; uint8_t decoder_max_layers = PKT_DEFAULT_MAX_DECODED_LAYERS; uint16_t packet_alert_max = PACKET_ALERT_MAX; +/* Settings order as in the enum */ +// clang-format off +ExceptionPolicyStatsSetts defrag_memcap_eps_stats = { + .valid_settings_ids = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ true, + /* EXCEPTION_POLICY_PASS_FLOW */ false, + /* EXCEPTION_POLICY_BYPASS_FLOW */ true, + /* EXCEPTION_POLICY_DROP_PACKET */ false, + /* EXCEPTION_POLICY_DROP_FLOW */ false, + /* EXCEPTION_POLICY_REJECT */ true, + }, + .valid_settings_ips = { + /* EXCEPTION_POLICY_NOT_SET */ false, + /* EXCEPTION_POLICY_AUTO */ false, + /* EXCEPTION_POLICY_PASS_PACKET */ true, + /* EXCEPTION_POLICY_PASS_FLOW */ false, + /* EXCEPTION_POLICY_BYPASS_FLOW */ true, + /* EXCEPTION_POLICY_DROP_PACKET */ true, + /* EXCEPTION_POLICY_DROP_FLOW */ false, + /* EXCEPTION_POLICY_REJECT */ true, + }, +}; +// clang-format on + /* Settings order as in the enum */ // clang-format off ExceptionPolicyStatsSetts flow_memcap_eps_stats = { @@ -551,6 +581,14 @@ void DecodeUnregisterCounters(void) SCMutexUnlock(&g_counter_table_mutex); } +static bool IsDefragMemcapExceptionPolicyStatsValid(enum ExceptionPolicy policy) +{ + if (EngineModeIsIPS()) { + return defrag_memcap_eps_stats.valid_settings_ips[policy]; + } + return defrag_memcap_eps_stats.valid_settings_ids[policy]; +} + static bool IsFlowMemcapExceptionPolicyStatsValid(enum ExceptionPolicy policy) { if (EngineModeIsIPS()) { @@ -638,6 +676,10 @@ void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv) dtv->counter_defrag_max_hit = StatsRegisterCounter("defrag.max_frag_hits", tv); + ExceptionPolicySetStatsCounters(tv, &dtv->counter_defrag_memcap_eps, &defrag_memcap_eps_stats, + DefragGetMemcapExceptionPolicy(), "defrag.memcap_exception_policy.", + IsDefragMemcapExceptionPolicyStatsValid); + for (int i = 0; i < DECODE_EVENT_MAX; i++) { BUG_ON(i != (int)DEvents[i].code); diff --git a/src/decode.h b/src/decode.h index 65e7ac1bb9..cae316923b 100644 --- a/src/decode.h +++ b/src/decode.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2023 Open Information Security Foundation +/* Copyright (C) 2007-2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -739,6 +739,7 @@ typedef struct DecodeThreadVars_ uint16_t counter_defrag_ipv6_fragments; uint16_t counter_defrag_ipv6_reassembled; uint16_t counter_defrag_max_hit; + ExceptionPolicyCounters counter_defrag_memcap_eps; uint16_t counter_flow_memcap; ExceptionPolicyCounters counter_flow_memcap_eps; diff --git a/src/defrag-hash.c b/src/defrag-hash.c index eb754d6efa..04104ce056 100644 --- a/src/defrag-hash.c +++ b/src/defrag-hash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2022 Open Information Security Foundation +/* Copyright (C) 2007-2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -74,6 +74,11 @@ uint64_t DefragTrackerGetMemuse(void) return memusecopy; } +enum ExceptionPolicy DefragGetMemcapExceptionPolicy(void) +{ + return defrag_config.memcap_policy; +} + uint32_t DefragTrackerSpareQueueGetSize(void) { return DefragTrackerQueueLen(&defragtracker_spare_q); @@ -459,6 +464,15 @@ static inline int DefragTrackerCompare(DefragTracker *t, Packet *p) return CMP_DEFRAGTRACKER(t, p, id); } +static void DefragExceptionPolicyStatsIncr( + ThreadVars *tv, DecodeThreadVars *dtv, enum ExceptionPolicy policy) +{ + uint16_t id = dtv->counter_defrag_memcap_eps.eps_id[policy]; + if (likely(tv && id > 0)) { + StatsIncr(tv, id); + } +} + /** * \brief Get a new defrag tracker * @@ -467,12 +481,13 @@ static inline int DefragTrackerCompare(DefragTracker *t, Packet *p) * * \retval dt *LOCKED* tracker on success, NULL on error. */ -static DefragTracker *DefragTrackerGetNew(Packet *p) +static DefragTracker *DefragTrackerGetNew(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p) { #ifdef DEBUG if (g_eps_defrag_memcap != UINT64_MAX && g_eps_defrag_memcap == p->pcap_cnt) { SCLogNotice("simulating memcap hit for packet %" PRIu64, p->pcap_cnt); ExceptionPolicyApply(p, defrag_config.memcap_policy, PKT_DROP_REASON_DEFRAG_MEMCAP); + DefragExceptionPolicyStatsIncr(tv, dtv, defrag_config.memcap_policy); return NULL; } #endif @@ -497,6 +512,7 @@ static DefragTracker *DefragTrackerGetNew(Packet *p) dt = DefragTrackerGetUsedDefragTracker(); if (dt == NULL) { ExceptionPolicyApply(p, defrag_config.memcap_policy, PKT_DROP_REASON_DEFRAG_MEMCAP); + DefragExceptionPolicyStatsIncr(tv, dtv, defrag_config.memcap_policy); return NULL; } @@ -506,6 +522,7 @@ static DefragTracker *DefragTrackerGetNew(Packet *p) dt = DefragTrackerAlloc(); if (dt == NULL) { ExceptionPolicyApply(p, defrag_config.memcap_policy, PKT_DROP_REASON_DEFRAG_MEMCAP); + DefragExceptionPolicyStatsIncr(tv, dtv, defrag_config.memcap_policy); return NULL; } @@ -530,7 +547,7 @@ static DefragTracker *DefragTrackerGetNew(Packet *p) * * returns a *LOCKED* tracker or NULL */ -DefragTracker *DefragGetTrackerFromHash (Packet *p) +DefragTracker *DefragGetTrackerFromHash(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p) { DefragTracker *dt = NULL; @@ -542,7 +559,7 @@ DefragTracker *DefragGetTrackerFromHash (Packet *p) /* see if the bucket already has a tracker */ if (hb->head == NULL) { - dt = DefragTrackerGetNew(p); + dt = DefragTrackerGetNew(tv, dtv, p); if (dt == NULL) { DRLOCK_UNLOCK(hb); return NULL; @@ -571,7 +588,7 @@ DefragTracker *DefragGetTrackerFromHash (Packet *p) dt = dt->hnext; if (dt == NULL) { - dt = pdt->hnext = DefragTrackerGetNew(p); + dt = pdt->hnext = DefragTrackerGetNew(tv, dtv, p); if (dt == NULL) { DRLOCK_UNLOCK(hb); return NULL; diff --git a/src/defrag-hash.h b/src/defrag-hash.h index 0cbbef1840..96368adcec 100644 --- a/src/defrag-hash.h +++ b/src/defrag-hash.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2023 Open Information Security Foundation +/* Copyright (C) 2007-2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -27,6 +27,7 @@ #include "decode.h" #include "defrag.h" #include "util-exception-policy.h" +#include "util-exception-policy-types.h" /** Spinlocks or Mutex for the flow buckets. */ //#define DRLOCK_SPIN @@ -92,7 +93,7 @@ void DefragInitConfig(bool quiet); void DefragHashShutdown(void); DefragTracker *DefragLookupTrackerFromHash (Packet *); -DefragTracker *DefragGetTrackerFromHash (Packet *); +DefragTracker *DefragGetTrackerFromHash(ThreadVars *tv, DecodeThreadVars *dtv, Packet *); void DefragTrackerRelease(DefragTracker *); void DefragTrackerClearMemory(DefragTracker *); void DefragTrackerMoveToSpare(DefragTracker *); @@ -101,5 +102,6 @@ uint32_t DefragTrackerSpareQueueGetSize(void); int DefragTrackerSetMemcap(uint64_t); uint64_t DefragTrackerGetMemcap(void); uint64_t DefragTrackerGetMemuse(void); +enum ExceptionPolicy DefragGetMemcapExceptionPolicy(void); #endif /* SURICATA_DEFRAG_HASH_H */ diff --git a/src/defrag.c b/src/defrag.c index 8cebe8fb95..0d54754200 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2022 Open Information Security Foundation +/* Copyright (C) 2007-2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -985,7 +985,7 @@ DefragGetOsPolicy(Packet *p) static DefragTracker * DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p) { - return DefragGetTrackerFromHash(p); + return DefragGetTrackerFromHash(tv, dtv, p); } /**