[network-data] deregister for invalid child on new network data (#4485)

This commit is contained in:
Rongli Sun
2020-02-24 13:13:01 -08:00
committed by Jonathan Hui
parent 2bc32a36d1
commit b2a845947e
3 changed files with 134 additions and 0 deletions
+18
View File
@@ -2606,6 +2606,24 @@ void MleRouter::HandleNetworkDataUpdateRouter(void)
SynchronizeChildNetworkData();
// Detect if any server entry with invalid child RLOC16
{
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
uint16_t rloc16 = Mac::kShortAddrInvalid;
while (Get<NetworkData::Leader>().GetNextServer(iterator, rloc16) == OT_ERROR_NONE)
{
if (!IsActiveRouter(rloc16) && RouterIdMatch(GetRloc16(), rloc16) &&
mChildTable.FindChild(rloc16, Child::kInStateValid) == NULL)
{
Get<NetworkData::Leader>().SendServerDataNotification(rloc16);
// In Thread 1.1 Specification 5.15.6.1, only one RLOC16 TLV entry may appear in SRV_DATA.ntf.
// So break here.
break;
}
}
}
exit:
return;
}
+104
View File
@@ -1036,6 +1036,110 @@ exit:
return error;
}
otError NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16)
{
otError error = OT_ERROR_NOT_FOUND;
NetworkDataIterator iterator(aIterator);
NetworkDataTlv * cur = reinterpret_cast<NetworkDataTlv *>(mTlvs + iterator.GetTlvOffset());
NetworkDataTlv * end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
for (; cur < end; cur = cur->GetNext(), iterator.SetSubTlvOffset(0), iterator.SetEntryIndex(0))
{
NetworkDataTlv *subCur;
NetworkDataTlv *subEnd;
VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);
switch (cur->GetType())
{
case NetworkDataTlv::kTypePrefix:
{
PrefixTlv *prefix = static_cast<PrefixTlv *>(cur);
subCur = reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(prefix->GetSubTlvs()) +
iterator.GetSubTlvOffset());
subEnd = cur->GetNext();
for (; subCur < subEnd; subCur = subCur->GetNext(), iterator.SetEntryIndex(0))
{
VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE);
if (subCur->GetType() == NetworkDataTlv::kTypeBorderRouter)
{
BorderRouterTlv *borderRouter = static_cast<BorderRouterTlv *>(subCur);
uint8_t index = iterator.GetEntryIndex();
if (index < borderRouter->GetNumEntries())
{
aRloc16 = borderRouter->GetEntry(index)->GetRloc();
iterator.SaveTlvOffset(cur, mTlvs);
iterator.SaveSubTlvOffset(subCur, prefix->GetSubTlvs());
iterator.SetEntryIndex(index + 1);
ExitNow(error = OT_ERROR_NONE);
}
}
else if (subCur->GetType() == NetworkDataTlv::kTypeHasRoute)
{
HasRouteTlv *hasRoute = static_cast<HasRouteTlv *>(subCur);
uint8_t index = iterator.GetEntryIndex();
if (index < hasRoute->GetNumEntries())
{
aRloc16 = hasRoute->GetEntry(index)->GetRloc();
iterator.SaveTlvOffset(cur, mTlvs);
iterator.SaveSubTlvOffset(subCur, prefix->GetSubTlvs());
iterator.SetEntryIndex(index + 1);
ExitNow(error = OT_ERROR_NONE);
}
}
}
break;
}
case NetworkDataTlv::kTypeService:
{
ServiceTlv *service = static_cast<ServiceTlv *>(cur);
subCur = reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(service->GetSubTlvs()) +
iterator.GetSubTlvOffset());
subEnd = cur->GetNext();
for (; subCur < subEnd; subCur = subCur->GetNext())
{
VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE);
if (subCur->GetType() == NetworkDataTlv::kTypeServer)
{
ServerTlv *server = static_cast<ServerTlv *>(subCur);
aRloc16 = server->GetServer16();
if (subCur->GetNext() >= cur->GetNext())
{
iterator.SaveTlvOffset(cur->GetNext(), mTlvs);
iterator.SetSubTlvOffset(0);
}
else
{
iterator.SaveTlvOffset(cur, mTlvs);
iterator.SaveSubTlvOffset(subCur->GetNext(), service->GetSubTlvs());
}
ExitNow(error = OT_ERROR_NONE);
}
}
break;
}
default:
break;
}
}
exit:
return error;
}
void NetworkData::ClearResubmitDelayTimer(void)
{
mLastAttempt.SetValue(0);
+12
View File
@@ -304,6 +304,18 @@ public:
*/
bool ContainsService(uint8_t aServiceId, uint16_t aRloc16);
/**
* This method provides the next server RLOC16 in the Thread Network Data.
*
* @param[inout] aIterator A reference to the Network Data iterator.
* @param[out] aRloc16 The RLOC16 value.
*
* @retval OT_ERROR_NONE Successfully found the next server.
* @retval OT_ERROR_NOT_FOUND No subsequent server exists in the Thread Network Data.
*
*/
otError GetNextServer(Iterator &aIterator, uint16_t &aRloc16);
/**
* This method cancels the data resubmit delay timer.
*