[child-table] move child related methods to 'ChildTable' (#5335)

This commit moves `GetChildInfoById()`, `GetChildInfoByIndex()`, and
`HasSleepyChildWithAddress()`, along with methods for saving/restoring
child entries in/from non-volatile settings (e.g., `Restore()`,
`RemoveStoredChild()`, etc.) from `Mle` module to `ChildTable`. It also
removes/inlines the `MleRouter::IsSleepyChildSubscribed()` method.
This commit is contained in:
Abtin Keshavarzian
2020-08-04 21:41:36 -07:00
committed by GitHub
parent 3cd5f49d71
commit 1cdb0e7767
8 changed files with 216 additions and 236 deletions
+2 -2
View File
@@ -259,7 +259,7 @@ otError otThreadGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChi
OT_ASSERT(aChildInfo != nullptr);
return instance.Get<Mle::MleRouter>().GetChildInfoById(aChildId, *static_cast<Child::Info *>(aChildInfo));
return instance.Get<ChildTable>().GetChildInfoById(aChildId, *static_cast<Child::Info *>(aChildInfo));
}
otError otThreadGetChildInfoByIndex(otInstance *aInstance, uint16_t aChildIndex, otChildInfo *aChildInfo)
@@ -268,7 +268,7 @@ otError otThreadGetChildInfoByIndex(otInstance *aInstance, uint16_t aChildIndex,
OT_ASSERT(aChildInfo != nullptr);
return instance.Get<Mle::MleRouter>().GetChildInfoByIndex(aChildIndex, *static_cast<Child::Info *>(aChildInfo));
return instance.Get<ChildTable>().GetChildInfoByIndex(aChildIndex, *static_cast<Child::Info *>(aChildInfo));
}
otError otThreadGetChildNextIp6Address(otInstance * aInstance,
+3 -3
View File
@@ -311,7 +311,7 @@ otError Ip6::InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aM
{
#if OPENTHREAD_FTD
if (aHeader.GetDestination().IsMulticastLargerThanRealmLocal() &&
Get<Mle::MleRouter>().HasSleepyChildrenSubscribed(aHeader.GetDestination()))
Get<ChildTable>().HasSleepyChildWithAddress(aHeader.GetDestination()))
{
Message *messageCopy = nullptr;
@@ -517,7 +517,7 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
if (aMessageInfo.GetPeerAddr().IsMulticastLargerThanRealmLocal())
{
#if OPENTHREAD_FTD
if (Get<Mle::MleRouter>().HasSleepyChildrenSubscribed(header.GetDestination()))
if (Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
{
Message *messageCopy = nullptr;
@@ -1193,7 +1193,7 @@ otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkM
#if OPENTHREAD_FTD
if (header.GetDestination().IsMulticastLargerThanRealmLocal() &&
Get<Mle::MleRouter>().HasSleepyChildrenSubscribed(header.GetDestination()))
Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
{
forward = true;
}
+149
View File
@@ -225,6 +225,155 @@ exit:
return error;
}
otError ChildTable::GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo)
{
otError error = OT_ERROR_NONE;
Child * child;
uint16_t rloc16;
if ((aChildId & ~Mle::kMaxChildId) != 0)
{
aChildId = Mle::Mle::ChildIdFromRloc16(aChildId);
}
rloc16 = Get<Mac::Mac>().GetShortAddress() | aChildId;
child = FindChild(rloc16, Child::kInStateValidOrRestoring);
VerifyOrExit(child != nullptr, error = OT_ERROR_NOT_FOUND);
aChildInfo.SetFrom(*child);
exit:
return error;
}
otError ChildTable::GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo)
{
otError error = OT_ERROR_NONE;
Child * child = nullptr;
child = GetChildAtIndex(aChildIndex);
VerifyOrExit((child != nullptr) && child->IsStateValidOrRestoring(), error = OT_ERROR_NOT_FOUND);
aChildInfo.SetFrom(*child);
exit:
return error;
}
void ChildTable::Restore(void)
{
otError error = OT_ERROR_NONE;
bool foundDuplicate = false;
uint16_t numChildren = 0;
for (const Settings::ChildInfo &childInfo : Get<Settings>().IterateChildInfo())
{
Child *child;
child = FindChild(childInfo.GetExtAddress(), Child::kInStateAnyExceptInvalid);
if (child == nullptr)
{
VerifyOrExit((child = GetNewChild()) != nullptr, error = OT_ERROR_NO_BUFS);
}
else
{
foundDuplicate = true;
}
child->Clear();
child->SetExtAddress(childInfo.GetExtAddress());
child->GetLinkInfo().Clear();
child->SetRloc16(childInfo.GetRloc16());
child->SetTimeout(childInfo.GetTimeout());
child->SetDeviceMode(Mle::DeviceMode(childInfo.GetMode()));
child->SetState(Neighbor::kStateRestored);
child->SetLastHeard(TimerMilli::GetNow());
child->SetVersion(static_cast<uint8_t>(childInfo.GetVersion()));
Get<IndirectSender>().SetChildUseShortAddress(*child, true);
numChildren++;
}
exit:
if (foundDuplicate || (numChildren > GetMaxChildren()) || (error != OT_ERROR_NONE))
{
// If there is any error, e.g., there are more saved children
// in non-volatile settings than could be restored or there are
// duplicate entries with same extended address, refresh the stored
// children info to ensure that the non-volatile settings remain
// consistent with the child table.
RefreshStoredChildren();
}
}
void ChildTable::RemoveStoredChild(const Child &aChild)
{
for (Settings::ChildInfoIterator iter(GetInstance()); !iter.IsDone(); iter++)
{
if (iter.GetChildInfo().GetRloc16() == aChild.GetRloc16())
{
IgnoreError(iter.Delete());
break;
}
}
}
otError ChildTable::StoreChild(const Child &aChild)
{
Settings::ChildInfo childInfo;
RemoveStoredChild(aChild);
childInfo.Init();
childInfo.SetExtAddress(aChild.GetExtAddress());
childInfo.SetTimeout(aChild.GetTimeout());
childInfo.SetRloc16(aChild.GetRloc16());
childInfo.SetMode(aChild.GetDeviceMode().Get());
childInfo.SetVersion(aChild.GetVersion());
return Get<Settings>().AddChildInfo(childInfo);
}
void ChildTable::RefreshStoredChildren(void)
{
const Child *child = &mChildren[0];
SuccessOrExit(Get<Settings>().DeleteAllChildInfo());
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->IsStateInvalid())
{
continue;
}
SuccessOrExit(StoreChild(*child));
}
exit:
return;
}
bool ChildTable::HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) const
{
bool hasChild = false;
const Child *child = &mChildren[0];
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->IsStateValidOrRestoring() && !child->IsRxOnWhenIdle() && child->HasIp6Address(aIp6Address))
{
hasChild = true;
break;
}
}
return hasChild;
}
#endif // OPENTHREAD_FTD
} // namespace ot
+57
View File
@@ -320,6 +320,61 @@ public:
*/
IteratorBuilder Iterate(Child::StateFilter aFilter) { return IteratorBuilder(GetInstance(), aFilter); }
/**
* This method retains diagnostic information for an attached child by Child ID or RLOC16.
*
* @param[in] aChildId The Child ID or RLOC16 for an attached child.
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
otError GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo);
/**
* This method retains diagnostic information for an attached child by the internal table index.
*
* @param[in] aChildIndex The table index.
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
otError GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo);
/**
* This method restores child table from non-volatile memory.
*
*/
void Restore(void);
/**
* This method removes a stored child information from non-volatile memory.
*
* @param[in] aChildRloc16 A reference to the child to remove from non-volatile memory.
*
*/
void RemoveStoredChild(const Child &aChild);
/**
* This method store a child information into non-volatile memory.
*
* @param[in] aChild A reference to the child to store.
*
* @retval OT_ERROR_NONE Successfully store child.
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to store child.
*
*/
otError StoreChild(const Child &aChild);
/**
* This method indicates whether the child table contains any sleepy child (in states valid or restoring) with a
* given IPv6 address.
*
* @param[in] aIp6Address An IPv6 address.
*
* @retval TRUE If the child table contains any sleepy child with @p aIp6Address.
* @retval FALSE If the child table does not contain any sleepy child with @p aIp6Address.
*
*/
bool HasSleepyChildWithAddress(const Ip6::Address &aIp6ddress) const;
private:
enum
{
@@ -342,6 +397,8 @@ private:
Child::StateFilter mFilter;
};
void RefreshStoredChildren(void);
uint16_t mMaxChildrenAllowed;
Child mChildren[kMaxChildren];
};
+1 -1
View File
@@ -93,7 +93,7 @@ otError MeshForwarder::SendMessage(Message &aMessage)
// destined for some sleepy children which subscribed the multicast address.
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
if (mle.IsSleepyChildSubscribed(ip6Header.GetDestination(), child))
if (!child.IsRxOnWhenIdle() && child.HasIp6Address(ip6Header.GetDestination()))
{
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
}
+1 -1
View File
@@ -434,7 +434,7 @@ otError Mle::Restore(void)
{
Get<MleRouter>().SetRouterId(RouterIdFromRloc16(GetRloc16()));
Get<MleRouter>().SetPreviousPartitionId(networkInfo.GetPreviousPartitionId());
Get<MleRouter>().RestoreChildren();
Get<ChildTable>().Restore();
}
#endif
+3 -159
View File
@@ -2548,7 +2548,7 @@ void MleRouter::HandleChildUpdateRequest(const Message & aMessage,
{
if (childDidChange)
{
IgnoreError(StoreChild(*child));
IgnoreError(mChildTable.StoreChild(*child));
}
}
@@ -3402,7 +3402,7 @@ void MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
Get<AddressResolver>().Remove(aNeighbor.GetRloc16());
}
IgnoreError(RemoveStoredChild(aNeighbor.GetRloc16()));
mChildTable.RemoveStoredChild(static_cast<Child &>(aNeighbor));
}
else if (aNeighbor.IsStateValid())
{
@@ -3663,136 +3663,6 @@ void MleRouter::SetRouterId(uint8_t aRouterId)
mPreviousRouterId = mRouterId;
}
otError MleRouter::GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo)
{
otError error = OT_ERROR_NONE;
Child * child;
uint16_t rloc16;
if ((aChildId & ~kMaxChildId) != 0)
{
aChildId = ChildIdFromRloc16(aChildId);
}
rloc16 = Get<Mac::Mac>().GetShortAddress() | aChildId;
child = mChildTable.FindChild(rloc16, Child::kInStateValidOrRestoring);
VerifyOrExit(child != nullptr, error = OT_ERROR_NOT_FOUND);
aChildInfo.SetFrom(*child);
exit:
return error;
}
otError MleRouter::GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo)
{
otError error = OT_ERROR_NONE;
Child * child = nullptr;
child = mChildTable.GetChildAtIndex(aChildIndex);
VerifyOrExit((child != nullptr) && child->IsStateValidOrRestoring(), error = OT_ERROR_NOT_FOUND);
aChildInfo.SetFrom(*child);
exit:
return error;
}
void MleRouter::RestoreChildren(void)
{
otError error = OT_ERROR_NONE;
bool foundDuplicate = false;
uint16_t numChildren = 0;
for (const Settings::ChildInfo &childInfo : Get<Settings>().IterateChildInfo())
{
Child *child;
child = mChildTable.FindChild(childInfo.GetExtAddress(), Child::kInStateAnyExceptInvalid);
if (child == nullptr)
{
VerifyOrExit((child = mChildTable.GetNewChild()) != nullptr, error = OT_ERROR_NO_BUFS);
}
else
{
foundDuplicate = true;
}
child->Clear();
child->SetExtAddress(childInfo.GetExtAddress());
child->GetLinkInfo().Clear();
child->SetRloc16(childInfo.GetRloc16());
child->SetTimeout(childInfo.GetTimeout());
child->SetDeviceMode(DeviceMode(childInfo.GetMode()));
child->SetState(Neighbor::kStateRestored);
child->SetLastHeard(TimerMilli::GetNow());
child->SetVersion(static_cast<uint8_t>(childInfo.GetVersion()));
Get<IndirectSender>().SetChildUseShortAddress(*child, true);
numChildren++;
}
exit:
if (foundDuplicate || (numChildren > mChildTable.GetMaxChildren()) || (error != OT_ERROR_NONE))
{
// If there is any error, e.g., there are more saved children
// in non-volatile settings than could be restored or there are
// duplicate entries with same extended address, refresh the stored
// children info to ensure that the non-volatile settings remain
// consistent with the child table.
RefreshStoredChildren();
}
}
otError MleRouter::RemoveStoredChild(uint16_t aChildRloc16)
{
otError error = OT_ERROR_NOT_FOUND;
for (Settings::ChildInfoIterator iter(GetInstance()); !iter.IsDone(); iter++)
{
if (iter.GetChildInfo().GetRloc16() == aChildRloc16)
{
error = iter.Delete();
ExitNow();
}
}
exit:
return error;
}
otError MleRouter::StoreChild(const Child &aChild)
{
Settings::ChildInfo childInfo;
IgnoreError(RemoveStoredChild(aChild.GetRloc16()));
childInfo.Init();
childInfo.SetExtAddress(aChild.GetExtAddress());
childInfo.SetTimeout(aChild.GetTimeout());
childInfo.SetRloc16(aChild.GetRloc16());
childInfo.SetMode(aChild.GetDeviceMode().Get());
childInfo.SetVersion(aChild.GetVersion());
return Get<Settings>().AddChildInfo(childInfo);
}
void MleRouter::RefreshStoredChildren(void)
{
SuccessOrExit(Get<Settings>().DeleteAllChildInfo());
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
{
SuccessOrExit(StoreChild(child));
}
exit:
return;
}
otError MleRouter::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
{
otError error = OT_ERROR_NONE;
@@ -4628,7 +4498,7 @@ void MleRouter::SetChildStateToValid(Child &aChild)
VerifyOrExit(!aChild.IsStateValid(), OT_NOOP);
aChild.SetState(Neighbor::kStateValid);
IgnoreError(StoreChild(aChild));
IgnoreError(mChildTable.StoreChild(aChild));
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
Get<MlrManager>().UpdateProxiedSubscriptions(aChild, nullptr, 0);
@@ -4755,32 +4625,6 @@ void MleRouter::Signal(otNeighborTableEvent aEvent, Neighbor &aNeighbor)
}
}
bool MleRouter::HasSleepyChildrenSubscribed(const Ip6::Address &aAddress)
{
bool rval = false;
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
if (child.IsRxOnWhenIdle())
{
continue;
}
if (IsSleepyChildSubscribed(aAddress, child))
{
ExitNow(rval = true);
}
}
exit:
return rval;
}
bool MleRouter::IsSleepyChildSubscribed(const Ip6::Address &aAddress, Child &aChild)
{
return aChild.IsStateValidOrRestoring() && !aChild.IsRxOnWhenIdle() && aChild.HasIp6Address(aAddress);
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
void MleRouter::HandleTimeSync(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor)
{
-70
View File
@@ -344,34 +344,6 @@ public:
*/
void RemoveRouterLink(Router &aRouter);
/**
* This method restores children information from non-volatile memory.
*
*/
void RestoreChildren(void);
/**
* This method remove a stored child information from non-volatile memory.
*
* @param[in] aChildRloc16 The child RLOC16 to remove.
*
* @retval OT_ERROR_NONE Successfully remove child.
* @retval OT_ERROR_NOT_FOUND There is no specified child stored in non-volatile memory.
*
*/
otError RemoveStoredChild(uint16_t aChildRloc16);
/**
* This method store a child information into non-volatile memory.
*
* @param[in] aChild A reference to the child to store.
*
* @retval OT_ERROR_NONE Successfully store child.
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to store child.
*
*/
otError StoreChild(const Child &aChild);
/**
* This method returns a pointer to a Neighbor object.
*
@@ -423,24 +395,6 @@ public:
*/
Neighbor *GetRxOnlyNeighborRouter(const Mac::Address &aAddress);
/**
* This method retains diagnostic information for an attached child by Child ID or RLOC16.
*
* @param[in] aChildId The Child ID or RLOC16 for an attached child.
* @param[out] aChildInfo The child information.
*
*/
otError GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo);
/**
* This method retains diagnostic information for an attached child by the internal table index.
*
* @param[in] aChildIndex The table index.
* @param[out] aChildInfo The child information.
*
*/
otError GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo);
/**
* This method indicates whether or not the RLOC16 is an MTD child of this device.
*
@@ -610,29 +564,6 @@ public:
*/
void Signal(otNeighborTableEvent aEvent, Neighbor &aNeighbor);
/**
* This method returns whether the device has any sleepy children subscribed the address.
*
* @param[in] aAddress The reference of the address.
*
* @retval TRUE If the device has any sleepy children subscribed the address @p aAddress.
* @retval FALSE If the device doesn't have any sleepy children subscribed the address @p aAddress.
*
*/
bool HasSleepyChildrenSubscribed(const Ip6::Address &aAddress);
/**
* This method returns whether the specific child subscribed the address.
*
* @param[in] aAddress The reference of the address.
* @param[in] aChild The reference of the child.
*
* @retval TRUE If the sleepy child @p aChild subscribed the address @p aAddress.
* @retval FALSE If the sleepy child @p aChild did not subscribe the address @p aAddress.
*
*/
bool IsSleepyChildSubscribed(const Ip6::Address &aAddress, Child &aChild);
/**
* This method resets the MLE Advertisement Trickle timer interval.
*
@@ -706,7 +637,6 @@ private:
otError AppendRoute(Message &aMessage);
otError AppendActiveDataset(Message &aMessage);
otError AppendPendingDataset(Message &aMessage);
void RefreshStoredChildren(void);
void HandleDetachStart(void);
void HandleChildStart(AttachMode aMode);
void HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);