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:
Abtin Keshavarzian
2017-03-23 21:40:36 -07:00
committed by Jonathan Hui
parent 662e8f4f72
commit 5bd141b1ec
2 changed files with 38 additions and 1 deletions
+37 -1
View File
@@ -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();
+1
View File
@@ -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);