From 40c7a14b23262487e413f54a578213c301bc96ff Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 11 Aug 2020 10:17:05 -0700 Subject: [PATCH] [mesh-forwarder] simplify 'FragmentPriorityList' (#5374) This commit simplifies management of "Fragment Priority Entries" defining a new class `FragmentPriorityList` with helper method to allocate/find entries in/from the list. The `Entry` types is also moved/defined as a nested type of `FragmentPriorityList`. --- src/core/thread/mesh_forwarder.cpp | 6 +- src/core/thread/mesh_forwarder.hpp | 168 ++++++++----------------- src/core/thread/mesh_forwarder_ftd.cpp | 74 ++++++----- 3 files changed, 94 insertions(+), 154 deletions(-) diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 934456c7e..c1908062c 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -77,7 +77,7 @@ MeshForwarder::MeshForwarder(Instance &aInstance) ResetCounters(); #if OPENTHREAD_FTD - memset(mFragmentEntries, 0, sizeof(mFragmentEntries)); + mFragmentPriorityList.Clear(); #endif } @@ -118,7 +118,7 @@ void MeshForwarder::Stop(void) #if OPENTHREAD_FTD mIndirectSender.Stop(); - memset(mFragmentEntries, 0, sizeof(mFragmentEntries)); + mFragmentPriorityList.Clear(); #endif mEnabled = false; @@ -1103,7 +1103,7 @@ void MeshForwarder::HandleUpdateTimer(void) bool shouldRun = false; #if OPENTHREAD_FTD - shouldRun = UpdateFragmentLifetime(); + shouldRun = mFragmentPriorityList.UpdateOnTimeTick(); #endif if (UpdateReassemblyList() || shouldRun) diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index a2281ac0b..af6af48de 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -36,6 +36,7 @@ #include "openthread-core-config.h" +#include "common/clearable.hpp" #include "common/locator.hpp" #include "common/tasklet.hpp" #include "mac/channel_mask.hpp" @@ -54,11 +55,6 @@ namespace Mle { class DiscoverScanner; } -enum -{ - kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT, -}; - /** * @addtogroup core-mesh-forwarding * @@ -68,103 +64,6 @@ enum * @{ */ -/** - * This class represents an IPv6 fragment priority entry - * - */ -class FragmentPriorityEntry -{ -public: - /** - * This method returns the fragment datagram tag value. - * - * @returns The fragment datagram tag value. - * - */ - uint16_t GetDatagramTag(void) const { return mDatagramTag; } - - /** - * This method sets the fragment datagram tag value. - * - * @param[in] aDatagramTag The fragment datagram tag value. - * - */ - void SetDatagramTag(uint16_t aDatagramTag) { mDatagramTag = aDatagramTag; } - - /** - * This method returns the source Rloc16 of the fragment. - * - * @returns The source Rloc16 value. - * - */ - uint16_t GetSrcRloc16(void) const { return mSrcRloc16; } - - /** - * This method sets the source Rloc16 value of the fragment. - * - * @param[in] aSrcRloc16 The source Rloc16 value. - * - */ - void SetSrcRloc16(uint16_t aSrcRloc16) { mSrcRloc16 = aSrcRloc16; } - - /** - * This method returns the fragment priority value. - * - * @returns The fragment priority value. - * - */ - Message::Priority GetPriority(void) const { return static_cast(mPriority); } - - /** - * This method sets the fragment priority value. - * - * @param[in] aPriority The fragment priority value. - * - */ - void SetPriority(Message::Priority aPriority) { mPriority = aPriority; } - - /** - * This method returns the fragment priority entry's remaining lifetime. - * - * @returns The fragment priority entry's remaining lifetime. - * - */ - uint8_t GetLifetime(void) const { return mLifetime; } - - /** - * This method sets the remaining lifetime of the fragment priority entry. - * - * @param[in] aLifetime The remaining lifetime of the fragment priority entry (in seconds). - * - */ - void SetLifetime(uint8_t aLifetime) - { - if (aLifetime > kMaxLifeTime) - { - aLifetime = kMaxLifeTime; - } - - mLifetime = aLifetime; - } - - /** - * This method decrements the entry lifetime. - * - */ - void DecrementLifetime(void) { mLifetime--; } - -private: - enum - { - kMaxLifeTime = 5, ///< The maximum lifetime of the fragment entry (in seconds). - }; - - uint16_t mSrcRloc16; ///< The source Rloc16 of the datagram. - uint16_t mDatagramTag; ///< The datagram tag of the fragment header. - uint8_t mPriority : 3; ///< The priority level of the first fragment. - uint8_t mLifetime : 3; ///< The lifetime of the entry (in seconds). 0 means the entry is invalid. -}; - /** * This class implements mesh forwarding within Thread. * @@ -318,15 +217,14 @@ public: const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; } #endif private: - enum + enum : uint8_t { - kStateUpdatePeriod = 1000, ///< State update period in milliseconds. + kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT, // Reassembly timeout (in seconds). + }; - /** - * The number of fragment priority entries. - * - */ - kNumFragmentPriorityEntries = OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES, + enum : uint32_t + { + kStateUpdatePeriod = 1000, // State update period in milliseconds. }; enum MessageAction ///< Defines the action parameter in `LogMessageInfo()` method. @@ -339,6 +237,46 @@ private: kMessageEvict, ///< Indicates that the message was evicted. }; +#if OPENTHREAD_FTD + class FragmentPriorityList : public Clearable + { + public: + class Entry : public Clearable + { + friend class FragmentPriorityList; + + public: + Message::Priority GetPriority(void) const { return mPriority; } + bool IsExpired(void) const { return (mLifetime == 0); } + void DecrementLifetime(void) { mLifetime--; } + void ResetLifetime(void) { mLifetime = kReassemblyTimeout; } + + bool Matches(uint16_t aSrcRloc16, uint16_t aTag) const + { + return (mSrcRloc16 == aSrcRloc16) && (mDatagramTag == aTag); + } + + private: + uint16_t mSrcRloc16; + uint16_t mDatagramTag; + Message::Priority mPriority; + uint8_t mLifetime; + }; + + Entry *AllocateEntry(uint16_t aSrcRloc16, uint16_t aTag, Message::Priority aPriority); + Entry *FindEntry(uint16_t aSrcRloc16, uint16_t aTag); + bool UpdateOnTimeTick(void); + + private: + enum : uint16_t + { + kNumEntries = OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES, + }; + + Entry mEntries[kNumEntries]; + }; +#endif // OPENTHREAD_FTD + void SendIcmpErrorIfDstUnreach(const Message & aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest); @@ -400,7 +338,6 @@ private: otError UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage); otError UpdateMeshRoute(Message &aMessage); bool UpdateReassemblyList(void); - bool UpdateFragmentLifetime(void); void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, uint16_t aFragmentLength, uint16_t aSrcRloc16, @@ -415,8 +352,6 @@ private: Neighbor *UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError aError, const Mac::Address &aMacDest); void HandleSentFrame(Mac::TxFrame &aFrame, otError aError); - static void HandleDiscoverTimer(Timer &aTimer); - void HandleDiscoverTimer(void); static void HandleUpdateTimer(Timer &aTimer); void HandleUpdateTimer(void); static void ScheduleTransmissionTask(Tasklet &aTasklet); @@ -436,9 +371,6 @@ private: const Mac::Address &aMeshDest, Message::Priority & aPriority); - FragmentPriorityEntry *FindFragmentPriorityEntry(uint16_t aTag, uint16_t aSrcRloc16); - FragmentPriorityEntry *GetUnusedFragmentPriorityEntry(void); - otError GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest); void PauseMessageTransmissions(void) { mTxPaused = true; } @@ -529,9 +461,9 @@ private: otIpCounters mIpCounters; #if OPENTHREAD_FTD - FragmentPriorityEntry mFragmentEntries[kNumFragmentPriorityEntries]; - PriorityQueue mResolvingQueue; - IndirectSender mIndirectSender; + FragmentPriorityList mFragmentPriorityList; + PriorityQueue mResolvingQueue; + IndirectSender mIndirectSender; #endif DataPollSender mDataPollSender; diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index d9037bc42..9b45349f9 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -726,17 +726,17 @@ exit: return; } -bool MeshForwarder::UpdateFragmentLifetime(void) +bool MeshForwarder::FragmentPriorityList::UpdateOnTimeTick(void) { bool shouldRun = false; - for (FragmentPriorityEntry &entry : mFragmentEntries) + for (Entry &entry : mEntries) { - if (entry.GetLifetime() != 0) + if (!entry.IsExpired()) { entry.DecrementLifetime(); - if (entry.GetLifetime() != 0) + if (!entry.IsExpired()) { shouldRun = true; } @@ -751,46 +751,47 @@ void MeshForwarder::UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHead uint16_t aSrcRloc16, Message::Priority aPriority) { - FragmentPriorityEntry *entry; + FragmentPriorityList::Entry *entry; - if (aFragmentHeader.GetDatagramOffset() == 0) + entry = mFragmentPriorityList.FindEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag()); + + if (entry == nullptr) { - VerifyOrExit((entry = GetUnusedFragmentPriorityEntry()) != nullptr, OT_NOOP); + VerifyOrExit(aFragmentHeader.GetDatagramOffset() == 0, OT_NOOP); - entry->SetDatagramTag(aFragmentHeader.GetDatagramTag()); - entry->SetSrcRloc16(aSrcRloc16); - entry->SetPriority(aPriority); - entry->SetLifetime(kReassemblyTimeout); + entry = mFragmentPriorityList.AllocateEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag(), aPriority); + + VerifyOrExit(entry != nullptr, OT_NOOP); if (!mUpdateTimer.IsRunning()) { mUpdateTimer.Start(kStateUpdatePeriod); } + + ExitNow(); + } + + if (aFragmentHeader.GetDatagramOffset() + aFragmentLength >= aFragmentHeader.GetDatagramSize()) + { + entry->Clear(); } else { - VerifyOrExit((entry = FindFragmentPriorityEntry(aFragmentHeader.GetDatagramTag(), aSrcRloc16)) != nullptr, - OT_NOOP); - - entry->SetLifetime(kReassemblyTimeout); - - if (aFragmentHeader.GetDatagramOffset() + aFragmentLength >= aFragmentHeader.GetDatagramSize()) - { - entry->SetLifetime(0); - } + entry->ResetLifetime(); } exit: return; } -FragmentPriorityEntry *MeshForwarder::FindFragmentPriorityEntry(uint16_t aTag, uint16_t aSrcRloc16) +MeshForwarder::FragmentPriorityList::Entry *MeshForwarder::FragmentPriorityList::FindEntry(uint16_t aSrcRloc16, + uint16_t aTag) { - FragmentPriorityEntry *rval = nullptr; + Entry *rval = nullptr; - for (FragmentPriorityEntry &entry : mFragmentEntries) + for (Entry &entry : mEntries) { - if ((entry.GetLifetime() != 0) && (entry.GetDatagramTag() == aTag) && (entry.GetSrcRloc16() == aSrcRloc16)) + if (!entry.IsExpired() && entry.Matches(aSrcRloc16, aTag)) { rval = &entry; break; @@ -800,30 +801,37 @@ FragmentPriorityEntry *MeshForwarder::FindFragmentPriorityEntry(uint16_t aTag, u return rval; } -FragmentPriorityEntry *MeshForwarder::GetUnusedFragmentPriorityEntry(void) +MeshForwarder::FragmentPriorityList::Entry *MeshForwarder::FragmentPriorityList::AllocateEntry( + uint16_t aSrcRloc16, + uint16_t aTag, + Message::Priority aPriority) { - FragmentPriorityEntry *rval = nullptr; + Entry *newEntry = nullptr; - for (FragmentPriorityEntry &entry : mFragmentEntries) + for (Entry &entry : mEntries) { - if (entry.GetLifetime() == 0) + if (entry.IsExpired()) { - rval = &entry; + entry.mSrcRloc16 = aSrcRloc16; + entry.mDatagramTag = aTag; + entry.mPriority = aPriority; + entry.ResetLifetime(); + newEntry = &entry; break; } } - return rval; + return newEntry; } otError MeshForwarder::GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, uint16_t aSrcRloc16, Message::Priority & aPriority) { - otError error = OT_ERROR_NONE; - FragmentPriorityEntry *entry; + otError error = OT_ERROR_NONE; + FragmentPriorityList::Entry *entry; - entry = FindFragmentPriorityEntry(aFragmentHeader.GetDatagramTag(), aSrcRloc16); + entry = mFragmentPriorityList.FindEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag()); VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND); aPriority = entry->GetPriority();