From 5cbbc1e2dd09d4c8d8a9196dafe20e1be5cf4861 Mon Sep 17 00:00:00 2001 From: "claude[bot]" Date: Wed, 4 Mar 2026 08:28:12 +0000 Subject: [PATCH] fix: remove TCP port probe from verify_port_forwarding after restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The verify_port_forwarding() method called wait_for_port_forwarding() after the ping succeeded, which did a bare TcpStream::connect() + immediate drop through pasta's L2 port forwarding. Even though the guest was alive and ARP was resolved at this point, the connect-then- drop created a half-open entry in pasta's connection tracking table that poisoned subsequent data connections on the same port — causing 0-byte HTTP responses in the bench clone_http test on both x64 and arm64. The ping already confirms the full L2/L3 path through pasta's bridge is working (namespace → bridge → guest). Pasta is listening on the loopback ports (confirmed at startup). Together these guarantee the forwarding chain is functional without needing a TCP port probe. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/network/pasta.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/network/pasta.rs b/src/network/pasta.rs index a3ed3fdb..326e8779 100644 --- a/src/network/pasta.rs +++ b/src/network/pasta.rs @@ -668,8 +668,16 @@ impl NetworkManager for PastaNetwork { /// existing ones. The active ping forces the namespace kernel to send an /// ARP request that the guest replies to, creating a REACHABLE entry. /// - /// Once ARP is resolved, we probe each forwarded port to confirm pasta's - /// loopback port forwarding is end-to-end functional. + /// Once ARP is resolved, the L2 forwarding path through pasta's bridge is + /// confirmed working. We do NOT probe individual forwarded ports with + /// TcpStream::connect() here — even though the guest is alive, a bare + /// connect-then-drop creates a half-open connection in pasta's L2 + /// connection tracking that can poison subsequent data connections + /// (manifesting as 0-byte HTTP responses). + /// + /// The ping proves: namespace → pasta bridge → guest L2/L3 path works. + /// Pasta is already listening on the loopback ports (confirmed at startup). + /// Together these guarantee the forwarding chain is functional. async fn verify_port_forwarding(&self) -> Result<()> { if self.port_mappings.is_empty() { return Ok(()); @@ -699,9 +707,14 @@ impl NetworkManager for PastaNetwork { if output.status.success() { info!( guest_ip = GUEST_IP, - "guest reachable via ping, ARP resolved" + "guest reachable via ping, ARP resolved — port forwarding path ready" ); - self.wait_for_port_forwarding().await?; + // Do NOT call wait_for_port_forwarding() here. + // A bare TcpStream::connect() + immediate drop through pasta's + // L2 translation creates a half-open entry in pasta's connection + // tracking table that poisons subsequent connections on the same + // port (0-byte responses). The ping already confirms L2 + // reachability and pasta is listening on the loopback ports. return Ok(()); }