summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/sys/socket/mod.rs22
-rw-r--r--src/sys/socket/sockopt.rs5
-rw-r--r--test/sys/test_socket.rs57
4 files changed, 86 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23c5c088..4c4516ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1547](https://github.com/nix-rust/nix/pull/1547))
- Added getter methods to `MqAttr` struct
(#[1619](https://github.com/nix-rust/nix/pull/1619))
+- Added the `TxTime` sockopt and control message.
+ (#[1564](https://github.com/nix-rust/nix/pull/1564))
### Changed
### Fixed
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 9df5ed4a..f6d37c99 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -1056,6 +1056,14 @@ pub enum ControlMessage<'a> {
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RxqOvfl(&'a u32),
+
+ /// Configure the transmission time of packets.
+ ///
+ /// For further information, please refer to the
+ /// [`tc-etf(8)`](https://man7.org/linux/man-pages/man8/tc-etf.8.html) man
+ /// page.
+ #[cfg(target_os = "linux")]
+ TxTime(&'a u64),
}
// An opaque structure used to prevent cmsghdr from being a public type
@@ -1153,6 +1161,10 @@ impl<'a> ControlMessage<'a> {
ControlMessage::RxqOvfl(drop_count) => {
drop_count as *const _ as *const u8
},
+ #[cfg(target_os = "linux")]
+ ControlMessage::TxTime(tx_time) => {
+ tx_time as *const _ as *const u8
+ },
};
unsafe {
ptr::copy_nonoverlapping(
@@ -1208,6 +1220,10 @@ impl<'a> ControlMessage<'a> {
ControlMessage::RxqOvfl(drop_count) => {
mem::size_of_val(drop_count)
},
+ #[cfg(target_os = "linux")]
+ ControlMessage::TxTime(tx_time) => {
+ mem::size_of_val(tx_time)
+ },
}
}
@@ -1237,6 +1253,8 @@ impl<'a> ControlMessage<'a> {
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
+ #[cfg(target_os = "linux")]
+ ControlMessage::TxTime(_) => libc::SOL_SOCKET,
}
}
@@ -1279,6 +1297,10 @@ impl<'a> ControlMessage<'a> {
ControlMessage::RxqOvfl(_) => {
libc::SO_RXQ_OVFL
},
+ #[cfg(target_os = "linux")]
+ ControlMessage::TxTime(_) => {
+ libc::SCM_TXTIME
+ },
}
}
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 056ded42..c600391c 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -582,6 +582,11 @@ sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
UdpGroSegment, Both, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
+#[cfg(target_os = "linux")]
+sockopt_impl!(
+ /// Configures the behavior of time-based transmission of packets, for use
+ /// with the `TxTime` control message.
+ TxTime, Both, libc::SOL_SOCKET, libc::SO_TXTIME, libc::sock_txtime);
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
sockopt_impl!(
/// Indicates that an unsigned 32-bit value ancillary message (cmsg) should
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 7a861abf..5262d3b8 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -1997,3 +1997,60 @@ mod linux_errqueue {
assert_eq!(ext_err.ee_info, 0);
}
}
+
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
+#[cfg(target_os = "linux")]
+#[test]
+pub fn test_txtime() {
+ use nix::sys::socket::{
+ bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
+ MsgFlags, SockFlag, SockType,
+ };
+ use nix::sys::time::TimeValLike;
+ use nix::time::{ClockId, clock_gettime};
+
+ require_kernel_version!(test_txtime, ">= 5.8");
+
+ 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 txtime_cfg = libc::sock_txtime {
+ clockid: libc::CLOCK_MONOTONIC,
+ flags: 0,
+ };
+ setsockopt(ssock, sockopt::TxTime, &txtime_cfg).unwrap();
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ bind(rsock, &sock_addr).unwrap();
+
+ let sbuf = [0u8; 2048];
+ let iov1 = [nix::sys::uio::IoVec::from_slice(&sbuf)];
+
+ let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
+ let delay = std::time::Duration::from_secs(1).into();
+ let txtime = (now + delay).num_nanoseconds() as u64;
+
+ let cmsg = ControlMessage::TxTime(&txtime);
+ sendmsg(ssock, &iov1, &[cmsg], MsgFlags::empty(), Some(&sock_addr)).unwrap();
+
+ let mut rbuf = [0u8; 2048];
+ let iov2 = [nix::sys::uio::IoVec::from_mut_slice(&mut rbuf)];
+ recvmsg(rsock, &iov2, None, MsgFlags::empty()).unwrap();
+}