Merge pull request #7212 from miri64/gnrc_ipv6_nib/feat/internal-offl
gnrc_ipv6_nib: provide internal implementation for off-link entries
This commit is contained in:
commit
c3d3e7d024
@ -184,6 +184,16 @@ extern "C" {
|
|||||||
#define GNRC_IPV6_NIB_NUMOF (4)
|
#define GNRC_IPV6_NIB_NUMOF (4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of off-link entries in NIB
|
||||||
|
*
|
||||||
|
* @attention This number is equal to the maximum number of forwarding table
|
||||||
|
* and prefix list entries in NIB
|
||||||
|
*/
|
||||||
|
#ifndef GNRC_IPV6_NIB_OFFL_NUMOF
|
||||||
|
#define GNRC_IPV6_NIB_OFFL_NUMOF (8)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -33,6 +33,7 @@ static _nib_dr_entry_t *_prime_def_router = NULL;
|
|||||||
static clist_node_t _next_removable = { NULL };
|
static clist_node_t _next_removable = { NULL };
|
||||||
|
|
||||||
static _nib_onl_entry_t _nodes[GNRC_IPV6_NIB_NUMOF];
|
static _nib_onl_entry_t _nodes[GNRC_IPV6_NIB_NUMOF];
|
||||||
|
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];
|
||||||
|
|
||||||
@ -54,34 +55,42 @@ void _nib_init(void)
|
|||||||
_next_removable.next = NULL;
|
_next_removable.next = NULL;
|
||||||
memset(_nodes, 0, sizeof(_nodes));
|
memset(_nodes, 0, sizeof(_nodes));
|
||||||
memset(_def_routers, 0, sizeof(_def_routers));
|
memset(_def_routers, 0, sizeof(_def_routers));
|
||||||
|
memset(_dsts, 0, sizeof(_dsts));
|
||||||
memset(_nis, 0, sizeof(_nis));
|
memset(_nis, 0, sizeof(_nis));
|
||||||
#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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool _addr_equals(const ipv6_addr_t *addr,
|
||||||
|
const _nib_onl_entry_t *node)
|
||||||
|
{
|
||||||
|
return (addr == NULL) || ipv6_addr_is_unspecified(&node->ipv6) ||
|
||||||
|
(ipv6_addr_equal(addr, &node->ipv6));
|
||||||
|
}
|
||||||
|
|
||||||
_nib_onl_entry_t *_nib_onl_alloc(const ipv6_addr_t *addr, unsigned iface)
|
_nib_onl_entry_t *_nib_onl_alloc(const ipv6_addr_t *addr, unsigned iface)
|
||||||
{
|
{
|
||||||
_nib_onl_entry_t *node = NULL;
|
_nib_onl_entry_t *node = NULL;
|
||||||
|
|
||||||
assert(addr != NULL);
|
|
||||||
DEBUG("nib: Allocating on-link node entry (addr = %s, iface = %u)\n",
|
DEBUG("nib: Allocating on-link node entry (addr = %s, iface = %u)\n",
|
||||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface);
|
(addr == NULL) ? "NULL" : ipv6_addr_to_str(addr_str, addr,
|
||||||
|
sizeof(addr_str)), iface);
|
||||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_NUMOF; i++) {
|
for (unsigned i = 0; i < GNRC_IPV6_NIB_NUMOF; i++) {
|
||||||
_nib_onl_entry_t *tmp = &_nodes[i];
|
_nib_onl_entry_t *tmp = &_nodes[i];
|
||||||
|
|
||||||
if ((_nib_onl_get_if(tmp) == iface) &&
|
if ((_nib_onl_get_if(tmp) == iface) && _addr_equals(addr, tmp)) {
|
||||||
(ipv6_addr_equal(addr, &tmp->ipv6))) {
|
|
||||||
/* exact match */
|
/* exact match */
|
||||||
DEBUG(" %p is an exact match\n", (void *)tmp);
|
DEBUG(" %p is an exact match\n", (void *)tmp);
|
||||||
return tmp;
|
node = tmp;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ((node == NULL) && (tmp->mode == _EMPTY)) {
|
if ((node == NULL) && (tmp->mode == _EMPTY)) {
|
||||||
|
DEBUG(" using %p\n", (void *)node);
|
||||||
node = tmp;
|
node = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
DEBUG(" using %p\n", (void *)node);
|
|
||||||
_override_node(addr, iface, node);
|
_override_node(addr, iface, node);
|
||||||
}
|
}
|
||||||
#if ENABLE_DEBUG
|
#if ENABLE_DEBUG
|
||||||
@ -144,6 +153,7 @@ static inline _nib_onl_entry_t *_cache_out_onl_entry(const ipv6_addr_t *addr,
|
|||||||
_nib_onl_entry_t *_nib_nc_add(const ipv6_addr_t *addr, unsigned iface,
|
_nib_onl_entry_t *_nib_nc_add(const ipv6_addr_t *addr, unsigned iface,
|
||||||
uint16_t cstate)
|
uint16_t cstate)
|
||||||
{
|
{
|
||||||
|
assert(addr != NULL);
|
||||||
cstate &= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK;
|
cstate &= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK;
|
||||||
assert(cstate != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY);
|
assert(cstate != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY);
|
||||||
assert(cstate != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE);
|
assert(cstate != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE);
|
||||||
@ -384,6 +394,95 @@ _nib_dr_entry_t *_nib_drl_get_dr(void)
|
|||||||
return _prime_def_router;
|
return _prime_def_router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_nib_offl_entry_t *_nib_offl_alloc(const ipv6_addr_t *next_hop, unsigned iface,
|
||||||
|
const ipv6_addr_t *pfx, unsigned pfx_len)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst = NULL;
|
||||||
|
|
||||||
|
assert((pfx != NULL) && (!ipv6_addr_is_unspecified(pfx)) &&
|
||||||
|
(pfx_len > 0) && (pfx_len <= 128));
|
||||||
|
DEBUG("nib: Allocating off-link-entry entry "
|
||||||
|
"(next_hop = %s, iface = %u, ",
|
||||||
|
(next_hop == NULL) ? "NULL" : ipv6_addr_to_str(addr_str, next_hop,
|
||||||
|
sizeof(addr_str)),
|
||||||
|
iface);
|
||||||
|
DEBUG("pfx = %s/%u)\n", ipv6_addr_to_str(addr_str, pfx,
|
||||||
|
sizeof(addr_str)), pfx_len);
|
||||||
|
for (unsigned i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *tmp = &_dsts[i];
|
||||||
|
_nib_onl_entry_t *tmp_node = tmp->next_hop;
|
||||||
|
|
||||||
|
if ((tmp->pfx_len == pfx_len) && /* prefix length matches and */
|
||||||
|
(tmp_node != NULL) && /* there is a next hop that */
|
||||||
|
(_nib_onl_get_if(tmp_node) == iface) && /* has a matching interface and */
|
||||||
|
_addr_equals(next_hop, tmp_node) && /* equal address to next_hop, also */
|
||||||
|
(ipv6_addr_match_prefix(&tmp->pfx, pfx) >= pfx_len)) { /* the prefix matches */
|
||||||
|
/* exact match (or next hop address was previously unset) */
|
||||||
|
DEBUG(" %p is an exact match\n", (void *)tmp);
|
||||||
|
if (next_hop != NULL) {
|
||||||
|
memcpy(&tmp_node->ipv6, next_hop, sizeof(tmp_node->ipv6));
|
||||||
|
}
|
||||||
|
tmp->next_hop->mode |= _DST;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
if ((dst == NULL) && (tmp_node == NULL)) {
|
||||||
|
dst = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dst != NULL) {
|
||||||
|
DEBUG(" using %p\n", (void *)dst);
|
||||||
|
dst->next_hop = _nib_onl_alloc(next_hop, iface);
|
||||||
|
|
||||||
|
if (dst->next_hop == NULL) {
|
||||||
|
memset(dst, 0, sizeof(_nib_offl_entry_t));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_override_node(next_hop, iface, dst->next_hop);
|
||||||
|
dst->next_hop->mode |= _DST;
|
||||||
|
ipv6_addr_init_prefix(&dst->pfx, pfx, pfx_len);
|
||||||
|
dst->pfx_len = pfx_len;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _in_dsts(const _nib_offl_entry_t *dst)
|
||||||
|
{
|
||||||
|
return (dst < (_dsts + GNRC_IPV6_NIB_OFFL_NUMOF));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _nib_offl_clear(_nib_offl_entry_t *dst)
|
||||||
|
{
|
||||||
|
if (dst->next_hop != NULL) {
|
||||||
|
_nib_offl_entry_t *ptr;
|
||||||
|
for (ptr = _dsts; _in_dsts(ptr); ptr++) {
|
||||||
|
/* there is another dst pointing to next-hop => only remove dst */
|
||||||
|
if ((dst != ptr) && (dst->next_hop == ptr->next_hop)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* we iterated and found no further dst pointing to next-hop */
|
||||||
|
if (!_in_dsts(ptr)) {
|
||||||
|
dst->next_hop->mode &= ~(_DST);
|
||||||
|
_nib_onl_clear(dst->next_hop);
|
||||||
|
}
|
||||||
|
memset(dst, 0, sizeof(_nib_offl_entry_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_nib_offl_entry_t *_nib_offl_iter(const _nib_offl_entry_t *last)
|
||||||
|
{
|
||||||
|
for (const _nib_offl_entry_t *dst = (last) ? (last + 1) : _dsts;
|
||||||
|
_in_dsts(dst);
|
||||||
|
dst++) {
|
||||||
|
if (dst->mode != _EMPTY) {
|
||||||
|
/* const modifier provided to assure internal consistency.
|
||||||
|
* Can now be discarded. */
|
||||||
|
return (_nib_offl_entry_t *)dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
_nib_iface_t *_nib_iface_get(unsigned iface)
|
_nib_iface_t *_nib_iface_get(unsigned iface)
|
||||||
{
|
{
|
||||||
_nib_iface_t *ni = NULL;
|
_nib_iface_t *ni = NULL;
|
||||||
@ -410,7 +509,9 @@ static void _override_node(const ipv6_addr_t *addr, unsigned iface,
|
|||||||
_nib_onl_entry_t *node)
|
_nib_onl_entry_t *node)
|
||||||
{
|
{
|
||||||
_nib_onl_clear(node);
|
_nib_onl_clear(node);
|
||||||
memcpy(&node->ipv6, addr, sizeof(node->ipv6));
|
if (addr != NULL) {
|
||||||
|
memcpy(&node->ipv6, addr, sizeof(node->ipv6));
|
||||||
|
}
|
||||||
_nib_onl_set_if(node, iface);
|
_nib_onl_set_if(node, iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#ifndef PRIV_NIB_INTERNAL_H
|
#ifndef PRIV_NIB_INTERNAL_H
|
||||||
#define PRIV_NIB_INTERNAL_H
|
#define PRIV_NIB_INTERNAL_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -52,6 +53,8 @@ extern "C" {
|
|||||||
#define _DRL (0x08) /**< default router list */
|
#define _DRL (0x08) /**< default router list */
|
||||||
#define _FT (0x10) /**< forwarding table */
|
#define _FT (0x10) /**< forwarding table */
|
||||||
#define _DAD (0x20) /**< 6LoWPAN duplicate address detection table */
|
#define _DAD (0x20) /**< 6LoWPAN duplicate address detection table */
|
||||||
|
#define _DST (0x40) /**< there is @ref _nib_offl_entry_t pointing
|
||||||
|
to this @ref _nib_onl_entry_t */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,6 +165,8 @@ typedef struct {
|
|||||||
ipv6_addr_t pfx; /**< prefix to the destination */
|
ipv6_addr_t pfx; /**< prefix to the destination */
|
||||||
unsigned pfx_len; /**< prefix-length in bits of
|
unsigned pfx_len; /**< prefix-length in bits of
|
||||||
* _nib_onl_entry_t::pfx */
|
* _nib_onl_entry_t::pfx */
|
||||||
|
uint8_t mode; /**< [mode](@ref net_gnrc_ipv6_nib_mode) of the
|
||||||
|
* off-link entry */
|
||||||
} _nib_offl_entry_t;
|
} _nib_offl_entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,10 +256,8 @@ static inline void _nib_onl_set_if(_nib_onl_entry_t *node, unsigned iface)
|
|||||||
/**
|
/**
|
||||||
* @brief Creates or gets an existing on-link entry by address
|
* @brief Creates or gets an existing on-link entry by address
|
||||||
*
|
*
|
||||||
* @pre `(addr != NULL)`.
|
* @param[in] addr An IPv6 address. May be NULL (to be pointed to by a prefix
|
||||||
*
|
* list entry). *May also be a global address!*
|
||||||
* @param[in] addr An IPv6 address. May not be NULL.
|
|
||||||
* *May also be a global address!*
|
|
||||||
* @param[in] iface The interface to the node.
|
* @param[in] iface The interface to the node.
|
||||||
*
|
*
|
||||||
* @return A new or existing on-link entry with _nib_onl_entry_t::ipv6 set to
|
* @return A new or existing on-link entry with _nib_onl_entry_t::ipv6 set to
|
||||||
@ -305,7 +308,6 @@ _nib_onl_entry_t *_nib_onl_get(const ipv6_addr_t *addr, unsigned iface);
|
|||||||
/**
|
/**
|
||||||
* @brief Creates or gets an existing node from the neighbor cache by address
|
* @brief Creates or gets an existing node from the neighbor cache by address
|
||||||
*
|
*
|
||||||
* @pre `(addr != NULL)`
|
|
||||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
||||||
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY)`
|
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY)`
|
||||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
||||||
@ -313,7 +315,8 @@ _nib_onl_entry_t *_nib_onl_get(const ipv6_addr_t *addr, unsigned iface);
|
|||||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) !=
|
||||||
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE)`
|
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE)`
|
||||||
*
|
*
|
||||||
* @param[in] addr The address of a node. May not be NULL.
|
* @param[in] addr The address of a node. May be NULL for prefix list
|
||||||
|
* entries.
|
||||||
* @param[in] iface The interface to the node.
|
* @param[in] iface The interface to the node.
|
||||||
* @param[in] cstate Creation state. State of the entry *if* the entry is
|
* @param[in] cstate Creation state. State of the entry *if* the entry is
|
||||||
* newly created.
|
* newly created.
|
||||||
@ -362,6 +365,7 @@ void _nib_nc_set_reachable(_nib_onl_entry_t *node);
|
|||||||
*/
|
*/
|
||||||
static inline _nib_onl_entry_t *_nib_dad_add(const ipv6_addr_t *addr)
|
static inline _nib_onl_entry_t *_nib_dad_add(const ipv6_addr_t *addr)
|
||||||
{
|
{
|
||||||
|
assert(addr != NULL);
|
||||||
_nib_onl_entry_t *node = _nib_onl_alloc(addr, 0);
|
_nib_onl_entry_t *node = _nib_onl_alloc(addr, 0);
|
||||||
|
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
@ -441,11 +445,10 @@ _nib_dr_entry_t *_nib_drl_get_dr(void);
|
|||||||
/**
|
/**
|
||||||
* @brief Creates or gets an existing off-link entry by next hop and prefix
|
* @brief Creates or gets an existing off-link entry by next hop and prefix
|
||||||
*
|
*
|
||||||
* @pre `(next_hop != NULL)`
|
|
||||||
* @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)`
|
* @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)`
|
||||||
*
|
*
|
||||||
* @param[in] next_hop An IPv6 address to next hop. May not be NULL.
|
* @param[in] next_hop An IPv6 address to next hop. May be NULL (for prefix
|
||||||
* *May also be a global address!*
|
* list). *May also be a global address!*
|
||||||
* @param[in] iface The interface to @p next_hop.
|
* @param[in] iface The interface to @p next_hop.
|
||||||
* @param[in] pfx The IPv6 prefix or address of the destination.
|
* @param[in] pfx The IPv6 prefix or address of the destination.
|
||||||
* May not be NULL or unspecified address. Use
|
* May not be NULL or unspecified address. Use
|
||||||
@ -456,15 +459,15 @@ _nib_dr_entry_t *_nib_drl_get_dr(void);
|
|||||||
* @p pfx.
|
* @p pfx.
|
||||||
* @return NULL, if no space is left.
|
* @return NULL, if no space is left.
|
||||||
*/
|
*/
|
||||||
_nib_offl_entry_t *_nib_dst_alloc(const ipv6_addr_t *next_hop, unsigned iface,
|
_nib_offl_entry_t *_nib_offl_alloc(const ipv6_addr_t *next_hop, unsigned iface,
|
||||||
const ipv6_addr_t *pfx, unsigned pfx_len);
|
const ipv6_addr_t *pfx, unsigned pfx_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clears out a NIB entry (off-link version)
|
* @brief Clears out a NIB entry (off-link version)
|
||||||
*
|
*
|
||||||
* @param[in,out] dst An entry.
|
* @param[in,out] dst An entry.
|
||||||
*/
|
*/
|
||||||
void _nib_dst_clear(_nib_offl_entry_t *dst);
|
void _nib_offl_clear(_nib_offl_entry_t *dst);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Iterates over off-link entries
|
* @brief Iterates over off-link entries
|
||||||
@ -473,16 +476,15 @@ void _nib_dst_clear(_nib_offl_entry_t *dst);
|
|||||||
*
|
*
|
||||||
* @return entry after @p last.
|
* @return entry after @p last.
|
||||||
*/
|
*/
|
||||||
_nib_offl_entry_t *_nib_dst_iter(const _nib_offl_entry_t *last);
|
_nib_offl_entry_t *_nib_offl_iter(const _nib_offl_entry_t *last);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for view-level add-functions below
|
* @brief Helper function for view-level add-functions below
|
||||||
*
|
*
|
||||||
* @pre `(next_hop != NULL)`
|
|
||||||
* @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)`
|
* @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)`
|
||||||
*
|
*
|
||||||
* @param[in] next_hop Next hop to the destination. May not be NULL.
|
* @param[in] next_hop An IPv6 address to next hop. May be NULL (for prefix
|
||||||
* *May also be a global address!*
|
* list). *May also be a global address!*
|
||||||
* @param[in] iface The interface to the destination.
|
* @param[in] iface The interface to the destination.
|
||||||
* @param[in] pfx The IPv6 prefix or address of the destination.
|
* @param[in] pfx The IPv6 prefix or address of the destination.
|
||||||
* May not be NULL or unspecified address. Use
|
* May not be NULL or unspecified address. Use
|
||||||
@ -490,19 +492,19 @@ _nib_offl_entry_t *_nib_dst_iter(const _nib_offl_entry_t *last);
|
|||||||
* @param[in] pfx_len The length in bits of @p pfx in bits.
|
* @param[in] pfx_len The length in bits of @p pfx in bits.
|
||||||
* @param[in] mode [NIB-mode](_nib_onl_entry_t::mode).
|
* @param[in] mode [NIB-mode](_nib_onl_entry_t::mode).
|
||||||
*
|
*
|
||||||
* @return A new or existing off-link entry with _nib_dr_entry_t::pfx set to
|
* @return A new or existing off-link entry with _nib_offl_entry_t::pfx set to
|
||||||
* @p pfx.
|
* @p pfx.
|
||||||
* @return NULL, if no space is left.
|
* @return NULL, if no space is left.
|
||||||
*/
|
*/
|
||||||
static inline _nib_offl_entry_t *_nib_dst_add(const ipv6_addr_t *next_hop,
|
static inline _nib_offl_entry_t *_nib_offl_add(const ipv6_addr_t *next_hop,
|
||||||
unsigned iface,
|
unsigned iface,
|
||||||
const ipv6_addr_t *pfx,
|
const ipv6_addr_t *pfx,
|
||||||
unsigned pfx_len, uint8_t mode)
|
unsigned pfx_len, uint8_t mode)
|
||||||
{
|
{
|
||||||
_nib_offl_entry_t *nib_offl = _nib_dst_alloc(next_hop, iface, pfx, pfx_len);
|
_nib_offl_entry_t *nib_offl = _nib_offl_alloc(next_hop, iface, pfx, pfx_len);
|
||||||
|
|
||||||
if (nib_offl != NULL) {
|
if (nib_offl != NULL) {
|
||||||
nib_offl->next_hop->mode |= (mode);
|
nib_offl->mode |= mode;
|
||||||
}
|
}
|
||||||
return nib_offl;
|
return nib_offl;
|
||||||
}
|
}
|
||||||
@ -512,17 +514,13 @@ static inline _nib_offl_entry_t *_nib_dst_add(const ipv6_addr_t *next_hop,
|
|||||||
*
|
*
|
||||||
* @param[in,out] nib_offl An entry.
|
* @param[in,out] nib_offl An entry.
|
||||||
*/
|
*/
|
||||||
static inline void _nib_dst_remove(_nib_offl_entry_t *nib_offl, uint8_t mode)
|
static inline void _nib_offl_remove(_nib_offl_entry_t *nib_offl, uint8_t mode)
|
||||||
{
|
{
|
||||||
_nib_onl_entry_t *node = nib_offl->next_hop;
|
nib_offl->mode &= ~mode;
|
||||||
|
_nib_offl_clear(nib_offl);
|
||||||
if (node != NULL) {
|
|
||||||
node->mode &= ~mode;
|
|
||||||
}
|
|
||||||
_nib_dst_clear(nib_offl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GNRC_IPV6_NIB_CONF_DC) || DOXYGEN
|
#if GNRC_IPV6_NIB_CONF_DC || DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @brief Creates or gets an existing destination cache entry by its addresses
|
* @brief Creates or gets an existing destination cache entry by its addresses
|
||||||
*
|
*
|
||||||
@ -535,16 +533,16 @@ static inline void _nib_dst_remove(_nib_offl_entry_t *nib_offl, uint8_t mode)
|
|||||||
*
|
*
|
||||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_DC.
|
* @note Only available if @ref GNRC_IPV6_NIB_CONF_DC.
|
||||||
*
|
*
|
||||||
* @return A new or existing destination cache entry with
|
* @return A new or existing off-link entry with _nib_offl_entry_t::pfx set to
|
||||||
* _nib_onl_entry_t::ipv6 of _nib_dr_entry_t::next_hop set to
|
* @p pfx.
|
||||||
* @p next_hop.
|
|
||||||
* @return NULL, if no space is left.
|
* @return NULL, if no space is left.
|
||||||
*/
|
*/
|
||||||
static inline _nib_offl_entry_t *_nib_dc_add(const ipv6_addr_t *next_hop,
|
static inline _nib_offl_entry_t *_nib_dc_add(const ipv6_addr_t *next_hop,
|
||||||
unsigned iface,
|
unsigned iface,
|
||||||
const ipv6_addr_t *dst)
|
const ipv6_addr_t *dst)
|
||||||
{
|
{
|
||||||
return _nib_dst_add(next_hop, iface, dst, IPV6_ADDR_BIT_LEN, _DC);
|
assert((next_hop != NULL) && (dst != NULL));
|
||||||
|
return _nib_offl_add(next_hop, iface, dst, IPV6_ADDR_BIT_LEN, _DC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -558,7 +556,7 @@ static inline _nib_offl_entry_t *_nib_dc_add(const ipv6_addr_t *next_hop,
|
|||||||
*/
|
*/
|
||||||
static inline void _nib_dc_remove(_nib_offl_entry_t *nib_offl)
|
static inline void _nib_dc_remove(_nib_offl_entry_t *nib_offl)
|
||||||
{
|
{
|
||||||
_nib_dst_remove(nib_offl, _DC);
|
_nib_offl_remove(nib_offl, _DC);
|
||||||
}
|
}
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_DC */
|
#endif /* GNRC_IPV6_NIB_CONF_DC */
|
||||||
|
|
||||||
@ -574,7 +572,7 @@ static inline void _nib_dc_remove(_nib_offl_entry_t *nib_offl)
|
|||||||
* @ref _nib_drl_add() for default route destinations.
|
* @ref _nib_drl_add() for default route destinations.
|
||||||
* @param[in] pfx_len The length in bits of @p pfx in bits.
|
* @param[in] pfx_len The length in bits of @p pfx in bits.
|
||||||
*
|
*
|
||||||
* @return A new or existing prefix list entry with _nib_dr_entry_t::pfx set to
|
* @return A new or existing off-link entry with _nib_offl_entry_t::pfx set to
|
||||||
* @p pfx.
|
* @p pfx.
|
||||||
* @return NULL, if no space is left.
|
* @return NULL, if no space is left.
|
||||||
*/
|
*/
|
||||||
@ -582,7 +580,7 @@ static inline _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)
|
||||||
{
|
{
|
||||||
return _nib_dst_add(NULL, iface, pfx, pfx_len, _PL);
|
return _nib_offl_add(NULL, iface, pfx, pfx_len, _PL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -594,10 +592,10 @@ static inline _nib_offl_entry_t *_nib_pl_add(unsigned iface,
|
|||||||
*/
|
*/
|
||||||
static inline void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
static inline void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
||||||
{
|
{
|
||||||
_nib_dst_remove(nib_offl, _PL);
|
_nib_offl_remove(nib_offl, _PL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GNRC_IPV6_NIB_CONF_ROUTER) || DOXYGEN
|
#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @brief Creates or gets an existing forwarding table entry by its prefix
|
* @brief Creates or gets an existing forwarding table entry by its prefix
|
||||||
*
|
*
|
||||||
@ -614,8 +612,8 @@ static inline void _nib_pl_remove(_nib_offl_entry_t *nib_offl)
|
|||||||
*
|
*
|
||||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER.
|
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER.
|
||||||
*
|
*
|
||||||
* @return A new or existing forwarding table entry with _nib_dr_entry_t::pfx
|
* @return A new or existing off-link entry with _nib_offl_entry_t::pfx set to
|
||||||
* set to @p pfx.
|
* @p pfx.
|
||||||
* @return NULL, if no space is left.
|
* @return NULL, if no space is left.
|
||||||
*/
|
*/
|
||||||
static inline _nib_offl_entry_t *_nib_ft_add(const ipv6_addr_t *next_hop,
|
static inline _nib_offl_entry_t *_nib_ft_add(const ipv6_addr_t *next_hop,
|
||||||
@ -623,7 +621,7 @@ static inline _nib_offl_entry_t *_nib_ft_add(const ipv6_addr_t *next_hop,
|
|||||||
const ipv6_addr_t *pfx,
|
const ipv6_addr_t *pfx,
|
||||||
unsigned pfx_len)
|
unsigned pfx_len)
|
||||||
{
|
{
|
||||||
return _nib_dst_add(next_hop, iface, pfx, pfx_len, _FT);
|
return _nib_offl_add(next_hop, iface, pfx, pfx_len, _FT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -637,7 +635,7 @@ static inline _nib_offl_entry_t *_nib_ft_add(const ipv6_addr_t *next_hop,
|
|||||||
*/
|
*/
|
||||||
static inline void _nib_ft_remove(_nib_offl_entry_t *nib_offl)
|
static inline void _nib_ft_remove(_nib_offl_entry_t *nib_offl)
|
||||||
{
|
{
|
||||||
_nib_dst_remove(nib_offl, _FT);
|
_nib_offl_remove(nib_offl, _FT);
|
||||||
}
|
}
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_ROUTER */
|
#endif /* GNRC_IPV6_NIB_CONF_ROUTER */
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
USEMODULE += gnrc_ipv6_nib
|
USEMODULE += gnrc_ipv6_nib
|
||||||
USEMODULE += gnrc_ipv6_netif
|
USEMODULE += gnrc_ipv6_netif
|
||||||
|
|
||||||
|
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_DEFAULT_ROUTER_NUMOF=4
|
CFLAGS += -DGNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF=4
|
||||||
|
|
||||||
INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/network_layer/ipv6/nib
|
INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/network_layer/ipv6/nib
|
||||||
|
|||||||
@ -29,7 +29,8 @@
|
|||||||
|
|
||||||
#define LINK_LOCAL_PREFIX { 0xfe, 0x08, 0, 0, 0, 0, 0, 0 }
|
#define LINK_LOCAL_PREFIX { 0xfe, 0x08, 0, 0, 0, 0, 0, 0 }
|
||||||
#define GLOBAL_PREFIX { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0 }
|
#define GLOBAL_PREFIX { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0 }
|
||||||
#define IFACE (26)
|
#define GLOBAL_PREFIX_LEN (30)
|
||||||
|
#define IFACE (6)
|
||||||
|
|
||||||
static void set_up(void)
|
static void set_up(void)
|
||||||
{
|
{
|
||||||
@ -121,6 +122,23 @@ static void test_nib_alloc__success_duplicate(void)
|
|||||||
TEST_ASSERT(node == _nib_onl_alloc(&addr, iface));
|
TEST_ASSERT(node == _nib_onl_alloc(&addr, iface));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a persistent on-link entry with no IPv6 address and then tries to
|
||||||
|
* create another one with the same interface, but with an address
|
||||||
|
* Expected result: entries should be identical
|
||||||
|
*/
|
||||||
|
static void test_nib_alloc__success_noaddr_override(void)
|
||||||
|
{
|
||||||
|
_nib_onl_entry_t *node1, *node2;
|
||||||
|
const ipv6_addr_t addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((node1 = _nib_onl_alloc(NULL, IFACE)));
|
||||||
|
TEST_ASSERT_NOT_NULL((node2 = _nib_onl_alloc(&addr, IFACE)));
|
||||||
|
TEST_ASSERT(node1 == node2);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&addr, &node1->ipv6));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates an non-persistent entry.
|
* Creates an non-persistent entry.
|
||||||
* Expected result: new entry should contain the given address and interface
|
* Expected result: new entry should contain the given address and interface
|
||||||
@ -964,6 +982,735 @@ static void test_nib_drl_get_dr__success4(void)
|
|||||||
TEST_ASSERT(nib_res != node2);
|
TEST_ASSERT(nib_res != node2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_NUMOF < GNRC_IPV6_NIB_OFFL_NUMOF
|
||||||
|
#define MAX_NUMOF (GNRC_IPV6_NIB_NUMOF)
|
||||||
|
#else /* GNRC_IPV6_NIB_NUMOF < GNRC_IPV6_NIB_OFFL_NUMOF */
|
||||||
|
#define MAX_NUMOF (GNRC_IPV6_NIB_OFFL_NUMOF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different next-hop addresses and
|
||||||
|
* then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different interfaces and then tries
|
||||||
|
* to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_iface(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _PL;
|
||||||
|
iface++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different next-hop addresses and
|
||||||
|
* interfaces and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_iface(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _DC;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
iface++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_OFFL_NUMOF off-link entries with different prefixes
|
||||||
|
* of the same length and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_pfx(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
for (int i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes of the same
|
||||||
|
* length and different next-hop addresses and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_pfx(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes of the same
|
||||||
|
* length and different interfaces and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_iface_pfx(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
iface++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes of the same
|
||||||
|
* length, different interfaces, and different next hop addresses and then
|
||||||
|
* tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
iface++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, GLOBAL_PREFIX_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_OFFL_NUMOF off-link entries with different prefix
|
||||||
|
* lengths and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_pfx_len(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN;
|
||||||
|
|
||||||
|
for (int i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _PL;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes and then tries to
|
||||||
|
* add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_pfx_len(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _PL;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefix lengths and
|
||||||
|
* interfaces and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_iface_pfx_len(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _PL;
|
||||||
|
iface++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefix lengths,
|
||||||
|
* interfaces, and next hop addresses and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx_len(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _PL;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
iface++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GNRC_IPV6_NIB_OFFL_NUMOF off-link entries with different prefixes
|
||||||
|
* and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_pfx_pfx_len(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN;
|
||||||
|
|
||||||
|
for (int i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes and different
|
||||||
|
* next-hop addresses and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_pfx_pfx_len(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, IFACE, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes and different
|
||||||
|
* interfaces and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_iface_pfx_pfx_len(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
iface++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes, different
|
||||||
|
* interfaces, and different next hop addresses and then tries to add another.
|
||||||
|
* Expected result: should return NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx_pfx_len(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
iface++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
pfx_len--;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates MAX_NUMOF off-link entries with different prefixes, different
|
||||||
|
* interfaces, and different next hop addresses and then tries to add another
|
||||||
|
* equal to the last.
|
||||||
|
* Expected result: should return not NULL (the last)
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__success_duplicate(void)
|
||||||
|
{
|
||||||
|
ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUMOF; i++) {
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
|
||||||
|
next_hop.u64[1].u64++;
|
||||||
|
iface++;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
pfx_len--;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, iface, &pfx,
|
||||||
|
pfx_len)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
dst->mode |= _FT;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_NOT_NULL(_nib_offl_alloc(&next_hop, iface, &pfx, pfx_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an off-link entry with no next hop address and then adds another
|
||||||
|
* with equal prefix and interface to the last, but with a next hop address
|
||||||
|
* Expected result: the first entry should be equal to the second and both
|
||||||
|
* have the same next hop address
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__success_overwrite_unspecified(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst1, *dst2;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst1 = _nib_offl_alloc(NULL, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst1->mode |= _PL;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst2 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst1->next_hop);
|
||||||
|
TEST_ASSERT_EQUAL_INT(_PL, dst1->mode);
|
||||||
|
TEST_ASSERT(dst1 == dst2);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&next_hop, &dst1->next_hop->ipv6));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an off-link entry.
|
||||||
|
* Expected result: new entry should contain the given prefix, address and
|
||||||
|
* interface
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_alloc__success(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT_EQUAL_INT(GLOBAL_PREFIX_LEN, dst->pfx_len);
|
||||||
|
TEST_ASSERT(GLOBAL_PREFIX_LEN <= ipv6_addr_match_prefix(&pfx, &dst->pfx));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
TEST_ASSERT_EQUAL_INT(_DST, dst->next_hop->mode);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&next_hop, &dst->next_hop->ipv6));
|
||||||
|
TEST_ASSERT_EQUAL_INT(IFACE, _nib_onl_get_if(dst->next_hop));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an off-link entry, sets a neighbor cache flag, and tries to remove
|
||||||
|
* it.
|
||||||
|
* Expected result: The off-link entry is removed, but the on-link entry should
|
||||||
|
* still exist
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_clear__uncleared(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
_nib_onl_entry_t *node;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
node = dst->next_hop;
|
||||||
|
node->mode |= _NC;
|
||||||
|
_nib_offl_clear(dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
TEST_ASSERT(node == _nib_onl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates two off-link entry off-link entries and tries to remove one of them.
|
||||||
|
* Expected result: The NIB should only contain the one removed, the on-link
|
||||||
|
* entry should still exist
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_clear__same_next_hop(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst1, *dst2, *res;
|
||||||
|
_nib_onl_entry_t *node;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst1 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst1->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst2 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT(dst1->next_hop == dst2->next_hop);
|
||||||
|
node = dst2->next_hop;
|
||||||
|
TEST_ASSERT_NOT_NULL(node);
|
||||||
|
_nib_offl_clear(dst2);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(NULL)));
|
||||||
|
TEST_ASSERT(dst1 == res);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(res));
|
||||||
|
TEST_ASSERT(node == _nib_onl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an off-link entry and tries to remove it.
|
||||||
|
* Expected result: The NIB should be empty
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_clear__cleared(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
_nib_offl_clear(dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
TEST_ASSERT_NULL(_nib_onl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over empty off-link entries
|
||||||
|
* Expected result: _nib_drl_iter returns NULL
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_iter__empty(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over off-link entries with one element
|
||||||
|
* Expected result: _nib_offl_iter returns element with NULL, and with that
|
||||||
|
* element NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_iter__one_elem(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst, *res;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst->mode |= _FT;
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over off-link entries with three element
|
||||||
|
* Expected result: _nib_offl_iter returns element with NULL, with that element
|
||||||
|
* another, with that element yet another and with the last NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_iter__three_elem(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst1, *dst2, *dst3, *res;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst1 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst1->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst2 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst2->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst3 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst3->mode |= _FT;
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == dst1);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(res)));
|
||||||
|
TEST_ASSERT(res == dst2);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(res)));
|
||||||
|
TEST_ASSERT(res == dst3);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterates over off-link entries with two elements, where there is a whole in
|
||||||
|
* the internal array
|
||||||
|
* Expected result: _nib_offl_iter returns element with NULL, with that element
|
||||||
|
* another, and with the last NULL.
|
||||||
|
*/
|
||||||
|
static void test_nib_offl_iter__three_elem_middle_removed(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst1, *dst2, *dst3, *res;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst1 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst1->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst2 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst2->mode |= _FT;
|
||||||
|
pfx.u16[0].u16++;
|
||||||
|
TEST_ASSERT_NOT_NULL((dst3 = _nib_offl_alloc(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
dst3->mode |= _FT;
|
||||||
|
dst2->mode = _EMPTY;
|
||||||
|
_nib_offl_clear(dst2);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(NULL)));
|
||||||
|
TEST_ASSERT(res == dst1);
|
||||||
|
TEST_ASSERT_NOT_NULL((res = _nib_offl_iter(res)));
|
||||||
|
TEST_ASSERT(res == dst3);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_DC
|
||||||
|
/*
|
||||||
|
* Creates a destination cache entry.
|
||||||
|
* Expected result: new entry should contain the given address and interface
|
||||||
|
*/
|
||||||
|
static void test_nib_dc_add__success(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_dc_add(&next_hop, IFACE, &dst_addr)));
|
||||||
|
TEST_ASSERT(dst->mode & _DC);
|
||||||
|
TEST_ASSERT_EQUAL_INT(IPV6_ADDR_BIT_LEN, dst->pfx_len);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&dst_addr, &dst->pfx));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
TEST_ASSERT_EQUAL_INT(_DST, dst->next_hop->mode);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&next_hop, &dst->next_hop->ipv6));
|
||||||
|
TEST_ASSERT_EQUAL_INT(IFACE, _nib_onl_get_if(dst->next_hop));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a destination cache entry and removes it.
|
||||||
|
* Expected result: The destination cache should be empty
|
||||||
|
*/
|
||||||
|
static void test_nib_dc_remove(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u64 = { { .u8 = GLOBAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_dc_add(&next_hop, IFACE, &dst_addr)));
|
||||||
|
_nib_dc_remove(dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a prefix list entry.
|
||||||
|
* Expected result: new entry should contain the given address and interface
|
||||||
|
*/
|
||||||
|
static void test_nib_pl_add__success(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_pl_add(IFACE, &pfx, GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT(dst->mode & _PL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GLOBAL_PREFIX_LEN, dst->pfx_len);
|
||||||
|
TEST_ASSERT(GLOBAL_PREFIX_LEN <= ipv6_addr_match_prefix(&pfx, &dst->pfx));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
TEST_ASSERT_EQUAL_INT(_DST, dst->next_hop->mode);
|
||||||
|
TEST_ASSERT_EQUAL_INT(IFACE, _nib_onl_get_if(dst->next_hop));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a prefix list entry and removes it.
|
||||||
|
* Expected result: The prefix list should be empty
|
||||||
|
*/
|
||||||
|
static void test_nib_pl_remove(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_pl_add(IFACE, &pfx, GLOBAL_PREFIX_LEN)));
|
||||||
|
_nib_pl_remove(dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a forwarding table entry.
|
||||||
|
* Expected result: new entry should contain the given address and interface
|
||||||
|
*/
|
||||||
|
static void test_nib_ft_add__success(void)
|
||||||
|
{
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_ft_add(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
TEST_ASSERT(dst->mode & _FT);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GLOBAL_PREFIX_LEN, dst->pfx_len);
|
||||||
|
TEST_ASSERT(GLOBAL_PREFIX_LEN <= ipv6_addr_match_prefix(&pfx, &dst->pfx));
|
||||||
|
TEST_ASSERT_NOT_NULL(dst->next_hop);
|
||||||
|
TEST_ASSERT_EQUAL_INT(_DST, dst->next_hop->mode);
|
||||||
|
TEST_ASSERT(ipv6_addr_equal(&next_hop, &dst->next_hop->ipv6));
|
||||||
|
TEST_ASSERT_EQUAL_INT(IFACE, _nib_onl_get_if(dst->next_hop));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a forwarding table entry and removes it.
|
||||||
|
* Expected result: The forwarding table should be empty
|
||||||
|
*/
|
||||||
|
static void test_nib_ft_remove(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
_nib_offl_entry_t *dst;
|
||||||
|
static const ipv6_addr_t next_hop = { .u64 = { { .u8 = LINK_LOCAL_PREFIX },
|
||||||
|
{ .u64 = TEST_UINT64 } } };
|
||||||
|
static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } };
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL((dst = _nib_ft_add(&next_hop, IFACE, &pfx,
|
||||||
|
GLOBAL_PREFIX_LEN)));
|
||||||
|
_nib_ft_remove(dst);
|
||||||
|
TEST_ASSERT_NULL(_nib_offl_iter(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@ -998,6 +1745,7 @@ Test *tests_gnrc_ipv6_nib_internal_tests(void)
|
|||||||
new_TestFixture(test_nib_alloc__no_space_left_diff_iface),
|
new_TestFixture(test_nib_alloc__no_space_left_diff_iface),
|
||||||
new_TestFixture(test_nib_alloc__no_space_left_diff_addr_iface),
|
new_TestFixture(test_nib_alloc__no_space_left_diff_addr_iface),
|
||||||
new_TestFixture(test_nib_alloc__success_duplicate),
|
new_TestFixture(test_nib_alloc__success_duplicate),
|
||||||
|
new_TestFixture(test_nib_alloc__success_noaddr_override),
|
||||||
new_TestFixture(test_nib_alloc__success),
|
new_TestFixture(test_nib_alloc__success),
|
||||||
new_TestFixture(test_nib_clear__persistent),
|
new_TestFixture(test_nib_clear__persistent),
|
||||||
new_TestFixture(test_nib_clear__non_persistent_but_content),
|
new_TestFixture(test_nib_clear__non_persistent_but_content),
|
||||||
@ -1041,6 +1789,39 @@ Test *tests_gnrc_ipv6_nib_internal_tests(void)
|
|||||||
new_TestFixture(test_nib_drl_get_dr__success2),
|
new_TestFixture(test_nib_drl_get_dr__success2),
|
||||||
new_TestFixture(test_nib_drl_get_dr__success3),
|
new_TestFixture(test_nib_drl_get_dr__success3),
|
||||||
new_TestFixture(test_nib_drl_get_dr__success4),
|
new_TestFixture(test_nib_drl_get_dr__success4),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_iface),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_iface),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_pfx),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_pfx),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_iface_pfx),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_iface_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_pfx_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_pfx_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_iface_pfx_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__no_space_left_diff_next_hop_iface_pfx_pfx_len),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__success_duplicate),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__success_overwrite_unspecified),
|
||||||
|
new_TestFixture(test_nib_offl_alloc__success),
|
||||||
|
new_TestFixture(test_nib_offl_clear__uncleared),
|
||||||
|
new_TestFixture(test_nib_offl_clear__same_next_hop),
|
||||||
|
new_TestFixture(test_nib_offl_clear__cleared),
|
||||||
|
new_TestFixture(test_nib_offl_iter__empty),
|
||||||
|
new_TestFixture(test_nib_offl_iter__one_elem),
|
||||||
|
new_TestFixture(test_nib_offl_iter__three_elem),
|
||||||
|
new_TestFixture(test_nib_offl_iter__three_elem_middle_removed),
|
||||||
|
#if GNRC_IPV6_NIB_CONF_DC
|
||||||
|
new_TestFixture(test_nib_dc_add__success),
|
||||||
|
new_TestFixture(test_nib_dc_remove),
|
||||||
|
#endif
|
||||||
|
new_TestFixture(test_nib_pl_add__success),
|
||||||
|
new_TestFixture(test_nib_pl_remove),
|
||||||
|
new_TestFixture(test_nib_ft_add__success),
|
||||||
|
new_TestFixture(test_nib_ft_remove),
|
||||||
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),
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user