mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
gnrc_sixlowpan_nd: initial import
This commit is contained in:
parent
fc6896b0c7
commit
2a1c243ad2
17
Makefile.dep
17
Makefile.dep
@ -52,6 +52,7 @@ endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += gnrc_sixlowpan
|
||||
USEMODULE += gnrc_sixlowpan_nd
|
||||
USEMODULE += gnrc_sixlowpan_frag
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
endif
|
||||
@ -77,10 +78,24 @@ ifneq (,$(filter gnrc_sixlowpan_ctx,$(USEMODULE)))
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ndp
|
||||
USEMODULE += gnrc_ndp_internal
|
||||
USEMODULE += gnrc_sixlowpan_ctx
|
||||
USEMODULE += random
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_ipv6_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += gnrc_icmpv6
|
||||
USEMODULE += gnrc_ndp_host
|
||||
ifeq (1,$(GNRC_NETIF_NUMOF))
|
||||
ifeq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE)))
|
||||
USEMODULE += gnrc_ndp_host
|
||||
endif
|
||||
else
|
||||
USEMODULE += gnrc_ndp_host
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_ipv6_router_default,$(USEMODULE)))
|
||||
|
190
sys/include/net/gnrc/sixlowpan/nd.h
Normal file
190
sys/include/net/gnrc/sixlowpan/nd.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* 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_sixlowpan_nd 6LoWPAN neighbor discovery
|
||||
* @ingroup net_gnrc_sixlowpan
|
||||
* @brief Neighbor Discovery Optimization for 6LoWPAN
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6775">
|
||||
* RFC 6775
|
||||
* </a>
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief General 6LoWPAN ND definitions
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_ND_H_
|
||||
#define GNRC_SIXLOWPAN_ND_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "net/gnrc/ipv6/nc.h"
|
||||
#include "net/gnrc/ipv6/netif.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
#include "net/ndp.h"
|
||||
#include "net/sixlowpan/nd.h"
|
||||
#include "timex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Message type for next multicast router solicitation.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL (0x0220)
|
||||
|
||||
/**
|
||||
* @brief Message type for next unicast router solicitation.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_ND_MSG_UC_RTR_SOL (0x0221)
|
||||
|
||||
/**
|
||||
* @brief Message type for removing 6LoWPAN contexts.
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX (0x0222)
|
||||
|
||||
#ifndef GNRC_SIXLOWPAN_ND_AR_LTIME
|
||||
/**
|
||||
* @brief Registration lifetime in minutes for the address registration option
|
||||
*
|
||||
* This value should be adapted to the devices power-lifecycle so that it is greater than the
|
||||
* time the device spends sleeping.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6775#section-5.8.1">
|
||||
* RFC 6775, section 5.8.1
|
||||
* </a>
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_ND_AR_LTIME (15U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Host constants
|
||||
* @{
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6775#section-9">
|
||||
* RFC 6775, section 9
|
||||
* </a>
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_ND_RTR_SOL_INT (10U) /**< replacement value (in seconds) for
|
||||
* @ref GNRC_NDP_MAX_RTR_SOL_INT */
|
||||
#define GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT (60U) /**< retransmission increment for exponential
|
||||
* backoff of subsequent RS */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Initializes 6LoWPAN neighbor discovery for the interface.
|
||||
* @pre @p iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN
|
||||
* @param[in] iface An IPv6 interface.
|
||||
*/
|
||||
void gnrc_sixlowpan_nd_init(gnrc_ipv6_netif_t *iface);
|
||||
|
||||
/**
|
||||
* @brief Multicasts a router solicitation over @p iface
|
||||
* @pre @p iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN
|
||||
* @param[in] iface An IPv6 interface.
|
||||
*/
|
||||
void gnrc_sixlowpan_nd_mc_rtr_sol(gnrc_ipv6_netif_t *iface);
|
||||
|
||||
/**
|
||||
* @brief Unicasts a router solicitation to the neighbor represented by @p nce
|
||||
* @pre @p nce->iface is an IPv6 interface and @ref GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN is set
|
||||
* in its flags.
|
||||
* @param[in] nce The neighbor to send the router solicitation to.
|
||||
*/
|
||||
void gnrc_sixlowpan_nd_uc_rtr_sol(gnrc_ipv6_nc_t *nce);
|
||||
|
||||
/**
|
||||
* @brief Get link-layer address and interface for next hop to destination
|
||||
* IPv6 address.
|
||||
*
|
||||
* @param[out] l2addr The link-layer for the next hop to @p dst.
|
||||
* @param[out] l2addr_len Length of @p l2addr.
|
||||
* @param[in] iface The interface to search the next hop on.
|
||||
* May be @ref KERNEL_PID_UNDEF if not specified.
|
||||
* @param[in] dst An IPv6 address to search the next hop for.
|
||||
*
|
||||
* @return The PID of the interface, on success.
|
||||
* @return -EHOSTUNREACH, if @p dst is not reachable.
|
||||
* @return -ENOBUFS, if @p l2addr_len was smaller than the resulting @p l2addr
|
||||
* would be long.
|
||||
*/
|
||||
kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
|
||||
kernel_pid_t iface, ipv6_addr_t *dst);
|
||||
|
||||
/**
|
||||
* @brief Reschedules the next router advertisement for a neighboring router.
|
||||
*
|
||||
* @pre nce != NULL && sec_delay != 0U
|
||||
*
|
||||
* @param[in] nce Neighbor cache entry representing the neighboring router.
|
||||
* @param[in] sec_delay The delay for the next router solicitation in seconds.
|
||||
*/
|
||||
void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay);
|
||||
|
||||
/**
|
||||
* @brief Builds the address registration option.
|
||||
*
|
||||
* @param[in] status Status for the ARO.
|
||||
* @param[in] ltime Registration lifetime for the ARO.
|
||||
* @param[in] eui64 The EUI-64 for the ARO
|
||||
* @param[in] next More options in the packet. NULL, if there are none.
|
||||
*
|
||||
* @return The pkt snip list of options, on success
|
||||
* @return NULL, if packet buffer is full
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, eui64_t *eui64,
|
||||
gnrc_pktsnip_t *next);
|
||||
|
||||
/**
|
||||
* @brief Handles address registration option.
|
||||
*
|
||||
* @param[in] iface The interface the ARO was received on.
|
||||
* @param[in] ipv6 The IPv6 header the ARO was received in.
|
||||
* @param[in] icmpv6_type Message type of the ICMPv6 message that contained.
|
||||
* this message.
|
||||
* @param[in] ar_opt The address registration option.
|
||||
* @param[in] sl2a The link-layer source address contained in SL2A accompanying this
|
||||
* option. May be NULL for icmpv6_type == ICMPV6_NBR_ADV.
|
||||
* @param[in] sl2a_len Length of @p sl2a. May be 0 if sl2a == NULL.
|
||||
*
|
||||
* @return Status for the ARO in the replying NA (always 0 if icmpv6_type == ICMPV6_NBR_ADV).
|
||||
*/
|
||||
uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6,
|
||||
uint8_t icmpv6_type, sixlowpan_nd_opt_ar_t *ar_opt,
|
||||
uint8_t *sl2a, size_t sl2a_len);
|
||||
|
||||
/**
|
||||
* @brief Handles 6LoWPAN context option.
|
||||
*
|
||||
* @param[in] icmpv6_type Message type of the ICMPv6 message that contained.
|
||||
* this message.
|
||||
* @param[in] ctx_opt The 6LoWPAN context option.
|
||||
*
|
||||
* @return true, when 6LoWPAN context option was correct.
|
||||
* @return false, when it was incorrect.
|
||||
*/
|
||||
bool gnrc_sixlowpan_nd_opt_6ctx_handle(uint8_t icmpv6_type, sixlowpan_nd_opt_6ctx_t *ctx_opt);
|
||||
|
||||
/**
|
||||
* @brief Handles registration calls after node-wakeup.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6775#section-5.8.2">
|
||||
* RFC 6776, section 5.8.2
|
||||
* </a>
|
||||
*/
|
||||
void gnrc_sixlowpan_nd_wakeup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_SIXLOWPAN_ND_H_ */
|
||||
/** @} */
|
@ -79,6 +79,9 @@ endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_iphc,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/iphc
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/nd
|
||||
endif
|
||||
ifneq (,$(filter gnrc_sixlowpan_netif,$(USEMODULE)))
|
||||
DIRS += network_layer/sixlowpan/netif
|
||||
endif
|
||||
|
3
sys/net/gnrc/network_layer/sixlowpan/nd/Makefile
Normal file
3
sys/net/gnrc/network_layer/sixlowpan/nd/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = gnrc_sixlowpan_nd
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
296
sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c
Normal file
296
sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "net/eui64.h"
|
||||
#include "net/gnrc/ipv6.h"
|
||||
#include "net/gnrc/ndp.h"
|
||||
#include "net/gnrc/ndp/internal.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
#include "net/gnrc/sixlowpan.h"
|
||||
#include "net/gnrc/sixlowpan/ctx.h"
|
||||
#include "random.h"
|
||||
#include "timex.h"
|
||||
|
||||
#include "net/gnrc/sixlowpan/nd.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static inline void _rtr_sol_reschedule(gnrc_ipv6_netif_t *iface, uint32_t sec_delay)
|
||||
{
|
||||
vtimer_remove(&iface->rtr_sol_timer);
|
||||
vtimer_set_msg(&iface->rtr_sol_timer, timex_set(sec_delay, 0), gnrc_ipv6_pid,
|
||||
GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL, iface);
|
||||
}
|
||||
|
||||
static inline uint32_t _binary_exp_backoff(uint32_t base_sec, unsigned int exp)
|
||||
{
|
||||
return genrand_uint32_range(0, (1 << exp) - 1) * base_sec;
|
||||
}
|
||||
|
||||
static inline void _revert_iid(uint8_t *iid)
|
||||
{
|
||||
iid[0] ^= 0x02;
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_nd_init(gnrc_ipv6_netif_t *iface)
|
||||
{
|
||||
assert(iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN);
|
||||
mutex_lock(&iface->mutex);
|
||||
iface->rtr_sol_count = 0; /* first will be send immediately */
|
||||
|
||||
DEBUG("6lo nd: retransmit multicast rtr sol in 10 sec\n");
|
||||
_rtr_sol_reschedule(iface, GNRC_SIXLOWPAN_ND_RTR_SOL_INT);
|
||||
mutex_unlock(&iface->mutex);
|
||||
gnrc_ndp_internal_send_rtr_sol(iface->pid, NULL);
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_nd_mc_rtr_sol(gnrc_ipv6_netif_t *iface)
|
||||
{
|
||||
uint32_t interval;
|
||||
assert(iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN);
|
||||
mutex_lock(&iface->mutex);
|
||||
if (iface->rtr_sol_count < GNRC_NDP_MAX_RTR_SOL_NUMOF) {
|
||||
DEBUG("6lo nd: retransmit multicast rtr sol in 10 sec\n");
|
||||
iface->rtr_sol_count++;
|
||||
interval = GNRC_SIXLOWPAN_ND_RTR_SOL_INT;
|
||||
}
|
||||
else {
|
||||
unsigned int exp = (unsigned int)(iface->rtr_sol_count - GNRC_NDP_MAX_RTR_SOL_NUMOF);
|
||||
interval = _binary_exp_backoff(1, exp);
|
||||
if (((1U << exp) - 1U) < GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT) {
|
||||
/* XXX Not sure if this is the correct interpretation of the truncation described in
|
||||
* https://tools.ietf.org/html/rfc6775#section-5.3. In every source I've read the
|
||||
* truncating value was the exponent, not the target value, so I'm very confused
|
||||
* about this sentencing. Anyway, since 60 sec is a maximum value this should only
|
||||
* affect the energy consumption of the implementation by sending the next RS too fast
|
||||
* but not its interoperability. */
|
||||
iface->rtr_sol_count++;
|
||||
}
|
||||
|
||||
DEBUG("6lo nd: retransmit multicast rtr sol in %" PRIu32 " sec\n", interval);
|
||||
iface->rtr_sol_count--;
|
||||
}
|
||||
_rtr_sol_reschedule(iface, interval);
|
||||
mutex_unlock(&iface->mutex);
|
||||
gnrc_ndp_internal_send_rtr_sol(iface->pid, NULL);
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_nd_uc_rtr_sol(gnrc_ipv6_nc_t *nce)
|
||||
{
|
||||
assert(gnrc_ipv6_netif_get(nce->iface)->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN);
|
||||
/* neighbor is not a router anymore */
|
||||
if (!(nce->flags & GNRC_IPV6_NC_IS_ROUTER) || ipv6_addr_is_unspecified(&nce->ipv6_addr)) {
|
||||
/* and there are no routers anymore */
|
||||
if (gnrc_ipv6_nc_get_next_router(NULL) == NULL) {
|
||||
/* start search for routers */
|
||||
gnrc_sixlowpan_nd_init(gnrc_ipv6_netif_get(nce->iface));
|
||||
}
|
||||
/* otherwise ignore this call */
|
||||
return;
|
||||
}
|
||||
/* next RS is rescheduled by RA handle function */
|
||||
gnrc_ndp_internal_send_rtr_sol(nce->iface, &nce->ipv6_addr);
|
||||
}
|
||||
|
||||
kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
|
||||
kernel_pid_t iface, ipv6_addr_t *dst)
|
||||
{
|
||||
ipv6_addr_t *next_hop = NULL;
|
||||
gnrc_ipv6_nc_t *nc_entry = NULL;
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6_EXT_RH
|
||||
ipv6_hdr_t *hdr;
|
||||
gnrc_pktsnip_t *ipv6;
|
||||
LL_SEARCH_SCALAR(pkt, ipv6, type, GNRC_NETTYPE_IPV6);
|
||||
assert(ipv6);
|
||||
hdr = ipv6->data;
|
||||
next_hop = ipv6_ext_rh_next_hop(hdr);
|
||||
#endif
|
||||
#ifdef MODULE_FIB
|
||||
ipv6_addr_t next_hop_actual; /* FIB copies address into this variable */
|
||||
/* don't look-up link local addresses in FIB */
|
||||
if ((next_hop == NULL) && !ipv6_addr_is_link_local(dst)) {
|
||||
size_t next_hop_size = sizeof(ipv6_addr_t);
|
||||
uint32_t next_hop_flags = 0;
|
||||
if ((next_hop == NULL) &&
|
||||
(fib_get_next_hop(&gnrc_ipv6_fib_table, &iface, next_hop_actual.u8, &next_hop_size,
|
||||
&next_hop_flags, (uint8_t *)dst,
|
||||
sizeof(ipv6_addr_t), 0) >= 0) &&
|
||||
(next_hop_size == sizeof(ipv6_addr_t))) {
|
||||
next_hop = &next_hop_actual;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* next hop determination according to: https://tools.ietf.org/html/rfc6775#section-5.6 */
|
||||
if ((next_hop == NULL) && ipv6_addr_is_link_local(dst)) { /* prefix is "on-link" */
|
||||
/* multicast is not handled here anyway so we don't need to check that */
|
||||
next_hop = dst;
|
||||
}
|
||||
else if (next_hop == NULL) { /* prefix is off-link */
|
||||
next_hop = gnrc_ndp_internal_default_router();
|
||||
}
|
||||
|
||||
/* address resolution of next_hop: https://tools.ietf.org/html/rfc6775#section-5.7 */
|
||||
if (ipv6_addr_is_link_local(next_hop)) {
|
||||
kernel_pid_t ifs[GNRC_NETIF_NUMOF];
|
||||
size_t ifnum = gnrc_netif_get(ifs);
|
||||
/* we don't need address resolution, the EUI-64 is in next_hop's IID */
|
||||
*l2addr_len = sizeof(eui64_t);
|
||||
memcpy(l2addr, &next_hop->u8[8], sizeof(eui64_t));
|
||||
_revert_iid(l2addr);
|
||||
if (iface == KERNEL_PID_UNDEF) {
|
||||
for (unsigned i = 0; i < ifnum; i++) {
|
||||
gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);
|
||||
if ((ipv6_if != NULL) && (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
|
||||
/* always take the first 6LoWPAN interface we can find */
|
||||
return ifs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return iface;
|
||||
}
|
||||
else {
|
||||
nc_entry = gnrc_ipv6_nc_get(iface, next_hop);
|
||||
if ((nc_entry == NULL) || (!gnrc_ipv6_nc_is_reachable(nc_entry))) {
|
||||
return KERNEL_PID_UNDEF;
|
||||
}
|
||||
if (nc_entry->l2_addr_len > 0) {
|
||||
memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len);
|
||||
}
|
||||
*l2addr_len = nc_entry->l2_addr_len;
|
||||
return nc_entry->iface;
|
||||
}
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay)
|
||||
{
|
||||
assert(nce != NULL);
|
||||
assert(sec_delay != 0U);
|
||||
vtimer_remove(&nce->rtr_sol_timer);
|
||||
vtimer_set_msg(&nce->rtr_sol_timer, timex_set(sec_delay, 0), gnrc_ipv6_pid,
|
||||
GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL, nce);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, eui64_t *eui64,
|
||||
gnrc_pktsnip_t *next)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_AR, sizeof(sixlowpan_nd_opt_ar_t), next);
|
||||
|
||||
if (pkt != NULL) {
|
||||
sixlowpan_nd_opt_ar_t *ar_opt = pkt->data;
|
||||
ar_opt->status = status;
|
||||
ar_opt->resv[0] = ar_opt->resv[1] = ar_opt->resv[2] = 0;
|
||||
ar_opt->ltime = byteorder_htons(ltime);
|
||||
memcpy(&ar_opt->eui64, eui64, sizeof(eui64_t));
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, uint8_t icmpv6_type,
|
||||
sixlowpan_nd_opt_ar_t *ar_opt, uint8_t *sl2a,
|
||||
size_t sl2a_len)
|
||||
{
|
||||
eui64_t eui64;
|
||||
gnrc_ipv6_netif_t *ipv6_iface;
|
||||
gnrc_ipv6_nc_t *nc_entry;
|
||||
(void)sl2a;
|
||||
(void)sl2a_len;
|
||||
if (ar_opt->len != SIXLOWPAN_ND_OPT_AR_LEN) {
|
||||
/* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
|
||||
return 0;
|
||||
}
|
||||
if (gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, &eui64,
|
||||
sizeof(eui64)) < 0) {
|
||||
/* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
|
||||
return 0;
|
||||
}
|
||||
ipv6_iface = gnrc_ipv6_netif_get(iface);
|
||||
nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
|
||||
switch (icmpv6_type) {
|
||||
case ICMPV6_NBR_ADV:
|
||||
if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
|
||||
DEBUG("6lo nd: interface not a 6LoWPAN interface\n");
|
||||
return 0;
|
||||
}
|
||||
if (eui64.uint64.u64 != ar_opt->eui64.uint64.u64) {
|
||||
/* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
|
||||
return 0;
|
||||
}
|
||||
switch (ar_opt->status) {
|
||||
case SIXLOWPAN_ND_STATUS_SUCCESS:
|
||||
DEBUG("6lo nd: address registration successful\n");
|
||||
mutex_lock(&ipv6_iface->mutex);
|
||||
vtimer_remove(&nc_entry->nbr_sol_timer);
|
||||
vtimer_set_msg(&nc_entry->nbr_sol_timer, ipv6_iface->retrans_timer,
|
||||
gnrc_ipv6_pid, GNRC_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
|
||||
mutex_unlock(&ipv6_iface->mutex);
|
||||
break;
|
||||
case SIXLOWPAN_ND_STATUS_DUP:
|
||||
DEBUG("6lo nd: address registration determined duplicated\n");
|
||||
/* TODO: handle DAD failed case */
|
||||
gnrc_ipv6_netif_remove_addr(iface, &ipv6->dst);
|
||||
/* address should not be used anymore */
|
||||
break;
|
||||
case SIXLOWPAN_ND_STATUS_NC_FULL:
|
||||
DEBUG("6lo nd: neighbor cache on router is full\n");
|
||||
gnrc_ipv6_nc_remove(iface, &ipv6->src);
|
||||
/* try to find another router */
|
||||
gnrc_sixlowpan_nd_init(ipv6_iface);
|
||||
break;
|
||||
default:
|
||||
DEBUG("6lo nd: unknown status for registration received\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool gnrc_sixlowpan_nd_opt_6ctx_handle(uint8_t icmpv6_type, sixlowpan_nd_opt_6ctx_t *ctx_opt)
|
||||
{
|
||||
if (((ctx_opt->ctx_len < 64) && (ctx_opt->len != 2)) ||
|
||||
((ctx_opt->ctx_len >= 64) && (ctx_opt->len != 3))) {
|
||||
DEBUG("6lo nd: invalid 6LoWPAN context option received\n");
|
||||
return false;
|
||||
}
|
||||
if (icmpv6_type != ICMPV6_RTR_ADV) {
|
||||
/* discard silently */
|
||||
return true;
|
||||
}
|
||||
/* don't care for result */
|
||||
gnrc_sixlowpan_ctx_update(sixlowpan_nd_opt_6ctx_get_cid(ctx_opt), (ipv6_addr_t *)(ctx_opt + 1),
|
||||
ctx_opt->ctx_len, byteorder_ntohs(ctx_opt->ltime),
|
||||
sixlowpan_nd_opt_6ctx_is_comp(ctx_opt));
|
||||
return true;
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_nd_wakeup(void)
|
||||
{
|
||||
gnrc_ipv6_nc_t *router = gnrc_ipv6_nc_get_next_router(NULL);
|
||||
while (router) {
|
||||
timex_t t = { 0, GNRC_NDP_RETRANS_TIMER };
|
||||
vtimer_remove(&router->rtr_sol_timer);
|
||||
gnrc_sixlowpan_nd_uc_rtr_sol(router);
|
||||
gnrc_ndp_internal_send_nbr_sol(router->iface, &router->ipv6_addr, &router->ipv6_addr);
|
||||
vtimer_remove(&router->nbr_sol_timer);
|
||||
vtimer_set_msg(&router->nbr_sol_timer, t, gnrc_ipv6_pid, GNRC_NDP_MSG_NBR_SOL_RETRANS,
|
||||
router);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user