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_ipv6_ext_frag: Initial import of IPv6 reassembly #11596

Merged
merged 3 commits into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ ifneq (,$(filter gnrc_rpl_srh,$(USEMODULE)))
USEMODULE += gnrc_ipv6_ext_rh
endif

ifneq (,$(filter gnrc_ipv6_ext_frag,$(USEMODULE)))
USEMODULE += gnrc_ipv6_ext
USEMODULE += xtimer
endif

ifneq (,$(filter gnrc_ipv6_ext_rh,$(USEMODULE)))
USEMODULE += gnrc_ipv6_ext
endif
Expand Down
40 changes: 40 additions & 0 deletions sys/include/net/gnrc/ipv6/ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "net/gnrc/pkt.h"
#include "net/ipv6/ext.h"
#include "timex.h"

#ifdef MODULE_GNRC_IPV6_EXT_RH
#include "net/gnrc/ipv6/ext/rh.h"
Expand All @@ -38,6 +39,45 @@
extern "C" {
#endif

/**
* @defgroup net_gnrc_ipv6_ext_conf IPv6 extension header compile configurations
* @ingroup net_gnrc_ipv6_ext
* @ingroup config
* @{
*/
/**
* @brief IPv6 fragmentation reassembly buffer size
*
* This limits the total amount of datagrams that can be reassembled at the same time.
*
* @note Only applicable with [gnrc_ipv6_ext_frag](@ref net_gnrc_ipv6_ext_frag) module
*/
#ifndef GNRC_IPV6_EXT_FRAG_RBUF_SIZE
#define GNRC_IPV6_EXT_FRAG_RBUF_SIZE (1U)
miri64 marked this conversation as resolved.
Show resolved Hide resolved
#endif

/**
* @brief The number of total allocatable @ref gnrc_ipv6_ext_frag_limits_t objects
*
* This is the maximum number of receivable fragments, shared between all
* fragmented datagrams
*
* @note Only applicable with [gnrc_ipv6_ext_frag](@ref net_gnrc_ipv6_ext_frag) module
*/
#ifndef GNRC_IPV6_EXT_FRAG_LIMITS_POOL_SIZE
#define GNRC_IPV6_EXT_FRAG_LIMITS_POOL_SIZE (GNRC_IPV6_EXT_FRAG_RBUF_SIZE * 2U)
miri64 marked this conversation as resolved.
Show resolved Hide resolved
#endif

/**
* @brief Timeout for IPv6 fragmentation reassembly buffer entries in microseconds
*
* @note Only applicable with [gnrc_ipv6_ext_frag](@ref net_gnrc_ipv6_ext_frag) module
*/
#ifndef GNRC_IPV6_EXT_FRAG_RBUF_TIMEOUT_US
#define GNRC_IPV6_EXT_FRAG_RBUF_TIMEOUT_US (10U * US_PER_SEC)
#endif
/** @} **/

/**
* @brief Builds an extension header for sending.
*
Expand Down
147 changes: 147 additions & 0 deletions sys/include/net/gnrc/ipv6/ext/frag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* 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_ipv6_ext_frag Support for IPv6 fragmentation extension
* @ingroup net_gnrc_ipv6_ext
* @brief GNRC implementation of IPv6 fragmentation extension
* @{
*
* @file
* @brief GNRC fragmentation extension definitions
*
* @author Martine Lenders <[email protected]>
*/
#ifndef NET_GNRC_IPV6_EXT_FRAG_H
#define NET_GNRC_IPV6_EXT_FRAG_H

#include <stdint.h>

#include "clist.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/pktbuf.h"
#include "net/ipv6/hdr.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Message type to time reassembly buffer garbage collection
*/
#define GNRC_IPV6_EXT_FRAG_RBUF_GC (0xfe00U)

/**
* @brief Data type to describe limits of a single fragment in the reassembly
* buffer
*/
typedef struct gnrc_ipv6_ext_frag_limits {
struct gnrc_ipv6_ext_frag_limits *next; /**< limits of next fragment */
uint16_t start; /**< the start (= offset) of the fragment */
uint16_t end; /**< the exclusive end (= offset + length) of the
* fragment */
} gnrc_ipv6_ext_frag_limits_t;

/**
* @brief A reassembly buffer entry
*/
typedef struct {
gnrc_pktsnip_t *pkt; /**< the (partly) reassembled packet */
ipv6_hdr_t *ipv6; /**< the IPv6 header of gnrc_ipv6_ext_frag_rbuf_t::pkt */
/**
* @brief The limits of the fragments in the reassembled packet
*
* @note Members of this list can be cast to gnrc_ipv6_ext_frag_limits_t.
*/
clist_node_t limits;
uint32_t id; /**< the identification from the fragment headers */
uint32_t arrival; /**< arrival time of last received fragment */
uint16_t pkt_len; /**< length of gnrc_ipv6_ext_frag_rbuf_t::pkt */
uint8_t last; /**< received last fragment */
} gnrc_ipv6_ext_frag_rbuf_t;

/**
* @brief Initializes IPv6 fragmentation and reassembly
* @internal
*/
void gnrc_ipv6_ext_frag_init(void);

/**
* @brief Reassemble fragmented IPv6 packet
*
* @param[in] pkt A fragment of the IPv6 packet to be reassembled containing
* the fragment header in the first snip.
*
* @return The reassembled packet when @p pkt completed the reassembly
* @return NULL, when there are still fragments missing or an error occured
* during reassembly
*/
gnrc_pktsnip_t *gnrc_ipv6_ext_frag_reass(gnrc_pktsnip_t *pkt);

/**
* @name Reassembly buffer operations
* @{
*/
/**
* @brief Get a reassembly buffer by the identifying parameters
*
* @internal
* @see [RFC 8200, section 4.5](https://tools.ietf.org/html/rfc8200#section-4.5)
*
* @param[in] hdr IPv6 header to get source and destination address from.
* @param[in] id The identification from the fragment header.
*
* @return A reassembly buffer matching @p id ipv6_hdr_t::src and ipv6_hdr::dst
* of @p hdr or first free reassembly buffer. Will never be NULL, as
* in the case of the reassembly buffer being full, the entry with the
* lowest gnrc_ipv6_ext_frag_rbuf_t::arrival (serial-number-like) is
* removed.
*/
gnrc_ipv6_ext_frag_rbuf_t *gnrc_ipv6_ext_frag_rbuf_get(ipv6_hdr_t *ipv6,
uint32_t id);

/**
* @brief Frees a reassembly buffer entry (but does not release its
* gnrc_ipv6_ext_frag_rbuf_t::pkt)
*
* @param[in] rbuf A reassembly buffer entry.
*/
void gnrc_ipv6_ext_frag_rbuf_free(gnrc_ipv6_ext_frag_rbuf_t *rbuf);

/**
* @brief Delete a reassembly buffer entry (and release its
* gnrc_ipv6_ext_frag_rbuf_t::pkt)
*
* @note May be used by the IPv6 thread to remove a timed out reassembly
* buffer entry.
*
* @param[in] rbuf A reassembly buffer entry.
*/
static inline void gnrc_ipv6_ext_frag_rbuf_del(gnrc_ipv6_ext_frag_rbuf_t *rbuf)
{
gnrc_pktbuf_release(rbuf->pkt);
rbuf->pkt = NULL;
gnrc_ipv6_ext_frag_rbuf_free(rbuf);
}

/**
* @brief Garbage-collect reassembly buffer
*
* This calls @ref gnrc_ipv6_ext_frag_rbuf_del() for all reassembly buffer
* entries for which * gnrc_ipv6_ext_frag_rbuf_t::arrival is
* @ref GNRC_IPV6_EXT_FRAG_RBUF_TIMEOUT_US in the past.
*/
void gnrc_ipv6_ext_frag_rbuf_gc(void);
/** @} */

#ifdef __cplusplus
}
#endif

#endif /* NET_GNRC_IPV6_EXT_FRAG_H */
/** @} */
3 changes: 3 additions & 0 deletions sys/net/gnrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ endif
ifneq (,$(filter gnrc_ipv6_ext,$(USEMODULE)))
DIRS += network_layer/ipv6/ext
endif
ifneq (,$(filter gnrc_ipv6_ext_frag,$(USEMODULE)))
DIRS += network_layer/ipv6/ext/frag
endif
ifneq (,$(filter gnrc_ipv6_ext_rh,$(USEMODULE)))
DIRS += network_layer/ipv6/ext/rh
endif
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/network_layer/ipv6/ext/frag/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE := gnrc_ipv6_ext_frag

include $(RIOTBASE)/Makefile.base
Loading