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 <wengzhe@xiaomi.com>
This commit is contained in:
parent
1fe07d0838
commit
84d261e3be
8 changed files with 113 additions and 151 deletions
|
@ -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.
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <nuttx/net/icmpv6.h>
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue