[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.
*/
#define OPENTHREAD_API_VERSION (504)
#define OPENTHREAD_API_VERSION (505)
/**
* @addtogroup api-instance

View File

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

View File

@ -102,18 +102,21 @@ void Interface::Disable(void)
VerifyOrExit(mInitialized);
otPlatTrelDisable(&GetInstance());
mPeerTable.Clear();
ClearPeerList();
LogDebg("Disabled interface");
exit:
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)
{
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
// keep stale entries in the peer table.
entry = mPeerTable.FindMatching(aInfo.GetSockAddr());
entry = mPeerList.FindMatching(aInfo.GetSockAddr());
if ((entry != nullptr) && !entry->Matches(extAddress))
{
@ -215,7 +218,7 @@ void Interface::HandleDiscoveredPeerInfo(const Peer::Info &aInfo)
if (entry == nullptr)
{
entry = mPeerTable.FindMatching(extAddress);
entry = mPeerList.FindMatching(extAddress);
}
if (entry == nullptr)
@ -297,10 +300,15 @@ Interface::Peer *Interface::GetNewPeerEntry(void)
{
Peer *peerEntry;
peerEntry = mPeerTable.PushBack();
VerifyOrExit(peerEntry == nullptr);
peerEntry = mPeerPool.Allocate();
for (Peer &entry : mPeerTable)
if (peerEntry != nullptr)
{
mPeerList.Push(*peerEntry);
ExitNow();
}
for (Peer &entry : mPeerList)
{
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
// entry is in invalid state).
@ -336,15 +344,10 @@ void Interface::RemovePeerEntry(Peer &aEntry)
{
aEntry.Log("Removing");
// Replace the entry being removed with the last entry (if not the
// last one already) and then pop the last entry from array.
if (&aEntry != mPeerTable.Back())
if (mPeerList.Remove(aEntry) == kErrorNone)
{
aEntry = *mPeerTable.Back();
mPeerPool.Free(aEntry);
}
mPeerTable.PopBack();
}
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())
{
case Header::kTypeBroadcast:
for (Peer &entry : mPeerTable)
for (Peer &entry : mPeerList)
{
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::kTypeAck:
peerEntry = mPeerTable.FindMatching(aPacket.GetHeader().GetDestination());
peerEntry = mPeerList.FindMatching(aPacket.GetHeader().GetDestination());
VerifyOrExit(peerEntry != nullptr, error = kErrorAbort);
otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peerEntry->mSockAddr);
break;
@ -414,14 +417,26 @@ exit:
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

View File

@ -41,8 +41,9 @@
#include <openthread/trel.h>
#include <openthread/platform/trel.h>
#include "common/array.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/pool.hpp"
#include "common/tasklet.hpp"
#include "common/time.hpp"
#include "mac/mac_types.hpp"
@ -83,9 +84,10 @@ public:
/**
* Represents information about a discovered TREL peer.
*/
class Peer : public otTrelPeer
class Peer : public otTrelPeer, public LinkedListEntry<Peer>
{
friend class Interface;
friend class LinkedListEntry<Peer>;
friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
public:
@ -153,6 +155,8 @@ public:
void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; }
void Log(const char *aAction) const;
Peer *mNext;
};
/**
@ -198,7 +202,7 @@ public:
*
* @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.
@ -214,7 +218,7 @@ public:
*
* @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).
@ -276,16 +280,14 @@ public:
private:
#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
static constexpr uint16_t kPeerTableExtraEntries = 32;
static constexpr uint16_t kPeerTableSize = Mle::kMaxRouters + Mle::kMaxChildren + kPeerTableExtraEntries;
static constexpr uint16_t kExtraEntries = 32;
static constexpr uint16_t kPeerPoolSize = Mle::kMaxRouters + Mle::kMaxChildren + kExtraEntries;
#endif
static const char kTxtRecordExtAddressKey[];
static const char kTxtRecordExtPanIdKey[];
typedef Array<Peer, kPeerTableSize, uint16_t> PeerTable;
explicit Interface(Instance &aInstance);
// Methods used by `Trel::Link`.
@ -304,16 +306,18 @@ private:
MeshCoP::ExtendedPanId &aExtPanId) const;
Peer *GetNewPeerEntry(void);
void RemovePeerEntry(Peer &aEntry);
void ClearPeerList(void);
using RegisterServiceTask = TaskletIn<Interface, &Interface::RegisterService>;
bool mInitialized : 1;
bool mEnabled : 1;
bool mFiltered : 1;
RegisterServiceTask mRegisterServiceTask;
uint16_t mUdpPort;
Packet mRxPacket;
PeerTable mPeerTable;
bool mInitialized : 1;
bool mEnabled : 1;
bool mFiltered : 1;
RegisterServiceTask mRegisterServiceTask;
uint16_t mUdpPort;
Packet mRxPacket;
LinkedList<Peer> mPeerList;
Pool<Peer, kPeerPoolSize> mPeerPool;
};
} // namespace Trel