Skip to content
New issue

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

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

Already on GitHub? Sign in 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 <[email protected]>
*/
#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 <[email protected]>
*/

#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