You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2023/08/22 07:34:30 UTC

[nuttx] branch master updated (7b34583996 -> 5597b8a9e2)

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

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


    from 7b34583996 ci/Dockerfile: Update riscv toolchain to gcc13.2.0
     new 2fa68fbddd drivers/virtio-net: Support different LL_GUARDSIZE
     new d44e19d115 mm/iob: Add support for increasing length in iob_update_pktlen
     new 318d136320 netdev/upper: Add netpkt_to_iov() interface
     new 5597b8a9e2 drivers/virtio-net: Add support to offload small IOBs

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 drivers/net/netdev_upperhalf.c       | 50 +++++++++++++++++--
 drivers/virtio/virtio-net.c          | 93 +++++++++++++++++++++++++++---------
 include/nuttx/mm/iob.h               | 12 +++--
 include/nuttx/net/netdev_lowerhalf.h | 42 ++++++++++++++--
 mm/iob/iob_update_pktlen.c           | 38 ++++++++++++---
 net/arp/arp_format.c                 |  2 +-
 net/devif/devif_filesend.c           |  4 +-
 net/devif/devif_poll.c               |  2 +-
 net/devif/devif_send.c               |  2 +-
 net/devif/ipv4_input.c               |  2 +-
 net/devif/ipv6_input.c               |  2 +-
 net/icmp/icmp_reply.c                |  7 +--
 net/icmpv6/icmpv6_advertise.c        |  2 +-
 net/icmpv6/icmpv6_radvertise.c       |  2 +-
 net/icmpv6/icmpv6_reply.c            |  7 +--
 net/icmpv6/icmpv6_rsolicit.c         |  2 +-
 net/icmpv6/icmpv6_solicit.c          |  2 +-
 net/igmp/igmp_send.c                 |  2 +-
 net/mld/mld_send.c                   |  2 +-
 net/tcp/tcp_send.c                   |  4 +-
 net/udp/udp_send.c                   |  2 +-
 net/udp/udp_sendto_buffered.c        |  2 +-
 22 files changed, 219 insertions(+), 64 deletions(-)


[nuttx] 04/04: drivers/virtio-net: Add support to offload small IOBs

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5597b8a9e235eb5d8a17947f3035543f3fe74b54
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Tue Jul 4 19:01:00 2023 +0800

    drivers/virtio-net: Add support to offload small IOBs
    
    TCP receive tested with different IOB_BUFSIZE:
    |             | 256B vs 1534B | 512B vs 1534B | 768B vs 1534B |
    | :---------: | :-----------: | :-----------: | :-----------: |
    |     Non-SMP |     ~85%      |     ~93%      |     ~96%      |
    |  armv8a-SMP |     ~66%      |     ~84%      |     ~92%      |
    | rv32/64-SMP |     ~52%      |     ~72%      |     ~83%      |
    
    It seems we still get performance penalty on smaller IOBs, and may be
    affected more under SMP mode. It may be caused by critical sections in
    IOB operations.
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/virtio/virtio-net.c | 72 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 17 deletions(-)

diff --git a/drivers/virtio/virtio-net.c b/drivers/virtio/virtio-net.c
index b0e3e0f9ac..5384d6798c 100644
--- a/drivers/virtio/virtio-net.c
+++ b/drivers/virtio/virtio-net.c
@@ -43,7 +43,7 @@
 
 #define VIRTIO_NET_HDRSIZE    (sizeof(struct virtio_net_hdr_s))
 #define VIRTIO_NET_LLHDRSIZE  (sizeof(struct virtio_net_llhdr_s))
-#define VIRTIO_NET_BUFSIZE    (MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE)
+#define VIRTIO_NET_BUFSIZE    (CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE)
 
 /* Virtio net virtqueue index and number */
 
@@ -51,6 +51,11 @@
 #define VIRTIO_NET_TX         1
 #define VIRTIO_NET_NUM        2
 
+#define VIRTIO_NET_MAX_PKT_SIZE \
+    ((CONFIG_NET_LL_GUARDSIZE - ETH_HDRLEN) + VIRTIO_NET_BUFSIZE)
+#define VIRTIO_NET_MAX_NIOB \
+    ((VIRTIO_NET_MAX_PKT_SIZE + CONFIG_IOB_BUFSIZE - 1) / CONFIG_IOB_BUFSIZE)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -168,8 +173,10 @@ static void virtio_net_rxfill(FAR struct netdev_lowerhalf_s *dev)
   FAR struct virtio_net_priv_s *priv = (FAR struct virtio_net_priv_s *)dev;
   FAR struct virtqueue *vq = priv->vdev->vrings_info[VIRTIO_NET_RX].vq;
   FAR struct virtio_net_llhdr_s *hdr;
-  FAR struct virtqueue_buf vb;
+  struct virtqueue_buf vb[VIRTIO_NET_MAX_NIOB];
+  struct iovec iov[VIRTIO_NET_MAX_NIOB];
   FAR netpkt_t *pkt;
+  int iov_cnt;
   int i;
 
   for (i = 0; i < priv->bufnum; i++)
@@ -183,21 +190,40 @@ static void virtio_net_rxfill(FAR struct netdev_lowerhalf_s *dev)
           break;
         }
 
+      /* Preserve data length */
+
+      if (netpkt_setdatalen(dev, pkt, VIRTIO_NET_BUFSIZE) <
+          VIRTIO_NET_BUFSIZE)
+        {
+          vrtwarn("No enough buffer to prepare RX buffer, i=%d\n", i);
+          netpkt_free(dev, pkt, NETPKT_RX);
+          break;
+        }
+
+      /* Convert netpkt to virtqueue_buf */
+
+      iov_cnt = netpkt_to_iov(dev, pkt, iov, VIRTIO_NET_MAX_NIOB);
+      for (i = 0; i < iov_cnt; i++)
+        {
+          vb[i].buf = iov[i].iov_base;
+          vb[i].len = iov[i].iov_len;
+        }
+
       /* Alloc cookie and net header from transport layer */
 
       hdr = (FAR struct virtio_net_llhdr_s *)
-              (netpkt_getdata(dev, pkt) - VIRTIO_NET_LLHDRSIZE);
+              ((FAR uint8_t *)vb[0].buf - VIRTIO_NET_LLHDRSIZE);
       DEBUGASSERT((FAR uint8_t *)hdr >= netpkt_getbase(pkt));
       memset(&hdr->vhdr, 0, sizeof(hdr->vhdr));
       hdr->pkt = pkt;
 
       /* Buffer 0, the virtio net header */
 
-      vb.buf = &hdr->vhdr;
-      vb.len = VIRTIO_NET_HDRSIZE + VIRTIO_NET_BUFSIZE;
+      vb[0].buf = &hdr->vhdr;
+      vb[0].len += VIRTIO_NET_HDRSIZE;
 
-      vrtinfo("Fill rx, hdr=%p, buf=%p, buflen=%d\n", hdr, vb.buf, vb.len);
-      virtqueue_add_buffer(vq, &vb, 0, 1, hdr);
+      vrtinfo("Fill rx, hdr=%p, count=%d\n", hdr, iov_cnt);
+      virtqueue_add_buffer(vq, vb, 0, iov_cnt, hdr);
     }
 
   if (i > 0)
@@ -289,33 +315,45 @@ static int virtio_net_send(FAR struct netdev_lowerhalf_s *dev,
   FAR struct virtio_net_priv_s *priv = (FAR struct virtio_net_priv_s *)dev;
   FAR struct virtqueue *vq = priv->vdev->vrings_info[VIRTIO_NET_TX].vq;
   FAR struct virtio_net_llhdr_s *hdr;
-  struct virtqueue_buf vb;
-  size_t len;
+  struct virtqueue_buf vb[VIRTIO_NET_MAX_NIOB];
+  struct iovec iov[VIRTIO_NET_MAX_NIOB];
+  int iov_cnt;
+  int i;
 
   /* Check the send length */
 
-  len = netpkt_getdatalen(dev, pkt);
-  if (len > VIRTIO_NET_BUFSIZE)
+  if (netpkt_getdatalen(dev, pkt) > VIRTIO_NET_BUFSIZE)
     {
       vrterr("net send buffer too large\n");
       return -EINVAL;
     }
 
+  /* Convert netpkt to virtqueue_buf */
+
+  iov_cnt = netpkt_to_iov(dev, pkt, iov, VIRTIO_NET_MAX_NIOB);
+  for (i = 0; i < iov_cnt; i++)
+    {
+      vb[i].buf = iov[i].iov_base;
+      vb[i].len = iov[i].iov_len;
+    }
+
+  /* Prepare virtio net header */
+
   hdr = (FAR struct virtio_net_llhdr_s *)
-          (netpkt_getdata(dev, pkt) - VIRTIO_NET_LLHDRSIZE);
+          ((FAR uint8_t *)vb[0].buf - VIRTIO_NET_LLHDRSIZE);
   DEBUGASSERT((FAR uint8_t *)hdr >= netpkt_getbase(pkt));
   hdr->pkt = pkt;
   memset(&hdr->vhdr, 0, sizeof(hdr->vhdr));
 
   /* Buffer 0 is the virtio net header */
 
-  vb.buf = &hdr->vhdr;
-  vb.len = VIRTIO_NET_HDRSIZE + len;
+  vb[0].buf = &hdr->vhdr;
+  vb[0].len += VIRTIO_NET_HDRSIZE;
 
   /* Add buffer to vq and notify the other side */
 
-  vrtinfo("Send, hdr=%p, buf=%p, buflen=%d\n", hdr, vb.buf, vb.len);
-  virtqueue_add_buffer(vq, &vb, 1, 0, hdr);
+  vrtinfo("Send, hdr=%p, count=%d\n", hdr, iov_cnt);
+  virtqueue_add_buffer(vq, vb, iov_cnt, 0, hdr);
   virtqueue_kick(vq);
 
   /* Try return Netpkt TX buffer to upper-half. */
@@ -473,7 +511,7 @@ static int virtio_net_init(FAR struct virtio_net_priv_s *priv,
    * 1/4 for the TX netpkts, 1/4 for the RX netpkts.
    */
 
-  priv->bufnum = CONFIG_IOB_NBUFFERS / 4;
+  priv->bufnum = CONFIG_IOB_NBUFFERS / VIRTIO_NET_MAX_NIOB / 4;
 #endif
   priv->bufnum = MIN(vdev->vrings_info[VIRTIO_NET_RX].info.num_descs,
                      priv->bufnum);


[nuttx] 01/04: drivers/virtio-net: Support different LL_GUARDSIZE

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2fa68fbdddf324315717055bdda0d2cbf44614e6
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Tue Jul 4 18:18:47 2023 +0800

    drivers/virtio-net: Support different LL_GUARDSIZE
    
    Previously, the CONFIG_NET_LL_GUARDSIZE is fixed to 32 (64-Bit) or
    28 (32-Bit), it's a little bit tricky.
    Now add support to any value greater than minimal size.
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/virtio/virtio-net.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/virtio/virtio-net.c b/drivers/virtio/virtio-net.c
index 1c463d4fe9..b0e3e0f9ac 100644
--- a/drivers/virtio/virtio-net.c
+++ b/drivers/virtio/virtio-net.c
@@ -42,6 +42,7 @@
 /* Virtio net header size and packet buffer size */
 
 #define VIRTIO_NET_HDRSIZE    (sizeof(struct virtio_net_hdr_s))
+#define VIRTIO_NET_LLHDRSIZE  (sizeof(struct virtio_net_llhdr_s))
 #define VIRTIO_NET_BUFSIZE    (MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE)
 
 /* Virtio net virtqueue index and number */
@@ -89,17 +90,21 @@ struct virtio_net_priv_s
  * |               |<--------- datalen -------->|
  * ^base           ^data
  *
- * CONFIG_NET_LL_GUARDSIZE = sizeof(struct virtio_net_llhdr_s) + ETH_HDR_SIZE
- *                         = sizeof(uintptr) + 10 + 14
- *                         = 32 (64-Bit)
- *                         = 28 (32-Bit)
+ * CONFIG_NET_LL_GUARDSIZE >= VIRTIO_NET_LLHDRSIZE + ETH_HDR_SIZE
+ *                          = sizeof(uintptr) + 10 + 14
+ *                          = 32 (64-Bit)
+ *                          = 28 (32-Bit)
  */
 
-struct virtio_net_llhdr_s
+begin_packed_struct struct virtio_net_llhdr_s
 {
   FAR netpkt_t           *pkt;         /* Netpaket pointer */
   struct virtio_net_hdr_s vhdr;        /* Virtio net header */
-};
+} end_packed_struct;
+
+static_assert(CONFIG_NET_LL_GUARDSIZE >= VIRTIO_NET_LLHDRSIZE + ETH_HDRLEN,
+              "CONFIG_NET_LL_GUARDSIZE cannot be less than ETH_HDRLEN"
+              " + VIRTIO_NET_LLHDRSIZE");
 
 /****************************************************************************
  * Private Function Prototypes
@@ -180,7 +185,9 @@ static void virtio_net_rxfill(FAR struct netdev_lowerhalf_s *dev)
 
       /* Alloc cookie and net header from transport layer */
 
-      hdr = (FAR struct virtio_net_llhdr_s *)netpkt_getbase(pkt);
+      hdr = (FAR struct virtio_net_llhdr_s *)
+              (netpkt_getdata(dev, pkt) - VIRTIO_NET_LLHDRSIZE);
+      DEBUGASSERT((FAR uint8_t *)hdr >= netpkt_getbase(pkt));
       memset(&hdr->vhdr, 0, sizeof(hdr->vhdr));
       hdr->pkt = pkt;
 
@@ -294,7 +301,9 @@ static int virtio_net_send(FAR struct netdev_lowerhalf_s *dev,
       return -EINVAL;
     }
 
-  hdr = (FAR struct virtio_net_llhdr_s *)netpkt_getbase(pkt);
+  hdr = (FAR struct virtio_net_llhdr_s *)
+          (netpkt_getdata(dev, pkt) - VIRTIO_NET_LLHDRSIZE);
+  DEBUGASSERT((FAR uint8_t *)hdr >= netpkt_getbase(pkt));
   hdr->pkt = pkt;
   memset(&hdr->vhdr, 0, sizeof(hdr->vhdr));
 


[nuttx] 02/04: mm/iob: Add support for increasing length in iob_update_pktlen

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d44e19d115b3b5f03789cfe3be0464d836ada72d
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Wed May 17 16:11:21 2023 +0800

    mm/iob: Add support for increasing length in iob_update_pktlen
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/net/netdev_upperhalf.c       | 11 ++++++++---
 include/nuttx/mm/iob.h               | 12 +++++++-----
 include/nuttx/net/netdev_lowerhalf.h |  7 +++++--
 mm/iob/iob_update_pktlen.c           | 38 +++++++++++++++++++++++++++++-------
 net/arp/arp_format.c                 |  2 +-
 net/devif/devif_filesend.c           |  4 ++--
 net/devif/devif_poll.c               |  2 +-
 net/devif/devif_send.c               |  2 +-
 net/devif/ipv4_input.c               |  2 +-
 net/devif/ipv6_input.c               |  2 +-
 net/icmp/icmp_reply.c                |  7 ++++---
 net/icmpv6/icmpv6_advertise.c        |  2 +-
 net/icmpv6/icmpv6_radvertise.c       |  2 +-
 net/icmpv6/icmpv6_reply.c            |  7 ++++---
 net/icmpv6/icmpv6_rsolicit.c         |  2 +-
 net/icmpv6/icmpv6_solicit.c          |  2 +-
 net/igmp/igmp_send.c                 |  2 +-
 net/mld/mld_send.c                   |  2 +-
 net/tcp/tcp_send.c                   |  4 ++--
 net/udp/udp_send.c                   |  2 +-
 net/udp/udp_sendto_buffered.c        |  2 +-
 21 files changed, 76 insertions(+), 40 deletions(-)

diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c
index a9f32cd93a..e2cede4d47 100644
--- a/drivers/net/netdev_upperhalf.c
+++ b/drivers/net/netdev_upperhalf.c
@@ -1290,12 +1290,17 @@ FAR uint8_t *netpkt_getbase(FAR netpkt_t *pkt)
  *   pkt    - The net packet
  *   len    - The length of data in netpkt
  *
+ * Returned Value:
+ *   The new effective data length, or a negated errno value on error.
+ *
  ****************************************************************************/
 
-void netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
-                       FAR netpkt_t *pkt, unsigned int len)
+int netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
+                      FAR netpkt_t *pkt, unsigned int len)
 {
-  iob_update_pktlen(pkt, len - NET_LL_HDRLEN(&dev->netdev));
+  uint8_t llhdrlen = NET_LL_HDRLEN(&dev->netdev);
+  int ret = iob_update_pktlen(pkt, len - llhdrlen, false);
+  return ret >= 0 ? ret + llhdrlen : ret;
 }
 
 /****************************************************************************
diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h
index 326597753c..704d9d7bc2 100644
--- a/include/nuttx/mm/iob.h
+++ b/include/nuttx/mm/iob.h
@@ -571,14 +571,16 @@ void iob_reserve(FAR struct iob_s *iob, unsigned int reserved);
  *
  * Description:
  *   This function will update packet length of the iob, it will be
- *   trimmed if the length of the iob chain is greater than the current
- *   length.
- *   This function will not grow the iob link, any grow operation should
- *   be implemented through iob_copyin()/iob_trycopyin().
+ *   trimmed if the current length of the iob chain is greater than the
+ *   new length, and will be grown if less than new length.
+ *
+ * Returned Value:
+ *   The new effective iob packet length, or a negated errno value on error.
  *
  ****************************************************************************/
 
-void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen);
+int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
+                      bool throttled);
 
 /****************************************************************************
  * Name: iob_count
diff --git a/include/nuttx/net/netdev_lowerhalf.h b/include/nuttx/net/netdev_lowerhalf.h
index 737da56a69..d47f324739 100644
--- a/include/nuttx/net/netdev_lowerhalf.h
+++ b/include/nuttx/net/netdev_lowerhalf.h
@@ -422,10 +422,13 @@ FAR uint8_t *netpkt_getbase(FAR netpkt_t *pkt);
  *   pkt    - The net packet
  *   len    - The length of data in netpkt
  *
+ * Returned Value:
+ *   The new effective data length, or a negated errno value on error.
+ *
  ****************************************************************************/
 
-void netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
-                       FAR netpkt_t *pkt, unsigned int len);
+int netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
+                      FAR netpkt_t *pkt, unsigned int len);
 
 /****************************************************************************
  * Name: netpkt_getdatalen
diff --git a/mm/iob/iob_update_pktlen.c b/mm/iob/iob_update_pktlen.c
index 3d1e9eafa9..e6e1fd46e3 100644
--- a/mm/iob/iob_update_pktlen.c
+++ b/mm/iob/iob_update_pktlen.c
@@ -36,14 +36,16 @@
  *
  * Description:
  *   This function will update packet length of the iob, it will be
- *   trimmed if the length of the iob chain is greater than the current
- *   length.
- *   This function will not grow the iob link, any grow operation should
- *   be implemented through iob_copyin()/iob_trycopyin().
+ *   trimmed if the current length of the iob chain is greater than the
+ *   new length, and will be grown if less than new length.
+ *
+ * Returned Value:
+ *   The new effective iob packet length, or a negated errno value on error.
  *
  ****************************************************************************/
 
-void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
+int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
+                      bool throttled)
 {
   FAR struct iob_s *penultimate;
   FAR struct iob_s *next;
@@ -56,7 +58,7 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
 
   if (iob == NULL)
     {
-      return;
+      return -EINVAL;
     }
 
   /* Calculate the total entries of the data in the I/O buffer chain */
@@ -66,7 +68,8 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
     {
       ninqueue++;
       offset += next->io_offset;
-      next    = next->io_flink;
+      penultimate = next;
+      next = next->io_flink;
     }
 
   /* Trim inqueue entries if needed */
@@ -104,6 +107,21 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
             }
         }
     }
+  else if (nrequire > ninqueue)
+    {
+      /* Start from the last IOB */
+
+      next = penultimate;
+
+      /* Loop to extend the link */
+
+      while (next != NULL && nrequire > ninqueue)
+        {
+          next->io_flink = iob_tryalloc(throttled);
+          next = next->io_flink;
+          ninqueue++;
+        }
+    }
 
   iob->io_pktlen = pktlen;
 
@@ -125,4 +143,10 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
       pktlen      -= len;
       next         = next->io_flink;
     }
+
+  /* Adjust final pktlen if it's not fully increased (e.g. alloc fail) */
+
+  iob->io_pktlen -= pktlen;
+
+  return iob->io_pktlen;
 }
diff --git a/net/arp/arp_format.c b/net/arp/arp_format.c
index 2b5db120bb..6623b033d8 100644
--- a/net/arp/arp_format.c
+++ b/net/arp/arp_format.c
@@ -109,7 +109,7 @@ void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, sizeof(struct arp_hdr_s));
+  iob_update_pktlen(dev->d_iob, sizeof(struct arp_hdr_s), false);
 }
 
 #endif /* CONFIG_NET_ARP */
diff --git a/net/devif/devif_filesend.c b/net/devif/devif_filesend.c
index a3245794c0..b6b4198df0 100644
--- a/net/devif/devif_filesend.c
+++ b/net/devif/devif_filesend.c
@@ -92,7 +92,7 @@ int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file,
       goto errout;
     }
 
-  iob_update_pktlen(dev->d_iob, target_offset);
+  iob_update_pktlen(dev->d_iob, target_offset, false);
 
   ret = file_seek(file, offset, SEEK_SET);
   if (ret < 0)
@@ -142,7 +142,7 @@ int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file,
         }
     }
 
-  iob_update_pktlen(dev->d_iob, target_offset + len);
+  iob_update_pktlen(dev->d_iob, target_offset + len, false);
 
   dev->d_sndlen = len;
   return len;
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 45b989add0..8be17bce97 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -704,7 +704,7 @@ static int devif_poll_ipfrag(FAR struct net_driver_s *dev,
 
   if (!bstop && reused)
     {
-      iob_update_pktlen(dev->d_iob, 0);
+      iob_update_pktlen(dev->d_iob, 0, false);
       netdev_iob_prepare(dev, true, 0);
     }
 
diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c
index 7ba5fd114b..943b737bbd 100644
--- a/net/devif/devif_send.c
+++ b/net/devif/devif_send.c
@@ -102,7 +102,7 @@ int devif_send(FAR struct net_driver_s *dev, FAR const void *buf,
 
   /* Prepare device buffer before poll callback */
 
-  iob_update_pktlen(dev->d_iob, offset);
+  iob_update_pktlen(dev->d_iob, offset, false);
 
   ret = iob_trycopyin(dev->d_iob, buf, len, offset, false);
   if (ret != len)
diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c
index 7a04d96dc2..5b8f9fc7fc 100644
--- a/net/devif/ipv4_input.c
+++ b/net/devif/ipv4_input.c
@@ -207,7 +207,7 @@ static int ipv4_in(FAR struct net_driver_s *dev)
   totlen = (ipv4->len[0] << 8) + ipv4->len[1];
   if (totlen < dev->d_len)
     {
-      iob_update_pktlen(dev->d_iob, totlen);
+      iob_update_pktlen(dev->d_iob, totlen, false);
       dev->d_len = totlen;
     }
   else if (totlen > dev->d_len)
diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c
index 943bbc5cb4..4565261c5d 100644
--- a/net/devif/ipv6_input.c
+++ b/net/devif/ipv6_input.c
@@ -256,7 +256,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
 
   if (paylen < dev->d_len)
     {
-      iob_update_pktlen(dev->d_iob, paylen);
+      iob_update_pktlen(dev->d_iob, paylen, false);
       dev->d_len = paylen;
     }
   else if (paylen > dev->d_len)
diff --git a/net/icmp/icmp_reply.c b/net/icmp/icmp_reply.c
index a19f556497..5a6ca57520 100644
--- a/net/icmp/icmp_reply.c
+++ b/net/icmp/icmp_reply.c
@@ -133,7 +133,7 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, datalen + ipicmplen);
+      iob_update_pktlen(dev->d_iob, datalen + ipicmplen, false);
     }
   else
     {
@@ -167,8 +167,9 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, dev->d_iob->io_pktlen +
-                                    sizeof(struct icmp_hdr_s));
+      iob_update_pktlen(dev->d_iob,
+                        dev->d_iob->io_pktlen + sizeof(struct icmp_hdr_s),
+                        false);
 
       /* Concat new icmp packet before original datagram */
 
diff --git a/net/icmpv6/icmpv6_advertise.c b/net/icmpv6/icmpv6_advertise.c
index 0bc2c4c5f9..583522ac1b 100644
--- a/net/icmpv6/icmpv6_advertise.c
+++ b/net/icmpv6/icmpv6_advertise.c
@@ -105,7 +105,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_radvertise.c b/net/icmpv6/icmpv6_radvertise.c
index c9a882a973..5b83530f53 100644
--- a/net/icmpv6/icmpv6_radvertise.c
+++ b/net/icmpv6/icmpv6_radvertise.c
@@ -282,7 +282,7 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_reply.c b/net/icmpv6/icmpv6_reply.c
index 4f20d3b263..9aa0745983 100644
--- a/net/icmpv6/icmpv6_reply.c
+++ b/net/icmpv6/icmpv6_reply.c
@@ -122,7 +122,7 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, datalen + ipicmplen);
+      iob_update_pktlen(dev->d_iob, datalen + ipicmplen, false);
     }
   else
     {
@@ -156,8 +156,9 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, dev->d_iob->io_pktlen +
-                                    sizeof(struct icmpv6_hdr_s));
+      iob_update_pktlen(dev->d_iob,
+                        dev->d_iob->io_pktlen + sizeof(struct icmpv6_hdr_s),
+                        false);
 
       /* Concat new icmp packet before original datagram */
 
diff --git a/net/icmpv6/icmpv6_rsolicit.c b/net/icmpv6/icmpv6_rsolicit.c
index efce18ef20..40f7f024b5 100644
--- a/net/icmpv6/icmpv6_rsolicit.c
+++ b/net/icmpv6/icmpv6_rsolicit.c
@@ -99,7 +99,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_solicit.c b/net/icmpv6/icmpv6_solicit.c
index 07421c9cba..8519abd933 100644
--- a/net/icmpv6/icmpv6_solicit.c
+++ b/net/icmpv6/icmpv6_solicit.c
@@ -122,7 +122,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/igmp/igmp_send.c b/net/igmp/igmp_send.c
index 9f770909c2..378f3fbc44 100644
--- a/net/igmp/igmp_send.c
+++ b/net/igmp/igmp_send.c
@@ -129,7 +129,7 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* The total size of the data is the size of the IGMP header */
 
diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c
index 09d676f075..07e8b76ed7 100644
--- a/net/mld/mld_send.c
+++ b/net/mld/mld_send.c
@@ -168,7 +168,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Select the IPv6 destination address.
    * This varies with the type of message being sent:
diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c
index 6c328c4c0d..68cd1830fc 100644
--- a/net/tcp/tcp_send.c
+++ b/net/tcp/tcp_send.c
@@ -170,7 +170,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
 
   /* Update device buffer length before setup the IP header */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Calculate chk & build L3 header */
 
@@ -464,7 +464,7 @@ void tcp_reset(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
 
   /* Update device buffer length before setup the IP header */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Calculate chk & build L3 header */
 
diff --git a/net/udp/udp_send.c b/net/udp/udp_send.c
index f6377a59f5..39e0ffe665 100644
--- a/net/udp/udp_send.c
+++ b/net/udp/udp_send.c
@@ -174,7 +174,7 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
 
       /* Update the device buffer length */
 
-      iob_update_pktlen(dev->d_iob, dev->d_len);
+      iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
 #ifdef CONFIG_NET_UDP_CHECKSUMS
       /* Calculate UDP checksum. */
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index 5e944b05cb..1eff0e8a24 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -790,7 +790,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
       udpiplen = udpip_hdrsize(conn);
 
       iob_reserve(wrb->wb_iob, CONFIG_NET_LL_GUARDSIZE);
-      iob_update_pktlen(wrb->wb_iob, udpiplen);
+      iob_update_pktlen(wrb->wb_iob, udpiplen, false);
 
       /* Copy the user data into the write buffer.  We cannot wait for
        * buffer space if the socket was opened non-blocking.


[nuttx] 03/04: netdev/upper: Add netpkt_to_iov() interface

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 318d136320a5b297404380c1b393f4b69342b86d
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Wed May 17 17:30:40 2023 +0800

    netdev/upper: Add netpkt_to_iov() interface
    
    Some driver like virtio-net can offload fragmented IOBs, so an interface
    to support this feature is needed.
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/net/netdev_upperhalf.c       | 39 ++++++++++++++++++++++++++++++++++++
 include/nuttx/net/netdev_lowerhalf.h | 35 +++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c
index e2cede4d47..8c1c3244d2 100644
--- a/drivers/net/netdev_upperhalf.c
+++ b/drivers/net/netdev_upperhalf.c
@@ -1359,3 +1359,42 @@ bool netpkt_is_fragmented(FAR netpkt_t *pkt)
 {
   return pkt->io_flink != NULL;
 }
+
+/****************************************************************************
+ * Name: netpkt_to_iov
+ *
+ * Description:
+ *   Write each piece of data/len into iov array.
+ *
+ * Input Parameters:
+ *   dev    - The lower half device driver structure
+ *   pkt    - The net packet
+ *   iov    - The iov array to write
+ *   iovcnt - The number of elements in the iov array
+ *
+ * Returned Value:
+ *   The actual written count of iov entries.
+ *
+ ****************************************************************************/
+
+int netpkt_to_iov(FAR struct netdev_lowerhalf_s *dev, FAR netpkt_t *pkt,
+                  FAR struct iovec *iov, int iovcnt)
+{
+  int i;
+
+  for (i = 0; pkt != NULL && i < iovcnt; pkt = pkt->io_flink, i++)
+    {
+      if (i == 0)
+        {
+          iov[i].iov_base = IOB_DATA(pkt) - NET_LL_HDRLEN(&dev->netdev);
+          iov[i].iov_len  = pkt->io_len   + NET_LL_HDRLEN(&dev->netdev);
+        }
+      else
+        {
+          iov[i].iov_base = IOB_DATA(pkt);
+          iov[i].iov_len  = pkt->io_len;
+        }
+    }
+
+  return i;
+}
diff --git a/include/nuttx/net/netdev_lowerhalf.h b/include/nuttx/net/netdev_lowerhalf.h
index d47f324739..f29f9b4337 100644
--- a/include/nuttx/net/netdev_lowerhalf.h
+++ b/include/nuttx/net/netdev_lowerhalf.h
@@ -47,7 +47,9 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/* | <-------------- NETPKT_BUFLEN ---------------> |
+/* Layout for net packet:
+ *
+ * | <-------------- NETPKT_BUFLEN ---------------> |
  * +---------------------+-------------------+------+      +-------------+
  * | reserved for driver |       data        | free | ---> | next netpkt |
  * +---------------------+-------------------+------+      +-------------+
@@ -55,6 +57,17 @@
  * ^base                 ^data
  */
 
+/* Layout for linked net packet, you can get list of (data, len) by
+ * netpkt_to_iov() interface:
+ *
+ *            | <----------- datalen = sum(len) ------------> |
+ * +----------+-----------+     +-----------+     +-----------+------+
+ * | reserved |   data    | --> |   data    | --> |   data    | free |
+ * +----------+-----------+     +-----------+     +-----------+------+
+ * |          | <- len -> |     | <- len -> |     | <- len -> |
+ * ^base      ^data             ^data             ^data
+ */
+
 #define NETPKT_BUFLEN   CONFIG_IOB_BUFSIZE
 
 /****************************************************************************
@@ -478,4 +491,24 @@ void netpkt_reset_reserved(FAR struct netdev_lowerhalf_s *dev,
 
 bool netpkt_is_fragmented(FAR netpkt_t *pkt);
 
+/****************************************************************************
+ * Name: netpkt_to_iov
+ *
+ * Description:
+ *   Write each piece of data/len into iov array.
+ *
+ * Input Parameters:
+ *   dev    - The lower half device driver structure
+ *   pkt    - The net packet
+ *   iov    - The iov array to write
+ *   iovcnt - The number of elements in the iov array
+ *
+ * Returned Value:
+ *   The actual written count of iov entries.
+ *
+ ****************************************************************************/
+
+int netpkt_to_iov(FAR struct netdev_lowerhalf_s *dev, FAR netpkt_t *pkt,
+                  FAR struct iovec *iov, int iovcnt);
+
 #endif /* __INCLUDE_NUTTX_NET_NETDEV_LOWERHALF_H */