microsoft / microsoft/WSL

WSL2 on AMD: Connected UDP socket loopback delivery silently drops packets after initial transmission (kvm_amd vs kvm_intel)

Open
#40,214 3 comments 0 reactions 0 assignees View on GitHub
kernel
Dominant language
C++
Stars
33.7k
Forks
1.8k
Avg merge
3d 17h
Merged PRs (30d)
116

Description

### Windows Version

10.0.26200.8246

### WSL Version

2.7.1.0

### Are you using WSL 1 or WSL 2?

- [x] WSL 2
- [ ] WSL 1

### Kernel Version

6.6.114.1-1

### Distro Version

Ubuntu 24.04.4 LTS

### Other Software

QEMU 8.2.2 (Debian 1:8.2.2+ds-0ubuntu1.16)
GNS3 server 2.2.58.1
ubridge 0.9.19

### Repro Steps

Hardware: AMD Ryzen CPU with Hyper-V nested virtualization enabled
(same configuration works good on Intel CPU)

1. Install GNS3 server in WSL2 Ubuntu 24.04
2. Create a topology with two QEMU VMs (e.g., Cisco IOSv and Huawei NE40E images)
3. Connect them via a virtual link (uses ubridge UDP tunnel internally)
4. Configure IP addresses on both ends of the link
5. Try ping between the two VMs

Internally, GNS3/QEMU uses:
qemu-system-x86_64 -enable-kvm \
-netdev socket,id=net0,udp=127.0.0.1:20053,localaddr=127.0.0.1:20052
And ubridge creates a connected UDP socket on port 20053 to bridge frames.

### Expected Behavior

Ping between the VMs should succeed (and does succeed on Intel CPU
machines with the same WSL kernel, QEMU, GNS3, and image versions).

### Actual Behavior

Ping fails with 100% packet loss.

Diagnostic findings:
- strace shows QEMU calls sendto(fd, ..., 127.0.0.1:20053) and the
kernel returns success (= packet length, e.g. 60).
- However, the receiving connected UDP socket on port 20053 (held by
ubridge) only receives the initial ~10 packets sent during VM boot.
- After that, sendto() continues to return success but no packets reach
the receiver. /proc/net/snmp shows OutDatagrams increasing but
InDatagrams unchanged — packets are silently dropped on loopback.
- The guest OS believes packets are sent (interface tx counter increases).

Workaround: Replacing -netdev socket with -netdev tap + Linux bridge
makes networking work. This proves the issue is specifically with
connected UDP socket loopback delivery in this environment.

Reproduction tests already done that did NOT fix the issue:
- QEMU 6.2 vs 8.2.2: same behavior
- KVM enabled vs accel=tcg: same behavior
- -netdev socket vs -netdev dgram: same behavior
- e1000 vs i82559er NIC: same behavior
- kvm_amd npt=0: same behavior
- Upgrading WSL kernel from 6.6.87.2 to 6.6.114.1: same behavior
- Disabling bridge-nf-call-iptables: irrelevant
- Standard Python connected UDP socket loopback test: WORKS fine,
so issue only manifests with QEMU's high-rate sendto pattern.

Same exact software stack on Intel CPU works perfectly. Only difference
between machines: kvm_intel vs kvm_amd module.

[wsl_kvm_amd_repro.sh](https://github.com/user-attachments/files/26806549/wsl_kvm_amd_repro.sh)

### Diagnostic Logs

dmesg | grep kvm output:
[ 2.733852] kvm_amd: TSC scaling supported
[ 2.733858] kvm_amd: Nested Virtualization enabled
[ 2.733859] kvm_amd: Nested Paging enabled
[ 2.733861] kvm_amd: kvm_amd: Hyper-V enlightened NPT TLB flush enabled
[ 2.733862] kvm_amd: kvm_amd: Hyper-V Direct TLB Flush enabled
[ 2.733872] kvm_amd: Virtual VMLOAD VMSAVE supported

Intel machine (working) shows instead:
kvm_intel: Using Hyper-V Enlightened VMCS

Contributor guide

Open the contributing guide

Research direction

Start with wsl_kvm_amd_repro.sh and reproduce the QEMU -netdev socket UDP loopback case on AMD and Intel configurations. Inspect sendto results alongside /proc/net/snmp and compare kvm_amd with kvm_intel; done means identifying and correcting the silent packet loss so the VM ping succeeds without the tap workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux
Domain
networking, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.