From 9580a1dacb0bf4dcf328fa64c89f7c86ae7e3ce1 Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Tue, 17 Dec 2024 18:29:14 +0800 Subject: [PATCH 1/2] net: Add buffer pool to replace connection allocation Our net socket connection allocations are powerful but redundant because they're implemented once in each protocol. This is not good for further optimizing and extending to other allocations, so maybe we can add a common implementation for the usage. Impact: 1. We add a `struct net_bufpool_s` as pool descriptor, which may use a little bit more memory than previous implementation (~28Bytes). 2. We share same functions between pools, so code size may shrink under some scenarios. Signed-off-by: Zhe Weng --- net/bluetooth/bluetooth_conn.c | 79 +++----------- net/can/can_conn.c | 73 +++---------- net/devif/devif_callback.c | 69 ++----------- net/icmp/icmp_conn.c | 74 +++---------- net/icmpv6/icmpv6_conn.c | 77 +++----------- net/ieee802154/ieee802154_conn.c | 80 ++++---------- net/netlink/netlink_conn.c | 76 +++----------- net/pkt/pkt_conn.c | 68 +++--------- net/tcp/tcp_conn.c | 108 +++---------------- net/udp/udp_conn.c | 105 +++---------------- net/usrsock/usrsock_conn.c | 82 +++------------ net/utils/CMakeLists.txt | 3 +- net/utils/Make.defs | 1 + net/utils/net_bufpool.c | 172 +++++++++++++++++++++++++++++++ net/utils/utils.h | 94 +++++++++++++++++ 15 files changed, 437 insertions(+), 724 deletions(-) create mode 100644 net/utils/net_bufpool.c diff --git a/net/bluetooth/bluetooth_conn.c b/net/bluetooth/bluetooth_conn.c index f649943bd468d..ad529326b64de 100644 --- a/net/bluetooth/bluetooth_conn.c +++ b/net/bluetooth/bluetooth_conn.c @@ -42,10 +42,19 @@ #include #include "devif/devif.h" +#include "utils/utils.h" #include "bluetooth/bluetooth.h" #ifdef CONFIG_NET_BLUETOOTH +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NET_BLUETOOTH_MAX_CONNS +# define CONFIG_NET_BLUETOOTH_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -54,14 +63,10 @@ * network lock. */ -#if CONFIG_NET_BLUETOOTH_PREALLOC_CONNS > 0 -static struct bluetooth_conn_s - g_bluetooth_connections[CONFIG_NET_BLUETOOTH_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_bluetooth_connections; +NET_BUFPOOL_DECLARE(g_bluetooth_connections, sizeof(struct bluetooth_conn_s), + CONFIG_NET_BLUETOOTH_PREALLOC_CONNS, + CONFIG_NET_BLUETOOTH_ALLOC_CONNS, + CONFIG_NET_BLUETOOTH_MAX_CONNS); /* A list of all allocated packet socket connections */ @@ -90,17 +95,7 @@ static const bt_addr_t g_any_addr = void bluetooth_conn_initialize(void) { -#if CONFIG_NET_BLUETOOTH_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_BLUETOOTH_PREALLOC_CONNS; i++) - { - /* Link each pre-allocated connection structure into the free list. */ - - dq_addlast(&g_bluetooth_connections[i].bc_conn.node, - &g_free_bluetooth_connections); - } -#endif + NET_BUFPOOL_INIT(g_bluetooth_connections); } /**************************************************************************** @@ -115,39 +110,12 @@ void bluetooth_conn_initialize(void) FAR struct bluetooth_conn_s *bluetooth_conn_alloc(void) { FAR struct bluetooth_conn_s *conn; -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by the network lock */ net_lock(); -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS > 0 - if (dq_peek(&g_active_bluetooth_connections) == NULL) - { -#if CONFIG_NET_BLUETOOTH_MAX_CONNS > 0 - if (dq_count(&g_active_bluetooth_connections) + - CONFIG_NET_BLUETOOTH_ALLOC_CONNS > CONFIG_NET_BLUETOOTH_MAX_CONNS) - { - net_unlock(); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_BLUETOOTH_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_BLUETOOTH_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].bc_conn.node, - &g_active_bluetooth_connections); - } - } - } -#endif - conn = (FAR struct bluetooth_conn_s *) - dq_remfirst(&g_free_bluetooth_connections); + conn = NET_BUFPOOL_TRYALLOC(g_bluetooth_connections); if (conn) { /* Mark as unbound */ @@ -207,22 +175,9 @@ void bluetooth_conn_free(FAR struct bluetooth_conn_s *conn) bluetooth_container_free(container); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection structure */ -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS == 1 - if (conn < g_bluetooth_connections || conn >= (g_bluetooth_connections + - CONFIG_NET_BLUETOOTH_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->bc_conn.node, &g_free_bluetooth_connections); - } + NET_BUFPOOL_FREE(g_bluetooth_connections, conn); net_unlock(); } diff --git a/net/can/can_conn.c b/net/can/can_conn.c index 89be629af56b7..6f26bab4c87e5 100644 --- a/net/can/can_conn.c +++ b/net/can/can_conn.c @@ -46,18 +46,22 @@ #ifdef CONFIG_NET_CAN /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all NetLink connections. */ - -#if CONFIG_CAN_PREALLOC_CONNS > 0 -static struct can_conn_s g_can_connections[CONFIG_CAN_PREALLOC_CONNS]; +#ifndef CONFIG_CAN_MAX_CONNS +# define CONFIG_CAN_MAX_CONNS 0 #endif -/* A list of all free NetLink connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all NetLink connections. */ -static dq_queue_t g_free_can_connections; +NET_BUFPOOL_DECLARE(g_can_connections, sizeof(struct can_conn_s), + CONFIG_CAN_PREALLOC_CONNS, CONFIG_CAN_ALLOC_CONNS, + CONFIG_CAN_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated NetLink connections */ @@ -79,16 +83,7 @@ static dq_queue_t g_active_can_connections; void can_initialize(void) { -#if CONFIG_CAN_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_CAN_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - dq_addlast(&g_can_connections[i].sconn.node, &g_free_can_connections); - } -#endif + NET_BUFPOOL_INIT(g_can_connections); } /**************************************************************************** @@ -103,37 +98,12 @@ void can_initialize(void) FAR struct can_conn_s *can_alloc(void) { FAR struct can_conn_s *conn; -#if CONFIG_CAN_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_CAN_ALLOC_CONNS > 0 - if (dq_peek(&g_free_can_connections) == NULL) - { -#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_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_can_connections); - } - } - } -#endif - conn = (FAR struct can_conn_s *)dq_remfirst(&g_free_can_connections); + conn = NET_BUFPOOL_TRYALLOC(g_can_connections); if (conn != NULL) { /* FIXME SocketCAN default behavior enables loopback */ @@ -184,22 +154,9 @@ void can_free(FAR struct can_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_can_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_CAN_ALLOC_CONNS == 1 - if (conn < g_can_connections || conn >= (g_can_connections + - CONFIG_CAN_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_can_connections); - } + NET_BUFPOOL_FREE(g_can_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c index ecd8283667792..6f451a2b381fc 100644 --- a/net/devif/devif_callback.c +++ b/net/devif/devif_callback.c @@ -39,6 +39,7 @@ #include #include "netdev/netdev.h" +#include "utils/utils.h" #include "devif/devif.h" /**************************************************************************** @@ -52,11 +53,9 @@ * Private Data ****************************************************************************/ -#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0 -static struct devif_callback_s - g_cbprealloc[CONFIG_NET_PREALLOC_DEVIF_CALLBACKS]; -#endif -static FAR struct devif_callback_s *g_cbfreelist = NULL; +NET_BUFPOOL_DECLARE(g_cbprealloc, sizeof(struct devif_callback_s), + CONFIG_NET_PREALLOC_DEVIF_CALLBACKS, + CONFIG_NET_ALLOC_DEVIF_CALLBACKS, 0); /**************************************************************************** * Private Functions @@ -88,7 +87,7 @@ static void devif_callback_free(FAR struct net_driver_s *dev, #ifdef CONFIG_DEBUG_FEATURES /* Check for double freed callbacks */ - curr = g_cbfreelist; + curr = (FAR struct devif_callback_s *)g_cbprealloc.freebuffers.head; while (curr != NULL) { @@ -187,23 +186,9 @@ static void devif_callback_free(FAR struct net_driver_s *dev, } } - /* If this is a preallocated or a batch allocated callback store it in - * the free callbacks list. Else free it. - */ + /* Free the callback structure */ -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS == 1 - if (cb < g_cbprealloc || cb >= (g_cbprealloc + - CONFIG_NET_PREALLOC_DEVIF_CALLBACKS)) - { - kmm_free(cb); - } - else -#endif - { - cb->nxtconn = g_cbfreelist; - cb->nxtdev = NULL; - g_cbfreelist = cb; - } + NET_BUFPOOL_FREE(g_cbprealloc, cb); net_unlock(); } @@ -266,15 +251,7 @@ static bool devif_event_trigger(uint16_t events, uint16_t triggers) void devif_callback_init(void) { -#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0 - int i; - - for (i = 0; i < CONFIG_NET_PREALLOC_DEVIF_CALLBACKS; i++) - { - g_cbprealloc[i].nxtconn = g_cbfreelist; - g_cbfreelist = &g_cbprealloc[i]; - } -#endif + NET_BUFPOOL_INIT(g_cbprealloc); } /**************************************************************************** @@ -299,9 +276,6 @@ FAR struct devif_callback_s * FAR struct devif_callback_s **list_tail) { FAR struct devif_callback_s *ret; -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0 - int i; -#endif net_lock(); @@ -324,34 +298,11 @@ FAR struct devif_callback_s * return NULL; } - /* Allocate the callback entry from heap */ + /* Get a callback structure */ -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0 - if (g_cbfreelist == NULL) - { - ret = kmm_zalloc(sizeof(struct devif_callback_s) * - CONFIG_NET_ALLOC_DEVIF_CALLBACKS); - if (ret != NULL) - { - for (i = 0; i < CONFIG_NET_ALLOC_DEVIF_CALLBACKS; i++) - { - ret[i].nxtconn = g_cbfreelist; - g_cbfreelist = &ret[i]; - } - } - } -#endif - - /* Check the head of the free list */ - - ret = g_cbfreelist; + ret = NET_BUFPOOL_TRYALLOC(g_cbprealloc); if (ret) { - /* Remove the next instance from the head of the free list */ - - g_cbfreelist = ret->nxtconn; - memset(ret, 0, sizeof(struct devif_callback_s)); - /* Add the newly allocated instance to the head of the device event * list. */ diff --git a/net/icmp/icmp_conn.c b/net/icmp/icmp_conn.c index a4eac7cd3a8fc..3fb3d1938ce44 100644 --- a/net/icmp/icmp_conn.c +++ b/net/icmp/icmp_conn.c @@ -41,22 +41,27 @@ #include "devif/devif.h" #include "icmp/icmp.h" +#include "utils/utils.h" #ifdef CONFIG_NET_ICMP_SOCKET /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all IPPROTO_ICMP socket connections */ - -#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0 -static struct icmp_conn_s g_icmp_connections[CONFIG_NET_ICMP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_ICMP_MAX_CONNS +# define CONFIG_NET_ICMP_MAX_CONNS 0 #endif -/* A list of all free IPPROTO_ICMP socket connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all IPPROTO_ICMP socket connections */ -static dq_queue_t g_free_icmp_connections; +NET_BUFPOOL_DECLARE(g_icmp_connections, sizeof(struct icmp_conn_s), + CONFIG_NET_ICMP_PREALLOC_CONNS, + CONFIG_NET_ICMP_ALLOC_CONNS, CONFIG_NET_ICMP_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated IPPROTO_ICMP socket connections */ @@ -78,17 +83,7 @@ static dq_queue_t g_active_icmp_connections; void icmp_sock_initialize(void) { -#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_ICMP_PREALLOC_CONNS; i++) - { - /* Move the connection structure to the free list */ - - dq_addlast(&g_icmp_connections[i].sconn.node, - &g_free_icmp_connections); - } -#endif + NET_BUFPOOL_INIT(g_icmp_connections); } /**************************************************************************** @@ -111,31 +106,7 @@ FAR struct icmp_conn_s *icmp_alloc(void) ret = nxmutex_lock(&g_free_lock); if (ret >= 0) { -#if CONFIG_NET_ICMP_ALLOC_CONNS > 0 - if (dq_peek(&g_free_icmp_connections) == NULL) - { -#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_ALLOC_CONNS; ret++) - { - dq_addlast(&conn[ret].sconn.node, - &g_free_icmp_connections); - } - } - } -#endif - - conn = (FAR struct icmp_conn_s *)dq_remfirst(&g_free_icmp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_icmp_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -184,22 +155,9 @@ void icmp_free(FAR struct icmp_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_icmp_connections); - /* If this is a preallocated or a batch allocated connection store it - * in the free connections list. Else free it. - */ + /* Free the connection. */ -#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 - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_icmp_connections); - } + NET_BUFPOOL_FREE(g_icmp_connections, conn); } nxmutex_unlock(&g_free_lock); diff --git a/net/icmpv6/icmpv6_conn.c b/net/icmpv6/icmpv6_conn.c index ac3d65a4dbcd3..228f83e8d5e57 100644 --- a/net/icmpv6/icmpv6_conn.c +++ b/net/icmpv6/icmpv6_conn.c @@ -41,23 +41,28 @@ #include "devif/devif.h" #include "icmpv6/icmpv6.h" +#include "utils/utils.h" #ifdef CONFIG_NET_ICMPv6_SOCKET /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all IPPROTO_ICMP socket connections */ - -#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0 -static struct icmpv6_conn_s - g_icmpv6_connections[CONFIG_NET_ICMPv6_PREALLOC_CONNS]; +#ifndef CONFIG_NET_ICMPv6_MAX_CONNS +# define CONFIG_NET_ICMPv6_MAX_CONNS 0 #endif -/* A list of all free IPPROTO_ICMP socket connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all IPPROTO_ICMP socket connections */ -static dq_queue_t g_free_icmpv6_connections; +NET_BUFPOOL_DECLARE(g_icmpv6_connections, sizeof(struct icmpv6_conn_s), + CONFIG_NET_ICMPv6_PREALLOC_CONNS, + CONFIG_NET_ICMPv6_ALLOC_CONNS, + CONFIG_NET_ICMPv6_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated IPPROTO_ICMP socket connections */ @@ -79,17 +84,7 @@ static dq_queue_t g_active_icmpv6_connections; void icmpv6_sock_initialize(void) { -#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_ICMPv6_PREALLOC_CONNS; i++) - { - /* Move the connection structure to the free list */ - - dq_addlast(&g_icmpv6_connections[i].sconn.node, - &g_free_icmpv6_connections); - } -#endif + NET_BUFPOOL_INIT(g_icmpv6_connections); } /**************************************************************************** @@ -112,32 +107,7 @@ FAR struct icmpv6_conn_s *icmpv6_alloc(void) ret = nxmutex_lock(&g_free_lock); if (ret >= 0) { -#if CONFIG_NET_ICMPv6_ALLOC_CONNS > 0 - if (dq_peek(&g_active_icmpv6_connections) == NULL) - { -#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_ALLOC_CONNS; ret++) - { - dq_addlast(&conn[ret].sconn.node, - &g_free_icmpv6_connections); - } - } - } -#endif - - conn = (FAR struct icmpv6_conn_s *) - dq_remfirst(&g_free_icmpv6_connections); + conn = NET_BUFPOOL_TRYALLOC(g_icmpv6_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -174,22 +144,9 @@ void icmpv6_free(FAR struct icmpv6_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_icmpv6_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#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 - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_icmpv6_connections); - } + NET_BUFPOOL_FREE(g_icmpv6_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/ieee802154/ieee802154_conn.c b/net/ieee802154/ieee802154_conn.c index d30f05c14ba62..46e7ff7047a7e 100644 --- a/net/ieee802154/ieee802154_conn.c +++ b/net/ieee802154/ieee802154_conn.c @@ -42,9 +42,18 @@ #include "devif/devif.h" #include "ieee802154/ieee802154.h" +#include "utils/utils.h" #ifdef CONFIG_NET_IEEE802154 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NET_IEEE802154_MAX_CONNS +# define CONFIG_NET_IEEE802154_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -53,14 +62,11 @@ * network lock. */ -#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 -static struct ieee802154_conn_s - g_ieee802154_connections[CONFIG_NET_IEEE802154_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_ieee802154_connections; +NET_BUFPOOL_DECLARE(g_ieee802154_connections, + sizeof(struct ieee802154_conn_s), + CONFIG_NET_IEEE802154_PREALLOC_CONNS, + CONFIG_NET_IEEE802154_ALLOC_CONNS, + CONFIG_NET_IEEE802154_MAX_CONNS); /* A list of all allocated packet socket connections */ @@ -84,17 +90,7 @@ static dq_queue_t g_active_ieee802154_connections; void ieee802154_conn_initialize(void) { -#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_IEEE802154_PREALLOC_CONNS; i++) - { - /* Link each pre-allocated connection structure into the free list. */ - - dq_addlast(&g_ieee802154_connections[i].sconn.node, - &g_free_ieee802154_connections); - } -#endif + NET_BUFPOOL_INIT(g_ieee802154_connections); } /**************************************************************************** @@ -109,39 +105,12 @@ void ieee802154_conn_initialize(void) FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void) { FAR struct ieee802154_conn_s *conn; -#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by the network lock. */ net_lock(); -#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 - if (dq_peek(&g_free_ieee802154_connections) == NULL) - { -#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_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, - &g_free_ieee802154_connections); - } - } - } -#endif - conn = (FAR struct ieee802154_conn_s *) - dq_remfirst(&g_free_ieee802154_connections); + conn = NET_BUFPOOL_TRYALLOC(g_ieee802154_connections); if (conn) { dq_addlast(&conn->sconn.node, &g_active_ieee802154_connections); @@ -195,22 +164,9 @@ void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn) ieee802154_container_free(container); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#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 - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_ieee802154_connections); - } + NET_BUFPOOL_FREE(g_ieee802154_connections, conn); net_unlock(); } diff --git a/net/netlink/netlink_conn.c b/net/netlink/netlink_conn.c index 0a1b5f71da353..dddb52bd5cda8 100644 --- a/net/netlink/netlink_conn.c +++ b/net/netlink/netlink_conn.c @@ -49,19 +49,22 @@ #ifdef CONFIG_NET_NETLINK /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all NetLink connections. */ - -#if CONFIG_NETLINK_PREALLOC_CONNS > 0 -static struct netlink_conn_s -g_netlink_connections[CONFIG_NETLINK_PREALLOC_CONNS]; +#ifndef CONFIG_NETLINK_MAX_CONNS +# define CONFIG_NETLINK_MAX_CONNS 0 #endif -/* A list of all free NetLink connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all NetLink connections. */ -static dq_queue_t g_free_netlink_connections; +NET_BUFPOOL_DECLARE(g_netlink_connections, sizeof(struct netlink_conn_s), + CONFIG_NETLINK_PREALLOC_CONNS, + CONFIG_NETLINK_ALLOC_CONNS, CONFIG_NETLINK_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated NetLink connections */ @@ -147,17 +150,7 @@ netlink_get_terminator(FAR const struct nlmsghdr *req) void netlink_initialize(void) { -#if CONFIG_NETLINK_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NETLINK_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - dq_addlast(&g_netlink_connections[i].sconn.node, - &g_free_netlink_connections); - } -#endif + NET_BUFPOOL_INIT(g_netlink_connections); } /**************************************************************************** @@ -172,38 +165,12 @@ void netlink_initialize(void) FAR struct netlink_conn_s *netlink_alloc(void) { FAR struct netlink_conn_s *conn; -#if CONFIG_NETLINK_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NETLINK_ALLOC_CONNS > 0 - if (dq_peek(&g_free_netlink_connections) == NULL) - { -#if CONFIG_NETLINK_MAX_CONNS > 0 - if (dq_count(&g_active_netlink_connections) + - CONFIG_NETLINK_ALLOC_CONNS > CONFIG_NETLINK_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NETLINK_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NETLINK_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_netlink_connections); - } - } - } -#endif - conn = (FAR struct netlink_conn_s *) - dq_remfirst(&g_free_netlink_connections); + conn = NET_BUFPOOL_TRYALLOC(g_netlink_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -245,22 +212,9 @@ void netlink_free(FAR struct netlink_conn_s *conn) kmm_free(resp); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection */ -#if CONFIG_NETLINK_ALLOC_CONNS == 1 - if (conn < g_netlink_connections || conn >= (g_netlink_connections + - CONFIG_NETLINK_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_netlink_connections); - } + NET_BUFPOOL_FREE(g_netlink_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/pkt/pkt_conn.c b/net/pkt/pkt_conn.c index 601dff89f3941..8856acb5bb10b 100644 --- a/net/pkt/pkt_conn.c +++ b/net/pkt/pkt_conn.c @@ -42,6 +42,7 @@ #include "devif/devif.h" #include "pkt/pkt.h" +#include "utils/utils.h" /**************************************************************************** * Pre-processor Definitions @@ -52,19 +53,19 @@ (addr1[2] == addr2[2]) && (addr1[3] == addr2[3]) && \ (addr1[4] == addr2[4]) && (addr1[5] == addr2[5])) +#ifndef CONFIG_NET_PKT_MAX_CONNS +# define CONFIG_NET_PKT_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ /* The array containing all packet socket connections */ -#if CONFIG_NET_PKT_PREALLOC_CONNS > 0 -static struct pkt_conn_s g_pkt_connections[CONFIG_NET_PKT_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_pkt_connections; +NET_BUFPOOL_DECLARE(g_pkt_connections, sizeof(struct pkt_conn_s), + CONFIG_NET_PKT_PREALLOC_CONNS, + CONFIG_NET_PKT_ALLOC_CONNS, CONFIG_NET_PKT_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated packet socket connections */ @@ -86,14 +87,7 @@ static dq_queue_t g_active_pkt_connections; void pkt_initialize(void) { -#if CONFIG_NET_PKT_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_PKT_PREALLOC_CONNS; i++) - { - dq_addlast(&g_pkt_connections[i].sconn.node, &g_free_pkt_connections); - } -#endif + NET_BUFPOOL_INIT(g_pkt_connections); } /**************************************************************************** @@ -108,37 +102,12 @@ void pkt_initialize(void) FAR struct pkt_conn_s *pkt_alloc(void) { FAR struct pkt_conn_s *conn; -#if CONFIG_NET_PKT_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NET_PKT_ALLOC_CONNS > 0 - if (dq_peek(&g_free_pkt_connections) == NULL) - { -#if CONFIG_NET_PKT_MAX_CONNS > 0 - if (dq_count(&g_active_pkt_connections) + - CONFIG_NET_PKT_ALLOC_CONNS > CONFIG_NET_PKT_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_PKT_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_PKT_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_pkt_connections); - } - } - } -#endif - conn = (FAR struct pkt_conn_s *)dq_remfirst(&g_free_pkt_connections); + conn = NET_BUFPOOL_TRYALLOC(g_pkt_connections); if (conn) { /* Enqueue the connection into the active list */ @@ -171,22 +140,9 @@ void pkt_free(FAR struct pkt_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_pkt_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_PKT_ALLOC_CONNS == 1 - if (conn < g_pkt_connections || conn >= (g_pkt_connections + - CONFIG_NET_PKT_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_pkt_connections); - } + NET_BUFPOOL_FREE(g_pkt_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index 2cc05157f5b42..d8bc2eda91f60 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -74,18 +74,22 @@ #include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all TCP connections. */ - -#if CONFIG_NET_TCP_PREALLOC_CONNS > 0 -static struct tcp_conn_s g_tcp_connections[CONFIG_NET_TCP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_TCP_MAX_CONNS +# define CONFIG_NET_TCP_MAX_CONNS 0 #endif -/* A list of all free TCP connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all TCP connections. */ -static dq_queue_t g_free_tcp_connections; +NET_BUFPOOL_DECLARE(g_tcp_connections, sizeof(struct tcp_conn_s), + CONFIG_NET_TCP_PREALLOC_CONNS, + CONFIG_NET_TCP_ALLOC_CONNS, CONFIG_NET_TCP_MAX_CONNS); /* A list of all connected TCP connections */ @@ -497,54 +501,6 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, } #endif /* CONFIG_NET_IPv6 */ -/**************************************************************************** - * Name: tcp_alloc_conn - * - * Description: - * Find or allocate a free TCP/IP connection structure for use. - * - ****************************************************************************/ - -#if CONFIG_NET_TCP_ALLOC_CONNS > 0 -static FAR struct tcp_conn_s *tcp_alloc_conn(void) -{ - FAR struct tcp_conn_s *conn; - int i; - - /* Return the entry from the head of the free list */ - - if (dq_peek(&g_free_tcp_connections) == NULL) - { -#if CONFIG_NET_TCP_MAX_CONNS > 0 - if (dq_count(&g_active_tcp_connections) + - CONFIG_NET_TCP_ALLOC_CONNS > CONFIG_NET_TCP_MAX_CONNS) - { - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(struct tcp_conn_s) * - CONFIG_NET_TCP_ALLOC_CONNS); - if (conn == NULL) - { - return conn; - } - - /* Now initialize each connection structure */ - - for (i = 0; i < CONFIG_NET_TCP_ALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - conn[i].tcpstateflags = TCP_CLOSED; - dq_addlast(&conn[i].sconn.node, &g_free_tcp_connections); - } - } - - return (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -650,17 +606,7 @@ int tcp_selectport(uint8_t domain, void tcp_initialize(void) { -#if CONFIG_NET_TCP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_TCP_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - g_tcp_connections[i].tcpstateflags = TCP_CLOSED; - dq_addlast(&g_tcp_connections[i].sconn.node, &g_free_tcp_connections); - } -#endif + NET_BUFPOOL_INIT(g_tcp_connections); } /**************************************************************************** @@ -687,7 +633,7 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) /* Return the entry from the head of the free list */ - conn = (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_tcp_connections); #ifndef CONFIG_NET_SOLINGER /* Is the free list empty? */ @@ -760,21 +706,11 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) * a new connection. */ - conn = (FAR struct tcp_conn_s *) - dq_remfirst(&g_free_tcp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_tcp_connections); } } #endif - /* Allocate the connect entry from heap */ - -#if CONFIG_NET_TCP_ALLOC_CONNS > 0 - if (conn == NULL) - { - conn = tcp_alloc_conn(); - } -#endif - net_unlock(); /* Mark the connection allocated */ @@ -972,21 +908,9 @@ void tcp_free(FAR struct tcp_conn_s *conn) conn->tcpstateflags = TCP_CLOSED; - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection structure */ -#if CONFIG_NET_TCP_ALLOC_CONNS == 1 - if (conn < g_tcp_connections || conn >= (g_tcp_connections + - CONFIG_NET_TCP_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - dq_addlast(&conn->sconn.node, &g_free_tcp_connections); - } + NET_BUFPOOL_FREE(g_tcp_connections, conn); net_unlock(); } diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c index 83a13e725ecfc..d2062b46aec56 100644 --- a/net/udp/udp_conn.c +++ b/net/udp/udp_conn.c @@ -75,18 +75,22 @@ #include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all UDP connections. */ - -#if CONFIG_NET_UDP_PREALLOC_CONNS > 0 -static struct udp_conn_s g_udp_connections[CONFIG_NET_UDP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_UDP_MAX_CONNS +# define CONFIG_NET_UDP_MAX_CONNS 0 #endif -/* A list of all free UDP connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ -static dq_queue_t g_free_udp_connections; +/* The array containing all UDP connections. */ + +NET_BUFPOOL_DECLARE(g_udp_connections, sizeof(struct udp_conn_s), + CONFIG_NET_UDP_PREALLOC_CONNS, + CONFIG_NET_UDP_ALLOC_CONNS, CONFIG_NET_UDP_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated UDP connections */ @@ -460,54 +464,6 @@ udp_ipv6_active(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, } #endif /* CONFIG_NET_IPv6 */ -/**************************************************************************** - * Name: udp_alloc_conn - * - * Description: - * Allocate a uninitialized UDP connection structure. - * - ****************************************************************************/ - -#if CONFIG_NET_UDP_ALLOC_CONNS > 0 -static FAR struct udp_conn_s *udp_alloc_conn(void) -{ - FAR struct udp_conn_s *conn; - int i; - - /* Return the entry from the head of the free list */ - - if (dq_peek(&g_free_udp_connections) == NULL) - { -#if CONFIG_NET_UDP_MAX_CONNS > 0 - if (dq_count(&g_active_udp_connections) + - CONFIG_NET_UDP_ALLOC_CONNS > CONFIG_NET_UDP_MAX_CONNS) - { - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(struct udp_conn_s) * - CONFIG_NET_UDP_ALLOC_CONNS); - if (conn == NULL) - { - return conn; - } - - /* Now initialize each connection structure */ - - for (i = 0; i < CONFIG_NET_UDP_ALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - conn[i].lport = 0; - dq_addlast(&conn[i].sconn.node, &g_free_udp_connections); - } - } - - return (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections); -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -593,17 +549,7 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u) void udp_initialize(void) { -#if CONFIG_NET_UDP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_UDP_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - g_udp_connections[i].lport = 0; - dq_addlast(&g_udp_connections[i].sconn.node, &g_free_udp_connections); - } -#endif + NET_BUFPOOL_INIT(g_udp_connections); } /**************************************************************************** @@ -623,14 +569,7 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain) nxmutex_lock(&g_free_lock); - conn = (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections); - -#if CONFIG_NET_UDP_ALLOC_CONNS > 0 - if (conn == NULL) - { - conn = udp_alloc_conn(); - } -#endif + conn = NET_BUFPOOL_TRYALLOC(g_udp_connections); if (conn) { @@ -712,23 +651,9 @@ void udp_free(FAR struct udp_conn_s *conn) #endif - /* Free the connection. - * If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_UDP_ALLOC_CONNS == 1 - if (conn < g_udp_connections || conn >= (g_udp_connections + - CONFIG_NET_UDP_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_udp_connections); - } + NET_BUFPOOL_FREE(g_udp_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/usrsock/usrsock_conn.c b/net/usrsock/usrsock_conn.c index c87703d915a67..496f248d35a1c 100644 --- a/net/usrsock/usrsock_conn.c +++ b/net/usrsock/usrsock_conn.c @@ -43,21 +43,26 @@ #include #include "usrsock/usrsock.h" +#include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all usrsock connections. */ - -#if CONFIG_NET_USRSOCK_PREALLOC_CONNS > 0 -static struct usrsock_conn_s - g_usrsock_connections[CONFIG_NET_USRSOCK_PREALLOC_CONNS]; +#ifndef CONFIG_NET_USRSOCK_MAX_CONNS +# define CONFIG_NET_USRSOCK_MAX_CONNS 0 #endif -/* A list of all free usrsock connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all usrsock connections. */ -static dq_queue_t g_free_usrsock_connections; +NET_BUFPOOL_DECLARE(g_usrsock_connections, sizeof(struct usrsock_conn_s), + CONFIG_NET_USRSOCK_PREALLOC_CONNS, + CONFIG_NET_USRSOCK_ALLOC_CONNS, + CONFIG_NET_USRSOCK_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated usrsock connections */ @@ -80,38 +85,12 @@ static dq_queue_t g_active_usrsock_connections; FAR struct usrsock_conn_s *usrsock_alloc(void) { FAR struct usrsock_conn_s *conn; -#if CONFIG_NET_USRSOCK_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NET_USRSOCK_ALLOC_CONNS > 0 - if (dq_peek(&g_free_usrsock_connections) == NULL) - { -#if CONFIG_NET_USRSOCK_MAX_CONNS > 0 - if (dq_count(&g_active_usrsock_connections) + - CONFIG_NET_USRSOCK_ALLOC_CONNS > CONFIG_NET_USRSOCK_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_USRSOCK_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_USRSOCK_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_usrsock_connections); - } - } - } -#endif - conn = (FAR struct usrsock_conn_s *) - dq_remfirst(&g_free_usrsock_connections); + conn = NET_BUFPOOL_TRYALLOC(g_usrsock_connections); if (conn) { /* Make sure that the connection is marked as uninitialized */ @@ -154,22 +133,9 @@ void usrsock_free(FAR struct usrsock_conn_s *conn) nxsem_destroy(&conn->resp.sem); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_USRSOCK_ALLOC_CONNS == 1 - if (conn < g_usrsock_connections || conn >= (g_usrsock_connections + - CONFIG_NET_USRSOCK_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_usrsock_connections); - } + NET_BUFPOOL_FREE(g_usrsock_connections, conn); nxmutex_unlock(&g_free_lock); } @@ -334,21 +300,7 @@ void usrsock_setup_datain(FAR struct usrsock_conn_s *conn, void usrsock_initialize(void) { -#if CONFIG_NET_USRSOCK_PREALLOC_CONNS > 0 - FAR struct usrsock_conn_s *conn; - int i; - - for (i = 0; i < CONFIG_NET_USRSOCK_PREALLOC_CONNS; i++) - { - conn = &g_usrsock_connections[i]; - - /* Mark the connection closed and move it to the free list */ - - conn->usockid = USRSOCK_USOCKID_INVALID; - conn->state = USRSOCK_CONN_STATE_UNINITIALIZED; - dq_addlast(&conn->sconn.node, &g_free_usrsock_connections); - } -#endif + NET_BUFPOOL_INIT(g_usrsock_connections); /* Register /dev/usrsock character device. */ diff --git a/net/utils/CMakeLists.txt b/net/utils/CMakeLists.txt index 8803381a3dccb..a960501fdbda0 100644 --- a/net/utils/CMakeLists.txt +++ b/net/utils/CMakeLists.txt @@ -33,7 +33,8 @@ set(SRCS net_snoop.c net_cmsg.c net_iob_concat.c - net_mask2pref.c) + net_mask2pref.c + net_bufpool.c) # IPv6 utilities diff --git a/net/utils/Make.defs b/net/utils/Make.defs index de2d96a28a8c5..a279cd2215144 100644 --- a/net/utils/Make.defs +++ b/net/utils/Make.defs @@ -25,6 +25,7 @@ NET_CSRCS += net_dsec2tick.c net_dsec2timeval.c net_timeval2dsec.c NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c NET_CSRCS += net_snoop.c net_cmsg.c net_iob_concat.c net_mask2pref.c +NET_CSRCS += net_bufpool.c # IPv6 utilities diff --git a/net/utils/net_bufpool.c b/net/utils/net_bufpool.c new file mode 100644 index 0000000000000..283f2748da6a1 --- /dev/null +++ b/net/utils/net_bufpool.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * net/utils/net_bufpool.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "utils/utils.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The node to store in the pool */ + +struct net_bufnode_s +{ + sq_entry_t node; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_bufpool_init + * + * Description: + * Initialize a network buffer pool. + * + * Input Parameters: + * pool - The pool to be initialized + * + ****************************************************************************/ + +void net_bufpool_init(FAR struct net_bufpool_s *pool) +{ + int i; + unsigned int maxalloc; + + if (pool->dynalloc > 0) + { + maxalloc = pool->u.maxalloc > 0 ? pool->u.maxalloc : INT16_MAX; + } + else + { + maxalloc = pool->prealloc; + } + + nxsem_init(&pool->u.sem, 0, maxalloc); + + sq_init(&pool->freebuffers); + for (i = 0; i < pool->prealloc; i++) + { + FAR struct net_bufnode_s *node = (FAR struct net_bufnode_s *) + (pool->pool + i * pool->nodesize); + sq_addlast(&node->node, &pool->freebuffers); + } +} + +/**************************************************************************** + * Name: net_bufpool_timedalloc + * + * Description: + * Allocate a buffer from the pool. If no buffer is available, then wait + * for the specified timeout. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * timeout - The maximum time to wait for a buffer to become available. + * + * Returned Value: + * A reference to the allocated buffer, which is guaranteed to be zeroed. + * NULL is returned on a timeout. + * + ****************************************************************************/ + +FAR void *net_bufpool_timedalloc(FAR struct net_bufpool_s *pool, + unsigned int timeout) +{ + FAR struct net_bufnode_s *node; + int ret; + int i; + + ret = net_sem_timedwait_uninterruptible(&pool->u.sem, timeout); + if (ret != OK) + { + return NULL; + } + + /* If we get here, then we didn't exceed maxalloc. */ + + if (pool->dynalloc > 0 && sq_peek(&pool->freebuffers) == NULL) + { + node = kmm_zalloc(pool->nodesize * pool->dynalloc); + if (node == NULL) + { + return NULL; + } + + /* Now initialize each connection structure */ + + for (i = 0; i < pool->dynalloc; i++) + { + sq_addlast(&node->node, &pool->freebuffers); + node = (FAR struct net_bufnode_s *) + ((FAR char *)node + pool->nodesize); + } + } + + return sq_remfirst(&pool->freebuffers); +} + +/**************************************************************************** + * Name: net_bufpool_free + * + * Description: + * Free a buffer from the pool. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * node - The buffer to be freed + * + ****************************************************************************/ + +void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node) +{ + if (pool->dynalloc == 1 && + ((FAR char *)node < pool->pool || + (FAR char *)node >= pool->pool + pool->prealloc * pool->nodesize)) + { + kmm_free(node); + } + else + { + FAR struct net_bufnode_s *net_bufnode = node; + + /* Set the buffer to zero, to make sure all nodes in the free buffer + * pool are zeroed. + */ + + memset(net_bufnode, 0, pool->nodesize); + sq_addlast(&net_bufnode->node, &pool->freebuffers); + } + + nxsem_post(&pool->u.sem); +} diff --git a/net/utils/utils.h b/net/utils/utils.h index d5355d03d8d67..4bd59159c800f 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -76,6 +76,33 @@ (nport) = HTONS(hport); \ } while (0) +/* Network buffer pool related macros, in which: + * pool: The name of the buffer pool + * nodesize: The size of each node in the pool + * prealloc: The number of pre-allocated buffers + * dynalloc: The number per dynamic allocations + * maxalloc: The number of max allocations, 0 means no limit + */ + +#define NET_BUFPOOL_DECLARE(pool,nodesize,prealloc,dynalloc,maxalloc) \ + static char pool##_buffer[prealloc][nodesize]; \ + static struct net_bufpool_s pool = \ + { \ + pool##_buffer[0], \ + prealloc, \ + dynalloc, \ + nodesize, \ + { \ + maxalloc \ + } \ + }; + +#define NET_BUFPOOL_INIT(p) net_bufpool_init(&p) +#define NET_BUFPOOL_TIMEDALLOC(p,t) net_bufpool_timedalloc(&p, t) +#define NET_BUFPOOL_TRYALLOC(p) net_bufpool_timedalloc(&p, 0) +#define NET_BUFPOOL_ALLOC(p) net_bufpool_timedalloc(&p, UINT_MAX) +#define NET_BUFPOOL_FREE(p,n) net_bufpool_free(&p, n) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -89,6 +116,26 @@ enum tv2ds_remainder_e TV2DS_CEIL /* Force to next larger full decisecond */ }; +/* This structure is used to manage a pool of network buffers */ + +struct net_bufpool_s +{ + /* Allocation configuration */ + + FAR char *pool; /* The beginning of the pre-allocated buffer pool */ + const int prealloc; /* The number of pre-allocated buffers */ + const int dynalloc; /* The number per dynamic allocations */ + const int nodesize; /* The size of each node in the pool */ + + union + { + int16_t maxalloc; /* The number of max allocations, used before init */ + sem_t sem; /* The semaphore for waiting for free buffers */ + } u; + + sq_queue_t freebuffers; +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -322,6 +369,53 @@ FAR void *net_ipv6_payload(FAR struct ipv6_hdr_s *ipv6, FAR uint8_t *proto); uint16_t net_iob_concat(FAR struct iob_s **iob1, FAR struct iob_s **iob2); #endif +/**************************************************************************** + * Name: net_bufpool_init + * + * Description: + * Initialize a network buffer pool. + * + * Input Parameters: + * pool - The pool to be initialized + * + ****************************************************************************/ + +void net_bufpool_init(FAR struct net_bufpool_s *pool); + +/**************************************************************************** + * Name: net_bufpool_timedalloc + * + * Description: + * Allocate a buffer from the pool. If no buffer is available, then wait + * for the specified timeout. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * timeout - The maximum time to wait for a buffer to become available. + * + * Returned Value: + * A reference to the allocated buffer, which is guaranteed to be zeroed. + * NULL is returned on a timeout. + * + ****************************************************************************/ + +FAR void *net_bufpool_timedalloc(FAR struct net_bufpool_s *pool, + unsigned int timeout); + +/**************************************************************************** + * Name: net_bufpool_free + * + * Description: + * Free a buffer from the pool. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * node - The buffer to be freed + * + ****************************************************************************/ + +void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node); + /**************************************************************************** * Name: net_chksum_adjust * From 48e57b046d9638d2438508d472ffe09047da37dd Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Wed, 18 Dec 2024 15:30:59 +0800 Subject: [PATCH 2/2] net: Optimize ipfwd and wrbuffer by buffer pool To allow dynamic allocation of these structs, performance keeps the same as the previous implementation. Signed-off-by: Zhe Weng --- net/ipforward/Kconfig | 18 +++++++++ net/ipforward/ipfwd_alloc.c | 40 +++++-------------- net/tcp/Kconfig | 14 +++++++ net/tcp/tcp_wrbuffer.c | 63 ++++-------------------------- net/udp/Kconfig | 14 +++++++ net/udp/udp_wrbuffer.c | 76 ++++++------------------------------- net/utils/net_bufpool.c | 25 ++++++++++++ net/utils/utils.h | 14 +++++++ 8 files changed, 113 insertions(+), 151 deletions(-) diff --git a/net/ipforward/Kconfig b/net/ipforward/Kconfig index 3be48eac75998..96cf02104b470 100644 --- a/net/ipforward/Kconfig +++ b/net/ipforward/Kconfig @@ -40,3 +40,21 @@ config NET_IPFORWARD_NSTRUCT WARNING: DO NOT set this setting to a value greater than or equal to CONFIG_IOB_NBUFFERS, otherwise it may consume all the IOB and let netdev fail to work. + +config NET_IPFORWARD_ALLOC_STRUCT + int "Dynamic forwarding structures allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled + + When set to 1 a new forwarding structure will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the forwarding structures + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + forwarding structures pool, and it will never be deallocated! + + Note: maximum number of allocated forwarding structures is limited + to CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE to avoid consuming all + the IOBs. diff --git a/net/ipforward/ipfwd_alloc.c b/net/ipforward/ipfwd_alloc.c index b0b5536dea8a5..dc3fb31ec0d52 100644 --- a/net/ipforward/ipfwd_alloc.c +++ b/net/ipforward/ipfwd_alloc.c @@ -37,6 +37,7 @@ #include #include "ipforward/ipforward.h" +#include "utils/utils.h" #ifdef CONFIG_NET_IPFORWARD @@ -66,13 +67,12 @@ * Private Data ****************************************************************************/ -/* This is an array of pre-allocating forwarding structures */ +/* This is the state of the global forwarding structures */ -static struct forward_s g_fwdpool[CONFIG_NET_IPFORWARD_NSTRUCT]; - -/* This is a list of free forwarding structures */ - -static FAR struct forward_s *g_fwdfree; +NET_BUFPOOL_DECLARE(g_fwdpool, sizeof(struct forward_s), + CONFIG_NET_IPFORWARD_NSTRUCT, + CONFIG_NET_IPFORWARD_ALLOC_STRUCT, + CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE); /**************************************************************************** * Public Functions @@ -91,25 +91,13 @@ static FAR struct forward_s *g_fwdfree; void ipfwd_initialize(void) { - FAR struct forward_s *fwd; - int i; - /* The IOB size must be such that the maximum L2 and L3 headers fit into * the contiguous memory of the first IOB in the IOB chain. */ DEBUGASSERT(MAX_HDRLEN <= CONFIG_IOB_BUFSIZE); - /* Add all pre-allocated forwarding structures to the free list */ - - g_fwdfree = NULL; - - for (i = 0; i < CONFIG_NET_IPFORWARD_NSTRUCT; i++) - { - fwd = &g_fwdpool[i]; - fwd->f_flink = g_fwdfree; - g_fwdfree = fwd; - } + NET_BUFPOOL_INIT(g_fwdpool); } /**************************************************************************** @@ -127,16 +115,7 @@ void ipfwd_initialize(void) FAR struct forward_s *ipfwd_alloc(void) { - FAR struct forward_s *fwd; - - fwd = g_fwdfree; - if (fwd != NULL) - { - g_fwdfree = fwd->f_flink; - memset (fwd, 0, sizeof(struct forward_s)); - } - - return fwd; + return NET_BUFPOOL_TRYALLOC(g_fwdpool); } /**************************************************************************** @@ -153,8 +132,7 @@ FAR struct forward_s *ipfwd_alloc(void) void ipfwd_free(FAR struct forward_s *fwd) { - fwd->f_flink = g_fwdfree; - g_fwdfree = fwd; + NET_BUFPOOL_FREE(g_fwdpool, fwd); } #endif /* CONFIG_NET_IPFORWARD */ diff --git a/net/tcp/Kconfig b/net/tcp/Kconfig index fd2bcec121177..28ce864133a06 100644 --- a/net/tcp/Kconfig +++ b/net/tcp/Kconfig @@ -259,6 +259,20 @@ config NET_TCP_NWRBCHAINS choice for this value would be the same as the maximum number of TCP connections. +config NET_TCP_ALLOC_WRBCHAINS + int "Dynamic I/O buffer chain heads allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled + + When set to 1 a new I/O buffer chain head will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the I/O buffer chain heads + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + I/O buffer chain heads pool, and it will never be deallocated! + config NET_TCP_WRBUFFER_DEBUG bool "Force write buffer debug" default n diff --git a/net/tcp/tcp_wrbuffer.c b/net/tcp/tcp_wrbuffer.c index 4e426736092f3..e3fbf333bbfae 100644 --- a/net/tcp/tcp_wrbuffer.c +++ b/net/tcp/tcp_wrbuffer.c @@ -48,34 +48,15 @@ #if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_TCP_WRITE_BUFFERS) -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* Package all globals used by this logic into a structure */ - -struct wrbuffer_s -{ - /* The semaphore to protect the buffers */ - - sem_t sem; - - /* This is the list of available write buffers */ - - sq_queue_t freebuffers; - - /* These are the pre-allocated write buffers */ - - struct tcp_wrbuffer_s buffers[CONFIG_NET_TCP_NWRBCHAINS]; -}; - /**************************************************************************** * Private Data ****************************************************************************/ /* This is the state of the global write buffer resource */ -static struct wrbuffer_s g_wrbuffer; +NET_BUFPOOL_DECLARE(g_wrbuffer, sizeof(struct tcp_wrbuffer_s), + CONFIG_NET_TCP_NWRBCHAINS, + CONFIG_NET_TCP_ALLOC_WRBCHAINS, 0); /**************************************************************************** * Public Functions @@ -94,16 +75,7 @@ static struct wrbuffer_s g_wrbuffer; void tcp_wrbuffer_initialize(void) { - int i; - - sq_init(&g_wrbuffer.freebuffers); - - nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_TCP_NWRBCHAINS); - - for (i = 0; i < CONFIG_NET_TCP_NWRBCHAINS; i++) - { - sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); - } + NET_BUFPOOL_INIT(g_wrbuffer); } /**************************************************************************** @@ -127,7 +99,6 @@ void tcp_wrbuffer_initialize(void) FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout) { FAR struct tcp_wrbuffer_s *wrb; - int ret; /* We need to allocate two things: (1) A write buffer structure and (2) * at least one I/O buffer to start the chain. @@ -137,20 +108,12 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout) * buffer */ - ret = net_sem_timedwait_uninterruptible(&g_wrbuffer.sem, timeout); - if (ret != OK) + wrb = NET_BUFPOOL_TIMEDALLOC(g_wrbuffer, timeout); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = net_iobtimedalloc(true, timeout); @@ -247,8 +210,7 @@ void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb) /* Then free the write buffer structure */ - sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); - nxsem_post(&g_wrbuffer.sem); + NET_BUFPOOL_FREE(g_wrbuffer, wrb); } /**************************************************************************** @@ -304,16 +266,7 @@ uint32_t tcp_wrbuffer_inqueue_size(FAR struct tcp_conn_s *conn) int tcp_wrbuffer_test(void) { - int val = 0; - int ret; - - ret = nxsem_get_value(&g_wrbuffer.sem, &val); - if (ret >= 0) - { - ret = val > 0 ? OK : -ENOSPC; - } - - return ret; + return NET_BUFPOOL_TEST(g_wrbuffer); } #endif /* CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */ diff --git a/net/udp/Kconfig b/net/udp/Kconfig index e147b7a608a90..a094e2850b9af 100644 --- a/net/udp/Kconfig +++ b/net/udp/Kconfig @@ -103,6 +103,20 @@ config NET_UDP_NWRBCHAINS choice for this value would be the same as the maximum number of UDP connections. +config NET_UDP_ALLOC_WRBCHAINS + int "Dynamic I/O buffer chain heads allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled. + + When set to 1 a new I/O buffer chain head will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the I/O buffer chain heads + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + I/O buffer chain heads pool, and it will never be deallocated! + config NET_UDP_WRBUFFER_DEBUG bool "Force write buffer debug" default n diff --git a/net/udp/udp_wrbuffer.c b/net/udp/udp_wrbuffer.c index 0b9846c77f66e..37ca4b580c3fa 100644 --- a/net/udp/udp_wrbuffer.c +++ b/net/udp/udp_wrbuffer.c @@ -47,34 +47,15 @@ #include "utils/utils.h" #include "udp/udp.h" -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* Package all globals used by this logic into a structure */ - -struct wrbuffer_s -{ - /* The semaphore to protect the buffers */ - - sem_t sem; - - /* This is the list of available write buffers */ - - sq_queue_t freebuffers; - - /* These are the pre-allocated write buffers */ - - struct udp_wrbuffer_s buffers[CONFIG_NET_UDP_NWRBCHAINS]; -}; - /**************************************************************************** * Private Data ****************************************************************************/ /* This is the state of the global write buffer resource */ -static struct wrbuffer_s g_wrbuffer; +NET_BUFPOOL_DECLARE(g_wrbuffer, sizeof(struct udp_wrbuffer_s), + CONFIG_NET_UDP_NWRBCHAINS, + CONFIG_NET_UDP_ALLOC_WRBCHAINS, 0); /**************************************************************************** * Public Functions @@ -93,16 +74,7 @@ static struct wrbuffer_s g_wrbuffer; void udp_wrbuffer_initialize(void) { - int i; - - sq_init(&g_wrbuffer.freebuffers); - - nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_UDP_NWRBCHAINS); - - for (i = 0; i < CONFIG_NET_UDP_NWRBCHAINS; i++) - { - sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); - } + NET_BUFPOOL_INIT(g_wrbuffer); } /**************************************************************************** @@ -133,15 +105,8 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void) * buffer */ - net_sem_wait_uninterruptible(&g_wrbuffer.sem); - - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); + wrb = NET_BUFPOOL_ALLOC(g_wrbuffer); DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); /* Now get the first I/O buffer for the write buffer structure */ @@ -177,7 +142,6 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void) FAR struct udp_wrbuffer_s *udp_wrbuffer_timedalloc(unsigned int timeout) { FAR struct udp_wrbuffer_s *wrb; - int ret; /* We need to allocate two things: (1) A write buffer structure and (2) * at least one I/O buffer to start the chain. @@ -187,20 +151,12 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_timedalloc(unsigned int timeout) * buffer */ - ret = net_sem_timedwait_uninterruptible(&g_wrbuffer.sem, timeout); - if (ret != OK) + wrb = NET_BUFPOOL_TIMEDALLOC(g_wrbuffer, timeout); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = net_iobtimedalloc(true, timeout); @@ -253,19 +209,12 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_tryalloc(void) * buffer */ - if (nxsem_trywait(&g_wrbuffer.sem) != OK) + wrb = NET_BUFPOOL_TRYALLOC(g_wrbuffer); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = @@ -312,8 +261,7 @@ void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb) /* Then free the write buffer structure */ - sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); - nxsem_post(&g_wrbuffer.sem); + NET_BUFPOOL_FREE(g_wrbuffer, wrb); } /**************************************************************************** @@ -363,9 +311,7 @@ uint32_t udp_wrbuffer_inqueue_size(FAR struct udp_conn_s *conn) int udp_wrbuffer_test(void) { - int val = 0; - nxsem_get_value(&g_wrbuffer.sem, &val); - return val > 0 ? OK : -ENOSPC; + return NET_BUFPOOL_TEST(g_wrbuffer); } #endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */ diff --git a/net/utils/net_bufpool.c b/net/utils/net_bufpool.c index 283f2748da6a1..8e65ced82ddae 100644 --- a/net/utils/net_bufpool.c +++ b/net/utils/net_bufpool.c @@ -170,3 +170,28 @@ void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node) nxsem_post(&pool->u.sem); } + +/**************************************************************************** + * Name: net_bufpool_test + * + * Description: + * Check if there is room in the buffer pool. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +int net_bufpool_test(FAR struct net_bufpool_s *pool) +{ + int val = 0; + int ret; + + ret = nxsem_get_value(&pool->u.sem, &val); + if (ret >= 0) + { + ret = val > 0 ? OK : -ENOSPC; + } + + return ret; +} diff --git a/net/utils/utils.h b/net/utils/utils.h index 4bd59159c800f..fa05c2690cb61 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -102,6 +102,7 @@ #define NET_BUFPOOL_TRYALLOC(p) net_bufpool_timedalloc(&p, 0) #define NET_BUFPOOL_ALLOC(p) net_bufpool_timedalloc(&p, UINT_MAX) #define NET_BUFPOOL_FREE(p,n) net_bufpool_free(&p, n) +#define NET_BUFPOOL_TEST(p) net_bufpool_test(&p) /**************************************************************************** * Public Types @@ -416,6 +417,19 @@ FAR void *net_bufpool_timedalloc(FAR struct net_bufpool_s *pool, void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node); +/**************************************************************************** + * Name: net_bufpool_test + * + * Description: + * Check if there is room in the buffer pool. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +int net_bufpool_test(FAR struct net_bufpool_s *pool); + /**************************************************************************** * Name: net_chksum_adjust *