You are not logged in.

#1 2023-03-23 12:32:16

jcul
Member
Registered: 2023-03-23
Posts: 5

SO_TIMESTAMPING / recvmsg return no timestamps

Hi,
I've recently switched back to arch linux.

I've come across an issue where requesting SO_TIMESTAMPING and doing recvmsg on a socket returns no timestamps.
The msghdr.msgcontrollen returned is 0, and CMSG_FIRSTHDR gives NULL.

I set the following options on the socket with SO_TIMESTAMPING:

    constexpr int value = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE |
                          SOF_TIMESTAMPING_SYS_HARDWARE | SOF_TIMESTAMPING_SOFTWARE;
    if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMPING_OLD, &value, sizeof(value)) < 0) {
       ...
    }

I have played around with the alignment and ensuring that the control buffer passed to recv_msg is initialized to zero.

However, it doesn't seem to make any difference.

This only seems to affect Arch linux.

I tested on these systems and it works fine:

* void linux, kernel 6.1.6_1
* centos7, kernel 5.4.210-1.el7.elrepo.x86_64
* fedora, 6.1.10-200.fc37.x86_64

I tested on a few different arch systems, all fail:

On arch, kernels: 6.2.7, 6.2.2-arch1-1, 6.1.21-1-lts, 6.1.7

The cmsg man page suggest something like the following to ensure alignment:

  union {         /* Ancillary data buffer, wrapped in a union
                     in order to ensure it is suitably aligned */
      char buf[CMSG_SPACE(1024)];
      struct cmsghdr align;
  } u;
  memset(u.buf, 0, sizeof(u.buf));

But it doesn't seem to make a difference.

This can be reproduced using the open onload rxtimestamping example:

curl -O https://raw.githubusercontent.com/majek/openonload/master/src/tests/onload/hwtimestamping/rx_timestamping.c
gcc rx_timestamping.c
./rx_timestamping

In another terminal:

socat - udp-sendto:127.0.0.1:9000

Output on arch:

Socket created, listening on port 9000
Selecting hardware timestamping mode.
Packet 1 - 5 bytes    no timestamp
Packet 2 - 5 bytes    no timestamp

On void:

$ ./rx_timestamping
Socket created, listening on port 9000
Selecting hardware timestamping mode.
Packet 1 - 5 bytes    timestamps 1679568125.035873270 0.000000000 0.000000000
Packet 2 - 5 bytes    timestamps 1679568129.227190604 0.000000000 0.000000000

Offline

#2 2023-03-23 14:05:10

3beb6e7c46a615a
Member
Registered: 2021-03-27
Posts: 165

Re: SO_TIMESTAMPING / recvmsg return no timestamps

Works for me:

$ gcc -o rx_timestamping rx_timestamping.c
$ ./rx_timestamping &
Socket created, listening on port 9000
Selecting hardware timestamping mode.
$ socat - udp-sendto:127.0.0.1:9000
a
Packet 1 - 2 bytes      timestamps 1679580257.536676109 0.000000000 0.000000000
b
Packet 2 - 2 bytes      timestamps 1679580258.351448003 0.000000000 0.000000000
c
Packet 3 - 2 bytes      timestamps 1679580258.751282000 0.000000000 0.000000000
^C⏎                                                                                                                                                                                                                                                           
$ fg
Send job 1 (./rx_timestamping &) to foreground
^C⏎                                                                                                                                                                                                                                                           
$ uname -r
6.2.7-zen1-1-zen

Last edited by 3beb6e7c46a615a (2023-03-23 14:05:32)

Offline

#3 2023-03-24 10:27:42

jcul
Member
Registered: 2023-03-23
Posts: 5

Re: SO_TIMESTAMPING / recvmsg return no timestamps

Thanks!
I'll try switching to the zen kernel and see if it makes a difference.

Offline

#4 2023-03-26 22:12:40

jcul
Member
Registered: 2023-03-23
Posts: 5

Re: SO_TIMESTAMPING / recvmsg return no timestamps

Interesting, I get no timestamps on 6.2.8-zen.
Perhaps it is not a kernel thing...

$ ./rx_timestamping
Socket created, listening on port 9000
Selecting hardware timestamping mode.
Packet 1 - 5 bytes	no timestamp
Packet 2 - 4 bytes	no timestamp

$ uname -r
6.2.8-zen1-1-zen

Last edited by jcul (2023-03-26 22:13:13)

Offline

#5 2023-03-29 12:18:45

jcul
Member
Registered: 2023-03-23
Posts: 5

Re: SO_TIMESTAMPING / recvmsg return no timestamps

OK I downloaded and built the latest stable kernel from kernel.org (6.2.8).
https://cdn.kernel.org/pub/linux/kernel … 2.8.tar.xz

Still the same... maybe this isn't something to do with the kernel.
Or perhaps it is some option in the kernel config, as I used the same one from my running system.

Offline

#6 2024-05-09 15:28:53

jcul
Member
Registered: 2023-03-23
Posts: 5

Re: SO_TIMESTAMPING / recvmsg return no timestamps

I looked into this again.

The issue is that neither SOF_TIMESTAMPING_RX_SOFTWARE nor SO_TIMESTAMP (SO_TIMESTAMP_OLD, SO_TIMESTAMP_NEW, SO_TIMESTAMPNS_OLD, SO_TIMESTAMPNS_NEW) were actually set.

When these are set then net_enable_timestamp is called.

net/core/sock.c sock_enable_timestamp:

          if (sock_needs_netstamp(sk) &&
              !(previous_flags & SK_FLAGS_TIMESTAMP))
              net_enable_timestamp();
      }

include/net/sock.h: sock_recv_timestamp

      if (sock_flag(sk, SOCK_RCVTSTAMP) ||
          (sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
          (kt && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
          (hwtstamps->hwtstamp &&
           (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
      {
      {
          __sock_recv_timestamp(msg, sk, skb);
      }

For this check:

(kt && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE)

SOF_TIMESTAMPING_SOFTWARE was enabled, which controls reporting of software timestamps.
But kt, the timestamp was 0, without net_enable_timestamp() having been called.

If SOF_TIMESTAMPING_RX_SOFTWARE was enabled, but net_enable_timestamp was not called, then __sock_recv_timestamp would have filled in the current time anyway.

https://www.kernel.org/doc/html/latest/ … mping.html

SOF_TIMESTAMPING_RX_SOFTWARE:

    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.

SOF_TIMESTAMPING_SOFTWARE:

    Report any software timestamps when available.

SOF_TIMESTAMPING_SOFTWARE does not control timestamp generation, just reporting.


If you run a program that causes net_enable_timestamp() to be set, e.g. a program that sets SOF_TIMESTAMPING_RX_SOFTWARE,  SO_TIMESTAMPNS.
And then run this original program without setting one of those, then you will get SW timestamps.

This is due to SOF_TIMESTAMPING_SOFTWARE being set, and net_enable_timestamp() sets global state, so enabling it in one process affects others.

I have not figured out why on some systems this program worked as is and on others it did not.
I now thing it is unrelated to kernel version or kernel config options.

It may be that some process running on the systems where it did work was causing net_enable_timestamp() to be called, which had the side effect of causing SW timestamps to be reported.

Offline

Board footer

Powered by FluxBB