Skip to content

Is there a way to understand that Linux system will not provide any TX timestamp?

I am exercising Linux timestamping functionality (TX part):

It looks like there is no easy way to understand that the system will never provide me with TX timestamps at runtime. It means that I can enable TX timestamping via setsockopt without an error:

int rc = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(val));
assert(rc == 0);

even on a system which does not support TX timestamps at all.

And then I can recheck that these options are applied:

int val = 0;
socklen_t len = sizeof(val);
int rc = getsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &val, &len);
assert(rc == 0);

But the real behavior is that no messages are generated for MSG_ERRQUEUE (TX timestamps are reported via this mechanism).

I know that the only way to understand if a system is capable of particular kind of timestamping is to execute sudo ethtool -T IFNAME.

For example, for one of my system the result is:

Time stamping parameters for lo:
        software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)
        software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
PTP Hardware Clock: none
Hardware Transmit Timestamp Modes: none
Hardware Receive Filter Modes: none

But I cannot rely on ethtool in my code as it’s a separate utility which requires sudo priveleges.

Any idea how to learn that TX timestamps are not available?



You should be able to do this through the SIOCETHTOOL ioctl, using the ETHTOOL_GET_TS_INFO command, which does not require root privileges. The socket to run the ioctl on can be any kind of network socket.

There is also a netlink interface for this, but that’s more complex and I am not familiar with it.

The ethtool command line tool uses one of the above two options depending on what is available on your kernel, and AFAICT it does not require privileges (runs fine on my machine without sudo).

Here’s a working example:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <err.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <linux/net_tstamp.h>

int main(int argc, char **argv) {
    struct ethtool_ts_info info = { .cmd = ETHTOOL_GET_TS_INFO };
    struct ifreq ifr = { .ifr_data = (void *)&info };

    if (argc != 2) {
        fprintf(stderr, "Usage: %s INTERFACEn", argv[0] ? argv[0] : "tool");
        return 1;

    if (strlen(argv[1]) >= IF_NAMESIZE) {
        fputs("Interface name too long!n", stderr);
        return 1;

    strcpy(ifr.ifr_name, argv[1]);

    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
        err(1, "socket");

    if (ioctl(fd, SIOCETHTOOL, &ifr) != 0)
        err(1, "ioctl");

    uint32_t ts = info.so_timestamping;

        printf("Hardware TX timestamping available on %s.n", ifr.ifr_name);
        printf("Software TX timestamping available on %s.n", ifr.ifr_name);

    return 0;

Output on my machine:

$ ./tool enp4s0
Hardware TX timestamping available on enp4s0.
Software TX timestamping available on enp4s0.
User contributions licensed under: CC BY-SA
10 People found this is helpful