mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
gnrc_ipv6_nib: provide component to handle ABRO
This commit is contained in:
parent
080590f587
commit
0b2bc25ee0
@ -22,6 +22,7 @@
|
||||
#ifndef NET_GNRC_IPV6_NIB_H
|
||||
#define NET_GNRC_IPV6_NIB_H
|
||||
|
||||
#include "net/gnrc/ipv6/nib/abr.h"
|
||||
#include "net/gnrc/ipv6/nib/nc.h"
|
||||
#include "net/gnrc/ipv6/nib/pl.h"
|
||||
|
||||
|
55
sys/include/net/gnrc/ipv6/nib/abr.h
Normal file
55
sys/include/net/gnrc/ipv6/nib/abr.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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_nib_abr Authoritative border router list
|
||||
* @ingroup net_gnrc_ipv6_nib
|
||||
* @brief Authoritative border router list component of neighbor
|
||||
* information base
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Authoritative border router list definitions
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_GNRC_IPV6_NIB_ABR_H
|
||||
#define NET_GNRC_IPV6_NIB_ABR_H
|
||||
|
||||
#include "net/ipv6/addr.h"
|
||||
#include "net/gnrc/ipv6/nib/conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Adds the address of an authoritative border router to the NIB
|
||||
*
|
||||
* @param[in] addr The address of an authoritative border router.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -ENOMEM, if no space is left in the neighbor cache.
|
||||
*/
|
||||
int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Removes an authoritative border router from the NIB
|
||||
*
|
||||
* @param[in] addr The address of an authoritative border router.
|
||||
*/
|
||||
void gnrc_ipv6_nib_abr_del(const ipv6_addr_t *addr);
|
||||
#endif /* (GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C) || defined(DOXYGEN) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_GNRC_IPV6_NIB_ABR_H */
|
||||
/** @} */
|
@ -194,6 +194,15 @@ extern "C" {
|
||||
#define GNRC_IPV6_NIB_OFFL_NUMOF (8)
|
||||
#endif
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Number of authoritative border router entries in NIB
|
||||
*/
|
||||
#ifndef GNRC_IPV6_NIB_ABR_NUMOF
|
||||
#define GNRC_IPV6_NIB_ABR_NUMOF (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -37,6 +37,10 @@ static _nib_offl_entry_t _dsts[GNRC_IPV6_NIB_OFFL_NUMOF];
|
||||
static _nib_dr_entry_t _def_routers[GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF];
|
||||
static _nib_iface_t _nis[GNRC_NETIF_NUMOF];
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
static _nib_abr_entry_t _abrs[GNRC_IPV6_NIB_ABR_NUMOF];
|
||||
#endif
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
#endif
|
||||
@ -57,6 +61,9 @@ void _nib_init(void)
|
||||
memset(_def_routers, 0, sizeof(_def_routers));
|
||||
memset(_dsts, 0, sizeof(_dsts));
|
||||
memset(_nis, 0, sizeof(_nis));
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
memset(_abrs, 0, sizeof(_abrs));
|
||||
#endif
|
||||
#endif
|
||||
evtimer_init_msg(&_nib_evtimer);
|
||||
/* TODO: load ABR information from persistent memory */
|
||||
@ -450,6 +457,13 @@ static inline bool _in_dsts(const _nib_offl_entry_t *dst)
|
||||
return (dst < (_dsts + GNRC_IPV6_NIB_OFFL_NUMOF));
|
||||
}
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
static inline bool _in_abrs(const _nib_abr_entry_t *abr)
|
||||
{
|
||||
return (abr < (_abrs + GNRC_IPV6_NIB_ABR_NUMOF));
|
||||
}
|
||||
#endif
|
||||
|
||||
void _nib_offl_clear(_nib_offl_entry_t *dst)
|
||||
{
|
||||
if (dst->next_hop != NULL) {
|
||||
@ -483,6 +497,131 @@ _nib_offl_entry_t *_nib_offl_iter(const _nib_offl_entry_t *last)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
||||
{
|
||||
_nib_offl_remove(nib_offl, _PL);
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
unsigned idx = nib_offl - _dsts;
|
||||
if (idx < GNRC_IPV6_NIB_OFFL_NUMOF) {
|
||||
for (_nib_abr_entry_t *abr = _abrs; _in_abrs(abr); abr++) {
|
||||
if (bf_isset(abr->pfxs, idx)) {
|
||||
DEBUG("nib: Removing prefix %s/%u ",
|
||||
ipv6_addr_to_str(addr_str, &nib_offl->pfx,
|
||||
sizeof(addr_str)),
|
||||
nib_offl->pfx_len);
|
||||
DEBUG("from border router %s\n",
|
||||
ipv6_addr_to_str(addr_str, &abr->addr, sizeof(addr_str)));
|
||||
bf_unset(abr->pfxs, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
_nib_abr_entry_t *_nib_abr_add(const ipv6_addr_t *addr)
|
||||
{
|
||||
_nib_abr_entry_t *abr = NULL;
|
||||
|
||||
assert(addr != NULL);
|
||||
DEBUG("nib: Allocating authoritative border router entry (addr = %s)\n",
|
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
|
||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_ABR_NUMOF; i++) {
|
||||
_nib_abr_entry_t *tmp = &_abrs[i];
|
||||
|
||||
if (ipv6_addr_equal(addr, &tmp->addr)) {
|
||||
/* exact match */
|
||||
DEBUG(" %p is an exact match\n", (void *)tmp);
|
||||
return tmp;
|
||||
}
|
||||
if ((abr == NULL) && (ipv6_addr_is_unspecified(&tmp->addr))) {
|
||||
abr = tmp;
|
||||
}
|
||||
}
|
||||
if (abr != NULL) {
|
||||
DEBUG(" using %p\n", (void *)abr);
|
||||
memcpy(&abr->addr, addr, sizeof(abr->addr));
|
||||
}
|
||||
#if ENABLE_DEBUG
|
||||
else {
|
||||
DEBUG(" NIB full\n");
|
||||
}
|
||||
#endif
|
||||
return abr;
|
||||
}
|
||||
|
||||
void _nib_abr_remove(const ipv6_addr_t *addr)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
DEBUG("nib: Removing border router %s\n", ipv6_addr_to_str(addr_str, addr,
|
||||
sizeof(addr_str)));
|
||||
for (_nib_abr_entry_t *abr = _abrs; _in_abrs(abr); abr++) {
|
||||
if (ipv6_addr_equal(addr, &abr->addr)) {
|
||||
for (int i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) {
|
||||
if (bf_isset(abr->pfxs, i)) {
|
||||
_nib_pl_remove(&_dsts[i]);
|
||||
}
|
||||
}
|
||||
#if MODULE_GNRC_SIXLOWPAN_CTX
|
||||
for (int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) {
|
||||
if (bf_isset(abr->ctxs, i)) {
|
||||
gnrc_sixlowpan_ctx_remove(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
memset(abr, 0, sizeof(_nib_abr_entry_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _nib_abr_add_pfx(_nib_abr_entry_t *abr, const _nib_offl_entry_t *offl)
|
||||
{
|
||||
assert((abr != NULL) && (offl != NULL) && (offl->mode & _PL));
|
||||
unsigned idx = (unsigned)(_dsts - offl);
|
||||
|
||||
DEBUG("nib: Prefix %s/%u ",
|
||||
ipv6_addr_to_str(addr_str, &offl->pfx, sizeof(addr_str)),
|
||||
offl->pfx_len);
|
||||
DEBUG("came from border router %s\n", ipv6_addr_to_str(addr_str, &abr->addr,
|
||||
sizeof(addr_str)));
|
||||
if (idx < GNRC_IPV6_NIB_OFFL_NUMOF) {
|
||||
bf_set(abr->pfxs, idx);
|
||||
}
|
||||
}
|
||||
|
||||
_nib_offl_entry_t *_nib_abr_iter_pfx(const _nib_abr_entry_t *abr,
|
||||
const _nib_offl_entry_t *last)
|
||||
{
|
||||
if ((last == NULL) ||
|
||||
(((unsigned)(_dsts - last)) < GNRC_IPV6_NIB_OFFL_NUMOF)) {
|
||||
/* we don't change `ptr`, so dropping const qualifier for now is okay */
|
||||
_nib_offl_entry_t *ptr = (_nib_offl_entry_t *)last;
|
||||
|
||||
while ((ptr = _nib_offl_iter(ptr))) {
|
||||
/* bf_isset() discards const, but doesn't change the array, so
|
||||
* discarding it on purpose */
|
||||
if ((ptr->mode & _PL) && (bf_isset((uint8_t *)abr->pfxs, ptr - _dsts))) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_nib_abr_entry_t *_nib_abr_iter(const _nib_abr_entry_t *last)
|
||||
{
|
||||
for (const _nib_abr_entry_t *abr = (last) ? (last + 1) : _abrs;
|
||||
_in_abrs(abr); abr++) {
|
||||
if (!ipv6_addr_is_unspecified(&abr->addr)) {
|
||||
/* const modifier provided to assure internal consistency.
|
||||
* Can now be discarded. */
|
||||
return (_nib_abr_entry_t *)abr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */
|
||||
|
||||
_nib_offl_entry_t *_nib_pl_add(unsigned iface,
|
||||
const ipv6_addr_t *pfx,
|
||||
unsigned pfx_len,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bitfield.h"
|
||||
#include "evtimer_msg.h"
|
||||
#include "kernel_types.h"
|
||||
#include "mutex.h"
|
||||
@ -34,6 +35,7 @@
|
||||
#include "net/gnrc/ipv6/nib/nc.h"
|
||||
#include "net/gnrc/ipv6/nib/conf.h"
|
||||
#include "net/gnrc/pktqueue.h"
|
||||
#include "net/gnrc/sixlowpan/ctx.h"
|
||||
#include "net/ndp.h"
|
||||
#include "random.h"
|
||||
|
||||
@ -221,6 +223,27 @@ typedef struct {
|
||||
uint8_t na_sent;
|
||||
} _nib_iface_t;
|
||||
|
||||
/**
|
||||
* @brief Internal NIB-representation of the authoritative border router
|
||||
* for multihop prefix and 6LoWPAN context dissemination
|
||||
*/
|
||||
typedef struct {
|
||||
ipv6_addr_t addr; /**< The address of the border router */
|
||||
uint32_t version; /**< last received version of the info of
|
||||
* the _nib_abr_entry_t::addr */
|
||||
evtimer_msg_event_t timeout; /**< timeout of the information */
|
||||
/**
|
||||
* @brief Bitfield marking the prefixes in the NIB's off-link entries
|
||||
* disseminated by _nib_abr_entry_t::addr
|
||||
*/
|
||||
BITFIELD(pfxs, GNRC_IPV6_NIB_OFFL_NUMOF);
|
||||
/**
|
||||
* @brief Bitfield marking the contexts disseminated by
|
||||
* _nib_abr_entry_t::addr
|
||||
*/
|
||||
BITFIELD(ctxs, GNRC_SIXLOWPAN_CTX_SIZE);
|
||||
} _nib_abr_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Mutex for locking the NIB
|
||||
*/
|
||||
@ -598,11 +621,7 @@ _nib_offl_entry_t *_nib_pl_add(unsigned iface,
|
||||
*
|
||||
* Corresponding on-link entry is removed, too.
|
||||
*/
|
||||
static inline void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
||||
{
|
||||
evtimer_del(&_nib_evtimer, &nib_offl->pfx_timeout.event);
|
||||
_nib_offl_remove(nib_offl, _PL);
|
||||
}
|
||||
void _nib_pl_remove(_nib_offl_entry_t *nib_offl);
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN
|
||||
/**
|
||||
@ -648,6 +667,65 @@ static inline void _nib_ft_remove(_nib_offl_entry_t *nib_offl)
|
||||
}
|
||||
#endif /* GNRC_IPV6_NIB_CONF_ROUTER */
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Creates or gets an existing authoritative border router.
|
||||
*
|
||||
* @pre `addr != NULL`
|
||||
*
|
||||
* @param[in] addr Address of the authoritative border router.
|
||||
*
|
||||
* @return An authoritative border router entry, on success.
|
||||
* @return NULL, if no space is left.
|
||||
*/
|
||||
_nib_abr_entry_t *_nib_abr_add(const ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Removes an authoritative border router
|
||||
*
|
||||
* @pre `addr != NULL`
|
||||
*
|
||||
* @param[in] addr Address of the authoritative border router.
|
||||
*/
|
||||
void _nib_abr_remove(const ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Adds a prefix to the managed prefix of the authoritative border
|
||||
* router
|
||||
*
|
||||
* @pre `(abr != NULL) && (offl != NULL) && (offl->mode & _PL)`
|
||||
*
|
||||
* @param[in] abr The border router.
|
||||
* @param[in] offl The prefix to add.
|
||||
*/
|
||||
void _nib_abr_add_pfx(_nib_abr_entry_t *abr, const _nib_offl_entry_t *offl);
|
||||
|
||||
/**
|
||||
* @brief Iterates over an authoritative border router's prefixes
|
||||
*
|
||||
* @pre `(abr != NULL)`
|
||||
*
|
||||
* @param[in] abr The border router
|
||||
* @param[in] last Last prefix (NULL to start)
|
||||
*
|
||||
* @return entry after @p last.
|
||||
* @return NULL, if @p last is the last prefix of @p abr or if @p last
|
||||
* wasn't in NIB (and != NULL).
|
||||
*/
|
||||
_nib_offl_entry_t *_nib_abr_iter_pfx(const _nib_abr_entry_t *abr,
|
||||
const _nib_offl_entry_t *last);
|
||||
|
||||
/**
|
||||
* @brief Iterates over authoritative border router entries
|
||||
*
|
||||
* @param[in] last Last entry (NULL to start).
|
||||
*
|
||||
* @return entry after @p last.
|
||||
* @return NULL, if @p last is the last ABR in the NIB.
|
||||
*/
|
||||
_nib_abr_entry_t *_nib_abr_iter(const _nib_abr_entry_t *last);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Gets (or creates if it not exists) interface information for
|
||||
* neighbor discovery
|
||||
|
57
sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c
Normal file
57
sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include "net/gnrc/ipv6/nib/abr.h"
|
||||
|
||||
#include "_nib-internal.h"
|
||||
|
||||
#if GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||
int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr)
|
||||
{
|
||||
_nib_abr_entry_t *abr;
|
||||
_nib_offl_entry_t *offl = NULL;
|
||||
|
||||
mutex_lock(&_nib_mutex);
|
||||
if ((abr = _nib_abr_add(addr)) == NULL) {
|
||||
mutex_unlock(&_nib_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
while ((offl = _nib_offl_iter(offl))) {
|
||||
if (offl->mode & _PL) {
|
||||
_nib_abr_add_pfx(abr, offl);
|
||||
}
|
||||
}
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_CTX /* included optionally for NIB testing */
|
||||
for (uint8_t id = 0; id < GNRC_SIXLOWPAN_CTX_SIZE; id++) {
|
||||
if (gnrc_sixlowpan_ctx_lookup_id(id) != NULL) {
|
||||
bf_set(abr->ctxs, id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mutex_unlock(&_nib_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gnrc_ipv6_nib_abr_del(const ipv6_addr_t *addr)
|
||||
{
|
||||
mutex_lock(&_nib_mutex);
|
||||
_nib_abr_remove(addr);
|
||||
mutex_unlock(&_nib_mutex);
|
||||
}
|
||||
#else
|
||||
typedef int dont_be_pedantic;
|
||||
#endif
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user