Tracked Time Packages

I am trying to get accurate timestamps for outgoing packets (sent using raw sockets). According to Linux/Documentation/networking/timestamping.txt , "For send time stamps, the outgoing packet is looped back into the socket error queue with the send time stamp attached. It can be obtained using recvmsg (flags = MSG_ERRQUEUE).".

Unfortunately, recvmsg always returns -1 when called on a raw socket (created using socket(PF_INET, SOCK_RAW, IPPROTO_RAW) and with SO_TIMESTAMP set to 1 with setsockopt ). What am I doing wrong? Is there a better way to get an accurate timestamp for an outgoing packet?

Addendum (information):

I also tried to get the timestamp from a packet sent via a UDP socket (source code below), and recvmsg returns -1 : "Resource temporarily unavailable" ( EAGAIN ) EAGAIN .

Addendum (source code):

 #include <arpa/inet.h> #include <linux/net_tstamp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> void die(char* s) { perror(s); exit(1); } int main(int argc, char* argv[]) { char* destination_ip = "10.0.0.1"; int destination_port = 1234; int sock; if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { die("socket()"); } int timestamp_flags = SOF_TIMESTAMPING_TX_SOFTWARE; if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &timestamp_flags, sizeof(timestamp_flags)) < 0) { die("setsockopt()"); } struct sockaddr_in si_server; memset(&si_server, 0, sizeof(si_server)); si_server.sin_family = AF_INET; si_server.sin_port = htons(destination_port); if (inet_aton(destination_ip, &si_server.sin_addr) == 0) { die("inet_aton()"); } const int buffer_len = 256; char buffer[buffer_len]; const int n_packets = 10; for (int i = 0; i < n_packets; ++i) { sprintf(buffer, "Packet %d", i); if (sendto(sock, buffer, buffer_len, 0, (const sockaddr*) &si_server, sizeof(si_server)) < 0) { die("sendto()"); } // Obtain the sent packet timestamp. char data[256]; struct msghdr msg; struct iovec entry; struct sockaddr_in from_addr; struct { struct cmsghdr cm; char control[512]; } control; int res; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &entry; msg.msg_iovlen = 1; entry.iov_base = data; entry.iov_len = sizeof(data); msg.msg_name = (caddr_t)&from_addr; msg.msg_namelen = sizeof(from_addr); msg.msg_control = &control; msg.msg_controllen = sizeof(control); if (recvmsg(sock, &msg, MSG_ERRQUEUE) < 0) { die("recvmsg()"); } } return 0; } 
+8
c linux timestamp raw-sockets
source share
4 answers

Having looked at the source code of the Linux kernel, I found that the function responsible for placing the message containing the packet's timestamp in the error queue is skb_tx_timestamp . This function must be called by the NIC driver, and, unfortunately, the e1000 driver e1000 not call it (there is a similar function for the hardware timestamp, but this obviously depends on the NIC driver that supports it).

According to this NetDev discussion from last September: "no driver calls skb_tx_timestamp ()" and "you need to configure your NIC driver to play using this TX timestamp." After adding the skb_tx_timestamp call to e1000_xmit_frame on e1000_main.c I managed to get timestamps for outgoing packets (via a UDP socket). I was not able to get timestamps for outgoing packets in RAW juice, though (I still get EAGAIN ).

+8
source share

It's hard to understand what you are doing wrong, because we cannot see your code.

However: The documentation states that SO_TIMESTAMP is for inbound packets, and SO_TIMESTAMPING is for outbound packets.

The kernel documentation contains a complete example that you can use as a base - although it uses UDP, you should be able to configure it to use a RAW socket. See Linux kernel Documentation / networking / timestamping / timestamping.c

EDIT: It seems that the transmission timestamp is not universally supported, see for example here . Even today, only a few of the best drivers implement software support, and some of them have hardware support.

+5
source share

sock_tx_timestamp is called only for SOCK_DGRAM sockets in the current kernel code.

By the way, the document Documentation / networking / timestamping / timestamping.c is not very accurate.

SO_TIMESTAMP / SO_TIMESTAMPNS / SO_TIMESTAMPING / SIOCGSTAMP / SIOCGSTAMPNS are similar. Any of these will allow the application to get the timestamp of the received packet.

With SOF_TIMESTAMPING_TX_SOFTWARE, any of the above flags will also provide the CMSG application in MSG_ERRQUEUE, indicating the timestamp of the packet sent.

But SOF_TIMESTAMPING_RX_SOFTWARE is useless at all. It cannot even be used to disable the timestamp report of received packets.

+2
source share

I think you should mention the timestamping flag as

 int timestamp_flags |= SOF_TIMESTAMPING_TX_SOFTWARE; timestamp_flags |= SOF_TIMESTAMPING_SOFTWARE; 

And also you should check strerror for all system calls before getting data from msg error message. This will help you get rid of the EAGAIN message.

0
source share

All Articles