From 1d10948069b4c15cb9bfdbb6d58723f1a9aab6a2 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 17 Aug 2022 15:36:10 -0700 Subject: [PATCH] [router-table] simplify `Allocate()` and random selection of ID (#8032) This commit updates `RouterTable::Allocate()` to use Reservoir sampling algorithm to randomly select a router ID while iterating through the list of available IDs. --- src/core/thread/router_table.cpp | 48 +++++++++++++------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index 722faddb9..d9731bdbb 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -205,9 +205,11 @@ void RouterTable::UpdateAllocation(void) Router *RouterTable::Allocate(void) { - Router *rval = nullptr; - uint8_t numAvailable = 0; - uint8_t freeBit; + Router *router = nullptr; + uint8_t numAvailable = 0; + uint8_t selectedRouterId = Mle::kInvalidRouterId; + + VerifyOrExit(mActiveRouterCount < Mle::kMaxRouters); // count available router ids #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE @@ -219,38 +221,26 @@ Router *RouterTable::Allocate(void) if (!IsAllocated(routerId) && mRouterIdReuseDelay[routerId] == 0) { numAvailable++; + + // Randomly select a router ID as we iterate through the + // list using Reservoir algorithm: We replace the + // selected ID with current entry in the list with + // probably `1/numAvailable`. + + if (Random::NonCrypto::GetUint8InRange(0, numAvailable) == 0) + { + selectedRouterId = routerId; + } } } - VerifyOrExit(mActiveRouterCount < Mle::kMaxRouters && numAvailable > 0); + VerifyOrExit(selectedRouterId != Mle::kInvalidRouterId); - // choose available router id at random - freeBit = Random::NonCrypto::GetUint8InRange(0, numAvailable); - - // allocate router -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - for (uint8_t routerId = mMinRouterId; routerId <= mMaxRouterId; routerId++) -#else - for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++) -#endif - { - if (IsAllocated(routerId) || mRouterIdReuseDelay[routerId] > 0) - { - continue; - } - - if (freeBit == 0) - { - rval = Allocate(routerId); - OT_ASSERT(rval != nullptr); - ExitNow(); - } - - freeBit--; - } + router = Allocate(selectedRouterId); + OT_ASSERT(router != nullptr); exit: - return rval; + return router; } Router *RouterTable::Allocate(uint8_t aRouterId)