From 7aa8417522827adbf9bbd290ae6b4a7cc9a89cc1 Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Tue, 10 Mar 2026 18:12:15 +0200 Subject: [PATCH 1/2] virtio/net: replace vnet_hdr_len() with a constant mem::size_of is a const fn, so the virtio-net header length can be a compile-time constant instead of a function call. This allows using it in const expressions, which is needed in a following change to derive the macOS socket send buffer size from MAX_BUFFER_SIZE. Assisted-by: Cursor/Claude Opus 4.6 Signed-off-by: Nir Soffer --- src/devices/src/virtio/net/mod.rs | 11 ++++------- src/devices/src/virtio/net/worker.rs | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/devices/src/virtio/net/mod.rs b/src/devices/src/virtio/net/mod.rs index d3e7e9739..e0c51f3fd 100644 --- a/src/devices/src/virtio/net/mod.rs +++ b/src/devices/src/virtio/net/mod.rs @@ -19,16 +19,13 @@ mod unixgram; mod unixstream; mod worker; -fn vnet_hdr_len() -> usize { - mem::size_of::() -} +// https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2050006 +const VNET_HDR_LEN: usize = mem::size_of::(); // This initializes to all 0 the virtio_net_hdr part of a buf and return the length of the header -// https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2050006 fn write_virtio_net_hdr(buf: &mut [u8]) -> usize { - let len = vnet_hdr_len(); - buf[0..len].fill(0); - len + buf[0..VNET_HDR_LEN].fill(0); + VNET_HDR_LEN } pub use self::device::Net; diff --git a/src/devices/src/virtio/net/worker.rs b/src/devices/src/virtio/net/worker.rs index 222b781a0..05341df3c 100644 --- a/src/devices/src/virtio/net/worker.rs +++ b/src/devices/src/virtio/net/worker.rs @@ -8,7 +8,7 @@ use crate::virtio::{DeviceQueue, InterruptTransport}; use super::backend::{NetBackend, ReadError, WriteError}; use super::device::{FrontendError, RxError, TxError, VirtioNetBackend}; -use super::vnet_hdr_len; +use super::VNET_HDR_LEN; use std::os::fd::{AsRawFd, FromRawFd, OwnedFd}; use std::thread; @@ -202,7 +202,7 @@ impl NetWorker { pub(crate) fn process_backend_socket_writeable(&mut self) { match self .backend - .try_finish_write(vnet_hdr_len(), &self.tx_frame_buf[..self.tx_frame_len]) + .try_finish_write(VNET_HDR_LEN, &self.tx_frame_buf[..self.tx_frame_len]) { Ok(()) => self.process_tx_loop(), Err(WriteError::PartialWrite | WriteError::NothingWritten) => {} @@ -275,7 +275,7 @@ impl NetWorker { if self.backend.has_unfinished_write() && self .backend - .try_finish_write(vnet_hdr_len(), &self.tx_frame_buf[..self.tx_frame_len]) + .try_finish_write(VNET_HDR_LEN, &self.tx_frame_buf[..self.tx_frame_len]) .is_err() { log::trace!("Cannot process tx because of unfinished partial write!"); @@ -321,7 +321,7 @@ impl NetWorker { self.tx_frame_len = read_count; match self .backend - .write_frame(vnet_hdr_len(), &mut self.tx_frame_buf[..read_count]) + .write_frame(VNET_HDR_LEN, &mut self.tx_frame_buf[..read_count]) { Ok(()) => { self.tx_frame_len = 0; From 4a90cfe410f6142afd8468d3269710f60650fe54 Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Mon, 9 Mar 2026 17:56:37 +0200 Subject: [PATCH 2/2] virtio/net/unixgram: Fix SO_SNDBUF size on macOS On macOS, Unix datagram sockets do not use the send buffer for queuing. The send buffer size determines the maximum datagram size that can be sent. Set SO_SNDBUF to the maximum frame size (65550) instead of 7 MiB to match the actual semantics. On Linux, keep the 7 MiB send buffer for actual queuing. Also fix the SO_RCVBUF warning message which incorrectly said "SO_SNDBUF". Assisted-by: Cursor/Claude Opus 4.6 Signed-off-by: Nir Soffer --- src/devices/src/virtio/net/unixgram.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/devices/src/virtio/net/unixgram.rs b/src/devices/src/virtio/net/unixgram.rs index 04e230066..1ceb0722e 100644 --- a/src/devices/src/virtio/net/unixgram.rs +++ b/src/devices/src/virtio/net/unixgram.rs @@ -9,8 +9,22 @@ use std::path::PathBuf; use super::backend::{ConnectError, NetBackend, ReadError, WriteError}; use super::write_virtio_net_hdr; +#[cfg(target_os = "macos")] +use super::{MAX_BUFFER_SIZE, VNET_HDR_LEN}; const VFKIT_MAGIC: [u8; 4] = *b"VFKT"; +const DEFAULT_SOCKET_BUF_SIZE: usize = 7 * 1024 * 1024; + +// On macOS, with UNIX datagram sockets the send buffer is not used for queuing; +// it determines the maximum frame size. +// https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/kern/uipc_usrreq.c#L953 +#[cfg(target_os = "macos")] +const SOCKET_SNDBUF: usize = MAX_BUFFER_SIZE - VNET_HDR_LEN; + +#[cfg(not(target_os = "macos"))] +const SOCKET_SNDBUF: usize = DEFAULT_SOCKET_BUF_SIZE; + +const SOCKET_RCVBUF: usize = DEFAULT_SOCKET_BUF_SIZE; pub struct Unixgram { fd: OwnedFd, @@ -77,11 +91,11 @@ impl Unixgram { .map_err(ConnectError::SendingMagic)?; } - if let Err(e) = setsockopt(&fd, sockopt::SndBuf, &(7 * 1024 * 1024)) { - log::warn!("Failed to increase SO_SNDBUF (performance may be decreased): {e}"); + if let Err(e) = setsockopt(&fd, sockopt::SndBuf, &SOCKET_SNDBUF) { + log::warn!("Failed to set SO_SNDBUF: {e}"); } - if let Err(e) = setsockopt(&fd, sockopt::RcvBuf, &(7 * 1024 * 1024)) { - log::warn!("Failed to increase SO_SNDBUF (performance may be decreased): {e}"); + if let Err(e) = setsockopt(&fd, sockopt::RcvBuf, &SOCKET_RCVBUF) { + log::warn!("Failed to set SO_RCVBUF: {e}"); } log::debug!(