Skip to content
Snippets Groups Projects
Unverified Commit 8e4b11cd authored by Gaëtan Harter's avatar Gaëtan Harter Committed by GitHub
Browse files

Merge pull request #10369 from miri64/gnrc_ipv6_nib/fix/arsm-16-bit

gnrc_ipv6_nib/arsm: ensure proper int width in backoff calculation
parents a37ba3c3 f5086e76
No related branches found
No related tags found
No related merge requests found
......@@ -460,17 +460,10 @@ bool _is_reachable(_nib_onl_entry_t *entry)
static inline uint32_t _exp_backoff_retrans_timer(uint8_t ns_sent,
uint32_t retrans_timer)
{
uint32_t tmp = random_uint32_range(NDP_MIN_RANDOM_FACTOR,
NDP_MAX_RANDOM_FACTOR);
/* backoff according to https://tools.ietf.org/html/rfc7048 with
* BACKOFF_MULTIPLE == 2 */
tmp = ((1 << ns_sent) * retrans_timer * tmp) / US_PER_MS;
/* random factors were statically multiplied with 1000 ^ */
if (tmp > NDP_MAX_RETRANS_TIMER_MS) {
tmp = NDP_MAX_RETRANS_TIMER_MS;
}
return tmp;
uint32_t factor = random_uint32_range(NDP_MIN_RANDOM_FACTOR,
NDP_MAX_RANDOM_FACTOR);
return _exp_backoff_retrans_timer_factor(ns_sent, retrans_timer, factor);
}
#if GNRC_IPV6_NIB_CONF_REDIRECT
......
......@@ -81,6 +81,43 @@ void _snd_uc_ns(_nib_onl_entry_t *nbr, bool reset);
void _handle_sl2ao(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
const icmpv6_hdr_t *icmpv6, const ndp_opt_t *sl2ao);
/**
* @brief Calculates truncated exponential back-off for retransmission timer
* for neighbor solicitations based on a randomized factor
*
* The truncation is at @ref NDP_MAX_RETRANS_TIMER_MS. as suggested in
* [RFC 7048, section 3](https://tools.ietf.org/html/rfc7048#section-3).
*
* @param[in] ns_sent Neighbor solicitations sent up until now. Must be
* lesser than or equal to @ref NDP_MAX_NS_NUMOF.
* @param[in] retrans_timer Currently configured retransmission timer in ms.
* @param[in] factor An equally distributed factor between
* @ref NDP_MIN_RANDOM_FACTOR and (exclusive)
* @ref NDP_MAX_RANDOM_FACTOR.
*
* @pre (NDP_MIN_RANDOM_FACTOR <= factor < NDP_MAX_RANDOM_FACTOR)
* @pre (ns_sent <= NDP_MAX_NS_NUMOF)
*
* @return exponential back-off of the retransmission timer
*/
static inline uint32_t _exp_backoff_retrans_timer_factor(uint8_t ns_sent,
uint32_t retrans_timer,
uint32_t factor)
{
assert(NDP_MIN_RANDOM_FACTOR <= factor);
assert(factor < NDP_MAX_RANDOM_FACTOR);
assert(ns_sent <= NDP_MAX_NS_NUMOF);
/* backoff according to https://tools.ietf.org/html/rfc7048 with
* BACKOFF_MULTIPLE == 2 */
uint32_t res = (uint32_t)(((uint64_t)(((uint32_t) 1) << ns_sent) *
retrans_timer * factor) / US_PER_MS);
/* random factors were statically multiplied with 1000 */
if (res > NDP_MAX_RETRANS_TIMER_MS) {
res = NDP_MAX_RETRANS_TIMER_MS;
}
return res;
}
#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN)
/**
* @brief Handler for @ref GNRC_IPV6_NIB_SND_UC_NS and
......
......@@ -21,6 +21,7 @@
#include "net/gnrc/ipv6/nib.h"
#include "_nib-internal.h"
#include "_nib-arsm.h"
#include "unittests-constants.h"
......@@ -1947,6 +1948,58 @@ static void test_nib_abr_iter__three_elem_middle_removed(void)
}
#endif
static void test_retrans_exp_backoff(void)
{
TEST_ASSERT_EQUAL_INT(0,
_exp_backoff_retrans_timer_factor(0, 0, NDP_MIN_RANDOM_FACTOR));
/* factor 1000 means multiplied by 1 */
TEST_ASSERT_EQUAL_INT(NDP_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(0, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(2 * NDP_RETRANS_TIMER_MS, /* 2^1 = 2 */
_exp_backoff_retrans_timer_factor(1, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(4 * NDP_RETRANS_TIMER_MS, /* 2^2 = 4 */
_exp_backoff_retrans_timer_factor(2, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(8 * NDP_RETRANS_TIMER_MS, /* 2^3 = 8 */
_exp_backoff_retrans_timer_factor(3, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(16 * NDP_RETRANS_TIMER_MS, /* 2^4 = 16 */
_exp_backoff_retrans_timer_factor(4, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(32 * NDP_RETRANS_TIMER_MS, /* 2^5 = 32 */
_exp_backoff_retrans_timer_factor(5, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(6, NDP_RETRANS_TIMER_MS, 1000));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(0, UINT32_MAX,
NDP_MIN_RANDOM_FACTOR));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(0, UINT32_MAX,
NDP_MAX_RANDOM_FACTOR - 1));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF, UINT32_MAX,
NDP_MAX_RANDOM_FACTOR - 1));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF,
NDP_RETRANS_TIMER_MS,
NDP_MAX_RANDOM_FACTOR - 1));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF,
NDP_RETRANS_TIMER_MS,
NDP_MIN_RANDOM_FACTOR));
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF,
NDP_MAX_RETRANS_TIMER_MS,
NDP_MAX_RANDOM_FACTOR - 1));
TEST_ASSERT_EQUAL_INT(32768,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF - 1, 1,
NDP_MIN_RANDOM_FACTOR));
TEST_ASSERT_EQUAL_INT(47653,
_exp_backoff_retrans_timer_factor(5U, 1118U, 1332));
TEST_ASSERT_EQUAL_INT(47653,
_exp_backoff_retrans_timer_factor(5U, 1118U, 1332));
/* test 64-bit overfrow */
TEST_ASSERT_EQUAL_INT(NDP_MAX_RETRANS_TIMER_MS,
_exp_backoff_retrans_timer_factor(NDP_MAX_NS_NUMOF, 32768, 1024));
}
Test *tests_gnrc_ipv6_nib_internal_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
......@@ -2046,6 +2099,7 @@ Test *tests_gnrc_ipv6_nib_internal_tests(void)
new_TestFixture(test_nib_abr_iter__three_elem),
new_TestFixture(test_nib_abr_iter__three_elem_middle_removed),
#endif
new_TestFixture(test_retrans_exp_backoff),
};
EMB_UNIT_TESTCALLER(tests, set_up, NULL,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment