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/13 08:41:19 UTC

[nuttx] 02/02: net/devif_poll: optimize device buffer alloc in txpoll

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 8a63d29c6edb3056bb2ab89e0eb16896bcf2d57c
Author: chao an <an...@xiaomi.com>
AuthorDate: Wed Jan 11 16:09:20 2023 +0800

    net/devif_poll: optimize device buffer alloc in txpoll
    
    Allocate the device buffer only if the protocol really need to send data.
    not all protocols require the driver to prepare additional iob before
    sending, especially UDP, each iob reserves l2/l3 header in advance
    after prepare write buffer, net device could reuse this entry to send directly
    
    Signed-off-by: chao an <an...@xiaomi.com>
---
 net/arp/arp_format.c            | 14 ++++++++++++--
 net/can/can_poll.c              |  5 ++---
 net/devif/devif_poll.c          | 16 ----------------
 net/devif/devif_send.c          | 11 +++++++++--
 net/icmp/icmp_poll.c            |  5 ++---
 net/icmpv6/icmpv6_autoconfig.c  |  7 +++++++
 net/icmpv6/icmpv6_neighbor.c    |  7 +++++++
 net/icmpv6/icmpv6_poll.c        |  5 ++---
 net/igmp/igmp_poll.c            |  8 ++------
 net/igmp/igmp_send.c            |  7 +++++++
 net/ipforward/ipfwd_forward.c   |  9 +++++----
 net/mld/mld_poll.c              |  5 ++---
 net/mld/mld_send.c              |  7 +++++++
 net/netdev/netdev_iob.c         |  1 +
 net/pkt/pkt_poll.c              |  5 ++---
 net/tcp/tcp_devpoll.c           |  7 +++++++
 net/udp/udp_devpoll.c           | 15 ++-------------
 net/udp/udp_sendto_buffered.c   | 21 ++++++++-------------
 net/udp/udp_sendto_unbuffered.c | 24 ++++++++++++------------
 19 files changed, 96 insertions(+), 83 deletions(-)

diff --git a/net/arp/arp_format.c b/net/arp/arp_format.c
index 6cca53a7f9..2b5db120bb 100644
--- a/net/arp/arp_format.c
+++ b/net/arp/arp_format.c
@@ -75,8 +75,18 @@
 
 void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr)
 {
-  FAR struct arp_hdr_s *arp = ARPBUF;
-  FAR struct eth_hdr_s *eth = ETHBUF;
+  FAR struct arp_hdr_s *arp;
+  FAR struct eth_hdr_s *eth;
+
+  /* Prepare device buffer before format arp */
+
+  if (netdev_iob_prepare(dev, false, 0) != OK)
+    {
+      return;
+    }
+
+  arp = ARPBUF;
+  eth = ETHBUF;
 
   /* Construct the ARP packet.  Creating both the Ethernet and ARP headers */
 
diff --git a/net/can/can_poll.c b/net/can/can_poll.c
index 1c7b95019d..2def213a5d 100644
--- a/net/can/can_poll.c
+++ b/net/can/can_poll.c
@@ -66,9 +66,8 @@ void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
 
   /* Setup for the application callback */
 
-  dev->d_appdata = IPBUF(0);
-  dev->d_len     = 0;
-  dev->d_sndlen  = 0;
+  dev->d_len    = 0;
+  dev->d_sndlen = 0;
 
   /* Perform the application callback */
 
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 4b77fbe218..2fdf462acb 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -821,13 +821,6 @@ static int devif_iob_poll(FAR struct net_driver_s *dev,
 {
   int bstop;
 
-  /* Device polling, prepare iob buffer */
-
-  if (netdev_iob_prepare(dev, false, 0) != OK)
-    {
-      return true;
-    }
-
   /* Perform all connections poll */
 
   bstop = devif_poll_connections(dev, callback);
@@ -920,15 +913,6 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
 
   do
     {
-      /* Device polling, prepare iob buffer */
-
-      if (netdev_iob_prepare(dev, false, 0) != OK)
-        {
-          nwarn("WARNING: IOB Prepare failed for dev %s!\n", dev->d_ifname);
-          bstop = true;
-          break;
-        }
-
       /* Perform all connections poll */
 
       bstop = devif_poll_connections(dev, devif_poll_callback);
diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c
index 5e076d0ff8..ea2d5cad41 100644
--- a/net/devif/devif_send.c
+++ b/net/devif/devif_send.c
@@ -78,12 +78,19 @@ void devif_send(FAR struct net_driver_s *dev, FAR const void *buf,
       return;
     }
 
-  iob_update_pktlen(dev->d_iob, offset);
-
   /* Copy in iob to target device buffer */
 
   if (len <= iob_navail(false) * CONFIG_IOB_BUFSIZE)
     {
+      /* Prepare device buffer before poll callback */
+
+      if (netdev_iob_prepare(dev, false, 0) != OK)
+        {
+          return;
+        }
+
+      iob_update_pktlen(dev->d_iob, offset);
+
       dev->d_sndlen = iob_trycopyin(dev->d_iob, buf, len, offset, false);
     }
   else
diff --git a/net/icmp/icmp_poll.c b/net/icmp/icmp_poll.c
index 290c129cd4..09d80d570f 100644
--- a/net/icmp/icmp_poll.c
+++ b/net/icmp/icmp_poll.c
@@ -66,9 +66,8 @@ void icmp_poll(FAR struct net_driver_s *dev, FAR struct icmp_conn_s *conn)
 
   /* Setup for the application callback */
 
-  dev->d_appdata = IPBUF(IPICMP_HDRLEN);
-  dev->d_len     = 0;
-  dev->d_sndlen  = 0;
+  dev->d_len    = 0;
+  dev->d_sndlen = 0;
 
   /* Perform the application callback */
 
diff --git a/net/icmpv6/icmpv6_autoconfig.c b/net/icmpv6/icmpv6_autoconfig.c
index 0d899ad4e1..a8021bd224 100644
--- a/net/icmpv6/icmpv6_autoconfig.c
+++ b/net/icmpv6/icmpv6_autoconfig.c
@@ -125,6 +125,13 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
           return flags;
         }
 
+      /* Prepare device buffer */
+
+      if (netdev_iob_prepare(dev, false, 0) != OK)
+        {
+          return flags;
+        }
+
       /* It looks like we are good to send the data.
        *
        * Copy the packet data into the device packet buffer and send it.
diff --git a/net/icmpv6/icmpv6_neighbor.c b/net/icmpv6/icmpv6_neighbor.c
index 9b2e4f18b4..1612865bad 100644
--- a/net/icmpv6/icmpv6_neighbor.c
+++ b/net/icmpv6/icmpv6_neighbor.c
@@ -109,6 +109,13 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
           return flags;
         }
 
+      /* Prepare device buffer */
+
+      if (netdev_iob_prepare(dev, false, 0) != OK)
+        {
+          return flags;
+        }
+
       /* It looks like we are good to send the data.
        *
        * Copy the packet data into the device packet buffer and send it.
diff --git a/net/icmpv6/icmpv6_poll.c b/net/icmpv6/icmpv6_poll.c
index 7da0cd005e..278c3f48b7 100644
--- a/net/icmpv6/icmpv6_poll.c
+++ b/net/icmpv6/icmpv6_poll.c
@@ -67,9 +67,8 @@ void icmpv6_poll(FAR struct net_driver_s *dev,
 
   /* Setup for the application callback */
 
-  dev->d_appdata = IPBUF(IPICMPv6_HDRLEN);
-  dev->d_len     = 0;
-  dev->d_sndlen  = 0;
+  dev->d_len    = 0;
+  dev->d_sndlen = 0;
 
   /* Perform the application callback */
 
diff --git a/net/igmp/igmp_poll.c b/net/igmp/igmp_poll.c
index 47ef3d34d6..b7f71f2fbe 100644
--- a/net/igmp/igmp_poll.c
+++ b/net/igmp/igmp_poll.c
@@ -151,15 +151,11 @@ static inline void igmp_sched_send(FAR struct net_driver_s *dev,
 void igmp_poll(FAR struct net_driver_s *dev)
 {
   FAR struct igmp_group_s *group;
-  uint16_t iphdrlen;
 
   /* Setup the poll operation */
 
-  iphdrlen       = IPv4_HDRLEN + RASIZE;
-
-  dev->d_appdata = IPBUF(iphdrlen + IGMP_HDRLEN);
-  dev->d_len     = 0;
-  dev->d_sndlen  = 0;
+  dev->d_len    = 0;
+  dev->d_sndlen = 0;
 
   /* Check each member of the group */
 
diff --git a/net/igmp/igmp_send.c b/net/igmp/igmp_send.c
index c15a695f77..d60a49a21f 100644
--- a/net/igmp/igmp_send.c
+++ b/net/igmp/igmp_send.c
@@ -109,6 +109,13 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
 
   ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
 
+  /* Prepare device buffer */
+
+  if (netdev_iob_prepare(dev, false, 0) != OK)
+    {
+      return;
+    }
+
   /* The IGMP header immediately follows the IP header */
 
   iphdrlen          = IPv4_HDRLEN + RASIZE;
diff --git a/net/ipforward/ipfwd_forward.c b/net/ipforward/ipfwd_forward.c
index 00d7034030..94a933c38a 100644
--- a/net/ipforward/ipfwd_forward.c
+++ b/net/ipforward/ipfwd_forward.c
@@ -161,6 +161,11 @@ static uint16_t ipfwd_eventhandler(FAR struct net_driver_s *dev,
 
       else
         {
+          /* Copy the user data into d_appdata and send it. */
+
+          devif_forward(fwd);
+          flags &= ~DEVPOLL_MASK;
+
 #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
           /* If both IPv4 and IPv6 support are enabled, then we will need to
            * select which one to use when generating the outgoing packet.
@@ -170,10 +175,6 @@ static uint16_t ipfwd_eventhandler(FAR struct net_driver_s *dev,
 
           forward_ipselect(fwd);
 #endif
-          /* Copy the user data into d_appdata and send it. */
-
-          devif_forward(fwd);
-          flags &= ~DEVPOLL_MASK;
         }
 
       /* Free the allocated callback structure */
diff --git a/net/mld/mld_poll.c b/net/mld/mld_poll.c
index d0cd926419..d706ffb29a 100644
--- a/net/mld/mld_poll.c
+++ b/net/mld/mld_poll.c
@@ -60,9 +60,8 @@ void mld_poll(FAR struct net_driver_s *dev)
 
   /* Setup the poll operation */
 
-  dev->d_appdata = IPBUF(IPv6_HDRLEN);
-  dev->d_len     = 0;
-  dev->d_sndlen  = 0;
+  dev->d_len    = 0;
+  dev->d_sndlen = 0;
 
   /* Check if a general query is pending */
 
diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c
index f3fab001d8..8364808f7c 100644
--- a/net/mld/mld_send.c
+++ b/net/mld/mld_send.c
@@ -96,6 +96,13 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
   DEBUGASSERT(dev != NULL);
   DEBUGASSERT(msgtype == MLD_SEND_GENQUERY || group != NULL);
 
+  /* Prepare device buffer */
+
+  if (netdev_iob_prepare(dev, false, 0) != OK)
+    {
+      return;
+    }
+
   /* Select IPv6 */
 
   IFF_SET_IPv6(dev->d_flags);
diff --git a/net/netdev/netdev_iob.c b/net/netdev/netdev_iob.c
index d6ebbd87de..f6159c4f54 100644
--- a/net/netdev/netdev_iob.c
+++ b/net/netdev/netdev_iob.c
@@ -69,6 +69,7 @@ int netdev_iob_prepare(FAR struct net_driver_s *dev, bool throttled,
 
   if (dev->d_iob == NULL)
     {
+      nwarn("WARNING: IOB Prepare failed for dev %s!\n", dev->d_ifname);
       return -ENOMEM;
     }
 
diff --git a/net/pkt/pkt_poll.c b/net/pkt/pkt_poll.c
index 7d6978fe84..6901ee324b 100644
--- a/net/pkt/pkt_poll.c
+++ b/net/pkt/pkt_poll.c
@@ -65,9 +65,8 @@ void pkt_poll(FAR struct net_driver_s *dev, FAR struct pkt_conn_s *conn)
     {
       /* Setup for the application callback */
 
-      dev->d_appdata = IPBUF(0);
-      dev->d_len     = 0;
-      dev->d_sndlen  = 0;
+      dev->d_len    = 0;
+      dev->d_sndlen = 0;
 
       /* Perform the application callback */
 
diff --git a/net/tcp/tcp_devpoll.c b/net/tcp/tcp_devpoll.c
index 51e022aa30..3d7206c9b4 100644
--- a/net/tcp/tcp_devpoll.c
+++ b/net/tcp/tcp_devpoll.c
@@ -87,6 +87,13 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
 
   DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
 
+  /* Prepare device buffer */
+
+  if (netdev_iob_prepare(dev, false, 0) != OK)
+    {
+      return;
+    }
+
   /* Discard any currently buffered data */
 
   if (conn->timeout)
diff --git a/net/udp/udp_devpoll.c b/net/udp/udp_devpoll.c
index 7796f8f5e1..d317147f9e 100644
--- a/net/udp/udp_devpoll.c
+++ b/net/udp/udp_devpoll.c
@@ -93,19 +93,8 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
 
   if (conn->lport != 0)
     {
-      /* Set up for the callback.  We can't know in advance if the
-       * application is going to send a IPv4 or an IPv6 packet, so this setup
-       * may not actually be used.
-       */
-
-#if defined(CONFIG_NET_IPv4)
-      udp_ipv4_select(dev);
-#else /* if defined(CONFIG_NET_IPv6) */
-      udp_ipv6_select(dev);
-#endif
-
-      dev->d_len     = 0;
-      dev->d_sndlen  = 0;
+      dev->d_len    = 0;
+      dev->d_sndlen = 0;
 
       /* Perform the application callback */
 
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index e5c36898fc..7263edb1c0 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -406,7 +406,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
     {
       uint16_t udpiplen = udpip_hdrsize(conn);
       FAR struct udp_wrbuffer_s *wrb;
-      size_t sndlen;
 
       /* Peek at the head of the write queue (but don't remove anything
        * from the write queue yet).  We know from the above test that
@@ -424,14 +423,20 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
 
       udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest);
 
+      /* Then set-up to send that amount of data with the offset
+       * corresponding to the size of the IP-dependent address structure.
+       */
+
+      netdev_iob_replace(dev, wrb->wb_iob);
+
       /* Get the amount of data that we can send in the next packet.
        * We will send either the remaining data in the buffer I/O
        * buffer chain, or as much as will fit given the MSS and current
        * window size.
        */
 
-      sndlen = wrb->wb_iob->io_pktlen - udpiplen;
-      ninfo("wrb=%p sndlen=%zu\n", wrb, sndlen);
+      dev->d_sndlen = wrb->wb_iob->io_pktlen - udpiplen;
+      ninfo("wrb=%p sndlen=%d\n", wrb, dev->d_sndlen);
 
 #ifdef NEED_IPDOMAIN_SUPPORT
       /* If both IPv4 and IPv6 support are enabled, then we will need to
@@ -443,16 +448,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
       sendto_ipselect(dev, conn);
 #endif
 
-      /* Release current device buffer and bypass the iob to l2 driver */
-
-      netdev_iob_release(dev);
-
-      /* Then set-up to send that amount of data with the offset
-       * corresponding to the size of the IP-dependent address structure.
-       */
-
-      devif_iob_send(dev, wrb->wb_iob, sndlen, 0, udpiplen);
-
       /* Free the write buffer at the head of the queue and attempt to
        * setup the next transfer.
        */
diff --git a/net/udp/udp_sendto_unbuffered.c b/net/udp/udp_sendto_unbuffered.c
index ae629bc91d..db1d6ad030 100644
--- a/net/udp/udp_sendto_unbuffered.c
+++ b/net/udp/udp_sendto_unbuffered.c
@@ -192,6 +192,15 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
 
       else
         {
+          /* Copy the user data into d_appdata and send it */
+
+          devif_send(dev, pstate->st_buffer,
+                     pstate->st_buflen, udpip_hdrsize(pstate->st_conn));
+          if (dev->d_sndlen == 0)
+            {
+              return flags;
+            }
+
 #ifdef NEED_IPDOMAIN_SUPPORT
           /* If both IPv4 and IPv6 support are enabled, then we will need to
            * select which one to use when generating the outgoing packet.
@@ -202,23 +211,14 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
           sendto_ipselect(dev, pstate);
 #endif
 
-          /* Copy the user data into d_appdata and send it */
-
-          devif_send(dev, pstate->st_buffer,
-                     pstate->st_buflen, udpip_hdrsize(pstate->st_conn));
-          if (dev->d_sndlen == 0)
-            {
-              return flags;
-            }
-
           pstate->st_sndlen = pstate->st_buflen;
         }
 
       /* Don't allow any further call backs. */
 
-      pstate->st_cb->flags   = 0;
-      pstate->st_cb->priv    = NULL;
-      pstate->st_cb->event   = NULL;
+      pstate->st_cb->flags = 0;
+      pstate->st_cb->priv  = NULL;
+      pstate->st_cb->event = NULL;
 
       /* Wake up the waiting thread */