@@ -1654,3 +1654,115 @@ fn test_recvmmsg_timestampns() {
1654
1654
// Close socket
1655
1655
nix:: unistd:: close ( in_socket) . unwrap ( ) ;
1656
1656
}
1657
+
1658
+ // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
1659
+ // support is suspected.
1660
+ #[ cfg_attr( not( any( target_arch = "x86_64" ) ) , ignore) ]
1661
+ #[ cfg( all( target_os = "linux" ) ) ]
1662
+ #[ test]
1663
+ fn test_recvmsg_timestamping ( ) {
1664
+ use nix:: sys:: socket:: * ;
1665
+ use nix:: sys:: uio:: IoVec ;
1666
+ use nix:: sys:: time:: * ;
1667
+ use std:: time:: * ;
1668
+
1669
+ // Set up
1670
+ let message = "Ohayō!" . as_bytes ( ) ;
1671
+ let in_socket = socket (
1672
+ AddressFamily :: Inet ,
1673
+ SockType :: Datagram ,
1674
+ SockFlag :: empty ( ) ,
1675
+ None ) . unwrap ( ) ;
1676
+ let flag: u32 = libc:: SOF_TIMESTAMPING_RX_SOFTWARE | libc:: SOF_TIMESTAMPING_SOFTWARE ;
1677
+ setsockopt ( in_socket, sockopt:: ReceiveTimestamping , & flag) . unwrap ( ) ;
1678
+ let localhost = InetAddr :: new ( IpAddr :: new_v4 ( 127 , 0 , 0 , 1 ) , 0 ) ;
1679
+ bind ( in_socket, & SockAddr :: new_inet ( localhost) ) . unwrap ( ) ;
1680
+ let address = getsockname ( in_socket) . unwrap ( ) ;
1681
+ // Get initial time
1682
+ let time0 = SystemTime :: now ( ) ;
1683
+ // Send the message
1684
+ let iov = [ IoVec :: from_slice ( message) ] ;
1685
+ let flags = MsgFlags :: empty ( ) ;
1686
+ let l = sendmsg ( in_socket, & iov, & [ ] , flags, Some ( & address) ) . unwrap ( ) ;
1687
+ assert_eq ! ( message. len( ) , l) ;
1688
+ // Receive the message
1689
+ let mut buffer = vec ! [ 0u8 ; message. len( ) ] ;
1690
+ let mut cmsgspace = nix:: cmsg_space!( [ TimeSpec ; 3 ] ) ;
1691
+ let iov = [ IoVec :: from_mut_slice ( & mut buffer) ] ;
1692
+ let r = recvmsg ( in_socket, & iov, Some ( & mut cmsgspace) , flags) . unwrap ( ) ;
1693
+ let times = match r. cmsgs ( ) . next ( ) {
1694
+ Some ( ControlMessageOwned :: ScmTimestamping ( times) ) => times,
1695
+ Some ( _) => panic ! ( "Unexpected control message" ) ,
1696
+ None => panic ! ( "No control message" )
1697
+ } ;
1698
+ // Check the final time
1699
+ let time1 = SystemTime :: now ( ) ;
1700
+ // the packet's received timestamp should lie in-between the two system
1701
+ // times, unless the system clock was adjusted in the meantime.
1702
+ let time = times[ 0 ] ;
1703
+ let rduration = Duration :: new ( time. tv_sec ( ) as u64 ,
1704
+ time. tv_nsec ( ) as u32 ) ;
1705
+ assert ! ( time0. duration_since( UNIX_EPOCH ) . unwrap( ) <= rduration) ;
1706
+ assert ! ( rduration <= time1. duration_since( UNIX_EPOCH ) . unwrap( ) ) ;
1707
+ // Close socket
1708
+ nix:: unistd:: close ( in_socket) . unwrap ( ) ;
1709
+ }
1710
+
1711
+ // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
1712
+ // support is suspected.
1713
+ #[ cfg_attr( not( any( target_arch = "x86_64" ) ) , ignore) ]
1714
+ #[ cfg( all( target_os = "linux" ) ) ]
1715
+ #[ test]
1716
+ fn test_recvmmsg_timestamping ( ) {
1717
+ use nix:: sys:: socket:: * ;
1718
+ use nix:: sys:: uio:: IoVec ;
1719
+ use nix:: sys:: time:: * ;
1720
+ use std:: time:: * ;
1721
+
1722
+ // Set up
1723
+ let message = "Ohayō!" . as_bytes ( ) ;
1724
+ let in_socket = socket (
1725
+ AddressFamily :: Inet ,
1726
+ SockType :: Datagram ,
1727
+ SockFlag :: empty ( ) ,
1728
+ None ) . unwrap ( ) ;
1729
+ let flag: u32 = libc:: SOF_TIMESTAMPING_RX_SOFTWARE | libc:: SOF_TIMESTAMPING_SOFTWARE ;
1730
+ setsockopt ( in_socket, sockopt:: ReceiveTimestamping , & flag) . unwrap ( ) ;
1731
+ let localhost = InetAddr :: new ( IpAddr :: new_v4 ( 127 , 0 , 0 , 1 ) , 0 ) ;
1732
+ bind ( in_socket, & SockAddr :: new_inet ( localhost) ) . unwrap ( ) ;
1733
+ let address = getsockname ( in_socket) . unwrap ( ) ;
1734
+ // Get initial time
1735
+ let time0 = SystemTime :: now ( ) ;
1736
+ // Send the message
1737
+ let iov = [ IoVec :: from_slice ( message) ] ;
1738
+ let flags = MsgFlags :: empty ( ) ;
1739
+ let l = sendmsg ( in_socket, & iov, & [ ] , flags, Some ( & address) ) . unwrap ( ) ;
1740
+ assert_eq ! ( message. len( ) , l) ;
1741
+ // Receive the message
1742
+ let mut buffer = vec ! [ 0u8 ; message. len( ) ] ;
1743
+ let mut cmsgspace = nix:: cmsg_space!( [ TimeSpec ; 3 ] ) ;
1744
+ let iov = [ IoVec :: from_mut_slice ( & mut buffer) ] ;
1745
+ let mut data = vec ! [
1746
+ RecvMmsgData {
1747
+ iov,
1748
+ cmsg_buffer: Some ( & mut cmsgspace) ,
1749
+ } ,
1750
+ ] ;
1751
+ let r = recvmmsg ( in_socket, & mut data, flags, None ) . unwrap ( ) ;
1752
+ let times = match r[ 0 ] . cmsgs ( ) . next ( ) {
1753
+ Some ( ControlMessageOwned :: ScmTimestamping ( times) ) => times,
1754
+ Some ( _) => panic ! ( "Unexpected control message" ) ,
1755
+ None => panic ! ( "No control message" )
1756
+ } ;
1757
+ // Check the final time
1758
+ let time1 = SystemTime :: now ( ) ;
1759
+ // the packet's received timestamp should lie in-between the two system
1760
+ // times, unless the system clock was adjusted in the meantime.
1761
+ let time = times[ 0 ] ;
1762
+ let rduration = Duration :: new ( time. tv_sec ( ) as u64 ,
1763
+ time. tv_nsec ( ) as u32 ) ;
1764
+ assert ! ( time0. duration_since( UNIX_EPOCH ) . unwrap( ) <= rduration) ;
1765
+ assert ! ( rduration <= time1. duration_since( UNIX_EPOCH ) . unwrap( ) ) ;
1766
+ // Close socket
1767
+ nix:: unistd:: close ( in_socket) . unwrap ( ) ;
1768
+ }
0 commit comments