diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index c191c1191..65cabe99d 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -37,6 +37,7 @@ #include "message.hpp" +#include "openthread-instance.h" #include "common/code_utils.hpp" #include "common/debug.hpp" #include "common/logging.hpp" @@ -70,6 +71,8 @@ Message *MessagePool::New(uint8_t aType, uint16_t aReserved) { Message *message = NULL; + SuccessOrExit(ReclaimBuffers(1)); + VerifyOrExit((message = static_cast(NewBuffer())) != NULL); memset(message, 0, sizeof(*message)); @@ -146,18 +149,18 @@ void MessagePool::FreeBuffers(Buffer *aBuffer) otError MessagePool::ReclaimBuffers(int aNumBuffers) { - uint16_t numFreeBuffers; + while (aNumBuffers > GetFreeBufferCount()) + { + MeshForwarder &meshForwarder = GetInstance().mThreadNetif.GetMeshForwarder(); + SuccessOrExit(meshForwarder.EvictIndirectMessage()); + } -#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT - numFreeBuffers = otPlatMessagePoolNumFreeBuffers(&GetInstance()); -#else - numFreeBuffers = mNumFreeBuffers; -#endif +exit: - //First comparison is to get around issues with comparing - //signed and unsigned numbers, if aNumBuffers is negative then - //the second comparison wont be attempted. - if (aNumBuffers < 0 || aNumBuffers <= numFreeBuffers) + // First comparison is to get around issues with comparing + // signed and unsigned numbers, if aNumBuffers is negative then + // the second comparison wont be attempted. + if (aNumBuffers < 0 || aNumBuffers <= GetFreeBufferCount()) { return OT_ERROR_NONE; } diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 066f54a11..deafbc2bf 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -237,6 +237,55 @@ void MeshForwarder::UpdateIndirectMessages(void) } } +otError MeshForwarder::EvictIndirectMessage(void) +{ + otError error = OT_ERROR_NOT_FOUND; + + for (Message *message = mSendQueue.GetHead(); message; message = message->GetNext()) + { + if (!message->IsChildPending()) + { + continue; + } + + RemoveMessage(*message); + ExitNow(error = OT_ERROR_NONE); + } + +exit: + return error; +} + +void MeshForwarder::RemoveMessage(Message &aMessage) +{ + Child *children; + uint8_t numChildren; + + children = GetNetif().GetMle().GetChildren(&numChildren); + + for (uint8_t i = 0; i < numChildren; i++) + { + if (aMessage.GetChildMask(i)) + { + aMessage.ClearChildMask(i); + mSourceMatchController.DecrementMessageCount(children[i]); + + if (children[i].GetIndirectMessage() == &aMessage) + { + children[i].SetIndirectMessage(NULL); + } + } + } + + if (mSendMessage == &aMessage) + { + mSendMessage = NULL; + } + + mSendQueue.Dequeue(aMessage); + aMessage.Free(); +} + void MeshForwarder::RemoveMessages(Child &aChild, uint8_t aSubType) { ThreadNetif &netif = GetNetif(); diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 76585a517..545fe4acc 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -173,6 +173,15 @@ public: */ void RemoveMessages(Child &aChild, uint8_t aSubType); + /** + * This method evicts the first indirect message in the indirect send queue. + * + * @retval OT_ERROR_NONE Successfully evicted an indirect message. + * @retval OT_ERROR_NOT_FOUND No indirect messages available to evict. + * + */ + otError EvictIndirectMessage(void); + /** * This method returns a reference to the send queue. * @@ -281,6 +290,7 @@ private: otError HandleDatagram(Message &aMessage, const otThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource); void ClearReassemblyList(void); + void RemoveMessage(Message &aMessage); static void HandleReceivedFrame(Mac::Receiver &aReceiver, Mac::Frame &aFrame); void HandleReceivedFrame(Mac::Frame &aFrame);