[mle] do not remove child on receiving an MLE parent request. (#1968)

MLE Parent Request messages may be sent by an existing child that is
searching for parents or trying to reattach.  Simply receiving an MLE
Parent Request message should not result in Router(s) flushing any
existing state and associated messages for the Child.

This commit makes the following changes:

- RemoveNeighbor() is no longer called from HandleParentRequest.

- MLE Parent Response messages are explicitly marked for direct
  transmission.

- A new method MeshForwarder::RemoveMessages() is introduced to remove
  all messages (direct and indirect) matching a particular sub-type for
  a given child.

- All queued MLE messages are removed for a given child upon receiving
  an MLE Child ID Request message.

- No queued data messages for a given child are removed.
This commit is contained in:
Jonathan Hui
2017-07-11 10:27:15 -07:00
committed by GitHub
parent 92b0ddca0a
commit 274ec794b7
3 changed files with 89 additions and 8 deletions
+73
View File
@@ -237,6 +237,79 @@ void MeshForwarder::UpdateIndirectMessages(void)
}
}
void MeshForwarder::RemoveMessages(Child &aChild, uint8_t aSubType)
{
ThreadNetif &netif = GetNetif();
Message *nextMessage;
for (Message *message = mSendQueue.GetHead(); message; message = nextMessage)
{
uint8_t childIndex = netif.GetMle().GetChildIndex(aChild);
nextMessage = message->GetNext();
if ((aSubType != Message::kSubTypeNone) && (aSubType != message->GetSubType()))
{
continue;
}
if (message->GetChildMask(childIndex))
{
message->ClearChildMask(childIndex);
mSourceMatchController.DecrementMessageCount(aChild);
}
else
{
switch (message->GetType())
{
case Message::kTypeIp6:
{
Ip6::Header ip6header;
IgnoreReturnValue(message->Read(0, sizeof(ip6header), &ip6header));
if (&aChild == static_cast<Child *>(netif.GetMle().GetNeighbor(ip6header.GetDestination())))
{
message->ClearDirectTransmission();
}
break;
}
case Message::kType6lowpan:
{
Lowpan::MeshHeader meshHeader;
IgnoreReturnValue(meshHeader.Init(*message));
if (&aChild == static_cast<Child *>(netif.GetMle().GetNeighbor(meshHeader.GetDestination())))
{
message->ClearDirectTransmission();
}
break;
}
default:
{
break;
}
}
}
if (!message->IsChildPending() && !message->GetDirectTransmission())
{
if (mSendMessage == message)
{
mSendMessage = NULL;
}
mSendQueue.Dequeue(*message);
message->Free();
}
}
}
void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
{
GetOwner(aTasklet).ScheduleTransmissionTask();
+10
View File
@@ -164,6 +164,16 @@ public:
*/
void UpdateIndirectMessages(void);
/**
* This method frees any messages queued for an existing child.
*
* @param[in] aChild A reference to the child.
* @param[in] aSubType The message sub-type to remove.
* Use Message::kSubTypeNone remove all messages for @p aChild.
*
*/
void RemoveMessages(Child &aChild, uint8_t aSubType);
/**
* This method returns a reference to the send queue.
*
+6 -8
View File
@@ -1706,13 +1706,6 @@ otError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::Messa
child = FindChild(macAddr);
if (child != NULL && !child->IsFullThreadDevice())
{
// Parent Request from a MTD child means that the child had detached. It can be safely removed.
RemoveNeighbor(*child);
child = NULL;
}
if (child == NULL)
{
VerifyOrExit((child = NewChild()) != NULL);
@@ -1919,6 +1912,8 @@ otError MleRouter::SendParentResponse(Child *aChild, const ChallengeTlv &challen
uint16_t delay;
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
message->SetDirectTransmission();
SuccessOrExit(error = AppendHeader(*message, Header::kCommandParentResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
@@ -2084,6 +2079,10 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
memcmp(response.GetResponse(), child->GetChallenge(), child->GetChallengeSize()) == 0,
error = OT_ERROR_SECURITY);
// Remove existing MLE messages
netif.GetMeshForwarder().RemoveMessages(*child, Message::kSubTypeMleGeneral);
netif.GetMeshForwarder().RemoveMessages(*child, Message::kSubTypeMleChildUpdateRequest);
// Link-Layer Frame Counter
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter),
linkFrameCounter));
@@ -2163,7 +2162,6 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
}
}
child->SetLastHeard(TimerMilli::GetNow());
child->SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
child->SetMleFrameCounter(mleFrameCounter.GetFrameCounter());