summaryrefslogtreecommitdiff
path: root/test/sys/test_socket.rs
diff options
context:
space:
mode:
authorLu, Wangshan <wisagan@gmail.com>2021-03-20 22:36:36 +0800
committerLu, Wangshan <wisagan@gmail.com>2021-04-08 10:41:38 +0800
commit830bab64a8615642ea7de69952b5ae122a124285 (patch)
treeb4d07b07e0abb496bbbe94852b1ad02f0bb2f64e /test/sys/test_socket.rs
parent3f8a66dc69ba3ae4df6a0f3eb879dc30020965bc (diff)
downloadnix-830bab64a8615642ea7de69952b5ae122a124285.zip
Support TIMESTAMPNS for linux
Diffstat (limited to 'test/sys/test_socket.rs')
-rw-r--r--test/sys/test_socket.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 2b89a453..22ecece7 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -1535,3 +1535,111 @@ pub fn test_vsock() {
close(s1).unwrap();
thr.join().unwrap();
}
+
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
+// support is suspected.
+#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+#[cfg(all(target_os = "linux"))]
+#[test]
+fn test_recvmsg_timestampns() {
+ use nix::sys::socket::*;
+ use nix::sys::uio::IoVec;
+ use nix::sys::time::*;
+ use std::time::*;
+
+ // Set up
+ let message = "Ohayō!".as_bytes();
+ let in_socket = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None).unwrap();
+ setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
+ let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
+ bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
+ let address = getsockname(in_socket).unwrap();
+ // Get initial time
+ let time0 = SystemTime::now();
+ // Send the message
+ let iov = [IoVec::from_slice(message)];
+ let flags = MsgFlags::empty();
+ let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
+ assert_eq!(message.len(), l);
+ // Receive the message
+ let mut buffer = vec![0u8; message.len()];
+ let mut cmsgspace = nix::cmsg_space!(TimeSpec);
+ let iov = [IoVec::from_mut_slice(&mut buffer)];
+ let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
+ let rtime = match r.cmsgs().next() {
+ Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
+ Some(_) => panic!("Unexpected control message"),
+ None => panic!("No control message")
+ };
+ // Check the final time
+ let time1 = SystemTime::now();
+ // the packet's received timestamp should lie in-between the two system
+ // times, unless the system clock was adjusted in the meantime.
+ let rduration = Duration::new(rtime.tv_sec() as u64,
+ rtime.tv_nsec() as u32);
+ assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
+ assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
+ // Close socket
+ nix::unistd::close(in_socket).unwrap();
+}
+
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
+// support is suspected.
+#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+#[cfg(all(target_os = "linux"))]
+#[test]
+fn test_recvmmsg_timestampns() {
+ use nix::sys::socket::*;
+ use nix::sys::uio::IoVec;
+ use nix::sys::time::*;
+ use std::time::*;
+
+ // Set up
+ let message = "Ohayō!".as_bytes();
+ let in_socket = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None).unwrap();
+ setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
+ let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
+ bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
+ let address = getsockname(in_socket).unwrap();
+ // Get initial time
+ let time0 = SystemTime::now();
+ // Send the message
+ let iov = [IoVec::from_slice(message)];
+ let flags = MsgFlags::empty();
+ let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
+ assert_eq!(message.len(), l);
+ // Receive the message
+ let mut buffer = vec![0u8; message.len()];
+ let mut cmsgspace = nix::cmsg_space!(TimeSpec);
+ let iov = [IoVec::from_mut_slice(&mut buffer)];
+ let mut data = vec![
+ RecvMmsgData {
+ iov,
+ cmsg_buffer: Some(&mut cmsgspace),
+ },
+ ];
+ let r = recvmmsg(in_socket, &mut data, flags, None).unwrap();
+ let rtime = match r[0].cmsgs().next() {
+ Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
+ Some(_) => panic!("Unexpected control message"),
+ None => panic!("No control message")
+ };
+ // Check the final time
+ let time1 = SystemTime::now();
+ // the packet's received timestamp should lie in-between the two system
+ // times, unless the system clock was adjusted in the meantime.
+ let rduration = Duration::new(rtime.tv_sec() as u64,
+ rtime.tv_nsec() as u32);
+ assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
+ assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
+ // Close socket
+ nix::unistd::close(in_socket).unwrap();
+}