From 39ed4baa92bf5fb1756bbfdc918a9520e9e336d0 Mon Sep 17 00:00:00 2001 From: Martine Lenders <mlenders@inf.fu-berlin.de> Date: Fri, 10 Apr 2015 12:02:55 +0200 Subject: [PATCH] ng_sixlowpan: initial import of a context buffer --- Makefile.dep | 5 + sys/Makefile | 3 + sys/include/net/ng_sixlowpan/ctx.h | 103 +++++++++++ .../network_layer/ng_sixlowpan/ctx/Makefile | 3 + .../ng_sixlowpan/ctx/ng_sixlowpan_ctx.c | 172 ++++++++++++++++++ 5 files changed, 286 insertions(+) create mode 100644 sys/include/net/ng_sixlowpan/ctx.h create mode 100644 sys/net/network_layer/ng_sixlowpan/ctx/Makefile create mode 100644 sys/net/network_layer/ng_sixlowpan/ctx/ng_sixlowpan_ctx.c diff --git a/Makefile.dep b/Makefile.dep index 5e40df93ee..2c14046231 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -48,6 +48,11 @@ ifneq (,$(filter sixlowpan,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE))) + USEMODULE += ng_ipv6_addr + USEMODULE += vtimer +endif + ifneq (,$(filter ng_ipv6_hdr,$(USEMODULE))) USEMODULE += ng_inet_csum USEMODULE += ng_pktbuf diff --git a/sys/Makefile b/sys/Makefile index b734317e10..dd4b6ba0dc 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -92,6 +92,9 @@ endif ifneq (,$(filter ng_pktbuf,$(USEMODULE))) DIRS += net/crosslayer/ng_pktbuf endif +ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE))) + DIRS += net/network_layer/ng_sixlowpan/ctx +endif ifneq (,$(filter netapi,$(USEMODULE))) DIRS += net/crosslayer/netapi endif diff --git a/sys/include/net/ng_sixlowpan/ctx.h b/sys/include/net/ng_sixlowpan/ctx.h new file mode 100644 index 0000000000..40e1544ebf --- /dev/null +++ b/sys/include/net/ng_sixlowpan/ctx.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * 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_ng_sixlowpan_ctx Contexts for 6LoWPAN address compression + * @ingroup net_ng_sixlowpan + * @brief Context buffer for stateful 6LoWPAN address compression + * @see <a href="https://tools.ietf.org/html/rfc6282#section-3.1.2"> + * RFC 6282, section 3.1.2 + * </a> + * @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2"> + * RFC 6775, section 4.2 + * </a> + * @{ + * + * @file + * @brief Context buffer definitions + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef NG_SIXLOWPAN_CTX_H_ +#define NG_SIXLOWPAN_CTX_H_ + +#include <inttypes.h> + +#include "net/ng_ipv6/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NG_SIXLOWPAN_CTX_SIZE (16) /**< maximum number of entries in + * context buffer */ + +typedef struct { + ng_ipv6_addr_t prefix; /**< The prefix associated to this context. */ + uint8_t prefix_len; /**< Length of ng_sixlowpan_ctx_t::prefix in bit. */ + /** + * @brief 4-bit Context ID. + * + * @note This needs to be here to easily translate prefixes to + * ID. + */ + uint8_t id; + /** + * @brief Lifetime in minutes this context is valid. + * + * @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2"> + * 6LoWPAN Context Option + * </a> + */ + uint16_t ltime; +} ng_sixlowpan_ctx_t; + +/** + * @brief Gets a context matching the given IPv6 address best with its prefix. + * + * @param[in] addr An IPv6 address. + * + * @return The context associated with the best prefix for @p addr. + * @return NULL if there is no such context. + */ +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_addr(const ng_ipv6_addr_t *addr); + +/** + * @brief Gets context by ID. + * + * @param[in] id A context ID. + * + * @return The context associated with @p id. + * @return NULL if there is no such context. + */ +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_id(uint8_t id); + +/** + * @brief Updates (or adds if currently not registered) a context + * + * @param[in] id The ID for the context. + * Must be < @ref NG_SIXLOWPAN_CTX_SIZE. + * @param[in] prefix The prefix for the context. + * @param[in] prefix_len Length of @p prefix in bits. Must be > 0, when + * @p ltime > 0. + * @param[in] ltime New lifetime of the context. The context will + * be removed if 0. + * + * @return The new context on success. + * @return NULL, on error or on removal. + */ +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *prefix, + uint8_t prefix_len, uint16_t ltime); + + +#ifdef __cplusplus +} +#endif + +#endif /* NG_SIXLOWPAN_CTX_H_ */ +/** @} */ diff --git a/sys/net/network_layer/ng_sixlowpan/ctx/Makefile b/sys/net/network_layer/ng_sixlowpan/ctx/Makefile new file mode 100644 index 0000000000..afa4a1ee6d --- /dev/null +++ b/sys/net/network_layer/ng_sixlowpan/ctx/Makefile @@ -0,0 +1,3 @@ +MODULE = ng_sixlowpan_ctx + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/network_layer/ng_sixlowpan/ctx/ng_sixlowpan_ctx.c b/sys/net/network_layer/ng_sixlowpan/ctx/ng_sixlowpan_ctx.c new file mode 100644 index 0000000000..3bd57f68ef --- /dev/null +++ b/sys/net/network_layer/ng_sixlowpan/ctx/ng_sixlowpan_ctx.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * 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 + */ + +#include <stdbool.h> +#include <inttypes.h> + +#include "mutex.h" +#include "net/ng_sixlowpan/ctx.h" +#include "vtimer.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static ng_sixlowpan_ctx_t _ctxs[NG_SIXLOWPAN_CTX_SIZE]; +static uint32_t _ctx_inval_times[NG_SIXLOWPAN_CTX_SIZE]; +static mutex_t _ctx_mutex = MUTEX_INIT; + +static uint32_t _current_minute(void); +static void _update_lifetime(unsigned int id); + +#if ENABLE_DEBUG +static char ipv6str[NG_IPV6_ADDR_MAX_STR_LEN]; +#endif + +static inline bool _still_valid(unsigned int id) +{ + _update_lifetime(id); + return (_ctxs[id].ltime > 0); +} + +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_addr(const ng_ipv6_addr_t *addr) +{ + uint8_t best = 0; + ng_sixlowpan_ctx_t *res = NULL; + + mutex_lock(&_ctx_mutex); + + for (unsigned int id = 0; id < NG_SIXLOWPAN_CTX_SIZE; id++) { + if (_still_valid(id)) { + uint8_t match = ng_ipv6_addr_match_prefix(&_ctxs[id].prefix, addr); + + if ((_ctxs[id].prefix_len <= match) && (match > best)) { + best = match; + res = _ctxs + id; + } + } + } + + mutex_unlock(&_ctx_mutex); + +#if ENABLE_DEBUG + if (res != NULL) { + DEBUG("6lo ctx: found context (%u, %s/%" PRIu8 ") ", res->id, + ng_ipv6_addr_to_str(ipv6str, &res->prefix, sizeof(ipv6str)), + res->prefix_len); + DEBUG("for address %s\n", ng_ipv6_addr_to_str(ipv6str, addr, sizeof(ipv6str))); + } +#endif + + return res; +} + +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_id(uint8_t id) +{ + if (id >= NG_SIXLOWPAN_CTX_SIZE) { + return NULL; + } + + mutex_lock(&_ctx_mutex); + + if (_still_valid((unsigned int)id)) { + DEBUG("6lo ctx: found context (%u, %s/%" PRIu8 ")\n", id, + ng_ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)), + _ctxs[id].prefix_len); + mutex_unlock(&_ctx_mutex); + return _ctxs + id; + } + + mutex_unlock(&_ctx_mutex); + + return NULL; +} + +ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *prefix, + uint8_t prefix_len, uint16_t ltime) +{ + if ((id >= NG_SIXLOWPAN_CTX_SIZE)) { + return NULL; + } + + mutex_lock(&_ctx_mutex); + + _ctxs[id].ltime = ltime; + + if (ltime == 0) { + mutex_unlock(&_ctx_mutex); + DEBUG("6lo ctx: remove context (%u, %s/%" PRIu8 ")\n", id, + ng_ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)), + _ctxs[id].prefix_len); + return NULL; + } + + /* test prefix_len now so that invalidation is possible regardless of the + * value. */ + if (prefix_len == 0) { + mutex_unlock(&_ctx_mutex); + _ctxs[id].ltime = 0; + return NULL; + } + + if (prefix_len > NG_IPV6_ADDR_BIT_LEN) { + _ctxs[id].prefix_len = NG_IPV6_ADDR_BIT_LEN; + } + else { + _ctxs[id].prefix_len = prefix_len; + } + + _ctxs[id].id = id; + + if (!ng_ipv6_addr_equal(&(_ctxs[id].prefix), prefix)) { + ng_ipv6_addr_set_unspecified(&(_ctxs[id].prefix)); + ng_ipv6_addr_init_prefix(&(_ctxs[id].prefix), prefix, + _ctxs[id].prefix_len); + } + DEBUG("6lo ctx: update context (%u, %s/%" PRIu8 "), lifetime: %" PRIu16 " min\n", + id, ng_ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)), + _ctxs[id].prefix_len, _ctxs[id].ltime); + _ctx_inval_times[id] = ltime + _current_minute(); + + mutex_unlock(&_ctx_mutex); + + return _ctxs + id; +} + +static uint32_t _current_minute(void) +{ + timex_t now; + vtimer_now(&now); + return now.seconds / 60; +} + +static void _update_lifetime(unsigned int id) +{ + uint32_t now; + + if (_ctxs[id].ltime == 0) { + return; + } + + now = _current_minute(); + + if (now >= _ctx_inval_times[id]) { + DEBUG("6lo ctx: context %u was invalidated\n", id); + _ctxs[id].ltime = 0; + } + else { + _ctxs[id].ltime = (uint16_t)(_ctx_inval_times[id] - now); + } +} + +/** @} */ -- GitLab