Skip to content

Commit 41bf1db

Browse files
thomaseizingerdjc
authored andcommitted
fix: evaluate max_gso_segments for every socket on Windows
This follows the behaviour we have for UNIX-based systems. Support for GSO varies depending on the network driver which may change at runtime when e.g. a device switches between Ethernet and WiFi or gets plugged into a docking station. Resolves: #2491
1 parent c67e9d8 commit 41bf1db

File tree

1 file changed

+10
-11
lines changed

1 file changed

+10
-11
lines changed

quinn-udp/src/windows.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use std::{
44
net::{IpAddr, Ipv4Addr},
55
os::windows::io::AsRawSocket,
66
ptr,
7-
sync::{LazyLock, Mutex},
7+
sync::{
8+
LazyLock, Mutex,
9+
atomic::{AtomicUsize, Ordering},
10+
},
811
time::Instant,
912
};
1013

@@ -24,6 +27,7 @@ use crate::{
2427
#[derive(Debug)]
2528
pub struct UdpSocketState {
2629
last_send_error: Mutex<Instant>,
30+
max_gso_segments: AtomicUsize,
2731

2832
/// Whether the underlying Winsock provider supports IPv4 ECN socket options/control messages.
2933
///
@@ -153,6 +157,7 @@ impl UdpSocketState {
153157
let now = Instant::now();
154158
Ok(Self {
155159
last_send_error: Mutex::new(now.checked_sub(2 * IO_ERROR_LOG_INTERVAL).unwrap_or(now)),
160+
max_gso_segments: AtomicUsize::new(max_gso_segments(&*socket.0)),
156161
ecn_v4_supported,
157162
ecn_v6_supported,
158163
})
@@ -332,7 +337,7 @@ impl UdpSocketState {
332337
/// while using GSO.
333338
#[inline]
334339
pub fn max_gso_segments(&self) -> usize {
335-
*MAX_GSO_SEGMENTS
340+
self.max_gso_segments.load(Ordering::Relaxed)
336341
}
337342

338343
/// The number of segments to read when GRO is enabled. Used as a factor to
@@ -552,16 +557,10 @@ static WSARECVMSG_PTR: LazyLock<WinSock::LPFN_WSARECVMSG> = LazyLock::new(|| {
552557
wsa_recvmsg_ptr
553558
});
554559

555-
static MAX_GSO_SEGMENTS: LazyLock<usize> = LazyLock::new(|| {
556-
let socket = match std::net::UdpSocket::bind("[::]:0")
557-
.or_else(|_| std::net::UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)))
558-
{
559-
Ok(socket) => socket,
560-
Err(_) => return 1,
561-
};
560+
fn max_gso_segments(socket: &impl AsRawSocket) -> usize {
562561
const GSO_SIZE: c_uint = 1500;
563562
match set_socket_option(
564-
&socket,
563+
socket,
565564
WinSock::IPPROTO_UDP,
566565
WinSock::UDP_SEND_MSG_SIZE,
567566
GSO_SIZE,
@@ -570,4 +569,4 @@ static MAX_GSO_SEGMENTS: LazyLock<usize> = LazyLock::new(|| {
570569
Ok(()) => 512,
571570
Err(_) => 1,
572571
}
573-
});
572+
}

0 commit comments

Comments
 (0)