diff --git a/netstack/src/filter/conntrack.rs b/netstack/src/filter/conntrack.rs index 53febed445..694ab3a24c 100644 --- a/netstack/src/filter/conntrack.rs +++ b/netstack/src/filter/conntrack.rs @@ -285,17 +285,21 @@ impl ConntrackTable { let key = ConnKey::from_context(l3num, ctx); let reply_key = key.reply(); - // First check if this packet belongs to an existing reply flow - let (is_orig, entry_key) = if let Some(entry) = self.entries.get_mut(&reply_key) { + // First check if this packet belongs to an existing reply flow. + // If found, update and return — we do not fall through to the + // orig-side check, so the reply-direction state machine is + // actually reachable. (The previous code captured `is_orig` in + // a `(true, key.clone())` else-branch but the early return on + // line 293 made the variable always true and the reply-side + // state advances unreachable for already-established flows.) + if let Some(entry) = self.entries.get_mut(&reply_key) { entry.reply_packets = entry.reply_packets.saturating_add(1); entry.reply_bytes = entry.reply_bytes.saturating_add(ctx.packet.len() as u64); advance_entry_state(entry, false, ctx, now); return entry.state; - } else { - (true, key.clone()) - }; + } - if let Some(entry) = self.entries.get_mut(&entry_key) { + if let Some(entry) = self.entries.get_mut(&key) { entry.orig_packets = entry.orig_packets.saturating_add(1); entry.orig_bytes = entry.orig_bytes.saturating_add(ctx.packet.len() as u64); advance_entry_state(entry, true, ctx, now);