You are not logged in.
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_timestampingIn another terminal:
socat - udp-sendto:127.0.0.1:9000Output on arch:
Socket created, listening on port 9000
Selecting hardware timestamping mode.
Packet 1 - 5 bytes no timestamp
Packet 2 - 5 bytes no timestampOn 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.000000000Offline
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-zenLast edited by 3beb6e7c46a615a (2023-03-23 14:05:32)
Offline
Thanks!
I'll try switching to the zen kernel and see if it makes a difference.
Offline
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-zenLast edited by jcul (2023-03-26 22:13:13)
Offline
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
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