From 22a82b3f51e25c1be81f00d51664032bbdda0ac3 Mon Sep 17 00:00:00 2001 From: Fotis Panagiotopoulos Date: Mon, 13 Feb 2023 12:21:46 +0200 Subject: [PATCH] Improvements in IEEE 802.15.4 connections allocation. --- net/ieee802154/Kconfig | 41 ++++++++++++++++++++++++++++-- net/ieee802154/ieee802154_conn.c | 43 ++++++++++++++++++++++++-------- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 302fecb500..9cb0716556 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig @@ -33,9 +33,46 @@ config NET_IEEE802154_FRAMELEN This setting is currently used only for detection data transfers that would exceed the radio frame length. -config NET_IEEE802154_NCONNS - int "Max IEEE 802.15.4 sockets" +config NET_IEEE802154_PREALLOC_CONNS + int "Preallocated IEEE 802.15.4 sockets" default 4 + ---help--- + Number of IEEE 802.15.4 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_IEEE802154_ALLOC_CONNS + int "Dynamic IEEE 802.15.4 connections allocation" + default 0 + ---help--- + Dynamic memory allocations for IEEE 802.15.4. + + 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_IEEE802154_MAX_CONNS + int "Maximum number of IEEE 802.15.4 connections" + default 0 + depends on NET_IEEE802154_ALLOC_CONNS > 0 + ---help--- + If dynamic connections allocation is selected (NET_IEEE802154_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_IEEE802154_NCONTAINERS int "Number of pre-allocated frame containers" diff --git a/net/ieee802154/ieee802154_conn.c b/net/ieee802154/ieee802154_conn.c index d32db2d2d0..a6133a100f 100644 --- a/net/ieee802154/ieee802154_conn.c +++ b/net/ieee802154/ieee802154_conn.c @@ -51,9 +51,9 @@ * network lock. */ -#ifndef CONFIG_NET_ALLOC_CONNS +#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 static struct ieee802154_conn_s - g_ieee802154_connections[CONFIG_NET_IEEE802154_NCONNS]; + g_ieee802154_connections[CONFIG_NET_IEEE802154_PREALLOC_CONNS]; #endif /* A list of all free packet socket connections */ @@ -82,10 +82,10 @@ static dq_queue_t g_active_ieee802154_connections; void ieee802154_conn_initialize(void) { -#ifndef CONFIG_NET_ALLOC_CONNS +#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 int i; - for (i = 0; i < CONFIG_NET_IEEE802154_NCONNS; i++) + for (i = 0; i < CONFIG_NET_IEEE802154_PREALLOC_CONNS; i++) { /* Link each pre-allocated connection structure into the free list. */ @@ -107,20 +107,30 @@ void ieee802154_conn_initialize(void) FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void) { FAR struct ieee802154_conn_s *conn; -#ifdef CONFIG_NET_ALLOC_CONNS +#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 int i; #endif /* The free list is protected by the network lock. */ net_lock(); -#ifdef CONFIG_NET_ALLOC_CONNS +#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 if (dq_peek(&g_free_ieee802154_connections) == NULL) { - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_IEEE802154_NCONNS); +#if CONFIG_NET_IEEE802154_MAX_CONNS > 0 + if (dq_count(&g_active_ieee802154_connections) + + CONFIG_NET_IEEE802154_ALLOC_CONNS + >= CONFIG_NET_IEEE802154_MAX_CONNS) + { + net_unlock(); + return NULL; + } +#endif + + conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_IEEE802154_ALLOC_CONNS); if (conn != NULL) { - for (i = 0; i < CONFIG_NET_IEEE802154_NCONNS; i++) + for (i = 0; i < CONFIG_NET_IEEE802154_ALLOC_CONNS; i++) { dq_addlast(&conn[i].sconn.node, &g_free_ieee802154_connections); @@ -188,9 +198,22 @@ void ieee802154_conn_free(FAR struct ieee802154_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_IEEE802154_ALLOC_CONNS == 1 + if (conn < g_ieee802154_connections || conn >= (g_ieee802154_connections + + CONFIG_NET_IEEE802154_PREALLOC_CONNS)) + { + kmm_free(conn); + } + else +#endif + { + dq_addlast(&conn->sconn.node, &g_free_ieee802154_connections); + } - dq_addlast(&conn->sconn.node, &g_free_ieee802154_connections); net_unlock(); }