From e6c96cde53d3a5bdc756f7f9a1324ea428c15336 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 31 Aug 2015 00:23:27 +0200 Subject: [PATCH 1/2] 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 fd0b79337f4a..701c9cef47dc 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 a9c4dea1d12c..1e123a297768 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 7260c3d2e94b..432da9515b25 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 919008a13e2c..0b3b3aefac00 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 000000000000..9e84d5b6c30a --- /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 9d02c7eca634..296e7a270277 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 a30c25bf1c99..0d6963f98a07 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 /** @} */ From 4da5c8095c152bad469bbb44d00def143a902896 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 31 Aug 2015 02:36:12 +0200 Subject: [PATCH 2/2] gnrc: adapt for gnrc_sixlowpan_nd_border_router --- .../ipv6/netif/gnrc_ipv6_netif.c | 21 +++++++++++++++++++ .../sixlowpan/ctx/gnrc_sixlowpan_ctx.c | 1 - 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c index cc8b967f0695..30fc643ad785 100644 --- a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c +++ b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c @@ -111,6 +111,12 @@ static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr gnrc_ndp_router_retrans_rtr_adv(entry); mutex_lock(&entry->mutex); /* relock mutex */ } +#endif +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER + gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get(); + if (gnrc_sixlowpan_nd_router_abr_add_prf(abr, entry, tmp_addr) < 0) { + DEBUG("ipv6_netif: error adding prefix to 6LoWPAN-ND management\n"); + } #endif } else { @@ -303,6 +309,10 @@ static void _remove_addr_from_entry(gnrc_ipv6_netif_t *entry, ipv6_addr_t *addr) return; } #endif +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER + gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get(); + gnrc_sixlowpan_nd_router_abr_rem_prf(abr, entry, &entry->addrs[i]); +#endif mutex_unlock(&entry->mutex); return; @@ -752,6 +762,9 @@ void gnrc_ipv6_netif_init_by_dev(void) { kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = gnrc_netif_get(ifs); +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER + bool abr_init = false; +#endif for (size_t i = 0; i < ifnum; i++) { ipv6_addr_t addr; @@ -826,6 +839,14 @@ void gnrc_ipv6_netif_init_by_dev(void) #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND if (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER + /* first interface wins */ + if (!abr_init) { + gnrc_sixlowpan_nd_router_abr_create(&addr, 0); + gnrc_ipv6_netif_set_rtr_adv(ipv6_if, true); + abr_init = true; + } +#endif gnrc_sixlowpan_nd_init(ipv6_if); continue; /* skip gnrc_ndp_host_init() */ } diff --git a/sys/net/gnrc/network_layer/sixlowpan/ctx/gnrc_sixlowpan_ctx.c b/sys/net/gnrc/network_layer/sixlowpan/ctx/gnrc_sixlowpan_ctx.c index 5c3ff30aeb5b..c1a186da2d89 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/ctx/gnrc_sixlowpan_ctx.c +++ b/sys/net/gnrc/network_layer/sixlowpan/ctx/gnrc_sixlowpan_ctx.c @@ -127,7 +127,6 @@ gnrc_sixlowpan_ctx_t *gnrc_sixlowpan_ctx_update(uint8_t id, const ipv6_addr_t *p _ctx_inval_times[id] = ltime + _current_minute(); mutex_unlock(&_ctx_mutex); - return &(_ctxs[id]); }