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 2021/10/12 06:09:07 UTC

[incubator-nuttx] branch master updated: net/can, icmp, icmpv6, tcp, tcp_timer, udp: device should poll only those connections that are bound to the device. tcp_timer: eliminated false decrements of conn->timer in case of multiple network adapters. The false timer decrements sometimes provoked TCP spurious retransmissions due to premature timeouts.

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/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 1e25602  net/can,icmp,icmpv6,tcp,tcp_timer,udp: device should poll only those connections that are bound to the device. tcp_timer: eliminated false decrements of conn->timer in case of multiple network adapters. The false timer decrements sometimes provoked TCP spurious retransmissions due to premature timeouts.
1e25602 is described below

commit 1e2560267898f413c93c5fb616ddc5b1d4d07184
Author: Alexander Lunev <al...@mail.ru>
AuthorDate: Sat Oct 2 03:47:08 2021 +0300

    net/can,icmp,icmpv6,tcp,tcp_timer,udp: device should poll only those connections that are bound to the device.
    tcp_timer: eliminated false decrements of conn->timer in case of multiple network adapters.
    The false timer decrements sometimes provoked TCP spurious retransmissions due to premature timeouts.
---
 net/can/can_poll.c       |  29 ++---
 net/devif/devif_poll.c   | 101 +++++++++++-------
 net/icmp/icmp_poll.c     |   5 +
 net/icmpv6/icmpv6_poll.c |   6 ++
 net/tcp/tcp_devpoll.c    |  50 ++++-----
 net/tcp/tcp_timer.c      | 267 ++++++++++++++++++++++-------------------------
 net/udp/udp_devpoll.c    |  11 ++
 7 files changed, 247 insertions(+), 222 deletions(-)

diff --git a/net/can/can_poll.c b/net/can/can_poll.c
index c968fe2..3caed22 100644
--- a/net/can/can_poll.c
+++ b/net/can/can_poll.c
@@ -26,6 +26,7 @@
 #include <nuttx/config.h>
 #if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
 
+#include <assert.h>
 #include <debug.h>
 
 #include <nuttx/net/netconfig.h>
@@ -53,31 +54,31 @@
  *
  * Assumptions:
  *   The network is locked.
+ *   dev is not NULL.
+ *   conn is not NULL.
+ *   The connection (conn) is bound to the polling device (dev).
  *
  ****************************************************************************/
 
 void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
 {
-  /* Verify that the packet connection is valid */
+  DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
 
-  if (conn != NULL)
-    {
-      /* Setup for the application callback */
+  /* Setup for the application callback */
 
-      dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev)];
-      dev->d_len     = 0;
-      dev->d_sndlen  = 0;
+  dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev)];
+  dev->d_len     = 0;
+  dev->d_sndlen  = 0;
 
-      /* Perform the application callback */
+  /* Perform the application callback */
 
-      can_callback(dev, conn, CAN_POLL);
+  can_callback(dev, conn, CAN_POLL);
 
-      /* Check if the application has data to send */
+  /* Check if the application has data to send */
 
-      if (dev->d_sndlen > 0)
-        {
-          return;
-        }
+  if (dev->d_sndlen > 0)
+    {
+      return;
     }
 
   /* Make sure that d_len is zero meaning that there is nothing to be sent */
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 6865742..4b14c73 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -248,10 +248,12 @@ static int devif_poll_can_connections(FAR struct net_driver_s *dev,
 
   while (!bstop && (can_conn = can_nextconn(can_conn)))
     {
-      /* Perform the packet TX poll */
+      /* Skip connections that are bound to other polling devices */
 
       if (dev == can_conn->dev)
         {
+          /* Perform the packet TX poll */
+
           can_poll(dev, can_conn);
 
           /* Call back into the driver */
@@ -361,17 +363,22 @@ static inline int devif_poll_icmp(FAR struct net_driver_s *dev,
 
   while (!bstop && (conn = icmp_nextconn(conn)) != NULL)
     {
-      /* Perform the ICMP poll */
+      /* Skip ICMP connections that are bound to other polling devices */
 
-      icmp_poll(dev, conn);
+      if (dev == conn->dev)
+        {
+          /* Perform the ICMP poll */
 
-      /* Perform any necessary conversions on outgoing packets */
+          icmp_poll(dev, conn);
 
-      devif_packet_conversion(dev, DEVIF_ICMP);
+          /* Perform any necessary conversions on outgoing packets */
 
-      /* Call back into the driver */
+          devif_packet_conversion(dev, DEVIF_ICMP);
 
-      bstop = callback(dev);
+          /* Call back into the driver */
+
+          bstop = callback(dev);
+        }
     }
 
   return bstop;
@@ -393,27 +400,32 @@ static inline int devif_poll_icmpv6(FAR struct net_driver_s *dev,
   FAR struct icmpv6_conn_s *conn = NULL;
   int bstop = 0;
 
-  /* Traverse all of the allocated ICMPV6 connections and perform the poll
+  /* Traverse all of the allocated ICMPv6 connections and perform the poll
    * action.
    */
 
   do
     {
-      /* Perform the ICMPV6 poll
-       * Note: conn equal NULL in the first iteration means poll dev's
-       * callback list since icmpv6_autoconfig and icmpv6_neighbor still
-       * append it's callback into this list.
-       */
+      /* Skip ICMPv6 connections that are bound to other polling devices */
 
-      icmpv6_poll(dev, conn);
+      if (conn == NULL || dev == conn->dev)
+        {
+          /* Perform the ICMPV6 poll
+           * Note: conn equal NULL in the first iteration means poll dev's
+           * callback list since icmpv6_autoconfig and icmpv6_neighbor still
+           * append it's callback into this list.
+           */
 
-      /* Perform any necessary conversions on outgoing packets */
+          icmpv6_poll(dev, conn);
 
-      devif_packet_conversion(dev, DEVIF_ICMP6);
+          /* Perform any necessary conversions on outgoing packets */
 
-      /* Call back into the driver */
+          devif_packet_conversion(dev, DEVIF_ICMP6);
 
-      bstop = callback(dev);
+          /* Call back into the driver */
+
+          bstop = callback(dev);
+        }
     }
   while (!bstop && (conn = icmpv6_nextconn(conn)) != NULL);
 
@@ -533,17 +545,24 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
 
   while (!bstop && (conn = udp_nextconn(conn)))
     {
-      /* Perform the UDP TX poll */
+#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
+      /* Skip UDP connections that are bound to other polling devices */
 
-      udp_poll(dev, conn);
+      if (dev == conn->dev)
+#endif
+        {
+          /* Perform the UDP TX poll */
 
-      /* Perform any necessary conversions on outgoing packets */
+          udp_poll(dev, conn);
 
-      devif_packet_conversion(dev, DEVIF_UDP);
+          /* Perform any necessary conversions on outgoing packets */
 
-      /* Call back into the driver */
+          devif_packet_conversion(dev, DEVIF_UDP);
 
-      bstop = callback(dev);
+          /* Call back into the driver */
+
+          bstop = callback(dev);
+        }
     }
 
   return bstop;
@@ -573,17 +592,22 @@ static inline int devif_poll_tcp_connections(FAR struct net_driver_s *dev,
 
   while (!bstop && (conn = tcp_nextconn(conn)))
     {
-      /* Perform the TCP TX poll */
+      /* Skip TCP connections that are bound to other polling devices */
 
-      tcp_poll(dev, conn);
+      if (dev == conn->dev)
+        {
+          /* Perform the TCP TX poll */
 
-      /* Perform any necessary conversions on outgoing packets */
+          tcp_poll(dev, conn);
 
-      devif_packet_conversion(dev, DEVIF_TCP);
+          /* Perform any necessary conversions on outgoing packets */
 
-      /* Call back into the driver */
+          devif_packet_conversion(dev, DEVIF_TCP);
 
-      bstop = callback(dev);
+          /* Call back into the driver */
+
+          bstop = callback(dev);
+        }
     }
 
   return bstop;
@@ -619,17 +643,22 @@ static inline int devif_poll_tcp_timer(FAR struct net_driver_s *dev,
 
   while (!bstop && (conn = tcp_nextconn(conn)))
     {
-      /* Perform the TCP timer poll */
+      /* Skip TCP connections that are bound to other polling devices */
 
-      tcp_timer(dev, conn, hsec);
+      if (dev == conn->dev)
+        {
+          /* Perform the TCP timer poll */
 
-      /* Perform any necessary conversions on outgoing packets */
+          tcp_timer(dev, conn, hsec);
 
-      devif_packet_conversion(dev, DEVIF_TCP);
+          /* Perform any necessary conversions on outgoing packets */
 
-      /* Call back into the driver */
+          devif_packet_conversion(dev, DEVIF_TCP);
 
-      bstop = callback(dev);
+          /* Call back into the driver */
+
+          bstop = callback(dev);
+        }
     }
 
   return bstop;
diff --git a/net/icmp/icmp_poll.c b/net/icmp/icmp_poll.c
index f0f76c6..bd0f761 100644
--- a/net/icmp/icmp_poll.c
+++ b/net/icmp/icmp_poll.c
@@ -54,11 +54,16 @@
  *
  * Assumptions:
  *   The network is locked.
+ *   dev is not NULL.
+ *   conn is not NULL.
+ *   The connection (conn) is bound to the polling device (dev).
  *
  ****************************************************************************/
 
 void icmp_poll(FAR struct net_driver_s *dev, FAR struct icmp_conn_s *conn)
 {
+  DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
+
   /* Setup for the application callback */
 
   dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPICMP_HDRLEN];
diff --git a/net/icmpv6/icmpv6_poll.c b/net/icmpv6/icmpv6_poll.c
index 63d89f6..5124739 100644
--- a/net/icmpv6/icmpv6_poll.c
+++ b/net/icmpv6/icmpv6_poll.c
@@ -53,12 +53,18 @@
  *
  * Assumptions:
  *   The network is locked.
+ *   dev is not NULL.
+ *   conn may be NULL.
+ *   The connection (conn), if not NULL, is bound to
+ *   the polling device (dev).
  *
  ****************************************************************************/
 
 void icmpv6_poll(FAR struct net_driver_s *dev,
                  FAR struct icmpv6_conn_s *conn)
 {
+  DEBUGASSERT(dev != NULL && (conn == NULL || dev == conn->dev));
+
   /* Setup for the application callback */
 
   dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPICMPv6_HDRLEN];
diff --git a/net/tcp/tcp_devpoll.c b/net/tcp/tcp_devpoll.c
index e1b7da2..30fd278 100644
--- a/net/tcp/tcp_devpoll.c
+++ b/net/tcp/tcp_devpoll.c
@@ -74,7 +74,10 @@
  *   None
  *
  * Assumptions:
- *   Called with the network locked.
+ *   It is called with the network locked.
+ *   dev is not NULL.
+ *   conn is not NULL.
+ *   The connection (conn) is bound to the polling device (dev).
  *
  ****************************************************************************/
 
@@ -82,6 +85,8 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
 {
   uint16_t result;
 
+  DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
+
   /* Discard any currently buffered data */
 
   dev->d_len     = 0;
@@ -91,43 +96,34 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
 
   if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
     {
-      /* The TCP connection is established and, hence, should be bound
-       * to a device. Make sure that the polling device is the one that
-       * we are bound to.
+      /* 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.
        */
 
-      DEBUGASSERT(conn->dev != NULL);
-      if (dev == conn->dev)
-        {
-          /* 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_IPv6) && defined(CONFIG_NET_IPv4)
-          if (conn->domain == PF_INET)
-            {
-              tcp_ipv4_select(dev);
-            }
-          else
-            {
-              tcp_ipv6_select(dev);
-            }
+      if (conn->domain == PF_INET)
+        {
+          tcp_ipv4_select(dev);
+        }
+      else
+        {
+          tcp_ipv6_select(dev);
+        }
 
 #elif defined(CONFIG_NET_IPv4)
-          tcp_ipv4_select(dev);
+      tcp_ipv4_select(dev);
 
 #else /* if defined(CONFIG_NET_IPv6) */
-          tcp_ipv6_select(dev);
+      tcp_ipv6_select(dev);
 #endif
-          /* Perform the callback */
+      /* Perform the callback */
 
-          result = tcp_callback(dev, conn, TCP_POLL);
+      result = tcp_callback(dev, conn, TCP_POLL);
 
-          /* Handle the callback response */
+      /* Handle the callback response */
 
-          tcp_appsend(dev, conn, result);
-        }
+      tcp_appsend(dev, conn, result);
     }
 }
 
diff --git a/net/tcp/tcp_timer.c b/net/tcp/tcp_timer.c
index 4e8fc13..7ecb987 100644
--- a/net/tcp/tcp_timer.c
+++ b/net/tcp/tcp_timer.c
@@ -94,6 +94,9 @@
  *
  * Assumptions:
  *   The network is locked.
+ *   dev is not NULL.
+ *   conn is not NULL.
+ *   The connection (conn) is bound to the polling device (dev).
  *
  ****************************************************************************/
 
@@ -103,6 +106,14 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   uint16_t result;
   uint8_t hdrlen;
 
+  /* NOTE: It is important to decrease conn->timer at "hsec" pace,
+   * not faster. Excessive (false) decrements of conn->timer are not allowed
+   * here. Otherwise, it breaks TCP timings and leads to TCP spurious
+   * retransmissions and other issues due to premature timeouts.
+   */
+
+  DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
+
   /* 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.  Furthermore, the TCP logic is required to call
@@ -140,6 +151,13 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   dev->d_len    = 0;
   dev->d_sndlen = 0;
 
+  if (conn->tcpstateflags == TCP_CLOSED)
+    {
+      /* Nothing to be done */
+
+      return;
+    }
+
   /* Check if the connection is in a state in which we simply wait
    * for the connection to time out. If so, we increase the
    * connection's timer and remove the connection if it times
@@ -162,30 +180,13 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
           /* Set the timer to the maximum value */
 
           conn->timer = TCP_TIME_WAIT_TIMEOUT * HSEC_PER_SEC;
+          conn->tcpstateflags = TCP_CLOSED;
 
-          /* The TCP connection was established and, hence, should be bound
-           * to a device. Make sure that the polling device is the one that
-           * we are bound to.
-           *
-           * If not, then we will catch the timeout on the next poll from
-           * the correct device.
-           */
-
-          DEBUGASSERT(conn->dev != NULL);
-          if (dev != conn->dev)
-            {
-              ninfo("TCP: TCP_CLOSED pending\n");
-            }
-          else
-            {
-              conn->tcpstateflags = TCP_CLOSED;
-
-              /* Notify upper layers about the timeout */
+          /* Notify upper layers about the timeout */
 
-              tcp_callback(dev, conn, TCP_TIMEDOUT);
+          tcp_callback(dev, conn, TCP_TIMEDOUT);
 
-              ninfo("TCP state: TCP_CLOSED\n");
-            }
+          ninfo("TCP state: TCP_CLOSED\n");
         }
       else
         {
@@ -217,21 +218,6 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
 
               conn->timer = 0;
 
-              /* The TCP is connected and, hence, should be bound to a
-               * device. Make sure that the polling device is the one that
-               * we are bound to.
-               *
-               * If not, then we will catch the timeout on the next poll
-               * from the correct device.
-               */
-
-              DEBUGASSERT(conn->dev != NULL);
-              if (dev != conn->dev)
-                {
-                  ninfo("TCP: TCP_CLOSED pending\n");
-                  goto done;
-                }
-
               /* Check for a timeout on connection in the TCP_SYN_RCVD state.
                * On such timeouts, we would normally resend the SYNACK until
                * the ACK is received, completing the 3-way handshake.  But if
@@ -370,157 +356,148 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
 
       else if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
         {
-          /* The TCP connection is established and, hence, should be bound
-           * to a device. Make sure that the polling device is the one that
-           * we are bound to.
-           */
+#ifdef CONFIG_NET_TCP_KEEPALIVE
+          /* Is this an established connected with KeepAlive enabled? */
 
-          DEBUGASSERT(conn->dev != NULL);
-          if (dev == conn->dev)
+          if (conn->keepalive)
             {
-#ifdef CONFIG_NET_TCP_KEEPALIVE
-              /* Is this an established connected with KeepAlive enabled? */
+              socktimeo_t timeo;
+              uint32_t saveseq;
 
-              if (conn->keepalive)
+              /* If this is the first probe, then the keepstart time is
+               * the time that the last ACK or data was received from the
+               * remote.
+               *
+               * On subsequent retries, keepstart is the time that the
+               * last probe was sent.
+               */
+
+              if (conn->keepretries > 0)
                 {
-                  socktimeo_t timeo;
-                  uint32_t saveseq;
-
-                  /* If this is the first probe, then the keepstart time is
-                   * the time that the last ACK or data was received from the
-                   * remote.
-                   *
-                   * On subsequent retries, keepstart is the time that the
-                   * last probe was sent.
-                   */
+                  timeo = (socktimeo_t)conn->keepintvl;
+                }
+              else
+                {
+                  timeo = (socktimeo_t)conn->keepidle;
+                }
 
-                  if (conn->keepretries > 0)
-                    {
-                      timeo = (socktimeo_t)conn->keepintvl;
-                    }
-                  else
-                    {
-                      timeo = (socktimeo_t)conn->keepidle;
-                    }
+              /* Yes... has the idle period elapsed with no data or ACK
+               * received from the remote peer?
+               */
 
-                  /* Yes... has the idle period elapsed with no data or ACK
-                   * received from the remote peer?
-                   */
+              if (net_timeo(conn->keeptime, timeo))
+                {
+                  /* Yes.. Has the retry count expired? */
 
-                  if (net_timeo(conn->keeptime, timeo))
+                  if (conn->keepretries >= conn->keepcnt)
                     {
-                      /* Yes.. Has the retry count expired? */
-
-                      if (conn->keepretries >= conn->keepcnt)
-                        {
-                          /* Yes... stop the network monitor, closing the
-                           * connection and all sockets associated with the
-                           * connection.
-                           */
+                      /* Yes... stop the network monitor, closing the
+                       * connection and all sockets associated with the
+                       * connection.
+                       */
 
-                          tcp_stop_monitor(conn, TCP_ABORT);
-                        }
-                      else
-                        {
-                          unsigned int tcpiplen;
+                      tcp_stop_monitor(conn, TCP_ABORT);
+                    }
+                  else
+                    {
+                      unsigned int tcpiplen;
 
-                          /* No.. we need to send another probe.
-                           * Get the size of the IP and TCP header.
-                           */
+                      /* No.. we need to send another probe.
+                       * Get the size of the IP and TCP header.
+                       */
 
 #ifdef CONFIG_NET_IPv4
 #ifdef CONFIG_NET_IPv6
-                          if (conn->domain == PF_INET)
+                      if (conn->domain == PF_INET)
 #endif
-                            {
-                              tcpiplen = IPv4_HDRLEN + TCP_HDRLEN;
-                            }
+                        {
+                          tcpiplen = IPv4_HDRLEN + TCP_HDRLEN;
+                        }
 #endif
 #ifdef CONFIG_NET_IPv6
 #ifdef CONFIG_NET_IPv4
-                          else
+                      else
 #endif
-                            {
-                              tcpiplen = IPv6_HDRLEN + TCP_HDRLEN;
-                            }
+                        {
+                          tcpiplen = IPv6_HDRLEN + TCP_HDRLEN;
+                        }
 #endif
 
-                          /* And send the probe.
-                           * The packet we send must have these properties:
-                           *
-                           *   - TCP_ACK flag (only) is set.
-                           *   - Sequence number is the sequence number of
-                           *     previously ACKed data, i.e., the expected
-                           *     sequence number minus one.
-                           *
-                           * tcp_send() will send the TCP sequence number as
-                           * conn->sndseq.  Rather than creating a new
-                           * interface, we spoof tcp_end() here:
-                           */
+                      /* And send the probe.
+                       * The packet we send must have these properties:
+                       *
+                       *   - TCP_ACK flag (only) is set.
+                       *   - Sequence number is the sequence number of
+                       *     previously ACKed data, i.e., the expected
+                       *     sequence number minus one.
+                       *
+                       * tcp_send() will send the TCP sequence number as
+                       * conn->sndseq.  Rather than creating a new
+                       * interface, we spoof tcp_end() here:
+                       */
 
-                          saveseq = tcp_getsequence(conn->sndseq);
-                          tcp_setsequence(conn->sndseq, saveseq - 1);
+                      saveseq = tcp_getsequence(conn->sndseq);
+                      tcp_setsequence(conn->sndseq, saveseq - 1);
 
-                          tcp_send(dev, conn, TCP_ACK, tcpiplen);
+                      tcp_send(dev, conn, TCP_ACK, tcpiplen);
 
-                          tcp_setsequence(conn->sndseq, saveseq);
+                      tcp_setsequence(conn->sndseq, saveseq);
 
 #ifdef CONFIG_NET_TCP_WRITE_BUFFERS
-                          /* Increment the un-ACKed sequence number */
+                      /* Increment the un-ACKed sequence number */
 
-                          conn->sndseq_max++;
+                      conn->sndseq_max++;
 #endif
-                          /* Update for the next probe */
-
-                          conn->keeptime = clock_systime_ticks();
-                          conn->keepretries++;
-                        }
+                      /* Update for the next probe */
 
-                      goto done;
+                      conn->keeptime = clock_systime_ticks();
+                      conn->keepretries++;
                     }
+
+                  goto done;
                 }
+            }
 #endif
 
 #ifdef CONFIG_NET_TCP_DELAYED_ACK
-              /* Handle delayed acknowledgments.  Is there a segment with a
-               * delayed acknowledgment?
-               */
+          /* Handle delayed acknowledgments.  Is there a segment with a
+           * delayed acknowledgment?
+           */
 
-              if (conn->rx_unackseg > 0)
-                {
-                  /* Increment the ACK delay. */
+          if (conn->rx_unackseg > 0)
+            {
+              /* Increment the ACK delay. */
 
-                  conn->rx_acktimer += hsec;
+              conn->rx_acktimer += hsec;
 
-                  /* Per RFC 1122:  "...an ACK should not be excessively
-                   * delayed; in particular, the delay must be less than
-                   * 0.5 seconds..."
-                   */
+              /* Per RFC 1122:  "...an ACK should not be excessively
+               * delayed; in particular, the delay must be less than
+               * 0.5 seconds..."
+               */
 
-                  if (conn->rx_acktimer >= ACK_DELAY)
-                    {
-                      /* Reset the delayed ACK state and send the ACK
-                       * packet.
-                       */
+              if (conn->rx_acktimer >= ACK_DELAY)
+                {
+                  /* Reset the delayed ACK state and send the ACK
+                   * packet.
+                   */
 
-                      conn->rx_unackseg = 0;
-                      conn->rx_acktimer = 0;
-                      tcp_synack(dev, conn, TCP_ACK);
-                      goto done;
-                    }
+                  conn->rx_unackseg = 0;
+                  conn->rx_acktimer = 0;
+                  tcp_synack(dev, conn, TCP_ACK);
+                  goto done;
                 }
+            }
 #endif
 
-              /* There was no need for a retransmission and there was no
-               * need to probe the remote peer and there was no need to
-               * send a delayed ACK.  We poll the application for new
-               * outgoing data.
-               */
+          /* There was no need for a retransmission and there was no
+           * need to probe the remote peer and there was no need to
+           * send a delayed ACK.  We poll the application for new
+           * outgoing data.
+           */
 
-              result = tcp_callback(dev, conn, TCP_POLL);
-              tcp_appsend(dev, conn, result);
-              goto done;
-            }
+          result = tcp_callback(dev, conn, TCP_POLL);
+          tcp_appsend(dev, conn, result);
+          goto done;
         }
     }
 
diff --git a/net/udp/udp_devpoll.c b/net/udp/udp_devpoll.c
index 92eaf04..7796f8f 100644
--- a/net/udp/udp_devpoll.c
+++ b/net/udp/udp_devpoll.c
@@ -45,6 +45,7 @@
 #include <nuttx/config.h>
 #if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
 
+#include <assert.h>
 #include <debug.h>
 
 #include <nuttx/net/netconfig.h>
@@ -73,11 +74,21 @@
  *
  * Assumptions:
  *   The network is locked.
+ *   dev is not NULL.
+ *   conn is not NULL.
+ *   The connection (conn) is bound to the polling device (dev) in case of
+ *   enabled CONFIG_NET_UDP_WRITE_BUFFERS option.
  *
  ****************************************************************************/
 
 void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
 {
+  DEBUGASSERT(dev != NULL && conn != NULL);
+
+#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
+  DEBUGASSERT(dev == conn->dev);
+#endif
+
   /* Verify that the UDP connection is valid */
 
   if (conn->lport != 0)