blob: e1a7656909ec81e325eebfafbdfc6821010f2cd9 [file] [edit]
#[cfg(target_os = "linux")]
use super::linux_imports::*;
#[cfg(unix)]
mod unix {
pub(super) use std::io;
pub(super) use std::os::fd::AsFd;
}
/// Indicators of settings applied to a socket. These settings aren't "applied"
/// to a socket. Rather, the same (maximal) settings are always applied to a
/// socket, and this struct indicates which of those settings were successfully
/// applied to a socket.
#[derive(Default)]
pub struct SocketCapabilities {
/// Indicates if the socket has "Generic Segmentation Offload" enabled.
pub has_gso: bool,
/// Indicates if the socket has "SO_RXQ_OVFL" set.
pub check_udp_drop: bool,
/// Indicates if the monotonic clock is set for transimssion timestamps.
pub has_txtime: bool,
/// Indicates if the monotonic clock is set for receiving timestamps.
pub has_rxtime: bool,
/// Indicates if the socket has "Generic Receive Offload" enabled.
pub has_gro: bool,
}
impl SocketCapabilities {
/// Try applying maximal settings to a socket and returns indicators of
/// which settings were successfully applied.
#[cfg(unix)]
pub fn apply_all_and_get_compatibility(
socket: &impl unix::AsFd, max_send_udp_payload_size: usize,
) -> Self {
let fd = socket.as_fd();
Self {
has_gso: set_gso_segment(&fd, max_send_udp_payload_size).is_ok(),
check_udp_drop: set_udp_rxq_ovfl(&fd).is_ok(),
has_txtime: set_tx_time(&fd).is_ok(),
has_rxtime: set_rx_time(&fd).is_ok(),
has_gro: set_gro(&fd).is_ok(),
}
}
}
#[cfg(target_os = "linux")]
pub fn set_gso_segment(sock: &impl AsFd, segment: usize) -> io::Result<()> {
setsockopt(sock, UdpGsoSegment, &(segment as i32))?;
Ok(())
}
#[cfg(all(not(target_os = "linux"), unix))]
pub fn set_gso_segment(_: &impl unix::AsFd, _: usize) -> unix::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
#[cfg(target_os = "linux")]
pub fn set_gro(sock: &impl AsFd) -> io::Result<()> {
UdpGroSegment.set(sock, &true)?;
Ok(())
}
#[cfg(not(target_os = "linux"))]
#[cfg(all(not(target_os = "linux"), unix))]
pub fn set_gro(_: &impl unix::AsFd) -> unix::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
#[cfg(target_os = "linux")]
fn set_udp_rxq_ovfl(sock: &impl AsFd) -> io::Result<()> {
setsockopt(sock, RxqOvfl, &1)?;
Ok(())
}
#[cfg(all(not(target_os = "linux"), unix))]
fn set_udp_rxq_ovfl(_: &impl unix::AsFd) -> unix::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
#[cfg(target_os = "linux")]
pub fn set_tx_time(sock: &impl AsFd) -> io::Result<()> {
let cfg = libc::sock_txtime {
clockid: libc::CLOCK_MONOTONIC,
flags: 0,
};
setsockopt(sock, TxTime, &cfg)?;
Ok(())
}
#[cfg(all(not(target_os = "linux"), unix))]
pub fn set_tx_time(_: &impl unix::AsFd) -> unix::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
#[cfg(target_os = "linux")]
pub fn set_rx_time(sock: &impl AsFd) -> io::Result<()> {
setsockopt(sock, ReceiveTimestampns, &true)?;
Ok(())
}
#[cfg(all(not(target_os = "linux"), unix))]
pub fn set_rx_time(_: &impl unix::AsFd) -> unix::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}