From e6c96cde53d3a5bdc756f7f9a1324ea428c15336 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 31 Aug 2015 00:23:27 +0200 Subject: [PATCH] gnrc_sixlowpan_nd_border_router: initial import --- Makefile.dep | 12 ++ Makefile.pseudomodules | 2 + doc/doxygen/riot.doxyfile | 1 + sys/include/net/gnrc/sixlowpan/nd.h | 11 ++ .../net/gnrc/sixlowpan/nd/border_router.h | 43 +++++++ sys/include/net/gnrc/sixlowpan/nd/router.h | 65 ++++++++++ .../nd/router/gnrc_sixlowpan_nd_router.c | 116 +++++++++++++++++- 7 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 sys/include/net/gnrc/sixlowpan/nd/border_router.h diff --git a/Makefile.dep b/Makefile.dep index fd0b79337f..701c9cef47 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -64,6 +64,14 @@ ifneq (,$(filter gnrc_sixlowpan_router_default,$(USEMODULE))) USEMODULE += gnrc_sixlowpan_iphc endif +ifneq (,$(filter gnrc_sixlowpan_border_router_default,$(USEMODULE))) + USEMODULE += gnrc_ipv6_router_default + USEMODULE += gnrc_sixlowpan_nd_border_router + USEMODULE += gnrc_sixlowpan_router + USEMODULE += gnrc_sixlowpan_frag + USEMODULE += gnrc_sixlowpan_iphc +endif + ifneq (,$(filter gnrc_sixlowpan_router,$(USEMODULE))) USEMODULE += gnrc_sixlowpan endif @@ -89,6 +97,10 @@ ifneq (,$(filter gnrc_sixlowpan_ctx,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter gnrc_sixlowpan_nd_border_router,$(USEMODULE))) + USEMODULE += gnrc_sixlowpan_nd_router +endif + ifneq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE))) USEMODULE += gnrc_sixlowpan_nd endif diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index a9c4dea1d1..1e123a2977 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -3,6 +3,8 @@ PSEUDOMODULES += gnrc_ipv6_default PSEUDOMODULES += gnrc_ipv6_router PSEUDOMODULES += gnrc_ipv6_router_default PSEUDOMODULES += gnrc_sixlowpan_default +PSEUDOMODULES += gnrc_sixlowpan_border_router_default +PSEUDOMODULES += gnrc_sixlowpan_nd_border_router PSEUDOMODULES += gnrc_sixlowpan_router PSEUDOMODULES += gnrc_sixlowpan_router_default PSEUDOMODULES += gnrc_pktbuf diff --git a/doc/doxygen/riot.doxyfile b/doc/doxygen/riot.doxyfile index 7260c3d2e9..432da9515b 100644 --- a/doc/doxygen/riot.doxyfile +++ b/doc/doxygen/riot.doxyfile @@ -2005,6 +2005,7 @@ PREDEFINED = DOXYGEN \ MODULE_GNRC_NDP_ROUTER \ MODULE_GNRC_SIXLOWPAN \ MODULE_GNRC_SIXLOWPAN_ND_ROUTER \ + MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER \ MODULE_GNRC_UDP diff --git a/sys/include/net/gnrc/sixlowpan/nd.h b/sys/include/net/gnrc/sixlowpan/nd.h index 919008a13e..0b3b3aefac 100644 --- a/sys/include/net/gnrc/sixlowpan/nd.h +++ b/sys/include/net/gnrc/sixlowpan/nd.h @@ -33,6 +33,7 @@ #include "net/sixlowpan/nd.h" #include "timex.h" +#include "net/gnrc/sixlowpan/nd/border_router.h" #include "net/gnrc/sixlowpan/nd/router.h" #ifdef __cplusplus @@ -78,6 +79,16 @@ extern "C" { #define GNRC_SIXLOWPAN_ND_AR_LTIME (15U) #endif +/** + * @name Border router constants + * @{ + * @see + * RFC 6775, section 9 + * + */ +#define GNRC_SIXLOWPAN_ND_RTR_MIN_CTX_DELAY (300U) /**< minimum delay between context change and + * stop of C=0 dissimination in seconds */ +/** @} */ /** * @name Host constants * @{ diff --git a/sys/include/net/gnrc/sixlowpan/nd/border_router.h b/sys/include/net/gnrc/sixlowpan/nd/border_router.h new file mode 100644 index 0000000000..9e84d5b6c3 --- /dev/null +++ b/sys/include/net/gnrc/sixlowpan/nd/border_router.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 Martine Lenders + * + * 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 gnrc_sixlowpan_nd_border_router Border router part of 6LoWPAN-ND + * @ingroup gnrc_sixlowpan_nd + * @brief Border router part of 6LoWPAN-ND + * @{ + * + * @file + * @brief Border router definitions for 6LoWPAN. + * + * @author Martine Lenders + */ +#ifndef GNRC_SIXLOWPAN_BORDER_ROUTER_H_ +#define GNRC_SIXLOWPAN_BORDER_ROUTER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Default lifetime in minutes for 6LoWPAN border router information. + * + * @see + * RFC 6775, section 4.3 + * + */ +#ifndef GNRC_SIXLOWPAN_ND_BORDER_ROUTER_DEFAULT_LTIME +#define GNRC_SIXLOWPAN_ND_BORDER_ROUTER_DEFAULT_LTIME (10000U) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GNRC_SIXLOWPAN_BORDER_ROUTER_H_ */ +/** @} */ diff --git a/sys/include/net/gnrc/sixlowpan/nd/router.h b/sys/include/net/gnrc/sixlowpan/nd/router.h index 9d02c7eca6..296e7a2702 100644 --- a/sys/include/net/gnrc/sixlowpan/nd/router.h +++ b/sys/include/net/gnrc/sixlowpan/nd/router.h @@ -156,6 +156,71 @@ bool gnrc_sixlowpan_nd_router_abr_older(sixlowpan_nd_opt_abr_t *abr_opt); */ void gnrc_sixlowpan_nd_router_abr_remove(gnrc_sixlowpan_nd_router_abr_t *abr); +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER +/** + * @brief Makes this node a new border router. + * + * @per addr != NULL + * + * @param[in] addr The local address to use in the ABROs + * @param[in] ltime The lifetime to advertise in the ABROs. 0 assumes a default value of + * @ref GNRC_SIXLOWPAN_ND_BORDER_ROUTER_DEFAULT_LTIME + * + * @return The new border router object. + * @return NULL, on error. + */ +gnrc_sixlowpan_nd_router_abr_t *gnrc_sixlowpan_nd_router_abr_create(ipv6_addr_t *addr, + unsigned int ltime); + +/** + * @brief Adds a prefix for this border router to manage. + * + * @pre iface != NULL && prefix != NULL + * + * @param[in] abr The local border router + * @param[in] iface The IPv6 interface the prefix was added to. + * @param[in] prefix The prefix. + * + * @return 0, on success + * @return -ENOMEM, if no space for the new prefix is available. + * @return -ENOENT, if @p abr is not registered. + */ +int gnrc_sixlowpan_nd_router_abr_add_prf(gnrc_sixlowpan_nd_router_abr_t* abr, + gnrc_ipv6_netif_t *iface, gnrc_ipv6_netif_addr_t *prefix); + +/** + * @brief Removes a prefix from this border router. + * + * @param[in] abr The local border router + * @param[in] iface The IPv6 interface the prefix was added to. + * @param[in] prefix The prefix. + */ +void gnrc_sixlowpan_nd_router_abr_rem_prf(gnrc_sixlowpan_nd_router_abr_t *abr, + gnrc_ipv6_netif_t *iface, gnrc_ipv6_netif_addr_t *prefix); + +/** + * @brief Adds a context for this border router to manage. + * + * @param[in] abr The local border router + * @param[in] ctx The context to be add. + * + * @return 0, on success + * @return -EINVAL, if @p ctx is greater than 15. + * @return -ENOENT, if @p abr is not registered. + */ +int gnrc_sixlowpan_nd_router_abr_add_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, uint8_t cid); + +/** + * @brief Removes a context from this border router. + * + * @param[in] abr The local border router + * @param[in] ctx The context to be remove. + */ +void gnrc_sixlowpan_nd_router_abr_rem_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, uint8_t cid); +#else +#define gnrc_sixlowpan_nd_router_abr_create(addr, ltime) (NULL) +#endif + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c index a30c25bf1c..0d6963f98a 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c +++ b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c @@ -95,6 +95,17 @@ static void _add_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, sixlowpan_nd_opt_6ctx_ bf_set(abr->ctxs, sixlowpan_nd_opt_6ctx_get_cid(ctx_opt)); } +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER +static inline bool _is_me(ipv6_addr_t *addr) +{ + ipv6_addr_t *res; + + return (gnrc_ipv6_netif_find_by_addr(&res, addr) != KERNEL_PID_UNDEF); +} +#else +#define _is_me(ignore) (false) +#endif + gnrc_sixlowpan_nd_router_abr_t *gnrc_sixlowpan_nd_router_abr_get(void) { if (ipv6_addr_is_unspecified(&_abrs[0].addr)) { @@ -113,6 +124,10 @@ bool gnrc_sixlowpan_nd_router_abr_older(sixlowpan_nd_opt_abr_t *abr_opt) return true; } + if (_is_me(&abr_opt->braddr)) { + return false; + } + abr = _get_abr(&abr_opt->braddr); if (abr == NULL) { @@ -155,9 +170,11 @@ void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv gnrc_sixlowpan_nd_router_abr_t *abr; timex_t t = { 0, 0 }; + if (_is_me(&abr_opt->braddr)) { + return; + } /* validity and version was checked in previously called * gnrc_sixlowpan_nd_router_abr_older() */ - abr = _get_abr(&abr_opt->braddr); if (abr == NULL) { @@ -167,7 +184,7 @@ void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv abr->ltime = byteorder_ntohs(abr_opt->ltime); if (abr->ltime == 0) { - gnrc_sixlowpan_nd_router_abr_remove(abr); + abr->ltime = GNRC_SIXLOWPAN_ND_BORDER_ROUTER_DEFAULT_LTIME; return; } @@ -242,4 +259,99 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime return pkt; } +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER +gnrc_sixlowpan_nd_router_abr_t *gnrc_sixlowpan_nd_router_abr_create(ipv6_addr_t *addr, + unsigned int ltime) +{ + assert(addr != NULL); + gnrc_sixlowpan_nd_router_abr_t *abr = _get_abr(addr); + if (abr == NULL) { + return NULL; + } + /* TODO: store and get this somewhere stable */ + abr->version = 0; + abr->ltime = (uint16_t)ltime; + abr->addr.u64[0] = addr->u64[0]; + abr->addr.u64[1] = addr->u64[1]; + memset(abr->ctxs, 0, sizeof(abr->ctxs)); + abr->prfs = NULL; + return abr; +} + +int gnrc_sixlowpan_nd_router_abr_add_prf(gnrc_sixlowpan_nd_router_abr_t* abr, + gnrc_ipv6_netif_t *iface, gnrc_ipv6_netif_addr_t *prefix) +{ + assert((iface != NULL) && (prefix != NULL)); + gnrc_sixlowpan_nd_router_prf_t *prf_ent; + if ((abr < _abrs) || (abr > (_abrs + GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF))) { + return -ENOENT; + } + prf_ent = _get_free_prefix(&prefix->addr, prefix->prefix_len); + if (prf_ent == NULL) { + return -ENOMEM; + } + prf_ent->iface = iface; + prf_ent->prefix = prefix; + LL_PREPEND(abr->prfs, prf_ent); + abr->version++; /* TODO: store somewhere stable */ + return 0; +} + + +void gnrc_sixlowpan_nd_router_abr_rem_prf(gnrc_sixlowpan_nd_router_abr_t *abr, + gnrc_ipv6_netif_t *iface, gnrc_ipv6_netif_addr_t *prefix) +{ + assert((iface != NULL) && (prefix != NULL)); + gnrc_sixlowpan_nd_router_prf_t *prf_ent = abr->prfs, *prev = NULL; + if ((abr < _abrs) || (abr > (_abrs + GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF))) { + return; + } + while (prf_ent) { + if (prf_ent->prefix == prefix) { + if (prev == NULL) { + abr->prfs = prf_ent->next; + } + else { + prev->next = prf_ent->next; + } + prf_ent->next = NULL; + prf_ent->iface = NULL; + prf_ent->prefix = NULL; + abr->version++; /* TODO: store somewhere stable */ + break; + } + prev = prf_ent; + prf_ent = prf_ent->next; + } +} + +int gnrc_sixlowpan_nd_router_abr_add_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, uint8_t cid) +{ + if ((abr < _abrs) || (abr > (_abrs + GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF))) { + return -ENOENT; + } + if (cid >= GNRC_SIXLOWPAN_CTX_SIZE) { + return -EINVAL; + } + if (bf_isset(abr->ctxs, cid)) { + return -EADDRINUSE; + } + bf_set(abr->ctxs, cid); + abr->version++; /* TODO: store somewhere stable */ + return 0; +} + +void gnrc_sixlowpan_nd_router_abr_rem_ctx(gnrc_sixlowpan_nd_router_abr_t *abr, uint8_t cid) +{ + if ((abr < _abrs) || (abr > (_abrs + GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF))) { + return; + } + if (cid >= GNRC_SIXLOWPAN_CTX_SIZE) { + return; + } + bf_unset(abr->ctxs, cid); + abr->version++; /* TODO: store somewhere stable */ + return; +} +#endif /** @} */