Merge pull request #7270 from miri64/gnrc_ipv6_nib/feat/abr-component
gnrc_ipv6_nib: provide component to handle ABRO
This commit is contained in:
commit
7af0f916fe
@ -22,6 +22,7 @@
|
|||||||
#ifndef NET_GNRC_IPV6_NIB_H
|
#ifndef NET_GNRC_IPV6_NIB_H
|
||||||
#define 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/nc.h"
|
||||||
#include "net/gnrc/ipv6/nib/pl.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)
|
#define GNRC_IPV6_NIB_OFFL_NUMOF (8)
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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_dr_entry_t _def_routers[GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF];
|
||||||
static _nib_iface_t _nis[GNRC_NETIF_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
|
#if ENABLE_DEBUG
|
||||||
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||||
#endif
|
#endif
|
||||||
@ -57,6 +61,9 @@ void _nib_init(void)
|
|||||||
memset(_def_routers, 0, sizeof(_def_routers));
|
memset(_def_routers, 0, sizeof(_def_routers));
|
||||||
memset(_dsts, 0, sizeof(_dsts));
|
memset(_dsts, 0, sizeof(_dsts));
|
||||||
memset(_nis, 0, sizeof(_nis));
|
memset(_nis, 0, sizeof(_nis));
|
||||||
|
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||||
|
memset(_abrs, 0, sizeof(_abrs));
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
evtimer_init_msg(&_nib_evtimer);
|
evtimer_init_msg(&_nib_evtimer);
|
||||||
/* TODO: load ABR information from persistent memory */
|
/* 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));
|
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)
|
void _nib_offl_clear(_nib_offl_entry_t *dst)
|
||||||
{
|
{
|
||||||
if (dst->next_hop != NULL) {
|
if (dst->next_hop != NULL) {
|
||||||
@ -483,6 +497,131 @@ _nib_offl_entry_t *_nib_offl_iter(const _nib_offl_entry_t *last)
|
|||||||
return NULL;
|
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,
|
_nib_offl_entry_t *_nib_pl_add(unsigned iface,
|
||||||
const ipv6_addr_t *pfx,
|
const ipv6_addr_t *pfx,
|
||||||
unsigned pfx_len,
|
unsigned pfx_len,
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "bitfield.h"
|
||||||
#include "evtimer_msg.h"
|
#include "evtimer_msg.h"
|
||||||
#include "kernel_types.h"
|
#include "kernel_types.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include "net/gnrc/ipv6/nib/nc.h"
|
#include "net/gnrc/ipv6/nib/nc.h"
|
||||||
#include "net/gnrc/ipv6/nib/conf.h"
|
#include "net/gnrc/ipv6/nib/conf.h"
|
||||||
#include "net/gnrc/pktqueue.h"
|
#include "net/gnrc/pktqueue.h"
|
||||||
|
#include "net/gnrc/sixlowpan/ctx.h"
|
||||||
#include "net/ndp.h"
|
#include "net/ndp.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
|
||||||
@ -221,6 +223,27 @@ typedef struct {
|
|||||||
uint8_t na_sent;
|
uint8_t na_sent;
|
||||||
} _nib_iface_t;
|
} _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
|
* @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.
|
* Corresponding on-link entry is removed, too.
|
||||||
*/
|
*/
|
||||||
static inline void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN
|
#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 */
|
#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
|
* @brief Gets (or creates if it not exists) interface information for
|
||||||
* neighbor discovery
|
* 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
|
||||||
|
|
||||||
|
/** @} */
|
||||||
@ -5,5 +5,9 @@ CFLAGS += -DGNRC_IPV6_NIB_CONF_ROUTER=1
|
|||||||
CFLAGS += -DGNRC_IPV6_NIB_NUMOF=16
|
CFLAGS += -DGNRC_IPV6_NIB_NUMOF=16
|
||||||
CFLAGS += -DGNRC_IPV6_NIB_OFFL_NUMOF=25
|
CFLAGS += -DGNRC_IPV6_NIB_OFFL_NUMOF=25
|
||||||
CFLAGS += -DGNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF=4
|
CFLAGS += -DGNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF=4
|
||||||
|
CFLAGS += -DGNRC_IPV6_NIB_ABR_NUMOF=4
|
||||||
|
CFLAGS += -DGNRC_IPV6_NIB_CONF_6LBR=1
|
||||||
|
CFLAGS += -DGNRC_IPV6_NIB_CONF_MULTIHOP_P6C=1
|
||||||
|
CFLAGS += -DGNRC_IPV6_NIB_CONF_DC=1
|
||||||
|
|
||||||
INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/network_layer/ipv6/nib
|
INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/network_layer/ipv6/nib
|
||||||
|
|||||||
102
tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-abr.c
Normal file
102
tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-abr.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "net/ipv6/addr.h"
|
||||||
|
#include "net/gnrc/ipv6/nib.h"
|
||||||
|
#include "net/gnrc/ipv6/nib/abr.h"
|
||||||
|
|
||||||
|
#include "_nib-internal.h"
|
||||||
|
|
||||||
|
#include "unittests-constants.h"
|
||||||
|
|
||||||
|
#include "tests-gnrc_ipv6_nib.h"
|
||||||
|
|
||||||
|
#define GLOBAL_PREFIX { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
static void set_up(void)
|
||||||
|
{
|
||||||
|
evtimer_event_t *tmp;
|
||||||
|
|
||||||
|
for (evtimer_event_t *ptr = _nib_evtimer.events;
|
||||||
|
(ptr != NULL) && (tmp = (ptr->next), 1);
|
||||||
|
ptr = tmp) {
|
||||||
|
evtimer_del((evtimer_t *)(&_nib_evtimer), ptr);
|
||||||
|
}
|
||||||
|
_nib_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_ABR_NUMOF authoritative border router list entries with
|
||||||
|
* different addresses and then tries to create another one
|
||||||
|
* Expected result: gnrc_ipv6_nib_abr_add() returns -ENOMEM
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add__ENOMEM(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < GNRC_IPV6_NIB_ABR_NUMOF; i++) {
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_abr_add(&addr));
|
||||||
|
addr.u16[0].u16++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_abr_add(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_ABR_NUMOF authoritative border router list entries with
|
||||||
|
* different addresses and then tries to add another equal to the last.
|
||||||
|
* Expected result: should return 0.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add__success(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < GNRC_IPV6_NIB_ABR_NUMOF; i++) {
|
||||||
|
addr.u16[0].u16++;
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_abr_add(&addr));
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_abr_add(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an authoritative border router list entry and removes it.
|
||||||
|
* Expected result: system does not crash ;-)
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_del__success(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_abr_add(&addr));
|
||||||
|
gnrc_ipv6_nib_abr_del(&addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test *tests_gnrc_ipv6_nib_abr_tests(void)
|
||||||
|
{
|
||||||
|
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||||
|
new_TestFixture(test_nib_abr_add__ENOMEM),
|
||||||
|
new_TestFixture(test_nib_abr_add__success),
|
||||||
|
new_TestFixture(test_nib_abr_del__success),
|
||||||
|
/* gnrc_ipv6_nib_pl_iter() is tested during all the tests above */
|
||||||
|
};
|
||||||
|
|
||||||
|
EMB_UNIT_TESTCALLER(tests, set_up, NULL,
|
||||||
|
fixtures);
|
||||||
|
|
||||||
|
return (Test *)&tests;
|
||||||
|
}
|
||||||
@ -1715,6 +1715,201 @@ static void test_nib_ft_remove(void)
|
|||||||
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_ABR_NUMOF ABR entries with different addresses and
|
||||||
|
* then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add__no_space_left(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
for (int i = 0; i < GNRC_IPV6_NIB_ABR_NUMOF; i++) {
|
||||||
|
TEST_ASSERT_NOT_NULL(_nib_abr_add(&addr));
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_add(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_ABR_NUMOF ABR entries with different addresses and then
|
||||||
|
* tries to add another that is equal to the last.
|
||||||
|
* Expected result: should return not NULL (the last)
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add__success_duplicate(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr;
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
for (int i = 0; i < GNRC_IPV6_NIB_ABR_NUMOF; i++) {
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
}
|
||||||
|
TEST_ASSERT(abr == _nib_abr_add(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an ABR entry.
|
||||||
|
* Expected result: new entry should contain the given address
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add__success(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&addr, &abr->addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an ABR entry and then removes the entry.
|
||||||
|
* Expected result: the ABR list should be empty
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_remove__success(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr = NULL;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(_nib_abr_add(&addr));
|
||||||
|
_nib_abr_remove(&addr);
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter(abr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an ABR entry and tries to add a prefix, that is not in the NIB.
|
||||||
|
* Expected result: the ABR's prefix list should be unchanged.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add_pfx__pfx_not_in_nib(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
_nib_offl_entry_t offl;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter_pfx(abr, NULL));
|
||||||
|
_nib_abr_add_pfx(abr, &offl);
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter_pfx(abr, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an ABR entry and a prefix and tries to add that prefix.
|
||||||
|
* Expected result: the ABR's prefix list should be changed.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_add_pfx__pfx_in_nib(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr;
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_pl_add(IFACE, &pfx, GLOBAL_PREFIX_LEN,
|
||||||
|
UINT32_MAX, UINT32_MAX)));
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter_pfx(abr, NULL));
|
||||||
|
_nib_abr_add_pfx(abr, dst);
|
||||||
|
TEST_ASSERT_NOT_NULL(_nib_abr_iter_pfx(abr, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over prefixes of ABR with no prefix entries
|
||||||
|
* Expected result: _nib_abr_pfx_iter returns NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_iter_pfx__empty(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter_pfx(abr, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over empty ABR entries
|
||||||
|
* Expected result: _nib_abr_iter returns NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_iter__empty(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over ABR entries with one element
|
||||||
|
* Expected result: _nib_abr_iter returns element with NULL, and with that
|
||||||
|
* element NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_iter__one_elem(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr, *res;
|
||||||
|
static const ipv6_addr_t addr = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == abr);
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over ABR entries with three element
|
||||||
|
* Expected result: _nib_abr_iter returns element with NULL, with that element
|
||||||
|
* another, with that element yet another and with the last NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_iter__three_elem(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr1, *abr2, *abr3, *res;
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr1 = _nib_abr_add(&addr)));
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
TEST_ASSERT_NOT_NULL((abr2 = _nib_abr_add(&addr)));
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
TEST_ASSERT_NOT_NULL((abr3 = _nib_abr_add(&addr)));
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == abr1);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(res)));
|
||||||
|
TEST_ASSERT(res == abr2);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(res)));
|
||||||
|
TEST_ASSERT(res == abr3);
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over ABR entries with two elements, where there is a hole in the
|
||||||
|
* internal array
|
||||||
|
* Expected result: _nib_abr_iter returns element with NULL, with that element
|
||||||
|
* another, and with the last NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_abr_iter__three_elem_middle_removed(void)
|
||||||
|
{
|
||||||
|
_nib_abr_entry_t *abr1, *abr2, *res;
|
||||||
|
ipv6_addr_t addr = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((abr1 = _nib_abr_add(&addr)));
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
TEST_ASSERT_NOT_NULL(_nib_abr_add(&addr));
|
||||||
|
addr.u64[1].u64++;
|
||||||
|
TEST_ASSERT_NOT_NULL((abr2 = _nib_abr_add(&addr)));
|
||||||
|
addr.u64[1].u64--;
|
||||||
|
_nib_abr_remove(&addr);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == abr1);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_abr_iter(res)));
|
||||||
|
TEST_ASSERT(res == abr2);
|
||||||
|
TEST_ASSERT_NULL(_nib_abr_iter(res));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates GNRC_NETIF_NUMOF interfaces and then tries to add another.
|
* Creates GNRC_NETIF_NUMOF interfaces and then tries to add another.
|
||||||
* Expected result: should return NULL
|
* Expected result: should return NULL
|
||||||
@ -1826,6 +2021,20 @@ Test *tests_gnrc_ipv6_nib_internal_tests(void)
|
|||||||
new_TestFixture(test_nib_pl_remove),
|
new_TestFixture(test_nib_pl_remove),
|
||||||
new_TestFixture(test_nib_ft_add__success),
|
new_TestFixture(test_nib_ft_add__success),
|
||||||
new_TestFixture(test_nib_ft_remove),
|
new_TestFixture(test_nib_ft_remove),
|
||||||
|
#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C
|
||||||
|
new_TestFixture(test_nib_abr_add__no_space_left),
|
||||||
|
new_TestFixture(test_nib_abr_add__success_duplicate),
|
||||||
|
new_TestFixture(test_nib_abr_add__success),
|
||||||
|
new_TestFixture(test_nib_abr_remove__success),
|
||||||
|
new_TestFixture(test_nib_abr_add_pfx__pfx_not_in_nib),
|
||||||
|
new_TestFixture(test_nib_abr_add_pfx__pfx_in_nib),
|
||||||
|
new_TestFixture(test_nib_abr_iter_pfx__empty),
|
||||||
|
/* rest of _nib_abr_iter_pfx() tested through _nib_abr_add_pfx() tests */
|
||||||
|
new_TestFixture(test_nib_abr_iter__empty),
|
||||||
|
new_TestFixture(test_nib_abr_iter__one_elem),
|
||||||
|
new_TestFixture(test_nib_abr_iter__three_elem),
|
||||||
|
new_TestFixture(test_nib_abr_iter__three_elem_middle_removed),
|
||||||
|
#endif
|
||||||
new_TestFixture(test_nib_iface_get__no_space_left),
|
new_TestFixture(test_nib_iface_get__no_space_left),
|
||||||
new_TestFixture(test_nib_iface_get__success),
|
new_TestFixture(test_nib_iface_get__success),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
void tests_gnrc_ipv6_nib(void)
|
void tests_gnrc_ipv6_nib(void)
|
||||||
{
|
{
|
||||||
TESTS_RUN(tests_gnrc_ipv6_nib_internal_tests());
|
TESTS_RUN(tests_gnrc_ipv6_nib_internal_tests());
|
||||||
|
TESTS_RUN(tests_gnrc_ipv6_nib_abr_tests());
|
||||||
TESTS_RUN(tests_gnrc_ipv6_nib_nc_tests());
|
TESTS_RUN(tests_gnrc_ipv6_nib_nc_tests());
|
||||||
TESTS_RUN(tests_gnrc_ipv6_nib_pl_tests());
|
TESTS_RUN(tests_gnrc_ipv6_nib_pl_tests());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,13 @@ void tests_gnrc_ipv6_nib(void);
|
|||||||
*/
|
*/
|
||||||
Test *tests_gnrc_ipv6_nib_internal_tests(void);
|
Test *tests_gnrc_ipv6_nib_internal_tests(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates tests for authoritative border router list view
|
||||||
|
*
|
||||||
|
* @return embUnit tests if successful, NULL if not.
|
||||||
|
*/
|
||||||
|
Test *tests_gnrc_ipv6_nib_abr_tests(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generates tests for neighbor cache view
|
* @brief Generates tests for neighbor cache view
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user