You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/04/26 16:31:04 UTC

[nuttx] branch master updated: net/can: fix can mssage corruption if enable NET_TIMESTAMP

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 2eb9abc3d8 net/can: fix can mssage corruption if enable NET_TIMESTAMP
2eb9abc3d8 is described below

commit 2eb9abc3d862a460a6a059f456cb83f80a8258cf
Author: chao an <an...@xiaomi.com>
AuthorDate: Wed Apr 26 21:29:15 2023 +0800

    net/can: fix can mssage corruption if enable NET_TIMESTAMP
    
    Timestamp location in can message has changed,
    In the original logic timestamp is saved at the end of the data segment:
    
    io_data
       -------------------------------------------------
       |         CAN message            |  Time Stamp  |
       -------------------------------------------------
       |<---------------     io_len   ---------------->|
    
    In the new structure timestamps will reuse NET_LL_GUARDSIZE to isolate CAN messages:
    io_data       io_offset
       -------------------------------------------------
       |  Time Stamp  |         CAN message            |
       -------------------------------------------------
                      |<--------    io_len   --------->|
    
    This PR will:
    1. Increase NET_LL_GUARDSIZE to 16 (sizeof(struct timeval)) if NET_CAN && NET_TIMESTAMP are enabled
    2. Apply timestamp to adapt to the new structure
    
    Signed-off-by: chao an <an...@xiaomi.com>
---
 net/Kconfig            |   1 +
 net/can/can_callback.c |   3 +-
 net/can/can_recvmsg.c  | 126 +++++++------------------------------------------
 3 files changed, 20 insertions(+), 110 deletions(-)

diff --git a/net/Kconfig b/net/Kconfig
index 0d11685b83..21d813b645 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -119,6 +119,7 @@ config NET_GUARDSIZE
 
 config NET_LL_GUARDSIZE
 	int "Data Link Layer(L2) Guard size of Network buffer(IOB)"
+	default 16 if NET_CAN && NET_TIMESTAMP
 	default 14 if NET_ETHERNET
 	default 0
 	---help---
diff --git a/net/can/can_callback.c b/net/can/can_callback.c
index c69a1dcbfb..d8ebfc6550 100644
--- a/net/can/can_callback.c
+++ b/net/can/can_callback.c
@@ -148,7 +148,8 @@ uint16_t can_callback(FAR struct net_driver_s *dev,
               tv.tv_usec = ts->tv_nsec / 1000;
 
               len = iob_trycopyin(dev->d_iob, (FAR uint8_t *)&tv,
-                                  sizeof(struct timeval), 0, false);
+                                  sizeof(struct timeval),
+                                  -CONFIG_NET_LL_GUARDSIZE, false);
               if (len != sizeof(struct timeval))
                 {
                   dev->d_len = 0;
diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c
index 451a33112c..2a11b66337 100644
--- a/net/can/can_recvmsg.c
+++ b/net/can/can_recvmsg.c
@@ -125,6 +125,15 @@ static size_t can_recvfrom_newdata(FAR struct net_driver_s *dev,
   unsigned int offset;
   size_t recvlen;
 
+#ifdef CONFIG_NET_TIMESTAMP
+  if (pstate->pr_conn->timestamp &&
+      pstate->pr_msglen == sizeof(struct timeval))
+    {
+      iob_copyout(pstate->pr_msgbuf, dev->d_iob, sizeof(struct timeval),
+                  -CONFIG_NET_LL_GUARDSIZE);
+    }
+#endif
+
   if (dev->d_len > pstate->pr_buflen)
     {
       recvlen = pstate->pr_buflen;
@@ -224,6 +233,14 @@ static inline int can_readahead(struct can_recvfrom_s *pstate)
     {
       DEBUGASSERT(iob->io_pktlen > 0);
 
+#ifdef CONFIG_NET_TIMESTAMP
+      if (conn->timestamp && pstate->pr_msglen == sizeof(struct timeval))
+        {
+          iob_copyout(pstate->pr_msgbuf, iob, sizeof(struct timeval),
+                      -CONFIG_NET_LL_GUARDSIZE);
+        }
+#endif
+
       /* Transfer that buffered data from the I/O buffer chain into
        * the user buffer.
        */
@@ -279,79 +296,6 @@ static inline int can_readahead(struct can_recvfrom_s *pstate)
   return 0;
 }
 
-/****************************************************************************
- * Name: can_readahead
- *
- * Description:
- *   Copy the read-ahead data from the packet
- *
- * Input Parameters:
- *   pstate   recvfrom state structure
- *
- * Returned Value:
- *   None
- *
- * Assumptions:
- *   The network is locked.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_TIMESTAMP
-static inline int can_readahead_timestamp(struct can_conn_s *conn,
-                                          FAR uint8_t *buffer)
-{
-  FAR struct iob_s *iob;
-  int recvlen;
-
-  if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
-    {
-      DEBUGASSERT(iob->io_pktlen > 0);
-
-      /* Transfer that buffered data from the I/O buffer chain into
-       * the user buffer.
-       */
-
-      recvlen = iob_copyout(buffer, iob, sizeof(struct timeval), 0);
-
-      /* If we took all of the data from the I/O buffer chain is empty, then
-       * release it.  If there is still data available in the I/O buffer
-       * chain, then just trim the data that we have taken from the
-       * beginning of the I/O buffer chain.
-       */
-
-      if (recvlen >= iob->io_pktlen)
-        {
-          FAR struct iob_s *tmp;
-
-          /* Remove the I/O buffer chain from the head of the read-ahead
-           * buffer queue.
-           */
-
-          tmp = iob_remove_queue(&conn->readahead);
-          DEBUGASSERT(tmp == iob);
-          UNUSED(tmp);
-
-          /* And free the I/O buffer chain */
-
-          iob_free_chain(iob);
-        }
-      else
-        {
-          /* The bytes that we have received from the head of the I/O
-           * buffer chain (probably changing the head of the I/O
-           * buffer queue).
-           */
-
-          iob_trimhead_queue(&conn->readahead, recvlen);
-        }
-
-      return recvlen;
-    }
-
-  return 0;
-}
-#endif
-
 #ifdef CONFIG_NET_CANPROTO_OPTIONS
 static int can_recv_filter(struct can_conn_s *conn, canid_t id)
 {
@@ -431,25 +375,6 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
 
           can_newdata(dev, pstate);
 
-#ifdef CONFIG_NET_TIMESTAMP
-          if (conn->timestamp)
-            {
-              if (pstate->pr_msglen == sizeof(struct timeval))
-                {
-                  can_readahead_timestamp(conn, pstate->pr_msgbuf);
-                }
-              else
-                {
-                  /* We still have to consume the data
-                   * otherwise IOB gets full
-                   */
-
-                  uint8_t dummy_buf[sizeof(struct timeval)];
-                  can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
-                }
-            }
-#endif
-
           /* We are finished. */
 
           /* Don't allow any further call backs. */
@@ -596,23 +521,6 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
   ret = can_readahead(&state);
   if (ret > 0)
     {
-#ifdef CONFIG_NET_TIMESTAMP
-      if (conn->timestamp)
-        {
-          if (state.pr_msglen == sizeof(struct timeval))
-            {
-              can_readahead_timestamp(conn, state.pr_msgbuf);
-            }
-          else
-            {
-              /* We still have to consume the data otherwise IOB gets full */
-
-              uint8_t dummy_buf[sizeof(struct timeval)];
-              can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
-            }
-        }
-#endif
-
       goto errout_with_state;
     }