Skip to content

Commit

Permalink
net: Optimize ipfwd and wrbuffer by buffer pool
Browse files Browse the repository at this point in the history
Signed-off-by: Zhe Weng <[email protected]>
  • Loading branch information
wengzhe committed Dec 19, 2024
1 parent cc2cfe3 commit 9e562cd
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 153 deletions.
20 changes: 19 additions & 1 deletion net/ipforward/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ config NET_IPFORWARD_BROADCAST
If selected, broadcast packets received on one network device will
be forwarded though other network devices.

config NET_IPFORWARD_NSTRUCT
config NET_IPFORWARD_PREALLOC_STRUCT
int "Number of pre-allocated forwarding structures"
default 4
depends on NET_IPFORWARD
Expand All @@ -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_PREALLOC_STRUCT,
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 */
16 changes: 15 additions & 1 deletion net/tcp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ config NET_TCP_WRITE_BUFFERS

if NET_TCP_WRITE_BUFFERS

config NET_TCP_NWRBCHAINS
config NET_TCP_PREALLOC_WRBCHAINS
int "Number of pre-allocated I/O buffer chain heads"
default 8
---help---
Expand All @@ -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_PREALLOC_WRBCHAINS,
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 */
16 changes: 15 additions & 1 deletion net/udp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ config NET_UDP_WRITE_BUFFERS

if NET_UDP_WRITE_BUFFERS

config NET_UDP_NWRBCHAINS
config NET_UDP_PREALLOC_WRBCHAINS
int "Number of pre-allocated I/O buffer chain heads"
default 8
---help---
Expand All @@ -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 9e562cd

Please sign in to comment.