mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #1638 from authmillenon/packetbuf2
net: Initial import of a global packet buffer
This commit is contained in:
commit
0812d4789a
@ -29,6 +29,11 @@
|
||||
#ifndef UART0_BUFSIZE
|
||||
#define UART0_BUFSIZE (32)
|
||||
#endif
|
||||
|
||||
#ifndef PKTBUF_SIZE
|
||||
#define PKTBUF_SIZE (2560) /* TODO: Make this value
|
||||
overall MTU dependent */
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#endif /* CPUCONF_H_ */
|
||||
|
@ -13,6 +13,9 @@ endif
|
||||
ifneq (,$(filter ping,$(USEMODULE)))
|
||||
DIRS += ping
|
||||
endif
|
||||
ifneq (,$(filter pktbuf,$(USEMODULE)))
|
||||
DIRS += net/crosslayer/pktbuf
|
||||
endif
|
||||
ifneq (,$(filter ps,$(USEMODULE)))
|
||||
DIRS += ps
|
||||
endif
|
||||
|
@ -18,6 +18,9 @@ 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
|
||||
|
1
sys/net/crosslayer/pktbuf/Makefile
Normal file
1
sys/net/crosslayer/pktbuf/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
509
sys/net/crosslayer/pktbuf/pktbuf.c
Normal file
509
sys/net/crosslayer/pktbuf/pktbuf.c
Normal file
@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file pktbuf.c
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mutex.h"
|
||||
#include "pktbuf.h"
|
||||
|
||||
typedef struct __attribute__((packed)) _packet_t {
|
||||
volatile struct _packet_t *next;
|
||||
uint8_t processing;
|
||||
size_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 <stdio.h>
|
||||
|
||||
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
|
||||
|
||||
/** @} */
|
187
sys/net/include/pktbuf.h
Normal file
187
sys/net/include/pktbuf.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef __PKTBUF_H_
|
||||
#define __PKTBUF_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cpu-conf.h"
|
||||
|
||||
#ifndef PKTBUF_SIZE
|
||||
/**
|
||||
* @brief Maximum size of the packet buffer.
|
||||
*
|
||||
* @detail 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.
|
||||
*
|
||||
* @datail 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.
|
||||
*
|
||||
* @detail 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.
|
||||
*
|
||||
* @detail 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.
|
||||
*
|
||||
* @detail 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
|
||||
|
||||
#endif /* __PKTBUF_H_ */
|
||||
/** @} */
|
@ -1,7 +1,7 @@
|
||||
APPLICATION = unittests
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BOARD_INSUFFICIENT_RAM := chronos redbee-econotag stm32f0discovery
|
||||
BOARD_INSUFFICIENT_RAM := chronos msb-430 msb-430h redbee-econotag stm32f0discovery
|
||||
|
||||
USEMODULE += embunit
|
||||
|
||||
|
3
tests/unittests/tests-pktbuf/Makefile
Normal file
3
tests/unittests/tests-pktbuf/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = tests-pktbuf
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
1
tests/unittests/tests-pktbuf/Makefile.include
Normal file
1
tests/unittests/tests-pktbuf/Makefile.include
Normal file
@ -0,0 +1 @@
|
||||
USEMODULE += pktbuf
|
538
tests/unittests/tests-pktbuf/tests-pktbuf.c
Normal file
538
tests/unittests/tests-pktbuf/tests-pktbuf.c
Normal file
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martine Lenders <mail@martine-lenders.eu>
|
||||
*
|
||||
* 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 tests-pktbuf.c
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "embUnit/embUnit.h"
|
||||
|
||||
#include "pktbuf.h"
|
||||
|
||||
#include "tests-pktbuf.h"
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int8_t s8;
|
||||
int16_t s16;
|
||||
int32_t s32;
|
||||
int64_t s64;
|
||||
} test_pktbuf_struct_t;
|
||||
|
||||
static void tear_down(void)
|
||||
{
|
||||
pktbuf_reset();
|
||||
}
|
||||
|
||||
static void test_pktbuf_alloc_0(void)
|
||||
{
|
||||
TEST_ASSERT_NULL(pktbuf_alloc(0));
|
||||
}
|
||||
|
||||
static void test_pktbuf_alloc_memfull(void)
|
||||
{
|
||||
for (int i = 0; i < 9; i++) {
|
||||
TEST_ASSERT_NOT_NULL(pktbuf_alloc((PKTBUF_SIZE / 10) + 4));
|
||||
/* 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);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_pktbuf_copy_data_len_too_long(void)
|
||||
{
|
||||
char *data = (char *)pktbuf_insert("ab", 3);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(data);
|
||||
TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(data, "cdef", 5));
|
||||
TEST_ASSERT_EQUAL_STRING("ab", data);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(data.u8, data_cpy->u8);
|
||||
TEST_ASSERT_EQUAL_INT(data.u16, data_cpy->u16);
|
||||
TEST_ASSERT_EQUAL_INT(data.u32, data_cpy->u32);
|
||||
TEST_ASSERT_EQUAL_INT(data.u64, data_cpy->u64);
|
||||
TEST_ASSERT_EQUAL_INT(data.s8, data_cpy->s8);
|
||||
TEST_ASSERT_EQUAL_INT(data.s16, data_cpy->s16);
|
||||
TEST_ASSERT_EQUAL_INT(data.s32, data_cpy->s32);
|
||||
TEST_ASSERT_EQUAL_INT(data.s64, data_cpy->s64);
|
||||
}
|
||||
|
||||
static void test_pktbuf_alloc_off_by_one1(void)
|
||||
{
|
||||
char *data1, *data2, *data3, *data4;
|
||||
|
||||
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());
|
||||
|
||||
pktbuf_release(data1);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated());
|
||||
TEST_ASSERT_EQUAL_INT(44 + 4, pktbuf_bytes_allocated());
|
||||
|
||||
data3 = (char *)pktbuf_insert("bcdefghijklm", 13);
|
||||
TEST_ASSERT_NOT_NULL(data3);
|
||||
TEST_ASSERT(data1 != data3);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated());
|
||||
TEST_ASSERT_EQUAL_INT(44 + 4 + 13, pktbuf_bytes_allocated());
|
||||
}
|
||||
|
||||
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),
|
||||
#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),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(pktbuf_tests, NULL, tear_down, fixtures);
|
||||
|
||||
return (Test *)&pktbuf_tests;
|
||||
}
|
||||
|
||||
void tests_pktbuf(void)
|
||||
{
|
||||
TESTS_RUN(tests_pktbuf_tests());
|
||||
}
|
||||
/** @} */
|
29
tests/unittests/tests-pktbuf/tests-pktbuf.h
Normal file
29
tests/unittests/tests-pktbuf/tests-pktbuf.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup unittests
|
||||
* @{
|
||||
*
|
||||
* @file tests-pktbuf.h
|
||||
* @brief Unittests for the ``pktbuf`` module
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef __TESTS_PKTBUF_H_
|
||||
#define __TESTS_PKTBUF_H_
|
||||
|
||||
#include "../unittests.h"
|
||||
|
||||
/**
|
||||
* @brief The entry point of this test suite.
|
||||
*/
|
||||
void tests_pktbuf(void);
|
||||
|
||||
#endif /* __TESTS_PKTBUF_H_ */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user