diff --git a/configure.ac b/configure.ac index f3909ed610c6..10bbc3f233f7 100644 --- a/configure.ac +++ b/configure.ac @@ -537,6 +537,14 @@ ]) AM_CONDITIONAL([DEBUG_VALIDATION], [test "x$enable_debug_validation" = "xyes"]) + # enable qa-simulation mode -- disabled by default + AC_ARG_ENABLE(qa-simulation, + AS_HELP_STRING([--enable-qa-simulation], [Enable qa-simulation mode])) + AS_IF([test "x$enable_qa_simulation" = "xyes"], [ + AC_DEFINE([QA_SIMULATION],[1],[Enable qa-simulation mode]) + ]) + AM_CONDITIONAL([QA_SIMULATION], [test "x$enable_qa_simulation" = "xyes"]) + # profiling support AC_ARG_ENABLE(profiling, AS_HELP_STRING([--enable-profiling], [Enable performance profiling]),[enable_profiling=$enableval],[enable_profiling=no]) @@ -2642,6 +2650,7 @@ Development settings: Unit tests enabled: ${enable_unittests} Debug output enabled: ${enable_debug} Debug validation enabled: ${enable_debug_validation} + QA-simulation enabled: ${enable_qa_simulation} Fuzz targets enabled: ${enable_fuzztargets} Generic build parameters: diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 0ab84a8269de..812c467d6144 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2025 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -1373,7 +1373,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow &stream_slice); HandleStreamFrames(f, stream_slice, input, input_len, flags); -#ifdef DEBUG +#ifdef QA_SIMULATION if (((stream_slice.flags & STREAM_TOSERVER) && stream_slice.offset >= g_eps_applayer_error_offset_ts)) { SCLogNotice("putting parser %s into an error state from toserver offset %" PRIu64, diff --git a/src/defrag-hash.c b/src/defrag-hash.c index 846c51d3dffd..49dc2b5305fa 100644 --- a/src/defrag-hash.c +++ b/src/defrag-hash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2024 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -468,7 +468,7 @@ static void DefragExceptionPolicyStatsIncr( */ static DefragTracker *DefragTrackerGetNew(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p) { -#ifdef DEBUG +#ifdef QA_SIMULATION if (g_eps_defrag_memcap != UINT64_MAX && g_eps_defrag_memcap == PcapPacketCntGet(p)) { SCLogNotice("simulating memcap hit for packet %" PRIu64, PcapPacketCntGet(p)); ExceptionPolicyApply(p, defrag_config.memcap_policy, PKT_DROP_REASON_DEFRAG_MEMCAP); diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c index 15929a8eb3ac..1dcc78f4c86b 100644 --- a/src/detect-engine-alert.c +++ b/src/detect-engine-alert.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2022 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -29,7 +29,7 @@ #include "flow.h" #include "flow-private.h" -#ifdef DEBUG +#ifdef QA_SIMULATION #include "util-exception-policy.h" #endif @@ -283,7 +283,7 @@ static inline uint16_t AlertQueueExpandDo(DetectEngineThreadCtx *det_ctx, uint16 */ static uint16_t AlertQueueExpand(DetectEngineThreadCtx *det_ctx) { -#ifdef DEBUG +#ifdef QA_SIMULATION if (unlikely(g_eps_is_alert_queue_fail_mode)) return det_ctx->alert_queue_capacity; #endif diff --git a/src/flow-hash.c b/src/flow-hash.c index bd35848a1d13..664dce45dae9 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2024 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -694,7 +694,7 @@ static inline void NoFlowHandleIPS(ThreadVars *tv, FlowLookupStruct *fls, Packet static Flow *FlowGetNew(ThreadVars *tv, FlowLookupStruct *fls, Packet *p) { const bool emerg = ((SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) != 0); -#ifdef DEBUG +#ifdef QA_SIMULATION if (g_eps_flow_memcap != UINT64_MAX && g_eps_flow_memcap == PcapPacketCntGet(p)) { NoFlowHandleIPS(tv, fls, p); StatsCounterIncr(&tv->stats, fls->dtv->counter_flow_memcap); diff --git a/src/source-pcap-file-helper.c b/src/source-pcap-file-helper.c index 0f3aac98f3f8..e88db6d51547 100644 --- a/src/source-pcap-file-helper.c +++ b/src/source-pcap-file-helper.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2020 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -104,7 +104,7 @@ void CleanupPcapFileFileVars(PcapFileFileVars *pfv) void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt) { SCEnter(); -#ifdef DEBUG +#ifdef QA_SIMULATION if (unlikely((pcap_g.cnt + 1ULL) == g_eps_pcap_packet_loss)) { SCLogNotice("skipping packet %" PRIu64, g_eps_pcap_packet_loss); pcap_g.cnt++; diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 6d9efa249d32..06439827ff31 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2024 Open Information Security Foundation +/* Copyright (C) 2007-2026 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 @@ -75,6 +75,8 @@ static SCMutex segment_pool_memuse_mutex; static uint64_t segment_pool_memuse = 0; static uint64_t segment_pool_memcnt = 0; +#endif +#ifdef QA_SIMULATION thread_local uint64_t t_pcapcnt = UINT64_MAX; #endif @@ -162,7 +164,7 @@ uint64_t StreamTcpReassembleMemuseGlobalCounter(void) */ int StreamTcpReassembleCheckMemcap(uint64_t size) { -#ifdef DEBUG +#ifdef QA_SIMULATION if (unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX && g_eps_stream_reassembly_memcap == t_pcapcnt))) { SCLogNotice("simulating memcap reached condition for packet %" PRIu64, t_pcapcnt); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index ff6b78130ab4..7b6d0764fc75 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -219,9 +219,9 @@ extern int g_detect_disabled; PoolThread *ssn_pool = NULL; static SCMutex ssn_pool_mutex = SCMUTEX_INITIALIZER; /**< init only, protect initializing and growing pool */ -#ifdef DEBUG -extern thread_local uint64_t t_pcapcnt; +#if defined(DEBUG) || defined(QA_SIMULATION) static uint64_t ssn_pool_cnt = 0; /** counts ssns, protected by ssn_pool_mutex */ +extern thread_local uint64_t t_pcapcnt; #endif TcpStreamCnf stream_config; @@ -948,12 +948,12 @@ static TcpSession *StreamTcpNewSession(ThreadVars *tv, StreamTcpThread *stt, Pac #endif StatsCounterIncr(&tv->stats, stt->counter_tcp_ssn_from_pool); } -#ifdef DEBUG +#if defined(DEBUG) || defined(QA_SIMULATION) SCMutexLock(&ssn_pool_mutex); if (p->flow->protoctx != NULL) ssn_pool_cnt++; SCMutexUnlock(&ssn_pool_mutex); - +#ifdef QA_SIMULATION if (unlikely((g_eps_stream_ssn_memcap != UINT64_MAX && g_eps_stream_ssn_memcap == t_pcapcnt))) { SCLogNotice("simulating memcap reached condition for packet %" PRIu64, t_pcapcnt); @@ -961,6 +961,7 @@ static TcpSession *StreamTcpNewSession(ThreadVars *tv, StreamTcpThread *stt, Pac StreamTcpSsnMemcapExceptionPolicyStatsIncr(tv, stt, stream_config.ssn_memcap_policy); return NULL; } +#endif #endif ssn = (TcpSession *)p->flow->protoctx; if (ssn == NULL) { @@ -6120,9 +6121,9 @@ TmEcode StreamTcp (ThreadVars *tv, Packet *p, void *data, PacketQueueNoLock *pq) : "noflow", PktSrcToString(p->pkt_src)); -#ifdef DEBUG +#ifdef QA_SIMULATION t_pcapcnt = PcapPacketCntGet(p); -#endif /* DEBUG */ +#endif if (!(PacketIsTCP(p))) { return TM_ECODE_OK; diff --git a/src/suricata.c b/src/suricata.c index 903d8abd05e6..a4830d431318 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -751,6 +751,7 @@ static void PrintBuildInfo(void) { const char *bits; const char *endian; + /* If all current features are enabled, features string would be 341 characters long */ char features[2048] = ""; const char *tls; @@ -761,6 +762,9 @@ static void PrintBuildInfo(void) #ifdef DEBUG_VALIDATION strlcat(features, "DEBUG_VALIDATION ", sizeof(features)); #endif +#ifdef QA_SIMULATION + strlcat(features, "QA_SIMULATION ", sizeof(features)); +#endif #ifdef UNITTESTS strlcat(features, "UNITTESTS ", sizeof(features)); #endif diff --git a/src/util-exception-policy.c b/src/util-exception-policy.c index 9befaf6c6b52..4276636fb248 100644 --- a/src/util-exception-policy.c +++ b/src/util-exception-policy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022-2025 Open Information Security Foundation +/* Copyright (C) 2022-2026 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 @@ -390,7 +390,7 @@ void ExceptionPolicySetStatsCounters(ThreadVars *tv, ExceptionPolicyCounters *co } } -#ifndef DEBUG +#ifndef QA_SIMULATION int ExceptionSimulationCommandLineParser(const char *name, const char *arg) { diff --git a/src/util-exception-policy.h b/src/util-exception-policy.h index 9d3dcc4260d6..7f94a9f8eda3 100644 --- a/src/util-exception-policy.h +++ b/src/util-exception-policy.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022-2025 Open Information Security Foundation +/* Copyright (C) 2022-2026 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 @@ -38,7 +38,7 @@ void ExceptionPolicySetStatsCounters(ThreadVars *tv, ExceptionPolicyCounters *co const char *default_str, bool (*isExceptionPolicyValid)(enum ExceptionPolicy)); extern enum ExceptionPolicy g_eps_master_switch; -#ifdef DEBUG +#ifdef QA_SIMULATION extern uint64_t g_eps_applayer_error_offset_ts; extern uint64_t g_eps_applayer_error_offset_tc; extern uint64_t g_eps_pcap_packet_loss;