diff --git a/src/socket.rs b/src/socket.rs index a0f4868..b2c207a 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -27,6 +27,12 @@ pub use self::linux::*; #[cfg(target_os = "macos")] use self::macos::*; +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default)] +pub struct FullTimestampData { + pub hardware: Option, + pub software: Option, +} + #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] pub struct Timestamp { pub seconds: i64, @@ -100,6 +106,7 @@ pub struct RecvResult { pub remote_addr: A, pub local_addr: A, pub timestamp: Option, + pub full_timestamp_data: FullTimestampData, } #[derive(Debug)] @@ -132,6 +139,7 @@ impl Socket { socket.receive_message(buf, &mut control_buf, MessageQueue::Normal)?; let mut timestamp = None; + let mut full_timestamp_data = FullTimestampData::default(); let mut local_addr = self.local_addr; // Loops through the control messages, but we should only get a single message @@ -141,6 +149,12 @@ impl Socket { ControlMessage::Timestamping { software, hardware } => { tracing::trace!("Timestamps: {:?} {:?}", software, hardware); timestamp = select_timestamp(self.timestamp_mode, software, hardware); + + // Keep the first timestamp of each kind + full_timestamp_data.software = + full_timestamp_data.software.or(software); + full_timestamp_data.hardware = + full_timestamp_data.hardware.or(hardware); } #[cfg(target_os = "linux")] @@ -175,6 +189,7 @@ impl Socket { remote_addr, local_addr, timestamp, + full_timestamp_data, }) }) .await @@ -182,7 +197,11 @@ impl Socket { } impl Socket { - pub async fn send_to(&mut self, buf: &[u8], addr: A) -> std::io::Result> { + pub async fn send_to( + &mut self, + buf: &[u8], + addr: A, + ) -> std::io::Result<(Option, FullTimestampData)> { let addr = addr.to_sockaddr(PrivateToken); self.socket @@ -205,7 +224,7 @@ impl Socket { unreachable!("Should not be able to create send timestamping sockets on platforms other than linux") } } else { - Ok(None) + Ok((None, FullTimestampData::default())) } } @@ -214,7 +233,7 @@ impl Socket { buf: &[u8], from: A, to: A, - ) -> std::io::Result> { + ) -> std::io::Result<(Option, FullTimestampData)> { let from = from.to_sockaddr(PrivateToken); let to = to.to_sockaddr(PrivateToken); @@ -240,7 +259,7 @@ impl Socket { unreachable!("Should not be able to create send timestamping sockets on platforms other than linux") } } else { - Ok(None) + Ok((None, FullTimestampData::default())) } } @@ -264,7 +283,10 @@ impl Socket { A::from_sockaddr(addr, PrivateToken).ok_or_else(|| std::io::ErrorKind::Other.into()) } - pub async fn send(&mut self, buf: &[u8]) -> std::io::Result> { + pub async fn send( + &mut self, + buf: &[u8], + ) -> std::io::Result<(Option, FullTimestampData)> { self.socket .async_io(Interest::WRITABLE, |socket| socket.send(buf)) .await?; @@ -285,11 +307,15 @@ impl Socket { unreachable!("Should not be able to create send timestamping sockets on platforms other than linux") } } else { - Ok(None) + Ok((None, FullTimestampData::default())) } } - pub async fn send_from(&mut self, buf: &[u8], from: A) -> std::io::Result> { + pub async fn send_from( + &mut self, + buf: &[u8], + from: A, + ) -> std::io::Result<(Option, FullTimestampData)> { let from = from.to_sockaddr(PrivateToken); self.socket .async_io(Interest::WRITABLE, |socket| socket.send_from(buf, from)) @@ -311,7 +337,7 @@ impl Socket { unreachable!("Should not be able to create send timestamping sockets on platforms other than linux") } } else { - Ok(None) + Ok((None, FullTimestampData::default())) } } } diff --git a/src/socket/linux.rs b/src/socket/linux.rs index a4c1c73..4cb4490 100644 --- a/src/socket/linux.rs +++ b/src/socket/linux.rs @@ -10,7 +10,7 @@ use crate::{ interface::{lookup_phc, InterfaceName}, networkaddress::{sealed::PrivateToken, EthernetAddress, MacAddress, NetworkAddress}, raw_socket::RawSocket, - socket::select_timestamp, + socket::{select_timestamp, FullTimestampData}, }; use super::{InterfaceTimestampMode, Open, Socket, Timestamp}; @@ -21,7 +21,7 @@ impl Socket { pub(super) async fn fetch_send_timestamp( &self, expected_counter: u32, - ) -> std::io::Result> { + ) -> std::io::Result<(Option, FullTimestampData)> { use std::time::Duration; const TIMEOUT: Duration = Duration::from_millis(200); @@ -29,20 +29,20 @@ impl Socket { match tokio::time::timeout(TIMEOUT, self.fetch_send_timestamp_loop(expected_counter)).await { Ok(res_opt_timestamp) => res_opt_timestamp, - Err(_timeout_elapsed) => Ok(None), + Err(_timeout_elapsed) => Ok((None, FullTimestampData::default())), } } pub(super) async fn fetch_send_timestamp_loop( &self, expected_counter: u32, - ) -> std::io::Result> { + ) -> std::io::Result<(Option, FullTimestampData)> { let try_read = |_: &RawSocket| self.fetch_send_timestamp_try_read(expected_counter); loop { // the timestamp being available triggers the error interest match self.socket.async_io(Interest::ERROR, try_read).await? { - Some(timestamp) => break Ok(Some(timestamp)), + Some((timestamp, timestamp_data)) => break Ok((Some(timestamp), timestamp_data)), None => continue, } } @@ -51,7 +51,7 @@ impl Socket { pub(super) fn fetch_send_timestamp_try_read( &self, expected_counter: u32, - ) -> std::io::Result> { + ) -> std::io::Result> { let mut control_buf = [0; EXPECTED_MAX_CMSG_SIZE]; // NOTE: this read could block! @@ -65,7 +65,8 @@ impl Socket { for msg in control_messages { match msg { ControlMessage::Timestamping { software, hardware } => { - send_ts = select_timestamp(self.timestamp_mode, software, hardware); + send_ts = select_timestamp(self.timestamp_mode, software, hardware) + .map(|v| (v, FullTimestampData { software, hardware })); } ControlMessage::ReceiveError(error) => { @@ -124,6 +125,7 @@ pub(super) fn configure_timestamping( let options = match mode { InterfaceTimestampMode::HardwareAll | InterfaceTimestampMode::HardwarePTPAll => { libc::SOF_TIMESTAMPING_RAW_HARDWARE + | libc::SOF_TIMESTAMPING_RX_SOFTWARE | libc::SOF_TIMESTAMPING_TX_SOFTWARE | libc::SOF_TIMESTAMPING_RX_HARDWARE | libc::SOF_TIMESTAMPING_TX_HARDWARE @@ -135,6 +137,7 @@ pub(super) fn configure_timestamping( } InterfaceTimestampMode::HardwareRecv | InterfaceTimestampMode::HardwarePTPRecv => { libc::SOF_TIMESTAMPING_RAW_HARDWARE + | libc::SOF_TIMESTAMPING_RX_SOFTWARE | libc::SOF_TIMESTAMPING_RX_HARDWARE | bind_phc .map(|_| SOF_TIMESTAMPING_BIND_PHC) @@ -460,7 +463,7 @@ mod tests { .unwrap(); let before = SystemTime::now(); - let send_ts = b.send(&[1, 2, 3]).await.unwrap().unwrap(); + let send_ts = b.send(&[1, 2, 3]).await.unwrap().0.unwrap(); let after = SystemTime::now(); let mut buf = [0; 4];