diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 772613a06..961776849 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -310,7 +310,7 @@ public: * @returns A reference to the resolving queue. * */ - const MessageQueue &GetResolvingQueue(void) const { return mResolvingQueue; } + const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; } #endif private: @@ -519,7 +519,7 @@ private: #if OPENTHREAD_FTD FragmentPriorityEntry mFragmentEntries[kNumFragmentPriorityEntries]; - MessageQueue mResolvingQueue; + PriorityQueue mResolvingQueue; IndirectSender mIndirectSender; #endif diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 60f86bb9f..f67dfc97f 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -184,36 +184,69 @@ void MeshForwarder::HandleResolved(const Ip6::Address &aEid, otError aError) otError MeshForwarder::EvictMessage(uint8_t aPriority) { - otError error = OT_ERROR_NOT_FOUND; - Message *message; + otError error = OT_ERROR_NOT_FOUND; + PriorityQueue *queues[] = {&mResolvingQueue, &mSendQueue}; + Message * evict = NULL; - VerifyOrExit((message = mSendQueue.GetTail()) != NULL); + // search for a lower priority message to evict (choose lowest priority message among all queues) + for (uint8_t index = 0; index < OT_ARRAY_LENGTH(queues); index++) + { + for (uint8_t priority = 0; priority < aPriority; priority++) + { + for (Message *message = queues[index]->GetHeadForPriority(priority); message; message = message->GetNext()) + { + if (message->GetPriority() != priority) + { + break; + } - if (message->GetPriority() < aPriority) + if (message->GetDoNotEvict()) + { + continue; + } + + evict = message; + aPriority = priority; + break; + } + } + } + + if (evict != NULL) { - VerifyOrExit(!message->GetDoNotEvict()); - RemoveMessage(*message); ExitNow(error = OT_ERROR_NONE); } - else + + for (uint8_t priority = aPriority; priority < Message::kNumPriorities; priority++) { - while (aPriority <= Message::kPriorityNet) + // search for an equal or higher priority indirect message to evict + for (Message *message = mSendQueue.GetHeadForPriority(aPriority); message; message = message->GetNext()) { - for (message = mSendQueue.GetHeadForPriority(aPriority); message && (message->GetPriority() == aPriority); - message = message->GetNext()) + if (message->GetPriority() != priority) { - if (message->IsChildPending()) - { - RemoveMessage(*message); - ExitNow(error = OT_ERROR_NONE); - } + break; } - aPriority++; + if (message->GetDoNotEvict()) + { + continue; + } + + if (message->IsChildPending()) + { + evict = message; + ExitNow(error = OT_ERROR_NONE); + } } } exit: + + if (error == OT_ERROR_NONE) + { + RemoveMessage(*evict); + } + return error; }