The socket attribute used for the software timestamp is SO_TIMESTAMPNS. This socket attribute returns the time from the system clock. It is not generated in hardware; rather, it is a snapshot of the system time when an interrupt is processed in software. We can access this timestamp using ancillary data (CMSG) that are 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 socket parameter SO_TIMESTAMPING offers many different flags, some of them,
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 interfaces (NICs). Currently, many network adapters support SO_TIMESTAMPING. To find out if any driver supports the SO_TIMESTAMPING interface, use:
ethtool -T ethX
This will return all socket attributes. Support, thanks for the timestamping.
To use the timestamping hardware feature provided by a particular network adapter, 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); } }