#701

Windows: duplicate TCP frames causes SACK storm and throttle throughput

Openlstocchiopened 3mo ago

When running high-throughput TCP tests with iperf3 on Windows against my libkrun VM I noticed that the result host -> guest were not that good (150Mbps). By digging into it, i found out that gvproxy frequently trasmits duplicate TCP frames within microseconds one another.

An example

15:41:32.691401 IP 192.168.127.1.19246 > 192.168.127.2.5202: Flags [P.], seq 129405470:129405578, ack 1, win 4096, options [nop,nop,TS val 3177150739 ecr 3838743611], length 108
15:41:32.691403 IP 192.168.127.1.19246 > 192.168.127.2.5202: Flags [.], seq 129405578:129412678, ack 1, win 4096, options [nop,nop,TS val 3177150739 ecr 3838743611], length 7100
15:41:32.691403 IP 192.168.127.1.19246 > 192.168.127.2.5202: Flags [P.], seq 129405470:129405578, ack 1, win 4096, options [nop,nop,TS val 3177150739 ecr 3838743611], length 108

This duplication is weird because i would expect to see a duplicate packet after a bit more time. It's impossible that the sender RTO is just 2 microseconds. This causes the receiver to generate SACKs/DSACKs in response, and the sender to update its congestion window and reducing the throughput.

Steps to Reproduce:

  • Launch a libkrun VM on Windows with gvproxy over a unix socket.
  • Run iperf3 -s -p <port> inside the VM.
  • Run iperf3 -c <target_ip> -p <port> -t 10 from the client.
  • Capture traffic with tcpdump on the interface and inspect for sub-millisecond duplicate sequence numbers and SACK blocks.

I am not sure this is from gvproxy or some other part of the stack. I'm opening this issue so i don't forget. Even if the result is not that good it's still 7x better than what we have with hvsock/hyperv. So i guess we always faced it but nobody complained/investigated.

Activity

1
Lanius-collaris2mo ago

It's impossible that the sender RTO is just 2 microseconds.

In fact gvisor-tap-vsock will convert 1 TCP connection into 2 TCP connections, one between the remote machine and the host, one between gVisor's TCP stack and the guest, so it's possible to observe very small RTTs.