diff --git a/src/core/api/trel_api.cpp b/src/core/api/trel_api.cpp index 35ad34b44..779097b25 100644 --- a/src/core/api/trel_api.cpp +++ b/src/core/api/trel_api.cpp @@ -50,17 +50,17 @@ bool otTrelIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().InitIterator(*aIterator); + AsCoreType(aInstance).Get().InitIterator(*aIterator); } const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *aIterator) { - return AsCoreType(aInstance).Get().GetNextPeer(*aIterator); + return AsCoreType(aInstance).Get().GetNextPeer(*aIterator); } uint16_t otTrelGetNumberOfPeers(otInstance *aInstance) { - return AsCoreType(aInstance).Get().GetNumberOfPeers(); + return AsCoreType(aInstance).Get().GetNumberOfPeers(); } void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable) diff --git a/src/core/config/trel.h b/src/core/config/trel.h index e4e04643f..dbd4dea25 100644 --- a/src/core/config/trel.h +++ b/src/core/config/trel.h @@ -43,14 +43,23 @@ * @{ */ +/** + * @def OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE + * + * Define as 1 to allow TREL modules to use heap allocated objects (e.g. for the TREL peer table). + */ +#ifndef OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE +#define OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE 0 +#endif + /** * @def OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE * - * Specifies the capacity of TREL peer table. Only non-zero value - * will be directly used for setting the TREL peer table capacity. - * Zero value lets the size to be determined by the OT stack itself - * which is derived based on other configurations such as a child - * table size, neighbor table size, etc. + * Specifies the capacity of TREL peer table. Only non-zero value will be directly used for setting the TREL peer table + * capacity. Zero value lets the size to be determined by the OT stack itself which is derived based on other + * configurations such as a child table size, neighbor table size, etc. + * + * Applicable when `OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE` is not used. */ #ifndef OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE #define OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE (0) diff --git a/src/core/instance/instance.hpp b/src/core/instance/instance.hpp index 7e9e6e4e2..269fe0b20 100644 --- a/src/core/instance/instance.hpp +++ b/src/core/instance/instance.hpp @@ -799,6 +799,8 @@ template <> inline Mac::SubMac &Instance::Get(void) { return mMac.mLinks.mSubMac template <> inline Trel::Link &Instance::Get(void) { return mMac.mLinks.mTrel; } template <> inline Trel::Interface &Instance::Get(void) { return mMac.mLinks.mTrel.mInterface; } + +template <> inline Trel::PeerTable &Instance::Get(void) { return mMac.mLinks.mTrel.mPeerTable; } #endif #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp index 12f20c089..601617522 100644 --- a/src/core/radio/trel_interface.cpp +++ b/src/core/radio/trel_interface.cpp @@ -102,21 +102,13 @@ void Interface::Disable(void) VerifyOrExit(mInitialized); otPlatTrelDisable(&GetInstance()); - ClearPeerList(); + Get().Clear(); LogDebg("Disabled interface"); exit: return; } -void Interface::ClearPeerList(void) -{ - mPeerList.Clear(); - mPeerPool.FreeAll(); -} - -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); @@ -183,7 +175,7 @@ exit: void Interface::HandleDiscoveredPeerInfo(const PeerInfo &aInfo) { - Peer *entry; + Peer *peer; Mac::ExtAddress extAddress; MeshCoP::ExtendedPanId extPanId; bool isNew = false; @@ -196,9 +188,7 @@ void Interface::HandleDiscoveredPeerInfo(const PeerInfo &aInfo) if (aInfo.IsRemoved()) { - entry = FindPeer(extAddress); - VerifyOrExit(entry != nullptr); - RemovePeerEntry(*entry); + Get().RemoveAndFreeAllMatching(extAddress); ExitNow(); } @@ -208,37 +198,37 @@ void Interface::HandleDiscoveredPeerInfo(const PeerInfo &aInfo) // different Extended MAC address. This ensures that we do not // keep stale entries in the peer table. - entry = mPeerList.FindMatching(aInfo.GetSockAddr()); + peer = Get().FindMatching(aInfo.GetSockAddr()); - if ((entry != nullptr) && !entry->Matches(extAddress)) + if ((peer != nullptr) && !peer->Matches(extAddress)) { - RemovePeerEntry(*entry); - entry = nullptr; + Get().RemoveMatching(aInfo.GetSockAddr()); + peer = nullptr; } - if (entry == nullptr) + if (peer == nullptr) { - entry = mPeerList.FindMatching(extAddress); + peer = Get().FindMatching(extAddress); } - if (entry == nullptr) + if (peer == nullptr) { - entry = GetNewPeerEntry(); - VerifyOrExit(entry != nullptr); + peer = Get().AllocateAndAddNewPeer(); + VerifyOrExit(peer != nullptr); - entry->SetExtAddress(extAddress); + peer->SetExtAddress(extAddress); isNew = true; } if (!isNew) { - VerifyOrExit((entry->GetExtPanId() != extPanId) || (entry->GetSockAddr() != aInfo.GetSockAddr())); + VerifyOrExit((peer->GetExtPanId() != extPanId) || (peer->GetSockAddr() != aInfo.GetSockAddr())); } - entry->SetExtPanId(extPanId); - entry->SetSockAddr(aInfo.GetSockAddr()); + peer->SetExtPanId(extPanId); + peer->SetSockAddr(aInfo.GetSockAddr()); - entry->Log(isNew ? Peer::kAdded : Peer::kUpdated); + peer->Log(isNew ? Peer::kAdded : Peer::kUpdated); exit: return; @@ -294,60 +284,6 @@ exit: return error; } -Peer *Interface::GetNewPeerEntry(void) -{ - Peer *peerEntry; - - peerEntry = mPeerPool.Allocate(); - - if (peerEntry != nullptr) - { - mPeerList.Push(*peerEntry); - ExitNow(); - } - - for (Peer &entry : mPeerList) - { - if (entry.GetExtPanId() != Get().GetExtPanId()) - { - ExitNow(peerEntry = &entry); - } - } - - for (Peer &entry : mPeerList) - { - // We skip over any existing entry in neighbor table (even if the - // entry is in invalid state). - - if (Get().FindNeighbor(entry.GetExtAddress(), Neighbor::kInStateAny) != nullptr) - { - continue; - } - -#if OPENTHREAD_FTD - if (Get().FindRxOnlyNeighborRouter(entry.GetExtAddress()) != nullptr) - { - continue; - } -#endif - - ExitNow(peerEntry = &entry); - } - -exit: - return peerEntry; -} - -void Interface::RemovePeerEntry(Peer &aEntry) -{ - aEntry.Log(Peer::kRemoving); - - if (mPeerList.Remove(aEntry) == kErrorNone) - { - mPeerPool.Free(aEntry); - } -} - const Counters *Interface::GetCounters(void) const { return otPlatTrelGetCounters(&GetInstance()); } void Interface::ResetCounters(void) { otPlatTrelResetCounters(&GetInstance()); } @@ -363,20 +299,20 @@ Error Interface::Send(const Packet &aPacket, bool aIsDiscovery) switch (aPacket.GetHeader().GetType()) { case Header::kTypeBroadcast: - for (Peer &entry : mPeerList) + for (const Peer &peer : Get()) { - if (!aIsDiscovery && (entry.GetExtPanId() != Get().GetExtPanId())) + if (!aIsDiscovery && (peer.GetExtPanId() != Get().GetExtPanId())) { continue; } - otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &entry.mSockAddr); + otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peer.mSockAddr); } break; case Header::kTypeUnicast: case Header::kTypeAck: - peerEntry = mPeerList.FindMatching(aPacket.GetHeader().GetDestination()); + peerEntry = Get().FindMatching(aPacket.GetHeader().GetDestination()); VerifyOrExit(peerEntry != nullptr, error = kErrorAbort); otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peerEntry->mSockAddr); break; @@ -413,30 +349,6 @@ exit: return; } -const Peer *Interface::GetNextPeer(PeerIterator &aIterator) const -{ - const Peer *entry = static_cast(aIterator); - - VerifyOrExit(entry != nullptr); - aIterator = entry->GetNext(); - -exit: - return entry; -} - -uint16_t Interface::GetNumberOfPeers(void) const -{ - uint16_t count = 0; - - for (const Peer &peer : mPeerList) - { - OT_UNUSED_VARIABLE(peer); - count++; - } - - return count; -} - } // namespace Trel } // namespace ot diff --git a/src/core/radio/trel_interface.hpp b/src/core/radio/trel_interface.hpp index 41e2e336b..5b278c86e 100644 --- a/src/core/radio/trel_interface.hpp +++ b/src/core/radio/trel_interface.hpp @@ -79,11 +79,6 @@ class Interface : public InstanceLocator friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo); public: - /** - * Represents an iterator for iterating over TREL peer table entries. - */ - typedef otTrelPeerIterator PeerIterator; - /** * Enables or disables the TREL interface. * @@ -117,29 +112,6 @@ public: */ bool IsEnabled(void) const { return mEnabled; } - /** - * Initializes a peer table iterator. - * - * @param[in] aIterator The iterator to initialize. - */ - void InitIterator(PeerIterator &aIterator) const { aIterator = mPeerList.GetHead(); } - - /** - * Iterates over the peer table entries. - * - * @param[in] aIterator The iterator. MUST be initialized. - * - * @returns A pointer to the next `Peer` entry or `nullptr` if no more entries in the table. - */ - const Peer *GetNextPeer(PeerIterator &aIterator) const; - - /** - * Returns the number of TREL peers. - * - * @returns The number of TREL peers. - */ - uint16_t GetNumberOfPeers(void) const; - /** * Sets the filter mode (enables/disables filtering). * @@ -180,15 +152,6 @@ public: */ uint16_t GetUdpPort(void) const { return mUdpPort; } - /** - * Finds the TREL peer associated with a given Extended Address. - * - * @param[in] aExtAddress The extended address. - * - * @returns The peer associated with @ aExtAddress, or `nullptr` if not found. - */ - Peer *FindPeer(const Mac::ExtAddress &aExtAddress); - /** * Notifies platform that a TREL packet is received from a peer using a different socket address than the one * reported earlier. @@ -227,21 +190,16 @@ private: void HandleReceived(uint8_t *aBuffer, uint16_t aLength, const Ip6::SockAddr &aSenderAddr); void HandleDiscoveredPeerInfo(const PeerInfo &aInfo); - void RegisterService(void); - Peer *GetNewPeerEntry(void); - void RemovePeerEntry(Peer &aEntry); - void ClearPeerList(void); + void RegisterService(void); using RegisterServiceTask = TaskletIn; - bool mInitialized : 1; - bool mEnabled : 1; - bool mFiltered : 1; - RegisterServiceTask mRegisterServiceTask; - uint16_t mUdpPort; - Packet mRxPacket; - LinkedList mPeerList; - Pool mPeerPool; + bool mInitialized : 1; + bool mEnabled : 1; + bool mFiltered : 1; + RegisterServiceTask mRegisterServiceTask; + uint16_t mUdpPort; + Packet mRxPacket; }; } // namespace Trel diff --git a/src/core/radio/trel_link.cpp b/src/core/radio/trel_link.cpp index ed6968150..67d00c565 100644 --- a/src/core/radio/trel_link.cpp +++ b/src/core/radio/trel_link.cpp @@ -50,6 +50,7 @@ Link::Link(Instance &aInstance) , mTxTasklet(aInstance) , mTimer(aInstance) , mInterface(aInstance) + , mPeerTable(aInstance) { ClearAllBytes(mTxFrame); ClearAllBytes(mRxFrame); @@ -343,7 +344,7 @@ void Link::ProcessReceivedPacket(Packet &aPacket, const Ip6::SockAddr &aSockAddr VerifyOrExit(aPacket.GetHeader().GetSource() != Get().GetExtAddress()); mRxPacketSenderAddr = aSockAddr; - mRxPacketPeer = Get().FindPeer(aPacket.GetHeader().GetSource()); + mRxPacketPeer = Get().FindMatching(aPacket.GetHeader().GetSource()); if (type != Header::kTypeBroadcast) { diff --git a/src/core/radio/trel_link.hpp b/src/core/radio/trel_link.hpp index bc787cb2d..e3759687d 100644 --- a/src/core/radio/trel_link.hpp +++ b/src/core/radio/trel_link.hpp @@ -47,6 +47,7 @@ #include "mac/mac_types.hpp" #include "radio/trel_interface.hpp" #include "radio/trel_packet.hpp" +#include "radio/trel_peer.hpp" namespace ot { @@ -199,6 +200,7 @@ private: TxTasklet mTxTasklet; TimeoutTimer mTimer; Interface mInterface; + PeerTable mPeerTable; Ip6::SockAddr mRxPacketSenderAddr; Peer *mRxPacketPeer; Mac::RxFrame mRxFrame; diff --git a/src/core/radio/trel_peer.cpp b/src/core/radio/trel_peer.cpp index 972fe792b..250c276e0 100644 --- a/src/core/radio/trel_peer.cpp +++ b/src/core/radio/trel_peer.cpp @@ -39,7 +39,50 @@ namespace ot { namespace Trel { -RegisterLogModule("TrelInterface"); +RegisterLogModule("TrelPeerTable"); + +//--------------------------------------------------------------------------------------------------------------------- +// Peer + +void Peer::Init(Instance &aInstance) +{ + InstanceLocatorInit::Init(aInstance); + + AsCoreType(&mExtAddress).Clear(); + AsCoreType(&mExtPanId).Clear(); + AsCoreType(&mSockAddr).Clear(); +} + +void Peer::Free(void) +{ + Log(kRemoving); + +#if OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE + Heap::Allocatable::Free(); +#else + this->~Peer(); + Get().mPool.Free(*this); +#endif +} + +bool Peer::Matches(const NonNeighborMatcher &aMatcher) const +{ + // Matches only if the peer is not a neighbor. This is used when + // evicting a peer to make room for a new one, where we search + // for and remove a non-neighbor from the list. + + bool matches = false; + + VerifyOrExit(aMatcher.mNeighborTable.FindNeighbor(GetExtAddress(), Neighbor::kInStateAny) == nullptr); +#if OPENTHREAD_FTD + VerifyOrExit(aMatcher.mNeighborTable.FindRxOnlyNeighborRouter(GetExtAddress()) == nullptr); +#endif + + matches = true; + +exit: + return matches; +} #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) @@ -55,6 +98,7 @@ const char *Peer::ActionToString(Action aAction) "Added", // (0) kAdded "Updated", // (1) kUpdated "Removing", // (2) kRemoving + "Evicting", // (3) kEvicting }; struct EnumCheck @@ -63,6 +107,7 @@ const char *Peer::ActionToString(Action aAction) ValidateNextEnum(kAdded); ValidateNextEnum(kUpdated); ValidateNextEnum(kRemoving); + ValidateNextEnum(kEvicting); }; return kActionStrings[aAction]; @@ -70,6 +115,98 @@ const char *Peer::ActionToString(Action aAction) #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) +//--------------------------------------------------------------------------------------------------------------------- +// PeerTable + +PeerTable::PeerTable(Instance &aInstance) + : InstanceLocator(aInstance) +{ +} + +Peer *PeerTable::AllocatePeer(void) +{ + Peer *newPeer; + +#if OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE + newPeer = Peer::Allocate(); +#else + newPeer = mPool.Allocate(); +#endif + + return newPeer; +} + +Peer *PeerTable::AllocateAndAddNewPeer(void) +{ + Peer *newPeer = nullptr; + + do + { + newPeer = AllocatePeer(); + + if (newPeer != nullptr) + { + break; + } + } while (EvictPeer() == kErrorNone); + + VerifyOrExit(newPeer != nullptr); + + newPeer->Init(GetInstance()); + Push(*newPeer); + +exit: + return newPeer; +} + +Error PeerTable::EvictPeer(void) +{ + Error error = kErrorNotFound; + OwnedPtr peerToEvict; + + // We first try to evict a peer belonging to a different PAN. + // If not found, we evict a non-neighbor peer. + + peerToEvict = RemoveMatching(Peer::OtherExtPanIdMatcher(Get().GetExtPanId())); + + if (peerToEvict == nullptr) + { + peerToEvict = RemoveMatching(Peer::NonNeighborMatcher(Get())); + } + + VerifyOrExit(peerToEvict != nullptr); + + peerToEvict->Log(Peer::kEvicting); + error = kErrorNone; + +exit: + return error; +} + +const Peer *PeerTable::GetNextPeer(PeerIterator &aIterator) const +{ + const Peer *entry = static_cast(aIterator); + + VerifyOrExit(entry != nullptr); + aIterator = entry->GetNext(); + +exit: + return entry; +} + +uint16_t PeerTable::GetNumberOfPeers(void) const +{ + uint16_t count = 0; + + for (const Peer &peer : *this) + { + OT_UNUSED_VARIABLE(peer); + count++; + } + + return count; +} + } // namespace Trel } // namespace ot diff --git a/src/core/radio/trel_peer.hpp b/src/core/radio/trel_peer.hpp index 4b22cdcb1..690aeeb1f 100644 --- a/src/core/radio/trel_peer.hpp +++ b/src/core/radio/trel_peer.hpp @@ -42,25 +42,43 @@ #include #include "common/as_core_type.hpp" -#include "common/linked_list.hpp" +#include "common/heap_allocatable.hpp" +#include "common/locator.hpp" #include "common/log.hpp" #include "common/non_copyable.hpp" +#include "common/owning_list.hpp" +#include "common/pool.hpp" #include "mac/mac_types.hpp" #include "meshcop/extended_panid.hpp" #include "net/socket.hpp" #include "thread/mle_types.hpp" namespace ot { + +class NeighborTable; + namespace Trel { class Interface; +class PeerTable; /** * Represents a discovered TREL peer. */ -class Peer : public otTrelPeer, public LinkedListEntry, private NonCopyable +class Peer : public InstanceLocatorInit, + public otTrelPeer, + public LinkedListEntry, +#if OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE + public Heap::Allocatable, +#endif + private NonCopyable + { friend class Interface; + friend class PeerTable; + friend class OwnedPtr; + friend class OwningList; + friend class LinkedList; friend class LinkedListEntry; public: @@ -118,10 +136,35 @@ private: kAdded, kUpdated, kRemoving, + kEvicting, }; + struct OtherExtPanIdMatcher // Matches if Ext PAN ID is different. + { + explicit OtherExtPanIdMatcher(const MeshCoP::ExtendedPanId &aExtPanId) + : mExtPanId(aExtPanId) + { + } + + const MeshCoP::ExtendedPanId &mExtPanId; + }; + + struct NonNeighborMatcher + { + explicit NonNeighborMatcher(NeighborTable &aNeighborTable) + : mNeighborTable(aNeighborTable) + { + } + + NeighborTable &mNeighborTable; + }; + + void Init(Instance &aInstance); + void Free(void); void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; } void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; } + bool Matches(const OtherExtPanIdMatcher &aMatcher) const { return GetExtPanId() != aMatcher.mExtPanId; } + bool Matches(const NonNeighborMatcher &aMatcher) const; #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) void Log(Action aAction) const; @@ -133,6 +176,84 @@ private: Peer *mNext; }; +//--------------------------------------------------------------------------------------------------------------------- + +/** + * Represents the TREL peer table. + */ +class PeerTable : public InstanceLocator, public OwningList +{ + friend class Peer; + +public: + /** + * Represents an iterator for iterating over TREL peer table entries. + */ + typedef otTrelPeerIterator PeerIterator; + + /** + * Initializes the TREL peer table. + * + * @param[in] aInstance The OpenThread instance. + */ + explicit PeerTable(Instance &aInstance); + + /** + * Allocates a new peer entry and adds it to the table. + * + * This method attempts to allocate a new `Peer`. If successful, the new peer is added to the peer table and + * becomes owned by it. + * + * If the initial allocation fail, the method will then attempt to make space by evicting an existing peer from the + * table. The eviction strategy prioritizes removing a peer associated with a different Extended PAN ID. If no + * such suitable peer is found, a non-neighbor peer will be targeted for eviction. If an existing peer is + * successfully evicted, allocation for the new `Peer` object is re-attempted. + * + * @returns A pointer to the newly allocated and added `Peer`, or `nullptr` if the allocation fails. + */ + Peer *AllocateAndAddNewPeer(void); + + /** + * Initializes a peer table iterator. + * + * @param[in] aIterator The iterator to initialize. + */ + void InitIterator(PeerIterator &aIterator) const { aIterator = GetHead(); } + + /** + * Iterates over the peer table entries. + * + * @param[in] aIterator The iterator. MUST be initialized. + * + * @returns A pointer to the next `Peer` entry or `nullptr` if no more entries in the table. + */ + const Peer *GetNextPeer(PeerIterator &aIterator) const; + + /** + * Returns the number of TREL peers. + * + * @returns The number of TREL peers. + */ + uint16_t GetNumberOfPeers(void) const; + +private: +#if !OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE +#if OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE != 0 + static constexpr uint16_t PoolSize = OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE; +#else + static constexpr uint16_t kExtraEntries = 32; + static constexpr uint16_t PoolSize = Mle::kMaxRouters + Mle::kMaxChildren + kExtraEntries; +#endif +#endif + + Peer *AllocatePeer(void); + Error EvictPeer(void); + +#if !OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE + Pool mPool; +#endif +}; + } // namespace Trel } // namespace ot diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h index 35c007950..a61047805 100644 --- a/tests/toranj/openthread-core-toranj-config-posix.h +++ b/tests/toranj/openthread-core-toranj-config-posix.h @@ -66,7 +66,12 @@ #define OPENTHREAD_POSIX_CONFIG_NAT64_AIL_PREFIX_ENABLE 1 -// Disabled explicitly on posix `toranj` to validate the build with this config +// The following two features (`USE_HEAP`) are disabled explicitly on posix `toranj` +// to validate the build with these config. The `toranj` build under simulation +// platform covers the opposite configs (allows `USE_HEAP`). + #define OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 0 +#define OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE 0 + #endif /* OPENTHREAD_CORE_TORANJ_CONFIG_POSIX_H_ */ diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h index c0f4dc03d..cdb4f3e6a 100644 --- a/tests/toranj/openthread-core-toranj-config-simulation.h +++ b/tests/toranj/openthread-core-toranj-config-simulation.h @@ -87,4 +87,6 @@ #define OPENTHREAD_CONFIG_RADIO_STATS_ENABLE 0 +#define OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE 1 + #endif /* OPENTHREAD_CORE_TORANJ_CONFIG_SIMULATION_H_ */