From 26a526eaee569c4e8a974a580b33ff3712783494 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 6 Feb 2019 14:48:13 +0100 Subject: [PATCH 1/3] gnrc_sixlowpan_frag: initial import of the VRB VRB = virtual reassembly buffer --- sys/include/net/gnrc/sixlowpan/config.h | 31 ++++ sys/include/net/gnrc/sixlowpan/frag/vrb.h | 149 ++++++++++++++++++ sys/net/gnrc/Makefile | 3 + .../sixlowpan/frag/gnrc_sixlowpan_frag.c | 2 +- .../network_layer/sixlowpan/frag/vrb/Makefile | 3 + .../frag/vrb/gnrc_sixlowpan_frag_vrb.c | 137 ++++++++++++++++ 6 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 sys/include/net/gnrc/sixlowpan/frag/vrb.h create mode 100644 sys/net/gnrc/network_layer/sixlowpan/frag/vrb/Makefile create mode 100644 sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c diff --git a/sys/include/net/gnrc/sixlowpan/config.h b/sys/include/net/gnrc/sixlowpan/config.h index d6cc3e44bbc1..84a825c135d5 100644 --- a/sys/include/net/gnrc/sixlowpan/config.h +++ b/sys/include/net/gnrc/sixlowpan/config.h @@ -115,6 +115,37 @@ extern "C" { #define GNRC_SIXLOWPAN_ND_AR_LTIME (15U) #endif +/** + * @brief Size of the virtual reassembly buffer + * + * @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01 + * + * @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_vrb` is not compiled in). + */ +#ifndef GNRC_SIXLOWPAN_FRAG_VRB_SIZE +#if defined(MODULE_GNRC_SIXLOWPAN_FRAG_VRB) || defined(DOXYGEN) +#define GNRC_SIXLOWPAN_FRAG_VRB_SIZE (16U) +#else /* defined(MODULE_GNRC_SIXLOWPAN_FRAG_VRB) || defined(DOXYGEN) */ +#define GNRC_SIXLOWPAN_FRAG_VRB_SIZE (0U) +#endif /* defined(MODULE_GNRC_SIXLOWPAN_FRAG_VRB) || defined(DOXYGEN) */ +#endif /* GNRC_SIXLOWPAN_FRAG_VRB_SIZE */ + +/** + * @brief Timeout for a VRB entry in microseconds + * + * @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01 + * + * @note Only applicable with + * [gnrc_sixlowpan_frag_vrb](@ref net_gnrc_sixlowpan_frag_vrb) module. + */ +#ifndef GNRC_SIXLOWPAN_FRAG_VRB_TIMEOUT_US +#define GNRC_SIXLOWPAN_FRAG_VRB_TIMEOUT_US (GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US) +#endif /* GNRC_SIXLOWPAN_FRAG_VRB_TIMEOUT_US */ + #ifdef __cplusplus } #endif diff --git a/sys/include/net/gnrc/sixlowpan/frag/vrb.h b/sys/include/net/gnrc/sixlowpan/frag/vrb.h new file mode 100644 index 000000000000..29409e5c87a6 --- /dev/null +++ b/sys/include/net/gnrc/sixlowpan/frag/vrb.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_gnrc_sixlowpan_frag_vrb Virtual reassembly buffer + * @ingroup net_gnrc_sixlowpan_frag + * @brief Virtual reassembly buffer + * @{ + * + * @file + * @brief Virtual reassembly buffer definitions + * @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_SIXLOWPAN_FRAG_VRB_H +#define NET_GNRC_SIXLOWPAN_FRAG_VRB_H + +#include +#include +#include + +#include "net/gnrc/netif.h" +#include "net/gnrc/sixlowpan/config.h" +#include "net/gnrc/sixlowpan/frag.h" +#include "timex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Representation of the virtual reassembly buffer entry + */ +typedef struct { + gnrc_sixlowpan_rbuf_base_t super; /**< base type */ + + /** + * @brief Link-layer destination address to which the fragments are + * supposed to be forwarded to + */ + uint8_t out_dst[IEEE802154_LONG_ADDRESS_LEN]; + /** + * @brief Outgoing interface to gnrc_sixlowpan_frag_vrb_t::out_dst + */ + gnrc_netif_t *out_netif; + /** + * @brief Outgoing tag to gnrc_sixlowpan_frag_vrb_t::out_dst + */ + uint16_t out_tag; + /** + * @brief Length of gnrc_sixlowpan_frag_vrb_t::out_dst + */ + uint8_t out_dst_len; +} gnrc_sixlowpan_frag_vrb_t; + +/** + * @brief Adds a new reassembly buffer entry + * + * @param[in] base Base data of the datagram. Must not be `NULL`. + * @param[in] out_netif Network interface that is out-going to @p out_dst. + * @param[in] out_dst Link-layer destination address to which to forward + * fragments identified by @p base. Must not be `NULL`. + * @param[in] out_dst_len Length of @p out_dst. Must be greater than 0. + * + * @pre `base != NULL` + * @pre `out_dst != NULL` + * @pre `out_dst_len > 0` + * + * @return A new VRB entry. + * @return NULL, if VRB is full. + */ +gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add( + const gnrc_sixlowpan_rbuf_base_t *base, + gnrc_netif_t *out_netif, const uint8_t *out_dst, size_t out_dst_len); + +/** + * @brief Checks timeouts and removes entries if necessary + */ +void gnrc_sixlowpan_frag_vrb_gc(void); + +/** + * @brief Gets a VRB entry + * + * @param[in] src Link-layer source address of the original fragment. + * @param[in] src_len Length of @p src. + * @param[in] dst Link-layer destination address of the original + * fragment. + * @param[in] dst_len Length of @p dst. + * @param[in] datagram_size The original fragment's datagram size. + * @param[in] src_tag Tag of the original fragment. + * + * @return The VRB entry identified by the given parameters. + * @return NULL, if there is no entry in the VRB that could be identified + * by the given parameters. + */ +gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get( + const uint8_t *src, size_t src_len, + const uint8_t *dst, size_t dst_len, + size_t datagram_size, unsigned src_tag); + +/** + * @brief Removes an entry from the VRB + * + * @param[in] vrb A VRB entry + */ +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); +#elif defined(TEST_SUITES) + /* for testing just zero datagram_size */ + vrb->super.datagram_size = 0; +#endif /* MODULE_GNRC_SIXLOWPAN_FRAG */ +} + +/** + * @brief Determines if a VRB entry is empty + * + * @param[in] vrb A VRB entry + * + * @return true, if @p vrb entry is empty. + * @return false, if @p vrb entry is not empty. + */ +static inline bool gnrc_sixlowpan_frag_vrb_entry_empty(gnrc_sixlowpan_frag_vrb_t *vrb) +{ + return (vrb->super.datagram_size == 0); +} + +#if defined(TEST_SUITES) || defined(DOXYGEN) +/** + * @brief Resets the VRB to a clean state + * + * @note Only available when @ref TEST_SUITES is defined + */ +void gnrc_sixlowpan_frag_vrb_reset(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_SIXLOWPAN_FRAG_VRB_H */ +/** @} */ diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index 349b8ca4a9c4..434f234ee359 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -88,6 +88,9 @@ endif ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE))) DIRS += network_layer/sixlowpan/frag endif +ifneq (,$(filter gnrc_sixlowpan_frag_vrb,$(USEMODULE))) + DIRS += network_layer/sixlowpan/frag/vrb +endif ifneq (,$(filter gnrc_sixlowpan_iphc,$(USEMODULE))) DIRS += network_layer/sixlowpan/iphc endif diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c b/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c index 496c6610070d..8d552bedc81e 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c @@ -358,7 +358,7 @@ void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf { assert(rbuf); assert(netif_hdr); - if (rbuf->super.current_size == rbuf->pkt->size) { + if (rbuf->super.current_size == rbuf->super.datagram_size) { gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(rbuf->super.src, rbuf->super.src_len, rbuf->super.dst, diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/Makefile b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/Makefile new file mode 100644 index 000000000000..e884112e3b99 --- /dev/null +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/Makefile @@ -0,0 +1,3 @@ +MODULE := gnrc_sixlowpan_frag_vrb + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c new file mode 100644 index 000000000000..18ddf349d0b7 --- /dev/null +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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 + * @author Martine Lenders + */ + +#include "net/ieee802154.h" +#include "xtimer.h" + +#include "net/gnrc/sixlowpan/frag/vrb.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static gnrc_sixlowpan_frag_vrb_t _vrb[GNRC_SIXLOWPAN_FRAG_VRB_SIZE]; +static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN]; + +#if !defined(MODULE_GNRC_SIXLOWPAN_FRAG) && defined(TEST_SUITES) +/* mock for e.g. testing */ +uint16_t tag = 0; + +uint16_t gnrc_sixlowpan_frag_next_tag(void) +{ + return tag++; +} +#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, + gnrc_netif_t *out_netif, const uint8_t *out_dst, size_t out_dst_len) +{ + gnrc_sixlowpan_frag_vrb_t *vrbe = NULL; + + assert(base != NULL); + assert(out_netif != NULL); + assert(out_dst != NULL); + assert(out_dst_len > 0); + for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) { + gnrc_sixlowpan_frag_vrb_t *ptr = &_vrb[i]; + + if (gnrc_sixlowpan_frag_vrb_entry_empty(ptr) || + (memcmp(&ptr->super, base, sizeof(ptr->super)) == 0)) { + vrbe = ptr; + if (gnrc_sixlowpan_frag_vrb_entry_empty(vrbe)) { + vrbe->super = *base; + vrbe->out_netif = out_netif; + memcpy(vrbe->out_dst, out_dst, out_dst_len); + vrbe->out_tag = gnrc_sixlowpan_frag_next_tag(); + vrbe->out_dst_len = out_dst_len; + DEBUG("6lo vrb: creating entry (%s, ", + gnrc_netif_addr_to_str(vrbe->super.src, + vrbe->super.src_len, + l2addr_str)); + DEBUG("%s, %u, %u) => ", + gnrc_netif_addr_to_str(vrbe->super.dst, + vrbe->super.dst_len, + l2addr_str), + (unsigned)vrbe->super.datagram_size, vrbe->super.tag); + DEBUG("(%s, %u)\n", + gnrc_netif_addr_to_str(vrbe->out_dst, + vrbe->out_dst_len, + l2addr_str), vrbe->out_tag); + } + break; + } + } + return vrbe; +} + +gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get( + const uint8_t *src, size_t src_len, + const uint8_t *dst, size_t dst_len, + size_t datagram_size, unsigned src_tag) +{ + DEBUG("6lo vrb: trying to get entry for (%s, ", + gnrc_netif_addr_to_str(src, src_len, l2addr_str)); + DEBUG("%s, %u, %u)\n", + gnrc_netif_addr_to_str(dst, dst_len, l2addr_str), + (unsigned)datagram_size, src_tag); + for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) { + gnrc_sixlowpan_frag_vrb_t *vrbe = &_vrb[i]; + + if ((vrbe->super.datagram_size == datagram_size) && + (vrbe->super.tag == src_tag) && + (vrbe->super.src_len == src_len) && + (vrbe->super.dst_len == dst_len) && + (memcmp(vrbe->super.src, src, src_len) == 0) && + (memcmp(vrbe->super.dst, dst, dst_len) == 0)) { + DEBUG("6lo vrb: got VRB to (%s, %u)\n", + gnrc_netif_addr_to_str(vrbe->out_dst, + vrbe->out_dst_len, + l2addr_str), vrbe->out_tag); + return vrbe; + } + } + DEBUG("6lo vrb: no entry found\n"); + return NULL; +} + +void gnrc_sixlowpan_frag_vrb_gc(void) +{ + uint32_t now_usec = xtimer_now_usec(); + + for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) { + if (!gnrc_sixlowpan_frag_vrb_entry_empty(&_vrb[i]) && + (now_usec - _vrb[i].super.arrival) > GNRC_SIXLOWPAN_FRAG_VRB_TIMEOUT_US) { + DEBUG("6lo vrb: entry (%s, ", + gnrc_netif_addr_to_str(_vrb[i].super.src, + _vrb[i].super.src_len, + l2addr_str)); + DEBUG("%s, %u, %u) timed out\n", + gnrc_netif_addr_to_str(_vrb[i].super.dst, + _vrb[i].super.dst_len, + l2addr_str), + (unsigned)_vrb[i].super.datagram_size, _vrb[i].super.tag); + gnrc_sixlowpan_frag_vrb_rm(&_vrb[i]); + } + } +} + +#ifdef TEST_SUITES +void gnrc_sixlowpan_frag_vrb_reset(void) +{ + memset(_vrb, 0, sizeof(_vrb)); +} +#endif + +/** @} */ From 2cd46e57abe249e9b1d32de38929db5a525d89ef Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 13 Feb 2019 17:08:29 +0100 Subject: [PATCH 2/3] tests: add unittests for gnrc_sixlowpan_frag_vrb --- .../tests-gnrc_sixlowpan_frag_vrb/Makefile | 1 + .../Makefile.include | 2 + .../tests-gnrc_sixlowpan_frag_vrb.c | 283 ++++++++++++++++++ .../tests-gnrc_sixlowpan_frag_vrb.h | 37 +++ 4 files changed, 323 insertions(+) create mode 100644 tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile create mode 100644 tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile.include create mode 100644 tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.c create mode 100644 tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.h diff --git a/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile.include b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile.include new file mode 100644 index 000000000000..6b1aeee049d6 --- /dev/null +++ b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile.include @@ -0,0 +1,2 @@ +USEMODULE += gnrc_sixlowpan_frag_vrb +USEMODULE += xtimer diff --git a/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.c b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.c new file mode 100644 index 000000000000..6b2feb4de181 --- /dev/null +++ b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.c @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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 tests + * @{ + * + * @author Martine Lenders + * @file + */ +#include +#include + +#include "embUnit/embUnit.h" + +#include "net/gnrc/sixlowpan/frag/vrb.h" +#include "xtimer.h" + +#include "tests-gnrc_sixlowpan_frag_vrb.h" + +#define TEST_TAG_INITIAL (6U) +#define TEST_SRC { 0x68, 0xDF, 0x2A, 0x5B, 0x21, 0x7D, 0xEE, 0xE5 } +#define TEST_DST { 0xB1, 0x5B, 0x0F, 0x2F, 0x63, 0x76, 0x28, 0x39 } +#define TEST_OUT_DST { 0x13, 0xF8, 0xEB, 0x75, 0x46, 0x60, 0x7C, 0x60 } +#define TEST_SRC_LEN (8U) +#define TEST_DST_LEN (8U) +#define TEST_TAG (26U) + +extern uint16_t tag; + +/* The interface is not used for anything by the VRB (it just is kept as a + * reference for forwarding) so an uninitialized one is enough */ +static gnrc_netif_t _dummy_netif; + +static void set_up(void) +{ + gnrc_sixlowpan_frag_vrb_reset(); + tag = 0; +} + +static void test_vrb_add__success(void) +{ + static const gnrc_sixlowpan_rbuf_int_t interval = { + .next = NULL, + .start = 0, + .end = 116U, + }; + static const gnrc_sixlowpan_rbuf_base_t base = { + .ints = (gnrc_sixlowpan_rbuf_int_t *)&interval, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + gnrc_sixlowpan_frag_vrb_t *res; + + tag = TEST_TAG_INITIAL; + TEST_ASSERT_NOT_NULL((res = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + TEST_ASSERT_NOT_NULL(res->super.ints); + TEST_ASSERT_NULL(res->super.ints->next); + /* make sure base and res->super are distinct*/ + TEST_ASSERT((&base) != (&res->super)); + /* but that the values are the same */ + TEST_ASSERT_EQUAL_INT(interval.start, res->super.ints->start); + TEST_ASSERT_EQUAL_INT(interval.end, res->super.ints->end); + TEST_ASSERT_EQUAL_INT(base.src_len, res->super.src_len); + TEST_ASSERT_MESSAGE(memcmp(base.src, res->super.src, TEST_SRC_LEN) == 0, + "TEST_SRC != res->super.src"); + TEST_ASSERT_EQUAL_INT(base.dst_len, res->super.src_len); + TEST_ASSERT_MESSAGE(memcmp(base.dst, res->super.dst, TEST_DST_LEN) == 0, + "TEST_DST != res->super.dst"); + TEST_ASSERT_EQUAL_INT(base.tag, res->super.tag); + TEST_ASSERT_EQUAL_INT(base.datagram_size, res->super.datagram_size); + TEST_ASSERT_EQUAL_INT(base.current_size, res->super.current_size); + TEST_ASSERT_EQUAL_INT(base.arrival, res->super.arrival); + TEST_ASSERT((&_dummy_netif) == res->out_netif); + TEST_ASSERT_EQUAL_INT(sizeof(out_dst), res->out_dst_len); + TEST_ASSERT_MESSAGE(memcmp(out_dst, res->out_dst, sizeof(out_dst)) == 0, + "TEST_DST != res->super.dst"); + TEST_ASSERT_EQUAL_INT(TEST_TAG_INITIAL, res->out_tag); + TEST_ASSERT(TEST_TAG_INITIAL != tag); +} + +static void test_vrb_add__duplicate(void) +{ + static const gnrc_sixlowpan_rbuf_int_t interval = { + .next = NULL, + .start = 0, + .end = 116U, + }; + static const gnrc_sixlowpan_rbuf_base_t base = { + .ints = (gnrc_sixlowpan_rbuf_int_t *)&interval, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + gnrc_sixlowpan_frag_vrb_t *res1, *res2; + + tag = TEST_TAG_INITIAL; + TEST_ASSERT_NOT_NULL((res1 = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + TEST_ASSERT_NOT_NULL((res2 = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + TEST_ASSERT(res1 == res2); +} + +static void test_vrb_add__full(void) +{ + gnrc_sixlowpan_rbuf_base_t base = { + .ints = NULL, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + + /* fill up VRB */ + for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) { + TEST_ASSERT_NOT_NULL(gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst))); + base.tag++; + } + /* another entry will not fit */ + TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_add(&base, &_dummy_netif, + out_dst, sizeof(out_dst))); + /* check if it really isn't in the VRB */ + TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_get(base.src, base.src_len, + base.dst, base.dst_len, + base.datagram_size, base.tag)); +} + +static void test_vrb_get__empty(void) +{ + static const gnrc_sixlowpan_rbuf_base_t base = { + .ints = NULL, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_get(base.src, base.src_len, + base.dst, base.dst_len, + base.datagram_size, base.tag)); +} + +static void test_vrb_get__after_add(void) +{ + static const gnrc_sixlowpan_rbuf_base_t base = { + .ints = NULL, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + gnrc_sixlowpan_frag_vrb_t *res1, *res2; + + TEST_ASSERT_NOT_NULL((res1 = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + TEST_ASSERT_NOT_NULL((res2 = gnrc_sixlowpan_frag_vrb_get(base.src, + base.src_len, + base.dst, + base.dst_len, + base.datagram_size, + base.tag))); + TEST_ASSERT(res1 == res2); +} + +static void test_vrb_rm(void) +{ + static const gnrc_sixlowpan_rbuf_base_t base = { + .ints = NULL, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = 1742197326U, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + gnrc_sixlowpan_frag_vrb_t *res; + + TEST_ASSERT_NOT_NULL((res = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + gnrc_sixlowpan_frag_vrb_rm(res); + TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_get(base.src, base.src_len, + base.dst, base.dst_len, + base.datagram_size, base.tag)); +} + +static void test_vrb_gc(void) +{ + gnrc_sixlowpan_rbuf_base_t base = { + .ints = NULL, + .src = TEST_SRC, + .dst = TEST_DST, + .src_len = TEST_SRC_LEN, + .dst_len = TEST_DST_LEN, + .tag = TEST_TAG, + .datagram_size = 1156U, + .current_size = 116U, + .arrival = xtimer_now_usec() - GNRC_SIXLOWPAN_FRAG_VRB_TIMEOUT_US - 1000, + }; + static uint8_t out_dst[] = TEST_OUT_DST; + gnrc_sixlowpan_frag_vrb_t *res; + + TEST_ASSERT_NOT_NULL((res = gnrc_sixlowpan_frag_vrb_add(&base, + &_dummy_netif, + out_dst, + sizeof(out_dst)))); + gnrc_sixlowpan_frag_vrb_gc(); + TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_get(base.src, base.src_len, + base.dst, base.dst_len, + base.datagram_size, base.tag)); +} + +static Test *tests_gnrc_sixlowpan_frag_vrb_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_vrb_add__success), + new_TestFixture(test_vrb_add__duplicate), + new_TestFixture(test_vrb_add__full), + new_TestFixture(test_vrb_get__empty), + new_TestFixture(test_vrb_get__after_add), + new_TestFixture(test_vrb_rm), + new_TestFixture(test_vrb_gc), + }; + + EMB_UNIT_TESTCALLER(vrb_tests, set_up, NULL, fixtures); + + return (Test *)&vrb_tests; +} + +void tests_gnrc_sixlowpan_frag_vrb(void) +{ + xtimer_init(); + TESTS_RUN(tests_gnrc_sixlowpan_frag_vrb_tests()); +} +/** @} */ diff --git a/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.h b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.h new file mode 100644 index 000000000000..3b845bbde9c2 --- /dev/null +++ b/tests/unittests/tests-gnrc_sixlowpan_frag_vrb/tests-gnrc_sixlowpan_frag_vrb.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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 unittests + * @{ + * + * @file + * @brief Unittests for the `gnrc_sixlowpan_frag_vrb` module + * + * @author Martine Lenders + */ +#ifndef TESTS_GNRC_SIXLOWPAN_FRAG_VRB_H +#define TESTS_GNRC_SIXLOWPAN_FRAG_VRB_H + +#include "embUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The entry point of this test suite. + */ +void tests_gnrc_sixlowpan_frag_vrb(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TESTS_GNRC_SIXLOWPAN_FRAG_VRB_H */ +/** @} */ From 1f1ff16e3c3d1b9d1dfabb39d10681d44bb272fd Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 26 Feb 2019 11:19:04 +0100 Subject: [PATCH 3/3] gnrc_sixlowpan_frag: include VRB in normal GC --- sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c index 394c6c5252ef..9ca95f9375dd 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c @@ -21,6 +21,9 @@ #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" @@ -264,7 +267,7 @@ void rbuf_gc(void) for (i = 0; i < RBUF_SIZE; i++) { /* since pkt occupies pktbuf, aggressivly collect garbage */ - if ((rbuf[i].pkt != NULL) && + 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, @@ -280,6 +283,9 @@ void rbuf_gc(void) rbuf_rm(&(rbuf[i])); } } +#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB + gnrc_sixlowpan_frag_vrb_gc(); +#endif } static inline void _set_rbuf_timeout(void)