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/07/21 03:25:36 UTC

[incubator-nuttx] branch master updated (011c938 -> 7d4502a)

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

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


    from 011c938  Remove xtensa_backtrace.S reference from esp32s2 as well
     new f52757f  net/wrb: add tcp/udp_inqueue_wrb_size() interface
     new 7d4502a  net/socket: add SO_SNDBUF support

The 2 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:
 include/nuttx/net/netconfig.h |  4 ++
 net/Kconfig                   |  7 ++++
 net/socket/setsockopt.c       | 63 +++++++++++++++++++++++++++-
 net/tcp/tcp.h                 | 23 +++++++++++
 net/tcp/tcp_conn.c            | 13 ++++++
 net/tcp/tcp_send_buffered.c   | 96 +++++++++++++++++++++++++++++++++++++++++++
 net/udp/udp.h                 | 23 +++++++++++
 net/udp/udp_conn.c            | 13 ++++++
 net/udp/udp_sendto_buffered.c | 85 ++++++++++++++++++++++++++++++++++++++
 9 files changed, 326 insertions(+), 1 deletion(-)

[incubator-nuttx] 02/02: net/socket: add SO_SNDBUF support

Posted by xi...@apache.org.
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

commit 7d4502aca61d3e760f3af0868efe800e864f3bf2
Author: chao.an <an...@xiaomi.com>
AuthorDate: Mon Jul 19 21:45:46 2021 +0800

    net/socket: add SO_SNDBUF support
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/nuttx/net/netconfig.h |  4 +++
 net/Kconfig                   |  7 +++++
 net/socket/setsockopt.c       | 63 ++++++++++++++++++++++++++++++++++++++++++-
 net/tcp/tcp.h                 | 23 ++++++++++++++++
 net/tcp/tcp_conn.c            | 13 +++++++++
 net/tcp/tcp_send_buffered.c   | 58 +++++++++++++++++++++++++++++++++++++++
 net/udp/udp.h                 | 23 ++++++++++++++++
 net/udp/udp_conn.c            | 13 +++++++++
 net/udp/udp_sendto_buffered.c | 53 ++++++++++++++++++++++++++++++++++++
 9 files changed, 256 insertions(+), 1 deletion(-)

diff --git a/include/nuttx/net/netconfig.h b/include/nuttx/net/netconfig.h
index adeb7ed..af1c439 100644
--- a/include/nuttx/net/netconfig.h
+++ b/include/nuttx/net/netconfig.h
@@ -201,6 +201,10 @@
 #  define NET_LO_PKTSIZE        CONFIG_NET_LOOPBACK_PKTSIZE
 #endif
 
+#ifndef CONFIG_NET_SEND_BUFSIZE
+#define CONFIG_NET_SEND_BUFSIZE 0
+#endif
+
 /* Layer 3/4 Configuration Options ******************************************/
 
 /* IP configuration options */
diff --git a/net/Kconfig b/net/Kconfig
index 083e6e1..481fa65 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -123,6 +123,13 @@ config NET_RECV_BUFSIZE
 	---help---
 		This is the default value for receive buffer size.
 
+config NET_SEND_BUFSIZE
+	int "Net Send buffer size"
+	depends on NET_TCP_WRITE_BUFFERS || NET_UDP_WRITE_BUFFERS
+	default 0
+	---help---
+		This is the default value for send buffer size.
+
 endmenu # Driver buffer configuration
 
 menu "Link layer support"
diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c
index 6e424ca..e9f87ac 100644
--- a/net/socket/setsockopt.c
+++ b/net/socket/setsockopt.c
@@ -196,6 +196,68 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
           return OK;
         }
 #endif
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      case SO_SNDBUF:     /* Sets send buffer size */
+        {
+          int buffersize;
+
+          /* Verify that option is the size of an 'int'.  Should also check
+           * that 'value' is properly aligned for an 'int'
+           */
+
+          if (value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+          /* Get the value.  Is the option being set or cleared? */
+
+          buffersize = *(FAR int *)value;
+
+          if (buffersize < 0 || buffersize > INT_MAX)
+            {
+              return -EINVAL;
+            }
+
+          net_lock();
+
+#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
+          if (psock->s_type == SOCK_STREAM)
+            {
+              FAR struct tcp_conn_s *conn;
+
+              conn = (FAR struct tcp_conn_s *)psock->s_conn;
+
+              /* Save the send buffer size */
+
+              conn->snd_bufs = buffersize;
+            }
+          else
+#endif
+#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
+          if (psock->s_type == SOCK_DGRAM)
+            {
+              FAR struct udp_conn_s *conn;
+
+              conn = (FAR struct udp_conn_s *)psock->s_conn;
+
+              /* Save the send buffer size */
+
+              conn->sndbufs = buffersize;
+            }
+          else
+#endif
+            {
+              net_unlock();
+              return -ENOPROTOOPT;
+            }
+
+          net_unlock();
+
+          return OK;
+        }
+#endif
     }
 
 #ifdef CONFIG_NET_USRSOCK
@@ -337,7 +399,6 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
       /* The following are not yet implemented */
 
       case SO_RCVLOWAT:   /* Sets the minimum number of bytes to input */
-      case SO_SNDBUF:     /* Sets send buffer size */
       case SO_SNDLOWAT:   /* Sets the minimum number of bytes to output */
 
       /* There options are only valid when used with getopt */
diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h
index 716e995..d80567c 100644
--- a/net/tcp/tcp.h
+++ b/net/tcp/tcp.h
@@ -31,6 +31,7 @@
 #include <queue.h>
 
 #include <nuttx/clock.h>
+#include <nuttx/semaphore.h>
 #include <nuttx/mm/iob.h>
 #include <nuttx/net/ip.h>
 
@@ -204,6 +205,10 @@ struct tcp_conn_s
 #if CONFIG_NET_RECV_BUFSIZE > 0
   int32_t  rcv_bufs;      /* Maximum amount of bytes queued in recv */
 #endif
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  int32_t  snd_bufs;      /* Maximum amount of bytes queued in send */
+  sem_t    snd_sem;       /* Semaphore signals send completion */
+#endif
 #ifdef CONFIG_NET_TCP_WRITE_BUFFERS
   uint32_t tx_unacked;    /* Number bytes sent but not yet ACKed */
 #else
@@ -1888,6 +1893,24 @@ int tcp_txdrain(FAR struct socket *psock, unsigned int timeout);
 int tcp_ioctl(FAR struct tcp_conn_s *conn, int cmd,
               FAR void *arg, size_t arglen);
 
+/****************************************************************************
+ * Name: tcp_sendbuffer_notify
+ *
+ * Description:
+ *   Notify the send buffer semaphore
+ *
+ * Input Parameters:
+ *   conn - The TCP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+void tcp_sendbuffer_notify(FAR struct tcp_conn_s *conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c
index f5ef61d..fbcfb52 100644
--- a/net/tcp/tcp_conn.c
+++ b/net/tcp/tcp_conn.c
@@ -676,6 +676,12 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain)
 #if CONFIG_NET_RECV_BUFSIZE > 0
       conn->rcv_bufs      = CONFIG_NET_RECV_BUFSIZE;
 #endif
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      conn->snd_bufs      = CONFIG_NET_SEND_BUFSIZE;
+
+      nxsem_init(&conn->snd_sem, 0, 0);
+      nxsem_set_protocol(&conn->snd_sem, SEM_PRIO_NONE);
+#endif
     }
 
   return conn;
@@ -746,6 +752,13 @@ void tcp_free(FAR struct tcp_conn_s *conn)
     {
       tcp_wrbuffer_release(wrbuffer);
     }
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  /* Notify the send buffer available */
+
+  tcp_sendbuffer_notify(conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #endif
 
 #ifdef CONFIG_NET_TCPBACKLOG
diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c
index 364f24f..2743dca 100644
--- a/net/tcp/tcp_send_buffered.c
+++ b/net/tcp/tcp_send_buffered.c
@@ -108,6 +108,7 @@
  *
  ****************************************************************************/
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
 static uint32_t tcp_inqueue_wrb_size(FAR struct tcp_conn_s *conn)
 {
   FAR struct tcp_wrbuffer_s *wrb;
@@ -131,6 +132,7 @@ static uint32_t tcp_inqueue_wrb_size(FAR struct tcp_conn_s *conn)
 
   return total;
 }
+#endif /* CONFIG_NET_SEND_BUFSIZE */
 
 /****************************************************************************
  * Name: psock_insert_segment
@@ -258,6 +260,12 @@ static inline void psock_lost_connection(FAR struct socket *psock,
           tcp_wrbuffer_release((FAR struct tcp_wrbuffer_s *)entry);
         }
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      /* Notify the send buffer available */
+
+      tcp_sendbuffer_notify(conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
       /* Reset write buffering variables */
 
       sq_init(&conn->unacked_q);
@@ -741,6 +749,12 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
         }
     }
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  /* Notify the send buffer available if wrbbuffer drained */
+
+  tcp_sendbuffer_notify(conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
   /* Check if the outgoing packet is available (it may have been claimed
    * by a sendto event serving a different thread).
    */
@@ -1098,6 +1112,23 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
       psock->s_sndcb->priv  = (FAR void *)psock;
       psock->s_sndcb->event = psock_send_eventhandler;
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      /* If the send buffer size exceeds the send limit,
+       * wait for the write buffer to be released
+       */
+
+      while (tcp_inqueue_wrb_size(conn) >= conn->snd_bufs)
+        {
+          if (nonblock)
+            {
+              ret = -EAGAIN;
+              goto errout_with_lock;
+            }
+
+          net_lockedwait_uninterruptible(&conn->snd_sem);
+        }
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
       /* Allocate a write buffer.  Careful, the network will be momentarily
        * unlocked here.
        */
@@ -1355,4 +1386,31 @@ int psock_tcp_cansend(FAR struct socket *psock)
   return OK;
 }
 
+/****************************************************************************
+ * Name: tcp_sendbuffer_notify
+ *
+ * Description:
+ *   Notify the send buffer semaphore
+ *
+ * Input Parameters:
+ *   conn - The TCP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+void tcp_sendbuffer_notify(FAR struct tcp_conn_s *conn)
+{
+  int val = 0;
+
+  nxsem_get_value(&conn->snd_sem, &val);
+  if (val < 0)
+    {
+      nxsem_post(&conn->snd_sem);
+    }
+}
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */
diff --git a/net/udp/udp.h b/net/udp/udp.h
index 71a4b2e..fef9c9f 100644
--- a/net/udp/udp.h
+++ b/net/udp/udp.h
@@ -31,6 +31,7 @@
 #include <sys/socket.h>
 #include <queue.h>
 
+#include <nuttx/semaphore.h>
 #include <nuttx/net/ip.h>
 #include <nuttx/mm/iob.h>
 
@@ -123,6 +124,10 @@ struct udp_conn_s
 #if CONFIG_NET_RECV_BUFSIZE > 0
   int32_t  rcvbufs;       /* Maximum amount of bytes queued in recv */
 #endif
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  int32_t  sndbufs;       /* Maximum amount of bytes queued in send */
+  sem_t    sndsem;        /* Semaphore signals send completion */
+#endif
 
   /* Read-ahead buffering.
    *
@@ -889,6 +894,24 @@ int udp_txdrain(FAR struct socket *psock, unsigned int timeout);
 int udp_ioctl(FAR struct udp_conn_s *conn,
               int cmd, FAR void *arg, size_t arglen);
 
+/****************************************************************************
+ * Name: udp_sendbuffer_notify
+ *
+ * Description:
+ *   Notify the send buffer semaphore
+ *
+ * Input Parameters:
+ *   conn - The UDP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+void udp_sendbuffer_notify(FAR struct udp_conn_s *conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c
index 1aba26c..acb4377 100644
--- a/net/udp/udp_conn.c
+++ b/net/udp/udp_conn.c
@@ -588,6 +588,12 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
 #if CONFIG_NET_RECV_BUFSIZE > 0
       conn->rcvbufs = CONFIG_NET_RECV_BUFSIZE;
 #endif
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      conn->sndbufs = CONFIG_NET_SEND_BUFSIZE;
+
+      nxsem_init(&conn->sndsem, 0, 0);
+      nxsem_set_protocol(&conn->sndsem, SEM_PRIO_NONE);
+#endif
 
 #ifdef CONFIG_NET_UDP_WRITE_BUFFERS
       /* Initialize the write buffer lists */
@@ -641,6 +647,13 @@ void udp_free(FAR struct udp_conn_s *conn)
     {
       udp_wrbuffer_release(wrbuffer);
     }
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  /* Notify the send buffer available */
+
+  udp_sendbuffer_notify(conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #endif
 
   /* Free the connection */
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index 899b3d5..9f8840b 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -119,6 +119,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
  *
  ****************************************************************************/
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
 static uint32_t udp_inqueue_wrb_size(FAR struct udp_conn_s *conn)
 {
   FAR struct udp_wrbuffer_s *wrb;
@@ -136,6 +137,7 @@ static uint32_t udp_inqueue_wrb_size(FAR struct udp_conn_s *conn)
 
   return total;
 }
+#endif /* CONFIG_NET_SEND_BUFSIZE */
 
 /****************************************************************************
  * Name: sendto_writebuffer_release
@@ -202,6 +204,12 @@ static void sendto_writebuffer_release(FAR struct socket *psock,
         }
     }
   while (wrb != NULL && ret < 0);
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+  /* Notify the send buffer available if wrbbuffer drained */
+
+  udp_sendbuffer_notify(conn);
+#endif /* CONFIG_NET_SEND_BUFSIZE */
 }
 
 /****************************************************************************
@@ -657,6 +665,23 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
     {
       net_lock();
 
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      /* If the send buffer size exceeds the send limit,
+       * wait for the write buffer to be released
+       */
+
+      while (udp_inqueue_wrb_size(conn) + len > conn->sndbufs)
+        {
+          if (nonblock)
+            {
+              ret = -EAGAIN;
+              goto errout_with_lock;
+            }
+
+          net_lockedwait_uninterruptible(&conn->sndsem);
+        }
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
       /* Allocate a write buffer.  Careful, the network will be momentarily
        * unlocked here.
        */
@@ -861,4 +886,32 @@ int psock_udp_cansend(FAR struct socket *psock)
 
   return OK;
 }
+
+/****************************************************************************
+ * Name: udp_sendbuffer_notify
+ *
+ * Description:
+ *   Notify the send buffer semaphore
+ *
+ * Input Parameters:
+ *   conn - The UDP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+void udp_sendbuffer_notify(FAR struct udp_conn_s *conn)
+{
+  int val = 0;
+
+  nxsem_get_value(&conn->sndsem, &val);
+  if (val < 0)
+    {
+      nxsem_post(&conn->sndsem);
+    }
+}
+#endif /* CONFIG_NET_SEND_BUFSIZE */
+
 #endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */

[incubator-nuttx] 01/02: net/wrb: add tcp/udp_inqueue_wrb_size() interface

Posted by xi...@apache.org.
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

commit f52757f90a3de3da57af5ea6d7e8ad7993236dc0
Author: chao.an <an...@xiaomi.com>
AuthorDate: Wed Jul 14 17:30:44 2021 +0800

    net/wrb: add tcp/udp_inqueue_wrb_size() interface
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/tcp/tcp_send_buffered.c   | 38 ++++++++++++++++++++++++++++++++++++++
 net/udp/udp_sendto_buffered.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c
index 5740ad4..364f24f 100644
--- a/net/tcp/tcp_send_buffered.c
+++ b/net/tcp/tcp_send_buffered.c
@@ -95,6 +95,44 @@
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: tcp_inqueue_wrb_size
+ *
+ * Description:
+ *   Get the in-queued write buffer size from connection
+ *
+ * Input Parameters:
+ *   conn - The TCP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+static uint32_t tcp_inqueue_wrb_size(FAR struct tcp_conn_s *conn)
+{
+  FAR struct tcp_wrbuffer_s *wrb;
+  FAR sq_entry_t *entry;
+  uint32_t total = 0;
+
+  if (conn)
+    {
+      for (entry = sq_peek(&conn->unacked_q); entry; entry = sq_next(entry))
+        {
+          wrb = (FAR struct tcp_wrbuffer_s *)entry;
+          total += TCP_WBPKTLEN(wrb);
+        }
+
+      for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry))
+        {
+          wrb = (FAR struct tcp_wrbuffer_s *)entry;
+          total += TCP_WBPKTLEN(wrb);
+        }
+    }
+
+  return total;
+}
+
+/****************************************************************************
  * Name: psock_insert_segment
  *
  * Description:
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index cefe8a3..899b3d5 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -106,6 +106,38 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: udp_inqueue_wrb_size
+ *
+ * Description:
+ *   Get the in-queued write buffer size from connection
+ *
+ * Input Parameters:
+ *   conn - The UDP connection of interest
+ *
+ * Assumptions:
+ *   Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+static uint32_t udp_inqueue_wrb_size(FAR struct udp_conn_s *conn)
+{
+  FAR struct udp_wrbuffer_s *wrb;
+  FAR sq_entry_t *entry;
+  uint32_t total = 0;
+
+  if (conn)
+    {
+      for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry))
+        {
+          wrb = (FAR struct udp_wrbuffer_s *)entry;
+          total += wrb->wb_iob->io_pktlen;
+        }
+    }
+
+  return total;
+}
+
+/****************************************************************************
  * Name: sendto_writebuffer_release
  *
  * Description: