Skip to content

Commit b9eb197

Browse files
bors[bot]ghedo
andauthored
Merge #1564
1564: Add support for the SO_TXTIME sockopt and SCM_TXTIME control message r=asomers a=ghedo Co-authored-by: Alessandro Ghedini <[email protected]>
2 parents c77a872 + a982985 commit b9eb197

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
2525
(#[1547](https://github.com/nix-rust/nix/pull/1547))
2626
- Added getter methods to `MqAttr` struct
2727
(#[1619](https://github.com/nix-rust/nix/pull/1619))
28+
- Added the `TxTime` sockopt and control message.
29+
(#[1564](https://github.com/nix-rust/nix/pull/1564))
2830

2931
### Changed
3032
### Fixed

src/sys/socket/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,14 @@ pub enum ControlMessage<'a> {
10561056
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
10571057
#[cfg_attr(docsrs, doc(cfg(all())))]
10581058
RxqOvfl(&'a u32),
1059+
1060+
/// Configure the transmission time of packets.
1061+
///
1062+
/// For further information, please refer to the
1063+
/// [`tc-etf(8)`](https://man7.org/linux/man-pages/man8/tc-etf.8.html) man
1064+
/// page.
1065+
#[cfg(target_os = "linux")]
1066+
TxTime(&'a u64),
10591067
}
10601068

10611069
// An opaque structure used to prevent cmsghdr from being a public type
@@ -1153,6 +1161,10 @@ impl<'a> ControlMessage<'a> {
11531161
ControlMessage::RxqOvfl(drop_count) => {
11541162
drop_count as *const _ as *const u8
11551163
},
1164+
#[cfg(target_os = "linux")]
1165+
ControlMessage::TxTime(tx_time) => {
1166+
tx_time as *const _ as *const u8
1167+
},
11561168
};
11571169
unsafe {
11581170
ptr::copy_nonoverlapping(
@@ -1208,6 +1220,10 @@ impl<'a> ControlMessage<'a> {
12081220
ControlMessage::RxqOvfl(drop_count) => {
12091221
mem::size_of_val(drop_count)
12101222
},
1223+
#[cfg(target_os = "linux")]
1224+
ControlMessage::TxTime(tx_time) => {
1225+
mem::size_of_val(tx_time)
1226+
},
12111227
}
12121228
}
12131229

@@ -1237,6 +1253,8 @@ impl<'a> ControlMessage<'a> {
12371253
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
12381254
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
12391255
ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
1256+
#[cfg(target_os = "linux")]
1257+
ControlMessage::TxTime(_) => libc::SOL_SOCKET,
12401258
}
12411259
}
12421260

@@ -1279,6 +1297,10 @@ impl<'a> ControlMessage<'a> {
12791297
ControlMessage::RxqOvfl(_) => {
12801298
libc::SO_RXQ_OVFL
12811299
},
1300+
#[cfg(target_os = "linux")]
1301+
ControlMessage::TxTime(_) => {
1302+
libc::SCM_TXTIME
1303+
},
12821304
}
12831305
}
12841306

src/sys/socket/sockopt.rs

+5
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,11 @@ sockopt_impl!(
582582
#[allow(missing_docs)]
583583
// Not documented by Linux!
584584
UdpGroSegment, Both, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
585+
#[cfg(target_os = "linux")]
586+
sockopt_impl!(
587+
/// Configures the behavior of time-based transmission of packets, for use
588+
/// with the `TxTime` control message.
589+
TxTime, Both, libc::SOL_SOCKET, libc::SO_TXTIME, libc::sock_txtime);
585590
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
586591
sockopt_impl!(
587592
/// Indicates that an unsigned 32-bit value ancillary message (cmsg) should

test/sys/test_socket.rs

+57
Original file line numberDiff line numberDiff line change
@@ -1997,3 +1997,60 @@ mod linux_errqueue {
19971997
assert_eq!(ext_err.ee_info, 0);
19981998
}
19991999
}
2000+
2001+
// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
2002+
// of QEMU support is suspected.
2003+
#[cfg_attr(qemu, ignore)]
2004+
#[cfg(target_os = "linux")]
2005+
#[test]
2006+
pub fn test_txtime() {
2007+
use nix::sys::socket::{
2008+
bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
2009+
MsgFlags, SockFlag, SockType,
2010+
};
2011+
use nix::sys::time::TimeValLike;
2012+
use nix::time::{ClockId, clock_gettime};
2013+
2014+
require_kernel_version!(test_txtime, ">= 5.8");
2015+
2016+
let std_sa = SocketAddr::from_str("127.0.0.1:6790").unwrap();
2017+
let inet_addr = InetAddr::from_std(&std_sa);
2018+
let sock_addr = SockAddr::new_inet(inet_addr);
2019+
2020+
let ssock = socket(
2021+
AddressFamily::Inet,
2022+
SockType::Datagram,
2023+
SockFlag::empty(),
2024+
None,
2025+
)
2026+
.expect("send socket failed");
2027+
2028+
let txtime_cfg = libc::sock_txtime {
2029+
clockid: libc::CLOCK_MONOTONIC,
2030+
flags: 0,
2031+
};
2032+
setsockopt(ssock, sockopt::TxTime, &txtime_cfg).unwrap();
2033+
2034+
let rsock = socket(
2035+
AddressFamily::Inet,
2036+
SockType::Datagram,
2037+
SockFlag::empty(),
2038+
None,
2039+
)
2040+
.unwrap();
2041+
bind(rsock, &sock_addr).unwrap();
2042+
2043+
let sbuf = [0u8; 2048];
2044+
let iov1 = [nix::sys::uio::IoVec::from_slice(&sbuf)];
2045+
2046+
let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
2047+
let delay = std::time::Duration::from_secs(1).into();
2048+
let txtime = (now + delay).num_nanoseconds() as u64;
2049+
2050+
let cmsg = ControlMessage::TxTime(&txtime);
2051+
sendmsg(ssock, &iov1, &[cmsg], MsgFlags::empty(), Some(&sock_addr)).unwrap();
2052+
2053+
let mut rbuf = [0u8; 2048];
2054+
let iov2 = [nix::sys::uio::IoVec::from_mut_slice(&mut rbuf)];
2055+
recvmsg(rsock, &iov2, None, MsgFlags::empty()).unwrap();
2056+
}

0 commit comments

Comments
 (0)