net: nbuf: Let's remove inner type

It's possible to know from which pool the nbuf comes from so
let's reduce nbuf size by removing its internal type attribute which
becomes then useless.

When a data buffer is not coming from nbuf data buffer pool, let's call
it "EXTERNAL", just to make debugging handling a little simple in the
code.

Change-Id: I6931394c8c4f594137f6380be0a0ba5cea371040
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2016-12-29 12:17:03 +01:00
commit 2e95186eff
2 changed files with 96 additions and 148 deletions

View file

@ -43,14 +43,6 @@ extern "C" {
struct net_context; struct net_context;
/** @cond ignore */
enum net_nbuf_type {
NET_NBUF_RX = 0,
NET_NBUF_TX = 1,
NET_NBUF_DATA = 2,
};
/** @endcond */
struct net_nbuf { struct net_nbuf {
/** Network connection context */ /** Network connection context */
struct net_context *context; struct net_context *context;
@ -71,8 +63,6 @@ struct net_nbuf {
struct net_linkaddr lladdr_src; struct net_linkaddr lladdr_src;
struct net_linkaddr lladdr_dst; struct net_linkaddr lladdr_dst;
enum net_nbuf_type type;
uint16_t appdatalen; uint16_t appdatalen;
uint16_t reserve; /* length of the protocol headers */ uint16_t reserve; /* length of the protocol headers */
uint8_t ll_reserve; /* link layer header length */ uint8_t ll_reserve; /* link layer header length */
@ -132,16 +122,6 @@ static inline void net_nbuf_set_iface(struct net_buf *buf, struct net_if *iface)
((struct net_nbuf *)net_buf_user_data(buf))->iface = iface; ((struct net_nbuf *)net_buf_user_data(buf))->iface = iface;
} }
static inline enum net_nbuf_type net_nbuf_type(struct net_buf *buf)
{
return ((struct net_nbuf *)net_buf_user_data(buf))->type;
}
static inline void net_nbuf_set_type(struct net_buf *buf, uint8_t type)
{
((struct net_nbuf *)net_buf_user_data(buf))->type = type;
}
static inline uint8_t net_nbuf_family(struct net_buf *buf) static inline uint8_t net_nbuf_family(struct net_buf *buf)
{ {
return ((struct net_nbuf *)net_buf_user_data(buf))->family; return ((struct net_nbuf *)net_buf_user_data(buf))->family;

View file

@ -89,6 +89,22 @@
#error "Too small net_buf fragment size" #error "Too small net_buf fragment size"
#endif #endif
/* The RX and TX pools do not store any data. Only bearer / protocol
* related data is stored here.
*/
static inline void free_rx_bufs_func(struct net_buf *buf);
static inline void free_tx_bufs_func(struct net_buf *buf);
static inline void free_data_bufs_func(struct net_buf *buf);
NET_BUF_POOL_DEFINE(rx_buffers, NBUF_RX_COUNT, 0, sizeof(struct net_nbuf),
free_rx_bufs_func);
NET_BUF_POOL_DEFINE(tx_buffers, NBUF_TX_COUNT, 0, sizeof(struct net_nbuf),
free_tx_bufs_func);
/* The data fragment pool is for storing network data. */
NET_BUF_POOL_DEFINE(data_buffers, NBUF_DATA_COUNT, NBUF_DATA_LEN,
NBUF_USER_DATA_LEN, free_data_bufs_func);
#if NET_DEBUG #if NET_DEBUG
#define NET_BUF_CHECK_IF_IN_USE(buf, ref) \ #define NET_BUF_CHECK_IF_IN_USE(buf, ref) \
@ -189,24 +205,31 @@ static inline void inc_free_data_bufs(struct net_buf *buf)
} }
} }
static inline int get_frees(enum net_nbuf_type type) static inline void dec_free_bufs(struct net_buf_pool *pool,
struct net_buf *buf)
{ {
switch (type) { if (pool == &rx_buffers) {
case NET_NBUF_RX: dec_free_rx_bufs(buf);
} else if (pool == &tx_buffers) {
dec_free_tx_bufs(buf);
} else {
dec_free_data_bufs(buf);
}
}
static inline int get_frees(struct net_buf_pool *pool)
{
if (pool == &rx_buffers) {
return num_free_rx_bufs; return num_free_rx_bufs;
case NET_NBUF_TX: } else if (pool == &tx_buffers) {
return num_free_tx_bufs; return num_free_tx_bufs;
case NET_NBUF_DATA: } else if (pool == &data_buffers) {
return num_free_data_bufs; return num_free_data_bufs;
} }
return 0xffffffff; return 0xffffffff;
} }
#define inc_free_rx_bufs_func inc_free_rx_bufs
#define inc_free_tx_bufs_func inc_free_tx_bufs
#define inc_free_data_bufs_func inc_free_data_bufs
#else /* NET_DEBUG */ #else /* NET_DEBUG */
#define dec_free_rx_bufs(...) #define dec_free_rx_bufs(...)
#define inc_free_rx_bufs(...) #define inc_free_rx_bufs(...)
@ -214,64 +237,49 @@ static inline int get_frees(enum net_nbuf_type type)
#define inc_free_tx_bufs(...) #define inc_free_tx_bufs(...)
#define dec_free_data_bufs(...) #define dec_free_data_bufs(...)
#define inc_free_data_bufs(...) #define inc_free_data_bufs(...)
#define inc_free_rx_bufs_func(...) #define dec_free_bufs(...)
#define inc_free_tx_bufs_func(...)
#define inc_free_data_bufs_func(...)
#define NET_BUF_CHECK_IF_IN_USE(buf, ref) #define NET_BUF_CHECK_IF_IN_USE(buf, ref)
#define NET_BUF_CHECK_IF_NOT_IN_USE(buf, ref) #define NET_BUF_CHECK_IF_NOT_IN_USE(buf, ref)
#endif /* NET_DEBUG */ #endif /* NET_DEBUG */
static inline void free_rx_bufs_func(struct net_buf *buf)
{
inc_free_rx_bufs_func(buf);
net_buf_destroy(buf);
}
static inline void free_tx_bufs_func(struct net_buf *buf)
{
inc_free_tx_bufs_func(buf);
net_buf_destroy(buf);
}
static inline void free_data_bufs_func(struct net_buf *buf)
{
inc_free_data_bufs_func(buf);
net_buf_destroy(buf);
}
/* The RX and TX pools do not store any data. Only bearer / protocol
* related data is stored here.
*/
NET_BUF_POOL_DEFINE(rx_buffers, NBUF_RX_COUNT, 0, sizeof(struct net_nbuf),
free_rx_bufs_func);
NET_BUF_POOL_DEFINE(tx_buffers, NBUF_TX_COUNT, 0, sizeof(struct net_nbuf),
free_tx_bufs_func);
/* The data fragment pool is for storing network data. */
NET_BUF_POOL_DEFINE(data_buffers, NBUF_DATA_COUNT, NBUF_DATA_LEN,
NBUF_USER_DATA_LEN, free_data_bufs_func);
static inline bool is_from_data_pool(struct net_buf *buf) static inline bool is_from_data_pool(struct net_buf *buf)
{ {
return (buf->pool == &data_buffers); return (buf->pool == &data_buffers);
} }
#if NET_DEBUG static inline void free_rx_bufs_func(struct net_buf *buf)
static inline const char *type2str(enum net_nbuf_type type)
{ {
switch (type) { inc_free_rx_bufs(buf);
case NET_NBUF_RX:
net_buf_destroy(buf);
}
static inline void free_tx_bufs_func(struct net_buf *buf)
{
inc_free_tx_bufs(buf);
net_buf_destroy(buf);
}
static inline void free_data_bufs_func(struct net_buf *buf)
{
inc_free_data_bufs(buf);
net_buf_destroy(buf);
}
#if NET_DEBUG
static inline const char *pool2str(struct net_buf_pool *pool)
{
if (pool == &rx_buffers) {
return "RX"; return "RX";
case NET_NBUF_TX: } else if (pool == &tx_buffers) {
return "TX"; return "TX";
case NET_NBUF_DATA: } else if (pool == &data_buffers) {
return "DATA"; return "DATA";
} }
return NULL; return "EXTERNAL";
} }
void net_nbuf_print_frags(struct net_buf *buf) void net_nbuf_print_frags(struct net_buf *buf)
@ -306,12 +314,12 @@ void net_nbuf_print_frags(struct net_buf *buf)
count * ll_overhead, (total * 100) / (count * frag_size)); count * ll_overhead, (total * 100) / (count * frag_size));
} }
static struct net_buf *net_nbuf_get_reserve_debug(enum net_nbuf_type type, static struct net_buf *net_nbuf_get_reserve_debug(struct net_buf_pool *pool,
uint16_t reserve_head, uint16_t reserve_head,
const char *caller, const char *caller,
int line) int line)
#else #else
static struct net_buf *net_nbuf_get_reserve(enum net_nbuf_type type, static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
uint16_t reserve_head) uint16_t reserve_head)
#endif #endif
{ {
@ -321,48 +329,24 @@ static struct net_buf *net_nbuf_get_reserve(enum net_nbuf_type type,
* The reserve_head variable in the function will tell * The reserve_head variable in the function will tell
* the size of the link layer headers if there are any. * the size of the link layer headers if there are any.
*/ */
switch (type) {
case NET_NBUF_RX:
buf = net_buf_alloc(&rx_buffers, K_FOREVER);
memset(net_buf_user_data(buf), 0, sizeof(struct net_nbuf)); buf = net_buf_alloc(pool, K_FOREVER);
NET_ASSERT_INFO(buf->ref, "RX buf %p ref %d", buf, buf->ref);
dec_free_rx_bufs(buf);
net_nbuf_set_type(buf, type);
break;
case NET_NBUF_TX:
buf = net_buf_alloc(&tx_buffers, K_FOREVER);
memset(net_buf_user_data(buf), 0, sizeof(struct net_nbuf));
NET_ASSERT_INFO(buf->ref, "TX buf %p ref %d", buf, buf->ref);
dec_free_tx_bufs(buf);
net_nbuf_set_type(buf, type);
break;
case NET_NBUF_DATA:
buf = net_buf_alloc(&data_buffers, K_FOREVER);
NET_ASSERT_INFO(buf->ref, "DATA buf %p ref %d", buf, buf->ref);
if (pool == &data_buffers) {
/* The buf->data will point to the start of the L3 /* The buf->data will point to the start of the L3
* header (like IPv4 or IPv6 packet header). * header (like IPv4 or IPv6 packet header).
*/ */
net_buf_reserve(buf, reserve_head); net_buf_reserve(buf, reserve_head);
} else {
dec_free_data_bufs(buf); memset(net_buf_user_data(buf), 0, sizeof(struct net_nbuf));
break;
default:
NET_ERR("Invalid type %d for net_buf", type);
return NULL;
} }
dec_free_bufs(pool, buf);
NET_BUF_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1); NET_BUF_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1);
NET_DBG("%s [%d] buf %p reserve %u ref %d (%s():%d)", NET_DBG("%s [%d] buf %p reserve %u ref %d (%s():%d)",
type2str(type), get_frees(type), pool2str(pool), get_frees(pool),
buf, reserve_head, buf->ref, caller, line); buf, reserve_head, buf->ref, caller, line);
return buf; return buf;
@ -372,21 +356,21 @@ static struct net_buf *net_nbuf_get_reserve(enum net_nbuf_type type,
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head, struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_reserve_debug(NET_NBUF_RX, reserve_head, return net_nbuf_get_reserve_debug(&rx_buffers, reserve_head,
caller, line); caller, line);
} }
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head, struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_reserve_debug(NET_NBUF_TX, reserve_head, return net_nbuf_get_reserve_debug(&tx_buffers, reserve_head,
caller, line); caller, line);
} }
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head, struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_reserve_debug(NET_NBUF_DATA, reserve_head, return net_nbuf_get_reserve_debug(&data_buffers, reserve_head,
caller, line); caller, line);
} }
@ -394,28 +378,28 @@ struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head) struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head)
{ {
return net_nbuf_get_reserve(NET_NBUF_RX, reserve_head); return net_nbuf_get_reserve(&rx_buffers, reserve_head);
} }
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head) struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head)
{ {
return net_nbuf_get_reserve(NET_NBUF_TX, reserve_head); return net_nbuf_get_reserve(&tx_buffers, reserve_head);
} }
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head) struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head)
{ {
return net_nbuf_get_reserve(NET_NBUF_DATA, reserve_head); return net_nbuf_get_reserve(&data_buffers, reserve_head);
} }
#endif /* NET_DEBUG */ #endif /* NET_DEBUG */
#if NET_DEBUG #if NET_DEBUG
static struct net_buf *net_nbuf_get_debug(enum net_nbuf_type type, static struct net_buf *net_nbuf_get_debug(struct net_buf_pool *pool,
struct net_context *context, struct net_context *context,
const char *caller, int line) const char *caller, int line)
#else #else
static struct net_buf *net_nbuf_get(enum net_nbuf_type type, static struct net_buf *net_nbuf_get(struct net_buf_pool *pool,
struct net_context *context) struct net_context *context)
#endif /* NET_DEBUG */ #endif /* NET_DEBUG */
{ {
@ -434,15 +418,15 @@ static struct net_buf *net_nbuf_get(enum net_nbuf_type type,
reserve = net_if_get_ll_reserve(iface, addr6); reserve = net_if_get_ll_reserve(iface, addr6);
#if NET_DEBUG #if NET_DEBUG
buf = net_nbuf_get_reserve_debug(type, reserve, caller, line); buf = net_nbuf_get_reserve_debug(pool, reserve, caller, line);
#else #else
buf = net_nbuf_get_reserve(type, reserve); buf = net_nbuf_get_reserve(pool, reserve);
#endif #endif
if (!buf) { if (!buf) {
return buf; return buf;
} }
if (type != NET_NBUF_DATA) { if (pool != &data_buffers) {
net_nbuf_set_context(buf, context); net_nbuf_set_context(buf, context);
net_nbuf_set_ll_reserve(buf, reserve); net_nbuf_set_ll_reserve(buf, reserve);
net_nbuf_set_family(buf, net_context_get_family(context)); net_nbuf_set_family(buf, net_context_get_family(context));
@ -456,19 +440,19 @@ static struct net_buf *net_nbuf_get(enum net_nbuf_type type,
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context, struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_debug(NET_NBUF_RX, context, caller, line); return net_nbuf_get_debug(&rx_buffers, context, caller, line);
} }
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context, struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_debug(NET_NBUF_TX, context, caller, line); return net_nbuf_get_debug(&tx_buffers, context, caller, line);
} }
struct net_buf *net_nbuf_get_data_debug(struct net_context *context, struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
const char *caller, int line) const char *caller, int line)
{ {
return net_nbuf_get_debug(NET_NBUF_DATA, context, caller, line); return net_nbuf_get_debug(&data_buffers, context, caller, line);
} }
#else /* NET_DEBUG */ #else /* NET_DEBUG */
@ -477,21 +461,21 @@ struct net_buf *net_nbuf_get_rx(struct net_context *context)
{ {
NET_ASSERT_INFO(context, "RX context not set"); NET_ASSERT_INFO(context, "RX context not set");
return net_nbuf_get(NET_NBUF_RX, context); return net_nbuf_get(&rx_buffers, context);
} }
struct net_buf *net_nbuf_get_tx(struct net_context *context) struct net_buf *net_nbuf_get_tx(struct net_context *context)
{ {
NET_ASSERT_INFO(context, "TX context not set"); NET_ASSERT_INFO(context, "TX context not set");
return net_nbuf_get(NET_NBUF_TX, context); return net_nbuf_get(&tx_buffers, context);
} }
struct net_buf *net_nbuf_get_data(struct net_context *context) struct net_buf *net_nbuf_get_data(struct net_context *context)
{ {
NET_ASSERT_INFO(context, "Data context not set"); NET_ASSERT_INFO(context, "Data context not set");
return net_nbuf_get(NET_NBUF_DATA, context); return net_nbuf_get(&data_buffers, context);
} }
#endif /* NET_DEBUG */ #endif /* NET_DEBUG */
@ -517,17 +501,9 @@ void net_nbuf_unref(struct net_buf *buf)
return; return;
} }
if (!is_from_data_pool(buf)) { NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)", pool2str(buf->pool), get_frees(buf->pool),
type2str(net_nbuf_type(buf)), buf, buf->ref - 1, buf->frags, caller, line);
get_frees(net_nbuf_type(buf)),
buf, buf->ref - 1, buf->frags, caller, line);
} else {
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
type2str(NET_NBUF_DATA),
get_frees(NET_NBUF_DATA),
buf, buf->ref - 1, buf->frags, caller, line);
}
#if NET_DEBUG #if NET_DEBUG
if (buf->ref > 1) { if (buf->ref > 1) {
@ -540,8 +516,7 @@ void net_nbuf_unref(struct net_buf *buf)
frag = buf->frags; frag = buf->frags;
while (frag) { while (frag) {
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)", NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
type2str(NET_NBUF_DATA), pool2str(buf->pool), get_frees(buf->pool),
get_frees(NET_NBUF_DATA),
frag, frag->ref - 1, frag->frags, caller, line); frag, frag->ref - 1, frag->frags, caller, line);
if (!frag->ref) { if (!frag->ref) {
@ -570,16 +545,9 @@ struct net_buf *net_nbuf_ref(struct net_buf *buf)
return NULL; return NULL;
} }
if (!is_from_data_pool(buf)) { NET_DBG("%s [%d] buf %p ref %d (%s():%d)",
NET_DBG("%s [%d] buf %p ref %d (%s():%d)", pool2str(buf->pool), get_frees(buf->pool),
type2str(net_nbuf_type(buf)), buf, buf->ref + 1, caller, line);
get_frees(net_nbuf_type(buf)),
buf, buf->ref + 1, caller, line);
} else {
NET_DBG("%s buf %p ref %d (%s():%d)",
type2str(NET_NBUF_DATA),
buf, buf->ref + 1, caller, line);
}
return net_buf_ref(buf); return net_buf_ref(buf);
} }
@ -1355,9 +1323,9 @@ void net_nbuf_get_info(size_t *tx_size, size_t *rx_size, size_t *data_size,
} }
#if NET_DEBUG #if NET_DEBUG
*tx = get_frees(NET_NBUF_TX); *tx = get_frees(&tx_buffers);
*rx = get_frees(NET_NBUF_RX); *rx = get_frees(&rx_buffers);
*data = get_frees(NET_NBUF_DATA); *data = get_frees(&data_buffers);
#else #else
*tx = BIT(31); *tx = BIT(31);
*rx = BIT(31); *rx = BIT(31);