mirror of
https://github.com/espressif/openthread.git
synced 2026-09-16 22:20:07 +00:00
Clean up indirect messages when a child is removed. (#941)
This commit is contained in:
@@ -181,6 +181,46 @@ void MeshForwarder::ScheduleTransmissionTask(void *aContext)
|
||||
static_cast<MeshForwarder *>(aContext)->ScheduleTransmissionTask();
|
||||
}
|
||||
|
||||
void MeshForwarder::UpdateIndirectMessages(void)
|
||||
{
|
||||
Child *children;
|
||||
uint8_t numChildren;
|
||||
|
||||
VerifyOrExit(mSendBusy == false,);
|
||||
|
||||
children = mMle.GetChildren(&numChildren);
|
||||
|
||||
for (uint8_t i = 0; i < numChildren; i++)
|
||||
{
|
||||
Child *child = &children[i];
|
||||
Message *nextMessage;
|
||||
|
||||
if (child->mState == Child::kStateValid || child->mQueuedIndirectMessageCnt == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Message *message = mSendQueue.GetHead(); message; message = nextMessage)
|
||||
{
|
||||
nextMessage = message->GetNext();
|
||||
|
||||
message->ClearChildMask(i);
|
||||
|
||||
if (!message->IsChildPending())
|
||||
{
|
||||
mSendQueue.Dequeue(*message);
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
child->mQueuedIndirectMessageCnt = 0;
|
||||
ClearSrcMatchEntry(*child);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MeshForwarder::ScheduleTransmissionTask()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -189,6 +229,8 @@ void MeshForwarder::ScheduleTransmissionTask()
|
||||
|
||||
VerifyOrExit(mSendBusy == false, error = kThreadError_Busy);
|
||||
|
||||
UpdateIndirectMessages();
|
||||
|
||||
children = mMle.GetChildren(&numChildren);
|
||||
|
||||
for (int i = 0; i < numChildren; i++)
|
||||
|
||||
@@ -171,6 +171,12 @@ public:
|
||||
*/
|
||||
void SetDiscoverParameters(uint32_t aScanChannels, uint16_t aScanDuration);
|
||||
|
||||
/**
|
||||
* This method frees any indirect messages queued for children that are no longer attached.
|
||||
*
|
||||
*/
|
||||
void UpdateIndirectMessages(void);
|
||||
|
||||
/**
|
||||
* This method returns a reference to the send queue.
|
||||
*
|
||||
|
||||
@@ -62,6 +62,7 @@ enum
|
||||
kParentResponseMaxDelayRouters = 500, ///< Maximum delay for response for Parent Request sent to routers only
|
||||
kParentResponseMaxDelayAll = 1000, ///< Maximum delay for response for Parent Request sent to all devices
|
||||
kMaxResponseDelay = 1000, ///< Maximum delay before responding to a multicast request
|
||||
kMaxChildIdRequestTimeout = 5000, ///< Maximum delay for receiving a Child ID Request
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -1701,12 +1701,28 @@ void MleRouter::HandleStateUpdateTimer(void)
|
||||
// update children state
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
if (mChildren[i].mState == Neighbor::kStateInvalid)
|
||||
uint32_t timeout = 0;
|
||||
|
||||
switch (mChildren[i].mState)
|
||||
{
|
||||
case Neighbor::kStateInvalid:
|
||||
case Neighbor::kStateChildIdRequest:
|
||||
continue;
|
||||
|
||||
case Neighbor::kStateParentRequest:
|
||||
timeout = kMaxChildIdRequestTimeout;
|
||||
break;
|
||||
|
||||
case Neighbor::kStateValid:
|
||||
timeout = Timer::SecToMsec(mChildren[i].mTimeout);
|
||||
break;
|
||||
|
||||
case Neighbor::kStateLinkRequest:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Timer::GetNow() - mChildren[i].mLastHeard) >= Timer::SecToMsec(mChildren[i].mTimeout))
|
||||
if ((Timer::GetNow() - mChildren[i].mLastHeard) >= timeout)
|
||||
{
|
||||
RemoveNeighbor(mChildren[i]);
|
||||
}
|
||||
@@ -2565,6 +2581,7 @@ ThreadError MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
|
||||
case kDeviceStateLeader:
|
||||
if (aNeighbor.mState == Neighbor::kStateValid && !IsActiveRouter(aNeighbor.mValid.mRloc16))
|
||||
{
|
||||
mMesh.UpdateIndirectMessages();
|
||||
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_REMOVED);
|
||||
mNetworkData.SendServerDataNotification(aNeighbor.mValid.mRloc16);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user