From 41f60aca4c55a8204d08b2018ee2c864f32e3cb4 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 11 Dec 2014 10:58:56 +0100 Subject: [PATCH] pktbuf: port to use ng_ version --- cpu/msp430-common/include/cpu-conf.h | 6 +- sys/Makefile | 6 +- sys/Makefile.include | 3 - sys/include/net/ng_pkt.h | 8 +- sys/include/net/ng_pktbuf.h | 183 +++ .../crosslayer/{pktbuf => ng_pktbuf}/Makefile | 0 .../crosslayer/ng_pktbuf/_pktbuf_dynamic.c | 299 +++++ .../crosslayer/ng_pktbuf/_pktbuf_internal.h | 107 ++ sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c | 298 +++++ sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c | 261 +++++ sys/net/crosslayer/pktbuf/pktbuf.c | 517 --------- sys/net/include/pktbuf.h | 195 ---- tests/unittests/Makefile | 1 + tests/unittests/tests-pkt/tests-pkt.c | 2 +- tests/unittests/tests-pktbuf/Makefile.include | 2 +- tests/unittests/tests-pktbuf/tests-pktbuf.c | 1014 +++++++++-------- 16 files changed, 1729 insertions(+), 1173 deletions(-) create mode 100644 sys/include/net/ng_pktbuf.h rename sys/net/crosslayer/{pktbuf => ng_pktbuf}/Makefile (100%) create mode 100644 sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c create mode 100644 sys/net/crosslayer/ng_pktbuf/_pktbuf_internal.h create mode 100644 sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c create mode 100644 sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c delete mode 100644 sys/net/crosslayer/pktbuf/pktbuf.c delete mode 100644 sys/net/include/pktbuf.h diff --git a/cpu/msp430-common/include/cpu-conf.h b/cpu/msp430-common/include/cpu-conf.h index 5a86a00438..cb3fa35cee 100644 --- a/cpu/msp430-common/include/cpu-conf.h +++ b/cpu/msp430-common/include/cpu-conf.h @@ -34,9 +34,9 @@ extern "C" { #define UART0_BUFSIZE (32) #endif -#ifndef PKTBUF_SIZE -#define PKTBUF_SIZE (2560) /* TODO: Make this value - overall MTU dependent */ +#ifndef NG_PKTBUF_SIZE +#define NG_PKTBUF_SIZE (2560) /* TODO: Make this value + * overall MTU dependent */ #endif /** @} */ diff --git a/sys/Makefile b/sys/Makefile index bb960d61f5..62c0d57d17 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -1,9 +1,6 @@ ifneq (,$(filter pkt,$(USEMODULE))) DIRS += net/crosslayer/pkt endif -ifneq (,$(filter pktbuf,$(USEMODULE))) - DIRS += net/crosslayer/pktbuf -endif ifneq (,$(filter pnet,$(USEMODULE))) DIRS += posix/pnet endif @@ -74,6 +71,9 @@ endif ifneq (,$(filter ng_netreg,$(USEMODULE))) DIRS += net/crosslayer/ng_netreg endif +ifneq (,$(filter ng_pktbuf,$(USEMODULE))) + DIRS += net/crosslayer/ng_pktbuf +endif ifneq (,$(filter netapi,$(USEMODULE))) DIRS += net/crosslayer/netapi endif diff --git a/sys/Makefile.include b/sys/Makefile.include index d56b9809e7..25e4fca899 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -25,9 +25,6 @@ endif ifneq (,$(filter net_if,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif -ifneq (,$(filter pktbuf,$(USEMODULE))) - USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include -endif ifneq (,$(filter pktqueue,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif diff --git a/sys/include/net/ng_pkt.h b/sys/include/net/ng_pkt.h index aa7eaa3dd8..6ca4e2022b 100644 --- a/sys/include/net/ng_pkt.h +++ b/sys/include/net/ng_pkt.h @@ -74,11 +74,17 @@ extern "C" { * * @note This type implements its own list implementation because of the way * it is stored in the packet buffer. - * @note This type has no initializer on purpose. Please use @ref pktbuf + * @note This type has no initializer on purpose. Please use @ref net_ng_pktbuf * as factory. */ /* packed to be aligned correctly in the static packet buffer */ typedef struct __attribute__((packed)) ng_pktsnip { + /** + * @brief Counter of threads currently having control over this packet. + * + * @internal + */ + unsigned int users; struct ng_pktsnip *next; /**< next snip in the packet */ void *data; /**< pointer to the data of the snip */ size_t size; /**< the length of the snip in byte */ diff --git a/sys/include/net/ng_pktbuf.h b/sys/include/net/ng_pktbuf.h new file mode 100644 index 0000000000..1a0c010368 --- /dev/null +++ b/sys/include/net/ng_pktbuf.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2014 Martine Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_ng_pktbuf Packet buffer + * @ingroup net + * @brief A global network packet buffer. + * + * @note **WARNING!!** Do not store data structures that are not packed + * (defined with `__attribute__((packed))`) or enforce alignment in + * in any way in here if @ref NG_PKTBUF_SIZE > 0. On some RISC architectures + * this *will* lead to alignment problems and can potentially result + * in segmentation/hard faults and other unexpected behaviour. + * + * @{ + * + * @file + * @brief Interface definition for the global network buffer. Network devices + * and layers can allocate space for packets here. + * + * @author Martine Lenders + */ +#ifndef NG_PKTBUF_H_ +#define NG_PKTBUF_H_ + +#include +#include +#include + +#include "atomic.h" +#include "cpu-conf.h" +#include "net/ng_pkt.h" +#include "net/ng_nettype.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def NG_PKTBUF_SIZE + * @brief Maximum size of the static packet buffer. + * + * @details The rational here is to have at least space for 4 full-MTU IPv6 + * packages (2 incoming, 2 outgoing; 2 * 2 * 1280 B = 5 KiB) + + * Meta-Data (roughly estimated to 1 KiB; might be smaller). If + * @ref NG_PKTBUF_SIZE is 0 the packet buffer will use dynamic memory + * management to allocate packets. + */ +#ifndef NG_PKTBUF_SIZE +#define NG_PKTBUF_SIZE (6144) +#endif /* NG_PKTBUF_SIZE */ + +/** + * @brief Prepends a new ng_pktsnip_t to a packet. + * + * @details It is ill-advised to add a ng_pktsnip_t simply by using + * + * next = ng_pktsnip_add(NULL, NULL, size1, NG_NETTYPE_UNDEF); + * pkt = ng_pktsnip_add(NULL, NULL, size2, NG_NETTYPE_UNDEF); + * + * pkt->next = next; + * next->data = next->data + size2; + * + * Since @p data can be in the range of the data allocated on + * ng_pktsnip_t::data of @p next, it would be impossible to free + * ng_pktsnip_t::data of @p next, after @p next was released and the + * generated ng_pktsnip_t not or vice versa. This function ensures that this + * can't happen. + * + * @param[in] next The packet you want to add the ng_pktsnip_t to. If + * ng_pktsnip_t::data field of @p next is equal to data it will + * be set to `next->data + size`. If @p next is NULL the + * ng_pktsnip_t::next field of the result will be also set to + * NULL. + * @param[in] data Data of the new ng_pktsnip_t. If @p data is NULL no data + * will be inserted into the result. + * @param[in] size Length of @p data. If @p size is 0, it will be assumed, + * that @p data is NULL and no data will be inserted into the + * result + * @param[in] type Protocol type of the ng_pktsnip_t. + * + * @return Pointer to the packet part that represents the new ng_pktsnip_t. + * @return NULL, if no space is left in the packet buffer. + */ +ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type); + +/** + * @brief Reallocates ng_pktsnip_t::data of @p pkt in the packet buffer, without + * changing the content. + * + * @pre `pkt->users == 1 && pkt->next == NULL` and @p pkt must be in packet buffer + * + * @details If enough memory is available behind it or @p size is smaller than + * the original size the packet then ng_pktsnip_t::data of @p pkt will + * not be moved. Otherwise, it will be moved. If no space is available + * nothing happens. + * + * @param[in] pkt A packet part. + * @param[in] size The size for @p pkt. + * + * @return 0, on success + * @return EINVAL, if precondition is not met + * @return ENOENT, if ng_pktsnip_t::data of @p pkt was not from the packet buffer. + * @return ENOMEM, if no space is left in the packet buffer or size was 0. + */ +int ng_pktbuf_realloc_data(ng_pktsnip_t *pkt, size_t size); + +/** + * @brief Increases ng_pktsnip_t::users of @p pkt atomically. + * + * @param[in] pkt A packet. + * @param[in] num Number you want to increment ng_pktsnip_t::users of @p pkt by. + */ +static inline void ng_pktbuf_hold(ng_pktsnip_t *pkt, unsigned int num) +{ + if (pkt != NULL) { + atomic_set_return(&(pkt->users), pkt->users + num); + } +} + +/** + * @brief Decreases ng_pktsnip_t::users of @p pkt atomically and removes it if it + * reaches 0. + * + * @param[in] pkt A packet. + */ +void ng_pktbuf_release(ng_pktsnip_t *pkt); + +/** + * @brief Must be called once before there is a write operation in a thread. + * + * @details This function duplicates a packet in the packet buffer if + * ng_pktsnip_t::users of @p pkt > 1. + * + * @note Do *not* call this function in a thread twice on the same packet. + * + * @param[in] pkt The packet you want to write into. + * + * @return The (new) pointer to the pkt. + * @return NULL, if ng_pktsnip_t::users of @p pkt > 1 and if there is not anough + * space in the packet buffer. + */ +ng_pktsnip_t *ng_pktbuf_start_write(ng_pktsnip_t *pkt); + +#ifdef DEVELHELP +/** + * @brief Prints some statistics about the packet buffer to stdout. + * + * @note Only available with DEVELHELP defined. + * + * @details Statistics include maximum number of reserved bytes. + */ +void ng_pktbuf_stats(void); +#endif + +/* for testing */ +#ifdef TEST_SUITES +/** + * @brief Checks if packet buffer is empty + * + * @return true, if packet buffer is empty + * @return false, if packet buffer is not empty + */ +bool ng_pktbuf_is_empty(void); + +/** + * @brief Resets the whole packet buffer + */ +void ng_pktbuf_reset(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NG_PKTBUF_H_ */ +/** @} */ diff --git a/sys/net/crosslayer/pktbuf/Makefile b/sys/net/crosslayer/ng_pktbuf/Makefile similarity index 100% rename from sys/net/crosslayer/pktbuf/Makefile rename to sys/net/crosslayer/ng_pktbuf/Makefile diff --git a/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c b/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c new file mode 100644 index 0000000000..12f6464da1 --- /dev/null +++ b/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2015 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_ng_pktbuf + * @{ + * + * @file + * + * @author Martine Lenders + */ + +#include +#include + +#include "_pktbuf_internal.h" +#include "net/ng_pktbuf.h" +#include "utlist.h" + +#if NG_PKTBUF_SIZE == 0 +/* chunk table to allow for free(ptr + x)-like behaviour */ +typedef struct __attribute__((packed)) _chunk_list_t { + struct _chunk_list_t *next; + uint8_t *ptr; +} _chunk_list_t; + +typedef struct __attribute__((packed)) _chunk_table_t { + struct _chunk_table_t *next; + uint8_t *range_start; + size_t range_len; + _chunk_list_t *chunks; + uint8_t used; +} _chunk_table_t; + +static _chunk_table_t *_chunk_table = NULL; + +/* this organizes chunks, since free(ptr + x) is not possible on most platforms */ +static _chunk_table_t *_create_table_entry(void *pkt, size_t size); +static _chunk_table_t *_find_chunk(const uint8_t *chunk, _chunk_table_t **prev, + _chunk_list_t **node_res); +static inline bool _in_range(_chunk_table_t *entry, uint8_t *ptr); + +void *_pktbuf_internal_alloc(size_t size) +{ + _chunk_table_t *entry; + void *data; + + if (size == 0) { + return 0; + } + + data = malloc(size); + + if (data == NULL) { + return NULL; + } + + entry = _create_table_entry(data, size); + + if (entry == NULL) { + free(data); + + return NULL; + } + + /* cppcheck-suppress memleak entry will be freed eventually in _pktbuf_internal_free(). + * Checked with valgrind. */ + return data; +} + +void *_pktbuf_internal_realloc(void *ptr, size_t size) +{ + _chunk_list_t *node = NULL; + void *new = NULL; + _chunk_table_t *entry; + + if (size == 0) { + return NULL; + } + + entry = _find_chunk(ptr, NULL, &node); + + /* entry can't be NULL since prelimanary _pktbuf_internal_contains() check ensures that */ + if ((ptr == entry->range_start) && (entry->chunks == NULL)) { + new = realloc(entry->range_start, size); + + if (new == NULL) { + return NULL; + } + + entry->range_start = new; + entry->range_len = size; + } + else { + size_t range_len = entry->range_len; + + if (node != NULL) { + range_len -= (node->ptr - entry->range_start); + } + + new = malloc(size); + + if (new == NULL) { + return NULL; + } + + entry = _create_table_entry(new, size); + + if (entry == NULL) { + free(new); + + return NULL; + } + + memcpy(new, ptr, (size < range_len) ? size : range_len); + _pktbuf_internal_free(ptr); + } + + return new; + /* cppcheck-suppress memleak entry will be freed eventually in _pktbuf_internal_free(). + * Checked with valgrind. */ +} + +bool _pktbuf_internal_add_pkt(void *ptr) +{ + _chunk_table_t *entry = _chunk_table; + + while (entry != NULL) { + if (_in_range(entry, ptr)) { + _chunk_list_t *node = malloc(sizeof(_chunk_list_t)); + + if (node == NULL) { + return false; + } + + node->ptr = ptr; + LL_PREPEND(entry->chunks, node); + + return true; + } + + entry = entry->next; + } + + return false; +} + +void _pktbuf_internal_free(void *ptr) +{ + _chunk_list_t *node = NULL; + _chunk_table_t *prev = NULL, *entry = _find_chunk(ptr, &prev, &node); + + if (node != NULL) { + LL_DELETE(entry->chunks, node); + free(node); + } + else if (entry->range_start == ptr) { + entry->used = 0; + } + + if (entry->chunks == NULL && entry->used == 0) { + if (prev == NULL) { + if (entry->next == NULL) { + _chunk_table = NULL; + } + else { + _chunk_table = entry->next; + } + } + else { + prev->next = entry->next; + } + + free(entry->range_start); + free(entry); + } +} + +bool _pktbuf_internal_contains(const void *ptr) +{ + return (_find_chunk(ptr, NULL, NULL) != NULL); +} + +#ifdef DEVELHELP +void _pktbuf_internal_stats(void) +{ + printf("Dynamic packet buffer\n"); +} +#endif + +#ifdef TEST_SUITES +bool _pktbuf_internal_is_empty(void) +{ + return (_chunk_table == NULL); +} + +void _pktbuf_internal_reset(void) +{ + _chunk_table_t *entry = _chunk_table; + + while (entry != NULL) { + _chunk_table_t *next = entry->next; + _chunk_list_t *node = entry->chunks; + free(entry->range_start); + + while (entry->chunks != NULL) { + LL_DELETE(entry->chunks, node); + free(node); + } + + free(entry); + entry = next; + } + + _chunk_table = NULL; +} +#endif + +static _chunk_table_t *_create_table_entry(void *data, size_t size) +{ + _chunk_table_t *entry = (_chunk_table_t *)malloc(sizeof(_chunk_table_t)); + + if (entry == NULL) { + return NULL; + } + + if (_chunk_table == NULL) { + entry->next = NULL; + _chunk_table = entry; + } + else { + entry->next = _chunk_table; + _chunk_table = entry; + } + + entry->range_start = data; + entry->range_len = size; + entry->chunks = NULL; + entry->used = 1; + + return entry; +} + +static _chunk_table_t *_find_chunk(const uint8_t *chunk, _chunk_table_t **prev, + _chunk_list_t **node_res) +{ + _chunk_table_t *entry = _chunk_table; + + if (prev != NULL) { + *prev = NULL; + } + + while (entry != NULL) { + _chunk_list_t *node = entry->chunks; + + if (entry->range_start == chunk) { + if (node_res != NULL) { + *node_res = NULL; + } + + return entry; + } + + while (node != NULL) { + if (node->ptr == chunk) { + if (node_res != NULL) { + *node_res = node; + } + + return entry; + } + + node = node->next; + } + + if (prev != NULL) { + *prev = entry; + } + + entry = entry->next; + } + + return NULL; +} + +static inline bool _in_range(_chunk_table_t *entry, uint8_t *ptr) +{ + return (entry != NULL) && + (ptr >= entry->range_start) && + (ptr < (entry->range_start + entry->range_len)); +} +#endif + +/** @} */ diff --git a/sys/net/crosslayer/ng_pktbuf/_pktbuf_internal.h b/sys/net/crosslayer/ng_pktbuf/_pktbuf_internal.h new file mode 100644 index 0000000000..ae29ca1880 --- /dev/null +++ b/sys/net/crosslayer/ng_pktbuf/_pktbuf_internal.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_ng_pktbuf + * @{ + * + * @file + * @brief Internal definitions for the packet buffer + * + * @author Martine Lenders + */ +#ifndef XPKTBUF_INTERNAL_H_ +#define XPKTBUF_INTERNAL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Internal alloc on packet buffer + * + * @internal + * + * @see + * malloc() + * + */ +void *_pktbuf_internal_alloc(size_t size); + +/** + * @brief Internal realloc on static packet buffer + * + * @internal + * + * @see + * realloc() + * + */ +void *_pktbuf_internal_realloc(void *ptr, size_t size); + +/** + * @brief Adds packet that uses @p ptr for its data part + * + * @internal + */ +bool _pktbuf_internal_add_pkt(void *ptr); + +/** + * @brief Internal free on static packet buffer + * + * @internal + * + * @see + * free() + * but @p ptr can be anywhere in alloced space. + */ +void _pktbuf_internal_free(void *ptr); + +/** + * @brief Checks if a pointer is part of the static packet buffer. + * + * @param[in] ptr A pointer. + * + * @return true, if @p ptr is part of the static packet buffer. + * @return false, if @p ptr is not part of the static packet buffer. + */ +bool _pktbuf_internal_contains(const void *ptr); + +#ifdef DEVELHELP +/** + * @brief Prints some statistics about the packet buffer to stdout. + * + * @details Statistics include maximum number of reserved bytes. + */ +void _pktbuf_internal_stats(void); +#endif + +/* for testing */ +#ifdef TEST_SUITES +/** + * @brief Checks if packet buffer is empty + * + * @return 1, if packet buffer is empty + * @return 0, if packet buffer is not empty + */ +bool _pktbuf_internal_is_empty(void); + +/** + * @brief Sets the whole packet buffer to 0 + */ +void _pktbuf_internal_reset(void); +#endif /* TEST_SUITES */ + +#ifdef __cplusplus +} +#endif + +#endif /* XPKTBUF_INTERNAL_H_ */ +/** @} */ diff --git a/sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c b/sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c new file mode 100644 index 0000000000..f03c8959f2 --- /dev/null +++ b/sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2015 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_ng_pktbuf + * @{ + * + * @file + * + * @author Martine Lenders + */ + +#include +#include +#include +#include + +#include "net/ng_pktbuf.h" +#include "_pktbuf_internal.h" + +/* only for static packet buffer */ +#if NG_PKTBUF_SIZE > 0 + +#define _PKTBUF_ALIGN_BYTES (sizeof(void *)) + +#ifdef DEVELHELP +static unsigned int _pktbuf_max_bytes = 0; +#endif + +/** + * @brief Data type to represent used chunks in packet buffer. + */ +typedef struct __attribute__((packed)) _used_t { + struct _used_t *next; + uint16_t size; + uint8_t pkts; + uint8_t _align; /* alignment */ +} _used_t; + +static uint8_t _buf[NG_PKTBUF_SIZE]; + +/** + * @brief Get first element in buffer + */ +static inline _used_t *_head(void) +{ + return (_used_t *)_buf; +} + +/** + * @brief Get data part (memory behind `_used_t` descriptive header) of a packet + */ +static inline void *_data(_used_t *node) +{ + return (void *)(((_used_t *)node) + 1); +} + +static inline void *_data_end(_used_t *node) +{ + return (void *)(((uint8_t *)_data(node)) + node->size); +} + +static inline bool _in_data_range(_used_t *node, const void *ptr) +{ + return (ptr >= _data(node)) && (ptr < _data_end(node)); +} + +/** + * @brief Size with metadata of allocation + */ +static inline size_t _total_sz(uint16_t sz) +{ + return sizeof(_used_t) + sz; +} + +/** + * @brief _used_t typed alias for _total_sz + */ +static inline size_t __total_sz(_used_t *node) +{ + return _total_sz(node->size); +} + +/** + * @brief aligned size with metadata + */ +static inline size_t __al_total_sz(_used_t *node) +{ + size_t size = __total_sz(node); + + if (size % _PKTBUF_ALIGN_BYTES) { + return size + (_PKTBUF_ALIGN_BYTES - (size % _PKTBUF_ALIGN_BYTES)); + } + else { + return size; + } +} + +/** + * @brief Index of an allocation's first byte in buffer + */ +static inline unsigned int _start_idx(_used_t *node) +{ + return (int)(((uint8_t *)node) - _buf); +} + +/** + * @brief Index of an allocation's last byte in buffer + */ +static inline unsigned int _end_idx(_used_t *node) +{ + return _start_idx(node) + __total_sz(node) - 1; +} + +static _used_t *_find(_used_t **prev_ptr, _used_t **node_ptr, const void *ptr) +{ + _used_t *node = _head(), *prev = NULL; + + if (ptr != NULL) { + while (node != NULL) { + if (_in_data_range(node, ptr)) { + *prev_ptr = prev; + *node_ptr = node; + return node; + } + + prev = node; + node = (_used_t *)node->next; + } + } + + *prev_ptr = NULL; + *node_ptr = NULL; + + return NULL; +} + +void *_pktbuf_internal_alloc(size_t size) +{ + _used_t *node = _head(), *old_next, *new_next; + + if ((size == 0) || (size > NG_PKTBUF_SIZE)) { + return NULL; + } + + if (node->size == 0) { /* if head is currently not initialized */ + if (node->next == NULL || (_start_idx(node->next) >= _total_sz(size))) { + /* if enough space is there */ + node->size = size; /* just take it */ + node->pkts = 1; + + return _data(node); + } + else if (node->next != NULL) { + /* else go directly to next allocation if it exists */ + node = node->next; + } + } + + while ((node->next != NULL) + /* and if space between current and next allocation is not big enough */ + && ((_start_idx(node->next) - _end_idx(node)) < _total_sz(size))) { + node = node->next; + } + + /* jump ahead size of current packet */ + new_next = (_used_t *)(((uint8_t *)node) + __al_total_sz(node)); + + if ((((uint8_t *)new_next) + size) > (((uint8_t *)_head()) + NG_PKTBUF_SIZE)) { + /* new packet does not fit into _pktbuf */ + return NULL; + } + + old_next = node->next; + node->next = new_next; + node->next->next = old_next; + + node = new_next; + node->size = size; + node->pkts = 1; + +#ifdef DEVELHELP + + if ((_end_idx(node) + 1) > _pktbuf_max_bytes) { + _pktbuf_max_bytes = _end_idx(node) + 1; + } + +#endif + + return _data(node); +} + +bool _pktbuf_internal_add_pkt(void *ptr) +{ + _used_t *prev, *node; + + if (_find(&prev, &node, ptr) != NULL) { + (node->pkts)++; + + return true; + } + + return false; +} + +static inline void _free_helper(_used_t *prev, _used_t *node) +{ + if ((--(node->pkts)) == 0) { + if (prev == NULL) { + node->size = 0; + } + else { + prev->next = node->next; + } + } +} + +void _pktbuf_internal_free(void *ptr) +{ + _used_t *prev, *node; + + if (_find(&prev, &node, ptr) != NULL) { + _free_helper(prev, node); + } +} + +void *_pktbuf_internal_realloc(void *ptr, size_t size) +{ + _used_t *new, *prev, *orig = NULL; + + if ((size == 0) || (size > NG_PKTBUF_SIZE)) { + return NULL; + } + + _find(&prev, &orig, ptr); + + if ((orig != NULL) && + ((orig->size >= size) /* size in orig is sufficient */ + || ((orig->next == NULL) /* or orig is last packet and buffer space is sufficient */ + && ((_start_idx(orig) + _total_sz(size)) < NG_PKTBUF_SIZE)) + || ((orig->next != NULL) /* or space between orig and orig->next is sufficient */ + && ((_start_idx(orig->next) - _start_idx(orig)) >= _total_sz(size))))) { + orig->size = size; + + return ptr; + } + + new = _pktbuf_internal_alloc(size); + + if (new != NULL) { + if (orig != NULL) { + memcpy(_data(new), ptr, (orig->size < size) ? orig->size : size); + _free_helper(prev, orig); + } + + return _data(new); + } + + return NULL; +} + +bool _pktbuf_internal_contains(const void *ptr) +{ + return ((_buf < ((uint8_t *)ptr)) && (((uint8_t *)ptr) <= &(_buf[NG_PKTBUF_SIZE - 1]))); +} + +#ifdef DEVELHELP +void _pktbuf_internal_stats(void) +{ + printf("Static packet buffer\n"); + printf(" * Maximum number of reserved bytes: %u\n", _pktbuf_max_bytes); +} +#endif + +/* for testing */ +#ifdef TEST_SUITES +bool _pktbuf_internal_is_empty(void) +{ + return ((_head()->next == NULL) && (_head()->size == 0)); +} + +void _pktbuf_internal_reset(void) +{ + _head()->next = NULL; + _head()->size = 0; +#ifdef DEVELHELP + _pktbuf_max_bytes = 0; +#endif +} +#endif /* TEST_SUITES */ +#endif /* NG_PKTBUF_SIZE > 0 */ + +/** @} */ diff --git a/sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c b/sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c new file mode 100644 index 0000000000..8f710371b4 --- /dev/null +++ b/sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2014 Martine Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_ng_pktbuf + * @{ + * + * @file + * + * @author Martine Lenders + */ + +#include +#include +#include +#include +#include + +#include "clist.h" +#include "mutex.h" +#include "net/ng_nettype.h" +#include "net/ng_pkt.h" +#include "utlist.h" + +#include "net/ng_pktbuf.h" + +#include "_pktbuf_internal.h" + +static mutex_t _pktbuf_mutex = MUTEX_INIT; + +/* internal ng_pktbuf functions */ +static ng_pktsnip_t *_pktbuf_alloc(size_t size); +static ng_pktsnip_t *_pktbuf_add_unsafe(ng_pktsnip_t *pkt, void *data, + size_t size, ng_nettype_t type); +static ng_pktsnip_t *_pktbuf_duplicate(const ng_pktsnip_t *pkt); + +int ng_pktbuf_realloc_data(ng_pktsnip_t *pkt, size_t size) +{ + void *new; + + if (pkt == NULL || !_pktbuf_internal_contains(pkt->data)) { + return ENOENT; + } + + if (pkt->users > 1 || pkt->next != NULL) { + return EINVAL; + } + + mutex_lock(&_pktbuf_mutex); + + new = _pktbuf_internal_realloc(pkt->data, size); + + mutex_unlock(&_pktbuf_mutex); + + if (new == NULL) { + return ENOMEM; + } + + pkt->data = new; + pkt->size = size; + + return 0; +} + +ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type) +{ + ng_pktsnip_t *snip; + + mutex_lock(&_pktbuf_mutex); + + snip = _pktbuf_add_unsafe(next, data, size, type); + + mutex_unlock(&_pktbuf_mutex); + + return snip; +} + +void ng_pktbuf_release(ng_pktsnip_t *pkt) +{ + if (pkt == NULL) { + return; + } + + atomic_set_return(&(pkt->users), pkt->users - 1); + + if (pkt->users == 0 && _pktbuf_internal_contains(pkt->data)) { + mutex_lock(&_pktbuf_mutex); + + _pktbuf_internal_free(pkt->data); + _pktbuf_internal_free(pkt); + + mutex_unlock(&_pktbuf_mutex); + } +} + +ng_pktsnip_t *ng_pktbuf_start_write(ng_pktsnip_t *pkt) +{ + if (pkt != NULL && pkt->users > 1) { + ng_pktsnip_t *res = NULL; + + mutex_lock(&_pktbuf_mutex); + + res = _pktbuf_duplicate(pkt); + + atomic_set_return(&pkt->users, pkt->users - 1); + + mutex_unlock(&_pktbuf_mutex); + + return res; + } + + return pkt; +} + +/*********************************** + * internal ng_pktbuf functions * + ***********************************/ + +static ng_pktsnip_t *_pktbuf_alloc(size_t size) +{ + ng_pktsnip_t *pkt; + + pkt = (ng_pktsnip_t *)_pktbuf_internal_alloc(sizeof(ng_pktsnip_t)); + + if (pkt == NULL) { + return NULL; + } + + pkt->data = _pktbuf_internal_alloc(size); + + if (pkt->data == NULL) { + _pktbuf_internal_free(pkt); + + return NULL; + } + + pkt->next = NULL; + pkt->size = size; + pkt->users = 1; + + return pkt; +} + +static ng_pktsnip_t *_pktbuf_add_unsafe(ng_pktsnip_t *next, void *data, + size_t size, ng_nettype_t type) +{ + ng_pktsnip_t *snip; + + if (size == 0) { + data = 0; + } + + snip = (ng_pktsnip_t *)_pktbuf_internal_alloc(sizeof(ng_pktsnip_t)); + + if (snip == NULL) { + return NULL; + } + + if (next == NULL || next->data != data) { + if (size != 0) { + snip->data = _pktbuf_internal_alloc(size); + + if (snip->data == NULL) { + _pktbuf_internal_free(snip); + + return NULL; + } + + if (data != NULL) { + memcpy(snip->data, data, size); + } + } + else { + snip->data = data; + } + } + else { + snip->data = data; + + next->size -= size; + next->data = (void *)(((uint8_t *)next->data) + size); + + if (!_pktbuf_internal_add_pkt(next->data)) { + _pktbuf_internal_free(snip); + + return NULL; + } + } + + snip->next = NULL; + snip->size = size; + snip->type = type; + snip->users = 1; + + LL_PREPEND(next, snip); + + return snip; +} + +static ng_pktsnip_t *_pktbuf_duplicate(const ng_pktsnip_t *pkt) +{ + ng_pktsnip_t *res = NULL; + + res = _pktbuf_alloc(pkt->size); + + if (res == NULL) { + return NULL; + } + + memcpy(res->data, pkt->data, pkt->size); + res->type = pkt->type; + + while (pkt->next) { + ng_pktsnip_t *header = NULL; + + pkt = pkt->next; + header = _pktbuf_add_unsafe(res, pkt->data, pkt->size, pkt->type); + + if (header == NULL) { + do { + ng_pktsnip_t *next = res->next; + + _pktbuf_internal_free(res->data); + _pktbuf_internal_free(res); + + res = next; + } while (res); + + return NULL; + } + } + + return res; +} + +#ifdef DEVELHELP +void ng_pktbuf_stats(void) +{ + _pktbuf_internal_stats(); +} +#endif + +#ifdef TEST_SUITES +bool ng_pktbuf_is_empty(void) +{ + return _pktbuf_internal_is_empty(); +} + +void ng_pktbuf_reset(void) +{ + _pktbuf_internal_reset(); +} +#endif + +/** @} */ diff --git a/sys/net/crosslayer/pktbuf/pktbuf.c b/sys/net/crosslayer/pktbuf/pktbuf.c deleted file mode 100644 index a1bebff285..0000000000 --- a/sys/net/crosslayer/pktbuf/pktbuf.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (C) 2014 Martine Lenders - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @{ - * - * @file pktbuf.c - * - * @author Martine Lenders - */ - -#include -#include -#include -#include - -#include "mutex.h" -#include "pktbuf.h" - -#if PKTBUF_SIZE < 128 -typedef uint8_t _pktsize_t; -#elif PKTBUF_SIZE < 65536 -typedef uint16_t _pktsize_t; -#else -typedef size_t _pktsize_t; -#endif - -typedef struct __attribute__((packed)) _packet_t { - volatile struct _packet_t *next; - uint8_t processing; - _pktsize_t size; -} _packet_t; - -static uint8_t _pktbuf[PKTBUF_SIZE]; -static mutex_t _pktbuf_mutex = MUTEX_INIT; - -/** - * @brief Get first element in packet buffer. - */ -static inline _packet_t *_pktbuf_head(void) -{ - return (_packet_t *)(&(_pktbuf[0])); -} - -/** - * @brief Get data part (memory behind `_packet_t` descriptive header) of a packet - * - * @param[in] pkt A packet - * - * @return Data part of the packet. - */ -static inline void *_pkt_data(_packet_t *pkt) -{ - return (void *)(((_packet_t *)pkt) + 1); -} - -/** - * @brief Calculates total size (*size* + size of `_packet_t` descriptive header) of a - * packet in memory - * - * @param[in] size A given packet size - * - * @return Total size of a packet in memory. - */ -static inline size_t _pkt_total_sz(size_t size) -{ - return sizeof(_packet_t) + size; -} - -/** - * @brief Get pointer to the byte after the last byte of a packet. - * - * @param[in] pkt A packet - * - * @return Pointer to the last byte of a packet - */ -static inline void *_pkt_end(_packet_t *pkt) -{ - return (void *)((uint8_t *)pkt + _pkt_total_sz(pkt->size)); -} - -/** - * @brief Get index in packet buffer of the first byte of a packet's data part - * - * @param[in] pkt A packet - * - * @return Index in packet buffer of the first byte of *pkt*'s data part. - */ -static inline size_t _pktbuf_start_idx(_packet_t *pkt) -{ - return (size_t)(((uint8_t *)pkt) - (&(_pktbuf[0]))); -} - -/** - * @brief Get index in packet buffer of the last byte of a packet's data part - * - * @param[in] pkt A packet - * - * @return Index in packet buffer of the last byte of *pkt*'s data part. - */ -static inline size_t _pktbuf_end_idx(_packet_t *pkt) -{ - return _pktbuf_start_idx(pkt) + _pkt_total_sz(pkt->size) - 1; -} - -static _packet_t *_pktbuf_find_with_prev(_packet_t **prev_ptr, - _packet_t **packet_ptr, const void *pkt) -{ - _packet_t *packet = _pktbuf_head(), *prev = NULL; - - while (packet != NULL) { - - if (_pkt_data(packet) == pkt) { - *prev_ptr = prev; - *packet_ptr = packet; - return packet; - } - - prev = packet; - packet = (_packet_t *)packet->next; - } - - *prev_ptr = NULL; - *packet_ptr = NULL; - - return NULL; -} - -static _packet_t *_pktbuf_find(const void *pkt) -{ - _packet_t *packet = _pktbuf_head(); - -#ifdef DEVELHELP - - if (pkt == NULL) { - return NULL; - } - -#endif /* DEVELHELP */ - - while (packet != NULL) { - if ((_pkt_data(packet) <= pkt) && (pkt < _pkt_end(packet))) { - mutex_unlock(&_pktbuf_mutex); - return packet; - } - - packet = (_packet_t *)packet->next; - } - - return NULL; -} - -static _packet_t *_pktbuf_alloc(size_t size) -{ - _packet_t *packet = _pktbuf_head(), *old_next; - - if ((size == 0) || (size > PKTBUF_SIZE)) { - return NULL; - } - - if ((packet->size == 0) /* if first packet is currently not initialized - * but next packet and no space between first - * and next in its slot */ - && (packet->processing == 0) - && (packet->next != NULL) - && ((_pktbuf_start_idx((_packet_t *)(packet->next)) - _pkt_total_sz(packet->size)) < size)) { - packet = (_packet_t *)packet->next; - } - - /* while packet is not initialized */ - while ((packet->processing > 0) || (packet->size > size)) { - old_next = (_packet_t *)packet->next; - - /* if current packet is the last in buffer, but buffer space is exceeded */ - if ((old_next == NULL) - && ((_pktbuf_end_idx(packet) + _pkt_total_sz(size)) > PKTBUF_SIZE)) { - return NULL; - } - - /* if current packet is the last in the buffer or if space between - * current packet and next packet is big enough */ - if ((old_next == NULL) - || ((_pktbuf_start_idx((_packet_t *)(packet->next)) - _pktbuf_end_idx(packet)) >= _pkt_total_sz( - size))) { - - _packet_t *new_next = (_packet_t *)(((uint8_t *)packet) + _pkt_total_sz(packet->size)); - /* jump ahead size of current packet. */ - packet->next = new_next; - packet->next->next = old_next; - - packet = new_next; - - break; - } - - packet = old_next; - } - - packet->size = size; - packet->processing = 1; - - return packet; -} - -static void _pktbuf_free(_packet_t *prev, _packet_t *packet) -{ - if ((packet->processing)-- > 1) { /* `> 1` because packet->processing may already - * be 0 in which case --(packet->processing) - * would wrap to 255. */ - return; - } - - if (prev == NULL) { /* packet is _pktbuf_head() */ - packet->size = 0; - } - else { - prev->next = packet->next; - } -} - -int pktbuf_contains(const void *pkt) -{ - return ((&(_pktbuf[0]) < ((uint8_t *)pkt)) && (((uint8_t *)pkt) <= &(_pktbuf[PKTBUF_SIZE - 1]))); -} - -void *pktbuf_alloc(size_t size) -{ - _packet_t *packet; - - mutex_lock(&_pktbuf_mutex); - - packet = _pktbuf_alloc(size); - - if (packet == NULL) { - mutex_unlock(&_pktbuf_mutex); - return NULL; - } - - mutex_unlock(&_pktbuf_mutex); - - return _pkt_data(packet); -} - -void *pktbuf_realloc(const void *pkt, size_t size) -{ - _packet_t *new, *prev, *orig; - - mutex_lock(&_pktbuf_mutex); - - if ((size == 0) || (size > PKTBUF_SIZE)) { - mutex_unlock(&_pktbuf_mutex); - return NULL; - } - - _pktbuf_find_with_prev(&prev, &orig, pkt); - - if ((orig != NULL) && - ((orig->size >= size) /* and *orig* is last packet, and space in - * _pktbuf is sufficient */ - || ((orig->next == NULL) - && ((_pktbuf_start_idx(orig) + _pkt_total_sz(size)) < PKTBUF_SIZE)) - || ((orig->next != NULL) /* or space between pointer and the next is big enough: */ - && ((_pktbuf_start_idx((_packet_t *)(orig->next)) - _pktbuf_start_idx(orig)) - >= _pkt_total_sz(size))))) { - orig->size = size; - - mutex_unlock(&_pktbuf_mutex); - return (void *)pkt; - } - - new = _pktbuf_alloc(size); - - if (new == NULL) { - mutex_unlock(&_pktbuf_mutex); - return NULL; - } - - if (orig != NULL) { - memcpy(_pkt_data(new), _pkt_data(orig), orig->size); - - _pktbuf_free(prev, orig); - } - else { - memcpy(_pkt_data(new), pkt, size); - } - - - mutex_unlock(&_pktbuf_mutex); - - return _pkt_data(new); -} - -void *pktbuf_insert(const void *data, size_t size) -{ - _packet_t *packet; - - if ((data == NULL) || (size == 0)) { - return NULL; - } - - mutex_lock(&_pktbuf_mutex); - packet = _pktbuf_alloc(size); - - if (packet == NULL) { - mutex_unlock(&_pktbuf_mutex); - return NULL; - } - - memcpy(_pkt_data(packet), data, size); - - mutex_unlock(&_pktbuf_mutex); - return _pkt_data(packet); -} - -int pktbuf_copy(void *pkt, const void *data, size_t data_len) -{ - _packet_t *packet; - - mutex_lock(&_pktbuf_mutex); - -#ifdef DEVELHELP - - if (data == NULL) { - mutex_unlock(&_pktbuf_mutex); - return -EFAULT; - } - - if (pkt == NULL) { - mutex_unlock(&_pktbuf_mutex); - return -EINVAL; - } - -#endif /* DEVELHELP */ - - packet = _pktbuf_find(pkt); - - - if ((packet != NULL) && (packet->size > 0) && (packet->processing > 0)) { - /* packet space not engough? */ - if (data_len > (size_t)(((uint8_t *)_pkt_end(packet)) - ((uint8_t *)pkt))) { - mutex_unlock(&_pktbuf_mutex); - return -ENOMEM; - } - } - - - memcpy(pkt, data, data_len); - - mutex_unlock(&_pktbuf_mutex); - return data_len; -} - -void pktbuf_hold(const void *pkt) -{ - _packet_t *packet; - - mutex_lock(&_pktbuf_mutex); - - packet = _pktbuf_find(pkt); - - if (packet != NULL) { - packet->processing++; - } - - mutex_unlock(&_pktbuf_mutex); -} - -void pktbuf_release(const void *pkt) -{ - _packet_t *packet = _pktbuf_head(), *prev = NULL; - - mutex_lock(&_pktbuf_mutex); - - while (packet != NULL) { - - if ((_pkt_data(packet) <= pkt) && (pkt < _pkt_end(packet))) { - _pktbuf_free(prev, packet); - - mutex_unlock(&_pktbuf_mutex); - return; - } - - prev = packet; - packet = (_packet_t *)packet->next; - } - - mutex_unlock(&_pktbuf_mutex); -} - -#ifdef DEVELHELP -#include - -void pktbuf_print(void) -{ - _packet_t *packet = _pktbuf_head(); - int i = 0; - - mutex_lock(&_pktbuf_mutex); - - printf("current pktbuf allocations:\n"); - printf("===================================================\n"); - - if (packet->next == NULL && packet->size == 0) { - printf("empty\n"); - printf("===================================================\n"); - printf("\n"); - mutex_unlock(&_pktbuf_mutex); - - return; - } - else if (packet->next != NULL && packet->size == 0) { - packet = (_packet_t *)packet->next; - } - - while (packet != NULL) { - uint8_t *data = (uint8_t *)_pkt_data(packet); - - printf("packet %d (%p):\n", i, (void *)packet); - printf(" next: %p\n", (void *)(packet->next)); - printf(" size: %" PRIu32 "\n", (uint32_t)packet->size); - printf(" processing: %" PRIu8 "\n", packet->processing); - - if (packet->next != NULL) { - printf(" free data after: %" PRIu32 "\n", - (uint32_t)(_pktbuf_start_idx((_packet_t *)(packet->next)) - _pktbuf_end_idx(packet) - 1)); - } - else { - printf(" free data after: %" PRIu32 "\n", (uint32_t)(PKTBUF_SIZE - _pktbuf_end_idx(packet) - 1)); - - } - - printf(" data: (start address: %p)\n ", data); - - if (packet->size > PKTBUF_SIZE) { - printf(" We have a problem: packet->size (%" PRIu32 ") > PKTBUF_SIZE (%" PRIu32 ")\n", - (uint32_t)(packet->size), (uint32_t)PKTBUF_SIZE); - } - else { - for (size_t j = 0; j < packet->size; j++) { - printf(" %02x", data[j]); - - if (((j + 1) % 16) == 0) { - printf("\n "); - } - } - - printf("\n\n"); - } - - packet = (_packet_t *)packet->next; - i++; - } - - printf("===================================================\n"); - printf("\n"); - - mutex_unlock(&_pktbuf_mutex); - -} -#endif - -#ifdef TEST_SUITES -size_t pktbuf_bytes_allocated(void) -{ - _packet_t *packet = _pktbuf_head(); - size_t bytes = 0; - - mutex_lock(&_pktbuf_mutex); - - while (packet != NULL) { - bytes += packet->size; - packet = (_packet_t *)(packet->next); - } - - mutex_unlock(&_pktbuf_mutex); - - return bytes; -} - -unsigned int pktbuf_packets_allocated(void) -{ - _packet_t *packet = _pktbuf_head(); - unsigned int packets = 0; - - mutex_lock(&_pktbuf_mutex); - - while (packet != NULL) { - if ((packet != _pktbuf_head()) || (packet->size > 0)) { /* ignore head if head->size == 0 */ - packets++; - } - - packet = (_packet_t *)(packet->next); - } - - mutex_unlock(&_pktbuf_mutex); - - return packets; -} - -int pktbuf_is_empty(void) -{ - return ((_pktbuf_head()->next == NULL) && (_pktbuf_head()->size == 0)); -} - -void pktbuf_reset(void) -{ - memset(_pktbuf, 0, PKTBUF_SIZE); - mutex_init(&_pktbuf_mutex); -} -#endif - -/** @} */ diff --git a/sys/net/include/pktbuf.h b/sys/net/include/pktbuf.h deleted file mode 100644 index ce9bb77087..0000000000 --- a/sys/net/include/pktbuf.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2014 Martine Lenders - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @defgroup pktbuf Packet buffer - * @ingroup net - * @brief A global network packet buffer. - * @{ - * - * @file pktbuf.h - * @brief Interface definition for the global network buffer. Network devices - * and layers can allocate space for packets here. - * - * @note **WARNING!!** Do not store data structures that are not packed - * (defined with `__attribute__((packed))`) or enforce alignment in - * in any way in here. On some RISC architectures this *will* lead to - * alignment problems and can potentially result in segmentation/hard - * faults and other unexpected behaviour. - * - * @author Martine Lenders - */ -#ifndef __PKTBUF_H_ -#define __PKTBUF_H_ - -#include - -#include "cpu-conf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef PKTBUF_SIZE -/** - * @brief Maximum size of the packet buffer. - * - * @details The rational here is to have at least space for 4 full-MTU IPv6 - * packages (2 incoming, 2 outgoing; 2 * 2 * 1280 B = 5 KiB) + - * Meta-Data (roughly estimated to 1 KiB; might be smaller) - */ -#define PKTBUF_SIZE (6144) -#endif /* PKTBUF_SIZE */ - -/** - * @brief Allocates new packet data in the packet buffer. This also marks the - * allocated data as processed. - * - * @see @ref pktbuf_hold() - * - * @param[in] size The length of the packet you want to allocate - * - * @return Pointer to the start of the data in the packet buffer, on success. - * @return NULL, if no space is left in the packet buffer or size was 0. - */ -void *pktbuf_alloc(size_t size); - -/** - * @brief Reallocates new space in the packet buffer, without changing the - * content. - * - * @details If enough memory is available behind it or *size* is smaller than - * the original size the packet will not be moved. Otherwise, it will - * be moved. If no space is available nothing happens. - * - * @param[in] pkt Old position of the packet in the packet buffer - * @param[in] size New amount of data you want to allocate - * - * @return Pointer to the (maybe new) position of the packet in the packet buffer, - * on success. - * @return NULL, if no space is left in the packet buffer or size was 0. - * The packet will remain at *ptr*. - */ -void *pktbuf_realloc(const void *pkt, size_t size); - -/** - * @brief Allocates and copies new packet data into the packet buffer. - * This also marks the allocated data as processed for the current - * thread. - * - * @see @ref pktbuf_hold() - * - * @param[in] data Data you want to copy into the new packet. - * @param[in] size The length of the packet you want to allocate - * - * @return Pointer to the start of the data in the packet buffer, on success. - * @return NULL, if no space is left in the packet buffer. - */ -void *pktbuf_insert(const void *data, size_t size); - -/** - * @brief Copies packet data into the packet buffer, safely. - * - * @details Use this instead of memcpy, since it is thread-safe and checks if - * *pkt* is - * - * -# in the buffer at all - * -# its *size* is smaller or equal to the data allocated at *pkt* - * - * If the *pkt* is not in the buffer the data is just copied as - * memcpy would do. - * - * @param[in,out] pkt The packet you want to set the data for. - * @param[in] data The data you want to copy into the packet. - * @param[in] data_len The length of the data you want to copy. - * - * @return *data_len*, on success. - * @return -EFAULT, if *data* is NULL and DEVELHELP is defined. - * @return -EINVAL, if *pkt* is NULL and DEVELHELP is defined. - * @return -ENOBUFS, if *data_len* was greater than the packet size of *pkt*. - */ -int pktbuf_copy(void *pkt, const void *data, size_t data_len); - -/** - * @brief Marks the data as being processed. - * - * @details Internally this increments just a counter on the data. - * @ref pktbuf_release() decrements it. If the counter is <=0 the - * reserved data block in the buffer will be made available again. - * - * @param[in] pkt The packet you want mark as being processed. - */ -void pktbuf_hold(const void *pkt); - -/** - * @brief Marks the data as not being processed. - * - * @param[in] pkt The packet you want mark as not being processed anymore. - * - * @details Internally this decrements just a counter on the data. - * @ref pktbuf_hold() increments and any allocation - * operation initializes it. If the counter is <=0 the reserved data - * block in the buffer will be made available again. - */ -void pktbuf_release(const void *pkt); - -/** - * @brief Prints current packet buffer to stdout if DEVELHELP is defined. - */ -#ifdef DEVELHELP -void pktbuf_print(void); -#else -#define pktbuf_print() ; -#endif - -/* for testing */ -#ifdef TEST_SUITES -/** - * @brief Counts the number of allocated bytes - * - * @return Number of allocated bytes - */ -size_t pktbuf_bytes_allocated(void); - -/** - * @brief Counts the number of allocated packets - * - * @return Number of allocated packets - */ -size_t pktbuf_packets_allocated(void); - -/** - * @brief Checks if packet buffer is empty - * - * @return 1, if packet buffer is empty - * @return 0, if packet buffer is not empty - */ -int pktbuf_is_empty(void); - -/** - * @brief Checks if a given pointer is stored in the packet buffer - * - * @param[in] pkt Pointer to be checked - * - * @return 1, if *pkt* is in packet buffer - * @return 0, otherwise - */ -int pktbuf_contains(const void *pkt); - -/** - * @brief Sets the whole packet buffer to 0 - */ -void pktbuf_reset(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __PKTBUF_H_ */ -/** @} */ diff --git a/tests/unittests/Makefile b/tests/unittests/Makefile index c3e63887d4..a897bec1c1 100644 --- a/tests/unittests/Makefile +++ b/tests/unittests/Makefile @@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_RAM := chronos msb-430 msb-430h redbee-econotag stm32f0discov USEMODULE += embunit # Some randomly generated but still deterministic values for testing +CFLAGS += -DTEST_STRING4="\"J&(d\"" CFLAGS += -DTEST_STRING8="\"o<\\\\rrB/q\"" CFLAGS += -DTEST_STRING12="\"50U'HLKC3_ft\"" CFLAGS += -DTEST_STRING16="\"nvxuO*6o3C=a6g7]\"" diff --git a/tests/unittests/tests-pkt/tests-pkt.c b/tests/unittests/tests-pkt/tests-pkt.c index 309ee420fc..d8864d7999 100644 --- a/tests/unittests/tests-pkt/tests-pkt.c +++ b/tests/unittests/tests-pkt/tests-pkt.c @@ -21,7 +21,7 @@ #include "tests-pkt.h" #define _INIT_ELEM(len, data, next) \ - { (next), (data), (len), NG_NETTYPE_UNDEF } + { 1, (next), (data), (len), NG_NETTYPE_UNDEF } #define _INIT_ELEM_STATIC_DATA(data, next) _INIT_ELEM(sizeof(data), data, next) static void test_pkt_len__NULL(void) diff --git a/tests/unittests/tests-pktbuf/Makefile.include b/tests/unittests/tests-pktbuf/Makefile.include index 48eec3ae44..5f8664dc17 100644 --- a/tests/unittests/tests-pktbuf/Makefile.include +++ b/tests/unittests/tests-pktbuf/Makefile.include @@ -1 +1 @@ -USEMODULE += pktbuf +USEMODULE += ng_pktbuf diff --git a/tests/unittests/tests-pktbuf/tests-pktbuf.c b/tests/unittests/tests-pktbuf/tests-pktbuf.c index 58e9176611..efea269bd7 100644 --- a/tests/unittests/tests-pktbuf/tests-pktbuf.c +++ b/tests/unittests/tests-pktbuf/tests-pktbuf.c @@ -16,7 +16,9 @@ #include "embUnit.h" -#include "pktbuf.h" +#include "net/ng_nettype.h" +#include "net/ng_pkt.h" +#include "net/ng_pktbuf.h" #include "tests-pktbuf.h" @@ -33,421 +35,232 @@ typedef struct __attribute__((packed)) { static void tear_down(void) { - pktbuf_reset(); + ng_pktbuf_reset(); } -static void test_pktbuf_alloc_0(void) +static void test_pktbuf_reset(void) { - TEST_ASSERT_NULL(pktbuf_alloc(0)); + TEST_ASSERT(ng_pktbuf_is_empty()); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_UNDEF)); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), + NG_NETTYPE_UNDEF)); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_UNDEF)); + TEST_ASSERT(!ng_pktbuf_is_empty()); + ng_pktbuf_reset(); + TEST_ASSERT(ng_pktbuf_is_empty()); } -static void test_pktbuf_alloc_memfull(void) +static void test_pktbuf_add__pkt_NULL__data_NULL__size_0(void) +{ + ng_pktsnip_t *pkt; + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(NULL, NULL, 0, NG_NETTYPE_UNDEF))); + + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(0, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NOT_NULL__data_NULL__size_0(void) +{ + ng_pktsnip_t *pkt, *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(next); + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, NULL, 0, NG_NETTYPE_UNDEF))); + + TEST_ASSERT(pkt->next == next); + TEST_ASSERT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(0, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT_NULL(next->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING4, next->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), next->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NULL__data_NOT_NULL__size_0(void) +{ + ng_pktsnip_t *pkt; + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(NULL, TEST_STRING8, 0, NG_NETTYPE_UNDEF))); + + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(0, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NOT_NULL__data_NOT_NULL__size_0(void) +{ + ng_pktsnip_t *pkt, *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(next); + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, TEST_STRING8, 0, NG_NETTYPE_UNDEF))); + + TEST_ASSERT(pkt->next == next); + TEST_ASSERT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(0, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT_NULL(next->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING4, next->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), next->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NULL__data_NULL__size_not_0(void) +{ + ng_pktsnip_t *pkt; + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), + NG_NETTYPE_UNDEF))); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NOT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NOT_NULL__data_NULL__size_not_0(void) +{ + ng_pktsnip_t *pkt, *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(next); + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF))); + + TEST_ASSERT(pkt->next == next); + TEST_ASSERT_NOT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT_NULL(next->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING4, next->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), next->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__pkt_NOT_NULL__data_NOT_NULL__size_not_0(void) +{ + ng_pktsnip_t *pkt, *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(next); + + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, TEST_STRING8, sizeof(TEST_STRING8), + NG_NETTYPE_UNDEF))); + + TEST_ASSERT(pkt->next == next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING8, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT_NULL(next->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING4, next->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), next->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + + TEST_ASSERT(!ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__in_place(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_UNDEF); + ng_pktsnip_t *header; + + TEST_ASSERT_NOT_NULL((header = ng_pktbuf_add(pkt, pkt->data, 4, NG_NETTYPE_UNDEF))); + TEST_ASSERT(header->next == pkt); + TEST_ASSERT_EQUAL_STRING(TEST_STRING16, header->data); /* there is no 0 byte */ + TEST_ASSERT_EQUAL_INT(4, header->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, header->type); + TEST_ASSERT_EQUAL_INT(1, header->users); + TEST_ASSERT_EQUAL_STRING(TEST_STRING16 + 4, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 4, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); + ng_pktbuf_release(header); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +#if NG_PKTBUF_SIZE > 0 +static void test_pktbuf_add__memfull(void) +{ + TEST_ASSERT_NULL(ng_pktbuf_add(NULL, NULL, NG_PKTBUF_SIZE + 1, NG_NETTYPE_UNDEF)); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__memfull2(void) +{ + TEST_ASSERT_NULL(ng_pktbuf_add(NULL, NULL, NG_PKTBUF_SIZE - sizeof(ng_pktsnip_t), + NG_NETTYPE_UNDEF)); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_add__memfull3(void) { for (int i = 0; i < 9; i++) { - TEST_ASSERT_NOT_NULL(pktbuf_alloc((PKTBUF_SIZE / 10) + 4)); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF)); /* Why 4? Because: http://xkcd.com/221/, thats why ;-) */ } - TEST_ASSERT_NULL(pktbuf_alloc((PKTBUF_SIZE / 10) + 4)); -} - -static void test_pktbuf_alloc_success(void) -{ - void *data, *data_prev = NULL; - - for (int i = 0; i < 9; i++) { - data = pktbuf_alloc((PKTBUF_SIZE / 10) + 4); - - TEST_ASSERT(data_prev < data); - - data_prev = data; - } -} - -static void test_pktbuf_realloc_0(void) -{ - void *data = pktbuf_alloc(512); - - TEST_ASSERT_NULL(pktbuf_realloc(data, 0)); -} - -static void test_pktbuf_realloc_memfull(void) -{ - void *data = pktbuf_alloc(512); - - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE + 1)); -} - -static void test_pktbuf_realloc_memfull2(void) -{ - void *data = pktbuf_alloc(512); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(512)); - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE - 512)); -} - -static void test_pktbuf_realloc_memfull3(void) -{ - void *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - - data = pktbuf_alloc(512); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(73)); - - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE - 512)); -} - -static void test_pktbuf_realloc_smaller(void) -{ - void *data; - - data = pktbuf_alloc(512); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - - TEST_ASSERT(data == pktbuf_realloc(data, 128)); -} - -static void test_pktbuf_realloc_memenough(void) -{ - void *data; - - data = pktbuf_alloc(128); - - TEST_ASSERT_NOT_NULL(data); - - TEST_ASSERT(data == pktbuf_realloc(data, 200)); -} - -static void test_pktbuf_realloc_memenough2(void) -{ - void *data, *data2; - - data = pktbuf_alloc(128); - - TEST_ASSERT_NOT_NULL(data); - - data2 = pktbuf_alloc(128); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - - pktbuf_release(data2); - - TEST_ASSERT(data == pktbuf_realloc(data, 200)); -} - -static void test_pktbuf_realloc_nomemenough(void) -{ - void *data, *data2; - - data = pktbuf_alloc(128); - - TEST_ASSERT_NOT_NULL(data); - - data2 = pktbuf_alloc(128); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - - pktbuf_release(data2); - - TEST_ASSERT(data != pktbuf_realloc(data, 512)); -} - -static void test_pktbuf_realloc_unknown_ptr(void) -{ - char *data = "abcd", *new_data = pktbuf_realloc(data, 5); - - TEST_ASSERT_NOT_NULL(new_data); - TEST_ASSERT(data != new_data); - TEST_ASSERT_EQUAL_STRING(data, new_data); -} - -static void test_pktbuf_insert_size_0(void) -{ - TEST_ASSERT_NULL(pktbuf_insert("", 0)); -} - -static void test_pktbuf_insert_data_NULL(void) -{ - TEST_ASSERT_NULL(pktbuf_insert(NULL, 4)); -} - -static void test_pktbuf_insert_memfull(void) -{ - while (pktbuf_insert("abc", 4)); - - TEST_ASSERT_NULL(pktbuf_insert("abc", 4)); -} - -static void test_pktbuf_insert_success(void) -{ - char *data, *data_prev = NULL; - - for (int i = 0; i < 10; i++) { - data = (char *)pktbuf_insert("abc", 4); - - TEST_ASSERT(data_prev < data); - TEST_ASSERT_EQUAL_STRING("abc", data); - - data_prev = data; - } -} - -#ifdef DEVELHELP -static void test_pktbuf_copy_efault(void) -{ - char *data = (char *)pktbuf_insert("abcd", 5); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-EFAULT, pktbuf_copy(data, NULL, 3)); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_NULL(ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF)); } #endif -static void test_pktbuf_copy_data_len_too_long(void) +static void test_pktbuf_add__success(void) { - char *data = (char *)pktbuf_insert("ab", 3); + ng_pktsnip_t *pkt, *pkt_prev = NULL; - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(data, "cdef", 5)); - TEST_ASSERT_EQUAL_STRING("ab", data); + for (int i = 0; i < 9; i++) { + pkt = ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NOT_NULL(pkt->data); + TEST_ASSERT_EQUAL_INT((NG_PKTBUF_SIZE / 10) + 4, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); + + if (pkt_prev != NULL) { + TEST_ASSERT(pkt_prev < pkt); + TEST_ASSERT(pkt_prev->data < pkt->data); + } + + pkt_prev = pkt; + } } -static void test_pktbuf_copy_data_len_too_long2(void) -{ - char *data = (char *)pktbuf_insert("abcd", 5); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(data + 2, "efgh", 5)); - TEST_ASSERT_EQUAL_STRING("abcd", data); -} - -static void test_pktbuf_copy_data_len_0(void) -{ - char *data = (char *)pktbuf_insert("abcd", 5); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(0, pktbuf_copy(data, "ef", 0)); - TEST_ASSERT_EQUAL_STRING("abcd", data); -} - -static void test_pktbuf_copy_success(void) -{ - char *data = (char *)pktbuf_insert("abcd", 5); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); -} - -static void test_pktbuf_copy_success2(void) -{ - char *data = (char *)pktbuf_insert("abcdef", 7); - - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data + 3, "gh", 2)); - TEST_ASSERT_EQUAL_STRING("abcghf", data); -} - -static void test_pktbuf_hold_ptr_null(void) -{ - char *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_hold(NULL); - pktbuf_release(data); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_STRING("abcd", data); -} - -static void test_pktbuf_hold_wrong_ptr(void) -{ - char *data, wrong; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_hold(&wrong); - pktbuf_release(data); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_STRING("abcd", data); -} - -static void test_pktbuf_hold_success(void) -{ - char *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - pktbuf_hold(data); - pktbuf_release(data); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); -} - -static void test_pktbuf_hold_success2(void) -{ - char *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - pktbuf_hold(data + 4); - pktbuf_release(data + 4); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); -} - -static void test_pktbuf_release_ptr_null(void) -{ - char *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - pktbuf_release(NULL); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); -} - -static void test_pktbuf_release_wrong_ptr(void) -{ - char *data, wrong; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - pktbuf_release(&wrong); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); -} - -static void test_pktbuf_release_success(void) -{ - char *data; - - TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_hold(data); - pktbuf_hold(data); - pktbuf_release(data + 3); - pktbuf_release(data + 4); - pktbuf_release(data + 2); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); -} - -static void test_pktbuf_release_success2(void) -{ - char *data1, *data2, *data3; - - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_release(data2); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data1, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data1); - TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(data3, "nop", 4)); - TEST_ASSERT_EQUAL_STRING("nop", data3); -} - -static void test_pktbuf_release_success3(void) -{ - char *data1, *data2, *data3; - - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_release(data1); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data2, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data2); - TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(data3, "nop", 4)); - TEST_ASSERT_EQUAL_STRING("nop", data3); -} - -static void test_pktbuf_release_success4(void) -{ - char *data1, *data2, *data3; - - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); - - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - - pktbuf_release(data3); - - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data1, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data1); - TEST_ASSERT_EQUAL_INT(1, pktbuf_copy(data2, "", 1)); - TEST_ASSERT_EQUAL_STRING("", data2); -} - -static void test_pktbuf_insert_packed_struct(void) +static void test_pktbuf_add__packed_struct(void) { test_pktbuf_struct_t data = { 0x4d, 0xef43, 0xacdef574, 0x43644305695afde5, 34, -4469, 149699748, -46590430597 }; test_pktbuf_struct_t *data_cpy; - - data_cpy = (test_pktbuf_struct_t *)pktbuf_insert(&data, sizeof(test_pktbuf_struct_t)); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, &data, sizeof(test_pktbuf_struct_t), NG_NETTYPE_UNDEF); + data_cpy = (test_pktbuf_struct_t *)pkt->data; TEST_ASSERT_EQUAL_INT(data.u8, data_cpy->u8); TEST_ASSERT_EQUAL_INT(data.u16, data_cpy->u16); @@ -459,76 +272,379 @@ static void test_pktbuf_insert_packed_struct(void) TEST_ASSERT_EQUAL_INT(data.s64, data_cpy->s64); } -static void test_pktbuf_alloc_off_by_one1(void) +static void test_pktbuf_realloc_data__pkt_NULL(void) { - char *data1, *data2, *data3, *data4; + TEST_ASSERT_EQUAL_INT(ENOENT, ng_pktbuf_realloc_data(NULL, 0)); + TEST_ASSERT(ng_pktbuf_is_empty()); +} - data1 = (char *)pktbuf_insert("1234567890a", 12); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_alloc(44); - TEST_ASSERT_NOT_NULL(data2); - data4 = (char *)pktbuf_alloc(4); - TEST_ASSERT_NOT_NULL(data4); - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(12 + 44 + 4, pktbuf_bytes_allocated()); +static void test_pktbuf_realloc_data__pkt_wrong(void) +{ + ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; - pktbuf_release(data1); + TEST_ASSERT_EQUAL_INT(ENOENT, ng_pktbuf_realloc_data(&pkt, 0)); + TEST_ASSERT(ng_pktbuf_is_empty()); +} - TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(44 + 4, pktbuf_bytes_allocated()); +static void test_pktbuf_realloc_data__pkt_data_wrong(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + void *orig_data = pkt->data; + pkt->data = TEST_STRING8; - data3 = (char *)pktbuf_insert("bcdefghijklm", 13); - TEST_ASSERT_NOT_NULL(data3); - TEST_ASSERT(data1 != data3); + TEST_ASSERT_EQUAL_INT(ENOENT, ng_pktbuf_realloc_data(pkt, 0)); + pkt->data = orig_data; + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} - TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(44 + 4 + 13, pktbuf_bytes_allocated()); +static void test_pktbuf_realloc_data__pkt_users_gt_1(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + ng_pktbuf_hold(pkt, 1); + + TEST_ASSERT_EQUAL_INT(EINVAL, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8) - 1)); + ng_pktbuf_release(pkt); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_realloc_data__pkt_next_neq_NULL(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + pkt->next = pkt; + + TEST_ASSERT_EQUAL_INT(EINVAL, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8) - 1)); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_realloc_data__size_0(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + + TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, 0)); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +#if NG_PKTBUF_SIZE > 0 +static void test_pktbuf_realloc_data__memfull(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + + TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, NG_PKTBUF_SIZE + 1)); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_realloc_data__memfull2(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF)); + TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, NG_PKTBUF_SIZE - sizeof(TEST_STRING8))); +} + +static void test_pktbuf_realloc_data__memfull3(void) +{ + ng_pktsnip_t *pkt; + + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF)); + + pkt = ng_pktbuf_add(NULL, NULL, TEST_UINT8, NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF)); + TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, NG_PKTBUF_SIZE - TEST_UINT8)); +} + +/* dynamic malloc is a little more unpredictable ;-) */ +static void test_pktbuf_realloc_data__shrink(void) +{ + ng_pktsnip_t *pkt; + void *exp_data; + + pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + exp_data = pkt->data; + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_UNDEF)); + + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8))); + TEST_ASSERT(exp_data == pkt->data); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); +} + +static void test_pktbuf_realloc_data__memenough(void) +{ + ng_pktsnip_t *pkt; + void *exp_data; + + pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + exp_data = pkt->data; + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8))); + TEST_ASSERT(exp_data == pkt->data); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); +} + +static void test_pktbuf_realloc_data__nomemenough(void) +{ + ng_pktsnip_t *pkt1, *pkt2; + void *exp_data; + + pkt1 = ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + exp_data = pkt1->data; + + TEST_ASSERT_NOT_NULL(pkt1); + + pkt2 = ng_pktbuf_add(NULL, NULL, 1, NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt2); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_UNDEF)); + + ng_pktbuf_release(pkt2); + + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt1, 200)); + TEST_ASSERT(exp_data != pkt1->data); + TEST_ASSERT_NULL(pkt1->next); + TEST_ASSERT_EQUAL_INT(200, pkt1->size); + TEST_ASSERT_EQUAL_STRING(TEST_STRING8, pkt1->data); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); +} +#endif + +static void test_pktbuf_realloc_data__success(void) +{ + ng_pktsnip_t *pkt; + + pkt = ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt); + + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8))); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING8, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); +} + +static void test_pktbuf_realloc_data__success2(void) +{ + ng_pktsnip_t *pkt; + + pkt = ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(pkt); + + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING16))); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING8, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); +} + +static void test_pktbuf_realloc_data__further_down_the_line(void) +{ + ng_pktsnip_t *pkt, *header; + void *exp_data; + + pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + exp_data = pkt->data; + + TEST_ASSERT_NOT_NULL(pkt); + + header = ng_pktbuf_add(pkt, pkt->data, 4, NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL(header); + TEST_ASSERT(header->next == pkt); + TEST_ASSERT_EQUAL_INT(4, header->size); + TEST_ASSERT(((uint8_t *)pkt->data) == (((uint8_t *)header->data) + 4)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 4, pkt->size); + + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, 20)); + TEST_ASSERT(exp_data != pkt->data); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_EQUAL_STRING(TEST_STRING16 + 4, pkt->data); + TEST_ASSERT_EQUAL_INT(20, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); + ng_pktbuf_release(pkt); + ng_pktbuf_release(header); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_hold__pkt_null(void) +{ + ng_pktbuf_hold(NULL, 1); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_hold__pkt_external(void) +{ + ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; + + ng_pktbuf_hold(&pkt, 1); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_hold__success(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + + for (uint8_t i = 0; i < TEST_UINT8; i++) { + uint8_t prev_users = pkt->users; + ng_pktbuf_hold(pkt, 1); + TEST_ASSERT_EQUAL_INT(prev_users + 1, pkt->users); + } +} + +static void test_pktbuf_hold__success2(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + + ng_pktbuf_hold(pkt, TEST_UINT8); + + TEST_ASSERT_EQUAL_INT(TEST_UINT8 + 1, pkt->users); +} + +static void test_pktbuf_release__pkt_null(void) +{ + ng_pktbuf_release(NULL); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_release__pkt_external(void) +{ + ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; + + ng_pktbuf_release(&pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_release__success(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + + for (uint8_t i = 0; i < TEST_UINT8; i++) { + uint8_t prev_users = pkt->users; + ng_pktbuf_hold(pkt, 1); + TEST_ASSERT_EQUAL_INT(prev_users + 1, pkt->users); + } + + TEST_ASSERT(!ng_pktbuf_is_empty()); + + for (uint8_t i = 0; i < TEST_UINT8; i++) { + uint8_t prev_users = pkt->users; + ng_pktbuf_release(pkt); + TEST_ASSERT_EQUAL_INT(prev_users - 1, pkt->users); + } + + TEST_ASSERT(!ng_pktbuf_is_empty()); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_start_write__NULL(void) +{ + ng_pktbuf_start_write(NULL); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_start_write__pkt_users_1(void) +{ + ng_pktsnip_t *pkt_copy, *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_UNDEF); + + TEST_ASSERT_NOT_NULL((pkt_copy = ng_pktbuf_start_write(pkt))); + TEST_ASSERT(pkt == pkt_copy); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} + +static void test_pktbuf_start_write__pkt_users_2(void) +{ + ng_pktsnip_t *pkt_copy, *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_UNDEF); + + ng_pktbuf_hold(pkt, 1); + TEST_ASSERT_NOT_NULL((pkt_copy = ng_pktbuf_start_write(pkt))); + TEST_ASSERT(pkt != pkt_copy); + TEST_ASSERT(pkt->next == pkt_copy->next); + TEST_ASSERT_EQUAL_STRING(pkt->data, pkt_copy->data); + TEST_ASSERT_EQUAL_INT(pkt->size, pkt_copy->size); + TEST_ASSERT_EQUAL_INT(pkt->type, pkt_copy->type); + TEST_ASSERT_EQUAL_INT(pkt->users, pkt_copy->users); + TEST_ASSERT_EQUAL_INT(1, pkt->users); + + ng_pktbuf_release(pkt_copy); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); } Test *tests_pktbuf_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_pktbuf_alloc_0), - new_TestFixture(test_pktbuf_alloc_memfull), - new_TestFixture(test_pktbuf_alloc_success), - new_TestFixture(test_pktbuf_realloc_0), - new_TestFixture(test_pktbuf_realloc_memfull), - new_TestFixture(test_pktbuf_realloc_memfull2), - new_TestFixture(test_pktbuf_realloc_memfull3), - new_TestFixture(test_pktbuf_realloc_smaller), - new_TestFixture(test_pktbuf_realloc_memenough), - new_TestFixture(test_pktbuf_realloc_memenough2), - new_TestFixture(test_pktbuf_realloc_nomemenough), - new_TestFixture(test_pktbuf_realloc_unknown_ptr), - new_TestFixture(test_pktbuf_insert_size_0), - new_TestFixture(test_pktbuf_insert_data_NULL), - new_TestFixture(test_pktbuf_insert_memfull), - new_TestFixture(test_pktbuf_insert_success), -#ifdef DEVELHELP - new_TestFixture(test_pktbuf_copy_efault), + new_TestFixture(test_pktbuf_reset), + new_TestFixture(test_pktbuf_add__pkt_NULL__data_NULL__size_0), + new_TestFixture(test_pktbuf_add__pkt_NOT_NULL__data_NULL__size_0), + new_TestFixture(test_pktbuf_add__pkt_NULL__data_NOT_NULL__size_0), + new_TestFixture(test_pktbuf_add__pkt_NOT_NULL__data_NOT_NULL__size_0), + new_TestFixture(test_pktbuf_add__pkt_NULL__data_NULL__size_not_0), + new_TestFixture(test_pktbuf_add__pkt_NOT_NULL__data_NULL__size_not_0), + new_TestFixture(test_pktbuf_add__pkt_NOT_NULL__data_NOT_NULL__size_not_0), + new_TestFixture(test_pktbuf_add__in_place), +#if NG_PKTBUF_SIZE > 0 + new_TestFixture(test_pktbuf_add__memfull), + new_TestFixture(test_pktbuf_add__memfull2), + new_TestFixture(test_pktbuf_add__memfull3), #endif - new_TestFixture(test_pktbuf_copy_data_len_too_long), - new_TestFixture(test_pktbuf_copy_data_len_too_long2), - new_TestFixture(test_pktbuf_copy_data_len_0), - new_TestFixture(test_pktbuf_copy_success), - new_TestFixture(test_pktbuf_copy_success2), - new_TestFixture(test_pktbuf_hold_ptr_null), - new_TestFixture(test_pktbuf_hold_wrong_ptr), - new_TestFixture(test_pktbuf_hold_success), - new_TestFixture(test_pktbuf_hold_success2), - new_TestFixture(test_pktbuf_release_ptr_null), - new_TestFixture(test_pktbuf_release_wrong_ptr), - new_TestFixture(test_pktbuf_release_success), - new_TestFixture(test_pktbuf_release_success2), - new_TestFixture(test_pktbuf_release_success3), - new_TestFixture(test_pktbuf_release_success4), - new_TestFixture(test_pktbuf_insert_packed_struct), - new_TestFixture(test_pktbuf_alloc_off_by_one1), + new_TestFixture(test_pktbuf_add__success), + new_TestFixture(test_pktbuf_add__packed_struct), + new_TestFixture(test_pktbuf_realloc_data__pkt_NULL), + new_TestFixture(test_pktbuf_realloc_data__pkt_wrong), + new_TestFixture(test_pktbuf_realloc_data__pkt_data_wrong), + new_TestFixture(test_pktbuf_realloc_data__pkt_users_gt_1), + new_TestFixture(test_pktbuf_realloc_data__pkt_next_neq_NULL), + new_TestFixture(test_pktbuf_realloc_data__size_0), +#if NG_PKTBUF_SIZE > 0 + new_TestFixture(test_pktbuf_realloc_data__memfull), + new_TestFixture(test_pktbuf_realloc_data__memfull2), + new_TestFixture(test_pktbuf_realloc_data__memfull3), + new_TestFixture(test_pktbuf_realloc_data__nomemenough), + new_TestFixture(test_pktbuf_realloc_data__shrink), + new_TestFixture(test_pktbuf_realloc_data__memenough), +#endif + new_TestFixture(test_pktbuf_realloc_data__success), + new_TestFixture(test_pktbuf_realloc_data__success2), + new_TestFixture(test_pktbuf_realloc_data__further_down_the_line), + new_TestFixture(test_pktbuf_hold__pkt_null), + new_TestFixture(test_pktbuf_hold__pkt_external), + new_TestFixture(test_pktbuf_hold__success), + new_TestFixture(test_pktbuf_hold__success2), + new_TestFixture(test_pktbuf_release__pkt_null), + new_TestFixture(test_pktbuf_release__pkt_external), + new_TestFixture(test_pktbuf_release__success), + new_TestFixture(test_pktbuf_start_write__NULL), + new_TestFixture(test_pktbuf_start_write__pkt_users_1), + new_TestFixture(test_pktbuf_start_write__pkt_users_2), }; - EMB_UNIT_TESTCALLER(pktbuf_tests, NULL, tear_down, fixtures); + EMB_UNIT_TESTCALLER(ng_pktbuf_tests, NULL, tear_down, fixtures); - return (Test *)&pktbuf_tests; + return (Test *)&ng_pktbuf_tests; } void tests_pktbuf(void)