diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c
index b8dc68d0bbadef36cda13c834e7366169686fc27..c4ecf556bc4388a5e092c22ba4718df160e0e660 100644
--- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c
+++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c
@@ -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
diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h
index abfdb8f263cb8a0374b3a6e944b6c95d74ca26fe..aa7210992b2516dbf0ff690d32ee413525130322 100644
--- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h
+++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h
@@ -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
diff --git a/tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-internal.c b/tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-internal.c
index be6e75d6836e93e59dccd54230cbf138f3a45d1d..a171d3c2a173ba3eb5afd42436c5912af0f342d5 100644
--- a/tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-internal.c
+++ b/tests/unittests/tests-gnrc_ipv6_nib/tests-gnrc_ipv6_nib-internal.c
@@ -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,