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?
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.
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.
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.
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.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With