mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #12648 from miri64/gnrc_sixlowpan_frag_sfr/feat/initial
gnrc_sixlowpan_frag: initial import of Selective Fragment Recovery
This commit is contained in:
commit
41a844f323
@ -56,6 +56,7 @@ PSEUDOMODULES += gnrc_sixloenc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_border_router_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_frag_hint
|
||||
PSEUDOMODULES += gnrc_sixlowpan_frag_sfr_stats
|
||||
PSEUDOMODULES += gnrc_sixlowpan_iphc_nhc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
||||
PSEUDOMODULES += gnrc_sixlowpan_router_default
|
||||
|
@ -280,20 +280,26 @@ endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib_6ln
|
||||
USEMODULE += gnrc_sixlowpan
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
ifeq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
endif
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_router_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib_6lr
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
ifeq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
endif
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_border_router_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_nib_6lbr
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
ifeq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
endif
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
endif
|
||||
|
||||
@ -318,6 +324,19 @@ ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan
|
||||
USEMODULE += gnrc_sixlowpan_frag_fb
|
||||
USEMODULE += gnrc_sixlowpan_frag_vrb
|
||||
USEMODULE += gnrc_sixlowpan_frag_rb
|
||||
USEMODULE += evtimer
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_sfr_stats,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sixlowpan_frag_sfr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_vrb,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += gnrc_sixlowpan_frag_fb
|
||||
|
@ -18,12 +18,34 @@
|
||||
#ifndef NET_GNRC_NETIF_6LO_H
|
||||
#define NET_GNRC_NETIF_6LO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Local 6LoWPAN capability flags
|
||||
* @anchor net_gnrc_netif_6lo_local_flags
|
||||
* @see gnrc_netif_6lo_t::local_flags
|
||||
*
|
||||
* Like the the capability flags in the [6LoWPAN Capability Indication Option
|
||||
* (6CIO)](https://tools.ietf.org/html/rfc7400#section-3.3) are less about
|
||||
* hardware capabilities than about the implementation status within the
|
||||
* network. For the flags in this group it is currently undefined how to
|
||||
* exchange the capabilities between nodes, but they might be added to the 6CIO
|
||||
* at a later point. Once the 6CIO is implemented in GNRC and the flag is
|
||||
* supported by it, the corresponding flag in these local flags can be removed.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Selective Fragment Recovery enabled
|
||||
* @see [RFC 8931](https://tools.ietf.org/html/rfc8931)
|
||||
*/
|
||||
#define GNRC_NETIF_6LO_LOCAL_FLAGS_SFR (0x01)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief 6Lo component of @ref gnrc_netif_t
|
||||
*/
|
||||
@ -35,6 +57,15 @@ typedef struct {
|
||||
* @ref net_gnrc_sixlowpan_frag "gnrc_sixlowpan_frag".
|
||||
*/
|
||||
uint16_t max_frag_size;
|
||||
/**
|
||||
* @brief 6LoWPAN capability flags beyond the ones advertised in
|
||||
* [6LoWPAN Capability Indication Option
|
||||
* (6CIO)](https://tools.ietf.org/html/rfc7400#section-3.3)
|
||||
*
|
||||
* @see [Local 6LoWPAN capability flags](@ref
|
||||
* net_gnrc_netif_6lo_local_flags)
|
||||
*/
|
||||
uint8_t local_flags;
|
||||
} gnrc_netif_6lo_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -63,7 +63,11 @@ extern "C" {
|
||||
* [gnrc_sixlowpan_frag_fb](@ref net_gnrc_sixlowpan_frag_fb) module
|
||||
*/
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_FRAG_FB_SIZE
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
#define CONFIG_GNRC_SIXLOWPAN_FRAG_FB_SIZE (4U)
|
||||
#else /* defined(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
#define CONFIG_GNRC_SIXLOWPAN_FRAG_FB_SIZE (1U)
|
||||
#endif /* defined(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -163,16 +167,16 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* @name Selective fragment recovery configuration
|
||||
* @see [draft-ietf-6lo-fragment-recovery-07, section 7.1]
|
||||
* (https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-07#section-7.1)
|
||||
* @see [RFC 8931, section 7.1]
|
||||
* (https://tools.ietf.org/html/rfc8931#section-7.1)
|
||||
* @note Only applicable with gnrc_sixlowpan_frag_sfr module
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Default minimum value for fragment size (MinFragmentSize)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE (96U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE 96U
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -182,32 +186,37 @@ extern "C" {
|
||||
* the chances of buffer bloat and transmission loss. The value must be less
|
||||
* than 512 if the unit is defined for the PHY layer is the octet.
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE (112U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE 112U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default value for fragment size that the sender should use to start
|
||||
* with (OptFragmentSize)
|
||||
*
|
||||
* @pre Must be inclusively between
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE and
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE (GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE CONFIG_GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Indicates whether the sender should react to ECN (UseECN)
|
||||
*
|
||||
* When the sender reacts to ECN its window size will vary between @ref
|
||||
* GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE and @ref GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE.
|
||||
* When the sender reacts to Explicit Congestion Notification (ECN) its window
|
||||
* size will vary between @ref CONFIG_GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE and @ref
|
||||
* CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_SFR_USE_ECN (0U)
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_USE_ECN 0U
|
||||
|
||||
/**
|
||||
* @brief Default minimum value of window size that the sender can use
|
||||
* (MinWindowSize)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE (1U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE 1U
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -216,16 +225,20 @@ extern "C" {
|
||||
*
|
||||
* @warning **Must** be lesser than 32.
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE (16U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE 16U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default value of window size that the sender should start with
|
||||
* (OptWindowSize)
|
||||
*
|
||||
* @pre Must be inclusively between
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE and
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE
|
||||
#define GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE (16U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE 16U
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -240,51 +253,53 @@ extern "C" {
|
||||
* ratio of air and memory in intermediate nodes that a particular datagram will
|
||||
* use.
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US
|
||||
#define GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US (100U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US 100U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default minimum amount of time in milliseconds a node should wait
|
||||
* for an RFRAG Acknowledgment before it takes a next action
|
||||
* @brief Minimum RFRAG-ACK timeout in msec before a node takes a next action
|
||||
* (MinARQTimeOut)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS
|
||||
#define GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS (350U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS 350U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default maximum amount of time in milliseconds a node should wait
|
||||
* for an RFRAG Acknowledgment before it takes a next action
|
||||
* @brief Maximum RFRAG-ACK timeout in msec before a node takes a next action
|
||||
* (MaxARQTimeOut)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
#define GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS (700U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS 700U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default starting point of the value of the amount of time in
|
||||
* milliseconds that a sender should wait for an RFRAG Acknowledgment
|
||||
* before it takes a next action (OptARQTimeOut)
|
||||
* @brief Default RFRAG-ACK timeout in msec before a node takes a next action
|
||||
* (OptARQTimeOut)
|
||||
*
|
||||
* @pre Must be inclusively between
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS and
|
||||
* @ref CONFIG_GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS
|
||||
#define GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS (GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS \
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The maximum number of retries for a particular fragment
|
||||
* (MaxFragRetries)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_FRAG_RETRIES
|
||||
#define GNRC_SIXLOWPAN_SFR_FRAG_RETRIES (2U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_FRAG_RETRIES
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_FRAG_RETRIES 2U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The maximum number of retries from scratch for a particular
|
||||
* datagram (MaxDatagramRetries)
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_SFR_DG_RETRIES
|
||||
#define GNRC_SIXLOWPAN_SFR_DG_RETRIES (0U)
|
||||
#ifndef CONFIG_GNRC_SIXLOWPAN_SFR_DG_RETRIES
|
||||
#define CONFIG_GNRC_SIXLOWPAN_SFR_DG_RETRIES 0U
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
#include "net/gnrc/sixlowpan/frag/hint.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
#include "net/gnrc/sixlowpan/frag/sfr_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -43,10 +44,22 @@ extern "C" {
|
||||
*/
|
||||
typedef struct {
|
||||
gnrc_pktsnip_t *pkt; /**< Pointer to the IPv6 packet to be fragmented */
|
||||
uint16_t datagram_size; /**< Length of just the (uncompressed) IPv6 packet to be fragmented */
|
||||
/**
|
||||
* @brief Length of just the (uncompressed) IPv6 packet to be fragmented
|
||||
*
|
||||
* @note With @ref net_gnrc_sixlowpan_frag_sfr this denotes the
|
||||
* _compressed form_ of the datagram
|
||||
*/
|
||||
uint16_t datagram_size;
|
||||
uint16_t tag; /**< Tag used for the fragment */
|
||||
uint16_t offset; /**< Offset of the Nth fragment from the beginning of the
|
||||
* payload datagram */
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
/**
|
||||
* @brief Extension for selective fragment recovery.
|
||||
*/
|
||||
gnrc_sixlowpan_frag_sfr_fb_t sfr;
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
/**
|
||||
* @brief Hint for the size (smaller than link-layer PDU) for the next
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include "net/gnrc/netif/hdr.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
#include "net/sixlowpan/sfr.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
|
||||
#include "net/gnrc/sixlowpan/config.h"
|
||||
|
||||
@ -96,6 +99,17 @@ typedef struct {
|
||||
* @brief The reassembled packet in the packet buffer
|
||||
*/
|
||||
gnrc_pktsnip_t *pkt;
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
/**
|
||||
* @brief Bitmap for received fragments
|
||||
*
|
||||
* @note Only available with module `gnrc_sixlowpan_frag_sfr` compiled
|
||||
* in.
|
||||
*/
|
||||
BITFIELD(received, SIXLOWPAN_SFR_ACK_BITMAP_SIZE);
|
||||
int8_t offset_diff; /**< offset change due to
|
||||
* recompression */
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
} gnrc_sixlowpan_frag_rb_t;
|
||||
|
||||
/**
|
||||
@ -118,6 +132,29 @@ gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_add(gnrc_netif_hdr_t *netif_hdr
|
||||
gnrc_pktsnip_t *frag,
|
||||
size_t offset, unsigned page);
|
||||
|
||||
/**
|
||||
* @brief Gets a reassembly buffer entry with a given link-layer address
|
||||
* pair and tag.
|
||||
*
|
||||
* @pre `netif_hdr != NULL`
|
||||
*
|
||||
* @param[in] netif_hdr An interface header to provide the (source, destination)
|
||||
* link-layer address pair. Must not be NULL.
|
||||
* @param[in] tag Tag to search for.
|
||||
*
|
||||
* @note datagram_size is not a search parameter as the primary use case
|
||||
* for this function is [Selective Fragment Recovery]
|
||||
* (https://tools.ietf.org/html/rfc8931) where this information only
|
||||
* exists in the first fragment.
|
||||
*
|
||||
* @return The reassembly buffer entry identified by the source and destination
|
||||
* address in the @p netif_hdr and @p tag, if any such entry exist.
|
||||
* @return NULL, if no entry with the given identifying tuple exist.
|
||||
*/
|
||||
gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_get_by_datagram(
|
||||
const gnrc_netif_hdr_t *netif_hdr,
|
||||
uint16_t tag);
|
||||
|
||||
/**
|
||||
* @brief Checks if a reassembly buffer entry with a given link-layer address
|
||||
* pair and tag exists
|
||||
@ -130,8 +167,8 @@ gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_add(gnrc_netif_hdr_t *netif_hdr
|
||||
*
|
||||
* @note datagram_size is not a search parameter as the primary use case
|
||||
* for this function is [Selective Fragment Recovery]
|
||||
* (https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05)
|
||||
* where this information only exists in the first fragment.
|
||||
* (https://tools.ietf.org/html/rfc8931) where this information only
|
||||
* exists in the first fragment.
|
||||
*
|
||||
* @return true, if an entry with the given tuple exist.
|
||||
* @return false, if no entry with the given tuple exist.
|
||||
@ -151,8 +188,8 @@ bool gnrc_sixlowpan_frag_rb_exists(const gnrc_netif_hdr_t *netif_hdr,
|
||||
*
|
||||
* @note datagram_size is not a search parameter as the primary use case
|
||||
* for this function is [Selective Fragment Recovery]
|
||||
* (https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05)
|
||||
* where this information only exists in the first fragment.
|
||||
* (https://tools.ietf.org/html/rfc8931) where this information only
|
||||
* exists in the first fragment.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_rb_rm_by_datagram(const gnrc_netif_hdr_t *netif_hdr,
|
||||
uint16_t tag);
|
||||
@ -251,6 +288,27 @@ static inline void gnrc_sixlowpan_frag_rb_remove(gnrc_sixlowpan_frag_rb_t *rbuf)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TEST_SUITES) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Check if pool of fragment intervals is empty
|
||||
*
|
||||
* @see @ref gnrc_sixlowpan_frag_rb_int_t
|
||||
* @note Returns only non-true values if @ref TEST_SUITES is defined.
|
||||
*
|
||||
* @return true, if pool of fragment intervals is empty
|
||||
* @return false, if pool of fragment intervals is not empty
|
||||
*/
|
||||
bool gnrc_sixlowpan_frag_rb_ints_empty(void);
|
||||
#else /* defined(TEST_SUITES) || defined(DOXYGEN) */
|
||||
/* always true without TEST_SUITES defined to optimize out when not testing,
|
||||
* as checking the status of the fragment interval pool is unnecessary in
|
||||
* production */
|
||||
static inline bool gnrc_sixlowpan_frag_rb_ints_empty(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* defined(TEST_SUITES) || defined(DOXYGEN) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
202
sys/include/net/gnrc/sixlowpan/frag/sfr.h
Normal file
202
sys/include/net/gnrc/sixlowpan/frag/sfr.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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_sfr 6LoWPAN selective fragment recovery
|
||||
* @ingroup net_gnrc_sixlowpan
|
||||
* @brief 6LoWPAN selective fragment recovery implementation for GNRC
|
||||
*
|
||||
* 6LoWPAN selective fragment recovery is an alternative fragmentation
|
||||
* specification to [classic 6LoWPAN fragmentation](@ref
|
||||
* net_gnrc_sixlowpan_frag). It can be run in parallel to classic fragmentation,
|
||||
* but is incompatible with its message formats.
|
||||
*
|
||||
* How nodes can exchange that they are able to communicate using selective
|
||||
* fragment recovery is currently not specified, so this feature should only be
|
||||
* used if the operator of a network can ensure that all 6LoWPAN nodes within
|
||||
* that network can communicate using selective fragment recovery.
|
||||
*
|
||||
* @see [RFC 8931](https://tools.ietf.org/html/rfc8931)
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief 6LoWPAN selective fragment recovery definitions for GNRC
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_GNRC_SIXLOWPAN_FRAG_SFR_H
|
||||
#define NET_GNRC_SIXLOWPAN_FRAG_SFR_H
|
||||
|
||||
#include "assert.h"
|
||||
#include "bitfield.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
#include "net/gnrc/sixlowpan/config.h"
|
||||
#include "net/gnrc/sixlowpan/frag/fb.h"
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
#include "net/gnrc/sixlowpan/frag/sfr_types.h"
|
||||
#include "net/sixlowpan/sfr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Message type to signal an acknowledgement request timeout.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_FRAG_SFR_ARQ_TIMEOUT_MSG (0x0227)
|
||||
|
||||
/**
|
||||
* @brief Message type to signal the sending of the next frame.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_FRAG_SFR_INTER_FRAG_GAP_MSG (0x0228)
|
||||
|
||||
/**
|
||||
* @brief Stats on selective fragment recovery
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t datagram_resends; /**< datagrams resent */
|
||||
struct {
|
||||
uint32_t usual; /**< non-abort fragments sent */
|
||||
uint32_t aborts; /**< abort pseudo-fragments sent */
|
||||
uint32_t forwarded; /**< forwarded fragments */
|
||||
} fragments_sent; /**< RFRAG packets sent */
|
||||
struct {
|
||||
uint32_t by_nack; /**< fragments resent due to a 0 in ACK's bitmap */
|
||||
uint32_t by_timeout; /**< fragments resent due to an ARQ timeout */
|
||||
} fragment_resends; /**< fragments resent */
|
||||
struct {
|
||||
uint32_t full; /**< full RFRAGs ACKs sent */
|
||||
uint32_t partly; /**< partly ACKing RFRAGs sent */
|
||||
uint32_t aborts; /**< abort RFRAG ACKs sent */
|
||||
uint32_t forwarded; /**< forwarded ACKs */
|
||||
} acks; /**< ACKs stats */
|
||||
} gnrc_sixlowpan_frag_sfr_stats_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize selective fragment recovery
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize a network interface for selective fragment recovery
|
||||
*
|
||||
* @note This is a NOP without module `gnrc_sixlowpan_frag_sfr`
|
||||
*
|
||||
* @param[in] netif A network interface
|
||||
*/
|
||||
static inline void gnrc_sixlowpan_frag_sfr_init_iface(gnrc_netif_t *netif)
|
||||
{
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
gnrc_netif_is_6lo(netif)) {
|
||||
#if IS_USED(MODULE_GNRC_NETIF_6LO)
|
||||
netif->sixlo.local_flags |= GNRC_NETIF_6LO_LOCAL_FLAGS_SFR;
|
||||
netif->sixlo.max_frag_size =
|
||||
(netif->sixlo.max_frag_size > CONFIG_GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE)
|
||||
? CONFIG_GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE
|
||||
: netif->sixlo.max_frag_size;
|
||||
assert(netif->sixlo.max_frag_size >= CONFIG_GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if a network interface is configured for selective fragment
|
||||
* recovery
|
||||
*
|
||||
* @param[in] netif A network interface.
|
||||
*
|
||||
* @return true, if @p netif supports selective fragment recovery and has it
|
||||
* enabled.
|
||||
* @return false, if @p netif does not support selective fragment recovery or
|
||||
* does not have it enabled.
|
||||
*/
|
||||
static inline bool gnrc_sixlowpan_frag_sfr_netif(gnrc_netif_t *netif)
|
||||
{
|
||||
#if IS_USED(MODULE_GNRC_NETIF_6LO)
|
||||
return IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
gnrc_netif_is_6lo(netif) &&
|
||||
(netif->sixlo.local_flags & GNRC_NETIF_6LO_LOCAL_FLAGS_SFR);
|
||||
#else
|
||||
(void)netif;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a packet via selective fragment recovery
|
||||
*
|
||||
* @pre `ctx != NULL`
|
||||
* @pre gnrc_sixlowpan_frag_fb_t::pkt of @p ctx is equal to @p pkt or
|
||||
* `pkt == NULL`.
|
||||
*
|
||||
* @param[in] pkt A packet. May be NULL.
|
||||
* @param[in] ctx Fragmentation buffer entry of. Expected to be of type
|
||||
* @ref gnrc_sixlowpan_frag_fb_t, with gnrc_sixlowpan_frag_fb_t
|
||||
* set to @p pkt. Must not be NULL.
|
||||
* @param[in] page Current 6Lo dispatch parsing page.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_send(gnrc_pktsnip_t *pkt, void *ctx,
|
||||
unsigned page);
|
||||
|
||||
/**
|
||||
* @brief Handles a packet containing a selective fragment recovery header
|
||||
*
|
||||
* @param[in] pkt The packet to handle.
|
||||
* @param[in] ctx Context for the packet. May be NULL.
|
||||
* @param[in] page Current 6Lo dispatch parsing page.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
|
||||
|
||||
/**
|
||||
* @brief Forward a fragment via selective fragment recovery
|
||||
*
|
||||
* @param[in] pkt The fragment to forward (without RFRAG header).
|
||||
* Is consumed by this function.
|
||||
* @param[in] rfrag The originally received RFRAG header.
|
||||
* @param[in] vrbe Virtual reassembly buffer containing the forwarding
|
||||
* information.
|
||||
* @param[in] page Current 6Lo dispatch parsing page.
|
||||
*
|
||||
* @return 0, on success.
|
||||
* @return -ENOMEM, when packet buffer is too full to prepare packet for
|
||||
* forwarding. @p pkt is released in that case.
|
||||
*/
|
||||
int gnrc_sixlowpan_frag_sfr_forward(gnrc_pktsnip_t *pkt,
|
||||
sixlowpan_sfr_rfrag_t *rfrag,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe,
|
||||
unsigned page);
|
||||
|
||||
/**
|
||||
* @brief Handles an Acknowledgment request timeout
|
||||
*
|
||||
* @param[in] fbuf The fragmentation buffer representing the datagram for which
|
||||
* fragments the Acknowledgment request timed out.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_arq_timeout(gnrc_sixlowpan_frag_fb_t *fbuf);
|
||||
|
||||
/**
|
||||
* @brief Handles inter frame gap
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_inter_frame_gap(void);
|
||||
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS)
|
||||
/**
|
||||
* @brief Fetch current stats for selective fragment recovery
|
||||
*
|
||||
* @param[out] stats The current stats. Must not be NULL.
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_sfr_stats_get(gnrc_sixlowpan_frag_sfr_stats_t *stats);
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_GNRC_SIXLOWPAN_FRAG_SFR_H */
|
||||
/** @} */
|
65
sys/include/net/gnrc/sixlowpan/frag/sfr_types.h
Normal file
65
sys/include/net/gnrc/sixlowpan/frag/sfr_types.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup net_gnrc_sixlowpan_frag_sfr
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief 6LoWPAN selective fragment recovery type definitions for GNRC
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_GNRC_SIXLOWPAN_FRAG_SFR_TYPES_H
|
||||
#define NET_GNRC_SIXLOWPAN_FRAG_SFR_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bitfield.h"
|
||||
#include "clist.h"
|
||||
#include "evtimer_msg.h"
|
||||
#include "msg.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Bitmap type to simplify comparisons
|
||||
*/
|
||||
typedef union {
|
||||
uint32_t u32; /**< numerical version of bitmap */
|
||||
BITFIELD(bf, 32U); /**< bitfield version of bitmap */
|
||||
} gnrc_sixlowpan_frag_sfr_bitmap_t;
|
||||
|
||||
/**
|
||||
* @brief Extension for @ref net_gnrc_sixlowpan_frag_fb for selective
|
||||
* fragment recovery
|
||||
*/
|
||||
typedef struct gnrc_sixlowpan_frag_sfr_fb {
|
||||
/**
|
||||
* @brief Acknowledgment request timeout event
|
||||
*/
|
||||
evtimer_msg_event_t arq_timeout_event;
|
||||
uint32_t arq_timeout; /**< Time in microseconds the sender should
|
||||
* wait for an RFRAG Acknowledgment */
|
||||
uint8_t cur_seq; /**< Sequence number for next fragment */
|
||||
uint8_t frags_sent; /**< Number of fragments sent */
|
||||
uint8_t window_size; /**< Current window size in number of
|
||||
* fragments */
|
||||
uint8_t retrans; /**< Datagram retransmissions */
|
||||
clist_node_t window; /**< Sent fragments of the current window */
|
||||
} gnrc_sixlowpan_frag_sfr_fb_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_GNRC_SIXLOWPAN_FRAG_SFR_TYPES_H */
|
||||
/** @} */
|
@ -54,6 +54,13 @@ typedef struct {
|
||||
* @brief Outgoing tag to gnrc_sixlowpan_frag_rb_base_t::dst
|
||||
*/
|
||||
uint16_t out_tag;
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
int16_t offset_diff; /**< offset change due to recompression */
|
||||
/**
|
||||
* @brief Incoming interface to gnrc_sixlowpan_frag_rb_base_t::src
|
||||
*/
|
||||
gnrc_netif_t *in_netif;
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
} gnrc_sixlowpan_frag_vrb_t;
|
||||
|
||||
/**
|
||||
@ -117,6 +124,23 @@ void gnrc_sixlowpan_frag_vrb_gc(void);
|
||||
gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get(
|
||||
const uint8_t *src, size_t src_len, unsigned src_tag);
|
||||
|
||||
/**
|
||||
* @brief Reverse VRB lookup
|
||||
*
|
||||
* @param[in] netif Network interface the reverse label-switched packet
|
||||
* came over
|
||||
* @param[in] src Link-layer source address of reverse label-switched
|
||||
* packet.
|
||||
* @param[in] src_len Length of @p src.
|
||||
* @param[in] tag Tag of the reverse label-switched packet.
|
||||
*
|
||||
* @return The VRB entry with `vrb->super.dst == src` and `vrb->out_tag == tag`.
|
||||
* @return NULL, if there is no entry in the VRB that has these values.
|
||||
*/
|
||||
gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_reverse(
|
||||
const gnrc_netif_t *netif, const uint8_t *src, size_t src_len,
|
||||
unsigned tag);
|
||||
|
||||
/**
|
||||
* @brief Removes an entry from the VRB
|
||||
*
|
||||
|
@ -63,22 +63,19 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* @brief Dispatch mask for 6LoWPAN selective fragment recovery
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05,
|
||||
* section 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5)
|
||||
* @see [RFC 8931, section 5](https://tools.ietf.org/html/rfc8931#section-5)
|
||||
*/
|
||||
#define SIXLOWPAN_SFR_DISP_MASK (0xfe)
|
||||
|
||||
/**
|
||||
* @brief Dispatch for 6LoWPAN recoverable fragment
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05, section
|
||||
* 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1)
|
||||
* @see [RFC 8931, section 5.1](https://tools.ietf.org/html/rfc8931#section-5.1)
|
||||
*/
|
||||
#define SIXLOWPAN_SFR_RFRAG_DISP (0xe8)
|
||||
|
||||
/**
|
||||
* @brief Dispatch for 6LoWPAN recoverable fragment acknowledgment
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05, section
|
||||
* 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2)
|
||||
* @see [RFC 8931, section 5.2](https://tools.ietf.org/html/rfc8931#section-5.2)
|
||||
*/
|
||||
#define SIXLOWPAN_SFR_ACK_DISP (0xea)
|
||||
|
||||
|
@ -57,8 +57,7 @@ extern "C" {
|
||||
/**
|
||||
* @brief Generic type for selective fragment recovery headers
|
||||
*
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05, section
|
||||
* 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5)
|
||||
* @see [RFC 8931, section 5](https://tools.ietf.org/html/rfc8931#section-5)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
/**
|
||||
@ -92,8 +91,7 @@ typedef struct __attribute__((packed)) {
|
||||
/**
|
||||
* @brief Recoverable fragment header
|
||||
*
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05, section
|
||||
* 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1)
|
||||
* @see [RFC 8931, section 5.1](https://tools.ietf.org/html/rfc8931#section-5.1)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
sixlowpan_sfr_t base; /**< generic part */
|
||||
@ -137,8 +135,7 @@ typedef struct __attribute__((packed)) {
|
||||
/**
|
||||
* @brief Recoverable fragment (RFRAG) acknowledgment header
|
||||
*
|
||||
* @see [draft-ietf-6lo-fragment-recovery-05, section
|
||||
* 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2)
|
||||
* @see [RFC 8931, section 5.2](https://tools.ietf.org/html/rfc8931#section-5.2)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
sixlowpan_sfr_t base; /**< generic part */
|
||||
|
@ -106,6 +106,9 @@ endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/rb
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_sfr,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/sfr
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_stats,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/stats
|
||||
endif
|
||||
|
@ -32,6 +32,9 @@
|
||||
#if IS_USED(MODULE_GNRC_NETIF_PKTQ)
|
||||
#include "net/gnrc/netif/pktq.h"
|
||||
#endif /* IS_USED(MODULE_GNRC_NETIF_PKTQ) */
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
#include "net/gnrc/sixlowpan/frag/sfr.h"
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
#if IS_USED(MODULE_NETSTATS)
|
||||
#include "net/netstats.h"
|
||||
#endif /* IS_USED(MODULE_NETSTATS) */
|
||||
@ -1389,6 +1392,9 @@ void gnrc_netif_default_init(gnrc_netif_t *netif)
|
||||
_init_from_device(netif);
|
||||
#ifdef DEVELHELP
|
||||
_test_options(netif);
|
||||
#endif
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
gnrc_sixlowpan_frag_sfr_init_iface(netif);
|
||||
#endif
|
||||
netif->cur_hl = CONFIG_GNRC_NETIF_DEFAULT_HL;
|
||||
#ifdef MODULE_GNRC_IPV6_NIB
|
||||
|
@ -5,10 +5,16 @@
|
||||
# directory for more details.
|
||||
#
|
||||
|
||||
if USEMODULE_GNRC_SIXLOWPAN_FRAG
|
||||
if USEMODULE_GNRC_SIXLOWPAN_FRAG || USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
|
||||
rsource "fb/Kconfig"
|
||||
rsource "rb/Kconfig"
|
||||
rsource "vrb/Kconfig"
|
||||
|
||||
endif # USEMODULE_GNRC_SIXLOWPAN_FRAG
|
||||
endif # USEMODULE_GNRC_SIXLOWPAN_FRAG || USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
|
||||
if USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
|
||||
rsource "sfr/Kconfig"
|
||||
|
||||
endif # USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
|
@ -14,6 +14,7 @@ if KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_FB
|
||||
|
||||
config GNRC_SIXLOWPAN_FRAG_FB_SIZE
|
||||
int "Number of datagrams that can be fragmented simultaneously"
|
||||
default 4 if MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
default 1
|
||||
help
|
||||
This determines the number of @ref gnrc_sixlowpan_frag_fb_t instances
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "net/gnrc/sixlowpan/frag/minfwd.h"
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
#include "net/sixlowpan.h"
|
||||
#include "net/sixlowpan/sfr.h"
|
||||
#include "thread.h"
|
||||
#include "xtimer.h"
|
||||
#include "utlist.h"
|
||||
@ -153,7 +154,12 @@ gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_add(gnrc_netif_hdr_t *netif_hdr
|
||||
return (res < 0) ? NULL : &rbuf[res];
|
||||
}
|
||||
|
||||
|
||||
gnrc_sixlowpan_frag_rb_t *gnrc_sixlowpan_frag_rb_get_by_datagram(
|
||||
const gnrc_netif_hdr_t *netif_hdr,
|
||||
uint16_t tag)
|
||||
{
|
||||
return _rbuf_get_by_tag(netif_hdr, tag);
|
||||
}
|
||||
|
||||
bool gnrc_sixlowpan_frag_rb_exists(const gnrc_netif_hdr_t *netif_hdr,
|
||||
uint16_t tag)
|
||||
@ -200,9 +206,18 @@ static gnrc_sixlowpan_frag_rb_t *_rbuf_get_by_tag(const gnrc_netif_hdr_t *netif_
|
||||
#ifndef NDEBUG
|
||||
static bool _valid_offset(gnrc_pktsnip_t *pkt, size_t offset)
|
||||
{
|
||||
return (sixlowpan_frag_1_is(pkt->data) && (offset == 0)) ||
|
||||
(sixlowpan_frag_n_is(pkt->data) &&
|
||||
(offset == sixlowpan_frag_offset(pkt->data)));
|
||||
return (
|
||||
IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG) &&
|
||||
((sixlowpan_frag_1_is(pkt->data) && (offset == 0)) ||
|
||||
(sixlowpan_frag_n_is(pkt->data) &&
|
||||
(offset == sixlowpan_frag_offset(pkt->data))))
|
||||
) || (
|
||||
IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
/* offset == 0 is an abort condition that should not be handed to the
|
||||
* reassembly buffer */
|
||||
sixlowpan_sfr_rfrag_is(pkt->data) &&
|
||||
(sixlowpan_sfr_rfrag_get_offset(pkt->data) != 0)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -234,6 +249,42 @@ static size_t _6lo_frag_size(gnrc_pktsnip_t *pkt, size_t offset, uint8_t *data)
|
||||
return frag_size;
|
||||
}
|
||||
|
||||
static uint16_t _6lo_sfr_datagram_size(gnrc_pktsnip_t *pkt, size_t offset)
|
||||
{
|
||||
/* offset doubles as datagram size in RFRAG header when sequence number is 0
|
||||
* see https://tools.ietf.org/html/rfc8931#section-5.1 */
|
||||
return (offset == 0) ? sixlowpan_sfr_rfrag_get_offset(pkt->data) : 0;
|
||||
}
|
||||
|
||||
static uint8_t *_6lo_sfr_payload(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
return ((uint8_t *)pkt->data) + sizeof(sixlowpan_sfr_rfrag_t);
|
||||
}
|
||||
|
||||
static size_t _6lo_sfr_frag_size(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
/* TODO: if necessary check MAC layer here,
|
||||
* see https://tools.ietf.org/html/rfc8931#section-5.1 */
|
||||
return sixlowpan_sfr_rfrag_get_frag_size(pkt->data);
|
||||
}
|
||||
|
||||
static gnrc_pktsnip_t *_mark_frag_hdr(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_IPHC)) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
sixlowpan_sfr_rfrag_is(pkt->data)) {
|
||||
return gnrc_pktbuf_mark(pkt, sizeof(sixlowpan_sfr_rfrag_t),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
}
|
||||
else if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG) &&
|
||||
sixlowpan_frag_is(pkt->data)) {
|
||||
return gnrc_pktbuf_mark(pkt, sizeof(sixlowpan_frag_t),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
size_t offset, unsigned page)
|
||||
{
|
||||
@ -244,18 +295,37 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
} entry;
|
||||
const uint8_t *src = gnrc_netif_hdr_get_src_addr(netif_hdr);
|
||||
const uint8_t *dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
|
||||
uint8_t *data;
|
||||
size_t frag_size;
|
||||
uint8_t *data = NULL;
|
||||
size_t frag_size = 0; /* assign 0, otherwise cppcheck complains ;-) */
|
||||
int res;
|
||||
uint16_t datagram_size;
|
||||
uint16_t datagram_tag;
|
||||
|
||||
/* check if provided offset is the same as in fragment */
|
||||
assert(_valid_offset(pkt, offset));
|
||||
data = _6lo_frag_payload(pkt);
|
||||
frag_size = _6lo_frag_size(pkt, offset, data);
|
||||
datagram_size = sixlowpan_frag_datagram_size(pkt->data);
|
||||
datagram_tag = sixlowpan_frag_datagram_tag(pkt->data);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG) && sixlowpan_frag_is(pkt->data)) {
|
||||
data = _6lo_frag_payload(pkt);
|
||||
frag_size = _6lo_frag_size(pkt, offset, data);
|
||||
datagram_size = sixlowpan_frag_datagram_size(pkt->data);
|
||||
datagram_tag = sixlowpan_frag_datagram_tag(pkt->data);
|
||||
}
|
||||
else if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
sixlowpan_sfr_rfrag_is(pkt->data)) {
|
||||
sixlowpan_sfr_rfrag_t *rfrag = pkt->data;
|
||||
|
||||
data = _6lo_sfr_payload(pkt);
|
||||
frag_size = _6lo_sfr_frag_size(pkt);
|
||||
/* offset doubles as datagram size in RFRAG header when sequence number
|
||||
* is 0 */
|
||||
datagram_size = _6lo_sfr_datagram_size(pkt, offset);
|
||||
datagram_tag = rfrag->base.tag;
|
||||
}
|
||||
else {
|
||||
/* either one of the if branches above was taken */
|
||||
assert(data != NULL);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
|
||||
gnrc_sixlowpan_frag_rb_gc();
|
||||
/* only check VRB for subsequent frags, first frags create and not get VRB
|
||||
@ -301,6 +371,9 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
entry.rbuf = &rbuf[res];
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
offset += entry.rbuf->offset_diff;
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
if ((offset + frag_size) > entry.super->datagram_size) {
|
||||
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
|
||||
gnrc_pktbuf_release(entry.rbuf->pkt);
|
||||
@ -326,11 +399,11 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
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)) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_IPHC) &&
|
||||
sixlowpan_iphc_is(data)) {
|
||||
DEBUG("6lo rbuf: detected IPHC header.\n");
|
||||
gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt,
|
||||
sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN);
|
||||
gnrc_pktsnip_t *frag_hdr = _mark_frag_hdr(pkt);
|
||||
|
||||
if (frag_hdr == NULL) {
|
||||
DEBUG("6lo rbuf: unable to mark fragment header. "
|
||||
"aborting reassembly.\n");
|
||||
@ -350,9 +423,7 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (data[0] == SIXLOWPAN_UNCOMP) {
|
||||
else if (data[0] == SIXLOWPAN_UNCOMP) {
|
||||
DEBUG("6lo rbuf: detected uncompressed datagram\n");
|
||||
data++;
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) &&
|
||||
@ -376,12 +447,17 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
return _forward_uncomp(pkt, rbuf, vrbe, page);
|
||||
}
|
||||
}
|
||||
else if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
sixlowpan_sfr_rfrag_is(pkt->data)) {
|
||||
entry.super->datagram_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD)) {
|
||||
/* all cases to try forwarding with minfwd above failed so just do
|
||||
* normal reassembly. For the `minfwd` case however, we need to
|
||||
* resize `entry.rbuf->pkt`, since we kept the packet allocation
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) ||
|
||||
IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)) {
|
||||
/* all cases to try forwarding with minfwd or SFR above failed so
|
||||
* just do normal reassembly. For the `minfwd` case however, we need
|
||||
* to resize `entry.rbuf->pkt`, since we kept the packet allocation
|
||||
* with fragment forwarding as minimal as possible in
|
||||
* `_rbuf_get()` */
|
||||
res = _rbuf_resize_for_reassembly(entry.rbuf);
|
||||
@ -423,6 +499,18 @@ static gnrc_sixlowpan_frag_rb_int_t *_rbuf_int_get_free(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef TEST_SUITES
|
||||
bool gnrc_sixlowpan_frag_rb_ints_empty(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < RBUF_INT_SIZE; i++) {
|
||||
if (rbuf_int[i].end > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* TEST_SUITES */
|
||||
|
||||
static bool _rbuf_update_ints(gnrc_sixlowpan_frag_rb_base_t *entry,
|
||||
uint16_t offset, size_t frag_size)
|
||||
{
|
||||
@ -510,8 +598,14 @@ static int _rbuf_get(const void *src, size_t src_len,
|
||||
|
||||
for (unsigned int i = 0; i < CONFIG_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) &&
|
||||
if ((rbuf[i].pkt != NULL) && (rbuf[i].super.tag == tag) &&
|
||||
((IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
/* not all SFR fragments carry the datagram size, so make 0 a
|
||||
* legal value to not compare datagram size */
|
||||
((size == 0) || (rbuf[i].super.datagram_size == size))) ||
|
||||
(!IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) &&
|
||||
(rbuf[i].super.datagram_size == size))) &&
|
||||
(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)) {
|
||||
@ -624,6 +718,10 @@ static int _rbuf_get(const void *src, size_t src_len,
|
||||
res->super.dst_len = dst_len;
|
||||
res->super.tag = tag;
|
||||
res->super.current_size = 0;
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
res->offset_diff = 0U;
|
||||
memset(res->received, 0U, sizeof(res->received));
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
|
||||
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
|
||||
gnrc_netif_addr_to_str(res->super.src, res->super.src_len,
|
||||
|
101
sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig
Normal file
101
sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Kconfig
Normal file
@ -0,0 +1,101 @@
|
||||
# Copyright (c) 2020 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.
|
||||
#
|
||||
menuconfig KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
bool "Configure GNRC 6LoWPAN Selective Fragment Recovery"
|
||||
depends on USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
help
|
||||
Configure GNRC 6LoWPAN Selective Fragement Recovery using Kconfig.
|
||||
|
||||
if KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE
|
||||
int "Default minimum value for fragment size (MinFragmentSize)"
|
||||
default 96
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
int "Default maximum value for fragment size (MaxFragmentSize)"
|
||||
default 112
|
||||
help
|
||||
It must be lower than the minimum MTU along the path. A large value
|
||||
augments the chances of buffer bloat and transmission loss. The value
|
||||
must be less than 512 if the unit is defined for the PHY layer is the
|
||||
octet.
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_OPT_FRAG_SIZE
|
||||
int "Default value for fragment size that the sender should use to start with (OptFragmentSize)"
|
||||
default 112
|
||||
help
|
||||
Must be inclusively between @ref GNRC_SIXLOWPAN_SFR_MIN_FRAG_SIZE and
|
||||
@ref GNRC_SIXLOWPAN_SFR_MAX_FRAG_SIZE
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_USE_ECN
|
||||
bool "Indicates whether the sender should react to ECN (UseECN)"
|
||||
default false
|
||||
help
|
||||
When the sender reacts to Explicit Congestion Notification (ECN) its
|
||||
window size will vary between @ref
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE and @ref
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE.
|
||||
|
||||
if GNRC_SIXLOWPAN_SFR_USE_ECN
|
||||
comment "Warning: Reaction of sender to ECN is not implemented yet"
|
||||
endif
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE
|
||||
int "Default minimum value of window size that the sender can use (MinWindowSize)"
|
||||
default 1
|
||||
range 1 32
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE
|
||||
int "Default maximum value of window size that the sender can use (MaxWindowSize)"
|
||||
default 16
|
||||
range 1 32
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE
|
||||
int "Default value of window size that the sender should start with (OptWindowSize)"
|
||||
default 16
|
||||
range 1 32
|
||||
help
|
||||
Must be inclusively between @ref GNRC_SIXLOWPAN_SFR_MIN_WIN_SIZE and
|
||||
@ref GNRC_SIXLOWPAN_SFR_MAX_WIN_SIZE
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US
|
||||
int "Default minimum amount of time between transmissions in microseconds (InterFrameGap)"
|
||||
default 100
|
||||
help
|
||||
All packets to a same destination, and in particular fragments, may be
|
||||
subject to receive while transmitting and hidden terminal collisions
|
||||
with the next or the previous transmission as the fragments progress
|
||||
along a same path. The InterFrameGap protects the propagation of to one
|
||||
transmission before the next one is triggered and creates a duty cycle
|
||||
that controls the ratio of air and memory in intermediate nodes that a
|
||||
particular datagram will use.
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS
|
||||
int "Minimum RFRAG-ACK timeout in msec before a node takes a next action (MinARQTimeOut)"
|
||||
default 350
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
int "Maximum RFRAG-ACK timeout in msec before a node takes a next action (MaxARQTimeOut)"
|
||||
default 700
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS
|
||||
int "Default RFRAG-ACK timeout in msec before a node takes a next action (OptARQTimeOut)"
|
||||
default 700
|
||||
help
|
||||
Must be inclusively between @ref GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS
|
||||
and @ref GNRC_SIXLOWPAN_SFR_MAX_ARQ_TIMEOUT_MS
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_FRAG_RETRIES
|
||||
int "The maximum number of retries for a particular fragment (MaxFragRetries)"
|
||||
default 2
|
||||
|
||||
config GNRC_SIXLOWPAN_SFR_DG_RETRIES
|
||||
int "The maximum number of retries from scratch for a particular datagram (MaxDatagramRetries)"
|
||||
default 0
|
||||
|
||||
endif
|
3
sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Makefile
Normal file
3
sys/net/gnrc/network_layer/sixlowpan/frag/sfr/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE := gnrc_sixlowpan_frag_sfr
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
File diff suppressed because it is too large
Load Diff
@ -184,6 +184,29 @@ gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_reverse(
|
||||
const gnrc_netif_t *netif, const uint8_t *src, size_t src_len,
|
||||
unsigned tag)
|
||||
{
|
||||
DEBUG("6lo vrb: trying to get entry for reverse label switching (%s, %u)\n",
|
||||
gnrc_netif_addr_to_str(src, src_len, addr_str), tag);
|
||||
for (unsigned i = 0; i < CONFIG_GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) {
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe = &_vrb[i];
|
||||
|
||||
if ((vrbe->out_tag == tag) && (vrbe->out_netif == netif) &&
|
||||
(memcmp(vrbe->super.dst, src, src_len) == 0)) {
|
||||
DEBUG("6lo vrb: got VRB entry from (%s, %u)\n",
|
||||
gnrc_netif_addr_to_str(vrbe->super.src,
|
||||
vrbe->super.src_len,
|
||||
addr_str), vrbe->super.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();
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "net/gnrc/sixlowpan.h"
|
||||
#include "net/gnrc/sixlowpan/frag.h"
|
||||
#include "net/gnrc/sixlowpan/frag/rb.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
#include "net/gnrc/sixlowpan/frag/sfr.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
#include "net/gnrc/sixlowpan/iphc.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
#include "net/sixlowpan.h"
|
||||
@ -114,11 +117,16 @@ void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
|
||||
DEBUG("6lo: Dispatch for sending\n");
|
||||
gnrc_sixlowpan_dispatch_send(pkt, NULL, page);
|
||||
}
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
#if defined(MODULE_GNRC_SIXLOWPAN_FRAG) || defined(MODULE_GNRC_SIXLOWPAN_FRAG_SFR)
|
||||
else if (orig_datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) {
|
||||
DEBUG("6lo: Send fragmented (%u > %u)\n",
|
||||
(unsigned int)datagram_size, netif->sixlo.max_frag_size);
|
||||
gnrc_sixlowpan_frag_fb_t *fbuf;
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
bool sfr = gnrc_sixlowpan_frag_sfr_netif(netif);
|
||||
#else /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
bool sfr = false;
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
|
||||
fbuf = gnrc_sixlowpan_frag_fb_get();
|
||||
if (fbuf == NULL) {
|
||||
@ -136,9 +144,20 @@ void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
|
||||
fbuf->hint.fragsz = 0;
|
||||
#endif
|
||||
|
||||
gnrc_sixlowpan_frag_send(pkt, fbuf, page);
|
||||
}
|
||||
if (!sfr) {
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
gnrc_sixlowpan_frag_send(pkt, fbuf, page);
|
||||
#endif
|
||||
}
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
else {
|
||||
fbuf->sfr.cur_seq = 0U;
|
||||
fbuf->sfr.frags_sent = 0U;
|
||||
gnrc_sixlowpan_frag_sfr_send(pkt, fbuf, page);
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
}
|
||||
#endif /* defined(MODULE_GNRC_SIXLOWPAN_FRAG) || defined(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) */
|
||||
else {
|
||||
(void)orig_datagram_size;
|
||||
DEBUG("6lo: packet too big (%u > %u)\n",
|
||||
@ -216,6 +235,13 @@ static void _receive(gnrc_pktsnip_t *pkt)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
else if (sixlowpan_sfr_is((sixlowpan_sfr_t *)dispatch)) {
|
||||
DEBUG("6lo: received 6LoWPAN recoverable fragment\n");
|
||||
gnrc_sixlowpan_frag_sfr_recv(pkt, NULL, 0);
|
||||
return;
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||
else if (sixlowpan_iphc_is(dispatch)) {
|
||||
DEBUG("6lo: received 6LoWPAN IPHC compressed datagram\n");
|
||||
@ -331,6 +357,32 @@ static void _send(gnrc_pktsnip_t *pkt)
|
||||
gnrc_sixlowpan_multiplex_by_size(pkt, datagram_size, netif, 0);
|
||||
}
|
||||
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_FB
|
||||
static void _continue_fragmenting(gnrc_sixlowpan_frag_fb_t *fbuf)
|
||||
{
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
if (fbuf->pkt == NULL) {
|
||||
/* In case the timer fired before the entry was removed */
|
||||
return;
|
||||
}
|
||||
|
||||
gnrc_netif_t *netif = gnrc_netif_hdr_get_netif(fbuf->pkt->data);
|
||||
assert(netif != NULL);
|
||||
if (gnrc_sixlowpan_frag_sfr_netif(netif)) {
|
||||
gnrc_sixlowpan_frag_sfr_send(NULL, fbuf, 0);
|
||||
return;
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
gnrc_sixlowpan_frag_send(NULL, fbuf, 0);
|
||||
#else /* MODULE_GNRC_SIXLOWPAN_FRAG */
|
||||
(void)fbuf;
|
||||
DEBUG("6lo: No fragmentation implementation available to sent\n");
|
||||
assert(false);
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG */
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_FB */
|
||||
|
||||
static void *_event_loop(void *args)
|
||||
{
|
||||
msg_t msg, reply, msg_q[GNRC_SIXLOWPAN_MSG_QUEUE_SIZE];
|
||||
@ -346,6 +398,10 @@ static void *_event_loop(void *args)
|
||||
/* preinitialize ACK */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
gnrc_sixlowpan_frag_sfr_init();
|
||||
#endif
|
||||
|
||||
/* start event loop */
|
||||
while (1) {
|
||||
DEBUG("6lo: waiting for incoming message.\n");
|
||||
@ -371,20 +427,25 @@ static void *_event_loop(void *args)
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_FB
|
||||
case GNRC_SIXLOWPAN_FRAG_FB_SND_MSG:
|
||||
DEBUG("6lo: send fragmented event received\n");
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
gnrc_sixlowpan_frag_send(NULL, msg.content.ptr, 0);
|
||||
#else /* MODULE_GNRC_SIXLOWPAN_FRAG_FB */
|
||||
DEBUG("6lo: No fragmentation implementation available to sent\n");
|
||||
assert(false);
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_FB */
|
||||
_continue_fragmenting(msg.content.ptr);
|
||||
break;
|
||||
#endif
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_FB */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_RB
|
||||
case GNRC_SIXLOWPAN_FRAG_RB_GC_MSG:
|
||||
DEBUG("6lo: garbage collect reassembly buffer event received\n");
|
||||
gnrc_sixlowpan_frag_rb_gc();
|
||||
break;
|
||||
#endif
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
case GNRC_SIXLOWPAN_FRAG_SFR_ARQ_TIMEOUT_MSG:
|
||||
DEBUG("6lo sfr: ARQ timeout received\n");
|
||||
gnrc_sixlowpan_frag_sfr_arq_timeout(msg.content.ptr);
|
||||
break;
|
||||
case GNRC_SIXLOWPAN_FRAG_SFR_INTER_FRAG_GAP_MSG:
|
||||
DEBUG("6lo sfr: sending next scheduled frame\n");
|
||||
gnrc_sixlowpan_frag_sfr_inter_frame_gap();
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
DEBUG("6lo: operation not supported\n");
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "net/gnrc/sixlowpan/ctx.h"
|
||||
#include "net/gnrc/sixlowpan/frag/rb.h"
|
||||
#include "net/gnrc/sixlowpan/frag/minfwd.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
#include "net/gnrc/sixlowpan/frag/sfr.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
|
||||
@ -116,6 +119,18 @@
|
||||
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
|
||||
|
||||
static inline bool _is_rfrag(gnrc_pktsnip_t *sixlo)
|
||||
{
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
assert((sixlo->next != NULL) &&
|
||||
(sixlo->next->type == GNRC_NETTYPE_SIXLOWPAN));
|
||||
return sixlowpan_sfr_rfrag_is(sixlo->next->data);
|
||||
#else /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
(void)sixlo;
|
||||
return false;
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
}
|
||||
|
||||
static inline bool _context_overlaps_iid(gnrc_sixlowpan_ctx_t *ctx,
|
||||
ipv6_addr_t *addr,
|
||||
eui64_t *iid)
|
||||
@ -562,8 +577,14 @@ static size_t _iphc_nhc_ipv6_decode(gnrc_pktsnip_t *sixlo, size_t offset,
|
||||
/* might be needed to be overwritten by IPv6 reassembly after the IPv6
|
||||
* packet was reassembled to get complete length */
|
||||
if (rbuf != NULL) {
|
||||
payload_len = rbuf->super.datagram_size - *uncomp_hdr_len-
|
||||
sizeof(ipv6_hdr_t);
|
||||
if (_is_rfrag(sixlo)) {
|
||||
payload_len = (rbuf->super.datagram_size + *uncomp_hdr_len) -
|
||||
(sizeof(ipv6_hdr_t) - offset);
|
||||
}
|
||||
else {
|
||||
payload_len = rbuf->super.datagram_size - *uncomp_hdr_len -
|
||||
sizeof(ipv6_hdr_t);
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload_len = (sixlo->size + *uncomp_hdr_len) -
|
||||
@ -669,7 +690,13 @@ static size_t _iphc_nhc_udp_decode(gnrc_pktsnip_t *sixlo, size_t offset,
|
||||
/* might be needed to be overwritten by IPv6 reassembly after the IPv6
|
||||
* packet was reassembled to get complete length */
|
||||
if (rbuf != NULL) {
|
||||
payload_len = rbuf->super.datagram_size - *uncomp_hdr_len;
|
||||
if (_is_rfrag(sixlo)) {
|
||||
payload_len = rbuf->super.datagram_size + sizeof(udp_hdr_t) -
|
||||
offset;
|
||||
}
|
||||
else {
|
||||
payload_len = rbuf->super.datagram_size - *uncomp_hdr_len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload_len = sixlo->size + sizeof(udp_hdr_t) - offset;
|
||||
@ -781,7 +808,29 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
uint16_t payload_len;
|
||||
if (rbuf != NULL) {
|
||||
/* for a fragmented datagram we know the overall length already */
|
||||
payload_len = (uint16_t)(rbuf->super.datagram_size - sizeof(ipv6_hdr_t));
|
||||
if (_is_rfrag(sixlo)) {
|
||||
DEBUG("6lo iphc: calculating payload length for SFR\n");
|
||||
DEBUG(" - rbuf->super.datagram_size: %u\n",
|
||||
rbuf->super.datagram_size);
|
||||
DEBUG(" - payload_offset: %u\n", (unsigned)payload_offset);
|
||||
DEBUG(" - uncomp_hdr_len: %u\n", (unsigned)uncomp_hdr_len);
|
||||
/* set IPv6 header payload length field to the length of whatever is
|
||||
* left after removing the 6LoWPAN header and adding uncompressed
|
||||
* headers */
|
||||
payload_len = (rbuf->super.datagram_size - payload_offset) +
|
||||
(uncomp_hdr_len - sizeof(ipv6_hdr_t));
|
||||
DEBUG(" => %u\n", payload_len);
|
||||
/* adapt datagram size for uncompressed datagram */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
/* guard required because SFR-specific field of vrbe is accessed */
|
||||
rbuf->offset_diff += (uncomp_hdr_len - payload_offset);
|
||||
rbuf->super.datagram_size += rbuf->offset_diff;
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
|
||||
}
|
||||
else {
|
||||
/* for a fragmented datagram we know the overall length already */
|
||||
payload_len = (uint16_t)(rbuf->super.datagram_size - sizeof(ipv6_hdr_t));
|
||||
}
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
|
||||
DEBUG("6lo iphc: VRB present, trying to create entry for dst %s\n",
|
||||
ipv6_addr_to_str(addr_str, &ipv6_hdr->dst, sizeof(addr_str)));
|
||||
@ -845,6 +894,16 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
ipv6_hdr->hl--;
|
||||
vrbe->super.current_size = rbuf->super.current_size;
|
||||
if ((ipv6 = _encode_frag_for_forwarding(ipv6, vrbe))) {
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
/* guard required because SFR-specific field of vrbe is
|
||||
* accessed */
|
||||
if (_is_rfrag(sixlo)) {
|
||||
vrbe->in_netif = iface;
|
||||
/* calculate offset difference due to compression */
|
||||
vrbe->offset_diff = ((int)gnrc_pkt_len(ipv6->next)) -
|
||||
sixlo->size;
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
if ((res = _forward_frag(ipv6, sixlo->next, vrbe, page)) == 0) {
|
||||
DEBUG("6lo iphc: successfully recompressed and forwarded "
|
||||
"1st fragment\n");
|
||||
@ -930,6 +989,11 @@ static int _forward_frag(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *frag_hdr,
|
||||
}
|
||||
/* the following is just debug output for testing without any forwarding
|
||||
* scheme */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR
|
||||
if (sixlowpan_sfr_rfrag_is(frag_hdr->data)) {
|
||||
return gnrc_sixlowpan_frag_sfr_forward(pkt, frag_hdr->data, vrbe, page);
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR */
|
||||
DEBUG("6lo iphc: Do not know how to forward fragment from (%s, %u) ",
|
||||
gnrc_netif_addr_to_str(vrbe->super.src, vrbe->super.src_len,
|
||||
addr_str), vrbe->super.tag);
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "net/gnrc/sixlowpan/frag/stats.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS
|
||||
#include "net/gnrc/sixlowpan/frag/sfr.h"
|
||||
#endif
|
||||
|
||||
int _gnrc_6lo_frag_stats(int argc, char **argv)
|
||||
{
|
||||
@ -28,6 +31,24 @@ int _gnrc_6lo_frag_stats(int argc, char **argv)
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
|
||||
printf("VRB full: %u\n", stats->vrb_full);
|
||||
#endif
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS
|
||||
gnrc_sixlowpan_frag_sfr_stats_t sfr;
|
||||
|
||||
gnrc_sixlowpan_frag_sfr_stats_get(&sfr);
|
||||
printf("DG resends: %lu\n", (long unsigned)sfr.datagram_resends);
|
||||
printf("frags sent: usual: %lu, aborts: %lu, forwarded: %lu\n",
|
||||
(long unsigned)sfr.fragments_sent.usual,
|
||||
(long unsigned)sfr.fragments_sent.aborts,
|
||||
(long unsigned)sfr.fragments_sent.forwarded);
|
||||
printf("frag resends: NACK: %lu, timeout: %lu\n",
|
||||
(long unsigned)sfr.fragment_resends.by_nack,
|
||||
(long unsigned)sfr.fragment_resends.by_timeout);
|
||||
printf("ACKs: full: %lu, partly: %lu, aborts: %lu, forwarded: %lu\n",
|
||||
(long unsigned)sfr.acks.full,
|
||||
(long unsigned)sfr.acks.partly,
|
||||
(long unsigned)sfr.acks.aborts,
|
||||
(long unsigned)sfr.acks.forwarded);
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_SFR_STATS */
|
||||
printf("frags complete: %u\n", stats->fragments);
|
||||
printf("dgs complete: %u\n", stats->datagrams);
|
||||
return 0;
|
||||
|
@ -536,6 +536,25 @@ static void test_rbuf_add__overlap_rhs(void)
|
||||
_check_pktbuf(NULL);
|
||||
}
|
||||
|
||||
static void test_rbuf_get_by_dg(void)
|
||||
{
|
||||
const gnrc_sixlowpan_frag_rb_t *entry;
|
||||
|
||||
TEST_ASSERT_NULL(
|
||||
gnrc_sixlowpan_frag_rb_get_by_datagram(&_test_netif_hdr.hdr, TEST_TAG)
|
||||
);
|
||||
/* add a fragment */
|
||||
_rbuf_create_first_fragment();
|
||||
TEST_ASSERT_NOT_NULL(
|
||||
gnrc_sixlowpan_frag_rb_get_by_datagram(&_test_netif_hdr.hdr, TEST_TAG)
|
||||
);
|
||||
/* get entry to release entry->pkt it in `_check_pktbuf()` */
|
||||
entry = _first_non_empty_rbuf();
|
||||
/* entry is however not properly removed yet */
|
||||
TEST_ASSERT_NOT_NULL(entry);
|
||||
_check_pktbuf(entry);
|
||||
}
|
||||
|
||||
static void test_rbuf_exists(void)
|
||||
{
|
||||
const gnrc_sixlowpan_frag_rb_t *entry;
|
||||
@ -631,6 +650,7 @@ static void run_unittests(void)
|
||||
new_TestFixture(test_rbuf_add__too_big_fragment),
|
||||
new_TestFixture(test_rbuf_add__overlap_lhs),
|
||||
new_TestFixture(test_rbuf_add__overlap_rhs),
|
||||
new_TestFixture(test_rbuf_get_by_dg),
|
||||
new_TestFixture(test_rbuf_exists),
|
||||
new_TestFixture(test_rbuf_rm_by_dg),
|
||||
new_TestFixture(test_rbuf_rm),
|
||||
|
36
tests/gnrc_sixlowpan_frag_sfr/Makefile
Normal file
36
tests/gnrc_sixlowpan_frag_sfr/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += gnrc_sixlowpan_frag_sfr
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
USEMODULE += gnrc_ipv6_nib
|
||||
USEMODULE += gnrc_netif
|
||||
USEMODULE += embunit
|
||||
USEMODULE += netdev_ieee802154
|
||||
USEMODULE += netdev_test
|
||||
|
||||
CFLAGS += -DTEST_SUITES
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
ifndef CONFIG_GNRC_IPV6_NIB_NO_RTR_SOL
|
||||
# disable router solicitations so they don't interfere with the tests
|
||||
CFLAGS += -DCONFIG_GNRC_IPV6_NIB_NO_RTR_SOL=1
|
||||
endif
|
||||
# SFR parameters
|
||||
ifndef CONFIG_GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE
|
||||
# fix window size
|
||||
CFLAGS += -DCONFIG_GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE=3U
|
||||
endif
|
||||
ifndef CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US
|
||||
# decrease inter frame gap
|
||||
CFLAGS += -DCONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US=5U
|
||||
endif
|
||||
ifndef CONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS
|
||||
# decrease minimal ARQ timeout
|
||||
CFLAGS += -DCONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS=100U
|
||||
endif
|
||||
ifndef CONFIG_GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS
|
||||
# decrease initial ARQ timeout
|
||||
CFLAGS += -DCONFIG_GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS=100U
|
||||
endif
|
42
tests/gnrc_sixlowpan_frag_sfr/Makefile.ci
Normal file
42
tests/gnrc_sixlowpan_frag_sfr/Makefile.ci
Normal file
@ -0,0 +1,42 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
blackpill \
|
||||
bluepill \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
i-nucleo-lrwan1 \
|
||||
im880b \
|
||||
mega-xplained \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f070rb \
|
||||
nucleo-f072rb \
|
||||
nucleo-f302r8 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
samd10-xmini \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32l0538-disco \
|
||||
stm32mp157c-dk2 \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
z1 \
|
||||
#
|
10
tests/gnrc_sixlowpan_frag_sfr/app.config
Normal file
10
tests/gnrc_sixlowpan_frag_sfr/app.config
Normal file
@ -0,0 +1,10 @@
|
||||
CONFIG_KCONFIG_USEMODULE_GNRC_IPV6_NIB=y
|
||||
CONFIG_KCONFIG_USEMODULE_GNRC_SIXLOWPAN=y
|
||||
CONFIG_KCONFIG_USEMODULE_GNRC_SIXLOWPAN_FRAG_SFR=y
|
||||
# disable router solicitations so they don't interfere with the tests
|
||||
CONFIG_GNRC_IPV6_NIB_NO_RTR_SOL=y
|
||||
# preconfigure SFR for tests
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_OPT_WIN_SIZE=3
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_INTER_FRAME_GAP_US=5
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_MIN_ARQ_TIMEOUT_MS=100
|
||||
CONFIG_GNRC_SIXLOWPAN_SFR_OPT_ARQ_TIMEOUT_MS=100
|
50
tests/gnrc_sixlowpan_frag_sfr/common.h
Normal file
50
tests/gnrc_sixlowpan_frag_sfr/common.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 tests_gnrc_ipv6_nib Common header for GNRC's NIB tests
|
||||
* @ingroup tests
|
||||
* @brief Common definitions for GNRC's NIB tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _LL0 (0xb8)
|
||||
#define _LL1 (0x8c)
|
||||
#define _LL2 (0xcc)
|
||||
#define _LL3 (0xba)
|
||||
#define _LL4 (0xef)
|
||||
#define _LL5 (0x9a)
|
||||
#define _LL6 (0x67)
|
||||
#define _LL7 (0x42)
|
||||
|
||||
extern gnrc_netif_t *_mock_netif;
|
||||
|
||||
void _tests_init(void);
|
||||
void _common_set_up(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMMON_H */
|
||||
/** @} */
|
2836
tests/gnrc_sixlowpan_frag_sfr/main.c
Normal file
2836
tests/gnrc_sixlowpan_frag_sfr/main.c
Normal file
File diff suppressed because it is too large
Load Diff
123
tests/gnrc_sixlowpan_frag_sfr/mockup_netif.c
Normal file
123
tests/gnrc_sixlowpan_frag_sfr/mockup_netif.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "msg.h"
|
||||
#include "net/gnrc.h"
|
||||
#include "net/ethernet.h"
|
||||
#include "net/gnrc/ipv6/nib.h"
|
||||
#include "net/gnrc/netif/ieee802154.h"
|
||||
#include "net/gnrc/netif/internal.h"
|
||||
#include "net/netdev_test.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
|
||||
#define _MSG_QUEUE_SIZE (2)
|
||||
|
||||
gnrc_netif_t *_mock_netif = NULL;
|
||||
|
||||
static netdev_test_t _mock_netdev;
|
||||
static char _mock_netif_stack[THREAD_STACKSIZE_DEFAULT];
|
||||
static msg_t _main_msg_queue[_MSG_QUEUE_SIZE];
|
||||
static gnrc_netif_t _netif;
|
||||
|
||||
void _common_set_up(void)
|
||||
{
|
||||
assert(_mock_netif != NULL);
|
||||
gnrc_ipv6_nib_init();
|
||||
gnrc_netif_acquire(_mock_netif);
|
||||
gnrc_ipv6_nib_init_iface(_mock_netif);
|
||||
gnrc_netif_release(_mock_netif);
|
||||
}
|
||||
|
||||
int _get_device_type(netdev_t *dev, void *value, size_t max_len)
|
||||
{
|
||||
(void)dev;
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)value) = NETDEV_TYPE_IEEE802154;
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
static int _get_netdev_proto(netdev_t *netdev, void *value, size_t max_len)
|
||||
{
|
||||
assert(max_len == sizeof(gnrc_nettype_t));
|
||||
(void)netdev;
|
||||
|
||||
*((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN;
|
||||
return sizeof(gnrc_nettype_t);
|
||||
}
|
||||
|
||||
int _get_max_packet_size(netdev_t *dev, void *value, size_t max_len)
|
||||
{
|
||||
(void)dev;
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)value) = 102U;
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
int _get_src_len(netdev_t *dev, void *value, size_t max_len)
|
||||
{
|
||||
(void)dev;
|
||||
assert(max_len == sizeof(uint16_t));
|
||||
*((uint16_t *)value) = IEEE802154_LONG_ADDRESS_LEN;
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
int _get_address_long(netdev_t *dev, void *value, size_t max_len)
|
||||
{
|
||||
static const uint8_t addr[] = { _LL0, _LL1, _LL2, _LL3,
|
||||
_LL4, _LL5, _LL6, _LL7 };
|
||||
|
||||
(void)dev;
|
||||
assert(max_len >= sizeof(addr));
|
||||
memcpy(value, addr, sizeof(addr));
|
||||
return sizeof(addr);
|
||||
}
|
||||
|
||||
int _get_proto(netdev_t *dev, void *value, size_t max_len)
|
||||
{
|
||||
(void)dev;
|
||||
assert(max_len == sizeof(gnrc_nettype_t));
|
||||
*((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN;
|
||||
return sizeof(gnrc_nettype_t);
|
||||
}
|
||||
|
||||
void _tests_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
msg_init_queue(_main_msg_queue, _MSG_QUEUE_SIZE);
|
||||
netdev_test_setup(&_mock_netdev, 0);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_DEVICE_TYPE,
|
||||
_get_device_type);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_PROTO,
|
||||
_get_netdev_proto);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_MAX_PACKET_SIZE,
|
||||
_get_max_packet_size);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_SRC_LEN,
|
||||
_get_src_len);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_ADDRESS_LONG,
|
||||
_get_address_long);
|
||||
netdev_test_set_get_cb(&_mock_netdev, NETOPT_PROTO,
|
||||
_get_proto);
|
||||
res = gnrc_netif_ieee802154_create(
|
||||
&_netif, _mock_netif_stack, THREAD_STACKSIZE_DEFAULT,
|
||||
GNRC_NETIF_PRIO, "mockup_wpan", &_mock_netdev.netdev.netdev
|
||||
);
|
||||
assert(res == 0);
|
||||
_mock_netif = &_netif;
|
||||
}
|
||||
|
||||
/** @} */
|
19
tests/gnrc_sixlowpan_frag_sfr/tests/01-run.py
Executable file
19
tests/gnrc_sixlowpan_frag_sfr/tests/01-run.py
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
# Copyright (C) 2016 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run
|
||||
|
||||
|
||||
def testfunc(child):
|
||||
child.expect(r"OK \(\d+ tests\)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run(testfunc))
|
Loading…
Reference in New Issue
Block a user