Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux kernel UDP reception timestamp

I've been reading the network timestamping documentation of linux kernel and there is something that it's not clear to me.

Where is the timestamp provided by SO_TIMESTAMPNS generated? In hardware or in the kernel? If so it is gerated as soon as an interrupt for a new packet is raised?

SO_TIMESTAMPING should also allow the generation of hardware timestamps. Is this supported by all the NICs? How does SO_TIMESTAMPING with options SOF_TIMESTAMPING_RX_HARDWARE and SO_TIMESTAMPNS? In that case is the hardware timestamp referring to the system clock or to the NIC clock? In the second case how to retrieve the NIC clock to compute elapsed time?

like image 942
Maverik Avatar asked Jan 23 '17 11:01

Maverik


People also ask

How to timestamp a packet in Linux?

Normally hardware that supports this functionality will see the socket option ( SO_TIMESTAMPNS or SO_TIMESTAMP) and then will stamp the packets. So, for example, if you have an appropriate solarflare card, then setting the options will cause the card to timestamp. Else it will be managed by the kernel.

When to request RX timestamps from the kernel?

Request rx timestamps when data enters the kernel. These timestamps are generated just after a device driver hands a packet to the kernel receive stack. Request tx timestamps generated by the network adapter. This flag can be enabled via both socket options and control messages. Request tx timestamps when data leaves the kernel.

What is the socket option for timestamping?

This socket option enables timestamping of datagrams on the reception path. Because the destination socket, if any, is not known early in the network stack, the feature has to be enabled for all packets. The same is true for all early receive timestamp options. For interface details, see man 7 socket.

What is the latency of kernel timestamps?

Kernel transmit latency is, if long, often dominated by queuing delay. The difference between this timestamp and one taken at SOF_TIMESTAMPING_TX_SOFTWARE will expose this latency independent of protocol processing.


Video Answer


1 Answers

The socket attribute used for software timestamping is, SO_TIMESTAMPNS. This socket attribute returns the time from the system clock. It is not generated in the hardware, rather it is the snapshot of the system time when the interrupt is handled in the software. We can access this timestamp through the ancillary data (CMSG) that is not part of the socket payload, using:

int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
    level = cm->cmsg_level;
    type  = cm->cmsg_type;
    if (SOL_SOCKET == level && SO_TIMESTAMPNS == type) {
        ts = (struct timespec *) CMSG_DATA(cm);
        printf("SW TIMESTAMP %ld.%09ld\n", (long)ts[0].tv_sec, (long)ts[0].tv_nsec);
    }
}

The SO_TIMESTAMPING socket option offers many different flags, some of them are,

SOF_TIMESTAMPING_TX_HARDWARE // Transmit timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_RX_HARDWARE // Receive  timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_TX_SOFTWARE // Transmit timestamp generated in kernel driver by NIC clock
SOF_TIMESTAMPING_RX_SOFTWARE // Receive  timestamp generated in kernel driver by NIC clock

This socket option is not supported by all Network Interface Cards (NICs). Currently many ethernet NICs support SO_TIMESTAMPING. In order to find if a particular interface driver supports SO_TIMESTAMPING, use:

ethtool -T ethX // where X corresponds to your particular interface

This will return all the socket attributes ethX supports for timestamping.

To use hardware timestamping feature provided by a particular NIC, use the code:

int flags;
flags   = SOF_TIMESTAMPING_TX_HARDWARE
            | SOF_TIMESTAMPING_RX_HARDWARE 
            | SOF_TIMESTAMPING_TX_SOFTWARE
            | SOF_TIMESTAMPING_RX_SOFTWARE 
            | SOF_TIMESTAMPING_RAW_HARDWARE;
    if (setsockopt(sd, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags)) < 0)
        printf("ERROR: setsockopt SO_TIMESTAMPING\n");

int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
     if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
        ts = (struct timespec *) CMSG_DATA(cm);
        printf("HW TIMESTAMP %ld.%09ld\n", (long)ts[2].tv_sec, (long)ts[2].tv_nsec);
      }
}
like image 56
Fatima Avatar answered Sep 28 '22 06:09

Fatima