1
0
Fork 0
forked from nuttx/nuttx-update

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 <anchao@xiaomi.com>
This commit is contained in:
chao an 2023-04-26 21:29:15 +08:00 committed by Xiang Xiao
parent df2925cf13
commit 2eb9abc3d8
3 changed files with 20 additions and 110 deletions

View file

@ -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---

View file

@ -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;

View file

@ -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;
}