

8 changed files with 1543 additions and 0 deletions
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 Neighbor Information Base for IPv6 |
||||
* @ingroup net_gnrc_ipv6 |
||||
* @brief Neighbor Information Base (NIB) for IPv6 |
||||
* |
||||
* @todo Add detailed description |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief NIB definitions |
||||
* |
||||
* @author Martine Lenders <m.lenders@fu-berlin.de> |
||||
*/ |
||||
#ifndef NET_GNRC_IPV6_NIB_H |
||||
#define NET_GNRC_IPV6_NIB_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name Timer event message types |
||||
* @anchor net_gnrc_ipv6_nib_msg |
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @brief (Re-)transmit unicast Neighbor Solicitation event. |
||||
* |
||||
* This message type is for the event of (re-)transmitting of unicast Neighbor |
||||
* Solicitation. The expected message context is a pointer to a valid on-link |
||||
* entry representing the neighbor to which the Neighbor Solicitation is |
||||
* supposed to be sent. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_SND_UC_NS (0x4fc0U) |
||||
|
||||
/**
|
||||
* @brief (Re-)transmit multicast Neighbor Solicitation event. |
||||
* |
||||
* This message type is for the event of (re-)transmitting of multicast Neighbor |
||||
* Solicitation. The expected message context is a pointer to a valid on-link |
||||
* entry representing the neighbor to which [solicited |
||||
* nodes](https://tools.ietf.org/html/rfc4291#section-2.7.1) group
|
||||
* the Neighbor Solicitation is supposed to be sent. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_SND_MC_NS (0x4fc1U) |
||||
|
||||
/**
|
||||
* @brief Send delayed Neighbor Advertisement event. |
||||
* |
||||
* This message type is for the event of sending delayed Neighbor |
||||
* Advertisements. The expected message context is a pointer to a valid |
||||
* [packet snip](@ref gnrc_pktsnip_t) in *sending order*, representing the |
||||
* Neighbor Advertisement. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_SND_NA (0x4fc2U) |
||||
|
||||
/**
|
||||
* @brief Search router event. |
||||
* |
||||
* This message type is for the event of searching a (new) router (which |
||||
* implies sending a multicast Router Solicitation). The expected message |
||||
* context is a pointer to a valid interface behind which the router is |
||||
* searched. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_SEARCH_RTR (0x4fc3U) |
||||
|
||||
/**
|
||||
* @brief Reconfirm router event. |
||||
* |
||||
* This message type is for the event the reconfirmation of a router (which |
||||
* implies sending a unicast Router Solicitation). The expected message context |
||||
* is a pointer to a valid on-link entry representing the router that is to be |
||||
* confirmed. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_RECONFIRM_RTR (0x4fc4U) |
||||
|
||||
/**
|
||||
* @brief Reply Router Solicitation event. |
||||
* |
||||
* This message type is for the event of the delayed reply to a Router |
||||
* Solicitaion with a Router Advertisement. The expected message context is a |
||||
* pointer to a valid on-link entry representing the neighbor that sent the |
||||
* Router Solicitation. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_REPLY_RS (0x4fc5U) |
||||
|
||||
/**
|
||||
* @brief (Re-)transmit multicast Router Advertisement event. |
||||
* |
||||
* This message type is for the event of (Re)transmit Advertisements |
||||
* event. The expected message context is a pointer to a valid interface over |
||||
* which the Router Advertisement will be sent and by which parameters it will |
||||
* be configured. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_SND_MC_RA (0x4fc6U) |
||||
|
||||
/**
|
||||
* @brief Reachability timeout event. |
||||
* |
||||
* This message type is for the event of a REACHABLE state timeout. |
||||
* The expected message context is a pointer to a valid on-link entry |
||||
* representing the neighbor cache entry that faces a state change. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ARSM != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_REACH_TIMEOUT (0x4fc7U) |
||||
|
||||
/**
|
||||
* @brief Delay timeout event. |
||||
* |
||||
* This message type is for the event of the DELAY state timeout. |
||||
* The expected message context is a pointer to a valid on-link entry |
||||
* representing the neighbor cache entry that faces a state change. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ARSM != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_DELAY_TIMEOUT (0x4fc8U) |
||||
|
||||
/**
|
||||
* @brief Address registration timeout event. |
||||
* |
||||
* This message type is for the event of a 6LoWPAN address registration state |
||||
* timeout. The expected message context is a pointer to a valid on-link entry |
||||
* representing the neighbor which faces a timeout of its address registration. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_6LR != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_ADDR_REG_TIMEOUT (0x4fc9U) |
||||
|
||||
/**
|
||||
* @brief 6LoWPAN context timeout event. |
||||
* |
||||
* This message type is for the event of a 6LoWPAN compression context timeout. |
||||
* The expected message context is the compression context's numerical |
||||
* identifier. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_6LN != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_6LO_CTX_TIMEOUT (0x4fcaU) |
||||
|
||||
/**
|
||||
* @brief Authoritative border router timeout event. |
||||
* |
||||
* This message type is for the event of an Authoritative border router timeout. |
||||
* The expected message context is the NIB-internal state of the authoritative |
||||
* border router. |
||||
* |
||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_MULTIHOP_P6C != 0 |
||||
*/ |
||||
#define GNRC_IPV6_NIB_ABR_TIMEOUT (0x4fcbU) |
||||
|
||||
/**
|
||||
* @brief Prefix timeout event. |
||||
* |
||||
* This message type is for the event of a prefix timeout. The expected message |
||||
* context is a valid off-link entry representing the prefix. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_PFX_TIMEOUT (0x4fccU) |
||||
|
||||
/**
|
||||
* @brief Router timeout event. |
||||
* |
||||
* This message type is for the event of a router timeout. The expected message |
||||
* context is a valid default router entry representing the router. |
||||
*/ |
||||
#define GNRC_IPV6_NIB_RTR_TIMEOUT (0x4fcdU) |
||||
/** @} */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NET_GNRC_IPV6_NIB_H */ |
||||
/** @} */ |
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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_conf Configuration macros |
||||
* @ingroup net_gnrc_ipv6_nib |
||||
* @brief Configuration macros for network information base |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Configuration macro definitions for network information base |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
#ifndef NET_GNRC_IPV6_NIB_CONF_H |
||||
#define NET_GNRC_IPV6_NIB_CONF_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name Compile flags |
||||
* @brief Compile flags to (de-)activate certain features for NIB |
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @brief enable features for 6Lo border router |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_6LBR |
||||
#define GNRC_IPV6_NIB_CONF_6LBR (0) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief enable features for 6Lo router |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_6LR |
||||
#if GNRC_IPV6_NIB_CONF_6LBR |
||||
#define GNRC_IPV6_NIB_CONF_6LR (1) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_6LR (0) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief enable features for 6Lo node |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_6LN |
||||
#if GNRC_IPV6_NIB_CONF_6LR |
||||
#define GNRC_IPV6_NIB_CONF_6LN (1) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_6LN (0) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief enable features for IPv6 routers |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_ROUTER |
||||
#if GNRC_IPV6_NIB_CONF_6LR |
||||
#define GNRC_IPV6_NIB_CONF_ROUTER (1) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_ROUTER (0) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief (de-)activate router advertising at interface start-up |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_ADV_ROUTER |
||||
#if GNRC_IPV6_NIB_CONF_ROUTER && \ |
||||
(!GNRC_IPV6_NIB_CONF_6LR || GNRC_IPV6_NIB_CONF_6LBR) |
||||
#define GNRC_IPV6_NIB_CONF_ADV_ROUTER (1) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_ADV_ROUTER (0) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief (de-)activate NDP address resolution state-machine |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_ARSM |
||||
#define GNRC_IPV6_NIB_CONF_ARSM (1) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief queue packets for address resolution |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_QUEUE_PKT |
||||
#if GNRC_IPV6_NIB_CONF_6LN |
||||
#define GNRC_IPV6_NIB_CONF_QUEUE_PKT (0) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_QUEUE_PKT (1) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief handle NDP messages according for stateless address |
||||
* auto-configuration (if activated on interface) |
||||
* |
||||
* @see [RFC 4862](https://tools.ietf.org/html/rfc4862)
|
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_SLAAC |
||||
#define GNRC_IPV6_NIB_CONF_SLAAC (1) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief handle Redirect Messages |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_REDIRECT |
||||
#define GNRC_IPV6_NIB_CONF_REDIRECT (0) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief (de-)activate destination cache |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_DC |
||||
#if GNRC_IPV6_NIB_CONF_REDIRECT |
||||
#define GNRC_IPV6_NIB_CONF_DC (1) |
||||
#else |
||||
#define GNRC_IPV6_NIB_CONF_DC (0) |
||||
#endif |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Multihop prefix and 6LoWPAN context distribution |
||||
* |
||||
* @see [RFC 6775, section 8.1](https://tools.ietf.org/html/rfc6775#section-8.1)
|
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_MULTIHOP_P6C |
||||
#define GNRC_IPV6_NIB_CONF_MULTIHOP_P6C (0) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Multihop duplicate address detection |
||||
* |
||||
* @see [RFC 6775, section 8.2](https://tools.ietf.org/html/rfc6775#section-8.2)
|
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_MULTIHOP_DAD |
||||
#define GNRC_IPV6_NIB_CONF_MULTIHOP_DAD (0) |
||||
#endif |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Reset time in milliseconds for the reachability time |
||||
* |
||||
* @see [RFC 4861, section 6.3.4](https://tools.ietf.org/html/rfc4861#section-6.3.4)
|
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_CONF_REACH_TIME_RESET |
||||
#define GNRC_IPV6_NIB_CONF_REACH_TIME_RESET (7200000U) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Maximum link-layer address length (aligned) |
||||
*/ |
||||
#if (GNRC_NETIF_HDR_L2ADDR_MAX_LEN % 8) |
||||
#define GNRC_IPV6_NIB_L2ADDR_MAX_LEN (((GNRC_NETIF_HDR_L2ADDR_MAX_LEN >> 3) + 1) << 3) |
||||
#else |
||||
#define GNRC_IPV6_NIB_L2ADDR_MAX_LEN (GNRC_NETIF_HDR_L2ADDR_MAX_LEN) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Number of default routers in the default router list. |
||||
* |
||||
* @note **This number has direct influence on the maximum number of |
||||
* default routers** |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF |
||||
#define GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF (1) |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Number of entries in NIB |
||||
* |
||||
* @note **This number has direct influence on the maximum number of |
||||
* neighbors and duplicate address detection table entries** |
||||
*/ |
||||
#ifndef GNRC_IPV6_NIB_NUMOF |
||||
#define GNRC_IPV6_NIB_NUMOF (4) |
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NET_GNRC_IPV6_NIB_CONF_H */ |
||||
/** @} */ |
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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_nc Neighbor Cache |
||||
* @ingroup net_gnrc_ipv6_nib |
||||
* @brief Neighbor cache component of network information base |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Neighbor cache definitions |
||||
* |
||||
* @author Martine Lenders <m.lenders@fu-berlin.de> |
||||
*/ |
||||
#ifndef NET_GNRC_IPV6_NIB_NC_H |
||||
#define NET_GNRC_IPV6_NIB_NC_H |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
|
||||
#include "net/eui64.h" |
||||
#include "net/gnrc/netif/hdr.h" |
||||
#include "net/gnrc/ipv6/nib/conf.h" |
||||
#include "net/ipv6/addr.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Values for gnrc_ipv6_nib_nc_t::info |
||||
* @anchor net_gnrc_ipv6_nib_nc_info |
||||
* @name Info values |
||||
* @{ |
||||
*/ |
||||
/**
|
||||
* @brief Mask for neighbor unreachability detection (NUD) states |
||||
* |
||||
* @see [RFC 4861, section 7.3.2](https://tools.ietf.org/html/rfc4861#section-7.3.2)
|
||||
* @see [RFC 7048](https://tools.ietf.org/html/rfc7048)
|
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK (0x0007) |
||||
|
||||
/**
|
||||
* @brief not managed by NUD |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED (0x0000) |
||||
|
||||
/**
|
||||
* @brief entry is not reachable |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE (0x0001) |
||||
|
||||
/**
|
||||
* @brief address resolution is currently performed |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE (0x0002) |
||||
|
||||
/**
|
||||
* @brief address might not be reachable |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE (0x0003) |
||||
|
||||
/**
|
||||
* @brief NUD will be performed in a moment |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY (0x0004) |
||||
|
||||
/**
|
||||
* @brief NUD is performed |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE (0x0005) |
||||
|
||||
/**
|
||||
* @brief entry is reachable |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE (0x0006) |
||||
|
||||
/**
|
||||
* @brief gnrc_ipv6_nib_t::next_hop is router |
||||
* |
||||
* This flag indicates that gnrc_ipv6_nib_t::next_hop is a router, but it does |
||||
* not necessarily indicate that it is in the default router list! A neighbor |
||||
* that has this flag unset however **must not** appear in the default router |
||||
* list. |
||||
* |
||||
* @see [RFC 4861, Appendix D](https://tools.ietf.org/html/rfc4861#page-91)
|
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_IS_ROUTER (0x0008) |
||||
|
||||
/**
|
||||
* @brief Mask for interface identifier |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_IFACE_MASK (0x01f0) |
||||
|
||||
/**
|
||||
* @brief Shift position of interface identifier |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_IFACE_POS (4) |
||||
|
||||
/**
|
||||
* @brief Mask for 6LoWPAN address registration (6Lo-AR) states |
||||
* |
||||
* @see [RFC 6775, section 3.5](https://tools.ietf.org/html/rfc6775#section-3.5)
|
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_AR_STATE_MASK (0x0600) |
||||
|
||||
/**
|
||||
* @brief not managed by 6Lo-AR (address can be removed when memory is low |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_AR_STATE_GC (0x0000) |
||||
|
||||
/**
|
||||
* @brief address registration still pending at upstream router |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_AR_STATE_TENTATIVE (0x0200) |
||||
|
||||
/**
|
||||
* @brief address is registered |
||||
*/ |
||||
#define GNRC_IPV6_NIB_NC_INFO_AR_STATE_REGISTERED (0x0600) |
||||
/** @} */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NET_GNRC_IPV6_NIB_NC_H */ |
||||
/** @} */ |
@ -0,0 +1,3 @@
|
||||
MODULE = gnrc_ipv6_nib
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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 <m.lenders@fu-berlin.de> |
||||
*/ |
||||
|
||||
#include <stdbool.h> |
||||
#include <string.h> |
||||
|
||||
#include "net/gnrc/ipv6.h" |
||||
#include "net/gnrc/ipv6/nib/conf.h" |
||||
#include "net/gnrc/ipv6/nib/nc.h" |
||||
#include "net/gnrc/ipv6/nib.h" |
||||
#include "net/gnrc/netif.h" |
||||
#include "random.h" |
||||
|
||||
#include "_nib-internal.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
/* pointers for default router selection */ |
||||
static _nib_dr_entry_t *_prime_def_router = NULL; |
||||
static clist_node_t _next_removable = { NULL }; |
||||
|
||||
static _nib_onl_entry_t _nodes[GNRC_IPV6_NIB_NUMOF]; |
||||
static _nib_dr_entry_t _def_routers[GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF]; |
||||
static _nib_iface_t _nis[GNRC_NETIF_NUMOF]; |
||||
|
||||
#if ENABLE_DEBUG |
||||
static char addr_str[IPV6_ADDR_MAX_STR_LEN]; |
||||
#endif |
||||
|
||||
mutex_t _nib_mutex = MUTEX_INIT; |
||||
|
||||
static void _override_node(const ipv6_addr_t *addr, unsigned iface, |
||||
_nib_onl_entry_t *node); |
||||
static inline bool _node_unreachable(_nib_onl_entry_t *node); |
||||
|
||||
void _nib_init(void) |
||||
{ |
||||
#ifdef TEST_SUITES |
||||
_prime_def_router = NULL; |
||||
_next_removable.next = NULL; |
||||
memset(_nodes, 0, sizeof(_nodes)); |
||||
memset(_def_routers, 0, sizeof(_def_routers)); |
||||
memset(_nis, 0, sizeof(_nis)); |
||||
#endif |
||||
/* TODO: load ABR information from persistent memory */ |
||||
} |
||||
|
||||
_nib_onl_entry_t *_nib_onl_alloc(const ipv6_addr_t *addr, unsigned iface) |
||||
{ |
||||
_nib_onl_entry_t *node = NULL; |
||||
|
||||
assert(addr != NULL); |
||||
DEBUG("nib: Allocating on-link node entry (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface); |
||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_NUMOF; i++) { |
||||
_nib_onl_entry_t *tmp = &_nodes[i]; |
||||
|
||||
if ((_nib_onl_get_if(tmp) == iface) && |
||||
(ipv6_addr_equal(addr, &tmp->ipv6))) { |
||||
/* exact match */ |
||||
DEBUG(" %p is an exact match\n", (void *)tmp); |
||||
return tmp; |
||||
} |
||||
if ((node == NULL) && (tmp->mode == _EMPTY)) { |
||||
node = tmp; |
||||
} |
||||
} |
||||
if (node != NULL) { |
||||
DEBUG(" using %p\n", (void *)node); |
||||
_override_node(addr, iface, node); |
||||
} |
||||
#if ENABLE_DEBUG |
||||
else { |
||||
DEBUG(" NIB full\n"); |
||||
} |
||||
#endif |
||||
return node; |
||||
} |
||||
|
||||
static inline bool _is_gc(_nib_onl_entry_t *node) |
||||
{ |
||||
return ((node->mode & ~(_NC)) == 0) && |
||||
((node->info & GNRC_IPV6_NIB_NC_INFO_AR_STATE_MASK) == |
||||
GNRC_IPV6_NIB_NC_INFO_AR_STATE_GC); |
||||
} |
||||
|
||||
static inline _nib_onl_entry_t *_cache_out_onl_entry(const ipv6_addr_t *addr, |
||||
unsigned iface, |
||||
uint16_t cstate) |
||||
{ |
||||
/* Use clist as FIFO for caching */ |
||||
_nib_onl_entry_t *first = (_nib_onl_entry_t *)clist_lpop(&_next_removable); |
||||
_nib_onl_entry_t *tmp = first, *res = NULL; |
||||
|
||||
DEBUG("nib: Searching for replaceable entries (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface); |
||||
if (tmp == NULL) { |
||||
return NULL; |
||||
} |
||||
do { |
||||
if (_is_gc(tmp)) { |
||||
DEBUG("nib: Removing neighbor cache entry (addr = %s, " |
||||
"iface = %u) ", |
||||
ipv6_addr_to_str(addr_str, &tmp->ipv6, |
||||
sizeof(addr_str)), |
||||
_nib_onl_get_if(tmp)); |
||||
DEBUG("for (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), |
||||
iface); |
||||
res = tmp; |
||||
res->mode = _EMPTY; |
||||
_override_node(addr, iface, res); |
||||
/* cstate masked above already */ |
||||
res->info = cstate; |
||||
res->mode = _NC; |
||||
break; |
||||
} |
||||
/* requeue if not garbage collectible at the moment */ |
||||
DEBUG("nib: Requeing (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, &tmp->ipv6, |
||||
sizeof(addr_str)), |
||||
_nib_onl_get_if(tmp)); |
||||
clist_rpush(&_next_removable, (clist_node_t *)tmp); |
||||
tmp = (_nib_onl_entry_t *)clist_lpop(&_next_removable); |
||||
} while (tmp != first); |
||||
return res; |
||||
} |
||||
|
||||
_nib_onl_entry_t *_nib_nc_add(const ipv6_addr_t *addr, unsigned iface, |
||||
uint16_t cstate) |
||||
{ |
||||
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_PROBE); |
||||
assert(cstate != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE); |
||||
_nib_onl_entry_t *node = _nib_onl_alloc(addr, iface); |
||||
if (node == NULL) { |
||||
return _cache_out_onl_entry(addr, iface, cstate); |
||||
} |
||||
DEBUG("nib: Adding to neighbor cache (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface); |
||||
if (!(node->mode & _NC)) { |
||||
node->info &= ~GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK; |
||||
/* masked above already */ |
||||
node->info |= cstate; |
||||
node->mode |= _NC; |
||||
} |
||||
if (node->next == NULL) { |
||||
DEBUG("nib: queueing (addr = %s, iface = %u) for potential removal\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface); |
||||
/* add to next removable list, if not already in it */ |
||||
clist_rpush(&_next_removable, (clist_node_t *)node); |
||||
} |
||||
return node; |
||||
} |
||||
|
||||
_nib_onl_entry_t *_nib_onl_iter(const _nib_onl_entry_t *last) |
||||
{ |
||||
for (const _nib_onl_entry_t *node = (last) ? last + 1 : _nodes; |
||||
node < (_nodes + GNRC_IPV6_NIB_NUMOF); |
||||
node++) { |
||||
if (node->mode != _EMPTY) { |
||||
/* const modifier provided to assure internal consistency.
|
||||
* Can now be discarded. */ |
||||
return (_nib_onl_entry_t *)node; |
||||
} |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
_nib_onl_entry_t *_nib_onl_get(const ipv6_addr_t *addr, unsigned iface) |
||||
{ |
||||
assert(addr != NULL); |
||||
DEBUG("nib: Getting on-link node entry (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), iface); |
||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_NUMOF; i++) { |
||||
_nib_onl_entry_t *node = &_nodes[i]; |
||||
|
||||
if ((node->mode != _EMPTY) && |
||||
/* either requested or current interface undefined or
|
||||
* interfaces equal */ |
||||
((_nib_onl_get_if(node) == 0) || (iface == 0) || |
||||
(_nib_onl_get_if(node) == iface)) && |
||||
ipv6_addr_equal(&node->ipv6, addr)) { |
||||
DEBUG(" Found %p\n", (void *)node); |
||||
return node; |
||||
} |
||||
} |
||||
DEBUG(" No suitable entry found\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
void _nib_nc_set_reachable(_nib_onl_entry_t *node) |
||||
{ |
||||
_nib_iface_t *iface = _nib_iface_get(_nib_onl_get_if(node)); |
||||
|
||||
DEBUG("nib: set %s%%%u reachable (reachable time = %u)\n", |
||||
ipv6_addr_to_str(addr_str, &node->ipv6, sizeof(addr_str)), |
||||
_nib_onl_get_if(node), iface->reach_time); |
||||
node->info &= ~GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK; |
||||
node->info |= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE; |
||||
/* TODO add event for state change to STALE to event timer*/ |
||||
(void)iface; |
||||
} |
||||
|
||||
void _nib_nc_remove(_nib_onl_entry_t *node) |
||||
{ |
||||
DEBUG("nib: remove from neighbor cache (addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, &node->ipv6, sizeof(addr_str)), |
||||
_nib_onl_get_if(node)); |
||||
node->mode &= ~(_NC); |
||||
/* TODO: remove NC related timers */ |
||||
_nib_onl_clear(node); |
||||
} |
||||
|
||||
_nib_dr_entry_t *_nib_drl_add(const ipv6_addr_t *router_addr, unsigned iface) |
||||
{ |
||||
_nib_dr_entry_t *def_router = NULL; |
||||
|
||||
DEBUG("nib: Allocating default router list entry " |
||||
"(router_addr = %s, iface = %u)\n", |
||||
ipv6_addr_to_str(addr_str, router_addr, sizeof(addr_str)), iface); |
||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF; i++) { |
||||
_nib_dr_entry_t *tmp = &_def_routers[i]; |
||||
_nib_onl_entry_t *tmp_node = tmp->next_hop; |
||||
|
||||
if ((tmp_node != NULL) && |
||||
(_nib_onl_get_if(tmp_node) == iface) && |
||||
(ipv6_addr_equal(router_addr, &tmp_node->ipv6))) { |
||||
/* exact match */ |
||||
DEBUG(" %p is an exact match\n", (void *)tmp); |
||||
tmp_node->mode |= _DRL; |
||||
return tmp; |
||||
} |
||||
if ((def_router == NULL) && (tmp_node == NULL)) { |
||||
def_router = tmp; |
||||
} |
||||
} |
||||
if (def_router != NULL) { |
||||
DEBUG(" using %p\n", (void *)def_router); |
||||
def_router->next_hop = _nib_onl_alloc(router_addr, iface); |
||||
|
||||
if (def_router->next_hop == NULL) { |
||||
return NULL; |
||||
} |
||||
_override_node(router_addr, iface, def_router->next_hop); |
||||
def_router->next_hop->mode |= _DRL; |
||||
} |
||||
return def_router; |
||||
} |
||||
|
||||
void _nib_drl_remove(_nib_dr_entry_t *nib_dr) |
||||
{ |
||||
if (nib_dr->next_hop != NULL) { |
||||
nib_dr->next_hop->mode &= ~(_DRL); |
||||
_nib_onl_clear(nib_dr->next_hop); |
||||
memset(nib_dr, 0, sizeof(_nib_dr_entry_t)); |
||||
} |
||||
if (nib_dr == _prime_def_router) { |
||||
_prime_def_router = NULL; |
||||
} |
||||
} |
||||
|
||||
_nib_dr_entry_t *_nib_drl_iter(const _nib_dr_entry_t *last) |
||||
{ |
||||
for (const _nib_dr_entry_t *def_router = (last) ? (last + 1) : _def_routers; |
||||
def_router < (_def_routers + GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF); |
||||
def_router++) { |
||||
_nib_onl_entry_t *node = def_router->next_hop; |
||||
if ((node != NULL) && (node->mode != _EMPTY)) { |
||||
/* const modifier provided to assure internal consistency.
|
||||
* Can now be discarded. */ |
||||
return (_nib_dr_entry_t *)def_router; |
||||
} |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
_nib_dr_entry_t *_nib_drl_get(const ipv6_addr_t *router_addr, unsigned iface) |
||||
{ |
||||
for (unsigned i = 0; i < GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF; i++) { |
||||
_nib_dr_entry_t *def_router = &_def_routers[i]; |
||||
_nib_onl_entry_t *node = def_router->next_hop; |
||||
|
||||
if ((node != NULL) && |
||||
(_nib_onl_get_if(node) == iface) && |
||||
(ipv6_addr_equal(router_addr, &node->ipv6))) { |
||||
/* It is linked to the default router list so it *should* be set */ |
||||
assert(node->mode & _DRL); |
||||
return def_router; |
||||
} |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
_nib_dr_entry_t *_nib_drl_get_dr(void) |
||||
{ |
||||
_nib_dr_entry_t *ptr = NULL; |
||||
|
||||
/* if there is already a default router selected or
|
||||
* its reachability is not suspect */ |
||||
if (!((_prime_def_router == NULL) || |
||||
(_node_unreachable(_prime_def_router->next_hop)))) { |
||||
/* take it */ |
||||
return _prime_def_router; |
||||
} |
||||
/* else search next reachable router */ |
||||
do { |
||||
ptr = _nib_drl_iter(ptr); |
||||
/* if there is no reachable router */ |
||||
if (ptr == NULL) { |
||||
_nib_dr_entry_t *next = _nib_drl_iter(_prime_def_router); |
||||
/* if first time called or last selected router is last in
|
||||
* router list */ |
||||
if ((_prime_def_router == NULL) || (next == NULL)) { |
||||
/* wrap around to first (potentially unreachable) route
|
||||
* to trigger NUD for it */ |
||||
_prime_def_router = _nib_drl_iter(NULL); |
||||
} |
||||
/* there is another default router, choose it regardless of
|
||||
* reachability to potentially trigger NUD for it */ |
||||
else if (next != NULL) { |
||||
_prime_def_router = next; |
||||
} |
||||
return _prime_def_router; |
||||
} |
||||
} while (_node_unreachable(ptr->next_hop)); |
||||
_prime_def_router = ptr; |
||||
return _prime_def_router; |
||||
} |
||||
|
||||
_nib_iface_t *_nib_iface_get(unsigned iface) |
||||
{ |
||||
_nib_iface_t *ni = NULL; |
||||
|
||||
assert(iface <= _NIB_IF_MAX); |
||||
for (unsigned i = 0; i < GNRC_NETIF_NUMOF; i++) { |
||||
_nib_iface_t *tmp = &_nis[i]; |
||||
if (((unsigned)tmp->pid) == iface) { |
||||
return tmp; |
||||
} |
||||
if ((ni == NULL) && (tmp->pid == KERNEL_PID_UNDEF)) { |
||||
ni = tmp; |
||||
} |
||||
} |
||||
if (ni != NULL) { |
||||
memset(ni, 0, sizeof(_nib_iface_t)); |
||||
/* TODO: set random reachable time using constants from #6220 */ |
||||
ni->pid = (kernel_pid_t)iface; |
||||
} |
||||
return ni; |
||||
} |
||||
|
||||
static void _override_node(const ipv6_addr_t *addr, unsigned iface, |
||||
_nib_onl_entry_t *node) |
||||
{ |
||||
_nib_onl_clear(node); |
||||
memcpy(&node->ipv6, addr, sizeof(node->ipv6)); |
||||
_nib_onl_set_if(node, iface); |
||||
} |
||||
|
||||
static inline bool _node_unreachable(_nib_onl_entry_t *node) |
||||
{ |
||||
switch (node->info & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) { |
||||
case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE: |
||||
/* Falls through. */ |
||||
case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE: |
||||
return true; |
||||
default: |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** @} */ |
@ -0,0 +1,633 @@
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
/**
|
||||
* @addtogroup net_gnrc_ipv6_nib |
||||
* @internal |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Internal definitions |
||||
* |
||||
* @author Martine Lenders <m.lenders@fu-berlin.de> |
||||
*/ |
||||
#ifndef PRIV_NIB_INTERNAL_H |
||||
#define PRIV_NIB_INTERNAL_H |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
|
||||
#include "kernel_types.h" |
||||
#include "mutex.h" |
||||
#include "net/eui64.h" |
||||
#include "net/ipv6/addr.h" |
||||
#include "net/gnrc/ipv6/nib/nc.h" |
||||
#include "net/gnrc/ipv6/nib/conf.h" |
||||
#include "net/gnrc/pktqueue.h" |
||||
#include "net/ndp.h" |
||||
#include "random.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name Mode flags for entries |
||||
* @anchor net_gnrc_ipv6_nib_mode |
||||
* @{ |
||||
*/ |
||||
#define _EMPTY (0x00) /**< empty */ |
||||
#define _NC (0x01) /**< neighbor cache */ |
||||
#define _DC (0x02) /**< destination cache */ |
||||
#define _PL (0x04) /**< prefix list */ |
||||
#define _DRL (0x08) /**< default router list */ |
||||
#define _FT (0x10) /**< forwarding table */ |
||||
#define _DAD (0x20) /**< 6LoWPAN duplicate address detection table */ |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Shorter name for convenience ;-) |
||||
*/ |
||||
#define _NIB_IF_MASK (GNRC_IPV6_NIB_NC_INFO_IFACE_MASK) |
||||
|
||||
/**
|
||||
* @brief Shorter name for convenience ;-) |
||||
*/ |
||||
#define _NIB_IF_POS (GNRC_IPV6_NIB_NC_INFO_IFACE_POS) |
||||
|
||||
/**
|
||||
* @brief Maximum identifier for the interface |
||||
*/ |
||||
#define _NIB_IF_MAX (_NIB_IF_MASK >> _NIB_IF_POS) |
||||
|
||||
/**
|
||||
* @brief On-link NIB entry |
||||
* @anchor _nib_onl_entry_t |
||||
*/ |
||||
typedef struct _nib_onl_entry { |
||||
struct _nib_onl_entry *next; /**< next removable entry */ |
||||
#if GNRC_IPV6_NIB_CONF_QUEUE_PKT || defined(DOXYGEN) |
||||
/**
|
||||
* @brief queue for packets currently in address resolution |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_QUEUE_PKT != 0. |
||||
*/ |
||||
gnrc_pktqueue_t *pktqueue; |
||||
#endif |
||||
/**
|
||||
* @brief Neighbors IPv6 address |
||||
*/ |
||||
ipv6_addr_t ipv6; |
||||
#if GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) |
||||
/**
|
||||
* @brief The neighbors EUI-64 (used for DAD) |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_6LR != 0. |
||||
*/ |
||||
eui64_t eui64; |
||||
#endif |
||||
#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) |
||||
/**
|
||||
* @brief Link-layer address of _nib_onl_entry_t::next_hop |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ARSM != 0. |
||||
*/ |
||||
uint8_t l2addr[GNRC_IPV6_NIB_L2ADDR_MAX_LEN]; |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Information flags |
||||
* |
||||
* @see [NC info values](@ref net_gnrc_ipv6_nib_nc_info) |
||||
*/ |
||||
uint16_t info; |
||||
|
||||
/**
|
||||
* @brief NIB entry mode |
||||
* |
||||
* This field identifies which "views" of the NIB the entry belongs to. |
||||
* |
||||
* @see [Mode flags for entries](@ref net_gnrc_ipv6_nib_mode). |
||||
*/ |
||||
uint8_t mode; |
||||
#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) |
||||
/**
|
||||
* @brief Neighbor solicitations sent for probing |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ARSM != 0. |
||||
*/ |
||||
uint8_t ns_sent; |
||||
|
||||
/**
|
||||
* @brief length in bytes of _nib_onl_entry_t::l2addr |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ARSM != 0. |
||||
*/ |
||||
uint8_t l2addr_len; |
||||
#endif |
||||
} _nib_onl_entry_t; |
||||
|
||||
/**
|
||||
* @brief Default route NIB entry |
||||
*/ |
||||
typedef struct { |
||||
_nib_onl_entry_t *next_hop; /**< next hop to destination */ |
||||
uint16_t ltime; /**< lifetime in seconds */ |
||||
} _nib_dr_entry_t; |
||||
|
||||
/**
|
||||
* @brief Off-link NIB entry |
||||
*/ |
||||
typedef struct { |
||||
_nib_onl_entry_t *next_hop; /**< next hop to destination */ |
||||
ipv6_addr_t pfx; /**< prefix to the destination */ |
||||
unsigned pfx_len; /**< prefix-length in bits of
|
||||
* _nib_onl_entry_t::pfx */ |
||||
} _nib_offl_entry_t; |
||||
|
||||
/**
|
||||
* @brief Interface specific information for Neighbor Discovery |
||||
*/ |
||||
typedef struct { |
||||
#if GNRC_IPV6_NIB_CONF_ARSM |
||||
/**
|
||||
* @brief base for random reachable time calculation |
||||
*/ |
||||
uint32_t reach_time_base; |
||||
uint32_t reach_time; /**< reachable time (in ms) */ |
||||
uint32_t retrans_time; /**< retransmission time (in ms) */ |
||||
#endif |
||||
#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) |
||||
/**
|
||||
* @brief timestamp in milliseconds of last unsolicited router |
||||
* advertisement |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER. |
||||
*/ |
||||
uint32_t last_ra; |
||||
#endif |
||||
kernel_pid_t pid; /**< identifier of the interface */ |
||||
#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) |
||||
/**
|
||||
* @brief number of unsolicited router advertisements sent |
||||
* |
||||
* This only counts up to the first @ref NDP_MAX_INIT_RA_NUMOF on interface |
||||
* initialization. The last @ref NDP_MAX_FIN_RA_NUMOF of an advertising |
||||
* interface are counted from UINT8_MAX - @ref NDP_MAX_FIN_RA_NUMOF + 1. |
||||
* |
||||
* @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER. |
||||
*/ |
||||
uint8_t ra_sent; |
||||
#endif |
||||
/**
|
||||
* @brief number of unsolicited router solicitations scheduled |
||||
*/ |
||||
uint8_t rs_sent; |
||||
/**
|
||||
* @brief number of unsolicited neighbor advertisements scheduled |
||||
*/ |
||||
uint8_t na_sent; |
||||
} _nib_iface_t; |
||||
|
||||
/**
|
||||
* @brief Mutex for locking the NIB |
||||
*/ |
||||
extern mutex_t _nib_mutex; |
||||
|
||||
/**
|
||||
* @brief Initializes NIB internally |
||||
*/ |
||||
void _nib_init(void); |
||||
|
||||
/**
|
||||
* @brief Gets interface identifier from a NIB entry |
||||
* |
||||
* @param[in] node A NIB entry. |
||||
* |
||||
* @return The NIB entry's interface identifier. |
||||
*/ |
||||
static inline unsigned _nib_onl_get_if(const _nib_onl_entry_t *node) |
||||
{ |
||||
return (node->info & _NIB_IF_MASK) >> _NIB_IF_POS; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Sets interface for a NIB entry |
||||
* |
||||
* @param[in,out] node A NIB entry. |
||||
* @param[in] iface An interface identifier. |
||||
*/ |
||||
static inline void _nib_onl_set_if(_nib_onl_entry_t *node, unsigned iface) |
||||
{ |
||||
assert(iface <= _NIB_IF_MAX); |
||||
node->info &= ~(_NIB_IF_MASK); |
||||
node->info |= ((iface << _NIB_IF_POS) & _NIB_IF_MASK); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Creates or gets an existing on-link entry by address |
||||
* |
||||
* @pre `(addr != NULL)`. |
||||
* |
||||
* @param[in] addr An IPv6 address. May not be NULL. |
||||
* *May also be a global address!* |
||||
* @param[in] iface The interface to the node. |
||||
* |
||||
* @return A new or existing on-link entry with _nib_onl_entry_t::ipv6 set to |
||||
* @p addr. |
||||
* @return NULL, if no space is left. |
||||
*/ |
||||
_nib_onl_entry_t *_nib_onl_alloc(const ipv6_addr_t *addr, unsigned iface); |
||||
|
||||
/**
|
||||
* @brief Clears out a NIB entry (on-link version) |
||||
* |
||||
* @param[in,out] node An entry. |
||||
* |
||||
* @return true, if entry was cleared. |
||||
* @return false, if entry was not cleared. |
||||
*/ |
||||
static inline bool _nib_onl_clear(_nib_onl_entry_t *node) |
||||
{ |
||||
if (node->mode == _EMPTY) { |
||||
memset(node, 0, sizeof(_nib_onl_entry_t)); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Iterates over on-link entries |
||||
* |
||||
* @param[in] last Last entry (NULL to start). |
||||
* |
||||
* @return entry after @p last. |
||||
*/ |
||||
_nib_onl_entry_t *_nib_onl_iter(const _nib_onl_entry_t *last); |
||||
|
||||
/**
|
||||
* @brief Gets a node by IPv6 address and interface |
||||
* |
||||
* @pre `(addr != NULL)` |
||||
* |
||||
* @param[in] addr The address of a node. May not be NULL. |
||||
* @param[in] iface The interface to the node. May be 0 for any interface. |
||||
* |
||||
* @return The NIB entry for node with @p addr and @p iface on success. |
||||
* @return NULL, if there is no such entry. |
||||
*/ |
||||
_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 |
||||
* |
||||
* @pre `(addr != NULL)` |
||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) != |
||||
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY)` |
||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) != |
||||
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE)` |
||||
* @pre `((cstate & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK) != |
||||
* GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE)` |
||||
* |
||||
* @param[in] addr The address of a node. May not be NULL. |
||||
* @param[in] iface The interface to the node. |
||||
* @param[in] cstate Creation state. State of the entry *if* the entry is |
||||
* newly created. |
||||
* |
||||
* @return The NIB entry for the new neighbor cache entry on success. |
||||
* @return NULL, if there is no space left. |
||||
*/ |
||||
_nib_onl_entry_t *_nib_nc_add(const ipv6_addr_t *addr, unsigned iface, |
||||
uint16_t cstate); |
||||
|
||||
/**
|
||||
* @brief Removes a node from the neighbor cache |
||||
* |
||||
* @param[in,out] node A node. |
||||
*/ |
||||
void _nib_nc_remove(_nib_onl_entry_t *node); |
||||
|
||||
/**
|
||||
* @brief Sets a NUD-managed neighbor cache entry to reachable and sets the |
||||
* respective event in @ref _nib_evtimer "event timer" |
||||
* (@ref GNRC_IPV6_NIB_MSG_NUD_SET_STALE) |
||||
* |
||||
* @param[in,out] node A node. |
||||
*/ |
||||
void _nib_nc_set_reachable(_nib_onl_entry_t *node); |
||||
|
||||
/**
|
||||
* @brief Creates or gets an existing node from the DAD table by address |
||||
* |
||||
* @pre `addr != NULL` |
||||
* |
||||
* @param[in] addr The address of a node. May not be NULL. |
||||
* |
||||
* @return The NIB entry for the new DAD table entry on success. |
||||
* @return NULL, if there is no space left. |
||||
*/ |
||||
static inline _nib_onl_entry_t *_nib_dad_add(const ipv6_addr_t *addr) |
||||
{ |
||||
_nib_onl_entry_t *node = _nib_onl_alloc(addr, 0); |
||||
|
||||
if (node != NULL) { |
||||
node->mode |= (_DAD); |
||||
} |
||||
return node; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Removes a node from the DAD table |
||||
* |
||||
* @param[in] node A node. |
||||
*/ |
||||
static inline void _nib_dad_remove(_nib_onl_entry_t *node) |
||||
{ |
||||
node->mode &= ~(_DAD); |
||||
_nib_onl_clear(node); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Creates or gets an existing default router list entry by address |
||||
* |
||||
* @pre `(router_addr != NULL)` |
||||
* |
||||
* @param[in] addr An IPv6 address. May not be NULL. |
||||
* *May also be a global address!* |
||||
* @param[in] iface The interface to the router. |
||||
* |
||||
* @return A new or existing default router entry with _nib_onl_entry_t::ipv6 |
||||
* of _nib_dr_entry_t::next_hop set to @p router_addr. |
||||
* @return NULL, if no space is left. |
||||
*/ |
||||
_nib_dr_entry_t *_nib_drl_add(const ipv6_addr_t *router_addr, unsigned iface); |
||||
|
||||
/**
|
||||
* @brief Removes a default router list entry |
||||
* |
||||
* @param[in,out] nib_dr An entry. |
||||
* |
||||
* Corresponding on-link entry is removed, too. |
||||
*/ |
||||
void _nib_drl_remove(_nib_dr_entry_t *nib_dr); |
||||
|
||||
/**
|
||||
* @brief Iterates over default router list |
||||
* |
||||
* @param[in] last Last entry (NULL to start). |
||||
* |
||||
* @return entry after @p last. |
||||
*/ |
||||
_nib_dr_entry_t *_nib_drl_iter(const _nib_dr_entry_t *last); |
||||
|
||||
/**
|
||||
* @brief Gets a default router by IPv6 address and interface |
||||
* |
||||
* @pre `(router_addr != NULL)` |
||||
* |
||||
* @param[in] router_addr The address of a default router. May not be NULL. |
||||
* @param[in] iface The interface to the node. May be 0 for any |
||||
* interface. |
||||
* |
||||
* @return The NIB entry for node with @p router_addr and @p iface onsuccess. |
||||
* @return NULL, if there is no such entry. |
||||
*/ |
||||
_nib_dr_entry_t *_nib_drl_get(const ipv6_addr_t *router_addr, unsigned iface); |
||||
|
||||
/**
|
||||
* @brief Gets *the* default router |
||||
* |
||||
* @see [RFC 4861, section 6.3.6](https://tools.ietf.org/html/rfc4861#section-6.3.6)
|
||||
* |
||||
* @return The current default router, on success. |
||||
* @return NULL, if there is no default router in the list. |
||||
*/ |
||||
_nib_dr_entry_t *_nib_drl_get_dr(void); |
||||
|
||||
/**
|
||||
* @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)` |
||||
* |
||||
* @param[in] next_hop An IPv6 address to next hop. May not be NULL. |
||||
* *May also be a global address!* |
||||
* @param[in] iface The interface to @p next_hop. |
||||
* @param[in] pfx The IPv6 prefix or address of the destination. |
||||
* May not be NULL or unspecified address. Use |
||||
* @ref _nib_drl_add() for default route destinations. |
||||
* @param[in] pfx_len The length in bits of @p pfx in bits. |
||||
* |
||||
* @return A new or existing off-link entry with _nib_dr_entry_t::pfx set to |
||||
* @p pfx. |
||||
* @return NULL, if no space is left. |
||||
*/ |
||||
_nib_offl_entry_t *_nib_dst_alloc(const ipv6_addr_t *next_hop, unsigned iface, |
||||
const ipv6_addr_t *pfx, unsigned pfx_len); |
||||
|
||||
/**
|
||||
* @brief Clears out a NIB entry (off-link version) |
||||
* |
||||
* @param[in,out] dst An entry. |
||||
*/ |
||||
void _nib_dst_clear(_nib_offl_entry_t *dst); |
||||
|
||||
/**
|
||||
* @brief Iterates over off-link entries |
||||
* |
||||
* @param[in] last Last entry (NULL to start). |
||||
* |
||||
* @return entry after @p last. |
||||
*/ |
||||
_nib_offl_entry_t *_nib_dst_iter(const _nib_offl_entry_t *last); |
||||
|
||||
/**
|
||||
* @brief Helper function for view-level add-functions below |
||||
* |
||||
* @pre `(next_hop != NULL)` |
||||
* @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)` |
||||
* |
||||
* @param[in] next_hop Next hop to the destination. May not be NULL. |
||||
* *May also be a global address!* |
||||
* @param[in] iface The interface to the destination. |
||||
* @param[in] pfx The IPv6 prefix or address of the destination. |
||||
* May not be NULL or unspecified address. Use |
||||
* @ref _nib_drl_add() for default route destinations. |
||||
* @param[in] pfx_len The length in bits of @p pfx in bits. |
||||
* @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 |
||||
* @p pfx. |
||||
* @return NULL, if no space is left. |
||||
*/ |
||||
static inline _nib_offl_entry_t *_nib_dst_add(const ipv6_addr_t *next_hop, |
||||
unsigned iface, |
||||
const ipv6_addr_t *pfx, |
||||
unsigned pfx_len, uint8_t mode) |
||||
{ |
||||
_nib_offl_entry_t *nib_offl = _nib_dst_alloc(next_hop, iface, pfx, pfx_len); |
||||
|
||||
if (nib_offl != NULL) { |
||||
nib_offl->next_hop->mode |= (mode); |
||||
} |
||||
return nib_offl; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Helper function for the view-level remove-functions below |
||||
* |
||||
* @param[in,out] nib_offl An entry. |
||||
*/ |
||||
static inline void _nib_dst_remove(_nib_offl_entry_t *nib_offl, uint8_t mode) |
||||
{ |
||||
_nib_onl_entry_t *node = nib_offl->next_hop; |
||||
|