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 b5b7d24ba1557dd745e0ef48e8f13a7a8a9a3865
Author: Fotis Panagiotopoulos <f.pa...@amco.gr>
AuthorDate: Mon Feb 13 19:15:37 2023 +0200

    Improvements in CAN connections allocation.
---
 .../nucleo-h743zi2/configs/socketcan/defconfig     |  2 +-
 net/can/Kconfig                                    | 41 +++++++++++++++++++--
 net/can/can_conn.c                                 | 42 ++++++++++++++++------
 3 files changed, 71 insertions(+), 14 deletions(-)

diff --git a/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig 
b/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig
index 5101756e2a..798bc06cea 100644
--- a/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig
+++ b/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig
@@ -25,7 +25,7 @@ CONFIG_BOARD_LOOPSPERMSEC=43103
 CONFIG_BUILTIN=y
 CONFIG_CANUTILS_CANDUMP=y
 CONFIG_CANUTILS_CANSEND=y
-CONFIG_CAN_CONNS=2
+CONFIG_CAN_PREALLOC_CONNS=2
 CONFIG_DEBUG_ERROR=y
 CONFIG_DEBUG_FEATURES=y
 CONFIG_DEBUG_INFO=y
diff --git a/net/can/Kconfig b/net/can/Kconfig
index 10cffb0024..3f053e7f38 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -30,11 +30,46 @@ config NET_CAN_HAVE_ERRORS
        bool
        default n
 
-config CAN_CONNS
-       int "Max number of CAN socket connections"
+config CAN_PREALLOC_CONNS
+       int "Preallocated CAN socket connections"
        default 4
        ---help---
-               Maximum number of CAN connections (all tasks).
+               Number of CAN 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 CAN_ALLOC_CONNS
+       int "Dynamic CAN connections allocation"
+       default 0
+       ---help---
+               Dynamic memory allocations for CAN.
+
+               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 CAN_MAX_CONNS
+       int "Maximum number of CAN connections"
+       default 0
+       depends on CAN_ALLOC_CONNS > 0
+       ---help---
+               If dynamic connections allocation is selected (CAN_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_CAN_EXTID
        bool "Enable CAN extended IDs"
diff --git a/net/can/can_conn.c b/net/can/can_conn.c
index b12683427b..4310bc81bb 100644
--- a/net/can/can_conn.c
+++ b/net/can/can_conn.c
@@ -49,8 +49,8 @@
 
 /* The array containing all NetLink connections. */
 
-#ifndef CONFIG_NET_ALLOC_CONNS
-static struct can_conn_s g_can_connections[CONFIG_CAN_CONNS];
+#if CONFIG_CAN_PREALLOC_CONNS > 0
+static struct can_conn_s g_can_connections[CONFIG_CAN_PREALLOC_CONNS];
 #endif
 
 /* A list of all free NetLink connections */
@@ -77,10 +77,10 @@ static dq_queue_t g_active_can_connections;
 
 void can_initialize(void)
 {
-#ifndef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_CAN_PREALLOC_CONNS > 0
   int i;
 
-  for (i = 0; i < CONFIG_CAN_CONNS; i++)
+  for (i = 0; i < CONFIG_CAN_PREALLOC_CONNS; i++)
     {
       /* Mark the connection closed and move it to the free list */
 
@@ -101,20 +101,29 @@ void can_initialize(void)
 FAR struct can_conn_s *can_alloc(void)
 {
   FAR struct can_conn_s *conn;
-#ifdef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_CAN_ALLOC_CONNS > 0
   int i;
 #endif
 
   /* The free list is protected by a a mutex. */
 
   nxmutex_lock(&g_free_lock);
-#ifdef CONFIG_NET_ALLOC_CONNS
+#if CONFIG_CAN_ALLOC_CONNS > 0
   if (dq_peek(&g_free_can_connections) == NULL)
     {
-      conn = kmm_zalloc(sizeof(*conn) * CONFIG_CAN_CONNS);
+#if CONFIG_CAN_MAX_CONNS > 0
+      if (dq_count(&g_active_can_connections) + CONFIG_CAN_ALLOC_CONNS
+          >= CONFIG_CAN_MAX_CONNS)
+        {
+          nxmutex_unlock(&g_free_lock);
+          return NULL;
+        }
+#endif
+
+      conn = kmm_zalloc(sizeof(*conn) * CONFIG_CAN_ALLOC_CONNS);
       if (conn != NULL)
         {
-          for (i = 0; i < CONFIG_CAN_CONNS; i++)
+          for (i = 0; i < CONFIG_CAN_ALLOC_CONNS; i++)
             {
               dq_addlast(&conn[i].sconn.node, &g_free_can_connections);
             }
@@ -177,9 +186,22 @@ void can_free(FAR struct can_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_CAN_ALLOC_CONNS == 1
+  if (conn < g_can_connections || conn >= (g_can_connections +
+      CONFIG_CAN_PREALLOC_CONNS))
+    {
+      kmm_free(conn);
+    }
+  else
+#endif
+    {
+      dq_addlast(&conn->sconn.node, &g_free_can_connections);
+    }
 
-  dq_addlast(&conn->sconn.node, &g_free_can_connections);
   nxmutex_unlock(&g_free_lock);
 }
 

Reply via email to