Improvements in UDP connections allocation.

This commit is contained in:
Fotis Panagiotopoulos 2023-02-02 16:20:55 +02:00 committed by Xiang Xiao
parent 8f9dfe0be1
commit 7f3591b9cc
6 changed files with 81 additions and 29 deletions

View file

@ -42,7 +42,7 @@ CONFIG_NET_BROADCAST=y
CONFIG_NET_ICMP=y
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_UDP=y
CONFIG_NET_UDP_CONNS=16
CONFIG_NET_UDP_PREALLOC_CONNS=16
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=268435456
CONFIG_RAM_START=0x20000000

View file

@ -40,7 +40,7 @@ CONFIG_NET_BROADCAST=y
CONFIG_NET_ICMP=y
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_UDP=y
CONFIG_NET_UDP_CONNS=16
CONFIG_NET_UDP_PREALLOC_CONNS=16
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=268435456
CONFIG_RAM_START=0x20000000

View file

@ -377,7 +377,7 @@ ViewTool DP83848 Ethernet Module
CONFIG_NET_NTCP_READAHEAD_BUFFERS=8
CONFIG_NET_UDP=y : UDP support
CONFIG_NET_UDP_CONNS=8
CONFIG_NET_UDP_PREALLOC_CONNS=8
CONFIG_NET_ICMP=y : ICMP support
CONFIG_NET_ICMP_SOCKET=y

View file

@ -288,16 +288,6 @@
/* UDP configuration options */
/* The maximum amount of concurrent UDP connection, Default: 10 */
#ifndef CONFIG_NET_UDP_CONNS
# ifdef CONFIG_NET_UDP
# define CONFIG_NET_UDP_CONNS 10
# else
# define CONFIG_NET_UDP_CONNS 0
# endif
#endif
/* The UDP maximum packet size. This should not be set to more than
* NETDEV_PKTSIZE(d) - NET_LL_HDRLEN(dev) - __UDP_HDRLEN - IPv*_HDRLEN.
*/
@ -432,7 +422,7 @@
#ifndef CONFIG_NET_NACTIVESOCKETS
# define CONFIG_NET_NACTIVESOCKETS (CONFIG_NET_TCP_PREALLOC_CONNS + \
CONFIG_NET_UDP_CONNS)
CONFIG_NET_UDP_PREALLOC_CONNS)
#endif
/* The initial retransmission timeout counted in timer pulses.

View file

@ -36,11 +36,46 @@ config NET_UDP_CHECKSUMS
Enable/disable UDP checksum support. UDP checksum support is
REQUIRED for IPv6.
config NET_UDP_CONNS
int "Number of UDP sockets"
config NET_UDP_PREALLOC_CONNS
int "Preallocated UDP sockets"
default 8
---help---
The maximum amount of open concurrent UDP sockets
Number of UDP 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_UDP_ALLOC_CONNS
int "Dynamic UDP connections allocation"
default 0
---help---
Dynamic memory allocations for UDP.
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_UDP_MAX_CONNS
int "Maximum number of UDP connections"
default 0
depends on NET_UDP_ALLOC_CONNS > 0
---help---
If dynamic connections allocation is selected (NET_UDP_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_UDP_NPOLLWAITERS
int "Number of UDP poll waiters"

View file

@ -76,8 +76,8 @@
/* The array containing all UDP connections. */
#ifndef CONFIG_NET_ALLOC_CONNS
struct udp_conn_s g_udp_connections[CONFIG_NET_UDP_CONNS];
#if CONFIG_NET_UDP_PREALLOC_CONNS > 0
struct udp_conn_s g_udp_connections[CONFIG_NET_UDP_PREALLOC_CONNS];
#endif
/* A list of all free UDP connections */
@ -462,7 +462,7 @@ static inline FAR struct udp_conn_s *
*
****************************************************************************/
#ifdef CONFIG_NET_ALLOC_CONNS
#if CONFIG_NET_UDP_ALLOC_CONNS > 0
FAR struct udp_conn_s *udp_alloc_conn(void)
{
FAR struct udp_conn_s *conn;
@ -472,8 +472,16 @@ FAR struct udp_conn_s *udp_alloc_conn(void)
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_CONNS);
CONFIG_NET_UDP_ALLOC_CONNS);
if (conn == NULL)
{
return conn;
@ -481,7 +489,7 @@ FAR struct udp_conn_s *udp_alloc_conn(void)
/* Now initialize each connection structure */
for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
for (i = 0; i < CONFIG_NET_UDP_ALLOC_CONNS; i++)
{
/* Mark the connection closed and move it to the free list */
@ -585,10 +593,10 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
void udp_initialize(void)
{
#ifndef CONFIG_NET_ALLOC_CONNS
#if CONFIG_NET_UDP_PREALLOC_CONNS > 0
int i;
for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
for (i = 0; i < CONFIG_NET_UDP_PREALLOC_CONNS; i++)
{
/* Mark the connection closed and move it to the free list */
@ -614,11 +622,16 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
/* The free list is protected by a mutex. */
nxmutex_lock(&g_free_lock);
#ifndef CONFIG_NET_ALLOC_CONNS
conn = (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections);
#else
conn = udp_alloc_conn();
#if CONFIG_NET_UDP_ALLOC_CONNS > 0
if (conn == NULL)
{
conn = udp_alloc_conn();
}
#endif
if (conn)
{
/* Make sure that the connection is marked as uninitialized */
@ -703,9 +716,23 @@ void udp_free(FAR struct udp_conn_s *conn)
memset(conn, 0, sizeof(*conn));
/* Free the connection */
/* 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_UDP_ALLOC_CONNS == 1
if (conn < g_udp_connections || conn >= (g_udp_connections +
CONFIG_NET_UDP_PREALLOC_CONNS))
{
kmm_free(conn);
}
else
#endif
{
dq_addlast(&conn->sconn.node, &g_free_udp_connections);
}
dq_addlast(&conn->sconn.node, &g_free_udp_connections);
nxmutex_unlock(&g_free_lock);
}