net: buf: Support allocation of a net_buf pointing to external buffer

Difference being that the data is not, then, allocated from the pool.
Only the net_buf is.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2018-02-08 12:55:43 +01:00 committed by Johan Hedberg
parent 5c464b1bcc
commit 47e45c52a1
2 changed files with 78 additions and 1 deletions

View file

@ -445,6 +445,15 @@ static inline void net_buf_simple_restore(struct net_buf_simple *buf,
* should be used instead.
*/
#define NET_BUF_FRAGS BIT(0)
/** Flag indicating that the buffer's associated data pointer, points to
* externally allocated memory. Therefore once ref goes down to zero, the
* pointed data will not need to be deallocated. This never needs to be
* explicitely set or unet by the net_buf API user. Such net_buf is
* exclusively instanciated via net_buf_alloc_with_data() function.
* Reference count mechanism however will behave the same way, and ref
* count going to 0 will free the net_buf but no the data pointer in it.
*/
#define NET_BUF_EXTERNAL_DATA BIT(1)
/** @brief Network buffer representation.
*
@ -787,6 +796,39 @@ struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size,
s32_t timeout);
#endif
/**
* @brief Allocate a new buffer from a pool but with external data pointer.
*
* Allocate a new buffer from a pool, where the data pointer comes from the
* user and not from the pool.
*
* @param pool Which pool to allocate the buffer from.
* @param data External data pointer
* @param size Amount of data the pointed data buffer if able to fit.
* @param timeout Affects the action taken should the 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. Note that some types
* of data allocators do not support blocking (such as the HEAP
* type). In this case it's still possible for net_buf_alloc() to
* fail (return NULL) even if it was given K_FOREVER.
*
* @return New buffer or NULL if out of buffers.
*/
#if defined(CONFIG_NET_BUF_LOG)
struct net_buf *net_buf_alloc_with_data_debug(struct net_buf_pool *pool,
void *data, size_t size,
s32_t timeout, const char *func,
int line);
#define net_buf_alloc_with_data(_pool, _data_, _size, _timeout) \
net_buf_alloc_with_data_debug(_pool, _data_, _size, _timeout, \
__func__, __LINE__)
#else
struct net_buf *net_buf_alloc_with_data(struct net_buf_pool *pool,
void *data, size_t size,
s32_t timeout);
#endif
/**
* @brief Get a buffer from a FIFO.
*

View file

@ -216,6 +216,10 @@ static void data_unref(struct net_buf *buf, u8_t *data)
{
struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
if (buf->flags & NET_BUF_EXTERNAL_DATA) {
return;
}
pool->alloc->cb->unref(buf, data);
}
@ -357,6 +361,37 @@ struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool, s32_t timeout)
}
#endif
#if defined(CONFIG_NET_BUF_LOG)
struct net_buf *net_buf_alloc_with_data_debug(struct net_buf_pool *pool,
void *data, size_t size,
s32_t timeout, const char *func,
int line)
#else
struct net_buf *net_buf_alloc_with_data(struct net_buf_pool *pool,
void *data, size_t size,
s32_t timeout)
#endif
{
struct net_buf *buf;
#if defined(CONFIG_NET_BUF_LOG)
buf = net_buf_alloc_len_debug(pool, 0, timeout, func, line);
#else
buf = net_buf_alloc_len(pool, 0, timeout);
#endif
if (!buf) {
return NULL;
}
buf->__buf = data;
buf->data = data;
buf->size = size;
buf->len = size;
buf->flags = NET_BUF_EXTERNAL_DATA;
return buf;
}
#if defined(CONFIG_NET_BUF_LOG)
struct net_buf *net_buf_get_debug(struct k_fifo *fifo, s32_t timeout,
const char *func, int line)
@ -542,7 +577,7 @@ struct net_buf *net_buf_clone(struct net_buf *buf, s32_t timeout)
/* If the pool supports data referencing use that. Otherwise
* we need to allocate new data and make a copy.
*/
if (pool->alloc->cb->ref) {
if (pool->alloc->cb->ref && !(buf->flags & NET_BUF_EXTERNAL_DATA)) {
clone->__buf = data_ref(buf, buf->__buf);
clone->data = buf->data;
clone->len = buf->len;