1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #12324 from miri64/gnrc_sixlowpan_frag/enh/rbuf-rework202

gnrc_sixlowpan_frag_rb: migrate more functions from gnrc_sixlowpan_frag
This commit is contained in:
Martine Lenders 2019-09-29 18:30:12 +02:00 committed by GitHub
commit fb8b8ad8dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 609 additions and 688 deletions

View File

@ -213,6 +213,9 @@ endif
ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE)))
USEMODULE += gnrc_sixlowpan
USEMODULE += gnrc_sixlowpan_frag_rb
endif
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
USEMODULE += xtimer
endif

View File

@ -67,12 +67,13 @@
*
* 1. If @ref net_gnrc_sixlowpan_frag is included and @ref sixlowpan_frag_is() is true for the
* packet, the fragmentation header will be removed and its remaining data will be added to
* the reassembly buffer (using @ref rbuf_add()) in accordance to the fragmentation header.
* The packet containing the fragment will be discarded. When the fragmented datagram is
* complete, its payload will be marked with @ref GNRC_NETTYPE_IPV6 and issued via a
* @ref GNRC_NETAPI_MSG_TYPE_RCV to all subscribers registered to @ref GNRC_NETTYPE_IPV6 with
* demultiplex context @ref GNRC_NETREG_DEMUX_CTX_ALL in the @ref net_gnrc_netreg. If
* reassembly times out or if fragments overlap the datagram will be silently discarded.
* the reassembly buffer (using @ref gnrc_sixlowpan_frag_rb_add()) in accordance to the
* fragmentation header. The packet containing the fragment will be discarded. When the
* fragmented datagram is complete, its payload will be marked with @ref GNRC_NETTYPE_IPV6 and
* issued via a @ref GNRC_NETAPI_MSG_TYPE_RCV to all subscribers registered to @ref
* GNRC_NETTYPE_IPV6 with demultiplex context @ref GNRC_NETREG_DEMUX_CTX_ALL in the @ref
* net_gnrc_netreg. If reassembly times out or if fragments overlap the datagram will be
* silently discarded.
* 2. If @ref net_gnrc_sixlowpan_iphc is included the packet will not be send to the subscribers
* to @ref GNRC_NETTYPE_IPV6 with demultiplex context @ref GNRC_NETREG_DEMUX_CTX_ALL
* immediately, but it will be checked first if @ref sixlowpan_iphc_is() is true for its

View File

@ -123,7 +123,7 @@ extern "C" {
* @note Only applicable with
* [gnrc_sixlowpan_frag_vrb](@ref net_gnrc_sixlowpan_frag_vrb) module,
* but has also a direct influence on the number of available
* gnrc_sixlowpan_rbuf_int_t entries (even when
* gnrc_sixlowpan_frag_rb_int_t entries (even when
* `gnrc_sixlowpan_frag_vrb` is not compiled in).
*/
#ifndef GNRC_SIXLOWPAN_FRAG_VRB_SIZE

View File

@ -21,6 +21,12 @@
#define NET_GNRC_SIXLOWPAN_FRAG_RB_H
#include <stdint.h>
#include <stdbool.h>
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/sixlowpan/config.h"
#ifdef __cplusplus
extern "C" {
@ -36,14 +42,14 @@ extern "C" {
* RFC 4944, section 5.3
* </a>
*/
typedef struct gnrc_sixlowpan_rbuf_int {
typedef struct gnrc_sixlowpan_frag_rb_int {
/**
* @brief next element in fragment interval list
*/
struct gnrc_sixlowpan_rbuf_int *next;
struct gnrc_sixlowpan_frag_rb_int *next;
uint16_t start; /**< start byte of the fragment interval */
uint16_t end; /**< end byte of the fragment interval */
} gnrc_sixlowpan_rbuf_int_t;
} gnrc_sixlowpan_frag_rb_int_t;
/**
* @brief Base class for both reassembly buffer and virtual reassembly buffer
@ -59,11 +65,11 @@ typedef struct gnrc_sixlowpan_rbuf_int {
* @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01
*/
typedef struct {
gnrc_sixlowpan_rbuf_int_t *ints; /**< intervals of already received fragments */
gnrc_sixlowpan_frag_rb_int_t *ints; /**< intervals of already received fragments */
uint8_t src[IEEE802154_LONG_ADDRESS_LEN]; /**< source address */
uint8_t dst[IEEE802154_LONG_ADDRESS_LEN]; /**< destination address */
uint8_t src_len; /**< length of gnrc_sixlowpan_rbuf_t::src */
uint8_t dst_len; /**< length of gnrc_sixlowpan_rbuf_t::dst */
uint8_t src_len; /**< length of gnrc_sixlowpan_frag_rb_t::src */
uint8_t dst_len; /**< length of gnrc_sixlowpan_frag_rb_t::dst */
uint16_t tag; /**< the datagram's tag */
uint16_t datagram_size; /**< the datagram's size */
/**
@ -72,7 +78,7 @@ typedef struct {
uint16_t current_size;
uint32_t arrival; /**< time in microseconds of arrival of
* last received fragment */
} gnrc_sixlowpan_rbuf_base_t;
} gnrc_sixlowpan_frag_rb_base_t;
/**
* @brief An entry in the 6LoWPAN reassembly buffer.
@ -81,34 +87,91 @@ typedef struct {
*
*/
typedef struct {
gnrc_sixlowpan_rbuf_base_t super; /**< base class */
gnrc_sixlowpan_frag_rb_base_t super; /**< base class */
/**
* @brief The reassembled packet in the packet buffer
*/
gnrc_pktsnip_t *pkt;
} gnrc_sixlowpan_rbuf_t;
} gnrc_sixlowpan_frag_rb_t;
/**
* @brief Adds a new fragment to the reassembly buffer. If the packet is
* complete, dispatch the packet with the transmit information of
* the last fragment.
*
* @param[in] netif_hdr The interface header of the fragment, with
* gnrc_netif_hdr_t::if_pid and its source and
* destination address set.
* @param[in] frag The fragment to add.
* @param[in] offset The fragment's offset.
* @param[in] page Current 6Lo dispatch parsing page.
*/
void gnrc_sixlowpan_frag_rb_add(gnrc_netif_hdr_t *netif_hdr,
gnrc_pktsnip_t *frag, size_t offset,
unsigned page);
/**
* @brief Checks if a reassembly buffer entry is unset
*
* @param[in] rbuf A reassembly buffer entry
*
* @return true, if @p rbuf is empty (i.e. rbuf->super.pkt is NULL).
* @return false, if @p rbuf is in use.
*/
static inline bool gnrc_sixlowpan_frag_rb_entry_empty(
const gnrc_sixlowpan_frag_rb_t *rbuf) {
return (rbuf->pkt == NULL);
}
#if defined(TEST_SUITES) || defined(DOXYGEN)
/**
* @brief Resets the packet buffer to a clean state
*
* @note Only available when @ref TEST_SUITES is defined
*/
void gnrc_sixlowpan_frag_rb_reset(void);
/**
* @brief Returns a pointer to the array representing the reassembly buffer.
*
* @note Only available when @ref TEST_SUITES is defined
*
* @return The first element of the reassembly buffer. `const`, so that write
* access is immediately spotted at compile time of tests. The `const`
* qualifier may however be discarded if required by the tests.
*/
const gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_array(void);
#endif
/**
* @brief Remove base entry
*
* @param[in,out] entry Entry to remove
*/
void gnrc_sixlowpan_frag_rbuf_base_rm(gnrc_sixlowpan_rbuf_base_t *entry);
void gnrc_sixlowpan_frag_rb_base_rm(gnrc_sixlowpan_frag_rb_base_t *entry);
/**
* @brief Garbage collect reassembly buffer.
*/
void gnrc_sixlowpan_frag_rbuf_gc(void);
void gnrc_sixlowpan_frag_rb_gc(void);
#if defined(MODULE_GNRC_SIXLOWPAN_FRAG) || defined(DOXYGEN)
#if defined(MODULE_GNRC_SIXLOWPAN_FRAG_RB) || defined(DOXYGEN)
/**
* @brief Removes an entry from the reassembly buffer
* @brief Unsets a reassembly buffer entry (but does not free
* rbuf_t::super::pkt)
*
* @pre `rbuf != NULL`
*
* This functions sets rbuf_t::super::pkt to NULL and removes all rbuf::ints.
*
* @param[in] rbuf A reassembly buffer entry. Must not be NULL.
*/
void gnrc_sixlowpan_frag_rbuf_remove(gnrc_sixlowpan_rbuf_t *rbuf);
static inline void gnrc_sixlowpan_frag_rb_remove(gnrc_sixlowpan_frag_rb_t *rbuf)
{
assert(rbuf != NULL);
gnrc_sixlowpan_frag_rb_base_rm(&rbuf->super);
rbuf->pkt = NULL;
}
/**
* @brief Checks if a reassembly buffer entry is complete and dispatches it
@ -122,13 +185,13 @@ void gnrc_sixlowpan_frag_rbuf_remove(gnrc_sixlowpan_rbuf_t *rbuf);
* Used to construct the @ref gnrc_netif_hdr_t of the completed
* datagram. Must not be NULL.
*/
void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf,
gnrc_netif_hdr_t *netif);
void gnrc_sixlowpan_frag_rb_dispatch_when_complete(gnrc_sixlowpan_frag_rb_t *rbuf,
gnrc_netif_hdr_t *netif);
#else
/* NOPs to be used with gnrc_sixlowpan_iphc if gnrc_sixlowpan_frag is not
/* NOPs to be used with gnrc_sixlowpan_iphc if gnrc_sixlowpan_frag_rb is not
* compiled in */
#define gnrc_sixlowpan_frag_rbuf_remove(rbuf) (void)(rbuf)
#define gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif) \
#define gnrc_sixlowpan_frag_rb_remove(rbuf) (void)(rbuf)
#define gnrc_sixlowpan_frag_rb_dispatch_when_complete(rbuf, netif) \
(void)(rbuf); (void)(netif)
#endif

View File

@ -38,7 +38,7 @@ extern "C" {
* @brief Representation of the virtual reassembly buffer entry
*/
typedef struct {
gnrc_sixlowpan_rbuf_base_t super; /**< base type */
gnrc_sixlowpan_frag_rb_base_t super; /**< base type */
/**
* @brief Link-layer destination address to which the fragments are
@ -76,7 +76,7 @@ typedef struct {
* @return NULL, if VRB is full.
*/
gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add(
const gnrc_sixlowpan_rbuf_base_t *base,
const gnrc_sixlowpan_frag_rb_base_t *base,
gnrc_netif_t *out_netif, const uint8_t *out_dst, size_t out_dst_len);
/**
@ -112,7 +112,7 @@ gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get(
static inline void gnrc_sixlowpan_frag_vrb_rm(gnrc_sixlowpan_frag_vrb_t *vrb)
{
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
gnrc_sixlowpan_frag_rbuf_base_rm(&vrb->super);
gnrc_sixlowpan_frag_rb_base_rm(&vrb->super);
#elif defined(TEST_SUITES)
/* for testing just zero datagram_size */
vrb->super.datagram_size = 0;

View File

@ -38,7 +38,7 @@ extern "C" {
* be expected to start with the IPHC dispatch.
* @param[in,out] ctx Context for the packet. May be NULL. If not NULL it
* is expected to be of type
* @ref gnrc_sixlowpan_rbuf_t. This function might
* @ref gnrc_sixlowpan_frag_rb_t. This function might
* change the content of that.
* @param[in] page Current 6Lo dispatch parsing page.
*/

View File

@ -21,13 +21,12 @@
#include "net/gnrc/netapi.h"
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/sixlowpan/frag.h"
#include "net/gnrc/sixlowpan/frag/rb.h"
#include "net/gnrc/sixlowpan/internal.h"
#include "net/gnrc/netif.h"
#include "net/sixlowpan.h"
#include "utlist.h"
#include "rbuf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
@ -360,7 +359,7 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
return;
}
rbuf_add(hdr, pkt, offset, page);
gnrc_sixlowpan_frag_rb_add(hdr, pkt, offset, page);
}
uint16_t gnrc_sixlowpan_frag_next_tag(void)

View File

@ -13,22 +13,430 @@
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#include <inttypes.h>
#include <stdbool.h>
#include "net/ieee802154.h"
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/pkt.h"
#include "net/ipv6.h"
#include "net/ipv6/hdr.h"
#include "net/gnrc.h"
#include "net/gnrc/sixlowpan.h"
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
#include "net/gnrc/sixlowpan/frag/vrb.h"
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
#include "net/sixlowpan.h"
#include "thread.h"
#include "xtimer.h"
#include "utlist.h"
#include "net/gnrc/sixlowpan/frag/rb.h"
#include "rbuf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
void gnrc_sixlowpan_frag_rbuf_base_rm(gnrc_sixlowpan_rbuf_base_t *entry)
/* estimated fragment payload size to determinate RBUF_INT_SIZE, default to
* MAC payload size - fragment header. */
#ifndef GNRC_SIXLOWPAN_FRAG_SIZE
/* assuming 64-bit source/destination address, source PAN ID omitted */
#define GNRC_SIXLOWPAN_FRAG_SIZE (104 - 5)
#endif
#ifndef RBUF_INT_SIZE
/* same as ((int) ceil((double) N / D)) */
#define DIV_CEIL(N, D) (((N) + (D) - 1) / (D))
#define RBUF_INT_SIZE (DIV_CEIL(IPV6_MIN_MTU, GNRC_SIXLOWPAN_FRAG_SIZE) * \
GNRC_SIXLOWPAN_FRAG_RBUF_SIZE)
#endif
static gnrc_sixlowpan_frag_rb_int_t rbuf_int[RBUF_INT_SIZE];
static gnrc_sixlowpan_frag_rb_t rbuf[GNRC_SIXLOWPAN_FRAG_RBUF_SIZE];
static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
static xtimer_t _gc_timer;
static msg_t _gc_timer_msg = { .type = GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF };
/* ------------------------------------
* internal function definitions
* ------------------------------------*/
/* checks whether start and end overlaps, but not identical to, given interval i */
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_frag_rb_int_t *i,
uint16_t start, uint16_t end);
/* gets a free entry from interval buffer */
static gnrc_sixlowpan_frag_rb_int_t *_rbuf_int_get_free(void);
/* update interval buffer of entry */
static bool _rbuf_update_ints(gnrc_sixlowpan_frag_rb_base_t *entry,
uint16_t offset, size_t frag_size);
/* gets an entry identified by its tupel */
static gnrc_sixlowpan_frag_rb_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_len,
size_t size, uint16_t tag,
unsigned page);
/* internal add to repeat add when fragments overlapped */
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
size_t offset, unsigned page);
/* status codes for _rbuf_add() */
enum {
RBUF_ADD_SUCCESS,
RBUF_ADD_ERROR,
RBUF_ADD_REPEAT,
RBUF_ADD_DUPLICATE,
};
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
static gnrc_sixlowpan_frag_stats_t _stats;
gnrc_sixlowpan_frag_stats_t *gnrc_sixlowpan_frag_stats_get(void)
{
return &_stats;
}
#endif
static int _check_fragments(gnrc_sixlowpan_frag_rb_base_t *entry,
size_t frag_size, size_t offset)
{
gnrc_sixlowpan_frag_rb_int_t *ptr = entry->ints;
/* If the fragment overlaps another fragment and differs in either the size
* or the offset of the overlapped fragment, discards the datagram
* https://tools.ietf.org/html/rfc4944#section-5.3 */
while (ptr != NULL) {
if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) {
/* "A fresh reassembly may be commenced with the most recently
* received link fragment"
* https://tools.ietf.org/html/rfc4944#section-5.3 */
return RBUF_ADD_REPEAT;
}
/* End was already checked in overlap check */
if (ptr->start == offset) {
DEBUG("6lo rbuf: fragment already in reassembly buffer");
return RBUF_ADD_DUPLICATE;
}
ptr = ptr->next;
}
return RBUF_ADD_SUCCESS;
}
void gnrc_sixlowpan_frag_rb_add(gnrc_netif_hdr_t *netif_hdr,
gnrc_pktsnip_t *pkt, size_t offset,
unsigned page)
{
if (_rbuf_add(netif_hdr, pkt, offset, page) == RBUF_ADD_REPEAT) {
_rbuf_add(netif_hdr, pkt, offset, page);
}
}
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
size_t offset, unsigned page)
{
gnrc_sixlowpan_frag_rb_t *entry;
sixlowpan_frag_n_t *frag = pkt->data;
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
size_t frag_size;
/* check if provided offset is the same as in fragment */
assert(((((frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) ==
SIXLOWPAN_FRAG_1_DISP)) && (offset == 0)) ||
((((frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) ==
SIXLOWPAN_FRAG_N_DISP)) && (offset == (frag->offset * 8U))));
gnrc_sixlowpan_frag_rb_gc();
entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK,
byteorder_ntohs(frag->tag), page);
if (entry == NULL) {
DEBUG("6lo rbuf: reassembly buffer full.\n");
gnrc_pktbuf_release(pkt);
return RBUF_ADD_ERROR;
}
/* dispatches in the first fragment are ignored */
if (offset == 0) {
frag_size = pkt->size - sizeof(sixlowpan_frag_t);
if (data[0] == SIXLOWPAN_UNCOMP) {
frag_size--;
}
}
else {
frag_size = pkt->size - sizeof(sixlowpan_frag_n_t);
data++; /* FRAGN header is one byte longer (offset) */
}
if ((offset + frag_size) > entry->super.datagram_size) {
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt);
gnrc_pktbuf_release(pkt);
gnrc_sixlowpan_frag_rb_remove(entry);
return RBUF_ADD_ERROR;
}
switch (_check_fragments(&entry->super, frag_size, offset)) {
case RBUF_ADD_REPEAT:
DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt);
gnrc_sixlowpan_frag_rb_remove(entry);
return RBUF_ADD_REPEAT;
case RBUF_ADD_DUPLICATE:
gnrc_pktbuf_release(pkt);
return RBUF_ADD_SUCCESS;
default:
break;
}
if (_rbuf_update_ints(&entry->super, offset, frag_size)) {
DEBUG("6lo rbuf: add fragment data\n");
entry->super.current_size += (uint16_t)frag_size;
if (offset == 0) {
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
if (sixlowpan_iphc_is(data)) {
gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt,
sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN);
if (frag_hdr == NULL) {
gnrc_pktbuf_release(entry->pkt);
gnrc_pktbuf_release(pkt);
gnrc_sixlowpan_frag_rb_remove(entry);
return RBUF_ADD_ERROR;
}
gnrc_sixlowpan_iphc_recv(pkt, entry, 0);
return RBUF_ADD_SUCCESS;
}
else
#endif
if (data[0] == SIXLOWPAN_UNCOMP) {
data++;
}
}
memcpy(((uint8_t *)entry->pkt->data) + offset, data,
frag_size);
}
gnrc_sixlowpan_frag_rb_dispatch_when_complete(entry, netif_hdr);
gnrc_pktbuf_release(pkt);
return RBUF_ADD_SUCCESS;
}
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_frag_rb_int_t *i,
uint16_t start, uint16_t end)
{
/* start and ends are both inclusive, so using <= for both */
return ((i->start <= end) && (start <= i->end)) && /* overlaps */
((start != i->start) || (end != i->end)); /* not identical */
}
static gnrc_sixlowpan_frag_rb_int_t *_rbuf_int_get_free(void)
{
for (unsigned int i = 0; i < RBUF_INT_SIZE; i++) {
if (rbuf_int[i].end == 0) { /* start must be smaller than end anyways*/
return rbuf_int + i;
}
}
return NULL;
}
static bool _rbuf_update_ints(gnrc_sixlowpan_frag_rb_base_t *entry,
uint16_t offset, size_t frag_size)
{
gnrc_sixlowpan_frag_rb_int_t *new;
uint16_t end = (uint16_t)(offset + frag_size - 1);
new = _rbuf_int_get_free();
if (new == NULL) {
DEBUG("6lo rfrag: no space left in rbuf interval buffer.\n");
return false;
}
new->start = offset;
new->end = end;
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
new->start, new->end, gnrc_netif_addr_to_str(entry->src,
entry->src_len,
l2addr_str));
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst,
entry->dst_len,
l2addr_str),
entry->datagram_size, entry->tag);
LL_PREPEND(entry->ints, new);
return true;
}
void gnrc_sixlowpan_frag_rb_gc(void)
{
uint32_t now_usec = xtimer_now_usec();
unsigned int i;
for (i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
/* since pkt occupies pktbuf, aggressivly collect garbage */
if (!gnrc_sixlowpan_frag_rb_entry_empty(&rbuf[i]) &&
((now_usec - rbuf[i].super.arrival) >
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
DEBUG("6lo rfrag: entry (%s, ",
gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) timed out\n",
gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str),
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
gnrc_pktbuf_release(rbuf[i].pkt);
gnrc_sixlowpan_frag_rb_remove(&(rbuf[i]));
}
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
gnrc_sixlowpan_frag_vrb_gc();
#endif
}
static inline void _set_rbuf_timeout(void)
{
xtimer_set_msg(&_gc_timer, GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US,
&_gc_timer_msg, sched_active_pid);
}
static gnrc_sixlowpan_frag_rb_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_len,
size_t size, uint16_t tag,
unsigned page)
{
gnrc_sixlowpan_frag_rb_t *res = NULL, *oldest = NULL;
uint32_t now_usec = xtimer_now_usec();
for (unsigned int i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
/* check first if entry already available */
if ((rbuf[i].pkt != NULL) && (rbuf[i].super.datagram_size == size) &&
(rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) &&
(rbuf[i].super.dst_len == dst_len) &&
(memcmp(rbuf[i].super.src, src, src_len) == 0) &&
(memcmp(rbuf[i].super.dst, dst, dst_len) == 0)) {
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) found\n",
gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str),
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
rbuf[i].super.arrival = now_usec;
_set_rbuf_timeout();
return &(rbuf[i]);
}
/* if there is a free spot: remember it */
if ((res == NULL) && gnrc_sixlowpan_frag_rb_entry_empty(&rbuf[i])) {
res = &(rbuf[i]);
}
/* remember oldest slot */
/* note that xtimer_now will overflow in ~1.2 hours */
if ((oldest == NULL) ||
(oldest->super.arrival - rbuf[i].super.arrival < UINT32_MAX / 2)) {
oldest = &(rbuf[i]);
}
}
/* entry not in buffer and no empty spot found */
if (res == NULL) {
assert(oldest != NULL);
/* if oldest is not empty, res must not be NULL (because otherwise
* oldest could have been picked as res) */
assert(!gnrc_sixlowpan_frag_rb_entry_empty(oldest));
if (GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE ||
((now_usec - oldest->super.arrival) >
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
gnrc_pktbuf_release(oldest->pkt);
gnrc_sixlowpan_frag_rb_remove(oldest);
res = oldest;
#if GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE && \
defined(MODULE_GNRC_SIXLOWPAN_FRAG_STATS)
_stats.rbuf_full++;
#endif
}
else {
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
_stats.rbuf_full++;
#endif
return NULL;
}
}
/* now we have an empty spot */
gnrc_nettype_t reass_type;
switch (page) {
/* use switch(page) to be extendable */
#ifdef MODULE_GNRC_IPV6
case 0U:
reass_type = GNRC_NETTYPE_IPV6;
break;
#endif
default:
reass_type = GNRC_NETTYPE_UNDEF;
}
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
if (res->pkt == NULL) {
DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n");
return NULL;
}
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later
* look-ups */
res->super.datagram_size = size;
res->super.arrival = now_usec;
memcpy(res->super.src, src, src_len);
memcpy(res->super.dst, dst, dst_len);
res->super.src_len = src_len;
res->super.dst_len = dst_len;
res->super.tag = tag;
res->super.current_size = 0;
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
gnrc_netif_addr_to_str(res->super.src, res->super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) created\n",
gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len,
l2addr_str), res->super.datagram_size,
res->super.tag);
_set_rbuf_timeout();
return res;
}
#ifdef TEST_SUITES
void gnrc_sixlowpan_frag_rb_reset(void)
{
xtimer_remove(&_gc_timer);
memset(rbuf_int, 0, sizeof(rbuf_int));
for (unsigned int i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
if ((rbuf[i].pkt != NULL) &&
(rbuf[i].pkt->users > 0)) {
gnrc_pktbuf_release(rbuf[i].pkt);
}
}
memset(rbuf, 0, sizeof(rbuf));
}
const gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_array(void)
{
return &rbuf[0];
}
#endif
void gnrc_sixlowpan_frag_rb_base_rm(gnrc_sixlowpan_frag_rb_base_t *entry)
{
while (entry->ints != NULL) {
gnrc_sixlowpan_rbuf_int_t *next = entry->ints->next;
gnrc_sixlowpan_frag_rb_int_t *next = entry->ints->next;
entry->ints->start = 0;
entry->ints->end = 0;
@ -38,19 +446,8 @@ void gnrc_sixlowpan_frag_rbuf_base_rm(gnrc_sixlowpan_rbuf_base_t *entry)
entry->datagram_size = 0;
}
void gnrc_sixlowpan_frag_rbuf_gc(void)
{
rbuf_gc();
}
void gnrc_sixlowpan_frag_rbuf_remove(gnrc_sixlowpan_rbuf_t *rbuf)
{
assert(rbuf != NULL);
rbuf_rm(rbuf);
}
void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf,
gnrc_netif_hdr_t *netif_hdr)
void gnrc_sixlowpan_frag_rb_dispatch_when_complete(gnrc_sixlowpan_frag_rb_t *rbuf,
gnrc_netif_hdr_t *netif_hdr)
{
assert(rbuf);
assert(netif_hdr);
@ -63,7 +460,7 @@ void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf
if (netif == NULL) {
DEBUG("6lo rbuf: error allocating netif header\n");
gnrc_pktbuf_release(rbuf->pkt);
gnrc_sixlowpan_frag_rbuf_remove(rbuf);
gnrc_sixlowpan_frag_rb_remove(rbuf);
return;
}
@ -78,7 +475,7 @@ void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf
new_netif_hdr->rssi = netif_hdr->rssi;
LL_APPEND(rbuf->pkt, netif);
gnrc_sixlowpan_dispatch_recv(rbuf->pkt, NULL, 0);
gnrc_sixlowpan_frag_rbuf_remove(rbuf);
gnrc_sixlowpan_frag_rb_remove(rbuf);
}
}

View File

@ -1,436 +0,0 @@
/*
* Copyright (C) 2015 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.
*/
/**
* @{
*
* @file
*/
#include <inttypes.h>
#include <stdbool.h>
#include "rbuf.h"
#include "net/ipv6.h"
#include "net/ipv6/hdr.h"
#include "net/gnrc.h"
#include "net/gnrc/sixlowpan.h"
#include "net/gnrc/sixlowpan/frag.h"
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
#include "net/gnrc/sixlowpan/frag/vrb.h"
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
#include "net/sixlowpan.h"
#include "thread.h"
#include "xtimer.h"
#include "utlist.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* estimated fragment payload size to determinate RBUF_INT_SIZE, default to
* MAC payload size - fragment header. */
#ifndef GNRC_SIXLOWPAN_FRAG_SIZE
/* assuming 64-bit source/destination address, source PAN ID omitted */
#define GNRC_SIXLOWPAN_FRAG_SIZE (104 - 5)
#endif
#ifndef RBUF_INT_SIZE
/* same as ((int) ceil((double) N / D)) */
#define DIV_CEIL(N, D) (((N) + (D) - 1) / (D))
#define RBUF_INT_SIZE (DIV_CEIL(IPV6_MIN_MTU, GNRC_SIXLOWPAN_FRAG_SIZE) * RBUF_SIZE)
#endif
static gnrc_sixlowpan_rbuf_int_t rbuf_int[RBUF_INT_SIZE];
static gnrc_sixlowpan_rbuf_t rbuf[RBUF_SIZE];
static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
static xtimer_t _gc_timer;
static msg_t _gc_timer_msg = { .type = GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF };
/* ------------------------------------
* internal function definitions
* ------------------------------------*/
/* checks whether start and end overlaps, but not identical to, given interval i */
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_rbuf_int_t *i,
uint16_t start, uint16_t end);
/* gets a free entry from interval buffer */
static gnrc_sixlowpan_rbuf_int_t *_rbuf_int_get_free(void);
/* update interval buffer of entry */
static bool _rbuf_update_ints(gnrc_sixlowpan_rbuf_base_t *entry,
uint16_t offset, size_t frag_size);
/* gets an entry identified by its tupel */
static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_len,
size_t size, uint16_t tag,
unsigned page);
/* internal add to repeat add when fragments overlapped */
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
size_t offset, unsigned page);
/* status codes for _rbuf_add() */
enum {
RBUF_ADD_SUCCESS,
RBUF_ADD_ERROR,
RBUF_ADD_REPEAT,
RBUF_ADD_DUPLICATE,
};
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
static gnrc_sixlowpan_frag_stats_t _stats;
gnrc_sixlowpan_frag_stats_t *gnrc_sixlowpan_frag_stats_get(void)
{
return &_stats;
}
#endif
static int _check_fragments(gnrc_sixlowpan_rbuf_base_t *entry,
size_t frag_size, size_t offset)
{
gnrc_sixlowpan_rbuf_int_t *ptr = entry->ints;
/* If the fragment overlaps another fragment and differs in either the size
* or the offset of the overlapped fragment, discards the datagram
* https://tools.ietf.org/html/rfc4944#section-5.3 */
while (ptr != NULL) {
if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) {
/* "A fresh reassembly may be commenced with the most recently
* received link fragment"
* https://tools.ietf.org/html/rfc4944#section-5.3 */
return RBUF_ADD_REPEAT;
}
/* End was already checked in overlap check */
if (ptr->start == offset) {
DEBUG("6lo rbuf: fragment already in reassembly buffer");
return RBUF_ADD_DUPLICATE;
}
ptr = ptr->next;
}
return RBUF_ADD_SUCCESS;
}
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
size_t offset, unsigned page)
{
if (_rbuf_add(netif_hdr, pkt, offset, page) == RBUF_ADD_REPEAT) {
_rbuf_add(netif_hdr, pkt, offset, page);
}
}
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
size_t offset, unsigned page)
{
gnrc_sixlowpan_rbuf_t *entry;
sixlowpan_frag_n_t *frag = pkt->data;
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
size_t frag_size;
/* check if provided offset is the same as in fragment */
assert(((((frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) ==
SIXLOWPAN_FRAG_1_DISP)) && (offset == 0)) ||
((((frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) ==
SIXLOWPAN_FRAG_N_DISP)) && (offset == (frag->offset * 8U))));
rbuf_gc();
entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK,
byteorder_ntohs(frag->tag), page);
if (entry == NULL) {
DEBUG("6lo rbuf: reassembly buffer full.\n");
gnrc_pktbuf_release(pkt);
return RBUF_ADD_ERROR;
}
/* dispatches in the first fragment are ignored */
if (offset == 0) {
frag_size = pkt->size - sizeof(sixlowpan_frag_t);
if (data[0] == SIXLOWPAN_UNCOMP) {
frag_size--;
}
}
else {
frag_size = pkt->size - sizeof(sixlowpan_frag_n_t);
data++; /* FRAGN header is one byte longer (offset) */
}
if ((offset + frag_size) > entry->super.datagram_size) {
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt);
gnrc_pktbuf_release(pkt);
rbuf_rm(entry);
return RBUF_ADD_ERROR;
}
switch (_check_fragments(&entry->super, frag_size, offset)) {
case RBUF_ADD_REPEAT:
DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt);
rbuf_rm(entry);
return RBUF_ADD_REPEAT;
case RBUF_ADD_DUPLICATE:
gnrc_pktbuf_release(pkt);
return RBUF_ADD_SUCCESS;
default:
break;
}
if (_rbuf_update_ints(&entry->super, offset, frag_size)) {
DEBUG("6lo rbuf: add fragment data\n");
entry->super.current_size += (uint16_t)frag_size;
if (offset == 0) {
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
if (sixlowpan_iphc_is(data)) {
gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt,
sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN);
if (frag_hdr == NULL) {
gnrc_pktbuf_release(entry->pkt);
gnrc_pktbuf_release(pkt);
rbuf_rm(entry);
return RBUF_ADD_ERROR;
}
gnrc_sixlowpan_iphc_recv(pkt, entry, 0);
return RBUF_ADD_SUCCESS;
}
else
#endif
if (data[0] == SIXLOWPAN_UNCOMP) {
data++;
}
}
memcpy(((uint8_t *)entry->pkt->data) + offset, data,
frag_size);
}
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(entry, netif_hdr);
gnrc_pktbuf_release(pkt);
return RBUF_ADD_SUCCESS;
}
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_rbuf_int_t *i,
uint16_t start, uint16_t end)
{
/* start and ends are both inclusive, so using <= for both */
return ((i->start <= end) && (start <= i->end)) && /* overlaps */
((start != i->start) || (end != i->end)); /* not identical */
}
static gnrc_sixlowpan_rbuf_int_t *_rbuf_int_get_free(void)
{
for (unsigned int i = 0; i < RBUF_INT_SIZE; i++) {
if (rbuf_int[i].end == 0) { /* start must be smaller than end anyways*/
return rbuf_int + i;
}
}
return NULL;
}
void rbuf_rm(gnrc_sixlowpan_rbuf_t *entry)
{
gnrc_sixlowpan_frag_rbuf_base_rm(&entry->super);
entry->pkt = NULL;
}
static bool _rbuf_update_ints(gnrc_sixlowpan_rbuf_base_t *entry,
uint16_t offset, size_t frag_size)
{
gnrc_sixlowpan_rbuf_int_t *new;
uint16_t end = (uint16_t)(offset + frag_size - 1);
new = _rbuf_int_get_free();
if (new == NULL) {
DEBUG("6lo rfrag: no space left in rbuf interval buffer.\n");
return false;
}
new->start = offset;
new->end = end;
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
new->start, new->end, gnrc_netif_addr_to_str(entry->src,
entry->src_len,
l2addr_str));
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst,
entry->dst_len,
l2addr_str),
entry->datagram_size, entry->tag);
LL_PREPEND(entry->ints, new);
return true;
}
void rbuf_gc(void)
{
uint32_t now_usec = xtimer_now_usec();
unsigned int i;
for (i = 0; i < RBUF_SIZE; i++) {
/* since pkt occupies pktbuf, aggressivly collect garbage */
if (!rbuf_entry_empty(&rbuf[i]) &&
((now_usec - rbuf[i].super.arrival) > RBUF_TIMEOUT)) {
DEBUG("6lo rfrag: entry (%s, ",
gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) timed out\n",
gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str),
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
gnrc_pktbuf_release(rbuf[i].pkt);
rbuf_rm(&(rbuf[i]));
}
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
gnrc_sixlowpan_frag_vrb_gc();
#endif
}
static inline void _set_rbuf_timeout(void)
{
xtimer_set_msg(&_gc_timer, RBUF_TIMEOUT, &_gc_timer_msg, sched_active_pid);
}
static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_len,
size_t size, uint16_t tag,
unsigned page)
{
gnrc_sixlowpan_rbuf_t *res = NULL, *oldest = NULL;
uint32_t now_usec = xtimer_now_usec();
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
/* check first if entry already available */
if ((rbuf[i].pkt != NULL) && (rbuf[i].super.datagram_size == size) &&
(rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) &&
(rbuf[i].super.dst_len == dst_len) &&
(memcmp(rbuf[i].super.src, src, src_len) == 0) &&
(memcmp(rbuf[i].super.dst, dst, dst_len) == 0)) {
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) found\n",
gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str),
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
rbuf[i].super.arrival = now_usec;
_set_rbuf_timeout();
return &(rbuf[i]);
}
/* if there is a free spot: remember it */
if ((res == NULL) && rbuf_entry_empty(&rbuf[i])) {
res = &(rbuf[i]);
}
/* remember oldest slot */
/* note that xtimer_now will overflow in ~1.2 hours */
if ((oldest == NULL) ||
(oldest->super.arrival - rbuf[i].super.arrival < UINT32_MAX / 2)) {
oldest = &(rbuf[i]);
}
}
/* entry not in buffer and no empty spot found */
if (res == NULL) {
assert(oldest != NULL);
/* if oldest is not empty, res must not be NULL (because otherwise
* oldest could have been picked as res) */
assert(!rbuf_entry_empty(oldest));
if (GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE ||
((now_usec - oldest->super.arrival) >
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
gnrc_pktbuf_release(oldest->pkt);
rbuf_rm(oldest);
res = oldest;
#if GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE && \
defined(MODULE_GNRC_SIXLOWPAN_FRAG_STATS)
_stats.rbuf_full++;
#endif
}
else {
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
_stats.rbuf_full++;
#endif
return NULL;
}
}
/* now we have an empty spot */
gnrc_nettype_t reass_type;
switch (page) {
/* use switch(page) to be extendable */
#ifdef MODULE_GNRC_IPV6
case 0U:
reass_type = GNRC_NETTYPE_IPV6;
break;
#endif
default:
reass_type = GNRC_NETTYPE_UNDEF;
}
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
if (res->pkt == NULL) {
DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n");
return NULL;
}
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later
* look-ups */
res->super.datagram_size = size;
res->super.arrival = now_usec;
memcpy(res->super.src, src, src_len);
memcpy(res->super.dst, dst, dst_len);
res->super.src_len = src_len;
res->super.dst_len = dst_len;
res->super.tag = tag;
res->super.current_size = 0;
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
gnrc_netif_addr_to_str(res->super.src, res->super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) created\n",
gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len,
l2addr_str), res->super.datagram_size,
res->super.tag);
_set_rbuf_timeout();
return res;
}
#ifdef TEST_SUITES
void rbuf_reset(void)
{
xtimer_remove(&_gc_timer);
memset(rbuf_int, 0, sizeof(rbuf_int));
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
if ((rbuf[i].pkt != NULL) &&
(rbuf[i].pkt->users > 0)) {
gnrc_pktbuf_release(rbuf[i].pkt);
}
}
memset(rbuf, 0, sizeof(rbuf));
}
const gnrc_sixlowpan_rbuf_t *rbuf_array(void)
{
return &rbuf[0];
}
#endif
/** @} */

View File

@ -1,116 +0,0 @@
/*
* Copyright (C) 2015 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_gnrc_sixlowpan_frag
* @{
*
* @file
* @internal
* @brief 6LoWPAN reassembly buffer
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef RBUF_H
#define RBUF_H
#include <inttypes.h>
#include <stdbool.h>
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/sixlowpan/config.h"
#include "net/gnrc/sixlowpan/frag/rb.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Legacy defines
* @{
*/
#define RBUF_SIZE (GNRC_SIXLOWPAN_FRAG_RBUF_SIZE)
#define RBUF_TIMEOUT (GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)
/** @} */
/**
* @brief Adds a new fragment to the reassembly buffer. If the packet is
* complete, dispatch the packet with the transmit information of
* the last fragment.
*
* @param[in] netif_hdr The interface header of the fragment, with
* gnrc_netif_hdr_t::if_pid and its source and
* destination address set.
* @param[in] frag The fragment to add.
* @param[in] offset The fragment's offset.
* @param[in] page Current 6Lo dispatch parsing page.
*
* @internal
*/
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *frag,
size_t offset, unsigned page);
/**
* @brief Checks timeouts and removes entries if necessary
*/
void rbuf_gc(void);
/**
* @brief Unsets a reassembly buffer entry (but does not free
* rbuf_t::super::pkt)
*
* This functions sets rbuf_t::super::pkt to NULL and removes all rbuf::ints.
*
* @param[in] rbuf A reassembly buffer entry
*
* @internal
*/
void rbuf_rm(gnrc_sixlowpan_rbuf_t *rbuf);
/**
* @brief Checks if a reassembly buffer entry is unset
*
* @param[in] rbuf A reassembly buffer entry
*
* @return true, if @p rbuf is empty (i.e. rbuf->super.pkt is NULL).
* @return false, if @p rbuf is in use.
*
* @internal
*/
static inline bool rbuf_entry_empty(const gnrc_sixlowpan_rbuf_t *rbuf) {
return (rbuf->pkt == NULL);
}
#if defined(TEST_SUITES) || defined(DOXYGEN)
/**
* @brief Resets the packet buffer to a clean state
*
* @note Only available when @ref TEST_SUITES is defined
*/
void rbuf_reset(void);
/**
* @brief Returns a pointer to the array representing the reassembly buffer.
*
* @note Only available when @ref TEST_SUITES is defined
*
* @return The first element of the reassembly buffer. `const`, so that write
* access is immediately spotted at compile time of tests. The `const`
* qualifier may however be discarded if required by the tests.
*/
const gnrc_sixlowpan_rbuf_t *rbuf_array(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* RBUF_H */
/** @} */

View File

@ -35,7 +35,7 @@ uint16_t gnrc_sixlowpan_frag_next_tag(void)
#endif /* !defined(MODULE_GNRC_SIXLOWPAN_FRAG) && defined(TEST_SUITES) */
gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add(
const gnrc_sixlowpan_rbuf_base_t *base,
const gnrc_sixlowpan_frag_rb_base_t *base,
gnrc_netif_t *out_netif, const uint8_t *out_dst, size_t out_dst_len)
{
gnrc_sixlowpan_frag_vrb_t *vrbe = NULL;

View File

@ -350,7 +350,7 @@ static void *_event_loop(void *args)
break;
case GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF:
DEBUG("6lo: garbage collect reassembly buffer event received\n");
gnrc_sixlowpan_frag_rbuf_gc();
gnrc_sixlowpan_frag_rb_gc();
break;
#endif

View File

@ -218,9 +218,9 @@ static size_t _iphc_nhc_udp_decode(gnrc_pktsnip_t *sixlo, size_t offset,
static inline void _recv_error_release(gnrc_pktsnip_t *sixlo,
gnrc_pktsnip_t *ipv6,
gnrc_sixlowpan_rbuf_t *rbuf) {
gnrc_sixlowpan_frag_rb_t *rbuf) {
if (rbuf != NULL) {
gnrc_sixlowpan_frag_rbuf_remove(rbuf);
gnrc_sixlowpan_frag_rb_remove(rbuf);
}
gnrc_pktbuf_release(ipv6);
gnrc_pktbuf_release(sixlo);
@ -238,7 +238,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
size_t payload_offset = SIXLOWPAN_IPHC_HDR_LEN;
size_t uncomp_hdr_len = sizeof(ipv6_hdr_t);
gnrc_sixlowpan_ctx_t *ctx = NULL;
gnrc_sixlowpan_rbuf_t *rbuf = rbuf_ptr;
gnrc_sixlowpan_frag_rb_t *rbuf = rbuf_ptr;
if (rbuf != NULL) {
ipv6 = rbuf->pkt;
@ -582,7 +582,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
sixlo->size - payload_offset);
if (rbuf != NULL) {
rbuf->super.current_size += (uncomp_hdr_len - payload_offset);
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif_hdr);
gnrc_sixlowpan_frag_rb_dispatch_when_complete(rbuf, netif_hdr);
}
else {
LL_DELETE(sixlo, netif);

View File

@ -12,7 +12,4 @@ DISABLE_MODULE += auto_init
# we don't need all this packet buffer space so reduce it a little
CFLAGS += -DTEST_SUITES -DGNRC_PKTBUF_SIZE=2048
# to be able to include gnrc_sixlowpan_frag-internal `rbuf.h`
INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/network_layer/sixlowpan/frag/
include $(RIOTBASE)/Makefile.include

View File

@ -23,7 +23,7 @@
#include "net/gnrc/pktbuf.h"
#include "net/gnrc/netreg.h"
#include "net/gnrc/sixlowpan/frag.h"
#include "rbuf.h"
#include "net/gnrc/sixlowpan/frag/rb.h"
#include "xtimer.h"
#define TEST_NETIF_HDR_SRC { 0xb3, 0x47, 0x60, 0x49, \
@ -34,7 +34,7 @@
#define TEST_TAG (0x690e)
#define TEST_PAGE (0)
#define TEST_RECEIVE_TIMEOUT (100U)
#define TEST_GC_TIMEOUT (RBUF_TIMEOUT + TEST_RECEIVE_TIMEOUT)
#define TEST_GC_TIMEOUT (GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US + TEST_RECEIVE_TIMEOUT)
/* test date taken from an experimental run (uncompressed ICMPv6 echo reply with
* 300 byte payload)*/
@ -184,7 +184,7 @@ static inline void _set_fragment_offset(void *frag, uint16_t offset)
static void _set_up(void)
{
rbuf_reset();
gnrc_sixlowpan_frag_rb_reset();
gnrc_pktbuf_init();
gnrc_netif_hdr_init(&_test_netif_hdr.hdr,
GNRC_NETIF_HDR_L2ADDR_MAX_LEN,
@ -205,19 +205,19 @@ static void _set_up(void)
_set_fragment_offset(_fragment4, TEST_FRAGMENT4_OFFSET);
}
static const gnrc_sixlowpan_rbuf_t *_first_non_empty_rbuf(void)
static const gnrc_sixlowpan_frag_rb_t *_first_non_empty_rbuf(void)
{
const gnrc_sixlowpan_rbuf_t *rbuf = rbuf_array();
const gnrc_sixlowpan_frag_rb_t *rbuf = gnrc_sixlowpan_frag_rb_array();
for (unsigned i = 0; i < RBUF_SIZE; i++) {
if (!rbuf_entry_empty(&rbuf[i])) {
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
if (!gnrc_sixlowpan_frag_rb_entry_empty(&rbuf[i])) {
return rbuf;
}
}
return NULL;
}
static void _test_entry(const gnrc_sixlowpan_rbuf_t *entry,
static void _test_entry(const gnrc_sixlowpan_frag_rb_t *entry,
unsigned exp_current_size,
unsigned exp_int_start, unsigned exp_int_end)
{
@ -242,7 +242,7 @@ static void _test_entry(const gnrc_sixlowpan_rbuf_t *entry,
TEST_ASSERT_EQUAL_INT(exp_int_end, entry->super.ints->end);
}
static void _check_pktbuf(const gnrc_sixlowpan_rbuf_t *entry)
static void _check_pktbuf(const gnrc_sixlowpan_frag_rb_t *entry)
{
if (entry != NULL) {
gnrc_pktbuf_release(entry->pkt);
@ -254,10 +254,11 @@ static void test_rbuf_add__success_first_fragment(void)
{
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
const gnrc_sixlowpan_rbuf_t *entry;
const gnrc_sixlowpan_frag_rb_t *entry;
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
entry = _first_non_empty_rbuf();
/* current_size must be the offset of fragment 2, not the size of
* fragment 1 (fragment dispatch was removed, IPHC was applied etc.). */
@ -270,10 +271,11 @@ static void test_rbuf_add__success_subsequent_fragment(void)
{
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment2, sizeof(_fragment2),
GNRC_NETTYPE_SIXLOWPAN);
const gnrc_sixlowpan_rbuf_t *entry;
const gnrc_sixlowpan_frag_rb_t *entry;
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT2_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT2_OFFSET, TEST_PAGE);
entry = _first_non_empty_rbuf();
/* current_size must be the offset of fragment 3, not the size of
* fragment 2 (fragment dispatch was removed, IPHC was applied etc.). */
@ -288,12 +290,14 @@ static void test_rbuf_add__success_duplicate_fragments(void)
GNRC_NETTYPE_SIXLOWPAN);
gnrc_pktsnip_t *pkt2 = gnrc_pktbuf_add(NULL, _fragment3, sizeof(_fragment3),
GNRC_NETTYPE_SIXLOWPAN);
const gnrc_sixlowpan_rbuf_t *entry;
const gnrc_sixlowpan_frag_rb_t *entry;
TEST_ASSERT_NOT_NULL(pkt1);
rbuf_add(&_test_netif_hdr.hdr, pkt1, TEST_FRAGMENT3_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt1,
TEST_FRAGMENT3_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt2);
rbuf_add(&_test_netif_hdr.hdr, pkt2, TEST_FRAGMENT3_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt2,
TEST_FRAGMENT3_OFFSET, TEST_PAGE);
entry = _first_non_empty_rbuf();
/* current_size must be the offset of fragment 4, not the size of
* fragment 3 (fragment dispatch was removed, IPHC was applied etc.). */
@ -322,13 +326,17 @@ static void test_rbuf_add__success_complete(void)
gnrc_netreg_register(TEST_DATAGRAM_NETTYPE, &reg);
/* Mixing up things. Order decided by fair dice-rolls ;-) */
TEST_ASSERT_NOT_NULL(pkt2);
rbuf_add(&_test_netif_hdr.hdr, pkt2, TEST_FRAGMENT2_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt2,
TEST_FRAGMENT2_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt4);
rbuf_add(&_test_netif_hdr.hdr, pkt4, TEST_FRAGMENT4_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt4,
TEST_FRAGMENT4_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt1);
rbuf_add(&_test_netif_hdr.hdr, pkt1, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt1,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt3);
rbuf_add(&_test_netif_hdr.hdr, pkt3, TEST_FRAGMENT3_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt3,
TEST_FRAGMENT3_OFFSET, TEST_PAGE);
TEST_ASSERT_MESSAGE(
xtimer_msg_receive_timeout(&msg, TEST_RECEIVE_TIMEOUT) >= 0,
"Receiving reassembled datagram timed out"
@ -349,27 +357,27 @@ static void test_rbuf_add__success_complete(void)
static void test_rbuf_add__full_rbuf(void)
{
gnrc_pktsnip_t *pkt;
const gnrc_sixlowpan_rbuf_t *rbuf;
const gnrc_sixlowpan_frag_rb_t *rbuf;
for (unsigned i = 0; i < RBUF_SIZE; i++) {
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET,
TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
_set_fragment_tag(_fragment1, TEST_TAG + i + 1);
/* pkt is released in rbuf_add() */
/* pkt is released in gnrc_sixlowpan_frag_rb_add() */
}
pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET,
TEST_PAGE);
rbuf = rbuf_array();
for (unsigned i = 0; i < RBUF_SIZE; i++) {
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
rbuf = gnrc_sixlowpan_frag_rb_array();
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
const gnrc_sixlowpan_frag_rb_t *entry = &rbuf[i];
TEST_ASSERT_MESSAGE(!rbuf_entry_empty(entry),
TEST_ASSERT_MESSAGE(!gnrc_sixlowpan_frag_rb_entry_empty(entry),
"Reassembly buffer entry unexpectedly empty");
TEST_ASSERT((sizeof(_fragment1) - sizeof(sixlowpan_frag_t)) <
entry->pkt->size);
@ -397,8 +405,8 @@ static void test_rbuf_add__too_big_fragment(void)
GNRC_NETTYPE_SIXLOWPAN);
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET,
TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
/* packet buffer is empty*/
TEST_ASSERT_NULL(_first_non_empty_rbuf());
_check_pktbuf(NULL);
@ -410,21 +418,22 @@ static void test_rbuf_add__overlap_lhs(void)
gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
gnrc_pktsnip_t *pkt2;
const gnrc_sixlowpan_rbuf_t *rbuf;
const gnrc_sixlowpan_frag_rb_t *rbuf;
unsigned rbuf_entries = 0;
_set_fragment_offset(_fragment2, pkt2_offset);
pkt2 = gnrc_pktbuf_add(NULL, _fragment2, sizeof(_fragment2),
GNRC_NETTYPE_SIXLOWPAN);
TEST_ASSERT_NOT_NULL(pkt1);
rbuf_add(&_test_netif_hdr.hdr, pkt1, TEST_FRAGMENT1_OFFSET,
TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt1,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt2);
rbuf_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset, TEST_PAGE);
rbuf = rbuf_array();
for (unsigned i = 0; i < RBUF_SIZE; i++) {
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
if (!rbuf_entry_empty(entry)) {
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset,
TEST_PAGE);
rbuf = gnrc_sixlowpan_frag_rb_array();
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
const gnrc_sixlowpan_frag_rb_t *entry = &rbuf[i];
if (!gnrc_sixlowpan_frag_rb_entry_empty(entry)) {
static const size_t pkt3_offset = TEST_FRAGMENT3_OFFSET - 8U - 1;
rbuf_entries++;
@ -452,23 +461,25 @@ static void test_rbuf_add__overlap_rhs(void)
gnrc_pktsnip_t *pkt2;
gnrc_pktsnip_t *pkt3 = gnrc_pktbuf_add(NULL, _fragment3, sizeof(_fragment3),
GNRC_NETTYPE_SIXLOWPAN);
const gnrc_sixlowpan_rbuf_t *rbuf;
const gnrc_sixlowpan_frag_rb_t *rbuf;
unsigned rbuf_entries = 0;
_set_fragment_offset(_fragment2, pkt2_offset);
pkt2 = gnrc_pktbuf_add(NULL, _fragment2, sizeof(_fragment2),
GNRC_NETTYPE_SIXLOWPAN);
TEST_ASSERT_NOT_NULL(pkt1);
rbuf_add(&_test_netif_hdr.hdr, pkt1, TEST_FRAGMENT1_OFFSET,
TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt1,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt3);
rbuf_add(&_test_netif_hdr.hdr, pkt3, TEST_FRAGMENT3_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt3,
TEST_FRAGMENT3_OFFSET, TEST_PAGE);
TEST_ASSERT_NOT_NULL(pkt2);
rbuf_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset, TEST_PAGE);
rbuf = rbuf_array();
for (unsigned i = 0; i < RBUF_SIZE; i++) {
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
if (!rbuf_entry_empty(entry)) {
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset,
TEST_PAGE);
rbuf = gnrc_sixlowpan_frag_rb_array();
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) {
const gnrc_sixlowpan_frag_rb_t *entry = &rbuf[i];
if (!gnrc_sixlowpan_frag_rb_entry_empty(entry)) {
static const size_t pkt3_offset = TEST_FRAGMENT3_OFFSET + 8U - 1U;
rbuf_entries++;
@ -490,7 +501,7 @@ static void test_rbuf_add__overlap_rhs(void)
static void test_rbuf_rm(void)
{
const gnrc_sixlowpan_rbuf_t *entry;
const gnrc_sixlowpan_frag_rb_t *entry;
test_rbuf_add__success_first_fragment();
entry = _first_non_empty_rbuf();
@ -498,7 +509,7 @@ static void test_rbuf_rm(void)
TEST_ASSERT_NOT_NULL(entry);
/* intentionally discarding const qualifier since we enter rbuf's internal
* context again */
rbuf_rm((gnrc_sixlowpan_rbuf_t *)entry);
gnrc_sixlowpan_frag_rb_remove((gnrc_sixlowpan_frag_rb_t *)entry);
/* reassembly buffer is now empty */
TEST_ASSERT_NULL(_first_non_empty_rbuf());
_check_pktbuf(NULL);
@ -508,16 +519,17 @@ static void test_rbuf_gc__manually(void)
{
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
gnrc_sixlowpan_rbuf_t *entry;
gnrc_sixlowpan_frag_rb_t *entry;
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
/* discarding const qualifier intentionally to override `arrival` */
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
entry = (gnrc_sixlowpan_frag_rb_t *)_first_non_empty_rbuf();
TEST_ASSERT_NOT_NULL(entry);
/* set arrival RBUF_TIMEOUT into the past */
entry->super.arrival -= RBUF_TIMEOUT;
rbuf_gc();
/* set arrival GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US into the past */
entry->super.arrival -= GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US;
gnrc_sixlowpan_frag_rb_gc();
/* reassembly buffer is now empty */
TEST_ASSERT_NULL(_first_non_empty_rbuf());
_check_pktbuf(NULL);
@ -528,19 +540,20 @@ static void test_rbuf_gc__timed(void)
msg_t msg;
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
GNRC_NETTYPE_SIXLOWPAN);
gnrc_sixlowpan_rbuf_t *entry;
gnrc_sixlowpan_frag_rb_t *entry;
TEST_ASSERT_NOT_NULL(pkt);
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
gnrc_sixlowpan_frag_rb_add(&_test_netif_hdr.hdr, pkt,
TEST_FRAGMENT1_OFFSET, TEST_PAGE);
/* discarding const qualifier intentionally to override `arrival` */
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
entry = (gnrc_sixlowpan_frag_rb_t *)_first_non_empty_rbuf();
TEST_ASSERT_NOT_NULL(entry);
TEST_ASSERT_MESSAGE(
xtimer_msg_receive_timeout(&msg, TEST_GC_TIMEOUT) >= 0,
"Waiting for GC timer timed out"
);
TEST_ASSERT_EQUAL_INT(GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF, msg.type);
rbuf_gc();
gnrc_sixlowpan_frag_rb_gc();
/* reassembly buffer is now empty */
TEST_ASSERT_NULL(_first_non_empty_rbuf());
_check_pktbuf(NULL);

View File

@ -45,13 +45,13 @@ static void set_up(void)
static void test_vrb_add__success(void)
{
static const gnrc_sixlowpan_rbuf_int_t interval = {
static const gnrc_sixlowpan_frag_rb_int_t interval = {
.next = NULL,
.start = 0,
.end = 116U,
};
static const gnrc_sixlowpan_rbuf_base_t base = {
.ints = (gnrc_sixlowpan_rbuf_int_t *)&interval,
static const gnrc_sixlowpan_frag_rb_base_t base = {
.ints = (gnrc_sixlowpan_frag_rb_int_t *)&interval,
.src = TEST_SRC,
.dst = TEST_DST,
.src_len = TEST_SRC_LEN,
@ -96,13 +96,13 @@ static void test_vrb_add__success(void)
static void test_vrb_add__duplicate(void)
{
static const gnrc_sixlowpan_rbuf_int_t interval = {
static const gnrc_sixlowpan_frag_rb_int_t interval = {
.next = NULL,
.start = 0,
.end = 116U,
};
static const gnrc_sixlowpan_rbuf_base_t base = {
.ints = (gnrc_sixlowpan_rbuf_int_t *)&interval,
static const gnrc_sixlowpan_frag_rb_base_t base = {
.ints = (gnrc_sixlowpan_frag_rb_int_t *)&interval,
.src = TEST_SRC,
.dst = TEST_DST,
.src_len = TEST_SRC_LEN,
@ -129,7 +129,7 @@ static void test_vrb_add__duplicate(void)
static void test_vrb_add__full(void)
{
gnrc_sixlowpan_rbuf_base_t base = {
gnrc_sixlowpan_frag_rb_base_t base = {
.ints = NULL,
.src = TEST_SRC,
.dst = TEST_DST,
@ -161,7 +161,7 @@ static void test_vrb_add__full(void)
static void test_vrb_get__empty(void)
{
static const gnrc_sixlowpan_rbuf_base_t base = {
static const gnrc_sixlowpan_frag_rb_base_t base = {
.ints = NULL,
.src = TEST_SRC,
.dst = TEST_DST,
@ -179,7 +179,7 @@ static void test_vrb_get__empty(void)
static void test_vrb_get__after_add(void)
{
static const gnrc_sixlowpan_rbuf_base_t base = {
static const gnrc_sixlowpan_frag_rb_base_t base = {
.ints = NULL,
.src = TEST_SRC,
.dst = TEST_DST,
@ -208,7 +208,7 @@ static void test_vrb_get__after_add(void)
static void test_vrb_rm(void)
{
static const gnrc_sixlowpan_rbuf_base_t base = {
static const gnrc_sixlowpan_frag_rb_base_t base = {
.ints = NULL,
.src = TEST_SRC,
.dst = TEST_DST,
@ -234,7 +234,7 @@ static void test_vrb_rm(void)
static void test_vrb_gc(void)
{
gnrc_sixlowpan_rbuf_base_t base = {
gnrc_sixlowpan_frag_rb_base_t base = {
.ints = NULL,
.src = TEST_SRC,
.dst = TEST_DST,