From 4ce2d01cb992e2b1bca9a306d6784b5cf057174f Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 12 Feb 2019 12:24:51 +0100 Subject: [PATCH] gnrc_sixlowpan_frag: initial import of minimal forwarding See https://tools.ietf.org/html/draft-ietf-6lo-minimal-fragment-04 --- sys/Makefile.dep | 7 ++ sys/include/net/gnrc/sixlowpan/frag/minfwd.h | 66 ++++++++++++++ sys/net/gnrc/Makefile | 3 + .../sixlowpan/frag/minfwd/Makefile | 3 + .../frag/minfwd/gnrc_sixlowpan_frag_minfwd.c | 89 +++++++++++++++++++ 5 files changed, 168 insertions(+) create mode 100644 sys/include/net/gnrc/sixlowpan/frag/minfwd.h create mode 100644 sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/Makefile create mode 100644 sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/gnrc_sixlowpan_frag_minfwd.c diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 34f0b3ca23..90383e3fa4 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -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 diff --git a/sys/include/net/gnrc/sixlowpan/frag/minfwd.h b/sys/include/net/gnrc/sixlowpan/frag/minfwd.h new file mode 100644 index 0000000000..af8705899b --- /dev/null +++ b/sys/include/net/gnrc/sixlowpan/frag/minfwd.h @@ -0,0 +1,66 @@ +/* + * 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 + */ +#ifndef NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H +#define NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H + +#include + +#include "net/gnrc/pkt.h" +#include "net/gnrc/netif.h" +#include "net/gnrc/sixlowpan/frag.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); + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_SIXLOWPAN_FRAG_MINFWD_H */ +/** @} */ diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index 2322bed62e..dc63650d80 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -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 diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/Makefile b/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/Makefile new file mode 100644 index 0000000000..6db089d5b0 --- /dev/null +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/Makefile @@ -0,0 +1,3 @@ +MODULE := gnrc_sixlowpan_frag_minfwd + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/gnrc_sixlowpan_frag_minfwd.c b/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/gnrc_sixlowpan_frag_minfwd.c new file mode 100644 index 0000000000..86a0983972 --- /dev/null +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/minfwd/gnrc_sixlowpan_frag_minfwd.c @@ -0,0 +1,89 @@ +/* + * 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 + */ + +#include +#include + +#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; +} + +/** @} */