

9 changed files with 702 additions and 4 deletions
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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_ndp_router Router-specific part of router discovery. |
||||
* @ingroup net_gnrc_ndp |
||||
* @brief Router-specific part for the router discovery in IPv6 |
||||
* neighbor discovery. |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Router-specific router discovery definitions |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
#ifndef GNRC_NDP_ROUTER_H_ |
||||
#define GNRC_NDP_ROUTER_H_ |
||||
|
||||
#include <stdbool.h> |
||||
|
||||
#include "kernel_types.h" |
||||
#include "net/ipv6/hdr.h" |
||||
#include "net/ndp.h" |
||||
#include "net/gnrc/ipv6/nc.h" |
||||
#include "timex.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set @p iface to router mode. |
||||
* |
||||
* @details This sets/unsets the GNRC_IPV6_NETIF_FLAGS_ROUTER and |
||||
* GNRC_IPV6_NETIF_FLAGS_RTR_ADV and initializes or ceases router |
||||
* behavior for neighbor discovery. |
||||
* |
||||
* @param[in] iface An IPv6 interface. Must not be NULL. |
||||
* @param[in] enable Status for the GNRC_IPV6_NETIF_FLAGS_ROUTER and |
||||
* GNRC_IPV6_NETIF_FLAGS_RTR_ADV flags. |
||||
*/ |
||||
void gnrc_ndp_router_set_router(gnrc_ipv6_netif_t *iface, bool enable); |
||||
|
||||
/**
|
||||
* @brief Set/Unset GNRC_IPV6_NETIF_FLAGS_RTR_ADV flag for @p iface. |
||||
* |
||||
* @see <a href="https://tools.ietf.org/html/rfc4861#section-6.2.2"> |
||||
* RFC 4861, section 6.2.2 |
||||
* </a> |
||||
* @see <a href="https://tools.ietf.org/html/rfc4861#section-6.2.5"> |
||||
* RFC 4861, section 6.2.5 |
||||
* </a> |
||||
* |
||||
* @details GNRC_IPV6_NETIF_FLAGS_RTR_ADV and initializes or ceases |
||||
* periodic router advertising behavior for neighbor discovery. |
||||
* |
||||
* @param[in] iface An IPv6 interface. Must not be NULL. |
||||
* @param[in] enable Status for the GNRC_IPV6_NETIF_FLAGS_RTR_ADV flags. |
||||
*/ |
||||
void gnrc_ndp_router_set_rtr_adv(gnrc_ipv6_netif_t *iface, bool enable); |
||||
|
||||
/**
|
||||
* @brief Send an unsolicited router advertisement over @p iface |
||||
* and reset the timer for the next one if necessary. |
||||
* |
||||
* @param[in] iface An IPv6 interface. |
||||
*/ |
||||
void gnrc_ndp_router_retrans_rtr_adv(gnrc_ipv6_netif_t *iface); |
||||
|
||||
/**
|
||||
* @brief Send an solicited router advertisement to IPv6 address of |
||||
* @p neighbor. |
||||
* |
||||
* @param[in] neighbor A neighbor cache entry. |
||||
*/ |
||||
void gnrc_ndp_router_send_rtr_adv(gnrc_ipv6_nc_t *neighbor); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GNRC_NDP_ROUTER_H_ */ |
||||
/** @} */ |
@ -0,0 +1,3 @@
|
||||
MODULE = gnrc_ndp_router
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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/gnrc/ipv6.h" |
||||
#include "net/gnrc/ndp.h" |
||||
#include "net/gnrc/ndp/internal.h" |
||||
#include "random.h" |
||||
#include "timex.h" |
||||
#include "vtimer.h" |
||||
|
||||
#include "net/gnrc/ndp/router.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static void _send_rtr_adv(gnrc_ipv6_netif_t *iface, ipv6_addr_t *dst); |
||||
|
||||
void gnrc_ndp_router_set_router(gnrc_ipv6_netif_t *iface, bool enable) |
||||
{ |
||||
ipv6_addr_t all_routers = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; |
||||
if (enable && !(iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { |
||||
gnrc_ipv6_netif_add_addr(iface->pid, &all_routers, 128, |
||||
GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST); |
||||
mutex_lock(&iface->mutex); |
||||
iface->flags |= GNRC_IPV6_NETIF_FLAGS_ROUTER; |
||||
iface->max_adv_int = GNRC_IPV6_NETIF_DEFAULT_MAX_ADV_INT; |
||||
iface->min_adv_int = GNRC_IPV6_NETIF_DEFAULT_MIN_ADV_INT; |
||||
iface->adv_ltime = GNRC_IPV6_NETIF_DEFAULT_ROUTER_LTIME; |
||||
mutex_unlock(&iface->mutex); |
||||
gnrc_ndp_router_set_rtr_adv(iface, enable); |
||||
} |
||||
else if (!enable && (iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { |
||||
gnrc_ipv6_netif_remove_addr(iface->pid, &all_routers); |
||||
gnrc_ndp_router_set_rtr_adv(iface, enable); |
||||
} |
||||
} |
||||
|
||||
void gnrc_ndp_router_set_rtr_adv(gnrc_ipv6_netif_t *iface, bool enable) |
||||
{ |
||||
if (enable && !(iface->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { |
||||
mutex_lock(&iface->mutex); |
||||
iface->flags |= GNRC_IPV6_NETIF_FLAGS_RTR_ADV; |
||||
iface->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF; |
||||
mutex_unlock(&iface->mutex); |
||||
_send_rtr_adv(iface, NULL); |
||||
} |
||||
else if (!enable && (iface->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { |
||||
mutex_lock(&iface->mutex); |
||||
iface->rtr_adv_count = GNRC_NDP_MAX_FIN_RTR_ADV_NUMOF; |
||||
iface->flags &= ~GNRC_IPV6_NETIF_FLAGS_RTR_ADV; |
||||
iface->adv_ltime = 0; |
||||
#ifdef MODULE_GNRC_NDP_HOST |
||||
iface->rtr_sol_count = GNRC_NDP_MAX_RTR_SOL_NUMOF; |
||||
#endif |
||||
mutex_unlock(&iface->mutex); |
||||
_send_rtr_adv(iface, NULL); |
||||
#ifdef MODULE_GNRC_NDP_HOST |
||||
gnrc_ndp_host_retrans_rtr_sol(iface); |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
void gnrc_ndp_router_retrans_rtr_adv(gnrc_ipv6_netif_t *iface) |
||||
{ |
||||
_send_rtr_adv(iface, NULL); |
||||
} |
||||
|
||||
void gnrc_ndp_router_send_rtr_adv(gnrc_ipv6_nc_t *neighbor) |
||||
{ |
||||
gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(neighbor->iface); |
||||
_send_rtr_adv(iface, &neighbor->ipv6_addr); |
||||
} |
||||
|
||||
static void _send_rtr_adv(gnrc_ipv6_netif_t *iface, ipv6_addr_t *dst) |
||||
{ |
||||
bool fin; |
||||
uint32_t interval; |
||||
|
||||
mutex_lock(&iface->mutex); |
||||
fin = (iface->adv_ltime == 0); |
||||
interval = genrand_uint32_range(iface->min_adv_int, iface->max_adv_int); |
||||
if (!fin && !((iface->flags | GNRC_IPV6_NETIF_FLAGS_ROUTER) && |
||||
(iface->flags | GNRC_IPV6_NETIF_FLAGS_RTR_ADV))) { |
||||
DEBUG("ndp rtr: interface %" PRIkernel_pid " is not an advertising interface\n", |
||||
iface->pid); |
||||
return; |
||||
} |
||||
if (iface->rtr_adv_count > 1) { /* regard for off-by-one error */ |
||||
iface->rtr_adv_count--; |
||||
if (!fin && (interval > GNRC_NDP_MAX_INIT_RTR_ADV_INT)) { |
||||
interval = GNRC_NDP_MAX_INIT_RTR_ADV_INT; |
||||
} |
||||
} |
||||
if (!fin || (iface->rtr_adv_count > 1)) { /* regard for off-by-one-error */ |
||||
/* reset timer for next router advertisement */ |
||||
vtimer_remove(&iface->rtr_adv_timer); |
||||
vtimer_set_msg(&iface->rtr_adv_timer, timex_set(interval, 0), |
||||
gnrc_ipv6_pid, GNRC_NDP_MSG_RTR_ADV_RETRANS, iface); |
||||
} |
||||
mutex_unlock(&iface->mutex); |
||||
for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { |
||||
ipv6_addr_t *src = &iface->addrs[i].addr; |
||||
|
||||
if (!ipv6_addr_is_unspecified(src) && ipv6_addr_is_link_local(src) && |
||||
!gnrc_ipv6_netif_addr_is_non_unicast(src)) { |
||||
/* send one for every link local address (ideally there is only one) */ |
||||
gnrc_ndp_internal_send_rtr_adv(iface->pid, src, dst, fin); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** @} */ |
Loading…
Reference in new issue