]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: per tx detect flags to a u8 progress value 12862/head
authorVictor Julien <vjulien@oisf.net>
Mon, 24 Mar 2025 10:20:39 +0000 (11:20 +0100)
committerVictor Julien <victor@inliniac.net>
Sat, 29 Mar 2025 05:38:03 +0000 (06:38 +0100)
Reduce per tx space for tracking detection/prefilter progress. Instead
of a per direction u64 of flags, where each bit reflected a progress
value, use a simple u8 to track the linear progression through the
progress values. Use an offset to allow 0 to mean no value.

Add flags field as well to track "skip detect" and "inspect complete".

rust/src/applayer.rs
rust/src/core.rs
src/app-layer-dnp3.c
src/app-layer-parser.c
src/app-layer-parser.h
src/detect-config.c
src/detect-engine-prefilter.c
src/detect-engine-prefilter.h
src/detect.c

index 604121c0e9ee77bdd456a1ba607e962f1ecd8f5c..943d35c16ac17a4aee42118049ea136e77519bbb 100644 (file)
@@ -114,6 +114,8 @@ pub struct AppLayerTxData {
     pub updated_tc: bool,
     pub updated_ts: bool,
 
+    flags: u8,
+
     /// logger flags for tx logging api
     logged: LoggerFlags,
 
@@ -134,9 +136,14 @@ pub struct AppLayerTxData {
     /// not using application layer keywords
     pub guessed_applayer_logged: u8,
 
-    /// detection engine flags for use by detection engine
-    detect_flags_ts: u64,
-    detect_flags_tc: u64,
+    /// detection engine progress tracking for use by detection engine
+    /// Reflects the "progress" of prefilter engines into this TX, where
+    /// the value is offset by 1. So if for progress state 0 the engines
+    /// are done, the value here will be 1. So a value of 0 means, no
+    /// progress tracked yet.
+    ///
+    detect_progress_ts: u8,
+    detect_progress_tc: u8,
 
     de_state: *mut DetectEngineState,
     pub events: *mut core::AppLayerDecoderEvents,
@@ -184,8 +191,9 @@ impl AppLayerTxData {
             guessed_applayer_logged: 0,
             updated_tc: true,
             updated_ts: true,
-            detect_flags_ts: 0,
-            detect_flags_tc: 0,
+            flags: 0,
+            detect_progress_ts: 0,
+            detect_progress_tc: 0,
             de_state: std::ptr::null_mut(),
             events: std::ptr::null_mut(),
         }
@@ -194,9 +202,9 @@ impl AppLayerTxData {
     /// Create new AppLayerTxData for a transaction in a single
     /// direction.
     pub fn for_direction(direction: Direction) -> Self {
-        let (detect_flags_ts, detect_flags_tc, updated_ts, updated_tc) = match direction {
-            Direction::ToServer => (0, APP_LAYER_TX_SKIP_INSPECT_FLAG, true, false),
-            Direction::ToClient => (APP_LAYER_TX_SKIP_INSPECT_FLAG, 0, false, true),
+        let (flags, updated_ts, updated_tc) = match direction {
+            Direction::ToServer => (APP_LAYER_TX_SKIP_INSPECT_TC, true, false),
+            Direction::ToClient => (APP_LAYER_TX_SKIP_INSPECT_TS, false, true),
         };
         Self {
             config: AppLayerTxConfig::new(),
@@ -209,8 +217,9 @@ impl AppLayerTxData {
             guessed_applayer_logged: 0,
             updated_tc,
             updated_ts,
-            detect_flags_ts,
-            detect_flags_tc,
+            detect_progress_ts: 0,
+            detect_progress_tc: 0,
+            flags,
             de_state: std::ptr::null_mut(),
             events: std::ptr::null_mut(),
         }
@@ -528,7 +537,10 @@ pub const APP_LAYER_PARSER_EOF_TC : u16 = BIT_U16!(6);
 
 pub const APP_LAYER_PARSER_OPT_ACCEPT_GAPS: u32 = BIT_U32!(0);
 
-pub const APP_LAYER_TX_SKIP_INSPECT_FLAG: u64 = BIT_U64!(62);
+pub const APP_LAYER_TX_SKIP_INSPECT_TS: u8 = BIT_U8!(0);
+pub const APP_LAYER_TX_SKIP_INSPECT_TC: u8 = BIT_U8!(1);
+pub const _APP_LAYER_TX_INSPECTED_TS: u8 = BIT_U8!(2);
+pub const _APP_LAYER_TX_INSPECTED_TC: u8 = BIT_U8!(3);
 
 /// cbindgen:ignore
 extern {
index 3366f37838200b89aa0e983ebada635b6bb95ca2..07fe219c50769d16f6f2dbf2b5caf9bb446f3b13 100644 (file)
@@ -50,11 +50,11 @@ pub const ALPROTO_FAILED : AppProto = AppProtoEnum::ALPROTO_FAILED as AppProto;
 pub const IPPROTO_TCP : u8 = 6;
 pub const IPPROTO_UDP : u8 = 17;
 
-/*
+
 macro_rules!BIT_U8 {
     ($x:expr) => (1 << $x);
 }
-*/
+
 macro_rules!BIT_U16 {
     ($x:expr) => (1 << $x);
 }
index 9d1bc126cf3e71347b6e18c3621016b03a78fb77..b8634abcee3f88c62a0a2b8404338a6ec74c0724 100644 (file)
@@ -494,9 +494,9 @@ static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request)
     tx->tx_num = dnp3->transaction_max;
     tx->is_request = request;
     if (tx->is_request) {
-        tx->tx_data.detect_flags_tc |= APP_LAYER_TX_SKIP_INSPECT_FLAG;
+        tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TC;
     } else {
-        tx->tx_data.detect_flags_ts |= APP_LAYER_TX_SKIP_INSPECT_FLAG;
+        tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TS;
     }
     TAILQ_INIT(&tx->objects);
     TAILQ_INSERT_TAIL(&dnp3->tx_list, tx, next);
index cc7eb38394d17884e1209582bfb4c371ee064736..1461df83d6d1257a12752e14dc46c318a6d9bffd 100644 (file)
@@ -710,20 +710,10 @@ uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint
     SCReturnCT(0ULL, "uint64_t");
 }
 
-inline uint64_t AppLayerParserGetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir)
+inline uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir)
 {
-    uint64_t detect_flags =
-        (dir & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
-    return detect_flags;
-}
-
-static inline void SetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir, const uint64_t detect_flags)
-{
-    if (dir & STREAM_TOSERVER) {
-        txd->detect_flags_ts = detect_flags;
-    } else {
-        txd->detect_flags_tc = detect_flags;
-    }
+    uint8_t p = (dir & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
+    return p;
 }
 
 static inline uint32_t GetTxLogged(AppLayerTxData *txd)
@@ -766,12 +756,12 @@ void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *p
 
         AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
         if (txd && tag_txs_as_inspected) {
-            uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
-            if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
-                detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
-                SetTxDetectFlags(txd, flags, detect_flags);
-                SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
-                        tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+            const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
+                                                                     : APP_LAYER_TX_INSPECTED_TC;
+            if (txd->flags & inspected_flag) {
+                txd->flags |= inspected_flag;
+                SCLogDebug("%p/%" PRIu64 " in-order tx is done for direction %s. Flags %02x", tx,
+                        idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
             }
         }
         idx++;
@@ -806,12 +796,13 @@ void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *p
             /* txd can be NULL for HTTP sessions where the user data alloc failed */
             AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
             if (likely(txd)) {
-                uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
-                if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
-                    detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
-                    SetTxDetectFlags(txd, flags, detect_flags);
-                    SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
-                            tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+                const uint8_t inspected_flag = (flags & STREAM_TOSERVER)
+                                                       ? APP_LAYER_TX_INSPECTED_TS
+                                                       : APP_LAYER_TX_INSPECTED_TC;
+                if (txd->flags & inspected_flag) {
+                    txd->flags |= inspected_flag;
+                    SCLogDebug("%p/%" PRIu64 " out of order tx is done for direction %s. Flag %02x",
+                            tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
 
                     SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
                             tx, idx, pstate->inspect_id[direction]);
@@ -965,21 +956,19 @@ void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
         if (txd && has_tx_detect_flags) {
             if (!IS_DISRUPTED(ts_disrupt_flags) &&
                     (f->sgh_toserver != NULL || (f->flags & FLOW_SGH_TOSERVER) == 0)) {
-                uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(txd, STREAM_TOSERVER);
-                if (!(detect_flags_ts &
-                            (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
-                    SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%" PRIx64, tx, i,
-                            detect_flags_ts);
+                if ((txd->flags & (APP_LAYER_TX_INSPECTED_TS | APP_LAYER_TX_SKIP_INSPECT_TS)) ==
+                        0) {
+                    SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%02x", tx, i,
+                            txd->flags);
                     tx_skipped = true;
                 }
             }
             if (!IS_DISRUPTED(tc_disrupt_flags) &&
                     (f->sgh_toclient != NULL || (f->flags & FLOW_SGH_TOCLIENT) == 0)) {
-                uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(txd, STREAM_TOCLIENT);
-                if (!(detect_flags_tc &
-                            (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
-                    SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%" PRIx64, tx, i,
-                            detect_flags_tc);
+                if ((txd->flags & (APP_LAYER_TX_INSPECTED_TC | APP_LAYER_TX_SKIP_INSPECT_TC)) ==
+                        0) {
+                    SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%02x", tx, i,
+                            txd->flags);
                     tx_skipped = true;
                 }
             }
index ddde6db91ca567c58d8b59aa58fa80b57f8593ff..dfcc8f28fc82d801aa5c64a35349350be7f42f85 100644 (file)
 
 #define APP_LAYER_PARSER_INT_STREAM_DEPTH_SET   BIT_U32(0)
 
-/* applies to DetectFlags uint64_t field */
-
-/** reserved for future use */
-#define APP_LAYER_TX_RESERVED1_FLAG  BIT_U64(48)
-#define APP_LAYER_TX_RESERVED2_FLAG  BIT_U64(49)
-#define APP_LAYER_TX_RESERVED3_FLAG  BIT_U64(50)
-#define APP_LAYER_TX_RESERVED4_FLAG  BIT_U64(51)
-#define APP_LAYER_TX_RESERVED5_FLAG  BIT_U64(52)
-#define APP_LAYER_TX_RESERVED6_FLAG  BIT_U64(53)
-#define APP_LAYER_TX_RESERVED7_FLAG  BIT_U64(54)
-#define APP_LAYER_TX_RESERVED8_FLAG  BIT_U64(55)
-#define APP_LAYER_TX_RESERVED9_FLAG  BIT_U64(56)
-#define APP_LAYER_TX_RESERVED10_FLAG BIT_U64(57)
-#define APP_LAYER_TX_RESERVED11_FLAG BIT_U64(58)
-#define APP_LAYER_TX_RESERVED12_FLAG BIT_U64(59)
-#define APP_LAYER_TX_RESERVED13_FLAG BIT_U64(60)
-#define APP_LAYER_TX_RESERVED14_FLAG BIT_U64(61)
-
-#define APP_LAYER_TX_RESERVED_FLAGS                                                                \
-    (APP_LAYER_TX_RESERVED1_FLAG | APP_LAYER_TX_RESERVED2_FLAG | APP_LAYER_TX_RESERVED3_FLAG |     \
-            APP_LAYER_TX_RESERVED4_FLAG | APP_LAYER_TX_RESERVED5_FLAG |                            \
-            APP_LAYER_TX_RESERVED6_FLAG | APP_LAYER_TX_RESERVED7_FLAG |                            \
-            APP_LAYER_TX_RESERVED8_FLAG | APP_LAYER_TX_RESERVED9_FLAG |                            \
-            APP_LAYER_TX_RESERVED10_FLAG | APP_LAYER_TX_RESERVED11_FLAG |                          \
-            APP_LAYER_TX_RESERVED12_FLAG | APP_LAYER_TX_RESERVED13_FLAG |                          \
-            APP_LAYER_TX_RESERVED14_FLAG)
+/* for use with the detect_progress_ts|detect_progress_tc fields */
 
 /** should inspection be skipped in that direction */
-#define APP_LAYER_TX_SKIP_INSPECT_FLAG BIT_U64(62)
+#define APP_LAYER_TX_SKIP_INSPECT_TS BIT_U8(0)
+#define APP_LAYER_TX_SKIP_INSPECT_TC BIT_U8(1)
 /** is tx fully inspected? */
-#define APP_LAYER_TX_INSPECTED_FLAG             BIT_U64(63)
-/** other 63 bits are for tracking which prefilter engine is already
- *  completely inspected */
-#define APP_LAYER_TX_PREFILTER_MASK ~(APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_RESERVED_FLAGS)
+#define APP_LAYER_TX_INSPECTED_TS BIT_U8(2)
+#define APP_LAYER_TX_INSPECTED_TC BIT_U8(3)
 
 /** parser has successfully processed in the input, and has consumed
  *  all of it. */
@@ -253,7 +227,7 @@ uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto);
 bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto);
 
 AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx);
-uint64_t AppLayerParserGetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir);
+uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir);
 AppLayerStateData *AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state);
 void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
         void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig);
index 7ad8c88dca68551419b450f233b73ddd6ab68def..d700e5d0f9649115b412bffdf1ee7dfc582b9e52 100644 (file)
@@ -98,9 +98,9 @@ static void ConfigApplyTx(Flow *f,
             SCLogDebug("tx %p txd %p: log_flags %x", tx, txd, txd->config.log_flags);
             txd->config.log_flags |= BIT_U8(config->type);
 
-            uint64_t unidir = ((AppLayerParserGetTxDetectFlags(txd, STREAM_TOSERVER) |
-                                       AppLayerParserGetTxDetectFlags(txd, STREAM_TOCLIENT)) &
-                                      APP_LAYER_TX_SKIP_INSPECT_FLAG) != 0;
+            const bool unidir =
+                    (txd->flags & (APP_LAYER_TX_SKIP_INSPECT_TS | APP_LAYER_TX_SKIP_INSPECT_TC)) !=
+                    0;
             if (unidir) {
                 SCLogDebug("handle unidir tx");
                 AppLayerTxConfig req;
index db388bd6d70da975265f3ada155738b85a24bb0f..ab3b345d276507237d2b004605f9623efe988043 100644 (file)
@@ -102,8 +102,8 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
     /* reset rule store */
     det_ctx->pmq.rule_id_array_cnt = 0;
 
-    SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->prefilter_flags %" PRIx64, p->pcap_cnt,
-            tx->tx_ptr, tx->tx_progress, tx->prefilter_flags);
+    SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->detect_progress %02x", p->pcap_cnt,
+            tx->tx_ptr, tx->tx_progress, tx->detect_progress);
 
     PrefilterEngine *engine = sgh->tx_engines;
     do {
@@ -116,7 +116,11 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
         if (engine->ctx.tx_min_progress > tx->tx_progress)
             break;
         if (tx->tx_progress > engine->ctx.tx_min_progress) {
-            if (tx->prefilter_flags & BIT_U64(engine->ctx.tx_min_progress)) {
+            /* if state value is at or beyond engine state, we can skip it. It means we ran at
+             * least once already. */
+            if (tx->detect_progress > engine->ctx.tx_min_progress) {
+                SCLogDebug("tx already marked progress as beyond engine: %u > %u",
+                        tx->detect_progress, engine->ctx.tx_min_progress);
                 goto next;
             }
         }
@@ -127,7 +131,14 @@ void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx,
         PREFILTER_PROFILING_END(det_ctx, engine->gid);
 
         if (tx->tx_progress > engine->ctx.tx_min_progress && engine->is_last_for_progress) {
-            tx->prefilter_flags |= BIT_U64(engine->ctx.tx_min_progress);
+            /* track with an offset of one, so that tx->progress 0 complete is tracked
+             * as 1, progress 1 as 2, etc. This is to allow 0 to mean: nothing tracked, even
+             * though a parser may use 0 as a valid value. */
+            tx->detect_progress = engine->ctx.tx_min_progress + 1;
+            SCLogDebug("tx->tx_progress %d engine->ctx.tx_min_progress %d "
+                       "engine->is_last_for_progress %d => tx->detect_progress updated to %02x",
+                    tx->tx_progress, engine->ctx.tx_min_progress, engine->is_last_for_progress,
+                    tx->detect_progress);
         }
     next:
         if (engine->is_last)
index ec58594b9b00591aa35bf764bbd21322bb0fa1eb..2434fca536ee0be64428dac80cc390c0fddcfc08 100644 (file)
@@ -33,10 +33,13 @@ typedef struct DetectTransaction_ {
     const uint64_t tx_id;
     struct AppLayerTxData *tx_data_ptr;
     DetectEngineStateDirection *de_state;
-    const uint64_t detect_flags; /* detect flags get/set from/to applayer */
-    uint64_t prefilter_flags; /* prefilter flags for direction, to be updated by prefilter code */
-    const uint64_t
-            prefilter_flags_orig; /* prefilter flags for direction, before prefilter has run */
+
+    /* tracking detect progress. Holds the value of
+     * the last completed "progress" + 1. */
+    uint8_t detect_progress;
+    /* original value to track changes. */
+    const uint8_t detect_progress_orig;
+
     const int tx_progress;
     const int tx_end_state;
 } DetectTransaction;
index 3343033f3865b2feb7feb1578fccf7ef84d9c1ed..41cbe6d84a7fa1e485e07e3523bf4772307adf53 100644 (file)
@@ -737,8 +737,9 @@ static bool IsOnlyTxInDirection(Flow *f, uint64_t txid, uint8_t dir)
         if (tx) {
             AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, tx);
             // test if the other tx is unidirectional in the other way
-            if (txd &&
-                    (AppLayerParserGetTxDetectFlags(txd, dir) & APP_LAYER_TX_SKIP_INSPECT_FLAG)) {
+            if (txd && ((dir == STREAM_TOSERVER && (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TS)) ||
+                               (dir == STREAM_TOCLIENT &&
+                                       (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TC)))) {
                 return true;
             }
         }
@@ -1305,7 +1306,7 @@ static bool DetectRunTxInspectRule(ThreadVars *tv,
 
 #define NO_TX                                                                                      \
     {                                                                                              \
-        NULL, 0, NULL, NULL, 0, 0, 0, 0, 0,                                                        \
+        NULL, 0, NULL, NULL, 0, 0, 0, 0,                                                           \
     }
 
 /** \internal
@@ -1326,51 +1327,52 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro
         DetectTransaction no_tx = NO_TX;
         return no_tx;
     }
-    uint64_t detect_flags =
-            (flow_flags & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
-    if (unlikely(detect_flags & APP_LAYER_TX_INSPECTED_FLAG)) {
-        SCLogDebug("%"PRIu64" tx already fully inspected for %s. Flags %016"PRIx64,
-                tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
-                detect_flags);
+    const uint8_t inspected_flag =
+            (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS : APP_LAYER_TX_INSPECTED_TC;
+    if (unlikely(txd->flags & inspected_flag)) {
+        SCLogDebug("%" PRIu64 " tx already fully inspected for %s. Flags %02x", tx_id,
+                flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
         DetectTransaction no_tx = NO_TX;
         return no_tx;
     }
-    if (unlikely(detect_flags & APP_LAYER_TX_SKIP_INSPECT_FLAG)) {
-        SCLogDebug("%" PRIu64 " tx should not be inspected in direction %s. Flags %016" PRIx64,
-                tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
+    const uint8_t skip_flag = (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_SKIP_INSPECT_TS
+                                                             : APP_LAYER_TX_SKIP_INSPECT_TC;
+    if (unlikely(txd->flags & skip_flag)) {
+        SCLogDebug("%" PRIu64 " tx should not be inspected in direction %s. Flags %02x", tx_id,
+                flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
         DetectTransaction no_tx = NO_TX;
         return no_tx;
     }
 
+    const uint8_t detect_progress =
+            (flow_flags & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
+
     const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
     DetectEngineState *tx_de_state = txd->de_state;
-    DetectEngineStateDirection *tx_dir_state = tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
-    uint64_t prefilter_flags = detect_flags & APP_LAYER_TX_PREFILTER_MASK;
-    DEBUG_VALIDATE_BUG_ON(prefilter_flags & APP_LAYER_TX_RESERVED_FLAGS);
-
+    DetectEngineStateDirection *tx_dir_state =
+            tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
     DetectTransaction tx = {
-                            .tx_ptr = tx_ptr,
-                            .tx_id = tx_id,
-                            .tx_data_ptr = (struct AppLayerTxData *)txd,
-                            .de_state = tx_dir_state,
-                            .detect_flags = detect_flags,
-                            .prefilter_flags = prefilter_flags,
-                            .prefilter_flags_orig = prefilter_flags,
-                            .tx_progress = tx_progress,
-                            .tx_end_state = tx_end_state,
-                           };
+        .tx_ptr = tx_ptr,
+        .tx_id = tx_id,
+        .tx_data_ptr = (struct AppLayerTxData *)txd,
+        .de_state = tx_dir_state,
+        .detect_progress = detect_progress,
+        .detect_progress_orig = detect_progress,
+        .tx_progress = tx_progress,
+        .tx_end_state = tx_end_state,
+    };
     return tx;
 }
 
-static inline void StoreDetectFlags(
-        DetectTransaction *tx, const uint8_t flow_flags, const uint64_t detect_flags)
+static inline void StoreDetectProgress(
+        DetectTransaction *tx, const uint8_t flow_flags, const uint8_t progress)
 {
     AppLayerTxData *txd = (AppLayerTxData *)tx->tx_data_ptr;
     if (likely(txd != NULL)) {
         if (flow_flags & STREAM_TOSERVER) {
-            txd->detect_flags_ts = detect_flags;
+            txd->detect_progress_ts = progress;
         } else {
-            txd->detect_flags_tc = detect_flags;
+            txd->detect_progress_tc = progress;
         }
     }
 }
@@ -1648,34 +1650,26 @@ static void DetectRunTx(ThreadVars *tv,
 
         /* see if we have any updated state to store in the tx */
 
-        uint64_t new_detect_flags = 0;
         /* this side of the tx is done */
         if (tx.tx_progress >= tx.tx_end_state) {
-            new_detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
-            SCLogDebug("%p/%"PRIu64" tx is done for direction %s. Flag %016"PRIx64,
-                    tx.tx_ptr, tx.tx_id,
-                    flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
-                    new_detect_flags);
-        }
-        if (tx.prefilter_flags != tx.prefilter_flags_orig) {
-            new_detect_flags |= tx.prefilter_flags;
-            DEBUG_VALIDATE_BUG_ON(new_detect_flags & APP_LAYER_TX_RESERVED_FLAGS);
-            SCLogDebug("%p/%"PRIu64" updated prefilter flags %016"PRIx64" "
-                    "(was: %016"PRIx64") for direction %s. Flag %016"PRIx64,
-                    tx.tx_ptr, tx.tx_id, tx.prefilter_flags, tx.prefilter_flags_orig,
-                    flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
-                    new_detect_flags);
+            SCLogDebug("%" PRIu64 ": %s tx done", p->pcap_cnt,
+                    flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
+            const uint8_t inspected_flag = (flow_flags & STREAM_TOSERVER)
+                                                   ? APP_LAYER_TX_INSPECTED_TS
+                                                   : APP_LAYER_TX_INSPECTED_TC;
+            tx.tx_data_ptr->flags |= inspected_flag;
+            SCLogDebug("%p/%" PRIu64 " tx is done for direction %s. Progress %02x", tx.tx_ptr,
+                    tx.tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
+                    tx.detect_progress);
         }
-        if (new_detect_flags != 0 &&
-                (new_detect_flags | tx.detect_flags) != tx.detect_flags)
-        {
-            new_detect_flags |= tx.detect_flags;
-            DEBUG_VALIDATE_BUG_ON(new_detect_flags & APP_LAYER_TX_RESERVED_FLAGS);
-            SCLogDebug("%p/%"PRIu64" Storing new flags %016"PRIx64" (was %016"PRIx64")",
-                    tx.tx_ptr, tx.tx_id, new_detect_flags, tx.detect_flags);
 
-            StoreDetectFlags(&tx, flow_flags, new_detect_flags);
+        if (tx.detect_progress != tx.detect_progress_orig) {
+            SCLogDebug("%p/%" PRIu64 " Storing new progress %02x (was %02x)", tx.tx_ptr, tx.tx_id,
+                    tx.detect_progress, tx.detect_progress_orig);
+
+            StoreDetectProgress(&tx, flow_flags, tx.detect_progress);
         }
+
         InspectionBufferClean(det_ctx);
 
     next: