From 24360415577b320c954687c65003a6758be1eab1 Mon Sep 17 00:00:00 2001 From: Max Inden <mail@max-inden.de> Date: Mon, 16 Dec 2024 11:40:13 +0100 Subject: [PATCH] fix(udp): make GRO (i.e. URO) optional, off by default We have multiple bug reports for URO on Windows, including non-ARM. See: - https://github.com/quinn-rs/quinn/issues/2041 - https://bugzilla.mozilla.org/show_bug.cgi?id=1916558 Instead of enabling GRO on Windows by default, this commit changes the default to off, adding a `set_gro` to optionally enable it. --- quinn-udp/src/windows.rs | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/quinn-udp/src/windows.rs b/quinn-udp/src/windows.rs index 223ab0fdf6..0af3c5021e 100644 --- a/quinn-udp/src/windows.rs +++ b/quinn-udp/src/windows.rs @@ -107,23 +107,35 @@ impl UdpSocketState { )?; } - // Opportunistically try to enable GRO - _ = set_socket_option( - &*socket.0, - WinSock::IPPROTO_UDP, - WinSock::UDP_RECV_MAX_COALESCED_SIZE, - // u32 per - // https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options. - // Choice of 2^16 - 1 inspired by msquic. - u16::MAX as u32, - ); - let now = Instant::now(); Ok(Self { last_send_error: Mutex::new(now.checked_sub(2 * IO_ERROR_LOG_INTERVAL).unwrap_or(now)), }) } + /// Enable or disable receive offloading. + /// + /// Also referred to as UDP Receive Segment Coalescing Offload (URO) on Windows. + /// + /// <https://learn.microsoft.com/en-us/windows-hardware/drivers/network/udp-rsc-offload> + /// + /// Disabled by default due to <https://github.com/quinn-rs/quinn/issues/2041>. + pub fn set_gro(&self, enable: bool) -> io::Result<()> { + set_socket_option( + &*socket.0, + WinSock::IPPROTO_UDP, + WinSock::UDP_RECV_MAX_COALESCED_SIZE, + if enable { + // u32 per + // https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options. + // Choice of 2^16 - 1 inspired by msquic. + u16::MAX as u32 + } else { + 0 + }, + ) + } + /// Sends a [`Transmit`] on the given socket. /// /// This function will only ever return errors of kind [`io::ErrorKind::WouldBlock`].