Repository navigation
Description
Windows Version
Microsoft Windows [Version 10.0.26200.9106]
WSL Version
2.7.10.0
Are you using WSL 1 or WSL 2?
- WSL 2
- WSL 1
Kernel Version
6.18.33.2-2
Distro Version
Ubuntu 24.04 (Noble Numbat)
Other Software
openvpn3-linux v26-3 and v27.1 (OpenVPN core 3.11.5 / 3.11.7) — affected, but only
as a symptom. The benchmark below reproduces the underlying behaviour with nothing
installed beyond Python 3.
Repro Steps
bind() takes ~10 ms on every socket family under WSL2, while socket() creation
is free. This is not specific to networking mode — a private (non-mirrored) network
namespace shows the same cost.
.wslconfig:
[wsl2]
networkingMode=mirrored
dnsTunneling=true
firewall=false
autoProxy=true
[experimental]
hostAddressLoopback=true- Save and run this benchmark.
socket()is timed separately as a control:
import socket, time, statistics, os
N = 200
def bench(label, make, act):
ts = []
for _ in range(N):
s = make()
t0 = time.perf_counter(); act(s); t1 = time.perf_counter()
ts.append((t1 - t0) * 1000); s.close()
ts.sort()
print(f"{label:36s} median {statistics.median(ts):7.3f} ms min {ts[0]:6.3f} max {ts[-1]:7.3f}")
bench("AF_NETLINK bind()",
lambda: socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE),
lambda s: s.bind((0, 0)))
bench("AF_NETLINK socket() only (control)",
lambda: socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE),
lambda s: None)
bench("AF_UNIX bind() (abstract)",
lambda: socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM),
lambda s: s.bind("\0b%d_%d" % (os.getpid(), time.time_ns())))
bench("AF_INET/UDP bind()",
lambda: socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
lambda s: s.bind(("127.0.0.1", 0)))- To separate mirrored-mode cost from baseline cost, run the same script again
inside a private network namespace, which is not mirrored:
sudo unshare -n -- sh -c "ip link set lo up; exec python3 bench.py"Expected Behavior
bind() on AF_UNIX and AF_NETLINK involves no network stack coordination and
should complete in microseconds, as it does on a conventional Linux kernel.
AF_INET bind() to an ephemeral port on loopback should likewise be
inexpensive.
Actual Behavior
host netns private netns
AF_NETLINK bind() 10.098 ms 10.092 ms <- unchanged
AF_UNIX bind() 10.150 ms 10.495 ms <- unchanged
AF_INET/UDP bind() 21.141 ms 10.500 ms <- halved
socket() only (control) 0.000 ms 0.000 ms
Two independent effects:
- A baseline ~10 ms
bind()cost on every socket family, identical inside a
private namespace. Not related to mirrored networking. This is the one with
real impact. - Mirrored mode adds a second ~10 ms increment, but only to
AF_INET
(21 ms vs 10.5 ms). Plausibly port coordination with the Windows host —
AF_UNIXandAF_NETLINKhave no ports and are unaffected.
socket() measuring ~0 ms rules out general syscall overhead.
Correction (see comment below). I originally wrote that the ~10 ms figure
looked like a scheduler tick. That is wrong — this kernel isCONFIG_HZ=250
(a 4 ms tick), and 10 ms is not a multiple of 4 ms. A 400-sample histogram is
sharply unimodal at 10–12 ms forAF_NETLINK(97% within 8–12 ms) and at
20–22 ms forAF_INET(90%), i.e. almost exactly 2×. That points at one and
two instances of a fixed ~10 ms synchronous cost rather than anything
timer-aligned. Confirmed independently of Python viastrace -Ton
openvpn3-service-netcfg(C++): 901bind()calls, mean 9.1 ms, max 10.8 ms.
Real-world impact. openvpn3-linux cannot establish a tunnel at all. Its
openvpn3-service-netcfg opens a fresh AF_NETLINK socket per configuration
operation; with a split-tunnel profile pushing ~900 routes (a commonplace
corporate configuration) that is ~900 × ~10 ms ≈ 9 s, against a fixed 5 s D-Bus
timeout on its Establish() call:
901 bind() calls mean 9.1 ms max 10.8 ms total 8.183 s
Error calling NetCfgDevice::Establish(): ... Timeout was reached
Failed configuring TUN device (TUN_IFACE_CREATE)
507 of the 900 operations had completed when the caller aborted. The identical
route set installed through a single reused socket (ip -batch) takes ~0.4 s, so
the per-bind() cost is the entire difference between working and not working.
Switching to NAT mode does not help, since the baseline cost is not
mirrored-mode related. The per-socket churn is also being reported to
openvpn3-linux separately.
Diagnostic Logs
Per-operation pattern from strace -f -tt -T on openvpn3-service-netcfg,
repeating once per route:
socket(AF_UNIX, SOCK_DGRAM) -> ioctl(SIOCGIFINDEX) -> close
socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
-> setsockopt(SO_SNDBUF) -> setsockopt(SO_RCVBUF)
-> bind() <-- ~9-10 ms, dominant cost
-> getsockname -> sendmsg -> recvmsg -> close
Within the 5 s Establish() window: 507 bind() calls, 4.601 s in bind()
alone out of 4.939 s total worker syscall time — 93% of the budget.
Possibly related, though a different mechanism: #41443 (mirrored networking drops
replies from a TUN-based VPN adapter). Same kernel and distro; that one is about
packet delivery, this one about syscall latency.
Activity
github-actions commentedon Aug 28, 2026
Logs are required for review from WSL team
If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.
How to collect WSL logs
Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:
The script will output the path of the log file once done.
If this is a networking issue, please use
.\collect-wsl-logs.ps1 -LogProfile networkinginstead, following the instructions in Collect WSL logs for networking issuesOnce completed please upload the output files to this GitHub issue.
See Collect WSL logs (recommended method).
If you choose to email these logs instead of attaching them to the bug, please send them to [email protected] with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.
icicimov commentedon Aug 28, 2026
Two problems with the log bundle, and some additional data that I think is more
useful than it would be.
I can't run the collector.
collect-wsl-logs.ps1is#Requires -RunAsAdministratorand this is a managed device where I don't havelocal admin. So neither the default nor the
-LogProfile networkingvariant isavailable to me.
Its contents can't go in a public issue. The script runs
Get-NetIPConfiguration,Get-NetRoute,Get-NetFirewallRule,netshandpktmon/wprtraces. On this machineGet-NetRouteenumerates a corporate VPNsplit-tunnel of ~900 prefixes, along with hostname, DNS suffixes and internal
addressing. I'm not able to publish that. If the logs are genuinely required I
can ask for a one-off elevated run and send them to
[email protected]referencing this issue rather than attaching them here — but see below on whether
they'd tell you anything.
This issue carries no machine-specific state. The whole report is a ~20 line
Python script with a control, and the effect is a fixed per-call cost, not a
race, a hang or a crash. Anyone can reproduce it on a clean WSL2 install in
under a minute. There is no trace window to capture — every single
bind()isslow, all 400 of them.
Correction to my own speculation
I suggested the ~10 ms figure looked like a scheduler tick. That is wrong —
this kernel is
CONFIG_HZ=250, i.e. a 4 ms tick, and 10 ms is not a multiple of4 ms. Relevant config:
What the distribution actually looks like
n=400 per family, 2 ms buckets, host namespace:
Sharply unimodal, and
AF_INETsits at almost exactly 2xAF_NETLINK. Thatlooks like one and two instances of a fixed ~10 ms synchronous cost rather than
anything timer-aligned.
socket()creation in the same loop remains ~0.000 ms.This is not a Python measurement artifact —
strace -f -tt -Tonopenvpn3-service-netcfg(C++) independently shows the same thing on the rawsyscall:
901 such calls across that trace: mean 9.1 ms, max 10.8 ms, total 8.183 s.
The question, restated
Is a fixed ~10 ms
bind()expected under WSL2? It applies toAF_UNIXandAF_NETLINK, which need no host coordination, and it persists inside a privatenetwork namespace — so it is not the mirrored-mode port coordination that
plausibly explains the extra ~10 ms on
AF_INET.Happy to run any specific unprivileged command, or a narrower elevated capture
if you can tell me which one component you need — I'd rather do that than ship a
full ETW bundle of a corporate network configuration.