Skip to content

Commit

Permalink
Added support for options SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTA…
Browse files Browse the repository at this point in the history
…MPING
  • Loading branch information
tglane committed Apr 18, 2024
1 parent 6923954 commit dabbd2f
Show file tree
Hide file tree
Showing 5 changed files with 750 additions and 4 deletions.
265 changes: 265 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,271 @@ impl RecvFlags {
}
}

/// Flags for network package timestamping configuration of a socket
///
/// On Unix flags are set at the `SOL_SOCKET` level and the `SO_TIMESTAMPING`
/// option
/// On Windows flags are set using `WSAIoctl` and the `SOI_TIMESTAMPING` option
#[cfg(not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "nto",
target_os = "openbsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "fuchsia",
target_os = "vita",
target_os = "hurd",
)))]
#[cfg_attr(
docsrs,
doc(cfg(not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "nto",
target_os = "openbsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "fuchsia",
target_os = "vita",
target_os = "hurd",
))))
)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct TimestampingFlags(sys::c_uint);

#[cfg(not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "nto",
target_os = "openbsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "fuchsia",
target_os = "vita",
target_os = "hurd",
)))]
impl TimestampingFlags {
/// Creates a new instance of `TimestampingFlags` with no flags set
pub fn new() -> Self {
Self(0)
}

/// This flags controls if transmit timestamp reception should be enabled
///
/// This flag is only used for datagram-based sockets,
/// not for stream sockets.
///
/// On Unix this corresponds to the `TIMESTAMPING_FLAG_RX` flag.
#[cfg(target_os = "windows")]
#[cfg_attr(docsrs, doc(cfg(target_os = "windows")))]
pub fn set_rx(&mut self, active: bool) {
self.set_flag(sys::TIMESTAMPING_FLAG_RX, active);
}

/// This flags controls if receive timestamp reception should be enabled
///
/// This flag is only used for datagram-based sockets,
/// not for stream sockets.
///
/// On Windows this corresponds to the `TIMESTAMPING_FLAG_TX` flag.
#[cfg(target_os = "windows")]
#[cfg_attr(docsrs, doc(cfg(target_os = "windows")))]
pub fn set_tx(&mut self, active: bool) {
self.set_flag(sys::TIMESTAMPING_FLAG_TX, active);
}

/// This flags controls if rx timestamps should be generated by the network
/// adapter
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_RX_HARDWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_rx_hardware_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_RX_HARDWARE, active)
}

/// This flags controls if rx timestamps should be generated when a package
/// enters the kernel. These timestamps are generated just after a device
/// driver hands a packet to the kernel receive stack.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_RX_SOFTWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_rx_software_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_RX_SOFTWARE, active)
}

/// This flags controls if tx timestamps should be generated by the network
/// adapter
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_TX_HARDWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_tx_hardware_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_TX_HARDWARE, active)
}

/// This flags controls if tx timestamps should be generated when a package
/// enters the kernel. These timestamps are generated just after a device
/// driver hands a packet to the kernel receive stack.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_TX_SOFTWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_tx_software_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_TX_SOFTWARE, active)
}

/// This flags controls if tx timestamps should be generated prior to
/// entering the packet scheduler.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_TX_SCHED` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_tx_sched_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_TX_SCHED, active)
}

/// This flag controls if tx timestamps when all data in the send buffer
/// has been acknowledged
///
/// This flag is only used for stream-based sockets,
/// not for datagram sockets.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_TX_ACK` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_tx_ack_gen(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_TX_ACK, active)
}

/// This flag controls if any software generated timestamps should be
/// reported when available.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_SOFTWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_software_reporting(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_SOFTWARE, active)
}

/// This flag controls if any hardware generated timestamps such as
/// SOF_TIMESTAMPING_TX_HARDWARE should be reported when available.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_RAW_HARDWARE` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_raw_hardware_reporting(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_RAW_HARDWARE, active)
}

/// This flag controls if a unique identifier should be generated for each
/// packet. For datagram sockets, the counter increments with each sent
/// packet. For stream sockets, it increments with every byte.
///
/// This option is only implemented for transmit timestamps.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_ID` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_id(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_ID, active)
}

/// This flag controls if control messages should be supported for all
/// timestamped packets. This option enables `recv()` `cmsg` support for
/// IPv4 packets with transmit timestamps.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_CMSG` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_cmsg(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_CMSG, active)
}

/// This flag controls if the timestamp should be returned as a `cmsg`
/// alongside an empty packet, as opposed to alognside the original
/// packet.
///
/// This option is only implemented for transmit timestamps.
/// This option disables `SOF_TIMESTAMPING_OPT_CMSG` flag set by
/// `set_opt_cmsg(bool)`
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_TSONLY` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_tsonly(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_TSONLY, active)
}

/// This flag controls if optional stats should be obtained along with the
/// transmit timestamps.
///
/// This option must be used together with `SOF_TIMESTAMPING_OPT_TSONLY` set
/// by `set_opt_tsonly(bool)`.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_STATS` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_stats(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_STATS, active)
}

/// This flag enables the `SCM_TIMESTAMPING_PKTINFO` control message for
/// incoming packets with hardware timestamps.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_PKTINFO` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_pktinfo(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_PKTINFO, active)
}

/// This flag enables both hardware and software timestamps for outgoing
/// packets when `SOF_TIMESTAMPING_TX_HARDWARE` and
/// `SOF_TIMESTAMPING_TX_SOFTWARE` are enabled at the same time. If both
/// timestamps are generated, two separate messages will be looped to the
/// socket’s error queue, each containing just one timestamp.
///
/// On Unix this corresponds to the `SOF_TIMESTAMPING_OPT_TX_SWHW` flag.
#[cfg(not(target_os = "windows"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "windows"))))]
pub fn set_opt_tx_swhw(&mut self, active: bool) {
self.set_flag(sys::SOF_TIMESTAMPING_OPT_TX_SWHW, active)
}

#[inline(always)]
fn set_flag(&mut self, flag: sys::c_uint, active: bool) {
if active {
self.0 |= flag;
} else {
self.0 &= !flag;
}
}
}

/// A version of [`IoSliceMut`] that allows the buffer to be uninitialised.
///
/// [`IoSliceMut`]: std::io::IoSliceMut
Expand Down

0 comments on commit dabbd2f

Please sign in to comment.