diff --git a/Makefile.dep b/Makefile.dep index 6c188b04053d6a72b259a0795930d73ef6a4e72b..c0241ca9cda6b000c93906813d53865187151105 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -218,6 +218,16 @@ ifneq (,$(filter ng_pktdump,$(USEMODULE))) USEMODULE += od endif +ifneq (,$(filter ng_pktbuf, $(USEMODULE))) + ifeq (,$(filter ng_pktbuf_%, $(USEMODULE))) + USEMODULE += ng_pktbuf_static + endif +endif + +ifneq (,$(filter ng_pktbuf_%, $(USEMODULE))) + USEMODULE += ng_pktbuf # make MODULE_NG_PKTBUF macro available for all implementations +endif + ifneq (,$(filter ng_slip,$(USEMODULE))) USEMODULE += ng_netbase endif diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index f76ef309d7906428765f9abfcb1e535f631e80e8..2b1d2700fb6eef58c7c399dce96120f57289d24e 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -7,6 +7,7 @@ PSEUDOMODULES += ng_ipv6_router PSEUDOMODULES += ng_ipv6_router_default PSEUDOMODULES += pktqueue PSEUDOMODULES += ng_netbase +PSEUDOMODULES += ng_pktbuf PSEUDOMODULES += newlib PSEUDOMODULES += ng_sixlowpan_default PSEUDOMODULES += log diff --git a/sys/Makefile b/sys/Makefile index 53021d44e3e519726ebc5db22fd13d41006efba9..d4db3fb42554c4c9b9c21edcf7ea4c57d36cdce5 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -113,8 +113,8 @@ endif ifneq (,$(filter cipher_modes,$(USEMODULE))) DIRS += crypto/modes endif -ifneq (,$(filter ng_pktbuf,$(USEMODULE))) - DIRS += net/crosslayer/ng_pktbuf +ifneq (,$(filter ng_pktbuf_static,$(USEMODULE))) + DIRS += net/crosslayer/ng_pktbuf_static endif ifneq (,$(filter ng_zep,$(USEMODULE))) DIRS += net/application_layer/ng_zep diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 10e72f19cd2edc2f6aeae1b5f1b9b3d5446e2509..91e94152e32581ea50df32d082b792ce14ce83e2 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -99,6 +99,10 @@ #include "l2_ping.h" #endif +#ifdef MODULE_NG_PKTBUF +#include "net/ng_pktbuf.h" +#endif + #ifdef MODULE_NG_PKTDUMP #include "net/ng_pktdump.h" #endif @@ -305,6 +309,10 @@ void auto_init(void) DEBUG("Auto init transport layer module: [tcp].\n"); tcp_init_transport_layer(); #endif +#ifdef MODULE_NG_PKTBUF + DEBUG("Auto init ng_pktbuf module\n"); + ng_pktbuf_init(); +#endif #ifdef MODULE_NG_PKTDUMP DEBUG("Auto init ng_pktdump module.\n"); ng_pktdump_init(); diff --git a/sys/include/net/ng_pktbuf.h b/sys/include/net/ng_pktbuf.h index f408c02151c21f83c2ad18760aa3d345c8e5e207..020bcf6ea07fe017c5fd2689cfcd2e9d32a2aff2 100644 --- a/sys/include/net/ng_pktbuf.h +++ b/sys/include/net/ng_pktbuf.h @@ -56,34 +56,37 @@ extern "C" { #define NG_PKTBUF_SIZE (6144) #endif /* NG_PKTBUF_SIZE */ +/** + * @brief Initializes packet buffer module. + */ +void ng_pktbuf_init(void); + /** * @brief Adds a new ng_pktsnip_t and its packet to the packet buffer. * - * @details This function is very powerful and reflects the unique characterics - * of ng_pktsnip_t of being reversed for either the sending or - * receiving context. Because of this the assumtion of the transmission - * direction, the state of the packet buffer and the values for the - * members of the resulting ng_pktsnip_t can be very different after - * execution of this function depending on what parameters you use: - * - * * The return value of this function is a @ref ng_pktsnip_t struct referred - * to as `result` - * * for most cases the build-up of `result` will be pretty straight forward: Its - * members will be exactly as the given parameters (ng_pktsnip_t::next of - * result will be set to @p pkt). If @p pkt is not NULL it and in turn `result` - * are assumed to be in sending direction. For packet creation (@p pkt == NULL) - * no assumtions about direction of `result` will be made (since its - * ng_pktsnip::next will be set to NULL). - * * if @p pkt != NULL, @p data = `pkt->data`, @p size < `pkt->size` receiving - * direction is assumed and the following values will be set: - * * ng_pktsnip_t::next of `result` = `pkt->next` - * * ng_pktsnip_t::data of `result` = @p data - * * ng_pktsnip_t::size of `result` = @p size - * * ng_pktsnip_t::next of @p pkt = `result` - * * ng_pktsnip_t::data of @p pkt = @p data + @p size - * * ng_pktsnip_t::size of @p pkt = old size value - @p size - * - * graphically this can be represented as follows: + * @warning **Do not** change the fields of the ng_pktsnip_t created by this + * function externally. This will most likely create memory leaks or + * not allowed memory access. + * + * @param[in] next Next ng_pktsnip_t in the packet. Leave NULL if you + * want to create a new packet. + * @param[in] data Data of the new ng_pktsnip_t. If @p data is NULL no data + * will be inserted into `result`. + * @param[in] size Length of @p data. May not be 0. + * @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. + * @return NULL, if @p size == 0. + */ +ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type); + +/** + * @brief Marks the first @p size bytes in a received packet with a new + * packet snip that is appended to the packet. + * + * Graphically this can be represented as follows: * @code * Before After * ====== ===== @@ -95,36 +98,23 @@ extern "C" { * \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ * @endcode * - * @note **Do not** change the ng_pktsnip_t::data and ng_pktsnip_t::size - * of a ng_pktsnip_t created by this function externally, except if - * they both are null or data is not from inside the packet buffer. - * This will most likely create memory leaks. + * @pre @p pkt != NULL && @p size != 0 * - * @param[in,out] pkt The packet you want to add a ng_pktsnip_t to. Leave - * NULL if you want to create a new packet. Members may - * change values; see above. - * @param[in] data Data of the new ng_pktsnip_t. If @p data is NULL no data - * will be inserted into `result`. If @p data is already - * in the packet buffer (e.g. a payload of an already - * allocated packet) it will not be duplicated. - * @param[in] size Length of @p data. If @p size is 0 no data will be inserted - * into the the packet buffer and ng_pktsnip_t::data will be - * set to @p data. - * @param[in] type Protocol type of the ng_pktsnip_t. + * @param[in] pkt A received packet. + * @param[in] size The size of the new packet snip. + * @param[in] type The type of the new packet snip. * - * @return Pointer to the packet part that represents the new ng_pktsnip_t. + * @return The new packet snip in @p pkt on success. + * @return NULL, if pkt == NULL or size == 0 or size > pkt->size or pkt->data == NULL. * @return NULL, if no space is left in the packet buffer. - * @return NULL, if @p pkt != NULL, @p data = `pkt->data`, - * and @p size > `pkt->data`. */ -ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *pkt, void *data, size_t size, - ng_nettype_t type); +ng_pktsnip_t *ng_pktbuf_mark(ng_pktsnip_t *pkt, 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 + * @pre ng_pktsnip_t::data of @p pkt is in the 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 @@ -135,8 +125,6 @@ ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *pkt, void *data, size_t size, * @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); @@ -182,7 +170,7 @@ ng_pktsnip_t *ng_pktbuf_start_write(ng_pktsnip_t *pkt); * @return The new reference to @p pkt. */ static inline ng_pktsnip_t *ng_pktbuf_remove_snip(ng_pktsnip_t *pkt, - ng_pktsnip_t *snip) + ng_pktsnip_t *snip) { LL_DELETE(pkt, snip); snip->next = NULL; @@ -213,9 +201,12 @@ void ng_pktbuf_stats(void); bool ng_pktbuf_is_empty(void); /** - * @brief Resets the whole packet buffer + * @brief Checks if the implenation's internal invariants still uphold + * + * @return true, the packet buffer is sane. + * @return false, the packet buffer is insane. */ -void ng_pktbuf_reset(void); +bool ng_pktbuf_is_sane(void); #endif #ifdef __cplusplus diff --git a/sys/net/application_layer/ng_zep/ng_zep.c b/sys/net/application_layer/ng_zep/ng_zep.c index 9c34810a0c87b64f89b66c5bcbbb9b9d798f29b0..9c8b0c9b95a8ba451820290c1c70dbf23ebd2056 100644 --- a/sys/net/application_layer/ng_zep/ng_zep.c +++ b/sys/net/application_layer/ng_zep/ng_zep.c @@ -724,7 +724,7 @@ static ng_pktsnip_t *_create_received(ng_zep_t *dev, ng_pktsnip_t *pkt, return NULL; } - payload = ng_pktbuf_add(pkt, pkt->data, pkt->size - 2, dev->proto); + payload = ng_pktbuf_mark(pkt, pkt->size - 2, dev->proto); if (payload == NULL) { return NULL; @@ -738,7 +738,7 @@ static ng_pktsnip_t *_create_received(ng_zep_t *dev, ng_pktsnip_t *pkt, return NULL; } - mhr = ng_pktbuf_add(pkt, pkt->data, mhr_len, NG_NETTYPE_UNDEF); + mhr = ng_pktbuf_mark(pkt, mhr_len, NG_NETTYPE_UNDEF); /* TODO: send ACK */ @@ -772,7 +772,7 @@ static ng_pktsnip_t *_recv_v1(ng_zep_t *dev, ng_pktsnip_t *pkt) return NULL; } - zep = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_zep_v1_hdr_t), NG_NETTYPE_UNDEF); + zep = ng_pktbuf_mark(pkt, sizeof(ng_zep_v1_hdr_t), NG_NETTYPE_UNDEF); if (zep == NULL) { return NULL; @@ -803,7 +803,7 @@ static ng_pktsnip_t *_recv_v2(ng_zep_t *dev, ng_pktsnip_t *pkt) return NULL; } - zep = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_zep_v2_data_hdr_t), NG_NETTYPE_UNDEF); + zep = ng_pktbuf_mark(pkt, sizeof(ng_zep_v2_data_hdr_t), NG_NETTYPE_UNDEF); if (zep == NULL) { return NULL; diff --git a/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c b/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c deleted file mode 100644 index e25689c0287a14eb4e5a2a9b9a29a40d797959db..0000000000000000000000000000000000000000 --- a/sys/net/crosslayer/ng_pktbuf/_pktbuf_dynamic.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2015 Martin Lenders <mlenders@inf.fu-berlin.de> - * - * 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 <mlenders@inf.fu-berlin.de> - */ - -#include <stdbool.h> -#include <stdlib.h> - -#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_value = 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_value = realloc(entry->range_start, size); - - if (new_value == NULL) { - return NULL; - } - - entry->range_start = new_value; - entry->range_len = size; - } - else { - size_t range_len = entry->range_len; - - if (node != NULL) { - range_len -= (node->ptr - entry->range_start); - } - - new_value = malloc(size); - - if (new_value == NULL) { - return NULL; - } - - entry = _create_table_entry(new_value, size); - - if (entry == NULL) { - free(new_value); - - return NULL; - } - - memcpy(new_value, ptr, (size < range_len) ? size : range_len); - _pktbuf_internal_free(ptr); - } - - return new_value; - /* 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 deleted file mode 100644 index ae29ca1880859df1bad8ac0f6ec70e5d54eaf22f..0000000000000000000000000000000000000000 --- a/sys/net/crosslayer/ng_pktbuf/_pktbuf_internal.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2015 Martin Lenders <mlenders@inf.fu-berlin.de> - * - * 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 <mlenders@inf.fu-berlin.de> - */ -#ifndef XPKTBUF_INTERNAL_H_ -#define XPKTBUF_INTERNAL_H_ - -#include <stdbool.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Internal alloc on packet buffer - * - * @internal - * - * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html"> - * malloc() - * </a> - */ -void *_pktbuf_internal_alloc(size_t size); - -/** - * @brief Internal realloc on static packet buffer - * - * @internal - * - * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html"> - * realloc() - * </a> - */ -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 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html"> - * free() - * </a> 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 deleted file mode 100644 index db31eb6b71288df6de0f7dc4ec7021fba47be7d6..0000000000000000000000000000000000000000 --- a/sys/net/crosslayer/ng_pktbuf/_pktbuf_static.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2015 Martin Lenders <mlenders@inf.fu-berlin.de> - * - * 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 <mlenders@inf.fu-berlin.de> - */ - -#include <inttypes.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include "od.h" -#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 aligns @p size to the next word alignment. - */ -static inline size_t _al_sz(size_t size) -{ - if (size % _PKTBUF_ALIGN_BYTES) { - return size + (_PKTBUF_ALIGN_BYTES - (size % _PKTBUF_ALIGN_BYTES)); - } - else { - return size; - } -} - -/** - * @brief aligned size with metadata - */ -static inline size_t __al_total_sz(_used_t *node) -{ - return _al_sz(__total_sz(node)); -} - -/** - * @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; -} - -/** - * @brief Allocate chunk of @p size in _buf - */ -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) /* while not last chunk allocation */ - /* and if space between current and next allocation is not big enough */ - && ((_start_idx(node->next) - _end_idx(node)) < _al_sz(_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) -{ - _used_t *ptr = _head(); - - printf("== Static packet buffer ==\n"); - printf("--- Maximum number of reserved bytes: %u ---\n", _pktbuf_max_bytes); - while (ptr) { - printf("**** %p: next: %p, size: %" PRIu16 ", pkts: %" PRIu8 " ****\n", - (void *)ptr, (void *)ptr->next, ptr->size, ptr->pkts); - od_hex_dump(_data(ptr), ptr->size, OD_WIDTH_DEFAULT); - puts(""); - ptr = ptr->next; - } -} -#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 deleted file mode 100644 index a67f954f75d9e97ed94c2f77211a23f4978fe3bf..0000000000000000000000000000000000000000 --- a/sys/net/crosslayer/ng_pktbuf/ng_pktbuf.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de> - * - * 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 <mlenders@inf.fu-berlin.de> - */ - -#include <errno.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include "clist.h" -#include "mutex.h" -#include "utlist.h" -#include "net/ng_pktbuf.h" -#include "net/ng_nettype.h" -#include "net/ng_pkt.h" - -#include "_pktbuf_internal.h" - -#define ENABLE_DEBUG (0) -#include "debug.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)) { - DEBUG("pktbuf: (pkt = %p) not in packet buffer\n", (void *)pkt); - return ENOENT; - } - - if (pkt->users > 1 || pkt->next != NULL) { - DEBUG("pktbuf: more than one user (%u) or pkt->next != NULL (%p)\n", - pkt->users, (void *)pkt->next); - return EINVAL; - } - - mutex_lock(&_pktbuf_mutex); - - new = _pktbuf_internal_realloc(pkt->data, size); - - mutex_unlock(&_pktbuf_mutex); - - if (new == NULL) { - DEBUG("pktbuf: no buffer space for realloc left\n"); - return ENOMEM; - } - - pkt->data = new; - pkt->size = size; - - return 0; -} - -ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *pkt, void *data, size_t size, - ng_nettype_t type) -{ - ng_pktsnip_t *new_pktsnip; - - mutex_lock(&_pktbuf_mutex); - - new_pktsnip = _pktbuf_add_unsafe(pkt, data, size, type); - - mutex_unlock(&_pktbuf_mutex); - - return new_pktsnip; -} - -void ng_pktbuf_hold(ng_pktsnip_t *pkt, unsigned int num) -{ - if ((pkt == NULL) || (num == 0)) { - return; - } - - mutex_lock(&_pktbuf_mutex); - - while (pkt != NULL) { - DEBUG("pktbuf: hold (pkt = %p) %u times\n", (void *)pkt, num); - pkt->users += num; - pkt = pkt->next; - } - - mutex_unlock(&_pktbuf_mutex); -} - -void ng_pktbuf_release(ng_pktsnip_t *pkt) -{ - if (pkt == NULL) { - return; - } - - mutex_lock(&_pktbuf_mutex); - - while (pkt != NULL) { - if (pkt->users > 0) { /* Don't accidentally overshoot */ - DEBUG("pktbuf: release (pkt = %p)\n", (void *)pkt); - pkt->users--; - } - - if (pkt->users == 0) { - if (_pktbuf_internal_contains(pkt->data)) { - DEBUG("pktbuf: free pkt->data = %p\n", pkt->data); - _pktbuf_internal_free(pkt->data); - } - - if (_pktbuf_internal_contains(pkt)) { - DEBUG("pktbuf: free pkt = %p\n", (void *)pkt); - _pktbuf_internal_free(pkt); - } - } - - pkt = pkt->next; - } - - 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); - - DEBUG("pktbuf: pkt->users = %u => copy-on-write\n", pkt->users); - res = _pktbuf_duplicate(pkt); - DEBUG("pktbuf: copy-on-write result: (pkt = %p) copied to (res = %p)\n", - (void *)pkt, (void *)res); - - pkt->users--; - - 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)); - DEBUG("pktbuf: allocated (pkt = %p) ", (void *)pkt); - - if (pkt == NULL) { - DEBUG("=> failed\n"); - return NULL; - } - - DEBUG("of size %u\n", (unsigned)sizeof(ng_pktsnip_t)); - - pkt->data = _pktbuf_internal_alloc(size); - DEBUG("pktbuf: allocated (pkt->data = %p) ", pkt->data); - - if (pkt->data == NULL) { - _pktbuf_internal_free(pkt); - DEBUG("=> failed (freeing %p)\n", (void *)pkt); - - return NULL; - } - - DEBUG("of size %u\n", (unsigned)size); - pkt->next = NULL; - pkt->size = size; - pkt->users = 1; - - return pkt; -} - -static ng_pktsnip_t *_pktbuf_add_unsafe(ng_pktsnip_t *pkt, void *data, - size_t size, ng_nettype_t type) -{ - ng_pktsnip_t *new_pktsnip; - - if (pkt == NULL || pkt->data != data) { - new_pktsnip = (ng_pktsnip_t *)_pktbuf_internal_alloc(sizeof(ng_pktsnip_t)); - DEBUG("pktbuf: allocated (new_pktsnip = %p) ", (void *)new_pktsnip); - - if (new_pktsnip == NULL) { - DEBUG("=> failed\n"); - return NULL; - } - - DEBUG("of size %u\n", (unsigned)sizeof(ng_pktsnip_t)); - - if ((size != 0) && (!_pktbuf_internal_contains(data))) { - new_pktsnip->data = _pktbuf_internal_alloc(size); - DEBUG("pktbuf: allocated (new_pktsnip->data = %p) ", new_pktsnip->data); - - if (new_pktsnip->data == NULL) { - _pktbuf_internal_free(new_pktsnip); - DEBUG("=> failed (freeing %p)\n", (void *)pkt); - - return NULL; - } - - DEBUG("of size %u\n", (unsigned)size); - - if (data != NULL) { - DEBUG("pktbuf: copying %u byte from %p to %p\n", (unsigned)size, - data, new_pktsnip->data); - memcpy(new_pktsnip->data, data, size); - } - } - else { - if (_pktbuf_internal_contains(data)) { - DEBUG("pktbuf: Adding chunk to %p ", new_pktsnip->data); - - if (!_pktbuf_internal_add_pkt(new_pktsnip->data)) { - _pktbuf_internal_free(new_pktsnip); - DEBUG("failed (freeing %p)\n", (void *)pkt); - - return NULL; - } - - DEBUG("successful\n"); - } - - new_pktsnip->data = data; - DEBUG("pktbuf: set new_pktsnip->data = %p\n", new_pktsnip->data); - } - - new_pktsnip->next = NULL; - LL_PREPEND(pkt, new_pktsnip); - DEBUG("pktbuf: prepended new_pktsnip to pkt\n"); - } - else { - if (size > pkt->size) { - DEBUG("pktbuf: new size (%u) out of pkt's boundaries (pkt->size = %u)", - (unsigned)size, (unsigned)pkt->size); - return NULL; - } - - if (size == pkt->size) { - DEBUG("pktbuf: size (%u) == pkt->size (%u) => just set new packet " - "type and return\n", (unsigned)size, (unsigned)pkt->size); - pkt->type = type; - return pkt; - } - - new_pktsnip = (ng_pktsnip_t *)_pktbuf_internal_alloc(sizeof(ng_pktsnip_t)); - DEBUG("pktbuf: allocated (new_pktsnip = %p) ", (void *)new_pktsnip); - - if (new_pktsnip == NULL) { - DEBUG("=> failed\n"); - return NULL; - } - - DEBUG("of size %u\n", (unsigned)sizeof(ng_pktsnip_t)); - DEBUG("pktbuf: Adding chunk to %p ", pkt->data); - - if (!_pktbuf_internal_add_pkt(pkt->data)) { - DEBUG("failed (freeing %p)\n", (void *)new_pktsnip); - _pktbuf_internal_free(new_pktsnip); - - return NULL; - } - - DEBUG("successful\n"); - new_pktsnip->next = pkt->next; - new_pktsnip->data = data; - DEBUG("pktbuf: set new_pktsnip->data = %p\n", new_pktsnip->data); - - DEBUG("pktbuf: add new_pktsnip (%p) to pkt (%p) after head\n", - (void *)new_pktsnip, (void *)pkt); - pkt->next = new_pktsnip; - pkt->size -= size; - DEBUG("pktbuf: resize pkt->size to %u\n", (unsigned)pkt->size); - pkt->data = (void *)(((uint8_t *)pkt->data) + size); - DEBUG("pktbuf: move pkt->data to %p\n", pkt->data); - } - - new_pktsnip->size = size; - new_pktsnip->type = type; - new_pktsnip->users = 1; - DEBUG("pktbuf: summary of new snip %p: next = %p, data = %p, size = %u, " - "type = %d, users: %u\n", (void *)new_pktsnip, (void *)new_pktsnip->next, - new_pktsnip->data, (unsigned)new_pktsnip->size, new_pktsnip->type, - new_pktsnip->users); - - return new_pktsnip; -} - -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; - } - - DEBUG("pktbuf: copying %u byte from %p to %p\n", (unsigned)pkt->size, - pkt->data, res->data); - memcpy(res->data, pkt->data, pkt->size); - res->type = pkt->type; - res->next = pkt->next; - DEBUG("pktbuf: set res->next to %p", (void *)pkt->next); - - 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/ng_pktbuf/Makefile b/sys/net/crosslayer/ng_pktbuf_static/Makefile similarity index 100% rename from sys/net/crosslayer/ng_pktbuf/Makefile rename to sys/net/crosslayer/ng_pktbuf_static/Makefile diff --git a/sys/net/crosslayer/ng_pktbuf_static/ng_pktbuf_static.c b/sys/net/crosslayer/ng_pktbuf_static/ng_pktbuf_static.c new file mode 100644 index 0000000000000000000000000000000000000000..6c520b622bbd17d6a67ab7f1227fe4c2b520db31 --- /dev/null +++ b/sys/net/crosslayer/ng_pktbuf_static/ng_pktbuf_static.c @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * 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 <mlenders@inf.fu-berlin.de> + */ + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> + +#include "mutex.h" +#include "od.h" +#include "utlist.h" +#include "net/ng_pktbuf.h" +#include "net/ng_nettype.h" +#include "net/ng_pkt.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define _ALIGNMENT_MASK (sizeof(void *) - 1) + +typedef struct _unused { + struct _unused *next; + unsigned int size; +} _unused_t; + +static mutex_t _mutex = MUTEX_INIT; +static uint8_t _pktbuf[NG_PKTBUF_SIZE]; +static _unused_t *_first_unused; + +/* internal ng_pktbuf functions */ +static ng_pktsnip_t *_create_snip(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type); +static void *_pktbuf_alloc(size_t size); +static void _pktbuf_free(void *data, size_t size); + +static inline bool _pktbuf_contains(void *ptr) +{ + return (&_pktbuf[0] <= (uint8_t *)ptr) && + ((uint8_t *)ptr <= &_pktbuf[NG_PKTBUF_SIZE - 1]); +} + +/* fits size to byte alignment */ +static inline size_t _align(size_t size) +{ + return ((size + _ALIGNMENT_MASK) & ~(_ALIGNMENT_MASK)); +} + + +void ng_pktbuf_init(void) +{ + mutex_lock(&_mutex); + _first_unused = (_unused_t *)_pktbuf; + _first_unused->next = NULL; + _first_unused->size = sizeof(_pktbuf); + mutex_unlock(&_mutex); +} + +ng_pktsnip_t *ng_pktbuf_add(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type) +{ + ng_pktsnip_t *pkt; + if ((size == 0) || (size > NG_PKTBUF_SIZE)) { + DEBUG("pktbuf: size (%u) == 0 || size == NG_PKTBUF_SIZE (%u)\n", + (unsigned)size, NG_PKTBUF_SIZE); + return NULL; + } + mutex_lock(&_mutex); + pkt = _create_snip(next, data, size, type); + mutex_unlock(&_mutex); + return pkt; +} + +ng_pktsnip_t *ng_pktbuf_mark(ng_pktsnip_t *pkt, size_t size, ng_nettype_t type) +{ + ng_pktsnip_t *marked_snip; + /* size required for chunk */ + size_t required_new_size = (size < sizeof(_unused_t)) ? + _align(sizeof(_unused_t)) : _align(size); + mutex_lock(&_mutex); + if ((size == 0) || (pkt == NULL) || (size > pkt->size) || (pkt->data == NULL)) { + DEBUG("pktbuf: size == 0 (was %u) or pkt == NULL (was %p) or " + "size > pkt->size (was %u) or pkt->data == NULL (was %p)\n", + (unsigned)size, (void *)pkt, (unsigned)pkt->size, pkt->data); + mutex_unlock(&_mutex); + return NULL; + } + else if (size == pkt->size) { + pkt->type = type; + mutex_unlock(&_mutex); + return pkt; + } + marked_snip = _pktbuf_alloc(sizeof(ng_pktsnip_t)); + if (marked_snip == NULL) { + DEBUG("pktbuf: could not reallocate marked section.\n"); + mutex_unlock(&_mutex); + return NULL; + } + if ((size < required_new_size)) { /* would not fit unused marker => move data around */ + void *new_data_marked, *new_data_rest; + new_data_marked = _pktbuf_alloc(size); + if (new_data_marked == NULL) { + DEBUG("pktbuf: could not reallocate marked section.\n"); + _pktbuf_free(marked_snip, sizeof(ng_pktsnip_t)); + mutex_unlock(&_mutex); + return NULL; + } + new_data_rest = _pktbuf_alloc(pkt->size - size); + if (new_data_rest == NULL) { + DEBUG("pktbuf: could not reallocate remaining section.\n"); + _pktbuf_free(marked_snip, sizeof(ng_pktsnip_t)); + _pktbuf_free(new_data_marked, size); + mutex_unlock(&_mutex); + return NULL; + } + memcpy(new_data_marked, pkt->data, size); + memcpy(new_data_rest, ((uint8_t *)pkt->data) + size, pkt->size - size); + _pktbuf_free(pkt->data, pkt->size); + marked_snip->data = new_data_marked; + pkt->data = new_data_rest; + } + else { + marked_snip->data = pkt->data; + pkt->data = ((uint8_t *)pkt->data) + size; + } + pkt->size -= size; + marked_snip->next = pkt->next; + marked_snip->size = size; + marked_snip->type = type; + marked_snip->users = 1; + pkt->next = marked_snip; + mutex_unlock(&_mutex); + return marked_snip; +} + +int ng_pktbuf_realloc_data(ng_pktsnip_t *pkt, size_t size) +{ + size_t aligned_size = (size < sizeof(_unused_t)) ? + _align(sizeof(_unused_t)) : _align(size); + mutex_lock(&_mutex); + assert((pkt != NULL) && (pkt->data != NULL) && _pktbuf_contains(pkt->data)); + if (size == 0) { + DEBUG("pktbuf: size == 0\n"); + mutex_unlock(&_mutex); + return ENOMEM; + } + if (size == pkt->size) { + mutex_unlock(&_mutex); + return 0; + } + if ((size > pkt->size) || /* new size does not fit */ + ((pkt->size - aligned_size) < sizeof(_unused_t))) { /* resulting hole would not fit marker */ + void *new_data = _pktbuf_alloc(size); + if (new_data == NULL) { + DEBUG("pktbuf: error allocating new data section\n"); + mutex_unlock(&_mutex); + return ENOMEM; + } + memcpy(new_data, pkt->data, (pkt->size < size) ? pkt->size : size); + _pktbuf_free(pkt->data, pkt->size); + pkt->data = new_data; + } + else { + _pktbuf_free(((uint8_t *)pkt->data) + aligned_size, + pkt->size - aligned_size); + } + pkt->size = size; + mutex_unlock(&_mutex); + return 0; +} + +void ng_pktbuf_hold(ng_pktsnip_t *pkt, unsigned int num) +{ + mutex_lock(&_mutex); + while (pkt) { + pkt->users += num; + pkt = pkt->next; + } + mutex_unlock(&_mutex); +} + +void ng_pktbuf_release(ng_pktsnip_t *pkt) +{ + mutex_lock(&_mutex); + while (pkt) { + ng_pktsnip_t *tmp = pkt->next; + if (pkt->users == 1) { + pkt->users = 0; /* not necessary but to be on the safe side */ + _pktbuf_free(pkt->data, pkt->size); + _pktbuf_free(pkt, sizeof(ng_pktsnip_t)); + } + else { + pkt->users--; + } + pkt = tmp; + } + mutex_unlock(&_mutex); +} + +ng_pktsnip_t *ng_pktbuf_start_write(ng_pktsnip_t *pkt) +{ + mutex_lock(&_mutex); + if ((pkt == NULL) || (pkt->size == 0)) { + mutex_unlock(&_mutex); + return NULL; + } + if (pkt->users > 1) { + ng_pktsnip_t *new; + new = _create_snip(pkt->next, pkt->data, pkt->size, pkt->type); + if (new != NULL) { + pkt->users--; + } + mutex_unlock(&_mutex); + return new; + } + mutex_unlock(&_mutex); + return pkt; +} + +#ifdef DEVELHELP +#ifdef MODULE_OD +static inline void _print_chunk(void *chunk, size_t size, int num) +{ + printf("================ chunk %3d (size: %4u) ================\n", num, + (unsigned int)size); + od(chunk, NG_PKTBUF_SIZE, OD_WIDTH_DEFAULT, + OD_FLAGS_ADDRESS_HEX | OD_FLAGS_BYTES_HEX | OD_FLAGS_LENGTH_1); +} + +static inline void _print_unused(_unused_t *ptr) +{ + printf("~ unused: %p (next: %p, size: %4u) ~\n", (void *)ptr, + (void *)ptr->next, ptr->size); +} +#endif + +void ng_pktbuf_stats(void) +{ +#ifdef MODULE_OD + _unused_t *ptr = _first_unused; + uint8_t *chunk = &_pktbuf[0]; + int count = 0; + + printf("packet buffer: first byte: %p, last byte: %p (size: %u)\n", + (void *)&_pktbuf[0], (void *)&_pktbuf[NG_PKTBUF_SIZE], NG_PKTBUF_SIZE); + if (ptr == NULL) { /* packet buffer is completely full */ + _print_chunk(chunk, NG_PKTBUF_SIZE, count++); + } + + if (((void *)ptr) == ((void *)chunk)) { /* _first_unused is at the beginning */ + _print_unused(ptr); + chunk += ptr->size; + ptr = ptr->next; + } + + while (ptr) { + size_t size = ((uint8_t *)ptr) - chunk; + if ((size == 0) && (!_pktbuf_contains(ptr)) && + (!_pktbuf_contains(chunk)) && (size > NG_PKTBUF_SIZE)) { + puts("ERROR"); + return; + } + _print_chunk(chunk, size, count++); + chunk += (size + ptr->size); + ptr = ptr->next; + _print_unused(ptr); + } + + if (chunk <= &_pktbuf[NG_PKTBUF_SIZE - 1]) { + _print_chunk(chunk, &_pktbuf[NG_PKTBUF_SIZE] - chunk, count); + } +#else + DEBUG("pktbuf: needs od module\n"); +#endif +} +#endif + +#ifdef TEST_SUITES +bool ng_pktbuf_is_empty(void) +{ + return (_first_unused == (_unused_t *)_pktbuf) && + (_first_unused->size == sizeof(_pktbuf)); +} + +bool ng_pktbuf_is_sane(void) +{ + _unused_t *ptr = _first_unused; + + /* Invariants of this implementation: + * - the head of _unused_t list is _first_unused + * - if _unused_t list is empty the packet buffer is full and _first_unused is NULL + * - forall ptr_in _unused_t list: &_pktbuf[0] < ptr < &_pktbuf[NG_PKTBUF_SIZE] + * - forall ptr in _unused_t list: ptr->next == NULL || ptr < ptr->next + * - forall ptr in _unused_t list: (ptr->next != NULL && ptr->size <= (ptr->next - ptr)) || + * (ptr->next == NULL && ptr->size == (NG_PKTBUF_SIZE - (ptr - &_pktbuf[0]))) + */ + + while (ptr) { + if (&_pktbuf[0] >= (uint8_t *)ptr && (uint8_t *)ptr >= &_pktbuf[NG_PKTBUF_SIZE]) { + return false; + } + if ((ptr->next != NULL) && (ptr >= ptr->next)) { + return false; + } + if (((ptr->next == NULL) || (ptr->size > (size_t)((uint8_t *)(ptr->next) - (uint8_t *)ptr))) && + ((ptr->next != NULL) || (ptr->size != (size_t)(NG_PKTBUF_SIZE - ((uint8_t *)ptr - &_pktbuf[0]))))) { + return false; + } + ptr = ptr->next; + } + + return true; +} +#endif + +static ng_pktsnip_t *_create_snip(ng_pktsnip_t *next, void *data, size_t size, + ng_nettype_t type) +{ + ng_pktsnip_t *pkt = _pktbuf_alloc(sizeof(ng_pktsnip_t)); + void *_data; + if (pkt == NULL) { + DEBUG("pktbuf: error allocating new packet snip\n"); + return NULL; + } + _data = _pktbuf_alloc(size); + if (_data == NULL) { + DEBUG("pktbuf: error allocating data for new packet snip\n"); + _pktbuf_free(pkt, sizeof(ng_pktsnip_t)); + return NULL; + } + pkt->next = next; + pkt->size = size; + pkt->data = _data; + pkt->type = type; + pkt->users = 1; + if (data != NULL) { + memcpy(_data, data, size); + } + return pkt; +} + +static void *_pktbuf_alloc(size_t size) +{ + _unused_t *prev = NULL, *ptr = _first_unused; + size = (size < sizeof(_unused_t)) ? _align(sizeof(_unused_t)) : _align(size); + while (ptr && size > ptr->size) { + prev = ptr; + ptr = ptr->next; + } + if (ptr == NULL) { + DEBUG("pktbuf: no space left in packet buffer\n"); + return NULL; + } + if (sizeof(_unused_t) > (ptr->size - size)) { + if (prev == NULL) { /* ptr was _first_unused */ + _first_unused = ptr->next; + } + else { + prev->next = ptr->next; + } + } + else { + _unused_t *new = (_unused_t *)(((uint8_t *)ptr) + size); + if (prev == NULL) { /* ptr was _first_unused */ + _first_unused = new; + } + else { + prev->next = new; + } + new->next = ptr->next; + new->size = ptr->size - size; + } + return (void *)ptr; +} + +static inline bool _too_small_hole(_unused_t *a, _unused_t *b) +{ + return sizeof(_unused_t) > (size_t)(((uint8_t *)b) - (((uint8_t *)a) + a->size)); +} + +static inline _unused_t *_merge(_unused_t *a, _unused_t *b) +{ + a->next = b->next; + a->size = b->size + ((uint8_t *)b - (uint8_t *)a); + return a; +} + +static void _pktbuf_free(void *data, size_t size) +{ + _unused_t *new = (_unused_t *)data, *prev = NULL, *ptr = _first_unused; + if (!_pktbuf_contains(data)) { + return; + } + while (ptr && (((void *)ptr) < data)) { + prev = ptr; + ptr = ptr->next; + } + new->next = ptr; + new->size = (size < sizeof(_unused_t)) ? _align(sizeof(_unused_t)) : _align(size); + if (prev == NULL) { /* ptr was _first_unused or data before _first_unused */ + _first_unused = new; + } + else { + prev->next = new; + if (_too_small_hole(prev, new)) { + new = _merge(prev, new); + } + } + if (_too_small_hole(new, new->next)) { + _merge(new, new->next); + } +} + +/** @} */ diff --git a/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c b/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c index 1f746e0ad0f0ed47bb4f6192d0197ca179a316a0..f1b6ef95409de3d4b4031ff3de6d2d74c2b12a8a 100644 --- a/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c +++ b/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c @@ -54,7 +54,7 @@ bool ng_ipv6_ext_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, } } - ext_snip = ng_pktbuf_add(pkt, pkt->data, offset, NG_NETTYPE_IPV6); + ext_snip = ng_pktbuf_mark(pkt, offset, NG_NETTYPE_IPV6); if (ext_snip == NULL) { return false; diff --git a/sys/net/network_layer/ng_ipv6/ng_ipv6.c b/sys/net/network_layer/ng_ipv6/ng_ipv6.c index 91a4194eec5bd8468269633d0134f5d00818b3b2..a68b72873636148e80398478a4d37c4abf30d78c 100644 --- a/sys/net/network_layer/ng_ipv6/ng_ipv6.c +++ b/sys/net/network_layer/ng_ipv6/ng_ipv6.c @@ -629,8 +629,7 @@ static void _receive(ng_pktsnip_t *pkt) pkt = ipv6; /* reset pkt from temporary variable */ - ipv6 = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_ipv6_hdr_t), - NG_NETTYPE_IPV6); + ipv6 = ng_pktbuf_mark(pkt, sizeof(ng_ipv6_hdr_t), NG_NETTYPE_IPV6); if (ipv6 == NULL) { DEBUG("ipv6: error marking IPv6 header, dropping packet\n"); diff --git a/sys/net/network_layer/ng_sixlowpan/iphc/ng_sixlowpan_iphc.c b/sys/net/network_layer/ng_sixlowpan/iphc/ng_sixlowpan_iphc.c index 56d565479650420085872829f1492601e5386eac..fde313efe91540f1caca71ae881d04c689d4fbbd 100644 --- a/sys/net/network_layer/ng_sixlowpan/iphc/ng_sixlowpan_iphc.c +++ b/sys/net/network_layer/ng_sixlowpan/iphc/ng_sixlowpan_iphc.c @@ -369,7 +369,7 @@ bool ng_sixlowpan_iphc_decode(ng_pktsnip_t *pkt) /* TODO: add next header decoding */ /* remove 6LoWPAN dispatch */ - payload = ng_pktbuf_add(pkt, pkt->data, payload_offset, NG_NETTYPE_SIXLOWPAN); + payload = ng_pktbuf_mark(pkt, payload_offset, NG_NETTYPE_SIXLOWPAN); pkt = ng_pktbuf_remove_snip(pkt, payload); /* set IPv6 header payload length field to the length of whatever is left diff --git a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c index daa2fc05289ee0d8933660b4b126c43145f2a6de..d7ae9359bb0727d6daf60af72f48cf3931602f71 100644 --- a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c +++ b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c @@ -103,8 +103,7 @@ static void _receive(ng_pktsnip_t *pkt) } /* packet is uncompressed: just mark and remove the dispatch */ - sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t), - NG_NETTYPE_SIXLOWPAN); + sixlowpan = ng_pktbuf_mark(payload, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: can not mark 6LoWPAN dispatch\n"); diff --git a/sys/net/transport_layer/ng_udp/ng_udp.c b/sys/net/transport_layer/ng_udp/ng_udp.c index 4e3f0ce27dae968abeb123c12504100b5a229584..5910bf19c3bbc0cc97ffa2f83ca1a6c292b5af6d 100644 --- a/sys/net/transport_layer/ng_udp/ng_udp.c +++ b/sys/net/transport_layer/ng_udp/ng_udp.c @@ -107,7 +107,7 @@ static void _receive(ng_pktsnip_t *pkt) return; } pkt = udp; - udp = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_udp_hdr_t), NG_NETTYPE_UDP); + udp = ng_pktbuf_mark(pkt, sizeof(ng_udp_hdr_t), NG_NETTYPE_UDP); if (udp == NULL) { DEBUG("udp: error marking UDP header, dropping packet\n"); ng_pktbuf_release(pkt); diff --git a/tests/unittests/tests-ipv6_hdr/tests-ipv6_hdr.c b/tests/unittests/tests-ipv6_hdr/tests-ipv6_hdr.c index 0aea586e89caea4dd782b498af4525419edfc0f0..c4dd4821668fa776f25a503b8ae63ada41645699 100644 --- a/tests/unittests/tests-ipv6_hdr/tests-ipv6_hdr.c +++ b/tests/unittests/tests-ipv6_hdr/tests-ipv6_hdr.c @@ -304,6 +304,7 @@ static void test_ipv6_hdr_build__wrong_src_len(void) ng_ipv6_addr_t src = DEFAULT_TEST_SRC; ng_ipv6_addr_t dst = DEFAULT_TEST_DST; + ng_pktbuf_init(); TEST_ASSERT_NULL(ng_ipv6_hdr_build(NULL, (uint8_t *)&src, sizeof(ng_ipv6_addr_t) + TEST_UINT8, (uint8_t *)&dst, @@ -316,6 +317,7 @@ static void test_ipv6_hdr_build__wrong_dst_len(void) ng_ipv6_addr_t src = DEFAULT_TEST_SRC; ng_ipv6_addr_t dst = DEFAULT_TEST_DST; + ng_pktbuf_init(); TEST_ASSERT_NULL(ng_ipv6_hdr_build(NULL, (uint8_t *)&src, sizeof(ng_ipv6_addr_t), (uint8_t *)&dst, @@ -329,7 +331,7 @@ static void test_ipv6_hdr_build__src_NULL(void) ng_pktsnip_t *pkt; ng_ipv6_hdr_t *hdr; - TEST_ASSERT(ng_pktbuf_is_empty()); + ng_pktbuf_init(); TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, NULL, 0, (uint8_t *)&dst, sizeof(ng_ipv6_addr_t)))); hdr = pkt->data; @@ -341,7 +343,6 @@ static void test_ipv6_hdr_build__src_NULL(void) TEST_ASSERT_EQUAL_INT(0, hdr->hl); TEST_ASSERT(ng_ipv6_addr_equal(&dst, &hdr->dst)); TEST_ASSERT(!ng_pktbuf_is_empty()); - ng_pktbuf_reset(); } static void test_ipv6_hdr_build__dst_NULL(void) @@ -350,7 +351,7 @@ static void test_ipv6_hdr_build__dst_NULL(void) ng_pktsnip_t *pkt; ng_ipv6_hdr_t *hdr; - TEST_ASSERT(ng_pktbuf_is_empty()); + ng_pktbuf_init(); TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, (uint8_t *)&src, sizeof(ng_ipv6_addr_t), NULL, 0))); @@ -363,7 +364,6 @@ static void test_ipv6_hdr_build__dst_NULL(void) TEST_ASSERT_EQUAL_INT(0, hdr->hl); TEST_ASSERT(ng_ipv6_addr_equal(&src, &hdr->src)); TEST_ASSERT(!ng_pktbuf_is_empty()); - ng_pktbuf_reset(); } static void test_ipv6_hdr_build__complete(void) @@ -373,7 +373,7 @@ static void test_ipv6_hdr_build__complete(void) ng_pktsnip_t *pkt; ng_ipv6_hdr_t *hdr; - TEST_ASSERT(ng_pktbuf_is_empty()); + ng_pktbuf_init(); TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, (uint8_t *)&src, sizeof(ng_ipv6_addr_t), (uint8_t *)&dst, @@ -388,7 +388,6 @@ static void test_ipv6_hdr_build__complete(void) TEST_ASSERT(ng_ipv6_addr_equal(&src, &hdr->src)); TEST_ASSERT(ng_ipv6_addr_equal(&dst, &hdr->dst)); TEST_ASSERT(!ng_pktbuf_is_empty()); - ng_pktbuf_reset(); } Test *tests_ipv6_hdr_tests(void) diff --git a/tests/unittests/tests-pktbuf/Makefile.include b/tests/unittests/tests-pktbuf/Makefile.include index 5f8664dc17ac02d337f27667ca6fee5d1757ef13..e9c3712c960df2f9e46a7354f5c01375293207e9 100644 --- a/tests/unittests/tests-pktbuf/Makefile.include +++ b/tests/unittests/tests-pktbuf/Makefile.include @@ -1 +1 @@ -USEMODULE += ng_pktbuf +USEMODULE += ng_pktbuf_static diff --git a/tests/unittests/tests-pktbuf/tests-pktbuf.c b/tests/unittests/tests-pktbuf/tests-pktbuf.c index c54dfe897ba3a345b4f139b1b9d2ce8567f502c1..4abe42907aa68508a9bd18b1596c7faae7c76aee 100644 --- a/tests/unittests/tests-pktbuf/tests-pktbuf.c +++ b/tests/unittests/tests-pktbuf/tests-pktbuf.c @@ -32,96 +32,72 @@ typedef struct __attribute__((packed)) { int16_t s16; int32_t s32; int64_t s64; -} test_pktbuf_struct_t; +} +test_pktbuf_struct_t; -static void tear_down(void) +static void set_up(void) { - ng_pktbuf_reset(); + ng_pktbuf_init(); } -static void test_pktbuf_reset(void) +static void test_pktbuf_init(void) { TEST_ASSERT(ng_pktbuf_is_empty()); TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), - NG_NETTYPE_UNDEF)); + NG_NETTYPE_TEST)); TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), - NG_NETTYPE_UNDEF)); + NG_NETTYPE_TEST)); TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), - NG_NETTYPE_UNDEF)); + NG_NETTYPE_TEST)); + TEST_ASSERT(ng_pktbuf_is_sane()); TEST_ASSERT(!ng_pktbuf_is_empty()); - ng_pktbuf_reset(); + ng_pktbuf_init(); TEST_ASSERT(ng_pktbuf_is_empty()); } 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()); + TEST_ASSERT_NULL(ng_pktbuf_add(NULL, NULL, 0, NG_NETTYPE_TEST)); + 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); + ng_pktsnip_t *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_TEST); 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(ng_pktbuf_add(next, NULL, 0, NG_NETTYPE_TEST)); 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_EQUAL_INT(NG_NETTYPE_TEST, next->type); + TEST_ASSERT(ng_pktbuf_is_sane()); 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_NOT_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()); + TEST_ASSERT_NULL(ng_pktbuf_add(NULL, TEST_STRING8, 0, NG_NETTYPE_TEST)); + 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); + ng_pktsnip_t *next = ng_pktbuf_add(NULL, TEST_STRING4, sizeof(TEST_STRING4), + NG_NETTYPE_TEST); 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_NOT_NULL(pkt->data); - TEST_ASSERT_EQUAL_INT(0, pkt->size); - TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + TEST_ASSERT_NULL(ng_pktbuf_add(next, TEST_STRING8, 0, NG_NETTYPE_TEST)); 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_EQUAL_INT(NG_NETTYPE_TEST, next->type); + TEST_ASSERT(ng_pktbuf_is_sane()); TEST_ASSERT(!ng_pktbuf_is_empty()); } @@ -130,34 +106,35 @@ 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))); + NG_NETTYPE_TEST))); 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(NG_NETTYPE_TEST, pkt->type); TEST_ASSERT_EQUAL_INT(1, pkt->users); + TEST_ASSERT(ng_pktbuf_is_sane()); 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); + NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(next); - TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF))); + TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, NULL, sizeof(TEST_STRING8), NG_NETTYPE_TEST))); 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_EQUAL_INT(NG_NETTYPE_TEST, 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_EQUAL_INT(NG_NETTYPE_TEST, pkt->type); TEST_ASSERT(!ng_pktbuf_is_empty()); } @@ -165,84 +142,50 @@ static void test_pktbuf_add__pkt_NOT_NULL__data_NULL__size_not_0(void) 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); + NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(next); TEST_ASSERT_NOT_NULL((pkt = ng_pktbuf_add(next, TEST_STRING8, sizeof(TEST_STRING8), - NG_NETTYPE_UNDEF))); + NG_NETTYPE_TEST))); 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_EQUAL_INT(NG_NETTYPE_TEST, 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_EQUAL_INT(NG_NETTYPE_TEST, pkt->type); + TEST_ASSERT(ng_pktbuf_is_sane()); 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 == pkt->next); - 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(ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF)); - /* Why 4? Because: http://xkcd.com/221/, thats why ;-) */ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, 1, NG_NETTYPE_TEST); + while (pkt) { + pkt = ng_pktbuf_add(NULL, NULL, 1, NG_NETTYPE_TEST); } - TEST_ASSERT_NULL(ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF)); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT(!ng_pktbuf_is_empty()); } -#endif static void test_pktbuf_add__success(void) { ng_pktsnip_t *pkt, *pkt_prev = NULL; for (int i = 0; i < 9; i++) { - pkt = ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_UNDEF); + pkt = ng_pktbuf_add(NULL, NULL, (NG_PKTBUF_SIZE / 10) + 4, NG_NETTYPE_TEST); 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(NG_NETTYPE_TEST, pkt->type); TEST_ASSERT_EQUAL_INT(1, pkt->users); if (pkt_prev != NULL) { @@ -252,6 +195,7 @@ static void test_pktbuf_add__success(void) pkt_prev = pkt; } + TEST_ASSERT(ng_pktbuf_is_sane()); } static void test_pktbuf_add__packed_struct(void) @@ -260,7 +204,7 @@ static void test_pktbuf_add__packed_struct(void) 34, -4469, 149699748, -46590430597 }; test_pktbuf_struct_t *data_cpy; - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, &data, sizeof(test_pktbuf_struct_t), NG_NETTYPE_UNDEF); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, &data, sizeof(test_pktbuf_struct_t), NG_NETTYPE_TEST); data_cpy = (test_pktbuf_struct_t *)pkt->data; TEST_ASSERT_EQUAL_INT(data.u8, data_cpy->u8); @@ -275,14 +219,14 @@ static void test_pktbuf_add__packed_struct(void) static void test_pktbuf_add__unaligned_in_aligned_hole(void) { - ng_pktsnip_t *pkt1 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_UNDEF); - ng_pktsnip_t *pkt2 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_UNDEF); - ng_pktsnip_t *pkt3 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_UNDEF); + ng_pktsnip_t *pkt1 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_TEST); + ng_pktsnip_t *pkt2 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_TEST); + ng_pktsnip_t *pkt3 = ng_pktbuf_add(NULL, NULL, 8, NG_NETTYPE_TEST); ng_pktsnip_t *pkt4; void *tmp_data2 = pkt2->data; ng_pktbuf_release(pkt2); - pkt4 = ng_pktbuf_add(NULL, TEST_STRING12, 9, NG_NETTYPE_UNDEF); + pkt4 = ng_pktbuf_add(NULL, TEST_STRING12, 9, NG_NETTYPE_TEST); TEST_ASSERT(tmp_data2 != pkt4->data); @@ -292,171 +236,287 @@ static void test_pktbuf_add__unaligned_in_aligned_hole(void) TEST_ASSERT(ng_pktbuf_is_empty()); } -static void test_pktbuf_realloc_data__pkt_NULL(void) +static void test_pktbuf_mark__pkt_NULL__size_0(void) { - TEST_ASSERT_EQUAL_INT(ENOENT, ng_pktbuf_realloc_data(NULL, 0)); - TEST_ASSERT(ng_pktbuf_is_empty()); + TEST_ASSERT_NULL(ng_pktbuf_mark(NULL, 0, NG_NETTYPE_TEST)); } -static void test_pktbuf_realloc_data__pkt_wrong(void) +static void test_pktbuf_mark__pkt_NULL__size_not_0(void) { - ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; - - TEST_ASSERT_EQUAL_INT(ENOENT, ng_pktbuf_realloc_data(&pkt, 0)); - TEST_ASSERT(ng_pktbuf_is_empty()); + TEST_ASSERT_NULL(ng_pktbuf_mark(NULL, sizeof(TEST_STRING4), NG_NETTYPE_TEST)); } -static void test_pktbuf_realloc_data__pkt_data_wrong(void) +static void test_pktbuf_mark__pkt_NOT_NULL__size_0(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; + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_TEST); - 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_NOT_NULL(pkt); + TEST_ASSERT_NULL(ng_pktbuf_mark(pkt, 0, NG_NETTYPE_TEST)); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NOT_NULL(pkt->data); + TEST_ASSERT_EQUAL_STRING(TEST_STRING16, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); } -static void test_pktbuf_realloc_data__pkt_users_gt_1(void) +static void test_pktbuf_mark__pkt_NOT_NULL__size_greater_than_pkt_size(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); - ng_pktbuf_hold(pkt, 1); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), + NG_NETTYPE_TEST); - 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()); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_NULL(ng_pktbuf_mark(pkt, sizeof(TEST_STRING16) + 8, + NG_NETTYPE_TEST)); + TEST_ASSERT_NULL(pkt->next); + TEST_ASSERT_NOT_NULL(pkt->data); + TEST_ASSERT_EQUAL_STRING(TEST_STRING16, pkt->data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt->type); + TEST_ASSERT_EQUAL_INT(1, pkt->users); } -static void test_pktbuf_realloc_data__pkt_next_neq_NULL(void) +static void test_pktbuf_mark__pkt_NOT_NULL__pkt_data_NULL(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + ng_pktsnip_t pkt = { 1, NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_TEST }; - TEST_ASSERT_NOT_NULL(ng_pktbuf_add(pkt, pkt->data, sizeof(TEST_STRING4), NG_NETTYPE_UNDEF)); - TEST_ASSERT_EQUAL_INT(EINVAL, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8) - 1)); - ng_pktbuf_release(pkt); - TEST_ASSERT(ng_pktbuf_is_empty()); + TEST_ASSERT_NULL(ng_pktbuf_mark(&pkt, sizeof(TEST_STRING16) - 1, + NG_NETTYPE_TEST)); + TEST_ASSERT_NULL(pkt.next); + TEST_ASSERT_NULL(pkt.data); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16), pkt.size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt.type); + TEST_ASSERT_EQUAL_INT(1, pkt.users); } -static void test_pktbuf_realloc_data__size_0(void) +static void test_pktbuf_mark__success_large(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + uint8_t *data = (uint8_t *)(TEST_STRING16); + ng_pktsnip_t *pkt1 = ng_pktbuf_add(NULL, data, sizeof(TEST_STRING16), + NG_NETTYPE_TEST); + ng_pktsnip_t *pkt2; + uint8_t exp_data1[sizeof(TEST_STRING16) - sizeof(TEST_STRING8)]; + uint8_t exp_data2[sizeof(TEST_STRING8)]; - TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, 0)); - ng_pktbuf_release(pkt); + memcpy(exp_data1, data + sizeof(exp_data2), sizeof(exp_data1)); + memcpy(exp_data2, data, sizeof(exp_data2)); + + TEST_ASSERT_NOT_NULL(pkt1); + TEST_ASSERT_NOT_NULL((pkt2 = ng_pktbuf_mark(pkt1, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF))); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT(pkt1->next == pkt2); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - sizeof(TEST_STRING8), + pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + TEST_ASSERT_NULL(pkt2->next); + TEST_ASSERT_NOT_NULL(pkt2->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data2, pkt2->data, pkt2->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt2->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt2->type); + TEST_ASSERT_EQUAL_INT(1, pkt2->users); + + /* check if slightly larger packet would override data */ + ng_pktbuf_remove_snip(pkt1, pkt2); + pkt2 = ng_pktbuf_add(NULL, TEST_STRING12, 12, NG_NETTYPE_TEST); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - sizeof(TEST_STRING8), + pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + + /* check if everything can be cleaned up */ + ng_pktbuf_release(pkt1); + ng_pktbuf_release(pkt2); TEST_ASSERT(ng_pktbuf_is_empty()); } -#if NG_PKTBUF_SIZE > 0 -static void test_pktbuf_realloc_data__memfull(void) +static void test_pktbuf_mark__success_aligned(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + uint8_t *data = (uint8_t *)(TEST_STRING16); + ng_pktsnip_t *pkt1 = ng_pktbuf_add(NULL, data, sizeof(TEST_STRING16), + NG_NETTYPE_TEST); + ng_pktsnip_t *pkt2; + uint8_t exp_data1[sizeof(TEST_STRING16) - 8]; + uint8_t exp_data2[8]; - TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, NG_PKTBUF_SIZE + 1)); - ng_pktbuf_release(pkt); + memcpy(exp_data1, data + sizeof(exp_data2), sizeof(exp_data1)); + memcpy(exp_data2, data, sizeof(exp_data2)); + + TEST_ASSERT_NOT_NULL(pkt1); + TEST_ASSERT_NOT_NULL((pkt2 = ng_pktbuf_mark(pkt1, 8, NG_NETTYPE_UNDEF))); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT(pkt1->next == pkt2); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 8, + pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + TEST_ASSERT_NULL(pkt2->next); + TEST_ASSERT_NOT_NULL(pkt2->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data2, pkt2->data, pkt2->size)); + TEST_ASSERT_EQUAL_INT(8, pkt2->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt2->type); + TEST_ASSERT_EQUAL_INT(1, pkt2->users); + + /* check if slightly larger packet would override data */ + ng_pktbuf_remove_snip(pkt1, pkt2); + pkt2 = ng_pktbuf_add(NULL, TEST_STRING12, 12, NG_NETTYPE_TEST); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 8, + pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + + /* check if everything can be cleaned up */ + ng_pktbuf_release(pkt1); + ng_pktbuf_release(pkt2); TEST_ASSERT(ng_pktbuf_is_empty()); } -static void test_pktbuf_realloc_data__memfull2(void) +static void test_pktbuf_mark__success_small(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF); + uint8_t *data = (uint8_t *)(TEST_STRING16); + ng_pktsnip_t *pkt1 = ng_pktbuf_add(NULL, data, sizeof(TEST_STRING16), + NG_NETTYPE_TEST); + ng_pktsnip_t *pkt2; + uint8_t exp_data1[sizeof(TEST_STRING16) - 1]; + uint8_t exp_data2[1]; - 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))); + memcpy(exp_data1, data + sizeof(exp_data2), sizeof(exp_data1)); + memcpy(exp_data2, data, sizeof(exp_data2)); + + TEST_ASSERT_NOT_NULL(pkt1); + TEST_ASSERT_NOT_NULL((pkt2 = ng_pktbuf_mark(pkt1, 1, NG_NETTYPE_UNDEF))); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT(pkt1->next == pkt2); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 1, pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + TEST_ASSERT_NULL(pkt2->next); + TEST_ASSERT_NOT_NULL(pkt2->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data2, pkt2->data, pkt2->size)); + TEST_ASSERT_EQUAL_INT(1, pkt2->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt2->type); + TEST_ASSERT_EQUAL_INT(1, pkt2->users); + + /* check if slightly larger packet would override data */ + ng_pktbuf_remove_snip(pkt1, pkt2); + pkt2 = ng_pktbuf_add(NULL, TEST_STRING12, 3, NG_NETTYPE_TEST); + TEST_ASSERT(ng_pktbuf_is_sane()); + TEST_ASSERT_NOT_NULL(pkt1->data); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_data1, pkt1->data, pkt1->size)); + TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 1, pkt1->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt1->type); + TEST_ASSERT_EQUAL_INT(1, pkt1->users); + + /* check if everything can be cleaned up */ + ng_pktbuf_release(pkt1); + ng_pktbuf_release(pkt2); + TEST_ASSERT(ng_pktbuf_is_empty()); } -static void test_pktbuf_realloc_data__memfull3(void) +static void test_pktbuf_realloc_data__size_0(void) { - ng_pktsnip_t *pkt; + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_TEST); - 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, 0)); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); +} - pkt = ng_pktbuf_add(NULL, NULL, TEST_UINT8, NG_NETTYPE_UNDEF); +static void test_pktbuf_realloc_data__memfull(void) +{ + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_TEST); - 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)); + TEST_ASSERT_EQUAL_INT(ENOMEM, ng_pktbuf_realloc_data(pkt, NG_PKTBUF_SIZE + 1)); + ng_pktbuf_release(pkt); + TEST_ASSERT(ng_pktbuf_is_empty()); } -/* 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); + pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_TEST); exp_data = pkt->data; TEST_ASSERT_NOT_NULL(pkt); - TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_UNDEF)); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_TEST)); - TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8))); + TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(pkt, 8)); 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(8, pkt->size); + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, 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; + pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING16), NG_NETTYPE_TEST); 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(NG_NETTYPE_TEST, 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; + pkt1 = ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(pkt1); - pkt2 = ng_pktbuf_add(NULL, NULL, 1, NG_NETTYPE_UNDEF); + pkt2 = ng_pktbuf_add(NULL, NULL, 1, NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(pkt2); - TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_UNDEF)); + TEST_ASSERT_NOT_NULL(ng_pktbuf_add(NULL, NULL, 4, NG_NETTYPE_TEST)); 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(NG_NETTYPE_TEST, pkt1->type); TEST_ASSERT_EQUAL_INT(1, pkt1->users); } -#endif static void test_pktbuf_realloc_data__success(void) { + char exp_data[] = TEST_STRING16; ng_pktsnip_t *pkt; - pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST); 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_STRING16, pkt->data); TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING8), pkt->size); - TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, pkt->type); + for (unsigned int i = 0; i < pkt->size; i++) { + uint8_t *data = pkt->data; + TEST_ASSERT_EQUAL_INT(exp_data[i], data[i]); + } + TEST_ASSERT_EQUAL_INT(NG_NETTYPE_TEST, pkt->type); TEST_ASSERT_EQUAL_INT(1, pkt->users); } @@ -464,7 +524,7 @@ 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); + pkt = ng_pktbuf_add(NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL(pkt); @@ -472,41 +532,10 @@ static void test_pktbuf_realloc_data__success2(void) 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(NG_NETTYPE_TEST, pkt->type); TEST_ASSERT_EQUAL_INT(1, pkt->users); } -static void test_pktbuf_realloc_data__further_down_the_line(void) -{ - ng_pktsnip_t *pkt1, *pkt2, *header; - void *exp_data; - - pkt1 = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); - exp_data = pkt1->data; - - TEST_ASSERT_NOT_NULL(pkt1); - - header = ng_pktbuf_add(pkt1, pkt1->data, 4, NG_NETTYPE_UNDEF); - pkt2 = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); - - TEST_ASSERT_NOT_NULL(header); - TEST_ASSERT(header == pkt1->next); - TEST_ASSERT_EQUAL_INT(4, header->size); - TEST_ASSERT(((uint8_t *)pkt1->data) == (((uint8_t *)header->data) + 4)); - TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING16) - 4, pkt1->size); - - TEST_ASSERT_EQUAL_INT(0, ng_pktbuf_realloc_data(header, 40)); - TEST_ASSERT(exp_data != header->data); - TEST_ASSERT_NULL(header->next); - TEST_ASSERT_EQUAL_STRING(TEST_STRING16, header->data); - TEST_ASSERT_EQUAL_INT(40, header->size); - TEST_ASSERT_EQUAL_INT(NG_NETTYPE_UNDEF, header->type); - TEST_ASSERT_EQUAL_INT(1, header->users); - ng_pktbuf_release(pkt1); - ng_pktbuf_release(pkt2); - TEST_ASSERT(ng_pktbuf_is_empty()); -} - static void test_pktbuf_hold__pkt_null(void) { ng_pktbuf_hold(NULL, 1); @@ -515,7 +544,7 @@ static void test_pktbuf_hold__pkt_null(void) static void test_pktbuf_hold__pkt_external(void) { - ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; + ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_TEST }; ng_pktbuf_hold(&pkt, 1); TEST_ASSERT(ng_pktbuf_is_empty()); @@ -523,7 +552,7 @@ static void test_pktbuf_hold__pkt_external(void) static void test_pktbuf_hold__success(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST); for (uint8_t i = 0; i < TEST_UINT8; i++) { uint8_t prev_users = pkt->users; @@ -534,7 +563,7 @@ static void test_pktbuf_hold__success(void) static void test_pktbuf_hold__success2(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST); ng_pktbuf_hold(pkt, TEST_UINT8); @@ -549,7 +578,7 @@ static void test_pktbuf_release__pkt_null(void) static void test_pktbuf_release__pkt_external(void) { - ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF }; + ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_TEST }; ng_pktbuf_release(&pkt); TEST_ASSERT(ng_pktbuf_is_empty()); @@ -557,7 +586,7 @@ static void test_pktbuf_release__pkt_external(void) static void test_pktbuf_release__success(void) { - ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF); + ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST); for (uint8_t i = 0; i < TEST_UINT8; i++) { uint8_t prev_users = pkt->users; @@ -587,7 +616,7 @@ static void test_pktbuf_start_write__NULL(void) 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); + NG_NETTYPE_TEST); TEST_ASSERT_NOT_NULL((pkt_copy = ng_pktbuf_start_write(pkt))); TEST_ASSERT(pkt == pkt_copy); @@ -598,7 +627,7 @@ static void test_pktbuf_start_write__pkt_users_1(void) 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_NETTYPE_TEST); ng_pktbuf_hold(pkt, 1); TEST_ASSERT_NOT_NULL((pkt_copy = ng_pktbuf_start_write(pkt))); @@ -618,7 +647,7 @@ static void test_pktbuf_start_write__pkt_users_2(void) Test *tests_pktbuf_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_pktbuf_reset), + new_TestFixture(test_pktbuf_init), 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), @@ -626,32 +655,25 @@ Test *tests_pktbuf_tests(void) 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_add__success), new_TestFixture(test_pktbuf_add__packed_struct), new_TestFixture(test_pktbuf_add__unaligned_in_aligned_hole), - 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_mark__pkt_NULL__size_0), + new_TestFixture(test_pktbuf_mark__pkt_NULL__size_not_0), + new_TestFixture(test_pktbuf_mark__pkt_NOT_NULL__size_0), + new_TestFixture(test_pktbuf_mark__pkt_NOT_NULL__size_greater_than_pkt_size), + new_TestFixture(test_pktbuf_mark__pkt_NOT_NULL__pkt_data_NULL), + new_TestFixture(test_pktbuf_mark__success_large), + new_TestFixture(test_pktbuf_mark__success_aligned), + new_TestFixture(test_pktbuf_mark__success_small), 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), @@ -664,7 +686,7 @@ Test *tests_pktbuf_tests(void) new_TestFixture(test_pktbuf_start_write__pkt_users_2), }; - EMB_UNIT_TESTCALLER(ng_pktbuf_tests, NULL, tear_down, fixtures); + EMB_UNIT_TESTCALLER(ng_pktbuf_tests, set_up, NULL, fixtures); return (Test *)&ng_pktbuf_tests; }