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

gnrc_sixlowpan_frag: factor-out and rename fragmentation buffer

The name `fragment_msg` or `frag_msg`/`msg_frag` always to me was a bit
misplaced, as it basically implements an asynchronous fragmentation
buffer and doesn't necessarily have anything to do with messages.
This change

1. changes the name to `fb` (for fragmentation buffer)
2. factors its code out to its own sub-module so it can be re-used by
   other 6LoWPAN fragmentation schemes like [Selective Fragment
   Recovery]

[Selective Fragment Recovery]: https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05
This commit is contained in:
Martine Lenders 2019-10-17 16:56:38 +02:00
parent 79c8fc5405
commit 8c3dc66ad8
11 changed files with 253 additions and 170 deletions

View File

@ -212,15 +212,21 @@ endif
ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE)))
USEMODULE += gnrc_sixlowpan
USEMODULE += gnrc_sixlowpan_frag_fb
USEMODULE += gnrc_sixlowpan_frag_rb
endif
ifneq (,$(filter gnrc_sixlowpan_frag_fb,$(USEMODULE)))
USEMODULE += core_msg
endif
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter gnrc_sixlowpan_frag_vrb,$(USEMODULE)))
USEMODULE += xtimer
USEMODULE += gnrc_sixlowpan_frag_fb
endif
ifneq (,$(filter gnrc_sixlowpan_iphc,$(USEMODULE)))

View File

@ -51,14 +51,14 @@ extern "C" {
/**
* @brief Number of datagrams that can be fragmented simultaneously
*
* This determines the number of @ref gnrc_sixlowpan_msg_frag_t instances
* This determines the number of @ref gnrc_sixlowpan_frag_fb_t instances
* available.
*
* @note Only applicable with
* [gnrc_sixlowpan_frag](@ref net_gnrc_sixlowpan_frag) module
* [gnrc_sixlowpan_frag_fb](@ref net_gnrc_sixlowpan_frag_fb) module
*/
#ifndef GNRC_SIXLOWPAN_MSG_FRAG_SIZE
#define GNRC_SIXLOWPAN_MSG_FRAG_SIZE (1U)
#ifndef GNRC_SIXLOWPAN_FRAG_FB_SIZE
#define GNRC_SIXLOWPAN_FRAG_FB_SIZE (1U)
#endif
/**

View File

@ -26,15 +26,14 @@
#define NET_GNRC_SIXLOWPAN_FRAG_H
#include <inttypes.h>
#include <stdbool.h>
#include "byteorder.h"
#include "msg.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/netif/hdr.h"
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
#include "net/gnrc/sixlowpan/frag/hint.h"
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
#include "net/gnrc/sixlowpan/frag/fb.h"
#include "net/gnrc/sixlowpan/internal.h"
#include "net/ieee802154.h"
#include "net/sixlowpan.h"
@ -43,34 +42,6 @@
extern "C" {
#endif
/**
* @name Message types
* @{
*/
/**
* @brief Message type for passing one 6LoWPAN fragment down the network stack
*/
#define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225)
/** @} */
/**
* @brief Definition of 6LoWPAN fragmentation type.
*/
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 */
uint16_t tag; /**< Tag used for the fragment */
uint16_t offset; /**< Offset of the Nth fragment from the beginning of the
* payload datagram */
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
/**
* @brief Hint for the size (smaller than link-layer PDU) for the next
* fragment to sent
*/
gnrc_sixlowpan_frag_hint_t hint;
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
} gnrc_sixlowpan_msg_frag_t;
#if defined(MODULE_GNRC_SIXLOWPAN_FRAG_STATS) || DOXYGEN
/**
* @brief Statistics on fragmentation and reassembly
@ -81,7 +52,7 @@ typedef struct {
unsigned rbuf_full; /**< counts the number of events where the
* reassembly buffer is full */
unsigned frag_full; /**< counts the number of events that there where
* no @ref gnrc_sixlowpan_msg_frag_t available */
* no @ref gnrc_sixlowpan_frag_fb_t available */
#if defined(MODULE_GNRC_SIXLOWPAN_FRAG_VRB) || DOXYGEN
unsigned vrb_full; /**< counts the number of events where the virtual
* reassembly buffer is full */
@ -96,26 +67,17 @@ typedef struct {
gnrc_sixlowpan_frag_stats_t *gnrc_sixlowpan_frag_stats_get(void);
#endif
/**
* @brief Allocates a @ref gnrc_sixlowpan_msg_frag_t object
*
* @return A @ref gnrc_sixlowpan_msg_frag_t if available
* @return NULL, otherwise
*/
gnrc_sixlowpan_msg_frag_t *gnrc_sixlowpan_msg_frag_get(void);
/**
* @brief Sends a packet fragmented
*
* @pre `ctx != NULL`
* @pre gnrc_sixlowpan_msg_frag_t::pkt of @p ctx is equal to @p pkt or
* @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 Message containing status of the 6LoWPAN fragmentation
* progress. Expected to be of type
* @ref gnrc_sixlowpan_msg_frag_t, with
* gnrc_sixlowpan_msg_frag_t set to @p pkt. Must not be
* @param[in] ctx A fragmentation buffer entry. 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.
*/
@ -130,36 +92,6 @@ void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
*/
void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
/**
* @brief Generate a new datagram tag for sending
*
* @return A new datagram tag.
*/
uint16_t gnrc_sixlowpan_frag_next_tag(void);
/**
* @brief Sends a message to pass a further fragment down the network stack
*
* @see GNRC_SIXLOWPAN_MSG_FRAG_SND
*
* @param[in] fragment_msg A @ref gnrc_sixlowpan_msg_frag_t object
*
* @return true, when the message was sent
* @return false when sending the message failed.
*/
static inline bool gnrc_sixlowpan_frag_send_msg(gnrc_sixlowpan_msg_frag_t *fragment_msg)
{
msg_t msg;
msg.content.ptr = fragment_msg;
msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND;
#ifdef TEST_SUITES
return (msg_try_send(&msg, gnrc_sixlowpan_get_pid()) > 0);
#else
return (msg_send_to_self(&msg) != 0);
#endif
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,115 @@
/*
* 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_fb 6LoWPAN fragmentation buffer
* @ingroup net_gnrc_sixlowpan_frag
* @brief Buffer for asynchronous 6LoWPAN fragmentation
* @{
*
* @file
* @brief Fragmentation buffer definitions
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#ifndef NET_GNRC_SIXLOWPAN_FRAG_FB_H
#define NET_GNRC_SIXLOWPAN_FRAG_FB_H
#include <stdbool.h>
#include <stdint.h>
#include "msg.h"
#include "net/gnrc/pkt.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Message type for passing one 6LoWPAN fragment down the network stack
*/
#define GNRC_SIXLOWPAN_FRAG_FB_SND_MSG (0x0225)
/**
* @brief 6LoWPAN fragmentation buffer entry.
*/
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 */
uint16_t tag; /**< Tag used for the fragment */
uint16_t offset; /**< Offset of the Nth fragment from the beginning of the
* payload datagram */
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
/**
* @brief Hint for the size (smaller than link-layer PDU) for the next
* fragment to sent
*/
gnrc_sixlowpan_frag_hint_t hint;
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
} gnrc_sixlowpan_frag_fb_t;
#ifdef TEST_SUITES
/**
* @brief Reset fragmentation buffer
*
* @note Only available with test
*/
void gnrc_sixlowpan_frag_fb_reset(void);
#endif
/**
* @brief Allocates a fragmentation buffer entry
*
* @return A fragmentation buffer entry if available
* @return NULL, otherwise
*/
gnrc_sixlowpan_frag_fb_t *gnrc_sixlowpan_frag_fb_get(void);
/**
* @brief Generate a new datagram tag for sending
*
* @return A new datagram tag.
*/
uint16_t gnrc_sixlowpan_frag_fb_next_tag(void);
#if defined(TEST_SUITES) && !defined(DOXYGEN)
#include "kernel_types.h"
/* can't include `net/sixlowpan.h` as this would create a cyclical include */
extern kernel_pid_t gnrc_sixlowpan_get_pid(void);
#endif
/**
* @brief Sends a message to pass a further fragment down the network stack
*
* @see GNRC_SIXLOWPAN_MSG_FRAG_SND
*
* @param[in] fbuf A fragmentation buffer entry
*]
* @return true, when the message was sent
* @return false when sending the message failed.
*/
static inline bool gnrc_sixlowpan_frag_fb_send(gnrc_sixlowpan_frag_fb_t *fbuf)
{
msg_t msg;
msg.content.ptr = fbuf;
msg.type = GNRC_SIXLOWPAN_FRAG_FB_SND_MSG;
#ifdef TEST_SUITES
return (msg_try_send(&msg, gnrc_sixlowpan_get_pid()) > 0);
#else
return (msg_send_to_self(&msg) != 0);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* NET_GNRC_SIXLOWPAN_FRAG_FB_H */
/** @} */

View File

@ -91,6 +91,9 @@ endif
ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE)))
DIRS += network_layer/sixlowpan/frag
endif
ifneq (,$(filter gnrc_sixlowpan_frag_fb,$(USEMODULE)))
DIRS += network_layer/sixlowpan/frag/fb
endif
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
DIRS += network_layer/sixlowpan/frag/rb
endif

View File

@ -0,0 +1,3 @@
MODULE := gnrc_sixlowpan_frag_fb
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,54 @@
/*
* 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 <stdint.h>
#include <string.h>
#include "net/gnrc/sixlowpan/config.h"
#include "net/gnrc/sixlowpan/frag/fb.h"
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
#include "net/gnrc/sixlowpan/frag/stats.h"
#endif
static gnrc_sixlowpan_frag_fb_t _fbs[GNRC_SIXLOWPAN_FRAG_FB_SIZE];
static uint16_t _current_tag;
#ifdef TEST_SUITES
void gnrc_sixlowpan_frag_fb_reset(void)
{
memset(_fbs, 0, sizeof(_fbs));
_current_tag = 0;
}
#endif
gnrc_sixlowpan_frag_fb_t *gnrc_sixlowpan_frag_fb_get(void)
{
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_FB_SIZE; i++) {
if (_fbs[i].pkt == NULL) {
return &_fbs[i];
}
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
gnrc_sixlowpan_frag_stats_get()->frag_full++;
#endif
return NULL;
}
uint16_t gnrc_sixlowpan_frag_fb_next_tag(void)
{
return (++_current_tag);
}
/** @} */

View File

@ -30,14 +30,11 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
static gnrc_sixlowpan_msg_frag_t _fragment_msg[GNRC_SIXLOWPAN_MSG_FRAG_SIZE];
#if ENABLE_DEBUG
/* For PRIu16 etc. */
#include <inttypes.h>
#endif
static uint16_t _current_tag;
static inline uint16_t _floor8(uint16_t length)
{
@ -50,41 +47,41 @@ static inline size_t _min(size_t a, size_t b)
}
static inline uint8_t _max_frag_size(gnrc_netif_t *iface,
gnrc_sixlowpan_msg_frag_t *fragment_msg)
gnrc_sixlowpan_frag_fb_t *fbuf)
{
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
if (fragment_msg->hint.fragsz > 0) {
if (fbuf->hint.fragsz > 0) {
/* account for rounding down to 8*/
return (fragment_msg->hint.fragsz & 0x7)
? (fragment_msg->hint.fragsz + 8U)
: fragment_msg->hint.fragsz;
return (fbuf->hint.fragsz & 0x7)
? (fbuf->hint.fragsz + 8U)
: fbuf->hint.fragsz;
}
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
(void)fragment_msg;
(void)fbuf;
return iface->sixlo.max_frag_size;
}
static inline int _payload_diff(gnrc_sixlowpan_msg_frag_t *fragment_msg,
static inline int _payload_diff(gnrc_sixlowpan_frag_fb_t *fbuf,
size_t payload_len)
{
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
if (fragment_msg->hint.fragsz > 0) {
return fragment_msg->hint.fragsz_uncomp - fragment_msg->hint.fragsz;
if (fbuf->hint.fragsz > 0) {
return fbuf->hint.fragsz_uncomp - fbuf->hint.fragsz;
}
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
return (fragment_msg->datagram_size - payload_len);
return (fbuf->datagram_size - payload_len);
}
static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt,
gnrc_sixlowpan_msg_frag_t *fragment_msg,
gnrc_sixlowpan_frag_fb_t *fbuf,
size_t payload_len, size_t size)
{
sixlowpan_frag_t *frag_hdr;
gnrc_netif_hdr_t *netif_hdr = pkt->data, *new_netif_hdr;
gnrc_pktsnip_t *netif, *frag;
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
size_t fragment_size = ((fragment_msg->hint.fragsz > 0) &&
(fragment_msg->offset == 0))
size_t fragment_size = ((fbuf->hint.fragsz > 0) &&
(fbuf->offset == 0))
? size /* we want the calculated fragment size
* to include full IPHC header */
: _min(size, payload_len);
@ -115,8 +112,8 @@ static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt,
}
frag_hdr = frag->data;
/* XXX: truncation of datagram_size > 4095 may happen here */
frag_hdr->disp_size = byteorder_htons(fragment_msg->datagram_size);
frag_hdr->tag = byteorder_htons(fragment_msg->tag);
frag_hdr->disp_size = byteorder_htons(fbuf->datagram_size);
frag_hdr->tag = byteorder_htons(fbuf->tag);
LL_PREPEND(frag, netif);
@ -141,25 +138,25 @@ static uint16_t _copy_pkt_to_frag(uint8_t *data, const gnrc_pktsnip_t *pkt,
}
static uint16_t _send_1st_fragment(gnrc_netif_t *iface,
gnrc_sixlowpan_msg_frag_t *fragment_msg,
gnrc_sixlowpan_frag_fb_t *fbuf,
size_t payload_len)
{
gnrc_pktsnip_t *frag, *pkt = fragment_msg->pkt;
gnrc_pktsnip_t *frag, *pkt = fbuf->pkt;
sixlowpan_frag_t *hdr;
uint8_t *data;
/* payload_len: actual size of the packet vs
* datagram_size: size of the uncompressed IPv6 packet */
int payload_diff = _payload_diff(fragment_msg, payload_len);
int payload_diff = _payload_diff(fbuf, payload_len);
uint16_t local_offset;
/* virtually add payload_diff to flooring to account for offset (must be divisable by 8)
* in uncompressed datagram */
uint16_t max_frag_size = _floor8(_max_frag_size(iface, fragment_msg) +
uint16_t max_frag_size = _floor8(_max_frag_size(iface, fbuf) +
payload_diff - sizeof(sixlowpan_frag_t)) -
payload_diff;
DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);
frag = _build_frag_pkt(pkt, fragment_msg, payload_len,
frag = _build_frag_pkt(pkt, fbuf, payload_len,
max_frag_size + sizeof(sixlowpan_frag_t));
if (frag == NULL) {
@ -179,19 +176,19 @@ static uint16_t _send_1st_fragment(gnrc_netif_t *iface,
DEBUG("6lo frag: send first fragment (datagram size: %u, "
"datagram tag: %" PRIu16 ", fragment size: %" PRIu16 ")\n",
fragment_msg->datagram_size, fragment_msg->tag, local_offset);
fbuf->datagram_size, fbuf->tag, local_offset);
gnrc_sixlowpan_dispatch_send(frag, NULL, 0);
return local_offset;
}
static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
gnrc_sixlowpan_msg_frag_t *fragment_msg,
gnrc_sixlowpan_frag_fb_t *fbuf,
size_t payload_len)
{
gnrc_pktsnip_t *frag, *pkt = fragment_msg->pkt;
gnrc_pktsnip_t *frag, *pkt = fbuf->pkt;
sixlowpan_frag_n_t *hdr;
uint8_t *data;
uint16_t local_offset = 0, offset_count = 0, offset = fragment_msg->offset;
uint16_t local_offset = 0, offset_count = 0, offset = fbuf->offset;
/* since dispatches aren't supposed to go into subsequent fragments, we need not account
* for payload difference as for the first fragment */
uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size -
@ -199,7 +196,7 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);
frag = _build_frag_pkt(pkt, fragment_msg,
frag = _build_frag_pkt(pkt, fbuf,
payload_len - offset + sizeof(sixlowpan_frag_n_t),
max_frag_size + sizeof(sixlowpan_frag_n_t));
@ -211,7 +208,7 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
data = (uint8_t *)(hdr + 1);
hdr->disp_size.u8[0] |= SIXLOWPAN_FRAG_N_DISP;
/* don't mention payload diff in offset */
hdr->offset = (uint8_t)((offset + _payload_diff(fragment_msg,
hdr->offset = (uint8_t)((offset + _payload_diff(fbuf,
payload_len)) >> 3);
pkt = pkt->next; /* don't copy netif header */
while ((pkt != NULL) && (offset_count != offset)) { /* go to offset */
@ -240,72 +237,59 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
DEBUG("6lo frag: send subsequent fragment (datagram size: %u, "
"datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), "
"fragment size: %" PRIu16 ")\n",
fragment_msg->datagram_size, fragment_msg->tag, hdr->offset,
fbuf->datagram_size, fbuf->tag, hdr->offset,
hdr->offset << 3, local_offset);
gnrc_sixlowpan_dispatch_send(frag, NULL, 0);
return local_offset;
}
gnrc_sixlowpan_msg_frag_t *gnrc_sixlowpan_msg_frag_get(void)
{
for (unsigned i = 0; i < GNRC_SIXLOWPAN_MSG_FRAG_SIZE; i++) {
if (_fragment_msg[i].pkt == NULL) {
return &_fragment_msg[i];
}
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_STATS
gnrc_sixlowpan_frag_stats_get()->frag_full++;
#endif
return NULL;
}
void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
{
assert(ctx != NULL);
gnrc_sixlowpan_msg_frag_t *fragment_msg = ctx;
gnrc_sixlowpan_frag_fb_t *fbuf = ctx;
gnrc_netif_t *iface;
uint16_t res;
/* payload_len: actual size of the packet vs
* datagram_size: size of the uncompressed IPv6 packet */
size_t payload_len = gnrc_pkt_len(fragment_msg->pkt->next);
size_t payload_len = gnrc_pkt_len(fbuf->pkt->next);
assert((fragment_msg->pkt == pkt) || (pkt == NULL));
assert((fbuf->pkt == pkt) || (pkt == NULL));
(void)page;
(void)pkt;
iface = gnrc_netif_hdr_get_netif(fragment_msg->pkt->data);
iface = gnrc_netif_hdr_get_netif(fbuf->pkt->data);
#if defined(DEVELHELP) && ENABLE_DEBUG
if (iface == NULL) {
DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n");
/* remove original packet from packet buffer */
gnrc_pktbuf_release(fragment_msg->pkt);
gnrc_pktbuf_release(fbuf->pkt);
/* 6LoWPAN free for next fragmentation */
fragment_msg->pkt = NULL;
fbuf->pkt = NULL;
return;
}
#endif
/* Check whether to send the first or an Nth fragment */
if (fragment_msg->offset == 0) {
if ((res = _send_1st_fragment(iface, fragment_msg, payload_len)) == 0) {
if (fbuf->offset == 0) {
if ((res = _send_1st_fragment(iface, fbuf, payload_len)) == 0) {
/* error sending first fragment */
DEBUG("6lo frag: error sending 1st fragment\n");
goto error;
}
}
/* (offset + (datagram_size - payload_len) < datagram_size) simplified */
else if (fragment_msg->offset < payload_len) {
if ((res = _send_nth_fragment(iface, fragment_msg, payload_len)) == 0) {
else if (fbuf->offset < payload_len) {
if ((res = _send_nth_fragment(iface, fbuf, payload_len)) == 0) {
/* error sending subsequent fragment */
DEBUG("6lo frag: error sending subsequent fragment"
"(offset = %u)\n", fragment_msg->offset);
"(offset = %u)\n", fbuf->offset);
goto error;
}
}
else {
goto error;
}
fragment_msg->offset += res;
if (!gnrc_sixlowpan_frag_send_msg(fragment_msg)) {
fbuf->offset += res;
if (!gnrc_sixlowpan_frag_fb_send(fbuf)) {
DEBUG("6lo frag: message queue full, can't issue next fragment "
"sending\n");
goto error;
@ -313,8 +297,8 @@ void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
thread_yield();
return;
error:
gnrc_pktbuf_release(fragment_msg->pkt);
fragment_msg->pkt = NULL;
gnrc_pktbuf_release(fbuf->pkt);
fbuf->pkt = NULL;
}
void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
@ -351,9 +335,4 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
gnrc_pktbuf_release(netif_hdr);
}
uint16_t gnrc_sixlowpan_frag_next_tag(void)
{
return (++_current_tag);
}
/** @} */

View File

@ -21,6 +21,7 @@
#include "net/gnrc/netif.h"
#include "xtimer.h"
#include "net/gnrc/sixlowpan/frag/fb.h"
#include "net/gnrc/sixlowpan/frag/vrb.h"
#define ENABLE_DEBUG (0)
@ -33,16 +34,6 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
static char addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
#endif /* MODULE_GNRC_IPV6_NIB */
#if !defined(MODULE_GNRC_SIXLOWPAN_FRAG) && defined(TEST_SUITES)
/* mock for e.g. testing */
uint16_t tag = 0;
uint16_t gnrc_sixlowpan_frag_next_tag(void)
{
return tag++;
}
#endif /* !defined(MODULE_GNRC_SIXLOWPAN_FRAG) && defined(TEST_SUITES) */
static inline bool _equal_index(const gnrc_sixlowpan_frag_vrb_t *vrbe,
const uint8_t *src, size_t src_len,
unsigned tag)
@ -73,7 +64,7 @@ gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add(
vrbe->super = *base;
vrbe->out_netif = out_netif;
memcpy(vrbe->super.dst, out_dst, out_dst_len);
vrbe->out_tag = gnrc_sixlowpan_frag_next_tag();
vrbe->out_tag = gnrc_sixlowpan_frag_fb_next_tag();
vrbe->super.dst_len = out_dst_len;
DEBUG("6lo vrb: creating entry (%s, ",
gnrc_netif_addr_to_str(vrbe->super.src,

View File

@ -121,25 +121,25 @@ void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
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_msg_frag_t *fragment_msg;
gnrc_sixlowpan_frag_fb_t *fbuf;
fragment_msg = gnrc_sixlowpan_msg_frag_get();
if (fragment_msg == NULL) {
fbuf = gnrc_sixlowpan_frag_fb_get();
if (fbuf == NULL) {
DEBUG("6lo: Not enough resources to fragment packet. "
"Dropping packet\n");
gnrc_pktbuf_release_error(pkt, ENOMEM);
return;
}
fragment_msg->pkt = pkt;
fragment_msg->datagram_size = orig_datagram_size;
fragment_msg->tag = gnrc_sixlowpan_frag_next_tag();
fbuf->pkt = pkt;
fbuf->datagram_size = orig_datagram_size;
fbuf->tag = gnrc_sixlowpan_frag_fb_next_tag();
/* Sending the first fragment has an offset==0 */
fragment_msg->offset = 0;
fbuf->offset = 0;
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
fragment_msg->hint.fragsz = 0;
fbuf->hint.fragsz = 0;
#endif
gnrc_sixlowpan_frag_send(pkt, fragment_msg, page);
gnrc_sixlowpan_frag_send(pkt, fbuf, page);
}
#endif
else {
@ -343,10 +343,15 @@ static void *_event_loop(void *args)
reply.content.value = -ENOTSUP;
msg_reply(&msg, &reply);
break;
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
case GNRC_SIXLOWPAN_MSG_FRAG_SND:
#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 */
break;
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_RB

View File

@ -18,6 +18,7 @@
#include "embUnit/embUnit.h"
#include "net/gnrc/sixlowpan/frag/fb.h"
#include "net/gnrc/sixlowpan/frag/vrb.h"
#include "xtimer.h"
@ -31,8 +32,6 @@
#define TEST_DST_LEN (8U)
#define TEST_TAG (26U)
extern uint16_t tag;
/* The interface is not used for anything by the VRB (it just is kept as a
* reference for forwarding) so an uninitialized one is enough */
static gnrc_netif_t _dummy_netif;
@ -58,14 +57,13 @@ static uint8_t _out_dst[] = TEST_OUT_DST;
static void set_up(void)
{
gnrc_sixlowpan_frag_vrb_reset();
tag = 0;
gnrc_sixlowpan_frag_fb_reset();
}
static void test_vrb_add__success(void)
{
gnrc_sixlowpan_frag_vrb_t *res;
tag = TEST_TAG_INITIAL;
TEST_ASSERT_NOT_NULL((res = gnrc_sixlowpan_frag_vrb_add(&_base,
&_dummy_netif,
_out_dst,
@ -88,15 +86,12 @@ static void test_vrb_add__success(void)
TEST_ASSERT_EQUAL_INT(sizeof(_out_dst), res->super.dst_len);
TEST_ASSERT_MESSAGE(memcmp(_out_dst, res->super.dst, sizeof(_out_dst)) == 0,
"TEST_DST != res->super.dst");
TEST_ASSERT_EQUAL_INT(TEST_TAG_INITIAL, res->out_tag);
TEST_ASSERT(TEST_TAG_INITIAL != tag);
}
static void test_vrb_add__duplicate(void)
{
gnrc_sixlowpan_frag_vrb_t *res1, *res2;
tag = TEST_TAG_INITIAL;
TEST_ASSERT_NOT_NULL((res1 = gnrc_sixlowpan_frag_vrb_add(&_base,
&_dummy_netif,
_out_dst,