Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

gnrc_sixlowpan_frag: initial import of minimal forwarding #11068

Merged
merged 10 commits into from
Dec 1, 2020
Merged
7 changes: 7 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,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
Expand Down
3 changes: 3 additions & 0 deletions sys/include/net/gnrc/sixlowpan/frag/fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down
100 changes: 100 additions & 0 deletions sys/include/net/gnrc/sixlowpan/frag/minfwd.h
Original file line number Diff line number Diff line change
@@ -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 */
/** @} */
6 changes: 6 additions & 0 deletions sys/include/net/gnrc/sixlowpan/iphc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
*/
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE := gnrc_sixlowpan_frag_minfwd

include $(RIOTBASE)/Makefile.base
Original file line number Diff line number Diff line change
@@ -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;
}

/** @} */
Loading