Skip to content

Commit bdfe862

Browse files
committed
fix(udp): do not enable URO on Windows on ARM
On Windows on ARM with Windows Subsystem for Linux (WSL) `WSA_RECVMSG` does not return the segment size of coalesced UDP datagrams. See quinn-rs#2041 for details. While lacking a fix for the root cause, don't enable URO, i.e. don't coalesce UDP datagrams on Windows on ARM.
1 parent f188909 commit bdfe862

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ tracing-subscriber = { version = "0.3.0", default-features = false, features = [
5353
url = "2"
5454
wasm-bindgen-test = { version = "0.3.45" }
5555
web-time = "1"
56-
windows-sys = { version = ">=0.52, <=0.59", features = ["Win32_Foundation", "Win32_System_IO", "Win32_Networking_WinSock"] }
56+
windows-sys = { version = ">=0.52, <=0.59", features = ["Win32_Foundation", "Win32_System_IO", "Win32_Networking_WinSock", "Win32_System_SystemInformation", "Win32_System_Threading"] }
5757

5858
[profile.bench]
5959
debug = true

quinn-udp/src/windows.rs

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ use std::{
44
net::{IpAddr, Ipv4Addr},
55
os::windows::io::AsRawSocket,
66
ptr,
7-
sync::Mutex,
7+
sync::{LazyLock, Mutex},
88
time::Instant,
99
};
1010

1111
use libc::{c_int, c_uint};
1212
use once_cell::sync::Lazy;
13-
use windows_sys::Win32::Networking::WinSock;
13+
use windows_sys::Win32::{
14+
Networking::WinSock,
15+
System::{
16+
SystemInformation::IMAGE_FILE_MACHINE_ARM64,
17+
Threading::{GetCurrentProcess, IsWow64Process2},
18+
},
19+
};
1420

1521
use crate::{
1622
cmsg::{self, CMsgHdr},
@@ -107,16 +113,33 @@ impl UdpSocketState {
107113
)?;
108114
}
109115

110-
// Opportunistically try to enable GRO
111-
_ = set_socket_option(
112-
&*socket.0,
113-
WinSock::IPPROTO_UDP,
114-
WinSock::UDP_RECV_MAX_COALESCED_SIZE,
115-
// u32 per
116-
// https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options.
117-
// Choice of 2^16 - 1 inspired by msquic.
118-
u16::MAX as u32,
119-
);
116+
match &*IS_WINDOWS_ON_ARM {
117+
Ok(true) => {
118+
// Bug on Windows on ARM, not receiving `UDP_COALESCED_INFO` `CMSG`
119+
// when _Virtual Machine Platform_ feature enabled. See
120+
// <https://github.com/quinn-rs/quinn/issues/2041> for details.
121+
debug!("detected Windows on ARM host thus not enabling URO")
122+
}
123+
Ok(false) => {
124+
// Opportunistically try to enable URO
125+
let result = set_socket_option(
126+
&*socket.0,
127+
WinSock::IPPROTO_UDP,
128+
WinSock::UDP_RECV_MAX_COALESCED_SIZE,
129+
// u32 per
130+
// https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options.
131+
// Choice of 2^16 - 1 inspired by msquic.
132+
u16::MAX as u32,
133+
);
134+
135+
if let Err(e) = result {
136+
debug!("failed to enable URO: {}", e);
137+
}
138+
}
139+
Err(e) => {
140+
debug!("failed to detect host system thus not enabling URO: {}", e);
141+
}
142+
}
120143

121144
let now = Instant::now();
122145
Ok(Self {
@@ -470,3 +493,28 @@ static MAX_GSO_SEGMENTS: Lazy<usize> = Lazy::new(|| {
470493
Err(_) => 1,
471494
}
472495
});
496+
497+
/// Evaluates to [`Ok(true)`] if executed either directly on Windows on ARM, or
498+
/// on an emulator which itself executes on Windows on ARM.
499+
///
500+
/// See
501+
/// <https://learn.microsoft.com/en-us/windows/arm/apps-on-arm-x86-emulation#detecting-emulation>
502+
/// for details.
503+
static IS_WINDOWS_ON_ARM: LazyLock<io::Result<bool>> = LazyLock::new(|| {
504+
let mut process_machine: u16 = 0;
505+
let mut native_machine: u16 = 0;
506+
507+
let result = unsafe {
508+
IsWow64Process2(
509+
GetCurrentProcess(),
510+
&mut process_machine as *mut u16,
511+
&mut native_machine as *mut u16,
512+
)
513+
};
514+
515+
if result == 0 {
516+
return Err(io::Error::last_os_error());
517+
}
518+
519+
Ok(native_machine == IMAGE_FILE_MACHINE_ARM64)
520+
});

0 commit comments

Comments
 (0)