[trel] use LinkedList for TREL peer tracking (#11476)

This commit updates the internal data structure used for tracking TREL
peers. Peer tracking now uses a `LinkedList` of `Peer` objects
allocated from a pre-allocated `Pool<Peer>`, instead of using a
fixed-size `Array<Peer>`.

This change allows for future enhancements, such as using
heap-allocated `Peer` entries and/or extending the `Peer` object to
track additional (dynamically allocated) information.
This commit is contained in:
Abtin Keshavarzian
2025-05-07 13:10:13 -07:00
committed by GitHub
parent 2591b58f3c
commit ec2b0d4873
4 changed files with 59 additions and 40 deletions

View File

@ -52,7 +52,7 @@ extern "C" {
* *
* @note This number versions both OpenThread platform and user APIs. * @note This number versions both OpenThread platform and user APIs.
*/ */
#define OPENTHREAD_API_VERSION (504) #define OPENTHREAD_API_VERSION (505)
/** /**
* @addtogroup api-instance * @addtogroup api-instance

View File

@ -68,7 +68,7 @@ typedef struct otTrelPeer
/** /**
* Represents an iterator for iterating over TREL peer table entries. * Represents an iterator for iterating over TREL peer table entries.
*/ */
typedef uint16_t otTrelPeerIterator; typedef const void *otTrelPeerIterator;
/** /**
* Enables or disables TREL operation. * Enables or disables TREL operation.

View File

@ -102,18 +102,21 @@ void Interface::Disable(void)
VerifyOrExit(mInitialized); VerifyOrExit(mInitialized);
otPlatTrelDisable(&GetInstance()); otPlatTrelDisable(&GetInstance());
mPeerTable.Clear(); ClearPeerList();
LogDebg("Disabled interface"); LogDebg("Disabled interface");
exit: exit:
return; return;
} }
Interface::Peer *Interface::FindPeer(const Mac::ExtAddress &aExtAddress) void Interface::ClearPeerList(void)
{ {
return mPeerTable.FindMatching(aExtAddress); mPeerList.Clear();
mPeerPool.FreeAll();
} }
Interface::Peer *Interface::FindPeer(const Mac::ExtAddress &aExtAddress) { return mPeerList.FindMatching(aExtAddress); }
void Interface::NotifyPeerSocketAddressDifference(const Ip6::SockAddr &aPeerSockAddr, const Ip6::SockAddr &aRxSockAddr) void Interface::NotifyPeerSocketAddressDifference(const Ip6::SockAddr &aPeerSockAddr, const Ip6::SockAddr &aRxSockAddr)
{ {
otPlatTrelNotifyPeerSocketAddressDifference(&GetInstance(), &aPeerSockAddr, &aRxSockAddr); otPlatTrelNotifyPeerSocketAddressDifference(&GetInstance(), &aPeerSockAddr, &aRxSockAddr);
@ -205,7 +208,7 @@ void Interface::HandleDiscoveredPeerInfo(const Peer::Info &aInfo)
// different Extended MAC address. This ensures that we do not // different Extended MAC address. This ensures that we do not
// keep stale entries in the peer table. // keep stale entries in the peer table.
entry = mPeerTable.FindMatching(aInfo.GetSockAddr()); entry = mPeerList.FindMatching(aInfo.GetSockAddr());
if ((entry != nullptr) && !entry->Matches(extAddress)) if ((entry != nullptr) && !entry->Matches(extAddress))
{ {
@ -215,7 +218,7 @@ void Interface::HandleDiscoveredPeerInfo(const Peer::Info &aInfo)
if (entry == nullptr) if (entry == nullptr)
{ {
entry = mPeerTable.FindMatching(extAddress); entry = mPeerList.FindMatching(extAddress);
} }
if (entry == nullptr) if (entry == nullptr)
@ -297,10 +300,15 @@ Interface::Peer *Interface::GetNewPeerEntry(void)
{ {
Peer *peerEntry; Peer *peerEntry;
peerEntry = mPeerTable.PushBack(); peerEntry = mPeerPool.Allocate();
VerifyOrExit(peerEntry == nullptr);
for (Peer &entry : mPeerTable) if (peerEntry != nullptr)
{
mPeerList.Push(*peerEntry);
ExitNow();
}
for (Peer &entry : mPeerList)
{ {
if (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId()) if (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId())
{ {
@ -308,7 +316,7 @@ Interface::Peer *Interface::GetNewPeerEntry(void)
} }
} }
for (Peer &entry : mPeerTable) for (Peer &entry : mPeerList)
{ {
// We skip over any existing entry in neighbor table (even if the // We skip over any existing entry in neighbor table (even if the
// entry is in invalid state). // entry is in invalid state).
@ -336,15 +344,10 @@ void Interface::RemovePeerEntry(Peer &aEntry)
{ {
aEntry.Log("Removing"); aEntry.Log("Removing");
// Replace the entry being removed with the last entry (if not the if (mPeerList.Remove(aEntry) == kErrorNone)
// last one already) and then pop the last entry from array.
if (&aEntry != mPeerTable.Back())
{ {
aEntry = *mPeerTable.Back(); mPeerPool.Free(aEntry);
} }
mPeerTable.PopBack();
} }
const Counters *Interface::GetCounters(void) const { return otPlatTrelGetCounters(&GetInstance()); } const Counters *Interface::GetCounters(void) const { return otPlatTrelGetCounters(&GetInstance()); }
@ -362,7 +365,7 @@ Error Interface::Send(const Packet &aPacket, bool aIsDiscovery)
switch (aPacket.GetHeader().GetType()) switch (aPacket.GetHeader().GetType())
{ {
case Header::kTypeBroadcast: case Header::kTypeBroadcast:
for (Peer &entry : mPeerTable) for (Peer &entry : mPeerList)
{ {
if (!aIsDiscovery && (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId())) if (!aIsDiscovery && (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId()))
{ {
@ -375,7 +378,7 @@ Error Interface::Send(const Packet &aPacket, bool aIsDiscovery)
case Header::kTypeUnicast: case Header::kTypeUnicast:
case Header::kTypeAck: case Header::kTypeAck:
peerEntry = mPeerTable.FindMatching(aPacket.GetHeader().GetDestination()); peerEntry = mPeerList.FindMatching(aPacket.GetHeader().GetDestination());
VerifyOrExit(peerEntry != nullptr, error = kErrorAbort); VerifyOrExit(peerEntry != nullptr, error = kErrorAbort);
otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peerEntry->mSockAddr); otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peerEntry->mSockAddr);
break; break;
@ -414,14 +417,26 @@ exit:
const Interface::Peer *Interface::GetNextPeer(PeerIterator &aIterator) const const Interface::Peer *Interface::GetNextPeer(PeerIterator &aIterator) const
{ {
const Peer *entry = mPeerTable.At(aIterator); const Peer *entry = static_cast<const Peer *>(aIterator);
if (entry != nullptr) VerifyOrExit(entry != nullptr);
aIterator = entry->GetNext();
exit:
return entry;
}
uint16_t Interface::GetNumberOfPeers(void) const
{
uint16_t count = 0;
for (const Peer &peer : mPeerList)
{ {
aIterator++; OT_UNUSED_VARIABLE(peer);
count++;
} }
return entry; return count;
} }
void Interface::Peer::Log(const char *aAction) const void Interface::Peer::Log(const char *aAction) const

View File

@ -41,8 +41,9 @@
#include <openthread/trel.h> #include <openthread/trel.h>
#include <openthread/platform/trel.h> #include <openthread/platform/trel.h>
#include "common/array.hpp" #include "common/linked_list.hpp"
#include "common/locator.hpp" #include "common/locator.hpp"
#include "common/pool.hpp"
#include "common/tasklet.hpp" #include "common/tasklet.hpp"
#include "common/time.hpp" #include "common/time.hpp"
#include "mac/mac_types.hpp" #include "mac/mac_types.hpp"
@ -83,9 +84,10 @@ public:
/** /**
* Represents information about a discovered TREL peer. * Represents information about a discovered TREL peer.
*/ */
class Peer : public otTrelPeer class Peer : public otTrelPeer, public LinkedListEntry<Peer>
{ {
friend class Interface; friend class Interface;
friend class LinkedListEntry<Peer>;
friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo); friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
public: public:
@ -153,6 +155,8 @@ public:
void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; } void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; } void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; }
void Log(const char *aAction) const; void Log(const char *aAction) const;
Peer *mNext;
}; };
/** /**
@ -198,7 +202,7 @@ public:
* *
* @param[in] aIterator The iterator to initialize. * @param[in] aIterator The iterator to initialize.
*/ */
void InitIterator(PeerIterator &aIterator) const { aIterator = 0; } void InitIterator(PeerIterator &aIterator) const { aIterator = mPeerList.GetHead(); }
/** /**
* Iterates over the peer table entries. * Iterates over the peer table entries.
@ -214,7 +218,7 @@ public:
* *
* @returns The number of TREL peers. * @returns The number of TREL peers.
*/ */
uint16_t GetNumberOfPeers(void) const { return mPeerTable.GetLength(); } uint16_t GetNumberOfPeers(void) const;
/** /**
* Sets the filter mode (enables/disables filtering). * Sets the filter mode (enables/disables filtering).
@ -276,16 +280,14 @@ public:
private: private:
#if OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE != 0 #if OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE != 0
static constexpr uint16_t kPeerTableSize = OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE; static constexpr uint16_t kPeerPoolSize = OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE;
#else #else
static constexpr uint16_t kPeerTableExtraEntries = 32; static constexpr uint16_t kExtraEntries = 32;
static constexpr uint16_t kPeerTableSize = Mle::kMaxRouters + Mle::kMaxChildren + kPeerTableExtraEntries; static constexpr uint16_t kPeerPoolSize = Mle::kMaxRouters + Mle::kMaxChildren + kExtraEntries;
#endif #endif
static const char kTxtRecordExtAddressKey[]; static const char kTxtRecordExtAddressKey[];
static const char kTxtRecordExtPanIdKey[]; static const char kTxtRecordExtPanIdKey[];
typedef Array<Peer, kPeerTableSize, uint16_t> PeerTable;
explicit Interface(Instance &aInstance); explicit Interface(Instance &aInstance);
// Methods used by `Trel::Link`. // Methods used by `Trel::Link`.
@ -304,16 +306,18 @@ private:
MeshCoP::ExtendedPanId &aExtPanId) const; MeshCoP::ExtendedPanId &aExtPanId) const;
Peer *GetNewPeerEntry(void); Peer *GetNewPeerEntry(void);
void RemovePeerEntry(Peer &aEntry); void RemovePeerEntry(Peer &aEntry);
void ClearPeerList(void);
using RegisterServiceTask = TaskletIn<Interface, &Interface::RegisterService>; using RegisterServiceTask = TaskletIn<Interface, &Interface::RegisterService>;
bool mInitialized : 1; bool mInitialized : 1;
bool mEnabled : 1; bool mEnabled : 1;
bool mFiltered : 1; bool mFiltered : 1;
RegisterServiceTask mRegisterServiceTask; RegisterServiceTask mRegisterServiceTask;
uint16_t mUdpPort; uint16_t mUdpPort;
Packet mRxPacket; Packet mRxPacket;
PeerTable mPeerTable; LinkedList<Peer> mPeerList;
Pool<Peer, kPeerPoolSize> mPeerPool;
}; };
} // namespace Trel } // namespace Trel