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/02/20 01:06:58 UTC

[nuttx] 05/12: Improvements in ICMPv6 connections allocation.

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 90a93a747412aa26df1ce91a8fa4a294ba503bd3
Author: Fotis Panagiotopoulos <f....@amco.gr>
AuthorDate: Sat Feb 11 15:09:01 2023 +0200

    Improvements in ICMPv6 connections allocation.
---
 net/icmpv6/Kconfig       | 41 +++++++++++++++++++++++++++++++++++++++--
 net/icmpv6/icmpv6_conn.c | 40 +++++++++++++++++++++++++++++++---------
 2 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/net/icmpv6/Kconfig b/net/icmpv6/Kconfig
index 248f0224f0..471204b981 100644
--- a/net/icmpv6/Kconfig
+++ b/net/icmpv6/Kconfig
@@ -200,9 +200,46 @@ endif # NET_ICMPv6_ROUTER
 
 if NET_ICMPv6_SOCKET
 
-config NET_ICMPv6_NCONNS
-	int "Max ICMPv6 packet sockets"
+config NET_ICMPv6_PREALLOC_CONNS
+	int "Preallocated ICMPv6 packet sockets"
 	default 4
+	---help---
+		Number of ICMPv6 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_ICMPv6_ALLOC_CONNS
+	int "Dynamic ICMPv6 connections allocation"
+	default 0
+	---help---
+		Dynamic memory allocations for ICMPv6.
+
+		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_ICMPv6_MAX_CONNS
+	int "Maximum number of ICMPv6 connections"
+	default 0
+	depends on NET_ICMPv6_ALLOC_CONNS > 0
+	---help---
+		If dynamic connections allocation is selected (NET_ICMPv6_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_ICMPv6_NPOLLWAITERS
 	int "Number of ICMPv6 poll waiters"
diff --git a/net/icmpv6/icmpv6_conn.c b/net/icmpv6/icmpv6_conn.c
index b10e7daf3d..4299fb62ac 100644
--- a/net/icmpv6/icmpv6_conn.c
+++ b/net/icmpv6/icmpv6_conn.c
@@ -48,8 +48,9 @@
 
 /* The array containing all IPPROTO_ICMP socket connections */
 
-#ifndef CONFIG_NET_ALLOC_CONNS
-static struct icmpv6_conn_s g_icmpv6_connections[CONFIG_NET_ICMPv6_NCONNS];
+#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0
+static struct icmpv6_conn_s
+              g_icmpv6_connections[CONFIG_NET_ICMPv6_PREALLOC_CONNS];
 #endif
 
 /* A list of all free IPPROTO_ICMP socket connections */
@@ -76,10 +77,10 @@ static dq_queue_t g_active_icmpv6_connections;
 
 void icmpv6_sock_initialize(void)
 {
-#ifndef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0
   int i;
 
-  for (i = 0; i < CONFIG_NET_ICMPv6_NCONNS; i++)
+  for (i = 0; i < CONFIG_NET_ICMPv6_PREALLOC_CONNS; i++)
     {
       /* Move the connection structure to the free list */
 
@@ -109,13 +110,22 @@ FAR struct icmpv6_conn_s *icmpv6_alloc(void)
   ret = nxmutex_lock(&g_free_lock);
   if (ret >= 0)
     {
-#ifdef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_NET_ICMPv6_ALLOC_CONNS > 0
       if (dq_peek(&g_active_icmpv6_connections) == NULL)
         {
-          conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMPv6_NCONNS);
+#if CONFIG_NET_ICMPv6_MAX_CONNS > 0
+          if (dq_count(&g_active_icmpv6_connections) +
+              CONFIG_NET_ICMPv6_ALLOC_CONNS >= CONFIG_NET_ICMPv6_MAX_CONNS)
+            {
+              nxmutex_unlock(&g_free_lock);
+              return NULL;
+            }
+#endif
+
+          conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMPv6_ALLOC_CONNS);
           if (conn != NULL)
             {
-              for (ret = 0; ret < CONFIG_NET_ICMPv6_NCONNS; ret++)
+              for (ret = 0; ret < CONFIG_NET_ICMPv6_ALLOC_CONNS; ret++)
                 {
                   dq_addlast(&conn[ret].sconn.node,
                              &g_free_icmpv6_connections);
@@ -166,9 +176,21 @@ void icmpv6_free(FAR struct icmpv6_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.
+   */
+#if CONFIG_NET_ICMPv6_ALLOC_CONNS == 1
+  if (conn < g_icmpv6_connections || conn >= (g_icmpv6_connections +
+      CONFIG_NET_ICMPv6_PREALLOC_CONNS))
+    {
+      kmm_free(conn);
+    }
+  else
+#endif
+    {
+      dq_addlast(&conn->sconn.node, &g_free_icmpv6_connections);
+    }
 
-  dq_addlast(&conn->sconn.node, &g_free_icmpv6_connections);
   nxmutex_unlock(&g_free_lock);
 }