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 *)&timestamp, iob,
-                                sizeof(struct timespec), offset);
-          DEBUGASSERT(recvlen == sizeof(struct timespec));
-
-          udp_store_cmsg_timestamp(pstate, &timestamp);
+          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
 

Reply via email to