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/01/30 16:39:24 UTC

[nuttx] 02/02: net/tun: Change TUN/TAP to use IOB

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

commit ff68d9ac04bdf20a12b8420b622f3cef282459d2
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Tue Jan 10 20:03:02 2023 +0800

    net/tun: Change TUN/TAP to use IOB
    
    TUN/TAP is not working after IOB offload, try to fix.
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/net/tun.c | 77 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 49 insertions(+), 28 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 47d32be57d..65e54fcdb1 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -61,6 +61,8 @@
 #include <nuttx/irq.h>
 #include <nuttx/mutex.h>
 #include <nuttx/wqueue.h>
+#include <nuttx/mm/iob.h>
+#include <nuttx/net/net.h>
 #include <nuttx/net/netdev.h>
 #include <nuttx/net/ethernet.h>
 #include <nuttx/net/tun.h>
@@ -98,12 +100,6 @@
 #  define CONFIG_TUN_NINTERFACES 1
 #endif
 
-/* Make sure that packet buffers include in configured guard size and are an
- * even multiple of 16-bits in length.
- */
-
-#define NET_TUN_PKTSIZE ((CONFIG_NET_TUN_PKTSIZE + CONFIG_NET_GUARDSIZE + 1) & ~1)
-
 /* This is a helper pointer for accessing the contents of the Ethernet
  * header.
  */
@@ -137,8 +133,8 @@ struct tun_device_s
    * is assured only by the preceding wide data types.
    */
 
-  uint8_t           read_buf[NET_TUN_PKTSIZE];
-  uint8_t           write_buf[NET_TUN_PKTSIZE];
+  FAR struct iob_s *read_buf;
+  FAR struct iob_s *write_buf;
 
   /* This holds the information visible to the NuttX network */
 
@@ -310,8 +306,14 @@ static void tun_fd_transmit(FAR struct tun_device_s *priv)
 
 static int tun_txpoll(FAR struct net_driver_s *dev)
 {
+  FAR struct tun_device_s *priv = (FAR struct tun_device_s *)dev->d_private;
   int ret;
 
+  DEBUGASSERT(priv->read_buf == NULL);
+  priv->read_d_len = dev->d_len;
+  priv->read_buf   = dev->d_iob;
+  netdev_iob_clear(dev);
+
 #ifdef CONFIG_NET_ETHERNET
   if (dev->d_lltype == NET_LL_ETHERNET)
     {
@@ -358,7 +360,6 @@ static int tun_txpoll_tap(FAR struct net_driver_s *dev)
 
   /* Send the packet */
 
-  priv->read_d_len = priv->dev.d_len;
   tun_fd_transmit(priv);
 
   return 1;
@@ -394,7 +395,6 @@ static int tun_txpoll_tun(FAR struct net_driver_s *dev)
 {
   FAR struct tun_device_s *priv = (FAR struct tun_device_s *)dev->d_private;
 
-  priv->read_d_len = priv->dev.d_len;
   tun_fd_transmit(priv);
 
   return 1;
@@ -495,17 +495,6 @@ static void tun_net_receive_tap(FAR struct tun_device_s *priv)
     {
       arp_input(&priv->dev);
       NETDEV_RXARP(&priv->dev);
-
-      /* If the above function invocation resulted in data that should be
-       * sent out on the network, the field d_len will set to a value > 0.
-       */
-
-      if (priv->dev.d_len > 0)
-        {
-          priv->write_d_len = priv->dev.d_len;
-          tun_fd_transmit(priv);
-          priv->dev.d_len = 0;
-        }
     }
   else
 #endif
@@ -522,7 +511,10 @@ static void tun_net_receive_tap(FAR struct tun_device_s *priv)
     {
       /* And send the packet */
 
+      DEBUGASSERT(priv->write_buf == NULL);
       priv->write_d_len = priv->dev.d_len;
+      priv->write_buf   = priv->dev.d_iob;
+      netdev_iob_clear(&priv->dev);
       tun_fd_transmit(priv);
     }
 }
@@ -599,7 +591,10 @@ static void tun_net_receive_tun(FAR struct tun_device_s *priv)
 
   if (dev->d_len > 0)
     {
+      DEBUGASSERT(priv->write_buf == NULL);
       priv->write_d_len = dev->d_len;
+      priv->write_buf   = dev->d_iob;
+      netdev_iob_clear(dev);
       tun_fd_transmit(priv);
     }
 }
@@ -629,7 +624,6 @@ static void tun_txdone(FAR struct tun_device_s *priv)
 
   /* Then poll the network for new XMIT data */
 
-  priv->dev.d_buf = priv->read_buf;
   devif_poll(&priv->dev, tun_txpoll);
 }
 
@@ -751,7 +745,6 @@ static void tun_txavail_work(FAR void *arg)
     {
       /* Poll the network for new XMIT data */
 
-      priv->dev.d_buf = priv->read_buf;
       devif_poll(&priv->dev, tun_txpoll);
     }
 
@@ -965,6 +958,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer,
 {
   FAR struct tun_device_s *priv = filep->f_priv;
   ssize_t nwritten = 0;
+  uint8_t llhdrlen;
   int ret;
 
   if (priv == NULL || buflen > CONFIG_NET_TUN_PKTSIZE)
@@ -972,6 +966,8 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer,
       return -EINVAL;
     }
 
+  llhdrlen = NET_LL_HDRLEN(&priv->dev);
+
   for (; ; )
     {
       /* Write must return immediately if interrupted by a signal (or if the
@@ -988,10 +984,24 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer,
 
       if (priv->write_d_len == 0)
         {
-          memcpy(priv->write_buf, buffer, buflen);
-
           net_lock();
-          priv->dev.d_buf = priv->write_buf;
+          ret = netdev_iob_prepare(&priv->dev, false, 0);
+          if (ret < 0)
+            {
+              nwritten = (nwritten == 0) ? ret : nwritten;
+              net_unlock();
+              break;
+            }
+
+          ret = iob_trycopyin(priv->dev.d_iob, (FAR const uint8_t *)buffer,
+                              buflen, -llhdrlen, false);
+          if (ret < 0)
+            {
+              nwritten = (nwritten == 0) ? ret : nwritten;
+              net_unlock();
+              break;
+            }
+
           priv->dev.d_len = buflen;
 
           tun_net_receive(priv);
@@ -1027,6 +1037,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer,
 {
   FAR struct tun_device_s *priv = filep->f_priv;
   ssize_t nread = 0;
+  uint8_t llhdrlen;
   int ret;
 
   if (priv == NULL)
@@ -1034,6 +1045,8 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer,
       return -EINVAL;
     }
 
+  llhdrlen = NET_LL_HDRLEN(&priv->dev);
+
   for (; ; )
     {
       /* Read must return immediately if interrupted by a signal (or if the
@@ -1056,8 +1069,12 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer,
               break;
             }
 
-          memcpy(buffer, priv->write_buf, priv->write_d_len);
+          iob_copyout((FAR uint8_t *)buffer, priv->write_buf,
+                      priv->write_d_len, -llhdrlen);
           nread = priv->write_d_len;
+
+          iob_free_chain(priv->write_buf);
+          priv->write_buf   = NULL;
           priv->write_d_len = 0;
 
           NETDEV_TXDONE(&priv->dev);
@@ -1075,8 +1092,12 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer,
               break;
             }
 
-          memcpy(buffer, priv->read_buf, priv->read_d_len);
+          iob_copyout((FAR uint8_t *)buffer, priv->read_buf,
+                      priv->read_d_len, -llhdrlen);
           nread = priv->read_d_len;
+
+          iob_free_chain(priv->read_buf);
+          priv->read_buf   = NULL;
           priv->read_d_len = 0;
 
           net_lock();