mirror of
https://gitee.com/openharmony/third_party_rust_nix
synced 2025-03-01 13:05:42 +00:00
Merge #1547
1547: feat: Add glibc::SOF_TIMESTAMPING_* support r=asomers a=pacak Support for kernel and hardware receive timestamps Co-authored-by: Michael Baikov <manpacket@gmail.com>
This commit is contained in:
commit
a392647f45
@ -19,6 +19,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
(#[1581](https://github.com/nix-rust/nix/pull/1581))
|
||||
- Added `sched_setaffinity` and `sched_getaffinity` on DragonFly.
|
||||
(#[1537](https://github.com/nix-rust/nix/pull/1537))
|
||||
- Added the `SO_TIMESTAMPING` support
|
||||
(#[1547](https://github.com/nix-rust/nix/pull/1547))
|
||||
|
||||
### Changed
|
||||
### Fixed
|
||||
|
@ -198,6 +198,28 @@ pub enum SockProtocol {
|
||||
NetlinkCrypto = libc::NETLINK_CRYPTO,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
libc_bitflags! {
|
||||
/// Configuration flags for `SO_TIMESTAMPING` interface
|
||||
///
|
||||
/// For use with [`Timestamping`][sockopt::Timestamping].
|
||||
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
|
||||
pub struct TimestampingFlag: c_uint {
|
||||
/// Report any software timestamps when available.
|
||||
SOF_TIMESTAMPING_SOFTWARE;
|
||||
/// Report hardware timestamps as generated by SOF_TIMESTAMPING_TX_HARDWARE when available.
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
/// Collect transmiting timestamps as reported by hardware
|
||||
SOF_TIMESTAMPING_TX_HARDWARE;
|
||||
/// Collect transmiting timestamps as reported by software
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE;
|
||||
/// Collect receiving timestamps as reported by hardware
|
||||
SOF_TIMESTAMPING_RX_HARDWARE;
|
||||
/// Collect receiving timestamps as reported by software
|
||||
SOF_TIMESTAMPING_RX_SOFTWARE;
|
||||
}
|
||||
}
|
||||
|
||||
libc_bitflags!{
|
||||
/// Additional socket options
|
||||
pub struct SockFlag: c_int {
|
||||
@ -641,6 +663,11 @@ pub enum ControlMessageOwned {
|
||||
/// # }
|
||||
/// ```
|
||||
ScmTimestamp(TimeVal),
|
||||
/// A set of nanosecond resolution timestamps
|
||||
///
|
||||
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
|
||||
#[cfg(all(target_os = "linux"))]
|
||||
ScmTimestampsns(Timestamps),
|
||||
/// Nanoseconds resolution timestamp
|
||||
///
|
||||
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
|
||||
@ -732,6 +759,18 @@ pub enum ControlMessageOwned {
|
||||
Unknown(UnknownCmsg),
|
||||
}
|
||||
|
||||
/// For representing packet timestamps via `SO_TIMESTAMPING` interface
|
||||
#[cfg(all(target_os = "linux"))]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Timestamps {
|
||||
/// software based timestamp, usually one containing data
|
||||
pub system: TimeSpec,
|
||||
/// legacy timestamp, usually empty
|
||||
pub hw_trans: TimeSpec,
|
||||
/// hardware based timestamp
|
||||
pub hw_raw: TimeSpec,
|
||||
}
|
||||
|
||||
impl ControlMessageOwned {
|
||||
/// Decodes a `ControlMessageOwned` from raw bytes.
|
||||
///
|
||||
@ -776,6 +815,18 @@ impl ControlMessageOwned {
|
||||
let ts: libc::timespec = ptr::read_unaligned(p as *const _);
|
||||
ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
|
||||
}
|
||||
#[cfg(all(target_os = "linux"))]
|
||||
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
|
||||
let tp = p as *const libc::timespec;
|
||||
let ts: libc::timespec = ptr::read_unaligned(tp);
|
||||
let system = TimeSpec::from(ts);
|
||||
let ts: libc::timespec = ptr::read_unaligned(tp.add(1));
|
||||
let hw_trans = TimeSpec::from(ts);
|
||||
let ts: libc::timespec = ptr::read_unaligned(tp.add(2));
|
||||
let hw_raw = TimeSpec::from(ts);
|
||||
let timestamping = Timestamps { system, hw_trans, hw_raw };
|
||||
ControlMessageOwned::ScmTimestampsns(timestamping)
|
||||
}
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
|
@ -16,7 +16,7 @@ use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
// Constants
|
||||
// TCP_CA_NAME_MAX isn't defined in user space include files
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
#[cfg(feature = "net")]
|
||||
const TCP_CA_NAME_MAX: usize = 16;
|
||||
|
||||
@ -465,7 +465,12 @@ sockopt_impl!(
|
||||
#[allow(missing_docs)]
|
||||
// Not documented by Linux!
|
||||
Ip6tOriginalDst, GetOnly, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6);
|
||||
sockopt_impl!(
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
sockopt_impl!(
|
||||
/// Specifies exact type of timestamping information collected by the kernel
|
||||
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
|
||||
Timestamping, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMPING, super::TimestampingFlag);
|
||||
sockopt_impl!(
|
||||
/// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
|
||||
ReceiveTimestamp, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
|
||||
#[cfg(all(target_os = "linux"))]
|
||||
@ -502,7 +507,7 @@ sockopt_impl!(
|
||||
/// Enable or disable the receiving of the `SCM_CREDENTIALS` control
|
||||
/// message.
|
||||
PassCred, Both, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
|
@ -57,6 +57,64 @@ pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
|
||||
assert_eq!(from_storage, sockaddr);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
#[test]
|
||||
pub fn test_timestamping() {
|
||||
use nix::sys::socket::{
|
||||
recvmsg, sendmsg, setsockopt, socket, sockopt::Timestamping, ControlMessageOwned, MsgFlags,
|
||||
SockFlag, SockType, TimestampingFlag,
|
||||
};
|
||||
use nix::sys::uio::IoVec;
|
||||
|
||||
let std_sa = SocketAddr::from_str("127.0.0.1:6790").unwrap();
|
||||
let inet_addr = InetAddr::from_std(&std_sa);
|
||||
let sock_addr = SockAddr::new_inet(inet_addr);
|
||||
|
||||
let ssock = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.expect("send socket failed");
|
||||
|
||||
let rsock = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
nix::sys::socket::bind(rsock, &sock_addr).unwrap();
|
||||
|
||||
setsockopt(rsock, Timestamping, &TimestampingFlag::all()).unwrap();
|
||||
|
||||
let sbuf = [0u8; 2048];
|
||||
let mut rbuf = [0u8; 2048];
|
||||
let flags = MsgFlags::empty();
|
||||
let iov1 = [IoVec::from_slice(&sbuf)];
|
||||
let iov2 = [IoVec::from_mut_slice(&mut rbuf)];
|
||||
let mut cmsg = cmsg_space!(nix::sys::socket::Timestamps);
|
||||
sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
|
||||
let recv = recvmsg(rsock, &iov2, Some(&mut cmsg), flags).unwrap();
|
||||
|
||||
let mut ts = None;
|
||||
for c in recv.cmsgs() {
|
||||
if let ControlMessageOwned::ScmTimestampsns(timestamps) = c {
|
||||
ts = Some(timestamps.system);
|
||||
}
|
||||
}
|
||||
let ts = ts.expect("ScmTimestampns is present");
|
||||
let sys_time = ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_REALTIME).unwrap();
|
||||
let diff = if ts > sys_time {
|
||||
ts - sys_time
|
||||
} else {
|
||||
sys_time - ts
|
||||
};
|
||||
assert!(std::time::Duration::from(diff).as_secs() < 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inetv6_addr_to_sock_addr() {
|
||||
let port: u16 = 3000;
|
||||
|
Loading…
x
Reference in New Issue
Block a user