From d0d8d76df6d3e95cd565ef63a47f55800e98357d Mon Sep 17 00:00:00 2001 From: tarun Date: Thu, 19 Mar 2026 17:32:55 +0530 Subject: [PATCH 1/2] Propagate DPDK mbuf RX timestamp to FreeBSD mbuf rcv_tstmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable RTE_ETH_RX_OFFLOAD_TIMESTAMP on ports where the NIC supports it, register the timestamp dynamic field and flag via rte_mbuf_dyn_rx_timestamp_register() after rte_eth_dev_start() (when the PMD has registered the dynfield), and copy it into the FreeBSD mbuf's m_pkthdr.rcv_tstmp so that the existing SO_TIMESTAMP / SCM_TIMESTAMP path delivers it to userspace. Uses the DPDK 23.11 dynamic field API: checks the registered dynflag mask per-packet (not the legacy RTE_MBUF_F_RX_IEEE1588_TMST) and reads the timestamp via RTE_MBUF_DYNFIELD at the registered offset. When HW timestamps are not available the offload is not enabled, the dynflag is never set, and the new code path is never entered — fully backward compatible. Fixes: https://github.com/F-Stack/f-stack/issues/1045 --- lib/ff_dpdk_if.c | 29 +++++++++++++++++++++++++++++ lib/ff_veth.c | 7 +++++++ lib/ff_veth.h | 1 + 3 files changed, 37 insertions(+) diff --git a/lib/ff_dpdk_if.c b/lib/ff_dpdk_if.c index 5b53c54a6..2e5156ae1 100644 --- a/lib/ff_dpdk_if.c +++ b/lib/ff_dpdk_if.c @@ -54,6 +54,7 @@ #include #include #include +#include #include "ff_dpdk_if.h" #include "ff_dpdk_pcap.h" @@ -80,6 +81,8 @@ static int numa_on; static unsigned idle_sleep; static unsigned pkt_tx_delay; +static int timestamp_dynfield_offset = -1; +static uint64_t timestamp_dynflag_mask; static uint64_t usr_cb_tsc; static int stop_loop; @@ -740,6 +743,11 @@ init_port_start(void) pconf->hw_features.rx_csum = 1; } + if (dev_info.rx_offload_capa & RTE_ETH_RX_OFFLOAD_TIMESTAMP) { + ff_log(FF_LOG_INFO, FF_LOGTYPE_FSTACK_LIB, "RX timestamp offload supported\n"); + port_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP; + } + if (ff_global_cfg.dpdk.tx_csum_offoad_skip == 0) { if ((dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) { ff_log(FF_LOG_INFO, FF_LOGTYPE_FSTACK_LIB, "TX ip checksum offload supported\n"); @@ -851,6 +859,20 @@ init_port_start(void) return ret; } + if ((port_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) && + timestamp_dynfield_offset < 0) { + ret = rte_mbuf_dyn_rx_timestamp_register( + ×tamp_dynfield_offset, ×tamp_dynflag_mask); + if (ret == 0) { + ff_log(FF_LOG_INFO, FF_LOGTYPE_FSTACK_LIB, + "RX timestamp dynfield registered, offset=%d\n", + timestamp_dynfield_offset); + } else { + ff_log(FF_LOG_ERR, FF_LOGTYPE_FSTACK_LIB, + "RX timestamp dynfield registration failed\n"); + } + } + //RSS reta update will failed when enable flow isolate #if !defined(FF_FLOW_ISOLATE) && !defined(FF_FLOW_IPIP) if (nb_queues > 1) { @@ -1459,6 +1481,13 @@ ff_veth_input(const struct ff_dpdk_if_context *ctx, struct rte_mbuf *pkt) ff_mbuf_set_vlan_info(hdr, pkt->vlan_tci); } + if ((pkt->ol_flags & timestamp_dynflag_mask) && + timestamp_dynfield_offset >= 0) { + rte_mbuf_timestamp_t ts = *RTE_MBUF_DYNFIELD( + pkt, timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + ff_mbuf_set_timestamp(hdr, (uint64_t)ts); + } + struct rte_mbuf *pn = pkt->next; void *prev = hdr; while(pn != NULL) { diff --git a/lib/ff_veth.c b/lib/ff_veth.c index 7fc6ee5a7..05734953b 100644 --- a/lib/ff_veth.c +++ b/lib/ff_veth.c @@ -1124,3 +1124,10 @@ ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci) { return; } +void +ff_mbuf_set_timestamp(void *hdr, uint64_t timestamp) { + struct mbuf *m = (struct mbuf *)hdr; + m->m_pkthdr.rcv_tstmp = timestamp; + m->m_flags |= M_TSTMP | M_TSTMP_HPREC; +} + diff --git a/lib/ff_veth.h b/lib/ff_veth.h index 87792ff04..0fb853f84 100644 --- a/lib/ff_veth.h +++ b/lib/ff_veth.h @@ -52,5 +52,6 @@ void *ff_veth_get_softc(void *host_ctx); void ff_veth_free_softc(void *softc); void ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci); +void ff_mbuf_set_timestamp(void *hdr, uint64_t timestamp); #endif /* ifndef _FSTACK_VETH_H */ From 7a6c0754da51f8f39af787e84b01ce7bfb9695b0 Mon Sep 17 00:00:00 2001 From: tarun Date: Thu, 19 Mar 2026 22:28:52 +0530 Subject: [PATCH 2/2] Map Linux SO_TIMESTAMP to FreeBSD in ff_syscall_wrapper Add LINUX_SO_TIMESTAMP (29) to the socket option translation table so that applications using the Linux syscall wrapper can enable packet receive timestamps via setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, ...). --- lib/ff_syscall_wrapper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ff_syscall_wrapper.c b/lib/ff_syscall_wrapper.c index df85b5b2f..11a5bdd13 100644 --- a/lib/ff_syscall_wrapper.c +++ b/lib/ff_syscall_wrapper.c @@ -80,6 +80,7 @@ #define LINUX_SO_SNDLOWAT 19 #define LINUX_SO_RCVTIMEO 20 #define LINUX_SO_SNDTIMEO 21 +#define LINUX_SO_TIMESTAMP 29 #define LINUX_SO_ACCEPTCONN 30 #define LINUX_SO_PROTOCOL 38 @@ -566,6 +567,8 @@ so_opt_convert(int optname) return SO_ACCEPTCONN; case LINUX_SO_PROTOCOL: return SO_PROTOCOL; + case LINUX_SO_TIMESTAMP: + return SO_TIMESTAMP; default: return -1; }