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:
parent
79c8fc5405
commit
8c3dc66ad8
@ -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)))
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
115
sys/include/net/gnrc/sixlowpan/frag/fb.h
Normal file
115
sys/include/net/gnrc/sixlowpan/frag/fb.h
Normal 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 */
|
||||
/** @} */
|
@ -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
|
||||
|
3
sys/net/gnrc/network_layer/sixlowpan/frag/fb/Makefile
Normal file
3
sys/net/gnrc/network_layer/sixlowpan/frag/fb/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE := gnrc_sixlowpan_frag_fb
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user