Skip to content

Commit

Permalink
net: Optimize ipfwd and wrbuffer by buffer pool
Browse files Browse the repository at this point in the history
To allow dynamic allocation of these structs, performance keeps the same
as the previous implementation.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
  • Loading branch information
wengzhe authored and xiaoxiang781216 committed Jan 1, 2025
1 parent 34e1fca commit b2ca642
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 151 deletions.
18 changes: 18 additions & 0 deletions net/ipforward/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
40 changes: 9 additions & 31 deletions net/ipforward/ipfwd_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <nuttx/net/icmpv6.h>

#include "ipforward/ipforward.h"
#include "utils/utils.h"

#ifdef CONFIG_NET_IPFORWARD

Expand Down Expand Up @@ -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
Expand All @@ -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);
}

/****************************************************************************
Expand All @@ -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);
}

/****************************************************************************
Expand All @@ -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 */
14 changes: 14 additions & 0 deletions net/tcp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 8 additions & 55 deletions net/tcp/tcp_wrbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

/****************************************************************************
Expand All @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

/****************************************************************************
Expand Down Expand Up @@ -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 */
14 changes: 14 additions & 0 deletions net/udp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit b2ca642

Please sign in to comment.