From 7c987e7ede7961e03981aa64a394af9f29de321a Mon Sep 17 00:00:00 2001 From: Erin Power Date: Mon, 21 Oct 2024 14:14:10 +0200 Subject: [PATCH] feat: Add UDP GRO option --- src/sys/unix.rs | 40 +++++++++++++++++++++++++++++++++++++++- tests/socket.rs | 6 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/sys/unix.rs b/src/sys/unix.rs index 3a898bc3..5f47342f 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -179,7 +179,7 @@ pub(crate) use libc::SO_LINGER; ))] pub(crate) use libc::SO_LINGER_SEC as SO_LINGER; #[cfg(target_os = "linux")] -pub(crate) use libc::SO_PASSCRED; +pub(crate) use libc::{SO_PASSCRED, SOL_UDP, UDP_GRO}; pub(crate) use libc::{ ip_mreq as IpMreq, linger, IPPROTO_IP, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, @@ -896,6 +896,44 @@ impl SockAddr { #[cfg(not(any(target_os = "linux", target_os = "android")))] None } + + /// Get the value of the `UDP_GRO` option on this socket. + /// + /// For more information about this option, see [`set_udp_gro`]. + /// + /// [`set_udp_gro`]: Socket::set_udp_gro + #[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))) + )] + pub fn udp_gro(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), sys::SOL_UDP, sys::UDP_GRO) + .map(|reuse| reuse != 0) + } + } + + /// Set value for the `UDP_GRO` option on this socket. + /// + /// This indicates that the kernel can combine multiple datagrams into a + /// single buffer, this needs to be used in combination with [`Self::recvmsg`] + /// to get the number of segments in the buffer from the [`MsgHdr`]. + #[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))) + )] + pub fn set_udp_gro(&self, reuse: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + sys::SOL_UDP, + sys::UDP_GRO, + reuse as c_int, + ) + } + } } pub(crate) type Socket = c_int; diff --git a/tests/socket.rs b/tests/socket.rs index 2300f0ed..4b3ca73c 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1355,6 +1355,12 @@ test!(reuse_address, set_reuse_address(true)); not(any(windows, target_os = "solaris", target_os = "illumos")) ))] test!(reuse_port, set_reuse_port(true)); +#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))) +)] +test!(udp_gro, set_udp_gro(true)); #[cfg(all(feature = "all", target_os = "freebsd"))] test!(reuse_port_lb, set_reuse_port_lb(true)); #[cfg(all(feature = "all", unix, not(target_os = "redox")))]