From be89bcc0445eba4101d09960f0b58ee63824dbfd Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Wed, 18 Jan 2023 19:58:52 +0800 Subject: [PATCH] mm/iob: Support negative offset when copyin/out. Signed-off-by: Zhe Weng --- include/nuttx/mm/iob.h | 6 +++--- mm/iob/iob_copyin.c | 21 ++++++++++++++------- mm/iob/iob_copyout.c | 13 +++++++++++-- net/devif/devif_poll.c | 7 +------ net/netdev/netdev_input.c | 23 +++++------------------ 5 files changed, 34 insertions(+), 36 deletions(-) diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index ee3987d086..ede9816f9e 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -405,7 +405,7 @@ unsigned int iob_get_queue_size(FAR struct iob_queue_s *queue); ****************************************************************************/ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src, - unsigned int len, unsigned int offset, bool throttled); + unsigned int len, int offset, bool throttled); /**************************************************************************** * Name: iob_trycopyin @@ -418,7 +418,7 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src, ****************************************************************************/ int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src, - unsigned int len, unsigned int offset, bool throttled); + unsigned int len, int offset, bool throttled); /**************************************************************************** * Name: iob_copyout @@ -430,7 +430,7 @@ int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src, ****************************************************************************/ int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob, - unsigned int len, unsigned int offset); + unsigned int len, int offset); /**************************************************************************** * Name: iob_tailroom diff --git a/mm/iob/iob_copyin.c b/mm/iob/iob_copyin.c index 039cd923bd..0d221ee3b9 100644 --- a/mm/iob/iob_copyin.c +++ b/mm/iob/iob_copyin.c @@ -51,7 +51,7 @@ ****************************************************************************/ static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src, - unsigned int len, unsigned int offset, + unsigned int len, int offset, bool throttled, bool can_block) { FAR struct iob_s *head = iob; @@ -61,23 +61,30 @@ static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src, unsigned int avail; unsigned int total = len; - iobinfo("iob=%p len=%u offset=%u\n", iob, len, offset); + iobinfo("iob=%p len=%u offset=%d\n", iob, len, offset); DEBUGASSERT(iob && src); /* The offset must applied to data that is already in the I/O buffer * chain */ - if (offset > iob->io_pktlen) + if ((int)(offset - iob->io_pktlen) > 0) { - ioberr("ERROR: offset is past the end of data: %u > %u\n", + ioberr("ERROR: offset is past the end of data: %d > %u\n", offset, iob->io_pktlen); return -ESPIPE; } + if ((int)(offset + iob->io_offset) < 0) + { + ioberr("ERROR: offset is before the start of data: %d < %d\n", + offset, -(int)iob->io_offset); + return -ESPIPE; + } + /* Skip to the I/O buffer containing the data offset */ - while (offset > iob->io_len) + while ((int)(offset - iob->io_len) > 0) { offset -= iob->io_len; iob = iob->io_flink; @@ -216,7 +223,7 @@ static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src, ****************************************************************************/ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src, - unsigned int len, unsigned int offset, bool throttled) + unsigned int len, int offset, bool throttled) { return iob_copyin_internal(iob, src, len, offset, throttled, true); } @@ -232,7 +239,7 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src, ****************************************************************************/ int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src, - unsigned int len, unsigned int offset, bool throttled) + unsigned int len, int offset, bool throttled) { return iob_copyin_internal(iob, src, len, offset, throttled, false); } diff --git a/mm/iob/iob_copyout.c b/mm/iob/iob_copyout.c index 5d9643c750..a32e777d10 100644 --- a/mm/iob/iob_copyout.c +++ b/mm/iob/iob_copyout.c @@ -54,16 +54,25 @@ ****************************************************************************/ int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob, - unsigned int len, unsigned int offset) + unsigned int len, int offset) { FAR const uint8_t *src; unsigned int ncopy; unsigned int avail; unsigned int remaining; + /* The offset must applied to data that is in the I/O buffer chain */ + + if ((int)(offset + iob->io_offset) < 0) + { + ioberr("ERROR: offset is before the start of data: %d < %d\n", + offset, -(int)iob->io_offset); + return -ESPIPE; + } + /* Skip to the I/O buffer containing the offset */ - while (offset >= iob->io_len) + while ((int)(offset - iob->io_len) >= 0) { offset -= iob->io_len; iob = iob->io_flink; diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 7eb4e49776..5cf78a6949 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -1004,12 +1004,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback) { /* Copy iob to flat buffer */ - iob_copyout(buf + llhdrlen, - dev->d_iob, dev->d_len, 0); - - /* Copy l2 header (arp out) */ - - memcpy(buf, IPBUF(-llhdrlen), llhdrlen); + iob_copyout(buf, dev->d_iob, dev->d_len, -llhdrlen); /* Restore flat buffer pointer */ diff --git a/net/netdev/netdev_input.c b/net/netdev/netdev_input.c index 45a63d7176..85aa6e7e57 100644 --- a/net/netdev/netdev_input.c +++ b/net/netdev/netdev_input.c @@ -68,8 +68,6 @@ int netdev_input(FAR struct net_driver_s *dev, { uint16_t llhdrlen = NET_LL_HDRLEN(dev); FAR uint8_t *buf = dev->d_buf; - unsigned int offset; - unsigned int l3l4len; int ret; /* Prepare iob buffer */ @@ -80,32 +78,21 @@ int netdev_input(FAR struct net_driver_s *dev, return ret; } - /* Copy l2 header to gruard area */ + /* Copy data to iob entry */ - offset = dev->d_iob->io_offset - llhdrlen; - memcpy(dev->d_iob->io_data + offset, buf, llhdrlen); - - /* Copy l3/l4 data to iob entry */ - - l3l4len = dev->d_len - llhdrlen; - - ret = iob_trycopyin(dev->d_iob, buf + llhdrlen, - l3l4len, 0, false); - if (ret == l3l4len) + ret = iob_trycopyin(dev->d_iob, buf, dev->d_len, -llhdrlen, false); + if (ret == dev->d_len) { /* Update device buffer to l2 start */ - dev->d_buf = dev->d_iob->io_data + offset; - - iob_update_pktlen(dev->d_iob, l3l4len); + dev->d_buf = NETLLBUF; ret = callback(dev); if (dev->d_iob != NULL && reply) { if (ret == OK && dev->d_len > 0) { - iob_copyout(buf + llhdrlen, dev->d_iob, dev->d_len, 0); - memcpy(buf, dev->d_iob->io_data + offset, llhdrlen); + iob_copyout(buf, dev->d_iob, dev->d_len, -llhdrlen); } } }