mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-27 07:21:18 +01:00
Merge pull request #11068 from miri64/gnrc_sixlowpan_frag/new/minfwd
gnrc_sixlowpan_frag: initial import of minimal forwarding
This commit is contained in:
commit
b18cbd8c2a
@ -298,6 +298,13 @@ ifneq (,$(filter gnrc_sixlowpan_frag_fb,$(USEMODULE)))
|
||||
USEMODULE += core_msg
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_minfwd,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif_pktq
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
USEMODULE += gnrc_sixlowpan_frag_hint
|
||||
USEMODULE += gnrc_sixlowpan_frag_vrb
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
#include "msg.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
#include "net/gnrc/sixlowpan/frag/hint.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
100
sys/include/net/gnrc/sixlowpan/frag/minfwd.h
Normal file
100
sys/include/net/gnrc/sixlowpan/frag/minfwd.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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_minfwd Minimal fragment forwarding
|
||||
* @ingroup net_gnrc_sixlowpan_frag
|
||||
* @brief Provides minimal fragment forwarding using the VRB
|
||||
* @see [RFC 8930](https://tools.ietf.org/html/rfc8930)
|
||||
* @see @ref net_gnrc_sixlowpan_frag_vrb
|
||||
* @experimental
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Minimal fragment forwarding definitions
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H
|
||||
#define NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
#include "net/gnrc/sixlowpan/frag.h"
|
||||
#include "net/gnrc/sixlowpan/frag/fb.h"
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Forwards a fragment according to a VRB entry
|
||||
*
|
||||
* @param[in] pkt The fragment to forward (without fragmentation header).
|
||||
* Is consumed by this function.
|
||||
* @param[in] frag The originally received fragmentation header.
|
||||
* @param[in] vrbe Virtual reassembly buffer containing the forwarding
|
||||
* information. Removed when datagram was completely
|
||||
* forwarded.
|
||||
* @param[in] page Current 6Lo dispatch parsing page.
|
||||
*
|
||||
* @pre `vrbe != NULL`
|
||||
* @pre `pkt != NULL`
|
||||
* @pre `frag != NULL`
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -ENOMEM, when packet buffer is too full to prepare packet for
|
||||
* forwarding.
|
||||
*/
|
||||
int gnrc_sixlowpan_frag_minfwd_forward(gnrc_pktsnip_t *pkt,
|
||||
const sixlowpan_frag_n_t *frag,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe,
|
||||
unsigned page);
|
||||
|
||||
/**
|
||||
* @brief Fragments a packet with just the IPHC (and padding payload to get
|
||||
* to 8 byte) as the first fragment
|
||||
*
|
||||
* @pre `(frag_msg != NULL)`
|
||||
* @pre `(pkt != NULL) && (pkt->type == GNRC_NETTYPE_NETIF)`
|
||||
* @pre `(pkt->next != NULL) && (pkt->next->type == GNRC_NETTYPE_SIXLOWPAN)`
|
||||
*
|
||||
* @param[in] pkt The compressed packet to be sent. Must be in
|
||||
* send order with a packet snip of type
|
||||
* @ref GNRC_NETTYPE_NETIF first,
|
||||
* @ref GNRC_NETTYPE_SIXLOWPAN (the IPHC
|
||||
* header including NHC) second, and 0 or more
|
||||
* snips of payload.
|
||||
* @param[in] orig_datagram_size The size of the @p pkt before compression
|
||||
* (without @ref GNRC_NETTYPE_NETIF snip).
|
||||
* This can differ from @p frag_msg's
|
||||
* gnrc_sixlowpan_msg_frag_t::datagram_size
|
||||
* as it might just be a fragment in forwarding
|
||||
* that is re-compressed in @p pkt.
|
||||
* @param[in] ipv6_addr The (uncompressed) destination address of
|
||||
* @p pkt.
|
||||
* @param[in] fbuf A fragmentation buffer entry.
|
||||
*
|
||||
* @return 0, when fragmentation was successful
|
||||
* @return -1, on error. @p pkt is **not** released in that case and *should*
|
||||
* be handled by normal fragmentation.
|
||||
*/
|
||||
int gnrc_sixlowpan_frag_minfwd_frag_iphc(gnrc_pktsnip_t *pkt,
|
||||
size_t orig_datagram_size,
|
||||
const ipv6_addr_t *ipv6_addr,
|
||||
gnrc_sixlowpan_frag_fb_t *fbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H */
|
||||
/** @} */
|
||||
@ -52,6 +52,12 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
|
||||
* @param[in] pkt A 6LoWPAN frame with an uncompressed IPv6 header to send.
|
||||
* Will be translated to an 6LoWPAN IPHC frame.
|
||||
* @param[in] ctx Context for the packet. May be NULL.
|
||||
* If not NULL it is expected to be of type @ref
|
||||
* gnrc_sixlowpan_frag_fb_t to provide initial information for
|
||||
* possible fragmentation after compression (see
|
||||
* net_gnrc_sixlowpan_frag_hint). This function might change
|
||||
* the content of that. Depending on the compile configuration
|
||||
* it might be ignored completely.
|
||||
* @param[in] page Current 6Lo dispatch parsing page.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -100,6 +100,9 @@ endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_fb,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/fb
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_minfwd,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/minfwd
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/frag/rb
|
||||
endif
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
MODULE := gnrc_sixlowpan_frag_minfwd
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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 <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "net/gnrc/netif/hdr.h"
|
||||
#include "net/gnrc/pktbuf.h"
|
||||
#include "net/gnrc/sixlowpan/internal.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "net/gnrc/sixlowpan/frag/minfwd.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static gnrc_pktsnip_t *_netif_hdr_from_vrbe(const gnrc_sixlowpan_frag_vrb_t *vrbe)
|
||||
{
|
||||
gnrc_pktsnip_t *res = gnrc_netif_hdr_build(NULL, 0, vrbe->super.dst,
|
||||
vrbe->super.dst_len);
|
||||
if (res == NULL) {
|
||||
DEBUG("6lo minfwd: can't allocate netif header for forwarding.\n");
|
||||
return NULL;
|
||||
}
|
||||
gnrc_netif_hdr_set_netif(res->data, vrbe->out_netif);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline bool _is_last_frag(const gnrc_sixlowpan_frag_vrb_t *vrbe)
|
||||
{
|
||||
return (vrbe->super.current_size >= vrbe->super.datagram_size);
|
||||
}
|
||||
|
||||
int gnrc_sixlowpan_frag_minfwd_forward(gnrc_pktsnip_t *pkt,
|
||||
const sixlowpan_frag_n_t *frag,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe,
|
||||
unsigned page)
|
||||
{
|
||||
sixlowpan_frag_t *new;
|
||||
gnrc_pktsnip_t *tmp;
|
||||
const size_t fragsnip_size = sizeof(sixlowpan_frag_t) +
|
||||
((sixlowpan_frag_1_is((sixlowpan_frag_t *)frag))
|
||||
? 0U : sizeof(frag->offset));
|
||||
|
||||
assert(vrbe != NULL);
|
||||
assert(pkt != NULL);
|
||||
assert(frag != NULL);
|
||||
if ((tmp = gnrc_pktbuf_add(pkt, frag, fragsnip_size,
|
||||
GNRC_NETTYPE_SIXLOWPAN)) == NULL) {
|
||||
DEBUG("6lo minfwd: unable to allocate new fragmentation header.\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
pkt = tmp;
|
||||
new = pkt->data;
|
||||
new->tag = byteorder_htons(vrbe->out_tag);
|
||||
tmp = _netif_hdr_from_vrbe(vrbe);
|
||||
if (tmp == NULL) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (_is_last_frag(vrbe)) {
|
||||
DEBUG("6lo minfwd: current_size (%u) >= datagram_size (%u)\n",
|
||||
vrbe->super.current_size, vrbe->super.datagram_size);
|
||||
gnrc_sixlowpan_frag_vrb_rm(vrbe);
|
||||
}
|
||||
else {
|
||||
gnrc_netif_hdr_t *netif_hdr = tmp->data;
|
||||
|
||||
netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_MORE_DATA;
|
||||
}
|
||||
pkt = gnrc_pkt_prepend(pkt, tmp);
|
||||
gnrc_sixlowpan_dispatch_send(pkt, NULL, page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gnrc_sixlowpan_frag_minfwd_frag_iphc(gnrc_pktsnip_t *pkt,
|
||||
size_t orig_datagram_size,
|
||||
const ipv6_addr_t *ipv6_dst,
|
||||
gnrc_sixlowpan_frag_fb_t *fbuf)
|
||||
{
|
||||
gnrc_netif_t *netif;
|
||||
int res = -1;
|
||||
|
||||
assert(fbuf != NULL);
|
||||
assert((pkt != NULL) && (pkt->type == GNRC_NETTYPE_NETIF));
|
||||
assert((pkt->next != NULL) && (pkt->next->type == GNRC_NETTYPE_SIXLOWPAN));
|
||||
netif = gnrc_netif_hdr_get_netif(pkt->data);
|
||||
|
||||
if (!ipv6_addr_is_link_local(ipv6_dst) &&
|
||||
(fbuf->datagram_size > netif->sixlo.max_frag_size)) {
|
||||
fbuf->pkt = pkt; /* packet might have been rewritten */
|
||||
/* put slack of IPHC in first fragment */
|
||||
fbuf->hint.fragsz = pkt->next->size;
|
||||
fbuf->hint.fragsz_uncomp = orig_datagram_size -
|
||||
gnrc_pkt_len(pkt->next->next);
|
||||
gnrc_sixlowpan_frag_send(NULL, fbuf, 0);
|
||||
res = 0;
|
||||
}
|
||||
else {
|
||||
/* we don't forward link-local so free fbuf again */
|
||||
DEBUG("6lo minfwd: link-local address is not forwarded or "
|
||||
"no fragmentation necessary (%u < %u)\n",
|
||||
fbuf->datagram_size, netif->sixlo.max_frag_size);
|
||||
fbuf->pkt = NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@ -26,9 +26,8 @@
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
|
||||
#include "net/gnrc/sixlowpan/frag/stats.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_STATS */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_VRB
|
||||
#include "net/gnrc/sixlowpan/frag/minfwd.h"
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
|
||||
#include "net/sixlowpan.h"
|
||||
#include "thread.h"
|
||||
#include "xtimer.h"
|
||||
@ -49,8 +48,14 @@
|
||||
#ifndef RBUF_INT_SIZE
|
||||
/* same as ((int) ceil((double) N / D)) */
|
||||
#define DIV_CEIL(N, D) (((N) + (D) - 1) / (D))
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD)
|
||||
#define RBUF_INT_SIZE (DIV_CEIL(IPV6_MIN_MTU, GNRC_SIXLOWPAN_FRAG_SIZE) * \
|
||||
(CONFIG_GNRC_SIXLOWPAN_FRAG_RBUF_SIZE + \
|
||||
CONFIG_GNRC_SIXLOWPAN_FRAG_VRB_SIZE))
|
||||
#else /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) */
|
||||
#define RBUF_INT_SIZE (DIV_CEIL(IPV6_MIN_MTU, GNRC_SIXLOWPAN_FRAG_SIZE) * \
|
||||
CONFIG_GNRC_SIXLOWPAN_FRAG_RBUF_SIZE)
|
||||
#endif /* IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) */
|
||||
#endif
|
||||
|
||||
static gnrc_sixlowpan_frag_rb_int_t rbuf_int[RBUF_INT_SIZE];
|
||||
@ -91,8 +96,19 @@ enum {
|
||||
RBUF_ADD_ERROR = -1,
|
||||
RBUF_ADD_REPEAT = -2,
|
||||
RBUF_ADD_DUPLICATE = -3,
|
||||
RBUF_ADD_FORWARDED = -4,
|
||||
};
|
||||
|
||||
static bool _check_hdr(gnrc_pktsnip_t *hdr, unsigned page);
|
||||
static void _adapt_hdr(gnrc_pktsnip_t *hdr, unsigned page);
|
||||
static int _forward_frag(gnrc_pktsnip_t *pkt, size_t frag_hdr_size,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe, unsigned page);
|
||||
static int _forward_uncomp(gnrc_pktsnip_t *pkt,
|
||||
gnrc_sixlowpan_frag_rb_t *rbuf,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe,
|
||||
unsigned page);
|
||||
static int _rbuf_resize_for_reassembly(gnrc_sixlowpan_frag_rb_t *rbuf);
|
||||
|
||||
static int _check_fragments(gnrc_sixlowpan_frag_rb_base_t *entry,
|
||||
size_t frag_size, size_t offset)
|
||||
{
|
||||
@ -221,7 +237,13 @@ static size_t _6lo_frag_size(gnrc_pktsnip_t *pkt, size_t offset, uint8_t *data)
|
||||
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
size_t offset, unsigned page)
|
||||
{
|
||||
gnrc_sixlowpan_frag_rb_t *entry;
|
||||
union {
|
||||
gnrc_sixlowpan_frag_rb_base_t *super;
|
||||
gnrc_sixlowpan_frag_rb_t *rbuf;
|
||||
gnrc_sixlowpan_frag_vrb_t *vrb;
|
||||
} 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;
|
||||
int res;
|
||||
@ -236,29 +258,62 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
datagram_tag = sixlowpan_frag_datagram_tag(pkt->data);
|
||||
|
||||
gnrc_sixlowpan_frag_rb_gc();
|
||||
res = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
|
||||
gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
|
||||
datagram_size, datagram_tag, page);
|
||||
|
||||
if (res < 0) {
|
||||
/* only check VRB for subsequent frags, first frags create and not get VRB
|
||||
* entries below */
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) &&
|
||||
(offset > 0) &&
|
||||
sixlowpan_frag_n_is(pkt->data) &&
|
||||
(entry.vrb = gnrc_sixlowpan_frag_vrb_get(src, netif_hdr->src_l2addr_len,
|
||||
datagram_tag)) != NULL) {
|
||||
DEBUG("6lo rbuf minfwd: VRB entry found, trying to forward\n");
|
||||
switch (_check_fragments(entry.super, frag_size, offset)) {
|
||||
case RBUF_ADD_REPEAT:
|
||||
DEBUG("6lo rbuf minfwd: overlap found; dropping VRB\n");
|
||||
gnrc_sixlowpan_frag_vrb_rm(entry.vrb);
|
||||
/* we don't repeat for VRB */
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_ERROR;
|
||||
case RBUF_ADD_DUPLICATE:
|
||||
DEBUG("6lo rbuf minfwd: not forwarding duplicate\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_FORWARDED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
res = RBUF_ADD_ERROR;
|
||||
if (_rbuf_update_ints(entry.super, offset, frag_size)) {
|
||||
DEBUG("6lo rbuf minfwd: trying to forward fragment\n");
|
||||
entry.super->current_size += (uint16_t)frag_size;
|
||||
if (_forward_frag(pkt, sizeof(sixlowpan_frag_n_t), entry.vrb,
|
||||
page) < 0) {
|
||||
DEBUG("6lo rbuf minfwd: unable to forward fragment\n");
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
res = RBUF_ADD_FORWARDED;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else if ((res = _rbuf_get(src, netif_hdr->src_l2addr_len,
|
||||
dst, netif_hdr->dst_l2addr_len,
|
||||
datagram_size, datagram_tag, page)) < 0) {
|
||||
DEBUG("6lo rbuf: reassembly buffer full.\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
entry = &rbuf[res];
|
||||
if ((offset + frag_size) > entry->super.datagram_size) {
|
||||
entry.rbuf = &rbuf[res];
|
||||
if ((offset + frag_size) > entry.super->datagram_size) {
|
||||
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_pktbuf_release(entry.rbuf->pkt);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry.rbuf);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
|
||||
switch (_check_fragments(&entry->super, frag_size, offset)) {
|
||||
switch (_check_fragments(entry.super, frag_size, offset)) {
|
||||
case RBUF_ADD_REPEAT:
|
||||
DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n");
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry);
|
||||
gnrc_pktbuf_release(entry.rbuf->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry.rbuf);
|
||||
return RBUF_ADD_REPEAT;
|
||||
case RBUF_ADD_DUPLICATE:
|
||||
gnrc_pktbuf_release(pkt);
|
||||
@ -267,9 +322,9 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
break;
|
||||
}
|
||||
|
||||
if (_rbuf_update_ints(&entry->super, offset, frag_size)) {
|
||||
if (_rbuf_update_ints(entry.super, offset, frag_size)) {
|
||||
DEBUG("6lo rbuf: add fragment data\n");
|
||||
entry->super.current_size += (uint16_t)frag_size;
|
||||
entry.super->current_size += (uint16_t)frag_size;
|
||||
if (offset == 0) {
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||
if (sixlowpan_iphc_is(data)) {
|
||||
@ -279,17 +334,17 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
if (frag_hdr == NULL) {
|
||||
DEBUG("6lo rbuf: unable to mark fragment header. "
|
||||
"aborting reassembly.\n");
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_pktbuf_release(entry.rbuf->pkt);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry.rbuf);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
else {
|
||||
DEBUG("6lo rbuf: handing over to IPHC reception.\n");
|
||||
/* `pkt` released in IPHC */
|
||||
gnrc_sixlowpan_iphc_recv(pkt, entry, 0);
|
||||
gnrc_sixlowpan_iphc_recv(pkt, entry.rbuf, 0);
|
||||
/* check if entry was deleted in IPHC (error case) */
|
||||
if (gnrc_sixlowpan_frag_rb_entry_empty(entry)) {
|
||||
if (gnrc_sixlowpan_frag_rb_entry_empty(entry.rbuf)) {
|
||||
res = RBUF_ADD_ERROR;
|
||||
}
|
||||
return res;
|
||||
@ -300,15 +355,48 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
if (data[0] == SIXLOWPAN_UNCOMP) {
|
||||
DEBUG("6lo rbuf: detected uncompressed datagram\n");
|
||||
data++;
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) &&
|
||||
/* only try minimal forwarding when fragment is the only
|
||||
* fragment in reassembly buffer yet */
|
||||
sixlowpan_frag_1_is(pkt->data) &&
|
||||
(entry.super->current_size == frag_size)) {
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe;
|
||||
gnrc_pktsnip_t tmp = {
|
||||
.data = data,
|
||||
.size = frag_size,
|
||||
.users = 1,
|
||||
};
|
||||
|
||||
if (_check_hdr(&tmp, page) &&
|
||||
(vrbe = gnrc_sixlowpan_frag_vrb_from_route(
|
||||
entry.super,
|
||||
gnrc_netif_hdr_get_netif(netif_hdr),
|
||||
&tmp))) {
|
||||
_adapt_hdr(&tmp, page);
|
||||
return _forward_uncomp(pkt, rbuf, vrbe, page);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(((uint8_t *)entry->pkt->data) + offset, data,
|
||||
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
|
||||
* with fragment forwarding as minimal as possible in
|
||||
* `_rbuf_get()` */
|
||||
res = _rbuf_resize_for_reassembly(entry.rbuf);
|
||||
if (res == RBUF_ADD_ERROR) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
memcpy(((uint8_t *)entry.rbuf->pkt->data) + offset, data,
|
||||
frag_size);
|
||||
}
|
||||
else {
|
||||
/* no space left in rbuf interval buffer*/
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry);
|
||||
gnrc_pktbuf_release(entry.rbuf->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(entry.rbuf);
|
||||
res = RBUF_ADD_ERROR;
|
||||
}
|
||||
/* no errors and not consumed => release packet */
|
||||
@ -501,7 +589,24 @@ static int _rbuf_get(const void *src, size_t src_len,
|
||||
default:
|
||||
reass_type = GNRC_NETTYPE_UNDEF;
|
||||
}
|
||||
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_VRB)) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_IPHC)) {
|
||||
/* only allocate enough space to decompress IPv6 header
|
||||
* for forwarding information */
|
||||
res->pkt = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t),
|
||||
reass_type);
|
||||
}
|
||||
else {
|
||||
/* try fragment forwarding without IPHC. Since `res->pkt == NULL`
|
||||
* is not a valid value for a reassembly buffer entry, we need to
|
||||
* set it to at least a packet snip for now */
|
||||
res->pkt = gnrc_pktbuf_add(NULL, NULL, 0, reass_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* reassemble whole datagram without direct fragment forwarding */
|
||||
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
|
||||
}
|
||||
if (res->pkt == NULL) {
|
||||
DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n");
|
||||
return -1;
|
||||
@ -639,5 +744,98 @@ int gnrc_sixlowpan_frag_rb_dispatch_when_complete(gnrc_sixlowpan_frag_rb_t *rbuf
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool _check_hdr(gnrc_pktsnip_t *hdr, unsigned page)
|
||||
{
|
||||
switch (page) {
|
||||
#if IS_USED(MODULE_GNRC_NETTYPE_IPV6)
|
||||
case 0: {
|
||||
ipv6_hdr_t *ipv6_hdr = hdr->data;
|
||||
|
||||
if (ipv6_hdr->hl <= 1) {
|
||||
DEBUG("6lo rbuf minfwd: minimal hop-limit reached\n");
|
||||
return false;
|
||||
}
|
||||
hdr->type = GNRC_NETTYPE_IPV6;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
hdr->type = GNRC_NETTYPE_UNDEF;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _adapt_hdr(gnrc_pktsnip_t *hdr, unsigned page)
|
||||
{
|
||||
switch (page) {
|
||||
#if IS_USED(MODULE_GNRC_NETTYPE_IPV6)
|
||||
case 0: {
|
||||
ipv6_hdr_t *ipv6_hdr = hdr->data;
|
||||
|
||||
ipv6_hdr->hl--;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
(void)hdr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _forward_frag(gnrc_pktsnip_t *pkt, size_t frag_hdr_size,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe, unsigned page)
|
||||
{
|
||||
int res = -ENOTSUP;
|
||||
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD)) {
|
||||
gnrc_pktsnip_t *frag = gnrc_pktbuf_mark(pkt, frag_hdr_size,
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
if (frag == NULL) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
res = -ENOMEM;
|
||||
}
|
||||
else {
|
||||
pkt = gnrc_pkt_delete(pkt, frag);
|
||||
frag->next = NULL;
|
||||
/* remove netif header */
|
||||
gnrc_pktbuf_remove_snip(pkt, pkt->next);
|
||||
res = gnrc_sixlowpan_frag_minfwd_forward(pkt, frag->data, vrbe,
|
||||
page);
|
||||
gnrc_pktbuf_release(frag);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int _forward_uncomp(gnrc_pktsnip_t *pkt,
|
||||
gnrc_sixlowpan_frag_rb_t *rbuf,
|
||||
gnrc_sixlowpan_frag_vrb_t *vrbe,
|
||||
unsigned page)
|
||||
{
|
||||
DEBUG("6lo rbuf minfwd: found route, trying to forward\n");
|
||||
int res = _forward_frag(pkt, sizeof(sixlowpan_frag_t),
|
||||
vrbe, page);
|
||||
|
||||
/* prevent intervals from being deleted (they are in the
|
||||
* VRB now) */
|
||||
rbuf->super.ints = NULL;
|
||||
gnrc_pktbuf_release(rbuf->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(rbuf);
|
||||
return (res == 0) ? RBUF_ADD_SUCCESS : RBUF_ADD_ERROR;
|
||||
}
|
||||
|
||||
static int _rbuf_resize_for_reassembly(gnrc_sixlowpan_frag_rb_t *rbuf)
|
||||
{
|
||||
DEBUG("6lo rbuf: just do normal reassembly\n");
|
||||
if (gnrc_pktbuf_realloc_data(rbuf->pkt,
|
||||
rbuf->super.datagram_size) != 0) {
|
||||
DEBUG("6lo rbuf minfwd: can't allocate packet data\n");
|
||||
gnrc_pktbuf_release(rbuf->pkt);
|
||||
gnrc_sixlowpan_frag_rb_remove(rbuf);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
return RBUF_ADD_SUCCESS;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -288,12 +288,40 @@ static void _send(gnrc_pktsnip_t *pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||
if (netif->flags & GNRC_NETIF_FLAGS_6LO_HC) {
|
||||
gnrc_sixlowpan_iphc_send(pkt, NULL, 0);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_IPHC) &&
|
||||
netif->flags & GNRC_NETIF_FLAGS_6LO_HC) {
|
||||
gnrc_sixlowpan_frag_fb_t *fbuf;
|
||||
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_HINT) &&
|
||||
IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD)) {
|
||||
/* prepare for sending with IPHC slack in first fragment */
|
||||
fbuf = gnrc_sixlowpan_frag_fb_get();
|
||||
if (fbuf != NULL) {
|
||||
fbuf->pkt = pkt;
|
||||
fbuf->datagram_size = datagram_size;
|
||||
fbuf->tag = gnrc_sixlowpan_frag_fb_next_tag();
|
||||
fbuf->offset = 0;
|
||||
/* fbuf->hint only exists with the `gnrc_sixlowpan_frag_hint`
|
||||
* module, so despite already specifying that this `if` block
|
||||
* only works with `IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_HINT)`
|
||||
* above, we need to add a pre-processor `#if` here */
|
||||
#if IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_HINT)
|
||||
fbuf->hint.fragsz = 0;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DEBUG("6lo: Not enough resources to fragment packet. "
|
||||
"Dropping packet\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fbuf = NULL;
|
||||
}
|
||||
gnrc_sixlowpan_iphc_send(pkt, fbuf, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!_add_uncompr_disp(pkt)) {
|
||||
/* adding uncompressed dispatch failed */
|
||||
DEBUG("6lo: no space left in packet buffer\n");
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "net/gnrc/sixlowpan.h"
|
||||
#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_VRB
|
||||
#include "net/gnrc/sixlowpan/frag/vrb.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_VRB */
|
||||
@ -823,6 +824,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
payload_offset - sizeof(ipv6_hdr_t));
|
||||
}
|
||||
if ((rbuf == NULL) &&
|
||||
/* (rbuf == NULL) => forwarding is not affected by this */
|
||||
(gnrc_pktbuf_realloc_data(ipv6, uncomp_hdr_len + payload_len) != 0)) {
|
||||
DEBUG("6lo iphc: no space left to copy payload\n");
|
||||
_recv_error_release(sixlo, ipv6, rbuf);
|
||||
@ -851,6 +853,12 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
}
|
||||
}
|
||||
if ((ipv6 == NULL) || (res < 0)) {
|
||||
/* TODO: There is a potential to fall-back to classic reassembly
|
||||
* when ipv6 != NULL. However, since `ipv6` was reversed in
|
||||
* `_encode_frag_for_forwarding`, that step needs to be reversed
|
||||
* or a version of the old ipv6 needs to be held in the buffer.
|
||||
* For now, just drop the packet all together in an error case
|
||||
*/
|
||||
gnrc_sixlowpan_frag_vrb_rm(vrbe);
|
||||
}
|
||||
gnrc_pktbuf_release(sixlo);
|
||||
@ -915,6 +923,11 @@ static int _forward_frag(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *frag_hdr,
|
||||
/* remove rewritten netif header (forwarding implementation must do this
|
||||
* anyway) */
|
||||
pkt = gnrc_pktbuf_remove_snip(pkt, pkt);
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) &&
|
||||
sixlowpan_frag_is(frag_hdr->data)) {
|
||||
return gnrc_sixlowpan_frag_minfwd_forward(pkt, frag_hdr->data, vrbe,
|
||||
page);
|
||||
}
|
||||
/* the following is just debug output for testing without any forwarding
|
||||
* scheme */
|
||||
DEBUG("6lo iphc: Do not know how to forward fragment from (%s, %u) ",
|
||||
@ -1609,9 +1622,20 @@ void gnrc_sixlowpan_iphc_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
|
||||
gnrc_pktsnip_t *tmp;
|
||||
/* datagram size before compression */
|
||||
size_t orig_datagram_size = gnrc_pkt_len(pkt->next);
|
||||
ipv6_hdr_t *ipv6_hdr = pkt->next->data;
|
||||
ipv6_addr_t dst;
|
||||
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD)) {
|
||||
dst = ipv6_hdr->dst; /* copying original destination address */
|
||||
}
|
||||
|
||||
(void)ctx;
|
||||
if ((tmp = _iphc_encode(pkt, pkt->data, netif))) {
|
||||
if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_MINFWD) && (ctx != NULL) &&
|
||||
(gnrc_sixlowpan_frag_minfwd_frag_iphc(tmp, orig_datagram_size, &dst,
|
||||
ctx) == 0)) {
|
||||
DEBUG("6lo iphc minfwd: putting slack in first fragment\n");
|
||||
return;
|
||||
}
|
||||
gnrc_sixlowpan_multiplex_by_size(tmp, orig_datagram_size, netif, page);
|
||||
}
|
||||
else {
|
||||
|
||||
19
tests/gnrc_sixlowpan_frag_minfwd/Makefile
Normal file
19
tests/gnrc_sixlowpan_frag_minfwd/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
USEMODULE += gnrc_sixlowpan_frag_minfwd
|
||||
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
|
||||
37
tests/gnrc_sixlowpan_frag_minfwd/Makefile.ci
Normal file
37
tests/gnrc_sixlowpan_frag_minfwd/Makefile.ci
Normal file
@ -0,0 +1,37 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
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-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32l0538-disco \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
z1 \
|
||||
#
|
||||
3
tests/gnrc_sixlowpan_frag_minfwd/app.config
Normal file
3
tests/gnrc_sixlowpan_frag_minfwd/app.config
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_KCONFIG_USEMODULE_GNRC_IPV6_NIB=y
|
||||
# disable router solicitations so they don't interfere with the tests
|
||||
CONFIG_GNRC_IPV6_NIB_NO_RTR_SOL=y
|
||||
51
tests/gnrc_sixlowpan_frag_minfwd/common.h
Normal file
51
tests/gnrc_sixlowpan_frag_minfwd/common.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 */
|
||||
/** @} */
|
||||
1689
tests/gnrc_sixlowpan_frag_minfwd/main.c
Normal file
1689
tests/gnrc_sixlowpan_frag_minfwd/main.c
Normal file
File diff suppressed because it is too large
Load Diff
123
tests/gnrc_sixlowpan_frag_minfwd/mockup_netif.c
Normal file
123
tests/gnrc_sixlowpan_frag_minfwd/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_minfwd/tests/01-run.py
Executable file
19
tests/gnrc_sixlowpan_frag_minfwd/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…
x
Reference in New Issue
Block a user