Skip to content

Commit

Permalink
Merge pull request #11000 from miri64/gnrc_sixlowpan_frag/new/vrb
Browse files Browse the repository at this point in the history
 gnrc_sixlowpan_frag: initial import of the VRB
  • Loading branch information
haukepetersen authored Aug 7, 2019
2 parents a06b84d + 1f1ff16 commit 02df6ab
Show file tree
Hide file tree
Showing 11 changed files with 654 additions and 2 deletions.
31 changes: 31 additions & 0 deletions sys/include/net/gnrc/sixlowpan/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
149 changes: 149 additions & 0 deletions sys/include/net/gnrc/sixlowpan/frag/vrb.h
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*/
#ifndef NET_GNRC_SIXLOWPAN_FRAG_VRB_H
#define NET_GNRC_SIXLOWPAN_FRAG_VRB_H

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>

#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 */
/** @} */
3 changes: 3 additions & 0 deletions sys/net/gnrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,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,
Expand Down
8 changes: 7 additions & 1 deletion sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/network_layer/sixlowpan/frag/vrb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE := gnrc_sixlowpan_frag_vrb

include $(RIOTBASE)/Makefile.base
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*/

#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

/** @} */
1 change: 1 addition & 0 deletions tests/unittests/tests-gnrc_sixlowpan_frag_vrb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
USEMODULE += gnrc_sixlowpan_frag_vrb
USEMODULE += xtimer
Loading

0 comments on commit 02df6ab

Please sign in to comment.