Skip to content

Commit

Permalink
[routing-manager] new config to use heap for PrefixTable entries (o…
Browse files Browse the repository at this point in the history
…penthread#9455)

This commit introduces a new configuration option for the routing
manager to use heap-allocated entries in the `DiscoveredPrefixTable`,
which maintains a list of discovered routers and their advertised
on-link prefixes. This makes the implementation more flexible when
dealing with a large number of routers and/or discovered prefix
entries.

The config option `OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE`
enables this behavior. By default, it is enabled. When disabled, the
previous model, which uses pre-allocated arrays and pools, is used
instead.

This commit also updates the unit test `test_routing_manager` to track
heap allocations and validate that all heap allocations by the
routing manager are freed when it is stopped.
  • Loading branch information
abtink committed Sep 29, 2023
1 parent bd63637 commit eaa6261
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 25 deletions.
44 changes: 28 additions & 16 deletions src/core/border_router/routing_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6

if (router == nullptr)
{
router = mRouters.PushBack();
router = AllocateRouter();

if (router == nullptr)
{
Expand All @@ -1193,6 +1193,8 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6

router->Clear();
router->mAddress = aSrcAddress;

mRouters.Push(*router);
}

// RA message can indicate router provides default route in the RA
Expand Down Expand Up @@ -1471,13 +1473,12 @@ void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)

for (Router &router : mRouters)
{
Entry *entry;

while ((entry = router.mEntries.Pop()) != nullptr)
if (!router.mEntries.IsEmpty())
{
FreeEntry(*entry);
SignalTableChanged();
}

FreeEntries(router.mEntries);
}

RemoveRoutersWithNoEntries();
Expand Down Expand Up @@ -1579,13 +1580,27 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill

void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
{
mRouters.RemoveAllMatching(Router::kContainsNoEntries);
LinkedList<Router> routersToFree;

mRouters.RemoveAllMatching(Router::kContainsNoEntries, routersToFree);
FreeRouters(routersToFree);
}

void RoutingManager::DiscoveredPrefixTable::FreeRouters(LinkedList<Router> &aRouters)
{
// Frees all routers in the given list `aRouters`

Router *router;

while ((router = aRouters.Pop()) != nullptr)
{
FreeRouter(*router);
}
}

void RoutingManager::DiscoveredPrefixTable::FreeEntries(LinkedList<Entry> &aEntries)
{
// Frees all entries in the given list `aEntries` (put them back
// in the entry pool).
// Frees all entries in the given list `aEntries`.

Entry *entry;

Expand Down Expand Up @@ -1768,8 +1783,8 @@ void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aI
Iterator &iterator = static_cast<Iterator &>(aIterator);

iterator.SetInitTime();
iterator.SetRouter(mRouters.Front());
iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters[0].mEntries.GetHead());
iterator.SetRouter(mRouters.GetHead());
iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters.GetHead()->mEntries.GetHead());
}

Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
Expand All @@ -1795,15 +1810,12 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a

if (iterator.GetEntry() == nullptr)
{
if (iterator.GetRouter() != mRouters.Back())
iterator.SetRouter(iterator.GetRouter()->GetNext());

if (iterator.GetRouter() != nullptr)
{
iterator.SetRouter(iterator.GetRouter() + 1);
iterator.SetEntry(iterator.GetRouter()->mEntries.GetHead());
}
else
{
iterator.SetRouter(nullptr);
}
}

exit:
Expand Down
44 changes: 35 additions & 9 deletions src/core/border_router/routing_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "border_router/infra_if.hpp"
#include "common/array.hpp"
#include "common/error.hpp"
#include "common/heap_allocatable.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
Expand Down Expand Up @@ -624,10 +625,17 @@ class RoutingManager : public InstanceLocator
void HandleRouterTimer(void);

private:
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
#endif

class Entry : public LinkedListEntry<Entry>, public Unequatable<Entry>, private Clearable<Entry>
class Entry : public LinkedListEntry<Entry>,
public Unequatable<Entry>,
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
public Heap::Allocatable<Entry>,
#endif
private Clearable<Entry>
{
friend class LinkedListEntry<Entry>;
friend class Clearable<Entry>;
Expand Down Expand Up @@ -725,7 +733,11 @@ class RoutingManager : public InstanceLocator
} mShared;
};

struct Router : public Clearable<Router>
struct Router : public LinkedListEntry<Router>,
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
public Heap::Allocatable<Router>,
#endif
public Clearable<Router>
{
// The timeout (in msec) for router staying in active state
// before starting the Neighbor Solicitation (NS) probes.
Expand All @@ -746,6 +758,7 @@ class RoutingManager : public InstanceLocator
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }

Router *mNext;
Ip6::Address mAddress;
LinkedList<Entry> mEntries;
TimeMilli mTimeout;
Expand Down Expand Up @@ -774,25 +787,38 @@ class RoutingManager : public InstanceLocator
void RemovePrefix(const Entry::Matcher &aMatcher);
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
void RemoveRoutersWithNoEntries(void);
Entry *AllocateEntry(void) { return mEntryPool.Allocate(); }
void FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); }
void FreeRouters(LinkedList<Router> &aRouters);
void FreeEntries(LinkedList<Entry> &aEntries);
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
const Entry *FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix) const;
void RemoveExpiredEntries(void);
void SignalTableChanged(void);
void UpdateRouterOnRx(Router &aRouter);
void SendNeighborSolicitToRouter(const Router &aRouter);
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
Router *AllocateRouter(void) { return Router::Allocate(); }
Entry *AllocateEntry(void) { return Entry::Allocate(); }
void FreeRouter(Router &aRouter) { aRouter.Free(); }
void FreeEntry(Entry &aEntry) { aEntry.Free(); }
#else
Router *AllocateRouter(void) { return mRouterPool.Allocate(); }
Entry *AllocateEntry(void) { return mEntryPool.Allocate(); }
void FreeRouter(Router &aRouter) { mRouterPool.Free(aRouter); }
void FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); }
#endif

using SignalTask = TaskletIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableChanged>;
using EntryTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableEntryTimer>;
using RouterTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableRouterTimer>;

Array<Router, kMaxRouters> mRouters;
Pool<Entry, kMaxEntries> mEntryPool;
EntryTimer mEntryTimer;
RouterTimer mRouterTimer;
SignalTask mSignalTask;
LinkedList<Router> mRouters;
EntryTimer mEntryTimer;
RouterTimer mRouterTimer;
SignalTask mSignalTask;
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
Pool<Entry, kMaxEntries> mEntryPool;
Pool<Router, kMaxRouters> mRouterPool;
#endif
};

class OmrPrefixManager;
Expand Down
22 changes: 22 additions & 0 deletions src/core/config/border_routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,30 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 0
#endif

/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
*
* Define to 1 to allow using heap by Routing Manager.
*
* When enabled heap allocated entries will be used to track discovered prefix table contain information about
* discovered routers and the advertised on-link prefixes on infra link.
*
* When disabled pre-allocated pools are used instead where max number of entries are specified by
* `OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS` and `MAX_DISCOVERED_PREFIXES` configurations.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
#define OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1
#endif

/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
*
* Specifies maximum number of routers (on infra link) to track by routing manager.
*
* Applicable only when heap allocation is not used, i.e., `OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE` is
* disabled.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS 16
Expand All @@ -60,6 +79,9 @@
*
* Specifies maximum number of discovered prefixes (on-link prefixes on the infra link) maintained by routing manager.
*
* Applicable only when heap allocation is not used, i.e., `OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE` is
* disabled.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 64
Expand Down
Loading

0 comments on commit eaa6261

Please sign in to comment.