This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 9a65ffc51d46bcdce4c5c13d9000cd49a61a2790 Author: OceanfromXiaomi <[email protected]> AuthorDate: Tue Oct 14 17:10:00 2025 +0800 net: move rx timestamp from d_rxtime to iob_s.io_time 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 <[email protected]> Signed-off-by: wenquan1 <[email protected]> --- boards/arm/imx9/imx95-evk/configs/can/defconfig | 1 - include/nuttx/mm/iob.h | 14 ++++++++++++ include/nuttx/net/netdev.h | 5 +++-- mm/iob/iob_clone.c | 4 ++++ net/Kconfig | 1 - net/can/can_bufpool.c | 8 ------- net/can/can_callback.c | 29 ------------------------- net/can/can_input.c | 6 +++++ net/can/can_recvmsg.c | 22 +++++++++---------- net/devif/ipv4_input.c | 12 +++++----- net/devif/ipv6_input.c | 12 +++++----- net/netdev/netdev_input.c | 4 ++++ net/pkt/pkt_input.c | 18 +-------------- net/pkt/pkt_recvmsg.c | 10 ++------- net/udp/udp_callback.c | 16 -------------- net/udp/udp_recvfrom.c | 11 ++-------- 16 files changed, 58 insertions(+), 115 deletions(-) diff --git a/boards/arm/imx9/imx95-evk/configs/can/defconfig b/boards/arm/imx9/imx95-evk/configs/can/defconfig index fb147108d64..6b14202f5b9 100644 --- a/boards/arm/imx9/imx95-evk/configs/can/defconfig +++ b/boards/arm/imx9/imx95-evk/configs/can/defconfig @@ -62,7 +62,6 @@ CONFIG_NET_CAN_EXTID=y CONFIG_NET_CAN_NOTIFIER=y CONFIG_NET_CAN_RAW_TX_DEADLINE=y CONFIG_NET_CAN_SOCK_OPTS=y -CONFIG_NET_LL_GUARDSIZE=14 CONFIG_NET_TIMESTAMP=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_FILEIOSIZE=512 diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index 4c3c2710264..a32c5090bca 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -37,6 +37,10 @@ # include <nuttx/wqueue.h> #endif +#ifdef CONFIG_NET_TIMESTAMP +# include <sys/time.h> +#endif + #ifdef CONFIG_MM_IOB /**************************************************************************** @@ -126,6 +130,16 @@ struct iob_s #endif unsigned int io_pktlen; /* Total length of the packet */ +#ifdef CONFIG_NET_TIMESTAMP + /* timestamp of the packet. + * If CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP is true, the timestamp is provided + * by hardware driver. Otherwise it is filled in by kernel when the packet + * is passed into respective protocol layer. The timestamp is in + * CLOCK_REALTIME. + */ + + struct timespec io_time; +#endif #ifdef CONFIG_IOB_ALLOC iob_free_cb_t io_free; /* Custom free callback */ FAR uint8_t *io_data; diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index 23a3f2f5e5d..ca68c30eaaf 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -527,9 +527,10 @@ struct net_driver_s /* Reception timestamp of packet being currently processed. * If CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP is true, the timestamp is provided * by hardware driver. Otherwise it is filled in by kernel when packet - * enters ipv4_input or ipv6_input. + * enters ipv4_input or ipv6_input. The timestamp is in CLOCK_REALTIME. * - * The timestamp is in CLOCK_REALTIME. + * d_rxtime is serviced for older netdev driver. + * d_rxtime will be replaced by iob->io_tstamp in net stack. */ struct timespec d_rxtime; diff --git a/mm/iob/iob_clone.c b/mm/iob/iob_clone.c index 3438a1b1097..86316bc4519 100644 --- a/mm/iob/iob_clone.c +++ b/mm/iob/iob_clone.c @@ -127,6 +127,10 @@ int iob_clone_partial(FAR struct iob_s *iob1, unsigned int len, iob2->io_pktlen = len + offset2; +#ifdef CONFIG_NET_TIMESTAMP + iob2->io_time = iob1->io_time; +#endif + /* Handle special case where there are empty buffers at the head * the list, Skip I/O buffer containing the data offset. */ diff --git a/net/Kconfig b/net/Kconfig index b561b3f8fcc..26d55b7a87e 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -139,7 +139,6 @@ config NET_LL_GUARDSIZE int "Data Link Layer(L2) Guard size of Network buffer(IOB)" default 50 if RNDIS default 18 if NET_VLAN - default 16 if NET_CAN && NET_TIMESTAMP default 14 if NET_ETHERNET default 0 ---help--- diff --git a/net/can/can_bufpool.c b/net/can/can_bufpool.c index a6b2b47f909..a5140a7d80b 100644 --- a/net/can/can_bufpool.c +++ b/net/can/can_bufpool.c @@ -36,14 +36,9 @@ * Pre-processor Definitions ****************************************************************************/ -#ifdef CONFIG_NET_TIMESTAMP # define CAN_BUFFER_SIZE ALIGN_UP(sizeof(struct iob_s) + NET_CAN_PKTSIZE + \ CONFIG_NET_LL_GUARDSIZE + IOB_ALIGNMENT - \ 1, IOB_ALIGNMENT) -#else -# define CAN_BUFFER_SIZE ALIGN_UP(sizeof(struct iob_s) + NET_CAN_PKTSIZE + \ - IOB_ALIGNMENT - 1, IOB_ALIGNMENT) -#endif /**************************************************************************** * Private Data @@ -117,10 +112,7 @@ FAR struct iob_s *can_iob_clone(FAR struct net_driver_s *dev) return NULL; } -#ifdef CONFIG_NET_TIMESTAMP iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE); -#endif - /* CAN data length is fixed, So when we use iob_clone_partial to copy * data, we don't have to worry about distributing other iob. */ diff --git a/net/can/can_callback.c b/net/can/can_callback.c index b06302e0e6c..c5c072d143a 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -70,10 +70,6 @@ can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn, int recvlen; uint32_t ret; -#ifdef CONFIG_NET_TIMESTAMP - buflen -= sizeof(struct timeval); -#endif - ret = (flags & ~CAN_NEWDATA); /* Save as the packet data as in the read-ahead buffer. NOTE that @@ -126,31 +122,6 @@ uint32_t can_callback(FAR struct net_driver_s *dev, if (conn) { -#ifdef CONFIG_NET_TIMESTAMP - /* TIMESTAMP sockopt is activated, - * create timestamp and copy to iob - */ - - if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && - (dev->d_iob != NULL)) - { - struct timeval tv; - FAR struct timespec *ts = (FAR struct timespec *)&tv; - int len; - - clock_systime_timespec(ts); - tv.tv_usec = ts->tv_nsec / 1000; - - len = iob_trycopyin(dev->d_iob, (FAR uint8_t *)&tv, - sizeof(struct timeval), - -CONFIG_NET_LL_GUARDSIZE, false); - if (len == sizeof(struct timeval)) - { - dev->d_len += len; - } - } -#endif - conn_lock(&conn->sconn); flags = devif_conn_event(dev, flags, conn->sconn.list); diff --git a/net/can/can_input.c b/net/can/can_input.c index a2c2b497f17..f1cd561df66 100644 --- a/net/can/can_input.c +++ b/net/can/can_input.c @@ -229,6 +229,12 @@ static int can_in(FAR struct net_driver_s *dev) return OK; } + /* Store reception timestamp if enabled and not provided by hardware. */ + +#if defined(CONFIG_NET_TIMESTAMP) && !defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) + clock_gettime(CLOCK_REALTIME, &dev->d_iob->io_time); +#endif + can_conn_list_lock(); /* Do we have second connection that can hold this packet? */ diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index 0a26ea28344..82fdb3a1f51 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -135,8 +135,11 @@ static size_t can_recvfrom_newdata(FAR struct net_driver_s *dev, if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && pstate->pr_msglen == sizeof(struct timeval)) { - iob_copyout(pstate->pr_msgbuf, dev->d_iob, sizeof(struct timeval), - -CONFIG_NET_LL_GUARDSIZE); + struct timeval tv; + + tv.tv_sec = dev->d_iob->io_time.tv_sec; + tv.tv_usec = dev->d_iob->io_time.tv_nsec / 1000; + memcpy(pstate->pr_msgbuf, &tv, sizeof(struct timeval)); } #endif @@ -249,8 +252,11 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && pstate->pr_msglen == sizeof(struct timeval)) { - iob_copyout(pstate->pr_msgbuf, iob, sizeof(struct timeval), - -CONFIG_NET_LL_GUARDSIZE); + struct timeval tv; + + tv.tv_sec = iob->io_time.tv_sec; + tv.tv_usec = iob->io_time.tv_nsec / 1000; + memcpy(pstate->pr_msgbuf, &tv, sizeof(struct timeval)); } #endif @@ -309,15 +315,7 @@ static uint32_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) #endif { -#ifdef CONFIG_NET_TIMESTAMP - if ((_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && - dev->d_len > sizeof(struct can_frame) + - sizeof(struct timeval)) || - (!_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && - dev->d_len > sizeof(struct can_frame))) -#else if (dev->d_len > sizeof(struct can_frame)) -#endif { /* DO WE NEED TO CLEAR FLAGS?? */ diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c index eb880ad2e90..b94c4c53ba4 100644 --- a/net/devif/ipv4_input.c +++ b/net/devif/ipv4_input.c @@ -231,6 +231,12 @@ static int ipv4_in(FAR struct net_driver_s *dev) bool isfrag; int ret = OK; + /* Store reception timestamp if enabled and not provided by hardware. */ + +#if defined(CONFIG_NET_TIMESTAMP) && !defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) + clock_gettime(CLOCK_REALTIME, &dev->d_iob->io_time); +#endif + /* Handle ARP on input then give the IPv4 packet to the network layer */ arp_ipin(dev); @@ -573,12 +579,6 @@ int ipv4_input(FAR struct net_driver_s *dev) netdev_lock(dev); - /* Store reception timestamp if enabled and not provided by hardware. */ - -#if defined(CONFIG_NET_TIMESTAMP) && !defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) - clock_gettime(CLOCK_REALTIME, &dev->d_rxtime); -#endif - if (dev->d_iob != NULL) { buf = dev->d_buf; diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c index 3400fdebd79..065c5873341 100644 --- a/net/devif/ipv6_input.c +++ b/net/devif/ipv6_input.c @@ -229,6 +229,12 @@ static int ipv6_in(FAR struct net_driver_s *dev) bool isfrag = false; #endif + /* Store reception timestamp if enabled and not provided by hardware. */ + +#if defined(CONFIG_NET_TIMESTAMP) && !defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) + clock_gettime(CLOCK_REALTIME, &dev->d_iob->io_time); +#endif + /* This is where the input processing starts. */ #ifdef CONFIG_NET_STATISTICS @@ -706,12 +712,6 @@ int ipv6_input(FAR struct net_driver_s *dev) netdev_lock(dev); - /* Store reception timestamp if enabled and not provided by hardware. */ - -#if defined(CONFIG_NET_TIMESTAMP) && !defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) - clock_gettime(CLOCK_REALTIME, &dev->d_rxtime); -#endif - if (dev->d_iob != NULL) { buf = dev->d_buf; diff --git a/net/netdev/netdev_input.c b/net/netdev/netdev_input.c index 6554e11520d..05882f5d9d7 100644 --- a/net/netdev/netdev_input.c +++ b/net/netdev/netdev_input.c @@ -80,6 +80,10 @@ int netdev_input(FAR struct net_driver_s *dev, return ret; } +#if defined(CONFIG_NET_TIMESTAMP) && defined(CONFIG_ARCH_HAVE_NETDEV_TIMESTAMP) + dev->d_iob->io_time = dev->d_rxtime; +#endif + /* Copy data to iob entry */ ret = iob_trycopyin(dev->d_iob, buf, dev->d_len, -llhdrlen, false); diff --git a/net/pkt/pkt_input.c b/net/pkt/pkt_input.c index 93701b5750d..a517f04a69d 100644 --- a/net/pkt/pkt_input.c +++ b/net/pkt/pkt_input.c @@ -70,22 +70,6 @@ static uint16_t pkt_datahandler(FAR struct net_driver_s *dev, return 0; } -#ifdef CONFIG_NET_TIMESTAMP - if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) || - _SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMPNS)) - { - ret = iob_trycopyin(iob, (FAR const uint8_t *)&dev->d_rxtime, - sizeof(struct timespec), 0, true); - if (ret != sizeof(struct timespec)) - { - nerr("ERROR: Failed to write timestamp: %d\n", ret); - goto errout; - } - - iob_reserve(iob, sizeof(struct timespec)); - } -#endif - /* Clone an I/O buffer chain of the L2 data, use throttled IOB to avoid * overconsumption. * TODO: Optimize IOB clone after we support shared IOB. @@ -179,7 +163,7 @@ static int pkt_in(FAR struct net_driver_s *dev) if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) || _SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMPNS)) { - clock_gettime(CLOCK_REALTIME, &dev->d_rxtime); + clock_gettime(CLOCK_REALTIME, &dev->d_iob->io_time); } #endif /* CONFIG_NET_TIMESTAMP */ diff --git a/net/pkt/pkt_recvmsg.c b/net/pkt/pkt_recvmsg.c index 531e48e9183..79489a9ca49 100644 --- a/net/pkt/pkt_recvmsg.c +++ b/net/pkt/pkt_recvmsg.c @@ -163,7 +163,7 @@ static void pkt_recvfrom_newdata(FAR struct net_driver_s *dev, if (_SO_GETOPT(pstate->pr_conn->sconn.s_options, SO_TIMESTAMP) || _SO_GETOPT(pstate->pr_conn->sconn.s_options, SO_TIMESTAMPNS)) { - pkt_store_cmsg_timestamp(pstate, &dev->d_rxtime); + pkt_store_cmsg_timestamp(pstate, &dev->d_iob->io_time); } #endif @@ -392,13 +392,7 @@ static inline void pkt_readahead(FAR struct pkt_recvfrom_s *pstate) if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) || _SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMPNS)) { - struct timespec ts; - recvlen = iob_copyout((FAR uint8_t *)&ts, iob, - sizeof(struct timespec), - -sizeof(struct timespec)); - DEBUGASSERT(recvlen == sizeof(struct timespec)); - - pkt_store_cmsg_timestamp(pstate, &ts); + pkt_store_cmsg_timestamp(pstate, &iob->io_time); } #endif diff --git a/net/udp/udp_callback.c b/net/udp/udp_callback.c index 1eae4b81d10..58f872cf4f9 100644 --- a/net/udp/udp_callback.c +++ b/net/udp/udp_callback.c @@ -159,22 +159,6 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev, */ offset = (dev->d_appdata - iob->io_data) - iob->io_offset; - -#ifdef CONFIG_NET_TIMESTAMP - /* Store timestamp while packet is being queued. - * This is done unconditionally to avoid race condition when SO_TIMESTAMP - * gets enabled after packet is received but before it is read. - */ - - offset -= sizeof(struct timespec); - ret = iob_trycopyin(iob, (FAR const uint8_t *)&dev->d_rxtime, - sizeof(struct timespec), offset, true); - if (ret < 0) - { - goto errout; - } -#endif - offset -= src_addr_size; ret = iob_trycopyin(iob, src_addr, src_addr_size, offset, true); if (ret < 0) diff --git a/net/udp/udp_recvfrom.c b/net/udp/udp_recvfrom.c index 66a4d8810fa..3514069fd07 100644 --- a/net/udp/udp_recvfrom.c +++ b/net/udp/udp_recvfrom.c @@ -224,15 +224,8 @@ static inline void udp_readahead(struct udp_recvfrom_s *pstate) if (conn->timestamp) { - struct timespec timestamp; - recvlen = iob_copyout((FAR uint8_t *)×tamp, iob, - sizeof(struct timespec), offset); - DEBUGASSERT(recvlen == sizeof(struct timespec)); - - udp_store_cmsg_timestamp(pstate, ×tamp); + udp_store_cmsg_timestamp(pstate, &iob->io_time); } - - offset += sizeof(struct timespec); #endif /* Copy to user */ @@ -472,7 +465,7 @@ static uint32_t udp_eventhandler(FAR struct net_driver_s *dev, #ifdef CONFIG_NET_TIMESTAMP if (pstate->ir_conn->timestamp) { - udp_store_cmsg_timestamp(pstate, &dev->d_rxtime); + udp_store_cmsg_timestamp(pstate, &dev->d_iob->io_time); } #endif
