feat(client): capture kernel transmit timestamps
On Linux, best-effort upgrade the socket's SO_TIMESTAMPING flags to TX_SOFTWARE | OPT_ID | OPT_TSONLY after a successful Open and before the first Echo probe. Promote the #103 error-queue foundation to production: MSG_ERRQUEUE is drained opportunistically with a fixed per-call budget at several natural choke points (after a probe send, before processing a reply, before evaluating timeouts), and each automatic OPT_ID timestamp is correlated directly with wire_seq — safe because Linux rolls back its speculative sk_tskey increment on every send failure, wire_seq and the kernel counter start together at every Open, and a socket can never be reopened for a second session. The observed kernel TX wall timestamp is retained on PendingProbe (surviving pending -> timed-out retention) as dormant metadata only; RTT, OWD, and IPDV are unchanged and continue to use the userspace send timestamp exclusively. Capability failure is fully non-fatal and RX timestamping is unaffected either way. Non-Linux and non-ancillary builds are unchanged.
This commit is contained in:
10 files changed
+948
-69
No files matched your search
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
io,
|
||||
net::{SocketAddr, UdpSocket},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
use crate::{metadata::ReceiveMeta, timing::ClientTimestamp};
|
||||
@@ -77,6 +78,40 @@ pub(crate) fn configure_receive_metadata(socket: &UdpSocket, remote: SocketAddr)
|
||||
linux::configure_receive_metadata(socket, remote)
|
||||
}
|
||||
|
||||
/// Best-effort upgrade a socket from RX-only to RX+TX kernel software
|
||||
/// timestamping. Returns whether the upgrade succeeded; a caller should
|
||||
/// track this to skip later drains entirely rather than perform harmless
|
||||
/// no-op ones. Always returns `false` off Linux or without the `ancillary`
|
||||
/// feature, so callers never need their own platform `cfg`.
|
||||
#[cfg(not(all(target_os = "linux", feature = "ancillary")))]
|
||||
pub(crate) fn try_enable_tx_timestamping<S>(_socket: &S) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "ancillary"))]
|
||||
pub(crate) fn try_enable_tx_timestamping<S: std::os::fd::AsFd>(socket: &S) -> bool {
|
||||
linux::try_enable_tx_timestamping(socket)
|
||||
}
|
||||
|
||||
/// Bounded, nonblocking drain of `socket`'s `MSG_ERRQUEUE`, reporting each
|
||||
/// usable TX timestamp completion to `on_timestamp`. Always a no-op off
|
||||
/// Linux or without the `ancillary` feature.
|
||||
#[cfg(not(all(target_os = "linux", feature = "ancillary")))]
|
||||
pub(crate) fn drain_tx_timestamps<S>(
|
||||
_socket: &S,
|
||||
_on_timestamp: impl FnMut(u32, SystemTime),
|
||||
) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "ancillary"))]
|
||||
pub(crate) fn drain_tx_timestamps<S: std::os::fd::AsRawFd>(
|
||||
socket: &S,
|
||||
on_timestamp: impl FnMut(u32, SystemTime),
|
||||
) -> io::Result<()> {
|
||||
linux::drain_tx_timestamps(socket, on_timestamp)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::net::UdpSocket;
|
||||
|
||||
Reference in new issue
Block a user