net: add SO_TIMESTAMPING support for PKT sockets - #20161
Conversation
|
@daniel-p-carvalho please review and try this pr for hw timestamp. |
|
@wenquan2015 @xiaoxiang781216 this modification is causing an error on CI |
|
@wenquan2015 suggestion: create testing with this sample code at apps/testing/nettest/timestamp/ |
5a547e5 to
8cde6d5
Compare
I'll create a separate nuttx-apps PR to add the SO_TIMESTAMPING test program under |
10b32ca to
699f7b4
Compare
699f7b4 to
65e5932
Compare
Tried this on real hardware (RMII Ethernet, STM32H743BI). The SO_TIMESTAMPING infrastructure itself is all correct - setsockopt/getsockopt, cmsg, the error queue, poll(POLLPRI), everything works exactly as expected. What I found: on real hardware, TX timestamp delivery depends on the transmitted frame looping back through the receive path (io_conn match in pkt_in()). That works fine in the simulator (which already has that loopback simulated), but on a real Ethernet board, full-duplex, point-to-point, the transmitted frame never shows up on RX again - so poll/recvmsg never fire. Probably just wasn't caught because testing this needs real physical hardware with a second point on the network, not just the simulator. I put together a prototype to close that last gap: a new function (pkt_tx_timestamp_complete()) that lets the driver deliver the timestamp directly from the TX-complete interrupt, without depending on any loopback - which is how hardware TX timestamping normally works (read the completed descriptor). Wired it into the STM32H7 driver as a reference and validated it end to end: poll/recvmsg now deliver correctly. Left the branches available in case they're useful: daniel-p-carvalho/apache-nuttx#test/pr20161-h7-tx-timestamp (the new delivery path + driver wiring) |
ee79d15 to
65e5932
Compare
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s): CI run: https://github.com/apache/nuttx/actions/runs/35173950789 |
SO_TIMESTAMPING_TX_HARDWARE depends on driver-level implementation. When transmitting, the driver checks if the IOB is tagged for TX completion interrupt (driver_txisr): Receive path (driver_receive): |
|
@wenquan2015 please fix ci error. |
3e47a2f
65e5932 to
3e47a2f
Compare
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s): CI run: https://github.com/apache/nuttx/actions/runs/35297281971 |
Move RX timestamp storage from net_driver_s.d_rxtime into iob_s.io_time so each IOB carries its own timestamp through the stack. Remove old iob_trycopyin/iob_copyout timestamp packing in CAN/PKT/UDP paths. Fix iob_clone_partial to copy io_time before source pointer advances to NULL. Signed-off-by: OceanfromXiaomi <zhaohaiyang1@xiaomi.com> Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Extract a common cmsg_store_timestamp() helper that checks SO_TIMESTAMP/SO_TIMESTAMPNS via s_options and appends the appropriate cmsg. Replaces per-protocol timestamp formatting in CAN, PKT, and UDP receive paths. Signed-off-by: OceanfromXiaomi <zhaohaiyang1@xiaomi.com>
Replace compile-time CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP with a runtime NETDEV_RX_STAMP bit in net_driver_s.d_features. Drivers providing hardware RX timestamps set the flag at probe time; the stack checks it at runtime. Signed-off-by: OceanfromXiaomi <zhaohaiyang1@xiaomi.com>
Add SO_TIMESTAMPING TX path for PKT sockets. Tagged TX packets loop back through the driver with io_conn set, are routed into conn->errahead, and delivered to userspace via recvmsg(MSG_ERRQUEUE) with SO_TIMESTAMPING cmsg. Add poll(POLLPRI) notification when errahead is non-empty. Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Fix a scheduling issue where MSG_ERRQUEUE readiness was not properly waking poll waiters in pkt_netpoll.c. Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Remove the redundant `timestamp` field from `udp_conn_s` and use the existing `s_options` bitmask to track SO_TIMESTAMP/SO_TIMESTAMPNS state. The socket-level setsockopt/getsockopt already handles SO_TIMESTAMP via _SO_SETOPT/_SO_GETOPT on s_options. The protocol-level handlers in inet_sockif.c were intercepting the option before the socket layer, causing s_options to never be set. This also meant SO_TIMESTAMPNS was broken since inet_sockif.c only handled SO_TIMESTAMP. Changes: - Remove udp_conn_s.timestamp field from udp.h - Remove SO_TIMESTAMP get/set handlers from inet_sockif.c, letting them fall through to the socket-level handler - Simplify udp_recvfrom.c to call cmsg_store_timestamp() directly, which already checks s_options internally - Align pkt_input.c software timestamp generation with ipv4/can by removing per-socket SO_TIMESTAMP option check, only checking hardware timestamp capability Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Consolidate the two separate timestamp Kconfig options into a single CONFIG_NET_TIMESTAMP option that covers SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTAMPING socket options. Previously CONFIG_NET_TIMESTAMPING was a separate option only used by PKT sockets for hardware TX/RX timestamps and error queue support. Since both options guard the same io_time field in iob_s and share the s_options bitmask, merging them simplifies configuration without functional impact. Changes: - Replace all CONFIG_NET_TIMESTAMPING with CONFIG_NET_TIMESTAMP in pkt_input.c, pkt_recvmsg.c, pkt_sendmsg_buffered.c, pkt_sendmsg_unbuffered.c, pkt_sockif.c, pkt_netpoll.c, pkt.h, setsockopt.c, getsockopt.c - Simplify iob.h conditional from OR of both to single option - Remove NET_TIMESTAMPING Kconfig entry, update NET_TIMESTAMP description to cover all three socket options Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Add missing SCM_TIMESTAMPNS and SCM_TIMESTAMPING control message type definitions mapped to their corresponding SO_TIMESTAMPNS and SO_TIMESTAMPING socket options. Also align whitespace of existing SCM_* definitions for consistency. Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Add TX timestamp loopback support to the simulator network driver. When a packet tagged with io_conn (SO_TIMESTAMPING TX) is sent, the driver clones the packet, generates a software timestamp, and queues it for loopback through the RX path. The protocol layer (UDP/PKT) then delivers the timestamp via MSG_ERRQUEUE. - Add tstampq IOB queue to sim_netdev_s for loopback packets. - In netdriver_send(), clone timestamped packets with realtime clock and notify RX ready. - In netdriver_recv(), return loopback packets before reading from the tap device. Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
Fix coding style issues flagged by nxstyle in files touched by the SO_TIMESTAMPING series. These are pre-existing issues, not introduced by the SO_TIMESTAMPING patches: - inet_sockif.c: missing blank lines after declarations - ipv4_input.c: missing blank line after declaration, bad comment alignment - can_input.c: bad indentation inside #ifdef block - getsockopt.c: bad comment block alignment, bad brace alignment - setsockopt.c: wrong column position of comment - sim_netdriver.c: missing blank lines after declarations Signed-off-by: wenquan1 <wenquan1@xiaomi.com>
3e47a2f to
17d71a9
Compare
🔗 Cross-repo PR dependenciesThe read-only Build run reported the following dependent PR(s) and fetched head SHA(s): CI run: https://github.com/apache/nuttx/actions/runs/35312719356 |
Summary
Add Linux-compatible SO_TIMESTAMPING socket option support to NuttX, enabling hardware and software TX/RX packet timestamping on PKT
sockets with MSG_ERRQUEUE delivery. This is the kernel infrastructure needed by PTP (IEEE 1588) daemons and network latency
measurement tools.
The series is organized as three foundation patches (from the Xiaomi Vela team) that modernize the existing SO_TIMESTAMP
infrastructure, followed by five patches that build SO_TIMESTAMPING on top.
What changed (8 commits)
nuttx: modify "d_rxtime" and use "iob->io_time" to instead in newer netdev driver
— Move RX timestamp storage from net_driver_s.d_rxtime into iob_s.io_time, so each IOB carries its own timestamp through the
stack. Remove the old iob_trycopyin/iob_copyout timestamp packing in CAN/PKT/UDP paths. Fix iob_clone_partial to copy io_time from
source before the source pointer advances to NULL.
nuttx: create "cmsg_store_timestamp" function
— Extract a common cmsg_store_timestamp() helper in net/utils/net_cmsg.c that checks SO_TIMESTAMP/SO_TIMESTAMPNS via s_options
and appends the appropriate cmsg. Replaces per-protocol timestamp cmsg formatting in CAN, PKT, and UDP receive paths.
nuttx: add NETDEV_RX_STAMP flag in d_features
— Replace the compile-time CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP Kconfig with a runtime NETDEV_RX_STAMP bit in
net_driver_s.d_features. Drivers that provide hardware RX timestamps set the flag at probe time; the stack checks it at runtime to
decide whether to fill software timestamps.
net/pkt: support option SO_TIMESTAMPING and MSG_ERRQUEUE
— Add SO_TIMESTAMPING TX path for PKT sockets: tagged TX packets loop back through the driver with io_conn set, are routed into
conn->errahead, and delivered to userspace via recvmsg(MSG_ERRQUEUE) with SO_TIMESTAMPING cmsg containing struct timespec[3]. Add
poll(POLLPRI) notification when errahead is non-empty.
net/pkt: fix time schedule problem when receive MSG_ERRQUEUE
— Fix a scheduling issue where MSG_ERRQUEUE readiness was not properly waking poll waiters in pkt_netpoll.c.
net/socket: use s_options for SO_TIMESTAMP instead of per-conn field
— Remove the redundant udp_conn_s.timestamp field. The socket-level setsockopt/getsockopt already manages
SO_TIMESTAMP/SO_TIMESTAMPNS via the s_options bitmask; the protocol-level handlers in inet_sockif.c were shadowing this, causing
SO_TIMESTAMPNS to never work. Remove the protocol-level intercepts so both options are handled uniformly at the socket layer.
net/socket: merge CONFIG_NET_TIMESTAMPING into CONFIG_NET_TIMESTAMP
— Consolidate the two Kconfig options (CONFIG_NET_TIMESTAMP and CONFIG_NET_TIMESTAMPING) into a single CONFIG_NET_TIMESTAMP that
covers SO_TIMESTAMP, SO_TIMESTAMPNS, and SO_TIMESTAMPING.
include/sys/socket.h: add SCM_TIMESTAMPNS and SCM_TIMESTAMPING macros
— Add missing SCM_TIMESTAMPNS and SCM_TIMESTAMPING control message type definitions for use with recvmsg() cmsg parsing.
Impact
poll(POLLPRI) notification for errqueue readiness.
preventing s_options from being set. Now both SO_TIMESTAMP and SO_TIMESTAMPNS work correctly.
cmsg_store_timestamp() helper; compile-time ARCH_HAVE_NETDEV_TIMESTAMP replaced with runtime NETDEV_RX_STAMP flag.
Testing
Tested on NuttX sim (sim:dynconns with CONFIG_NET_TIMESTAMP=y, CONFIG_NET_PKT=y) using TAP networking:
timestamp ✅
✅
SO_TIMESTAMPING Test Suite
=== Test 1: SO_TIMESTAMPING setsockopt/getsockopt ===
setsockopt SO_TIMESTAMPING TX: OK
getsockopt SO_TIMESTAMPING: flags=0x1
TX flag set: OK (val=0x1)
=== Test 2: SO_TIMESTAMP backward compatibility ===
setsockopt SO_TIMESTAMP: OK
setsockopt SO_TIMESTAMPNS: OK
=== Test 3: TX timestamping + MSG_ERRQUEUE ===
sent 46 bytes
recvmsg MSG_ERRQUEUE: got 46 bytes, flags=0x2000
TX timestamp: 1789550304.500344702
PASS: SO_TIMESTAMPING TX works!
=== Test 4: RX timestamp via SO_TIMESTAMP ===
recvmsg: got 60 bytes
RX timestamp: 1789550304.519840
PASS: SO_TIMESTAMP RX works!
=== Test 5: TX timestamping with poll() ===
poll returned: revents=0xa (POLLPRI)
recvmsg: got 46 bytes, flags=0x2000
TX timestamp: 1789550304.579824479
PASS: poll + MSG_ERRQUEUE works!
All tests PASSED
depends-on: apache/nuttx-apps/pull/3788