net: Add net_buf pool support to each context
User can configure its own pools for data that needs to be transmitted out (TX). This helps to avoid deadlocking the system if user space application uses all the buffers in the system, and the core IP stack tries to get buffer that needs to be sent out. By default the net_buf pool support in net_context is turned off as application developer needs to create the pools and tie them to desired contexts. Change-Id: Ida4a1771d34d6c250974e56fba4f0e0b2592cb29 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
9fce1626d7
commit
7719cee113
8 changed files with 367 additions and 44 deletions
|
@ -313,12 +313,42 @@ static inline void net_nbuf_set_src_ipv6_addr(struct net_buf *buf)
|
|||
|
||||
/* @endcond */
|
||||
|
||||
/**
|
||||
* @brief Create a TX net_buf pool that is used when sending user
|
||||
* specified data to network.
|
||||
*
|
||||
* @param name Name of the pool.
|
||||
* @param count Number of net_buf in this pool.
|
||||
*/
|
||||
#define NET_NBUF_TX_POOL_DEFINE(name, count) \
|
||||
NET_BUF_POOL_DEFINE(name, count, 0, sizeof(struct net_nbuf), NULL)
|
||||
|
||||
/**
|
||||
* @brief Create a DATA net_buf pool that is used when sending user
|
||||
* specified data to network.
|
||||
*
|
||||
* @param name Name of the pool.
|
||||
* @param count Number of net_buf in this pool.
|
||||
*/
|
||||
#define NET_NBUF_DATA_POOL_DEFINE(name, count) \
|
||||
NET_BUF_POOL_DEFINE(name, count, CONFIG_NET_NBUF_DATA_SIZE, \
|
||||
CONFIG_NET_NBUF_USER_DATA_SIZE, NULL)
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
|
||||
/* Debug versions of the nbuf functions that are used when tracking
|
||||
* buffer usage.
|
||||
*/
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_debug(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout,
|
||||
const char *caller,
|
||||
int line);
|
||||
#define net_nbuf_get_reserve(pool, reserve_head, timeout) \
|
||||
net_nbuf_get_reserve_debug(pool, reserve_head, timeout, \
|
||||
__func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
|
||||
int32_t timeout,
|
||||
const char *caller, int line);
|
||||
|
@ -355,6 +385,12 @@ struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
|
|||
#define net_nbuf_get_reserve_data(res, timeout) \
|
||||
net_nbuf_get_reserve_data_debug(res, timeout, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_frag_debug(struct net_buf *buf,
|
||||
int32_t timeout,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_frag(buf, timeout) \
|
||||
net_nbuf_get_frag_debug(buf, timeout, __func__, __LINE__)
|
||||
|
||||
void net_nbuf_unref_debug(struct net_buf *buf, const char *caller, int line);
|
||||
#define net_nbuf_unref(buf) net_nbuf_unref_debug(buf, __func__, __LINE__)
|
||||
|
||||
|
@ -376,6 +412,24 @@ void net_nbuf_print_frags(struct net_buf *buf);
|
|||
|
||||
#define net_nbuf_print_frags(...)
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the given buffer pool.
|
||||
*
|
||||
* @details Get network buffer from the specific buffer pool.
|
||||
*
|
||||
* @param pool Network buffer pool.
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
* @param timeout Affects the action taken should the net buf pool be empty.
|
||||
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
|
||||
* wait as long as necessary. Otherwise, wait up to the specified
|
||||
* number of milliseconds before timing out.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the RX buffers pool.
|
||||
*
|
||||
|
@ -484,6 +538,22 @@ struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head,
|
|||
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head,
|
||||
int32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Get a data fragment that might be from user specific
|
||||
* buffer pool or from global DATA pool.
|
||||
*
|
||||
* @param buf Network buffer. This must be the first buffer of the
|
||||
* buffer chain with user data part in it.
|
||||
* @param timeout Affects the action taken should the net buf pool be empty.
|
||||
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
|
||||
* wait as long as necessary. Otherwise, wait up to the specified
|
||||
* number of milliseconds before timing out.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_frag(struct net_buf *buf,
|
||||
int32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Place buffer back into the available buffers pool.
|
||||
*
|
||||
|
|
|
@ -139,6 +139,19 @@ typedef void (*net_context_connect_cb_t)(struct net_context *context,
|
|||
int status,
|
||||
void *user_data);
|
||||
|
||||
/* The net_nbuf_get_pool_func_t is here in order to avoid circular
|
||||
* dependency between nbuf.h and net_context.h
|
||||
*/
|
||||
/**
|
||||
* @typedef net_nbuf_get_pool_func_t
|
||||
*
|
||||
* @brief Function that is called to get the pool that is used
|
||||
* for net_buf allocations.
|
||||
*
|
||||
* @return Pointer to valid struct net_buf_pool instance.
|
||||
*/
|
||||
typedef struct net_buf_pool *(*net_nbuf_get_pool_func_t)(void);
|
||||
|
||||
struct net_tcp;
|
||||
|
||||
struct net_conn_handle;
|
||||
|
@ -184,6 +197,16 @@ struct net_context {
|
|||
*/
|
||||
void *user_data;
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
/** Get TX net_buf pool for this context.
|
||||
*/
|
||||
net_nbuf_get_pool_func_t tx_pool;
|
||||
|
||||
/** Get DATA net_buf pool for this context.
|
||||
*/
|
||||
net_nbuf_get_pool_func_t data_pool;
|
||||
#endif /* CONFIG_NET_CONTEXT_NBUF_POOL */
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
|
||||
/**
|
||||
* Semaphore to signal synchronous recv call completion.
|
||||
|
@ -697,6 +720,35 @@ typedef void (*net_context_cb_t)(struct net_context *context, void *user_data);
|
|||
*/
|
||||
void net_context_foreach(net_context_cb_t cb, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Create network buffer pool that is used by the IP stack
|
||||
* to allocate network buffers that are used by the context when
|
||||
* sending data to network.
|
||||
*
|
||||
* @param context Context that will use the given net_buf pools.
|
||||
* @param tx_pool Pointer to the function that will return TX pool
|
||||
* to the caller. The TX pool is used when sending data to network.
|
||||
* There is one TX net_buf for each network packet that is sent.
|
||||
* @param data_pool Pointer to the function that will return DATA pool
|
||||
* to the caller. The DATA pool is used to store data that is sent to
|
||||
* the network.
|
||||
*/
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
static inline void net_context_setup_pools(struct net_context *context,
|
||||
net_nbuf_get_pool_func_t tx_pool,
|
||||
net_nbuf_get_pool_func_t data_pool)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
NET_ASSERT(tx_pool);
|
||||
NET_ASSERT(data_pool);
|
||||
|
||||
context->tx_pool = tx_pool;
|
||||
context->data_pool = data_pool;
|
||||
}
|
||||
#else
|
||||
#define net_context_setup_pools(context, tx_pool, data_pool)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -149,6 +149,17 @@ config NET_MAX_CONTEXTS
|
|||
is used when listening or sending network traffic. This is very
|
||||
similar as one could call a network socket in some other systems.
|
||||
|
||||
config NET_CONTEXT_NBUF_POOL
|
||||
bool "Enable net_buf TX pool / context"
|
||||
default n
|
||||
help
|
||||
If enabled, then it is possible to fine-tune network buffer pool
|
||||
for each context when sending network data. If this setting is
|
||||
enabled, then you should define the context pools in your application
|
||||
using NET_NBUF_TX_POOL_DEFINE() and NET_NBUF_DATA_POOL_DEFINE()
|
||||
macros and tie these pools to desired context using the
|
||||
net_context_setup_pools() function.
|
||||
|
||||
config NET_CONTEXT_SYNC_RECV
|
||||
bool "Support synchronous functionality in net_context_recv() API"
|
||||
default y
|
||||
|
|
|
@ -30,7 +30,7 @@ struct net_buf *net_ipv4_create_raw(struct net_buf *buf,
|
|||
{
|
||||
struct net_buf *header;
|
||||
|
||||
header = net_nbuf_get_reserve_data(reserve, K_FOREVER);
|
||||
header = net_nbuf_get_frag(buf, K_FOREVER);
|
||||
|
||||
net_buf_frag_insert(buf, header);
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ struct net_buf *net_ipv6_create_raw(struct net_buf *buf,
|
|||
{
|
||||
struct net_buf *header;
|
||||
|
||||
header = net_nbuf_get_reserve_data(reserve, K_FOREVER);
|
||||
header = net_nbuf_get_frag(buf, K_FOREVER);
|
||||
|
||||
net_buf_frag_insert(buf, header);
|
||||
|
||||
|
@ -550,7 +550,7 @@ static struct net_buf *update_ll_reserve(struct net_buf *buf,
|
|||
|
||||
while (orig_frag) {
|
||||
if (!room_len) {
|
||||
frag = net_nbuf_get_reserve_data(reserve, K_FOREVER);
|
||||
frag = net_nbuf_get_frag(buf, K_FOREVER);
|
||||
|
||||
net_buf_frag_add(buf, frag);
|
||||
|
||||
|
|
|
@ -116,9 +116,46 @@ static inline int16_t get_frees(struct net_buf_pool *pool)
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline bool is_data_pool(struct net_buf_pool *pool)
|
||||
{
|
||||
/* The user data can only be found in TX/RX pool and it
|
||||
* is always the size of struct net_nbuf.
|
||||
*/
|
||||
if (pool->user_data_size != sizeof(struct net_nbuf)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_from_data_pool(struct net_buf *buf)
|
||||
{
|
||||
return (buf->pool == &data_buffers);
|
||||
return is_data_pool(buf->pool);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
static inline struct net_buf_pool *get_tx_pool(struct net_context *context)
|
||||
{
|
||||
return context->tx_pool();
|
||||
}
|
||||
|
||||
static inline struct net_buf_pool *get_data_pool(struct net_context *context)
|
||||
{
|
||||
return context->data_pool();
|
||||
}
|
||||
#else
|
||||
#define get_tx_pool(context) NULL
|
||||
#define get_data_pool(context) NULL
|
||||
#endif /* CONFIG_NET_CONTEXT_NBUF_POOL */
|
||||
|
||||
static inline bool is_external_pool(struct net_buf_pool *pool)
|
||||
{
|
||||
if (pool != &rx_buffers && pool != &tx_buffers &&
|
||||
pool != &data_buffers) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
|
@ -130,6 +167,8 @@ static inline const char *pool2str(struct net_buf_pool *pool)
|
|||
return "TX";
|
||||
} else if (pool == &data_buffers) {
|
||||
return "DATA";
|
||||
} else if (is_data_pool(pool)) {
|
||||
return "EDATA";
|
||||
}
|
||||
|
||||
return "EXTERNAL";
|
||||
|
@ -167,15 +206,15 @@ void net_nbuf_print_frags(struct net_buf *buf)
|
|||
count * ll_overhead, (total * 100) / (count * frag_size));
|
||||
}
|
||||
|
||||
static struct net_buf *net_nbuf_get_reserve_debug(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout,
|
||||
const char *caller,
|
||||
int line)
|
||||
struct net_buf *net_nbuf_get_reserve_debug(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout,
|
||||
const char *caller,
|
||||
int line)
|
||||
#else /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout)
|
||||
struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
|
||||
uint16_t reserve_head,
|
||||
int32_t timeout)
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
{
|
||||
struct net_buf *buf = NULL;
|
||||
|
@ -195,7 +234,7 @@ static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (pool == &data_buffers) {
|
||||
if (is_data_pool(pool)) {
|
||||
/* The buf->data will point to the start of the L3
|
||||
* header (like IPv4 or IPv6 packet header).
|
||||
*/
|
||||
|
@ -206,13 +245,60 @@ static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
|
|||
|
||||
NET_BUF_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1);
|
||||
|
||||
NET_DBG("%s [%d] buf %p reserve %u ref %d (%s():%d)",
|
||||
pool2str(pool), get_frees(pool),
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
NET_DBG("%s (%p) [%d] buf %p reserve %u ref %d (%s():%d)",
|
||||
pool2str(pool), pool, get_frees(pool),
|
||||
buf, reserve_head, buf->ref, caller, line);
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Get a fragment, try to figure out the pool from where to get
|
||||
* the data.
|
||||
*/
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
struct net_buf *net_nbuf_get_frag_debug(struct net_buf *buf,
|
||||
int32_t timeout,
|
||||
const char *caller, int line)
|
||||
#else
|
||||
struct net_buf *net_nbuf_get_frag(struct net_buf *buf,
|
||||
int32_t timeout)
|
||||
#endif
|
||||
{
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
struct net_context *context;
|
||||
#endif
|
||||
|
||||
if (is_from_data_pool(buf)) {
|
||||
/* We cannot know the correct data pool in this case (because
|
||||
* we do not know the context). Return error to the caller.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
context = net_nbuf_context(buf);
|
||||
if (context && context->data_pool) {
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
return net_nbuf_get_reserve_debug(context->data_pool(),
|
||||
net_nbuf_ll_reserve(buf),
|
||||
timeout, caller, line);
|
||||
#else
|
||||
return net_nbuf_get_reserve(context->data_pool(),
|
||||
net_nbuf_ll_reserve(buf), timeout);
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
}
|
||||
#endif /* CONFIG_NET_CONTEXT_NBUF_POOL */
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
return net_nbuf_get_reserve_data_debug(net_nbuf_ll_reserve(buf),
|
||||
timeout, caller, line);
|
||||
#else
|
||||
return net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf), timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
|
||||
int32_t timeout,
|
||||
|
@ -300,7 +386,7 @@ static struct net_buf *net_nbuf_get(struct net_buf_pool *pool,
|
|||
return buf;
|
||||
}
|
||||
|
||||
if (pool != &data_buffers) {
|
||||
if (!is_data_pool(pool)) {
|
||||
net_nbuf_set_context(buf, context);
|
||||
net_nbuf_set_ll_reserve(buf, reserve);
|
||||
net_nbuf_set_iface(buf, iface);
|
||||
|
@ -326,15 +412,20 @@ struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
|
|||
int32_t timeout,
|
||||
const char *caller, int line)
|
||||
{
|
||||
return net_nbuf_get_debug(&tx_buffers, context, timeout, caller, line);
|
||||
struct net_buf_pool *pool = get_tx_pool(context);
|
||||
|
||||
return net_nbuf_get_debug(pool ? pool : &tx_buffers, context,
|
||||
timeout, caller, line);
|
||||
}
|
||||
|
||||
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
|
||||
int32_t timeout,
|
||||
const char *caller, int line)
|
||||
{
|
||||
return net_nbuf_get_debug(&data_buffers, context, timeout,
|
||||
caller, line);
|
||||
struct net_buf_pool *pool = get_data_pool(context);
|
||||
|
||||
return net_nbuf_get_debug(pool ? pool : &data_buffers, context,
|
||||
timeout, caller, line);
|
||||
}
|
||||
|
||||
#else /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
@ -348,16 +439,24 @@ struct net_buf *net_nbuf_get_rx(struct net_context *context, int32_t timeout)
|
|||
|
||||
struct net_buf *net_nbuf_get_tx(struct net_context *context, int32_t timeout)
|
||||
{
|
||||
struct net_buf_pool *pool;
|
||||
|
||||
NET_ASSERT_INFO(context, "TX context not set");
|
||||
|
||||
return net_nbuf_get(&tx_buffers, context, timeout);
|
||||
pool = get_tx_pool(context);
|
||||
|
||||
return net_nbuf_get(pool ? pool : &tx_buffers, context, timeout);
|
||||
}
|
||||
|
||||
struct net_buf *net_nbuf_get_data(struct net_context *context, int32_t timeout)
|
||||
{
|
||||
struct net_buf_pool *pool;
|
||||
|
||||
NET_ASSERT_INFO(context, "Data context not set");
|
||||
|
||||
return net_nbuf_get(&data_buffers, context, timeout);
|
||||
pool = get_data_pool(context);
|
||||
|
||||
return net_nbuf_get(pool ? pool : &data_buffers, context, timeout);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
@ -383,11 +482,11 @@ void net_nbuf_unref(struct net_buf *buf)
|
|||
return;
|
||||
}
|
||||
|
||||
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
|
||||
pool2str(buf->pool), get_frees(buf->pool),
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
NET_DBG("%s (%p) [%d] buf %p ref %d frags %p (%s():%d)",
|
||||
pool2str(buf->pool), buf->pool, get_frees(buf->pool),
|
||||
buf, buf->ref - 1, buf->frags, caller, line);
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
if (buf->ref > 1) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -397,9 +496,10 @@ void net_nbuf_unref(struct net_buf *buf)
|
|||
*/
|
||||
frag = buf->frags;
|
||||
while (frag) {
|
||||
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
|
||||
pool2str(frag->pool), get_frees(frag->pool),
|
||||
frag, frag->ref - 1, frag->frags, caller, line);
|
||||
NET_DBG("%s (%p) [%d] buf %p ref %d frags %p (%s():%d)",
|
||||
pool2str(frag->pool), frag->pool,
|
||||
get_frees(frag->pool), frag, frag->ref - 1,
|
||||
frag->frags, caller, line);
|
||||
|
||||
if (!frag->ref) {
|
||||
NET_DBG("*** ERROR *** frag %p is freed already "
|
||||
|
@ -427,9 +527,11 @@ struct net_buf *net_nbuf_ref(struct net_buf *buf)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
NET_DBG("%s [%d] buf %p ref %d (%s():%d)",
|
||||
pool2str(buf->pool), get_frees(buf->pool),
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
NET_DBG("%s (%p) [%d] buf %p ref %d (%s():%d)",
|
||||
pool2str(buf->pool), buf->pool, get_frees(buf->pool),
|
||||
buf, buf->ref + 1, caller, line);
|
||||
#endif
|
||||
|
||||
return net_buf_ref(buf);
|
||||
}
|
||||
|
@ -744,7 +846,6 @@ static inline bool net_nbuf_append_bytes(struct net_buf *buf,
|
|||
uint16_t len, int32_t timeout)
|
||||
{
|
||||
struct net_buf *frag = net_buf_frag_last(buf);
|
||||
uint16_t ll_reserve = net_nbuf_ll_reserve(buf);
|
||||
|
||||
do {
|
||||
uint16_t count = min(len, net_buf_tailroom(frag));
|
||||
|
@ -758,7 +859,7 @@ static inline bool net_nbuf_append_bytes(struct net_buf *buf,
|
|||
return true;
|
||||
}
|
||||
|
||||
frag = net_nbuf_get_reserve_data(ll_reserve, timeout);
|
||||
frag = net_nbuf_get_frag(buf, timeout);
|
||||
if (!frag) {
|
||||
return false;
|
||||
}
|
||||
|
@ -788,8 +889,7 @@ bool net_nbuf_append(struct net_buf *buf, uint16_t len, const uint8_t *data,
|
|||
}
|
||||
|
||||
if (!buf->frags) {
|
||||
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
|
||||
timeout);
|
||||
frag = net_nbuf_get_frag(buf, timeout);
|
||||
if (!frag) {
|
||||
return false;
|
||||
}
|
||||
|
@ -923,8 +1023,7 @@ static inline struct net_buf *check_and_create_data(struct net_buf *buf,
|
|||
return data;
|
||||
}
|
||||
|
||||
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
|
||||
timeout);
|
||||
frag = net_nbuf_get_frag(buf, timeout);
|
||||
if (!frag) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1025,15 +1124,11 @@ struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
|
|||
uint16_t len, uint8_t *data,
|
||||
int32_t timeout)
|
||||
{
|
||||
uint16_t ll_reserve;
|
||||
|
||||
if (!buf || is_from_data_pool(buf)) {
|
||||
NET_ERR("Invalid buffer or it is data fragment");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ll_reserve = net_nbuf_ll_reserve(buf);
|
||||
|
||||
frag = adjust_write_offset(buf, frag, offset, &offset, timeout);
|
||||
if (!frag) {
|
||||
NET_DBG("Failed to adjust offset");
|
||||
|
@ -1067,7 +1162,7 @@ struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
|
|||
frag = frag->frags;
|
||||
|
||||
if (!frag) {
|
||||
frag = net_nbuf_get_reserve_data(ll_reserve, timeout);
|
||||
frag = net_nbuf_get_frag(buf, timeout);
|
||||
if (!frag) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1117,8 +1212,7 @@ static inline bool insert_data(struct net_buf *buf, struct net_buf *frag,
|
|||
data += count;
|
||||
offset = 0;
|
||||
|
||||
insert = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
|
||||
timeout);
|
||||
insert = net_nbuf_get_frag(buf, timeout);
|
||||
if (!insert) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1190,8 +1284,7 @@ bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
|
|||
*/
|
||||
bytes = frag->len - offset;
|
||||
if (bytes) {
|
||||
temp = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
|
||||
timeout);
|
||||
temp = net_nbuf_get_frag(buf, timeout);
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1189,6 +1189,17 @@ static void buf_get_sockaddr(sa_family_t family, struct net_buf *buf,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
static inline void copy_pool_vars(struct net_context *new_context,
|
||||
struct net_context *listen_context)
|
||||
{
|
||||
new_context->tx_pool = listen_context->tx_pool;
|
||||
new_context->data_pool = listen_context->data_pool;
|
||||
}
|
||||
#else
|
||||
#define copy_pool_vars(...)
|
||||
#endif /* CONFIG_NET_CONTEXT_NBUF_POOL */
|
||||
|
||||
/* This callback is called when we are waiting connections and we receive
|
||||
* a packet. We need to check if we are receiving proper msg (SYN) here.
|
||||
* The ACK could also be received, in which case we have an established
|
||||
|
@ -1394,6 +1405,7 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
tmp_tcp->accept_cb = tcp->accept_cb;
|
||||
tcp->accept_cb = NULL;
|
||||
new_context->tcp = tcp;
|
||||
copy_pool_vars(new_context, context);
|
||||
context->tcp = tmp_tcp;
|
||||
|
||||
tcp->context = new_context;
|
||||
|
|
|
@ -551,6 +551,80 @@ static int shell_cmd_iface(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ctx_info {
|
||||
int pos;
|
||||
bool are_external_pools;
|
||||
struct net_buf_pool *tx_pools[CONFIG_NET_MAX_CONTEXTS];
|
||||
struct net_buf_pool *data_pools[CONFIG_NET_MAX_CONTEXTS];
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
static bool pool_found_already(struct ctx_info *info,
|
||||
struct net_buf_pool *pool)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NET_MAX_CONTEXTS; i++) {
|
||||
if (info->tx_pools[i] == pool ||
|
||||
info->data_pools[i] == pool) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void context_info(struct net_context *context, void *user_data)
|
||||
{
|
||||
#if defined(CONFIG_NET_CONTEXT_NBUF_POOL)
|
||||
struct ctx_info *info = user_data;
|
||||
struct net_buf_pool *pool;
|
||||
|
||||
if (!net_context_is_used(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->tx_pool) {
|
||||
pool = context->tx_pool();
|
||||
|
||||
if (pool_found_already(info, pool)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
printk("\tETX\t%d bytes, %d elements, available %d (%p)\n",
|
||||
pool->pool_size, pool->buf_count, pool->avail_count,
|
||||
pool);
|
||||
#else
|
||||
printk("\tETX\t%d elements (%p)\n", pool->buf_count, pool);
|
||||
#endif
|
||||
info->are_external_pools = true;
|
||||
info->tx_pools[info->pos] = pool;
|
||||
}
|
||||
|
||||
if (context->data_pool) {
|
||||
pool = context->data_pool();
|
||||
|
||||
if (pool_found_already(info, pool)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
printk("\tEDATA\t%d bytes, %d elements, available %d (%p)\n",
|
||||
pool->pool_size, pool->buf_count, pool->avail_count,
|
||||
pool);
|
||||
#else
|
||||
printk("\tEDATA\t%d elements (%p)\n", pool->buf_count, pool);
|
||||
#endif
|
||||
info->are_external_pools = true;
|
||||
info->data_pools[info->pos] = pool;
|
||||
}
|
||||
|
||||
info->pos++;
|
||||
#endif /* CONFIG_NET_CONTEXT_NBUF_POOL */
|
||||
}
|
||||
|
||||
static int shell_cmd_mem(int argc, char *argv[])
|
||||
{
|
||||
size_t tx_size, rx_size, data_size;
|
||||
|
@ -586,6 +660,17 @@ static int shell_cmd_mem(int argc, char *argv[])
|
|||
}
|
||||
printk("\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_CONTEXT_NBUF_POOL)) {
|
||||
struct ctx_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
net_context_foreach(context_info, &info);
|
||||
|
||||
if (!info.are_external_pools) {
|
||||
printk("No external memory pools found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue