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 1c07a3a696acfcdf7fc48063994bf64a5783063f
Author: Fotis Panagiotopoulos <f.pa...@amco.gr>
AuthorDate: Tue Feb 7 19:02:52 2023 +0200

    Improvements in ICMP connections allocation.
---
 net/icmp/Kconfig     | 41 +++++++++++++++++++++++++++++++++++++++--
 net/icmp/icmp_conn.c | 39 ++++++++++++++++++++++++++++++---------
 2 files changed, 69 insertions(+), 11 deletions(-)

diff --git a/net/icmp/Kconfig b/net/icmp/Kconfig
index 8ce7ceaa77..5cee9de515 100644
--- a/net/icmp/Kconfig
+++ b/net/icmp/Kconfig
@@ -32,9 +32,46 @@ config NET_ICMP_SOCKET
 
 if NET_ICMP_SOCKET
 
-config NET_ICMP_NCONNS
-       int "Max ICMP packet sockets"
+config NET_ICMP_PREALLOC_CONNS
+       int "Preallocated ICMP packet sockets"
        default 4
+       ---help---
+               Number of ICMP connections (all tasks).
+               
+               This number of connections will be pre-allocated during system 
boot.
+               If dynamic connections allocation is enabled, more connections 
may
+               be allocated at a later time, as the system needs them. Else 
this
+               will be the maximum number of connections available to the 
system
+               at all times.
+
+               Set to 0 to disable (and rely only on dynamic allocations).
+
+config NET_ICMP_ALLOC_CONNS
+       int "Dynamic ICMP connections allocation"
+       default 0
+       ---help---
+               Dynamic memory allocations for ICMP.
+
+               When set to 0 all dynamic allocations are disabled.
+
+               When set to 1 a new connection will be allocated every time,
+               and it will be free'd when no longer needed.
+
+               Setting this to 2 or more will allocate the connections in
+               batches (with batch size equal to this config). When a
+               connection is no longer needed, it will be returned to the
+               free connections pool, and it will never be deallocated!
+
+config NET_ICMP_MAX_CONNS
+       int "Maximum number of ICMP connections"
+       default 0
+       depends on NET_ICMP_ALLOC_CONNS > 0
+       ---help---
+               If dynamic connections allocation is selected 
(NET_ICMP_ALLOC_CONNS > 0)
+               this will limit the number of connections that can be allocated.
+               
+               This is useful in case the system is under very heavy load (or
+               under attack), ensuring that the heap will not be exhausted.
 
 config NET_ICMP_NPOLLWAITERS
        int "Number of ICMP poll waiters"
diff --git a/net/icmp/icmp_conn.c b/net/icmp/icmp_conn.c
index a8456c4967..2ddcc6903d 100644
--- a/net/icmp/icmp_conn.c
+++ b/net/icmp/icmp_conn.c
@@ -48,8 +48,8 @@
 
 /* The array containing all IPPROTO_ICMP socket connections */
 
-#ifndef CONFIG_NET_ALLOC_CONNS
-static struct icmp_conn_s g_icmp_connections[CONFIG_NET_ICMP_NCONNS];
+#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0
+static struct icmp_conn_s g_icmp_connections[CONFIG_NET_ICMP_PREALLOC_CONNS];
 #endif
 
 /* A list of all free IPPROTO_ICMP socket connections */
@@ -76,10 +76,10 @@ static dq_queue_t g_active_icmp_connections;
 
 void icmp_sock_initialize(void)
 {
-#ifndef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0
   int i;
 
-  for (i = 0; i < CONFIG_NET_ICMP_NCONNS; i++)
+  for (i = 0; i < CONFIG_NET_ICMP_PREALLOC_CONNS; i++)
     {
       /* Move the connection structure to the free list */
 
@@ -109,13 +109,22 @@ FAR struct icmp_conn_s *icmp_alloc(void)
   ret = nxmutex_lock(&g_free_lock);
   if (ret >= 0)
     {
-#ifdef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_NET_ICMP_ALLOC_CONNS > 0
       if (dq_peek(&g_free_icmp_connections) == NULL)
         {
-          conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMP_NCONNS);
+#if CONFIG_NET_ICMP_MAX_CONNS > 0
+          if (dq_count(&g_active_icmp_connections) +
+              CONFIG_NET_ICMP_ALLOC_CONNS >= CONFIG_NET_ICMP_MAX_CONNS)
+            {
+              nxmutex_unlock(&g_free_lock);
+              return NULL;
+            }
+#endif
+
+          conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMP_ALLOC_CONNS);
           if (conn != NULL)
             {
-              for (ret = 0; ret < CONFIG_NET_ICMP_NCONNS; ret++)
+              for (ret = 0; ret < CONFIG_NET_ICMP_ALLOC_CONNS; ret++)
                 {
                   dq_addlast(&conn[ret].sconn.node,
                              &g_free_icmp_connections);
@@ -177,9 +186,21 @@ void icmp_free(FAR struct icmp_conn_s *conn)
 
       memset(conn, 0, sizeof(*conn));
 
-      /* Free the connection */
+      /* If this is a preallocated or a batch allocated connection store it
+       * in the free connections list. Else free it.
+       */
 
-      dq_addlast(&conn->sconn.node, &g_free_icmp_connections);
+#if CONFIG_NET_ICMP_ALLOC_CONNS == 1
+      if (conn < g_icmp_connections || conn >= (g_icmp_connections +
+          CONFIG_NET_ICMP_PREALLOC_CONNS))
+        {
+          kmm_free(conn);
+        }
+      else
+#endif
+        {
+          dq_addlast(&conn->sconn.node, &g_free_icmp_connections);
+        }
     }
 
   nxmutex_unlock(&g_free_lock);

Reply via email to