Merge pull request #8823 from miri64/gnrc_ipv6_nib/feat/slaac
gnrc_ipv6_nib: add full RFC4862 DAD support
This commit is contained in:
commit
579d9d78d4
@ -202,6 +202,26 @@ extern "C" {
|
|||||||
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ROUTER != 0
|
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_ROUTER != 0
|
||||||
*/
|
*/
|
||||||
#define GNRC_IPV6_NIB_ROUTE_TIMEOUT (0x4fd0U)
|
#define GNRC_IPV6_NIB_ROUTE_TIMEOUT (0x4fd0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform DAD event.
|
||||||
|
*
|
||||||
|
* This message type is for performing DAD for a given address. The expected
|
||||||
|
* message context is a TENTATIVE IPv6 address.
|
||||||
|
*
|
||||||
|
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_SLAAC != 0
|
||||||
|
*/
|
||||||
|
#define GNRC_IPV6_NIB_DAD (0x4fd1U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate a tentative address event.
|
||||||
|
*
|
||||||
|
* Moves a TENTATIVE address to VALID state. The expected message context is a
|
||||||
|
* TENTATIVE IPv6 address.
|
||||||
|
*
|
||||||
|
* @note Only handled with @ref GNRC_IPV6_NIB_CONF_SLAAC != 0
|
||||||
|
*/
|
||||||
|
#define GNRC_IPV6_NIB_VALID_ADDR (0x4fd2U)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -151,13 +151,14 @@ typedef struct {
|
|||||||
* and @ref net_gnrc_ipv6_nib "NIB"
|
* and @ref net_gnrc_ipv6_nib "NIB"
|
||||||
*/
|
*/
|
||||||
evtimer_msg_event_t search_rtr;
|
evtimer_msg_event_t search_rtr;
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN || DOXYGEN
|
#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC || DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @brief Timers for address re-registration
|
* @brief Timers for address re-registration
|
||||||
*
|
*
|
||||||
* @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and
|
* @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and
|
||||||
* @ref net_gnrc_ipv6_nib "NIB" and if
|
* @ref net_gnrc_ipv6_nib "NIB" and if
|
||||||
* @ref GNRC_IPV6_NIB_CONF_6LN != 0
|
* @ref GNRC_IPV6_NIB_CONF_6LN != 0 or
|
||||||
|
* @ref GNRC_IPV6_NIB_CONF_SLAAC != 0
|
||||||
* @note Might also be usable in the later default SLAAC implementation
|
* @note Might also be usable in the later default SLAAC implementation
|
||||||
* for NS retransmission timers.
|
* for NS retransmission timers.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "net/gnrc.h"
|
#include "net/gnrc.h"
|
||||||
#ifdef MODULE_GNRC_IPV6_NIB
|
#ifdef MODULE_GNRC_IPV6_NIB
|
||||||
#include "net/gnrc/ipv6/nib.h"
|
#include "net/gnrc/ipv6/nib.h"
|
||||||
|
#include "net/gnrc/ipv6.h"
|
||||||
#endif /* MODULE_GNRC_IPV6_NIB */
|
#endif /* MODULE_GNRC_IPV6_NIB */
|
||||||
#ifdef MODULE_NETSTATS_IPV6
|
#ifdef MODULE_NETSTATS_IPV6
|
||||||
#include "net/netstats.h"
|
#include "net/netstats.h"
|
||||||
@ -589,8 +590,13 @@ int gnrc_netif_ipv6_addr_add_internal(gnrc_netif_t *netif,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if GNRC_IPV6_NIB_CONF_SLAAC
|
#if GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
else {
|
else if (!gnrc_netif_is_6ln(netif)) {
|
||||||
/* TODO: send out NS to solicited nodes for DAD probing */
|
/* cast to remove const qualifier (will still be used NIB internally as
|
||||||
|
* const) */
|
||||||
|
msg_t msg = { .type = GNRC_IPV6_NIB_DAD,
|
||||||
|
.content = { .ptr = &netif->ipv6.addrs[idx] } };
|
||||||
|
|
||||||
|
msg_send(&msg, gnrc_ipv6_pid);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
@ -961,8 +967,7 @@ static int _create_candidate_set(const gnrc_netif_t *netif,
|
|||||||
* be included in a candidate set."
|
* be included in a candidate set."
|
||||||
*/
|
*/
|
||||||
if ((netif->ipv6.addrs_flags[i] == 0) ||
|
if ((netif->ipv6.addrs_flags[i] == 0) ||
|
||||||
(gnrc_netif_ipv6_addr_get_state(netif, i) ==
|
gnrc_netif_ipv6_addr_dad_trans(netif, i)) {
|
||||||
GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Check if we only want link local addresses */
|
/* Check if we only want link local addresses */
|
||||||
|
|||||||
@ -297,7 +297,8 @@ static void *_event_loop(void *args)
|
|||||||
case GNRC_IPV6_NIB_RTR_TIMEOUT:
|
case GNRC_IPV6_NIB_RTR_TIMEOUT:
|
||||||
case GNRC_IPV6_NIB_RECALC_REACH_TIME:
|
case GNRC_IPV6_NIB_RECALC_REACH_TIME:
|
||||||
case GNRC_IPV6_NIB_REREG_ADDRESS:
|
case GNRC_IPV6_NIB_REREG_ADDRESS:
|
||||||
case GNRC_IPV6_NIB_ROUTE_TIMEOUT:
|
case GNRC_IPV6_NIB_DAD:
|
||||||
|
case GNRC_IPV6_NIB_VALID_ADDR:
|
||||||
DEBUG("ipv6: NIB timer event received\n");
|
DEBUG("ipv6: NIB timer event received\n");
|
||||||
gnrc_ipv6_nib_handle_timer_event(msg.content.ptr, msg.type);
|
gnrc_ipv6_nib_handle_timer_event(msg.content.ptr, msg.type);
|
||||||
break;
|
break;
|
||||||
|
|||||||
205
sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c
Normal file
205
sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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 "luid.h"
|
||||||
|
#include "net/gnrc/netif/internal.h"
|
||||||
|
|
||||||
|
#include "_nib-6ln.h"
|
||||||
|
#include "_nib-arsm.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
|
void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx,
|
||||||
|
uint8_t pfx_len)
|
||||||
|
{
|
||||||
|
ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED;
|
||||||
|
int idx;
|
||||||
|
uint8_t flags = GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE;
|
||||||
|
|
||||||
|
DEBUG("nib: add address based on %s/%u automatically to interface %u\n",
|
||||||
|
ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)),
|
||||||
|
pfx_len, netif->pid);
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN
|
||||||
|
bool new_address = false;
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]);
|
||||||
|
ipv6_addr_init_prefix(&addr, pfx, pfx_len);
|
||||||
|
if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) {
|
||||||
|
if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len,
|
||||||
|
flags)) < 0) {
|
||||||
|
DEBUG("nib: Can't add link-local address on interface %u\n",
|
||||||
|
netif->pid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN
|
||||||
|
new_address = true;
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN
|
||||||
|
/* mark link-local addresses as valid on 6LN */
|
||||||
|
if (gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)) {
|
||||||
|
/* don't do this beforehand or risk a deadlock:
|
||||||
|
* - gnrc_netif_ipv6_addr_add_internal() adds VALID (i.e. manually configured
|
||||||
|
* addresses to the prefix list locking the NIB's mutex which is already
|
||||||
|
* locked here) */
|
||||||
|
netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
|
||||||
|
netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID;
|
||||||
|
}
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN
|
||||||
|
if (new_address && gnrc_netif_is_6ln(netif) &&
|
||||||
|
!gnrc_netif_is_6lbr(netif)) {
|
||||||
|
_handle_rereg_address(&netif->ipv6.addrs[idx]);
|
||||||
|
}
|
||||||
|
#else /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
(void)idx;
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
}
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
|
static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif)
|
||||||
|
{
|
||||||
|
uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN];
|
||||||
|
uint16_t hwaddr_len;
|
||||||
|
|
||||||
|
if (gnrc_netapi_get(netif->pid, NETOPT_SRC_LEN, 0, &hwaddr_len,
|
||||||
|
sizeof(hwaddr_len)) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
luid_get(hwaddr, hwaddr_len);
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN
|
||||||
|
if (hwaddr_len == IEEE802154_LONG_ADDRESS_LEN) {
|
||||||
|
if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS_LONG, 0, hwaddr,
|
||||||
|
hwaddr_len) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS, 0, hwaddr,
|
||||||
|
hwaddr_len) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _try_addr_reconfiguration(gnrc_netif_t *netif)
|
||||||
|
{
|
||||||
|
eui64_t orig_iid;
|
||||||
|
bool remove_old = false, hwaddr_reconf;
|
||||||
|
|
||||||
|
if (gnrc_netif_ipv6_get_iid(netif, &orig_iid) == 0) {
|
||||||
|
remove_old = true;
|
||||||
|
}
|
||||||
|
/* seize netif to netif thread since _try_l2addr_reconfiguration uses
|
||||||
|
* gnrc_netapi_get()/gnrc_netapi_set(). Since these are synchronous this is
|
||||||
|
* safe */
|
||||||
|
gnrc_netif_release(netif);
|
||||||
|
/* reacquire netif for IPv6 address reconfiguraton */
|
||||||
|
hwaddr_reconf = _try_l2addr_reconfiguration(netif);
|
||||||
|
gnrc_netif_acquire(netif);
|
||||||
|
if (hwaddr_reconf) {
|
||||||
|
if (remove_old) {
|
||||||
|
for (unsigned i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) {
|
||||||
|
ipv6_addr_t *addr = &netif->ipv6.addrs[i];
|
||||||
|
if (addr->u64[1].u64 == orig_iid.uint64.u64) {
|
||||||
|
gnrc_netif_ipv6_addr_remove_internal(netif, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG("nib: Changed hardware address, due to DAD\n");
|
||||||
|
_auto_configure_addr(netif, &ipv6_addr_link_local_prefix, 64U);
|
||||||
|
}
|
||||||
|
return hwaddr_reconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr)
|
||||||
|
{
|
||||||
|
DEBUG("nib: other node has TENTATIVE address %s assigned "
|
||||||
|
"=> removing that address\n",
|
||||||
|
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
|
||||||
|
gnrc_netif_ipv6_addr_remove_internal(netif, addr);
|
||||||
|
|
||||||
|
if (!ipv6_addr_is_link_local(addr) ||
|
||||||
|
!_try_addr_reconfiguration(netif)) {
|
||||||
|
/* Cannot use target address as personal address and can
|
||||||
|
* not change hardware address to retry SLAAC => use purely
|
||||||
|
* DHCPv6 instead */
|
||||||
|
/* TODO: implement IA_NA for DHCPv6 */
|
||||||
|
/* then => tgt_netif->aac_mode = GNRC_NETIF_AAC_DHCP; */
|
||||||
|
DEBUG("nib: would set interface %i to DHCPv6, "
|
||||||
|
"but is not implemented yet", netif->pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_netif_state(gnrc_netif_t **netif, const ipv6_addr_t *addr)
|
||||||
|
{
|
||||||
|
*netif = gnrc_netif_get_by_ipv6_addr(addr);
|
||||||
|
if (*netif != NULL) {
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
gnrc_netif_acquire(*netif);
|
||||||
|
idx = gnrc_netif_ipv6_addr_idx(*netif, addr);
|
||||||
|
return ((idx >= 0) && gnrc_netif_ipv6_addr_dad_trans(*netif, idx)) ?
|
||||||
|
idx : -1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handle_dad(const ipv6_addr_t *addr)
|
||||||
|
{
|
||||||
|
ipv6_addr_t sol_nodes;
|
||||||
|
gnrc_netif_t *netif = NULL;
|
||||||
|
int idx = _get_netif_state(&netif, addr);
|
||||||
|
if (idx >= 0) {
|
||||||
|
ipv6_addr_set_solicited_nodes(&sol_nodes, addr);
|
||||||
|
_snd_ns(addr, netif, &ipv6_addr_unspecified, &sol_nodes);
|
||||||
|
_evtimer_add((void *)addr, GNRC_IPV6_NIB_VALID_ADDR,
|
||||||
|
&netif->ipv6.addrs_timers[idx],
|
||||||
|
netif->ipv6.retrans_time);
|
||||||
|
}
|
||||||
|
if (netif != NULL) {
|
||||||
|
/* was acquired in `_get_netif_state()` */
|
||||||
|
gnrc_netif_release(netif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handle_valid_addr(const ipv6_addr_t *addr)
|
||||||
|
{
|
||||||
|
gnrc_netif_t *netif = NULL;
|
||||||
|
int idx = _get_netif_state(&netif, addr);
|
||||||
|
|
||||||
|
if (idx >= 0) {
|
||||||
|
netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
|
||||||
|
netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID;
|
||||||
|
}
|
||||||
|
if (netif != NULL) {
|
||||||
|
/* was acquired in `_get_netif_state()` */
|
||||||
|
gnrc_netif_release(netif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
typedef int dont_be_pedantic;
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
83
sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h
Normal file
83
sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup net_gnrc_ipv6_nib
|
||||||
|
* @brief
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Definions related to SLAAC functionality of the NIB
|
||||||
|
* @see @ref GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef PRIV_NIB_SLAAC_H
|
||||||
|
#define PRIV_NIB_SLAAC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "net/gnrc/ipv6/nib/conf.h"
|
||||||
|
#include "net/gnrc/netif.h"
|
||||||
|
#include "net/ipv6/addr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Auto-configures an address from a given prefix
|
||||||
|
*
|
||||||
|
* @param[in] netif The network interface the address should be added to.
|
||||||
|
* @param[in] pfx The prefix for the address.
|
||||||
|
* @param[in] pfx_len Length of @p pfx in bits.
|
||||||
|
*/
|
||||||
|
void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx,
|
||||||
|
uint8_t pfx_len);
|
||||||
|
#else /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
#define _auto_configure_addr(netif, pfx, pfx_len) \
|
||||||
|
(void)netif; (void)pfx; (void)pfx_len;
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
#if GNRC_IPV6_NIB_CONF_SLAAC || defined(DOXYGE)
|
||||||
|
/**
|
||||||
|
* @brief Removes a tentative address from the interface and tries to
|
||||||
|
* reconfigure a new address
|
||||||
|
*
|
||||||
|
* @param[in] netif The network interface the address is to be removed from.
|
||||||
|
* @param[in] addr The address to remove.
|
||||||
|
*/
|
||||||
|
void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle @ref GNRC_IPV6_NIB_DAD event
|
||||||
|
*
|
||||||
|
* @param[in] addr A TENTATIVE address.
|
||||||
|
*/
|
||||||
|
void _handle_dad(const ipv6_addr_t *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle @ref GNRC_IPV6_NIB_VALID_ADDR event
|
||||||
|
*
|
||||||
|
* @param[in] addr A TENTATIVE address.
|
||||||
|
*/
|
||||||
|
void _handle_valid_addr(const ipv6_addr_t *addr);
|
||||||
|
#else /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
#define _remove_tentative_addr(netif, addr) \
|
||||||
|
(void)netif; (void)addr
|
||||||
|
#define _handle_dad(addr) (void)addr
|
||||||
|
#define _handle_valid_addr(addr) (void)addr
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PRIV_NIB_SLAAC_H */
|
||||||
|
/** @} */
|
||||||
@ -32,6 +32,7 @@
|
|||||||
#include "_nib-router.h"
|
#include "_nib-router.h"
|
||||||
#include "_nib-6ln.h"
|
#include "_nib-6ln.h"
|
||||||
#include "_nib-6lr.h"
|
#include "_nib-6lr.h"
|
||||||
|
#include "_nib-slaac.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -67,14 +68,6 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif,
|
|||||||
static void _handle_pfx_timeout(_nib_offl_entry_t *pfx);
|
static void _handle_pfx_timeout(_nib_offl_entry_t *pfx);
|
||||||
static void _handle_rtr_timeout(_nib_dr_entry_t *router);
|
static void _handle_rtr_timeout(_nib_dr_entry_t *router);
|
||||||
static void _handle_snd_na(gnrc_pktsnip_t *pkt);
|
static void _handle_snd_na(gnrc_pktsnip_t *pkt);
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC
|
|
||||||
static void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx,
|
|
||||||
uint8_t pfx_len);
|
|
||||||
#else /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
|
||||||
#define _auto_configure_addr(netif, pfx, pfx_len) (void)netif; \
|
|
||||||
(void)pfx; \
|
|
||||||
(void)pfx_len
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
|
||||||
/* needs to be exported for 6LN's ARO handling */
|
/* needs to be exported for 6LN's ARO handling */
|
||||||
void _handle_search_rtr(gnrc_netif_t *netif);
|
void _handle_search_rtr(gnrc_netif_t *netif);
|
||||||
/** @} */
|
/** @} */
|
||||||
@ -356,6 +349,12 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type)
|
|||||||
_handle_rereg_address(ctx);
|
_handle_rereg_address(ctx);
|
||||||
break;
|
break;
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
||||||
|
case GNRC_IPV6_NIB_DAD:
|
||||||
|
_handle_dad(ctx);
|
||||||
|
break;
|
||||||
|
case GNRC_IPV6_NIB_VALID_ADDR:
|
||||||
|
_handle_valid_addr(ctx);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -838,9 +837,30 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
|
|||||||
DEBUG(" - Destination address: %s\n",
|
DEBUG(" - Destination address: %s\n",
|
||||||
ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
|
ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
|
||||||
#if GNRC_IPV6_NIB_CONF_SLAAC
|
#if GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
/* TODO SLAAC behavior */
|
gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_sol->tgt);
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
|
||||||
|
if (tgt_netif != NULL) {
|
||||||
|
int idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt);
|
||||||
|
|
||||||
|
if (gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) {
|
||||||
if (!ipv6_addr_is_unspecified(&ipv6->src)) {
|
if (!ipv6_addr_is_unspecified(&ipv6->src)) {
|
||||||
|
/* (see https://tools.ietf.org/html/rfc4862#section-5.4.3) */
|
||||||
|
DEBUG("nib: Neighbor is performing AR, but target address is "
|
||||||
|
"still TENTATIVE for us => Ignoring NS\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* cancel validation timer */
|
||||||
|
evtimer_del(&_nib_evtimer,
|
||||||
|
&tgt_netif->ipv6.addrs_timers[idx].event);
|
||||||
|
_remove_tentative_addr(tgt_netif, &nbr_sol->tgt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
|
if (ipv6_addr_is_unspecified(&ipv6->src)) {
|
||||||
|
gnrc_ndp_nbr_adv_send(&nbr_sol->tgt, netif, &ipv6->src, false, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
gnrc_pktsnip_t *reply_aro = NULL;
|
gnrc_pktsnip_t *reply_aro = NULL;
|
||||||
#if GNRC_IPV6_NIB_CONF_6LR
|
#if GNRC_IPV6_NIB_CONF_6LR
|
||||||
ndp_opt_t *sl2ao = NULL;
|
ndp_opt_t *sl2ao = NULL;
|
||||||
@ -948,7 +968,21 @@ static void _handle_nbr_adv(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
|
|||||||
(nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) ? 'S' : '-',
|
(nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) ? 'S' : '-',
|
||||||
(nbr_adv->flags & NDP_NBR_ADV_FLAGS_O) ? 'O' : '-');
|
(nbr_adv->flags & NDP_NBR_ADV_FLAGS_O) ? 'O' : '-');
|
||||||
#if GNRC_IPV6_NIB_CONF_SLAAC
|
#if GNRC_IPV6_NIB_CONF_SLAAC
|
||||||
/* TODO SLAAC behavior */
|
gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_adv->tgt);
|
||||||
|
|
||||||
|
if (tgt_netif != NULL) {
|
||||||
|
int idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_adv->tgt);
|
||||||
|
|
||||||
|
if (gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) {
|
||||||
|
/* cancel validation timer */
|
||||||
|
evtimer_del(&_nib_evtimer,
|
||||||
|
&tgt_netif->ipv6.addrs_timers[idx].event);
|
||||||
|
_remove_tentative_addr(tgt_netif, &nbr_adv->tgt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* else case beyond scope of RFC4862:
|
||||||
|
* https://tools.ietf.org/html/rfc4862#section-5.4.4 */
|
||||||
|
}
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
||||||
if (((nce = _nib_onl_get(&nbr_adv->tgt, netif->pid)) != NULL) &&
|
if (((nce = _nib_onl_get(&nbr_adv->tgt, netif->pid)) != NULL) &&
|
||||||
(nce->mode & _NC)) {
|
(nce->mode & _NC)) {
|
||||||
@ -1246,11 +1280,9 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
|||||||
DEBUG(" - Preferred lifetime: %" PRIu32 "\n",
|
DEBUG(" - Preferred lifetime: %" PRIu32 "\n",
|
||||||
byteorder_ntohl(pio->pref_ltime));
|
byteorder_ntohl(pio->pref_ltime));
|
||||||
|
|
||||||
#if GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN
|
|
||||||
if (pio->flags & NDP_OPT_PI_FLAGS_A) {
|
if (pio->flags & NDP_OPT_PI_FLAGS_A) {
|
||||||
_auto_configure_addr(netif, &pio->prefix, pio->prefix_len);
|
_auto_configure_addr(netif, &pio->prefix, pio->prefix_len);
|
||||||
}
|
}
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
if ((pio->flags & NDP_OPT_PI_FLAGS_L) || gnrc_netif_is_6lr(netif)) {
|
if ((pio->flags & NDP_OPT_PI_FLAGS_L) || gnrc_netif_is_6lr(netif)) {
|
||||||
_nib_offl_entry_t *pfx;
|
_nib_offl_entry_t *pfx;
|
||||||
|
|
||||||
@ -1293,60 +1325,4 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6,
|
|||||||
return UINT32_MAX;
|
return UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC
|
|
||||||
static void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx,
|
|
||||||
uint8_t pfx_len)
|
|
||||||
{
|
|
||||||
ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED;
|
|
||||||
int idx;
|
|
||||||
uint8_t flags = GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE;
|
|
||||||
|
|
||||||
DEBUG("nib: add address based on %s/%u automatically to interface %u\n",
|
|
||||||
ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)),
|
|
||||||
pfx_len, netif->pid);
|
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN
|
|
||||||
bool new_address = false;
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]);
|
|
||||||
ipv6_addr_init_prefix(&addr, pfx, pfx_len);
|
|
||||||
if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) {
|
|
||||||
if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len,
|
|
||||||
flags)) < 0) {
|
|
||||||
DEBUG("nib: Can't add link-local address on interface %u\n",
|
|
||||||
netif->pid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN
|
|
||||||
new_address = true;
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN
|
|
||||||
/* mark link-local addresses as valid on 6LN */
|
|
||||||
if (gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)) {
|
|
||||||
/* don't do this beforehand or risk a deadlock:
|
|
||||||
* * gnrc_netif_ipv6_addr_add_internal() adds VALID (i.e. manually configured
|
|
||||||
* addresses to the prefix list locking the NIB's mutex which is already
|
|
||||||
* locked here) */
|
|
||||||
netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
|
|
||||||
netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID;
|
|
||||||
}
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
/* TODO: make this line conditional on 6LN when there is a SLAAC
|
|
||||||
* implementation */
|
|
||||||
#if GNRC_IPV6_NIB_CONF_6LN
|
|
||||||
if (new_address && gnrc_netif_is_6ln(netif) &&
|
|
||||||
!gnrc_netif_is_6lbr(netif)) {
|
|
||||||
_handle_rereg_address(&netif->ipv6.addrs[idx]);
|
|
||||||
}
|
|
||||||
#else /* GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
(void)idx;
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN */
|
|
||||||
#if GNRC_IPV6_NIB_CONF_SLAAC
|
|
||||||
/* TODO send NS to solicited nodes and wait netif->ipv6.retrans_time to
|
|
||||||
* confirm uniqueness of the link-local address */
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_SLAAC */
|
|
||||||
}
|
|
||||||
#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */
|
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@ -475,6 +475,11 @@ void gnrc_ndp_rtr_adv_send(gnrc_netif_t *netif, const ipv6_addr_t *src,
|
|||||||
/* get address from source selection algorithm.
|
/* get address from source selection algorithm.
|
||||||
* Only link local addresses may be used (RFC 4861 section 4.1) */
|
* Only link local addresses may be used (RFC 4861 section 4.1) */
|
||||||
src = gnrc_netif_ipv6_addr_best_src(netif, dst, true);
|
src = gnrc_netif_ipv6_addr_best_src(netif, dst, true);
|
||||||
|
|
||||||
|
if (src == NULL) {
|
||||||
|
DEBUG("ndp rtr: no VALID source address found for RA\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* add SL2A for source address */
|
/* add SL2A for source address */
|
||||||
if (src != NULL) {
|
if (src != NULL) {
|
||||||
|
|||||||
@ -449,8 +449,67 @@ static void test_handle_pkt__nbr_sol__invalid_dst(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_pkt_is_nbr_adv(gnrc_pktsnip_t *pkt, const ipv6_addr_t *dst,
|
||||||
|
const ipv6_addr_t *tgt,
|
||||||
|
const uint8_t *tgt_l2addr,
|
||||||
|
size_t tgt_l2addr_len)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *options;
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
ndp_nbr_adv_t *nbr_adv;
|
||||||
|
|
||||||
|
/* first snip is a netif header to _mock_netif */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_NETIF, pkt->type);
|
||||||
|
TEST_ASSERT(sizeof(gnrc_netif_hdr_t) <= pkt->size);
|
||||||
|
netif_hdr = pkt->data;
|
||||||
|
TEST_ASSERT_EQUAL_INT(_mock_netif->pid, netif_hdr->if_pid);
|
||||||
|
/* second snip is an IPv6 header to dst */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt->next);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_IPV6, pkt->next->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(sizeof(ipv6_hdr_t), pkt->next->size);
|
||||||
|
ipv6_hdr = pkt->next->data;
|
||||||
|
if ((tgt_l2addr != NULL) && (tgt_l2addr_len > 0)) {
|
||||||
|
TEST_ASSERT(!ipv6_addr_is_multicast(&ipv6_hdr->dst));
|
||||||
|
}
|
||||||
|
TEST_ASSERT_MESSAGE(ipv6_addr_equal(dst, &ipv6_hdr->dst),
|
||||||
|
"dst != ipv6_hdr->dst");
|
||||||
|
TEST_ASSERT_EQUAL_INT(255, ipv6_hdr->hl);
|
||||||
|
/* third snip is a valid solicited neighbor advertisement to tgt */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt->next->next);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_ICMPV6, pkt->next->next->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(sizeof(ndp_nbr_adv_t), pkt->next->next->size);
|
||||||
|
nbr_adv = pkt->next->next->data;
|
||||||
|
TEST_ASSERT_EQUAL_INT(ICMPV6_NBR_ADV, nbr_adv->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, nbr_adv->code);
|
||||||
|
TEST_ASSERT(!ipv6_addr_is_multicast(&nbr_adv->tgt));
|
||||||
|
TEST_ASSERT_MESSAGE(ipv6_addr_equal(tgt, &nbr_adv->tgt),
|
||||||
|
"tgt != nbr_adv->tgt");
|
||||||
|
options = pkt->next->next->next;
|
||||||
|
if ((tgt_l2addr != NULL) && (tgt_l2addr_len > 0)) {
|
||||||
|
ndp_opt_t *tl2ao;
|
||||||
|
|
||||||
|
TEST_ASSERT(nbr_adv->flags & NDP_NBR_ADV_FLAGS_S);
|
||||||
|
|
||||||
|
/* fourth snip is a TL2AO for tgt_l2addr */
|
||||||
|
TEST_ASSERT_NOT_NULL(options);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_UNDEF, options->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(ceil8(sizeof(ndp_opt_t) + tgt_l2addr_len),
|
||||||
|
options->size);
|
||||||
|
tl2ao = options->data;
|
||||||
|
TEST_ASSERT_EQUAL_INT(NDP_OPT_TL2A, tl2ao->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, tl2ao->len);
|
||||||
|
TEST_ASSERT_MESSAGE(memcmp(tl2ao + 1, tgt_l2addr, tgt_l2addr_len) == 0,
|
||||||
|
"tl2ao.l2addr != tgt_l2addr");
|
||||||
|
}
|
||||||
|
/* no further options */
|
||||||
|
TEST_ASSERT_NULL(options->next);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_handle_pkt__nbr_sol__invalid_sl2ao(void)
|
static void test_handle_pkt__nbr_sol__invalid_sl2ao(void)
|
||||||
{
|
{
|
||||||
|
msg_t msg;
|
||||||
gnrc_ipv6_nib_nc_t nce;
|
gnrc_ipv6_nib_nc_t nce;
|
||||||
void *state = NULL;
|
void *state = NULL;
|
||||||
size_t icmpv6_len = _set_nbr_sol(&ipv6_addr_unspecified, &_loc_sol_nodes,
|
size_t icmpv6_len = _set_nbr_sol(&ipv6_addr_unspecified, &_loc_sol_nodes,
|
||||||
@ -461,6 +520,15 @@ static void test_handle_pkt__nbr_sol__invalid_sl2ao(void)
|
|||||||
TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce),
|
TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce),
|
||||||
"There is an unexpected neighbor cache entry");
|
"There is an unexpected neighbor cache entry");
|
||||||
/* TODO: check other views as well */
|
/* TODO: check other views as well */
|
||||||
|
|
||||||
|
/* check if SLAAC generated neighbor advertisement */
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, msg_avail());
|
||||||
|
msg_receive(&msg);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETAPI_MSG_TYPE_SND, msg.type);
|
||||||
|
test_pkt_is_nbr_adv(msg.content.ptr, &ipv6_addr_all_nodes_link_local,
|
||||||
|
&_loc_ll, NULL, 0);
|
||||||
|
gnrc_pktbuf_release(msg.content.ptr);
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,56 +547,6 @@ static void test_handle_pkt__nbr_sol__tgt_not_assigned(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
TEST_ASSERT_EQUAL_INT(0, msg_avail());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_pkt_is_nbr_adv(gnrc_pktsnip_t *pkt, const ipv6_addr_t *dst,
|
|
||||||
const ipv6_addr_t *tgt,
|
|
||||||
const uint8_t *tgt_l2addr,
|
|
||||||
size_t tgt_l2addr_len)
|
|
||||||
{
|
|
||||||
gnrc_netif_hdr_t *netif_hdr;
|
|
||||||
ipv6_hdr_t *ipv6_hdr;
|
|
||||||
ndp_nbr_adv_t *nbr_adv;
|
|
||||||
ndp_opt_t *tl2ao;
|
|
||||||
|
|
||||||
/* first snip is a netif header to _mock_netif */
|
|
||||||
TEST_ASSERT_NOT_NULL(pkt);
|
|
||||||
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_NETIF, pkt->type);
|
|
||||||
TEST_ASSERT(sizeof(gnrc_netif_hdr_t) <= pkt->size);
|
|
||||||
netif_hdr = pkt->data;
|
|
||||||
TEST_ASSERT_EQUAL_INT(_mock_netif->pid, netif_hdr->if_pid);
|
|
||||||
/* second snip is an IPv6 header to dst */
|
|
||||||
TEST_ASSERT_NOT_NULL(pkt->next);
|
|
||||||
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_IPV6, pkt->next->type);
|
|
||||||
TEST_ASSERT_EQUAL_INT(sizeof(ipv6_hdr_t), pkt->next->size);
|
|
||||||
ipv6_hdr = pkt->next->data;
|
|
||||||
TEST_ASSERT(!ipv6_addr_is_multicast(&ipv6_hdr->dst));
|
|
||||||
TEST_ASSERT_MESSAGE(ipv6_addr_equal(dst, &ipv6_hdr->dst),
|
|
||||||
"dst != ipv6_hdr->dst");
|
|
||||||
TEST_ASSERT_EQUAL_INT(255, ipv6_hdr->hl);
|
|
||||||
/* third snip is a valid solicited neighbor advertisement to tgt */
|
|
||||||
TEST_ASSERT_NOT_NULL(pkt->next->next);
|
|
||||||
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_ICMPV6, pkt->next->next->type);
|
|
||||||
TEST_ASSERT_EQUAL_INT(sizeof(ndp_nbr_adv_t), pkt->next->next->size);
|
|
||||||
nbr_adv = pkt->next->next->data;
|
|
||||||
TEST_ASSERT_EQUAL_INT(ICMPV6_NBR_ADV, nbr_adv->type);
|
|
||||||
TEST_ASSERT_EQUAL_INT(0, nbr_adv->code);
|
|
||||||
TEST_ASSERT(!ipv6_addr_is_multicast(&nbr_adv->tgt));
|
|
||||||
TEST_ASSERT_MESSAGE(ipv6_addr_equal(tgt, &nbr_adv->tgt),
|
|
||||||
"tgt != nbr_adv->tgt");
|
|
||||||
TEST_ASSERT(nbr_adv->flags & NDP_NBR_ADV_FLAGS_S);
|
|
||||||
/* fourth snip is a TL2AO for tgt_l2addr */
|
|
||||||
TEST_ASSERT_NOT_NULL(pkt->next->next->next);
|
|
||||||
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_UNDEF, pkt->next->next->next->type);
|
|
||||||
TEST_ASSERT_EQUAL_INT(ceil8(sizeof(ndp_opt_t) + tgt_l2addr_len),
|
|
||||||
pkt->next->next->next->size);
|
|
||||||
tl2ao = pkt->next->next->next->data;
|
|
||||||
TEST_ASSERT_EQUAL_INT(NDP_OPT_TL2A, tl2ao->type);
|
|
||||||
TEST_ASSERT_EQUAL_INT(1, tl2ao->len);
|
|
||||||
TEST_ASSERT_MESSAGE(memcmp(tl2ao + 1, tgt_l2addr, tgt_l2addr_len) == 0,
|
|
||||||
"tl2ao.l2addr != tgt_l2addr");
|
|
||||||
/* no further options */
|
|
||||||
TEST_ASSERT_NULL(pkt->next->next->next->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_handle_pkt__nbr_sol__ll_src(unsigned exp_nud_state,
|
static void test_handle_pkt__nbr_sol__ll_src(unsigned exp_nud_state,
|
||||||
unsigned exp_ar_state)
|
unsigned exp_ar_state)
|
||||||
{
|
{
|
||||||
@ -1096,9 +1114,50 @@ static void test_handle_pkt__rtr_adv__success(uint8_t rtr_adv_flags,
|
|||||||
state = NULL;
|
state = NULL;
|
||||||
if (pio) {
|
if (pio) {
|
||||||
if (pio_flags & NDP_OPT_PI_FLAGS_A) {
|
if (pio_flags & NDP_OPT_PI_FLAGS_A) {
|
||||||
|
msg_t msg;
|
||||||
|
gnrc_pktsnip_t *pkt;
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
ndp_nbr_adv_t *nbr_sol;
|
||||||
|
|
||||||
TEST_ASSERT_MESSAGE(gnrc_netif_ipv6_addr_idx(_mock_netif,
|
TEST_ASSERT_MESSAGE(gnrc_netif_ipv6_addr_idx(_mock_netif,
|
||||||
&_loc_gb) >= 0,
|
&_loc_gb) >= 0,
|
||||||
"Address was not configured by PIO");
|
"Address was not configured by PIO");
|
||||||
|
|
||||||
|
/* Check if SLAAC generated a neighbor solicitation */
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, msg_avail());
|
||||||
|
msg_receive(&msg);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETAPI_MSG_TYPE_SND, msg.type);
|
||||||
|
pkt = msg.content.ptr;
|
||||||
|
/* first snip is a netif header to _mock_netif */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_NETIF, pkt->type);
|
||||||
|
TEST_ASSERT(sizeof(gnrc_netif_hdr_t) <= pkt->size);
|
||||||
|
netif_hdr = pkt->data;
|
||||||
|
TEST_ASSERT_EQUAL_INT(_mock_netif->pid, netif_hdr->if_pid);
|
||||||
|
/* second snip is an IPv6 header to solicited nodes of _loc_gb */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt->next);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_IPV6, pkt->next->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(sizeof(ipv6_hdr_t), pkt->next->size);
|
||||||
|
ipv6_hdr = pkt->next->data;
|
||||||
|
TEST_ASSERT_MESSAGE(ipv6_addr_equal(&ipv6_hdr->dst,
|
||||||
|
&_loc_sol_nodes),
|
||||||
|
"ipv6_hdr->dst != _loc_sol_nodes");
|
||||||
|
TEST_ASSERT_EQUAL_INT(255, ipv6_hdr->hl);
|
||||||
|
/* third snip is a valid solicited neighbor solicitation to
|
||||||
|
* _loc_gb */
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt->next->next);
|
||||||
|
TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_ICMPV6, pkt->next->next->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(sizeof(ndp_nbr_sol_t), pkt->next->next->size);
|
||||||
|
nbr_sol = pkt->next->next->data;
|
||||||
|
TEST_ASSERT_EQUAL_INT(ICMPV6_NBR_SOL, nbr_sol->type);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, nbr_sol->code);
|
||||||
|
TEST_ASSERT(!ipv6_addr_is_multicast(&nbr_sol->tgt));
|
||||||
|
TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_loc_gb, &nbr_sol->tgt),
|
||||||
|
"_loc_gb != nbr_sol->tgt");
|
||||||
|
/* no further options */
|
||||||
|
TEST_ASSERT_NULL(pkt->next->next->next);
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TEST_ASSERT_MESSAGE(gnrc_netif_ipv6_addr_idx(_mock_netif,
|
TEST_ASSERT_MESSAGE(gnrc_netif_ipv6_addr_idx(_mock_netif,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
include ../Makefile.tests_common
|
include ../Makefile.tests_common
|
||||||
|
|
||||||
BOARD_INSUFFICIENT_MEMORY := calliope-mini chronos microbit msb-430 msb-430h \
|
BOARD_INSUFFICIENT_MEMORY := calliope-mini chronos hifive1 microbit msb-430 msb-430h \
|
||||||
nucleo-f031k6 nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 \
|
nucleo-f031k6 nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 \
|
||||||
nucleo-f030r8 nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 \
|
nucleo-f030r8 nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 \
|
||||||
nucleo-f334r8 nucleo-l053r8 spark-core stm32f0discovery telosb \
|
nucleo-f334r8 nucleo-l053r8 spark-core stm32f0discovery telosb \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user