mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 22:57:47 +00:00
[message-pool] evict indirect message buffers if no available buffers (#2188)
Message buffer allocation can fail if there are no available message buffers. Without a way to evict messages, critical messages (i.e. MLE Advertisements) needed to maintain the Thread network cannot be generated. This commit takes a first step towards evicting queued message buffers. In particular, this commit evicts indirect messages from the head of queue until there are enough available buffers. Future commits will seek to implement fairness and priority mechanisms to better select which messages are evicted from the send queue.
This commit is contained in:
+13
-10
@@ -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<Message *>(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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user