mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 18:07:47 +00:00
[coap] ensure correct dequeue time for entries in response queue (#4686)
This commit changes the handling of timer for CoAP response queue to ensure that correct dequeue time is used. The existing code assumed that entries in the queue would be in order of their dequeue time (due to exchange lifetime being fixed). With the addition of configurable CoAP tx parameters feature, this is no longer valid. This commit changes the code to restart the timer with the earliest dequeue time. Also when evicting a message from the queue (due to the number of entries reaching the max limit of `kMaxCachedResponses`) we now search and find the message with earliest dequeue time to remove (instead of removing the entry at the head of queue).
This commit is contained in:
committed by
Jonathan Hui
parent
1d463868d9
commit
bf1cf97b0f
+53
-46
@@ -834,44 +834,58 @@ void ResponsesQueue::EnqueueResponse(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const TxParameters & aTxParameters)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * responseCopy = NULL;
|
||||
uint16_t messageCount;
|
||||
uint16_t bufferCount;
|
||||
uint32_t exchangeLifetime = aTxParameters.CalculateExchangeLifetime();
|
||||
Message * responseCopy;
|
||||
ResponseMetadata metadata;
|
||||
|
||||
metadata.mDequeueTime = TimerMilli::GetNow() + exchangeLifetime;
|
||||
metadata.mDequeueTime = TimerMilli::GetNow() + aTxParameters.CalculateExchangeLifetime();
|
||||
metadata.mMessageInfo = aMessageInfo;
|
||||
|
||||
// Return success if matched response already exists in the cache.
|
||||
VerifyOrExit(FindMatchedResponse(aMessage, aMessageInfo) == NULL);
|
||||
|
||||
mQueue.GetInfo(messageCount, bufferCount);
|
||||
|
||||
if (messageCount >= kMaxCachedResponses)
|
||||
{
|
||||
DequeueOldestResponse();
|
||||
}
|
||||
UpdateQueue();
|
||||
|
||||
VerifyOrExit((responseCopy = aMessage.Clone()) != NULL);
|
||||
|
||||
SuccessOrExit(error = metadata.AppendTo(*responseCopy));
|
||||
VerifyOrExit(metadata.AppendTo(*responseCopy) == OT_ERROR_NONE, responseCopy->Free());
|
||||
|
||||
mQueue.Enqueue(*responseCopy);
|
||||
|
||||
if (!mTimer.IsRunning())
|
||||
{
|
||||
mTimer.Start(exchangeLifetime);
|
||||
}
|
||||
mTimer.FireAtIfEarlier(metadata.mDequeueTime);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != OT_ERROR_NONE && responseCopy != NULL)
|
||||
void ResponsesQueue::UpdateQueue(void)
|
||||
{
|
||||
uint16_t msgCount = 0;
|
||||
Message * earliestMsg = NULL;
|
||||
TimeMilli earliestDequeueTime(0);
|
||||
|
||||
// Check the number of messages in the queue and if number is at
|
||||
// `kMaxCachedResponses` remove the one with earliest dequeue
|
||||
// time.
|
||||
|
||||
for (Message *message = static_cast<Message *>(mQueue.GetHead()); message != NULL;
|
||||
message = static_cast<Message *>(message->GetNext()))
|
||||
{
|
||||
responseCopy->Free();
|
||||
ResponseMetadata metadata;
|
||||
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if ((earliestMsg == NULL) || (metadata.mDequeueTime < earliestDequeueTime))
|
||||
{
|
||||
earliestMsg = message;
|
||||
earliestDequeueTime = metadata.mDequeueTime;
|
||||
}
|
||||
|
||||
msgCount++;
|
||||
}
|
||||
|
||||
return;
|
||||
if (msgCount >= kMaxCachedResponses)
|
||||
{
|
||||
DequeueResponse(*earliestMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void ResponsesQueue::DequeueResponse(Message &aMessage)
|
||||
@@ -880,17 +894,6 @@ void ResponsesQueue::DequeueResponse(Message &aMessage)
|
||||
aMessage.Free();
|
||||
}
|
||||
|
||||
void ResponsesQueue::DequeueOldestResponse(void)
|
||||
{
|
||||
Message *message;
|
||||
|
||||
VerifyOrExit((message = static_cast<Message *>(mQueue.GetHead())) != NULL);
|
||||
DequeueResponse(*message);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void ResponsesQueue::DequeueAllResponses(void)
|
||||
{
|
||||
Message *message;
|
||||
@@ -908,23 +911,34 @@ void ResponsesQueue::HandleTimer(Timer &aTimer)
|
||||
|
||||
void ResponsesQueue::HandleTimer(void)
|
||||
{
|
||||
Message * message;
|
||||
ResponseMetadata metadata;
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
TimeMilli nextDequeueTime = now.GetDistantFuture();
|
||||
Message * nextMessage;
|
||||
|
||||
while ((message = static_cast<Message *>(mQueue.GetHead())) != NULL)
|
||||
for (Message *message = static_cast<Message *>(mQueue.GetHead()); message != NULL; message = nextMessage)
|
||||
{
|
||||
ResponseMetadata metadata;
|
||||
|
||||
nextMessage = static_cast<Message *>(message->GetNext());
|
||||
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if (TimerMilli::GetNow() >= metadata.mDequeueTime)
|
||||
if (now >= metadata.mDequeueTime)
|
||||
{
|
||||
DequeueResponse(*message);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
if (metadata.mDequeueTime < nextDequeueTime)
|
||||
{
|
||||
mTimer.Start(metadata.GetRemainingTime());
|
||||
break;
|
||||
nextDequeueTime = metadata.mDequeueTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextDequeueTime < now.GetDistantFuture())
|
||||
{
|
||||
mTimer.FireAt(nextDequeueTime);
|
||||
}
|
||||
}
|
||||
|
||||
void ResponsesQueue::ResponseMetadata::ReadFrom(const Message &aMessage)
|
||||
@@ -935,13 +949,6 @@ void ResponsesQueue::ResponseMetadata::ReadFrom(const Message &aMessage)
|
||||
aMessage.Read(length - sizeof(*this), sizeof(*this), this);
|
||||
}
|
||||
|
||||
uint32_t ResponsesQueue::ResponseMetadata::GetRemainingTime(void) const
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
|
||||
return (mDequeueTime > now) ? mDequeueTime - now : 0;
|
||||
}
|
||||
|
||||
/// Return product of @p aValueA and @p aValueB if no overflow otherwise 0.
|
||||
static uint32_t Multiply(uint32_t aValueA, uint32_t aValueB)
|
||||
{
|
||||
|
||||
@@ -210,12 +210,6 @@ public:
|
||||
*/
|
||||
void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const TxParameters &aTxParameters);
|
||||
|
||||
/**
|
||||
* This method removes the oldest response from the cache.
|
||||
*
|
||||
*/
|
||||
void DequeueOldestResponse(void);
|
||||
|
||||
/**
|
||||
* This method removes all responses from the cache.
|
||||
*
|
||||
@@ -252,9 +246,8 @@ private:
|
||||
|
||||
struct ResponseMetadata
|
||||
{
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
void ReadFrom(const Message &aMessage);
|
||||
uint32_t GetRemainingTime(void) const;
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
void ReadFrom(const Message &aMessage);
|
||||
|
||||
TimeMilli mDequeueTime;
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
@@ -262,6 +255,7 @@ private:
|
||||
|
||||
const Message *FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const;
|
||||
void DequeueResponse(Message &aMessage);
|
||||
void UpdateQueue(void);
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
Reference in New Issue
Block a user