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 504af7a1fa drivers/virtio-net: Support VIRTIO_F_ANY_LAYOUT
504af7a1fa is described below

commit 504af7a1fae0bdf76ea42b5235ad9a0ff5466725
Author: Zhe Weng <[email protected]>
AuthorDate: Tue May 21 19:59:49 2024 +0800

    drivers/virtio-net: Support VIRTIO_F_ANY_LAYOUT
    
    According to Virtual I/O Spec:
    When using legacy interfaces, transitional drivers which have not 
negotiated VIRTIO_F_ANY_LAYOUT MUST use a single descriptor for the struct 
virtio_net_hdr on both transmit and receive, with the network data in the 
following descriptors.
    
    
https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.html#x1-2280006
 (Section 5.1.6.6)
    
    Signed-off-by: Zhe Weng <[email protected]>
---
 drivers/virtio/virtio-net.c   | 135 ++++++++++++++++++++++++------------------
 include/nuttx/virtio/virtio.h |   6 ++
 2 files changed, 84 insertions(+), 57 deletions(-)

diff --git a/drivers/virtio/virtio-net.c b/drivers/virtio/virtio-net.c
index 93d94818b1..ce0afc88bb 100644
--- a/drivers/virtio/virtio-net.c
+++ b/drivers/virtio/virtio-net.c
@@ -40,6 +40,8 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Virtio net feature bits */
+
 #define VIRTIO_NET_F_MAC      5
 
 /* Virtio net header size and packet buffer size */
@@ -193,6 +195,77 @@ static const struct netdev_ops_s g_virtio_net_ops =
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: virtio_net_addbuffer
+ ****************************************************************************/
+
+static int virtio_net_addbuffer(FAR struct netdev_lowerhalf_s *dev,
+                                FAR struct virtqueue *vq, FAR netpkt_t *pkt,
+                                unsigned int vq_id)
+{
+  FAR struct virtio_net_priv_s *priv = (FAR struct virtio_net_priv_s *)dev;
+  FAR struct virtio_net_llhdr_s *hdr;
+  struct virtqueue_buf vb[VIRTIO_NET_MAX_NIOB + 1];
+  struct iovec iov[VIRTIO_NET_MAX_NIOB];
+  int iov_cnt;
+  int i;
+
+  /* Convert netpkt to virtqueue_buf */
+
+  iov_cnt = netpkt_to_iov(dev, pkt, iov, VIRTIO_NET_MAX_NIOB);
+
+  /* Alloc cookie and net header from transport layer */
+
+  hdr = (FAR struct virtio_net_llhdr_s *)
+          ((FAR uint8_t *)iov[0].iov_base - VIRTIO_NET_LLHDRSIZE);
+  DEBUGASSERT((FAR uint8_t *)hdr >= netpkt_getbase(pkt));
+  memset(&hdr->vhdr, 0, sizeof(hdr->vhdr));
+  hdr->pkt = pkt;
+
+  /* Prepare buffers depends on the feature VIRTIO_F_ANY_LAYOUT */
+
+  if (virtio_has_feature(priv->vdev, VIRTIO_F_ANY_LAYOUT))
+    {
+      /* Append the virtio net header to the first buffer */
+
+      vb[0].buf = &hdr->vhdr;
+      vb[0].len = iov[0].iov_len + VIRTIO_NET_HDRSIZE;
+
+#if VIRTIO_NET_MAX_NIOB > 1
+      for (i = 1; i < iov_cnt; i++)
+        {
+          vb[i].buf = iov[i].iov_base;
+          vb[i].len = iov[i].iov_len;
+        }
+#endif
+    }
+  else
+    {
+      /* Buffer 0 is only for virtio net header */
+
+      vb[0].buf = &hdr->vhdr;
+      vb[0].len = VIRTIO_NET_HDRSIZE;
+
+      for (i = 0; i < iov_cnt; i++)
+        {
+          vb[i + 1].buf = iov[i].iov_base;
+          vb[i + 1].len = iov[i].iov_len;
+        }
+
+      iov_cnt++;
+    }
+
+  vrtinfo("Fill vq=%u, hdr=%p, count=%d\n", vq_id, hdr, iov_cnt);
+  if (vq_id == VIRTIO_NET_RX)
+    {
+      return virtqueue_add_buffer(vq, vb, 0, iov_cnt, hdr);
+    }
+  else
+    {
+      return virtqueue_add_buffer(vq, vb, iov_cnt, 0, hdr);
+    }
+}
+
 /****************************************************************************
  * Name: virtio_net_rxfill
  ****************************************************************************/
@@ -201,11 +274,7 @@ 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;
-  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++)
@@ -229,30 +298,9 @@ static void virtio_net_rxfill(FAR struct 
netdev_lowerhalf_s *dev)
           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 *)
-              ((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 */
+      /* Add buffer to RX virtqueue */
 
-      vb[0].buf = &hdr->vhdr;
-      vb[0].len += VIRTIO_NET_HDRSIZE;
-
-      vrtinfo("Fill rx, hdr=%p, count=%d\n", hdr, iov_cnt);
-      virtqueue_add_buffer(vq, vb, 0, iov_cnt, hdr);
+      virtio_net_addbuffer(dev, vq, pkt, VIRTIO_NET_RX);
     }
 
   if (i > 0)
@@ -360,11 +408,6 @@ 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[VIRTIO_NET_MAX_NIOB];
-  struct iovec iov[VIRTIO_NET_MAX_NIOB];
-  int iov_cnt;
-  int i;
 
   /* Check the send length */
 
@@ -374,32 +417,9 @@ static int virtio_net_send(FAR struct netdev_lowerhalf_s 
*dev,
       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 *)
-          ((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[0].buf = &hdr->vhdr;
-  vb[0].len += VIRTIO_NET_HDRSIZE;
-
   /* Add buffer to vq and notify the other side */
 
-  vrtinfo("Send, hdr=%p, count=%d\n", hdr, iov_cnt);
-  virtqueue_add_buffer(vq, vb, iov_cnt, 0, hdr);
+  virtio_net_addbuffer(dev, vq, pkt, VIRTIO_NET_TX);
   virtqueue_kick(vq);
 
   /* Try return Netpkt TX buffer to upper-half. */
@@ -534,7 +554,8 @@ static int virtio_net_init(FAR struct virtio_net_priv_s 
*priv,
   /* Initialize the virtio device */
 
   virtio_set_status(vdev, VIRTIO_CONFIG_STATUS_DRIVER);
-  virtio_negotiate_features(vdev, 1 << VIRTIO_NET_F_MAC);
+  virtio_negotiate_features(vdev, (1UL << VIRTIO_NET_F_MAC) |
+                                  (1UL << VIRTIO_F_ANY_LAYOUT));
   virtio_set_status(vdev, VIRTIO_CONFIG_FEATURES_OK);
 
   vqnames[VIRTIO_NET_RX]   = "virtio_net_rx";
diff --git a/include/nuttx/virtio/virtio.h b/include/nuttx/virtio/virtio.h
index 061cb04f55..7ad756b527 100644
--- a/include/nuttx/virtio/virtio.h
+++ b/include/nuttx/virtio/virtio.h
@@ -38,6 +38,12 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Virtio common feature bits */
+
+#define VIRTIO_F_ANY_LAYOUT   27
+
+/* Virtio helper functions */
+
 #define virtio_has_feature(vdev, fbit) \
       (((vdev)->features & (1UL << (fbit))) != 0)
 

Reply via email to