[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`.
This commit is contained in:
Abtin Keshavarzian
2020-08-11 10:17:05 -07:00
committed by GitHub
parent 9af8fe8cc5
commit 40c7a14b23
3 changed files with 94 additions and 154 deletions
+3 -3
View File
@@ -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)
+50 -118
View File
@@ -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<Message::Priority>(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<FragmentPriorityList>
{
public:
class Entry : public Clearable<Entry>
{
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;
+41 -33
View File
@@ -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();