Skip to content

Commit 45a0a49

Browse files
jukkarnashif
authored andcommitted
lib: net_buf: Add a way to create pool with aligned data
Add a new macro NET_BUF_POOL_VAR_ALIGN_DEFINE() which can be used to create a pool with aligned data where both the start of the data and the length of the data is aligned. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
1 parent 5b1d16d commit 45a0a49

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

include/zephyr/net_buf.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,7 @@ struct net_buf_data_alloc {
10661066
const struct net_buf_data_cb *cb;
10671067
void *alloc_data;
10681068
size_t max_alloc_size;
1069+
size_t alignment;
10691070
};
10701071

10711072
/** @endcond */
@@ -1279,6 +1280,51 @@ extern const struct net_buf_data_cb net_buf_var_cb;
12791280
_net_buf_##_name, _count, _ud_size, \
12801281
_destroy)
12811282

1283+
/**
1284+
*
1285+
* @brief Define a new pool for buffers with variable size payloads. Align the
1286+
* length and start of the buffer to the specified alignment.
1287+
*
1288+
* Defines a net_buf_pool struct and the necessary memory storage (array of
1289+
* structs) for the needed amount of buffers. After this, the buffers can be
1290+
* accessed from the pool through net_buf_alloc. The pool is defined as a
1291+
* static variable, so if it needs to be exported outside the current module
1292+
* this needs to happen with the help of a separate pointer rather than an
1293+
* extern declaration.
1294+
*
1295+
* The data payload of the buffers will be based on a memory pool from which
1296+
* variable size payloads may be allocated.
1297+
*
1298+
* If provided with a custom destroy callback, this callback is
1299+
* responsible for eventually calling net_buf_destroy() to complete the
1300+
* process of returning the buffer to the pool.
1301+
*
1302+
* Both the length and start of the buffer will be aligned to the specified
1303+
* alignment. The alignment must be a power of 2 and the size of the
1304+
* alignment must be less than or equal to the size of the data payload.
1305+
*
1306+
* @param _name Name of the pool variable.
1307+
* @param _count Number of buffers in the pool.
1308+
* @param _data_size Total amount of memory available for data payloads.
1309+
* @param _ud_size User data space to reserve per buffer.
1310+
* @param _destroy Optional destroy callback when buffer is freed.
1311+
* @param _align Alignment of the length and start of the buffer.
1312+
*/
1313+
#define NET_BUF_POOL_VAR_ALIGN_DEFINE(_name, _count, _data_size, _ud_size, \
1314+
_destroy, _align) \
1315+
_NET_BUF_ARRAY_DEFINE(_name, _count, _ud_size); \
1316+
K_HEAP_DEFINE(net_buf_mem_pool_##_name, _data_size); \
1317+
static const struct net_buf_data_alloc net_buf_data_alloc_##_name = { \
1318+
.cb = &net_buf_var_cb, \
1319+
.alloc_data = &net_buf_mem_pool_##_name, \
1320+
.max_alloc_size = 0, \
1321+
.alignment = _align, \
1322+
}; \
1323+
static STRUCT_SECTION_ITERABLE(net_buf_pool, _name) = \
1324+
NET_BUF_POOL_INITIALIZER(_name, &net_buf_data_alloc_##_name, \
1325+
_net_buf_##_name, _count, _ud_size, \
1326+
_destroy)
1327+
12821328
/**
12831329
*
12841330
* @brief Define a new pool for buffers

lib/net_buf/buf.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
4242
#define WARN_ALLOC_INTERVAL K_FOREVER
4343
#endif
4444

45+
#define GET_ALIGN(pool) MAX(sizeof(void *), pool->alloc->alignment)
46+
4547
/* Linker-defined symbol bound to the static pool structs */
4648
STRUCT_SECTION_START_EXTERN(net_buf_pool);
4749

@@ -95,9 +97,10 @@ void net_buf_reset(struct net_buf *buf)
9597

9698
static uint8_t *generic_data_ref(struct net_buf *buf, uint8_t *data)
9799
{
100+
struct net_buf_pool *buf_pool = net_buf_pool_get(buf->pool_id);
98101
uint8_t *ref_count;
99102

100-
ref_count = data - sizeof(void *);
103+
ref_count = data - GET_ALIGN(buf_pool);
101104
(*ref_count)++;
102105

103106
return data;
@@ -109,9 +112,26 @@ static uint8_t *mem_pool_data_alloc(struct net_buf *buf, size_t *size,
109112
struct net_buf_pool *buf_pool = net_buf_pool_get(buf->pool_id);
110113
struct k_heap *pool = buf_pool->alloc->alloc_data;
111114
uint8_t *ref_count;
115+
void *b;
116+
117+
if (buf_pool->alloc->alignment == 0) {
118+
/* Reserve extra space for a ref-count (uint8_t) */
119+
b = k_heap_alloc(pool, sizeof(void *) + *size, timeout);
120+
121+
} else {
122+
if (*size < buf_pool->alloc->alignment) {
123+
NET_BUF_DBG("Requested size %zu is smaller than alignment %zu",
124+
*size, buf_pool->alloc->alignment);
125+
return NULL;
126+
}
112127

113-
/* Reserve extra space for a ref-count (uint8_t) */
114-
void *b = k_heap_alloc(pool, sizeof(void *) + *size, timeout);
128+
/* Reserve extra space for a ref-count (uint8_t) */
129+
b = k_heap_aligned_alloc(pool,
130+
buf_pool->alloc->alignment,
131+
GET_ALIGN(buf_pool) +
132+
ROUND_UP(*size, buf_pool->alloc->alignment),
133+
timeout);
134+
}
115135

116136
if (b == NULL) {
117137
return NULL;
@@ -121,7 +141,7 @@ static uint8_t *mem_pool_data_alloc(struct net_buf *buf, size_t *size,
121141
*ref_count = 1U;
122142

123143
/* Return pointer to the byte following the ref count */
124-
return ref_count + sizeof(void *);
144+
return ref_count + GET_ALIGN(buf_pool);
125145
}
126146

127147
static void mem_pool_data_unref(struct net_buf *buf, uint8_t *data)
@@ -130,7 +150,7 @@ static void mem_pool_data_unref(struct net_buf *buf, uint8_t *data)
130150
struct k_heap *pool = buf_pool->alloc->alloc_data;
131151
uint8_t *ref_count;
132152

133-
ref_count = data - sizeof(void *);
153+
ref_count = data - GET_ALIGN(buf_pool);
134154
if (--(*ref_count)) {
135155
return;
136156
}
@@ -171,23 +191,25 @@ const struct net_buf_data_cb net_buf_fixed_cb = {
171191
static uint8_t *heap_data_alloc(struct net_buf *buf, size_t *size,
172192
k_timeout_t timeout)
173193
{
194+
struct net_buf_pool *buf_pool = net_buf_pool_get(buf->pool_id);
174195
uint8_t *ref_count;
175196

176-
ref_count = k_malloc(sizeof(void *) + *size);
197+
ref_count = k_malloc(GET_ALIGN(buf_pool) + *size);
177198
if (!ref_count) {
178199
return NULL;
179200
}
180201

181202
*ref_count = 1U;
182203

183-
return ref_count + sizeof(void *);
204+
return ref_count + GET_ALIGN(buf_pool);
184205
}
185206

186207
static void heap_data_unref(struct net_buf *buf, uint8_t *data)
187208
{
209+
struct net_buf_pool *buf_pool = net_buf_pool_get(buf->pool_id);
188210
uint8_t *ref_count;
189211

190-
ref_count = data - sizeof(void *);
212+
ref_count = data - GET_ALIGN(buf_pool);
191213
if (--(*ref_count)) {
192214
return;
193215
}

0 commit comments

Comments
 (0)