mirror of
https://github.com/espressif/openthread.git
synced 2026-09-11 19:50:05 +00:00
MeshForwarder: Ensure to re-assemble one message at a time on a SED (#1509)
This commit makes two changes in how the re-assembly list for fragmented messages is updated for a sleepy end-device (SED). It ensures that we re-assemble only one message at a time on a SED. If a new (secure) first fragment is received we clear any remaining fragments in reassembly list. Also, if we receive a new (secure) next fragment with a non-matching fragmentation offset or tag, it indicates that we have either missed a fragment, or that the parent has moved to a new message with a new tag. In either case, we then safely clear any earlier fragments stored in the reassembly list. This change ensures that the buffers are freed more quickly.
This commit is contained in:
committed by
Jonathan Hui
parent
662e8f4f72
commit
5bd141b1ec
@@ -887,7 +887,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MeshForwarder::SetRxOff()
|
||||
void MeshForwarder::SetRxOff(void)
|
||||
{
|
||||
mNetif.GetMac().SetRxOnWhenIdle(false);
|
||||
|
||||
@@ -2061,6 +2061,15 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
// Security Check
|
||||
VerifyOrExit(mNetif.GetIp6Filter().Accept(*message), error = kThreadError_Drop);
|
||||
|
||||
// Allow re-assembly of only one message at a time on a SED by clearing
|
||||
// any remaining fragments in reassembly list upon receiving of a new
|
||||
// (secure) first fragment.
|
||||
|
||||
if ((GetRxOnWhenIdle() == false) && message->IsLinkSecurityEnabled())
|
||||
{
|
||||
ClearReassemblyList();
|
||||
}
|
||||
|
||||
mReassemblyList.Enqueue(*message);
|
||||
|
||||
if (!mReassemblyTimer.IsRunning())
|
||||
@@ -2085,6 +2094,20 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
}
|
||||
}
|
||||
|
||||
// For a sleepy-end-device, if we receive a new (secure) next fragment
|
||||
// with a non-matching fragmentation offset or tag, it indicates that
|
||||
// we have either missed a fragment, or the parent has moved to a new
|
||||
// message with a new tag. In either case, we can safely clear any
|
||||
// remaining fragments stored in the reassembly list.
|
||||
|
||||
if (GetRxOnWhenIdle() == false)
|
||||
{
|
||||
if ((message == NULL) && (aMessageInfo.mLinkSecurity))
|
||||
{
|
||||
ClearReassemblyList();
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(message != NULL, error = kThreadError_Drop);
|
||||
|
||||
// copy Fragment
|
||||
@@ -2113,6 +2136,19 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
void MeshForwarder::ClearReassemblyList(void)
|
||||
{
|
||||
Message *message;
|
||||
Message *next;
|
||||
|
||||
for (message = mReassemblyList.GetHead(); message; message = next)
|
||||
{
|
||||
next = message->GetNext();
|
||||
mReassemblyList.Dequeue(*message);
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleReassemblyTimer(void *aContext)
|
||||
{
|
||||
static_cast<MeshForwarder *>(aContext)->HandleReassemblyTimer();
|
||||
|
||||
@@ -302,6 +302,7 @@ private:
|
||||
ThreadError UpdateIp6Route(Message &aMessage);
|
||||
ThreadError UpdateMeshRoute(Message &aMessage);
|
||||
ThreadError HandleDatagram(Message &aMessage, const ThreadMessageInfo &aMessageInfo);
|
||||
void ClearReassemblyList(void);
|
||||
|
||||
static void HandleReceivedFrame(void *aContext, Mac::Frame &aFrame);
|
||||
void HandleReceivedFrame(Mac::Frame &aFrame);
|
||||
|
||||
Reference in New Issue
Block a user