diff --git a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c index 598329b61..7fd4e09c6 100644 --- a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c +++ b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c @@ -564,6 +564,11 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t * not to run out; see https://tools.ietf.org/html/rfc6775#section-5.4.3 */ next_rtr_sol *= 3; next_rtr_sol >>= 2; + /* according to https://tools.ietf.org/html/rfc6775#section-5.3: + * "In all cases, the RS retransmissions are terminated when an RA is + * received." + * Hence, reset router solicitation counter and reset timer. */ + &nc_entry->rtr_sol_count = 0; gnrc_sixlowpan_nd_rtr_sol_reschedule(nc_entry, next_rtr_sol); gnrc_ndp_internal_send_nbr_sol(ifs[i], &nc_entry->ipv6_addr, &nc_entry->ipv6_addr); vtimer_remove(&nc_entry->nbr_sol_timer); diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c index cae74d1d1..8308394b4 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c +++ b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c @@ -36,7 +36,7 @@ static inline void _rtr_sol_reschedule(gnrc_ipv6_netif_t *iface, uint32_t sec_de static inline uint32_t _binary_exp_backoff(uint32_t base_sec, unsigned int exp) { - return genrand_uint32_range(0, (1 << exp) - 1) * base_sec; + return genrand_uint32_range(0, (1 << exp)) * base_sec; } static inline void _revert_iid(uint8_t *iid) @@ -48,7 +48,7 @@ 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 */ + iface->rtr_sol_count = 0; /* first will be sent immediately */ DEBUG("6lo nd: retransmit multicast rtr sol in 10 sec\n"); _rtr_sol_reschedule(iface, GNRC_SIXLOWPAN_ND_RTR_SOL_INT); @@ -69,7 +69,7 @@ void gnrc_sixlowpan_nd_mc_rtr_sol(gnrc_ipv6_netif_t *iface) 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) { + if ((1U << exp) < 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 @@ -78,9 +78,18 @@ void gnrc_sixlowpan_nd_mc_rtr_sol(gnrc_ipv6_netif_t *iface) * but not its interoperability. */ iface->rtr_sol_count++; } + /* RFC6775, section 5.3 (https://tools.ietf.org/html/rfc6775#section-5.3) + * states that router solicitation should be sent slower after the + * initial 3 retransmissions (i.e. >= 10 secondes) and truncate "the + * increase of the retransmission timer at 60 seconds". */ + if (interval < GNRC_SIXLOWPAN_ND_RTR_SOL_INT) { + interval = GNRC_SIXLOWPAN_ND_RTR_SOL_INT; + } + else if (interval > GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT) { + interval = GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT; + } 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);