mirror of
https://github.com/espressif/openthread.git
synced 2026-10-02 13:57:38 +00:00
[child-table] enable use of range-based "for" loop (#5239)
This commit updates `ChildTable` class. It mainly adds support for using range-based `for` loops to iterate over all child entries (matching a given state filter). It also simplifies the `Iterator` implementation (removing the now unused behavior to start the iteration from a specific child in the table). The unit test `test_child_table` is also updated to add tests for the newly added behavior.
This commit is contained in:
@@ -79,9 +79,8 @@ DataPollHandler::DataPollHandler(Instance &aInstance)
|
|||||||
|
|
||||||
void DataPollHandler::Clear(void)
|
void DataPollHandler::Clear(void)
|
||||||
{
|
{
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
child.SetDataPollPending(false);
|
child.SetDataPollPending(false);
|
||||||
child.SetFrameReplacePending(false);
|
child.SetFrameReplacePending(false);
|
||||||
child.SetFramePurgePending(false);
|
child.SetFramePurgePending(false);
|
||||||
@@ -289,20 +288,18 @@ exit:
|
|||||||
|
|
||||||
void DataPollHandler::ProcessPendingPolls(void)
|
void DataPollHandler::ProcessPendingPolls(void)
|
||||||
{
|
{
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
Child *child = iter.GetChild();
|
if (!child.IsDataPollPending())
|
||||||
|
|
||||||
if (!child->IsDataPollPending())
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the child with earliest poll receive time.
|
// Find the child with earliest poll receive time.
|
||||||
|
|
||||||
if ((mIndirectTxChild == nullptr) || (child->GetLastHeard() < mIndirectTxChild->GetLastHeard()))
|
if ((mIndirectTxChild == nullptr) || (child.GetLastHeard() < mIndirectTxChild->GetLastHeard()))
|
||||||
{
|
{
|
||||||
mIndirectTxChild = child;
|
mIndirectTxChild = &child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -723,10 +723,8 @@ void AddressResolver::HandleAddressError(Coap::Message &aMessage, const Ip6::Mes
|
|||||||
|
|
||||||
meshLocalIid.ConvertToExtAddress(extAddr);
|
meshLocalIid.ConvertToExtAddress(extAddr);
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (child.IsFullThreadDevice())
|
if (child.IsFullThreadDevice())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -780,10 +778,8 @@ void AddressResolver::HandleAddressQuery(Coap::Message &aMessage, const Ip6::Mes
|
|||||||
ExitNow();
|
ExitNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (child.IsFullThreadDevice() || child.GetLinkFailures() >= Mle::kFailedChildTransmissions)
|
if (child.IsFullThreadDevice() || child.GetLinkFailures() >= Mle::kFailedChildTransmissions)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -44,16 +44,6 @@ namespace ot {
|
|||||||
ChildTable::Iterator::Iterator(Instance &aInstance, Child::StateFilter aFilter)
|
ChildTable::Iterator::Iterator(Instance &aInstance, Child::StateFilter aFilter)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mFilter(aFilter)
|
, mFilter(aFilter)
|
||||||
, mStart(nullptr)
|
|
||||||
, mChild(nullptr)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
ChildTable::Iterator::Iterator(Instance &aInstance, Child::StateFilter aFilter, Child *aStartingChild)
|
|
||||||
: InstanceLocator(aInstance)
|
|
||||||
, mFilter(aFilter)
|
|
||||||
, mStart(aStartingChild)
|
|
||||||
, mChild(nullptr)
|
, mChild(nullptr)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
@@ -61,12 +51,7 @@ ChildTable::Iterator::Iterator(Instance &aInstance, Child::StateFilter aFilter,
|
|||||||
|
|
||||||
void ChildTable::Iterator::Reset(void)
|
void ChildTable::Iterator::Reset(void)
|
||||||
{
|
{
|
||||||
if (mStart == nullptr)
|
mChild = &Get<ChildTable>().mChildren[0];
|
||||||
{
|
|
||||||
mStart = &Get<ChildTable>().mChildren[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
mChild = mStart;
|
|
||||||
|
|
||||||
if (!mChild->MatchesFilter(mFilter))
|
if (!mChild->MatchesFilter(mFilter))
|
||||||
{
|
{
|
||||||
@@ -76,22 +61,12 @@ void ChildTable::Iterator::Reset(void)
|
|||||||
|
|
||||||
void ChildTable::Iterator::Advance(void)
|
void ChildTable::Iterator::Advance(void)
|
||||||
{
|
{
|
||||||
ChildTable &childTable = Get<ChildTable>();
|
|
||||||
Child * listStart = &childTable.mChildren[0];
|
|
||||||
Child * listEnd = &childTable.mChildren[childTable.mMaxChildrenAllowed];
|
|
||||||
|
|
||||||
VerifyOrExit(mChild != nullptr, OT_NOOP);
|
VerifyOrExit(mChild != nullptr, OT_NOOP);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
mChild++;
|
mChild++;
|
||||||
|
VerifyOrExit(mChild < &Get<ChildTable>().mChildren[Get<ChildTable>().mMaxChildrenAllowed], mChild = nullptr);
|
||||||
if (mChild >= listEnd)
|
|
||||||
{
|
|
||||||
mChild = listStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
VerifyOrExit(mChild != mStart, mChild = nullptr);
|
|
||||||
} while (!mChild->MatchesFilter(mFilter));
|
} while (!mChild->MatchesFilter(mFilter));
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ namespace ot {
|
|||||||
*/
|
*/
|
||||||
class ChildTable : public InstanceLocator
|
class ChildTable : public InstanceLocator
|
||||||
{
|
{
|
||||||
|
class IteratorBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* This class represents an iterator for iterating through the child entries in the child table.
|
* This class represents an iterator for iterating through the child entries in the child table.
|
||||||
@@ -56,9 +58,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
class Iterator : public InstanceLocator
|
class Iterator : public InstanceLocator
|
||||||
{
|
{
|
||||||
|
friend class IteratorBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* This constructor initializes an `Iterator` instance to start from beginning of the child table.
|
* This constructor initializes an `Iterator` instance.
|
||||||
*
|
*
|
||||||
* @param[in] aInstance A reference to the OpenThread instance.
|
* @param[in] aInstance A reference to the OpenThread instance.
|
||||||
* @param[in] aFilter A child state filter.
|
* @param[in] aFilter A child state filter.
|
||||||
@@ -66,23 +70,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Iterator(Instance &aInstance, Child::StateFilter aFilter);
|
Iterator(Instance &aInstance, Child::StateFilter aFilter);
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor initializes an `Iterator` instance to start from a given child.
|
|
||||||
*
|
|
||||||
* This constructor allows the iterator to start from a given `Child` entry. The iterator will start from the
|
|
||||||
* given child and will go through all entries in the child table (matching the filter) till it gets back to
|
|
||||||
* the starting `Child` entry.
|
|
||||||
*
|
|
||||||
* If the given starting `Child` pointer is `nullptr`, then the iterator starts from beginning of the child
|
|
||||||
* table.
|
|
||||||
*
|
|
||||||
* @param[in] aInstance A reference to the OpenThread instance.
|
|
||||||
* @param[in] aFilter A child state filter.
|
|
||||||
* @param[in] aStartingChild A pointer to a child. If non-nullptr, the iterator starts from the given entry.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
Iterator(Instance &aInstance, Child::StateFilter aFilter, Child *aStartingChild);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method resets the iterator to start over.
|
* This method resets the iterator to start over.
|
||||||
*
|
*
|
||||||
@@ -99,16 +86,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool IsDone(void) const { return (mChild == nullptr); }
|
bool IsDone(void) const { return (mChild == nullptr); }
|
||||||
|
|
||||||
/**
|
|
||||||
* This method advances the iterator.
|
|
||||||
*
|
|
||||||
* The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
|
|
||||||
* If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
|
|
||||||
* `GetChild()` returns `nullptr` and `IsDone()` returns `true`).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void Advance(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method overloads `++` operator (pre-increment) to advance the iterator.
|
* This method overloads `++` operator (pre-increment) to advance the iterator.
|
||||||
*
|
*
|
||||||
@@ -137,9 +114,61 @@ public:
|
|||||||
*/
|
*/
|
||||||
Child *GetChild(void) { return mChild; }
|
Child *GetChild(void) { return mChild; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method overloads the `*` dereference operator and gets a reference to `Child` entry to which the
|
||||||
|
* iterator is currently pointing.
|
||||||
|
*
|
||||||
|
* This method MUST be used when the iterator is not empty/finished (i.e., `IsDone()` returns `false`).
|
||||||
|
*
|
||||||
|
* @returns A reference to the `Child` entry currently pointed by the iterator.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Child &operator*(void) { return *mChild; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method overloads the `->` dereference operator and gets a pointer to `Child` entry to which the iterator
|
||||||
|
* is currently pointing.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the `Child` entry associated with the iterator, or `nullptr` if iterator is empty/done.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Child *operator->(void) { return mChild; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method overloads operator `==` to evaluate whether or not two `Iterator` instances point to the same
|
||||||
|
* child entry.
|
||||||
|
*
|
||||||
|
* @param[in] aOther The other `Iterator` to compare with.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the two `Iterator` objects point to the same child entry or both are done.
|
||||||
|
* @retval FALSE If the two `Iterator` objects do not point to the same child entry.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool operator==(const Iterator &aOther) const { return mChild == aOther.mChild; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method overloads operator `!=` to evaluate whether or not two `Iterator` instances point to the same
|
||||||
|
* child entry.
|
||||||
|
*
|
||||||
|
* @param[in] aOther The other `Iterator` to compare with.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the two `Iterator` objects do not point to the same child entry.
|
||||||
|
* @retval FALSE If the two `Iterator` objects point to the same child entry or both are done.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool operator!=(const Iterator &aOther) const { return mChild != aOther.mChild; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Iterator(Instance &aInstance)
|
||||||
|
: InstanceLocator(aInstance)
|
||||||
|
, mFilter(Child::StateFilter::kInStateValid)
|
||||||
|
, mChild(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Advance(void);
|
||||||
|
|
||||||
Child::StateFilter mFilter;
|
Child::StateFilter mFilter;
|
||||||
Child * mStart;
|
|
||||||
Child * mChild;
|
Child * mChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -276,12 +305,43 @@ public:
|
|||||||
*/
|
*/
|
||||||
otError SetMaxChildrenAllowed(uint16_t aMaxChildren);
|
otError SetMaxChildrenAllowed(uint16_t aMaxChildren);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method enables range-based `for` loop iteration over all child entries in the child table matching a given
|
||||||
|
* state filter.
|
||||||
|
*
|
||||||
|
* This method should be used as follows:
|
||||||
|
*
|
||||||
|
* for (Child &child : aChildTable.Iterate(aFilter)) { ... }
|
||||||
|
*
|
||||||
|
* @param[in] aFilter A child state filter.
|
||||||
|
*
|
||||||
|
* @returns An IteratorBuilder instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
IteratorBuilder Iterate(Child::StateFilter aFilter) { return IteratorBuilder(GetInstance(), aFilter); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN,
|
kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IteratorBuilder : public InstanceLocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IteratorBuilder(Instance &aInstance, Child::StateFilter aFilter)
|
||||||
|
: InstanceLocator(aInstance)
|
||||||
|
, mFilter(aFilter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator begin(void) { return Iterator(GetInstance(), mFilter); }
|
||||||
|
Iterator end(void) { return Iterator(GetInstance()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Child::StateFilter mFilter;
|
||||||
|
};
|
||||||
|
|
||||||
uint16_t mMaxChildrenAllowed;
|
uint16_t mMaxChildrenAllowed;
|
||||||
Child mChildren[kMaxChildren];
|
Child mChildren[kMaxChildren];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ void IndirectSender::Stop(void)
|
|||||||
{
|
{
|
||||||
VerifyOrExit(mEnabled, OT_NOOP);
|
VerifyOrExit(mEnabled, OT_NOOP);
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
iter.GetChild()->SetIndirectMessage(nullptr);
|
child.SetIndirectMessage(nullptr);
|
||||||
mSourceMatchController.ResetMessageCount(*iter.GetChild());
|
mSourceMatchController.ResetMessageCount(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataPollHandler.Clear();
|
mDataPollHandler.Clear();
|
||||||
@@ -556,14 +556,14 @@ exit:
|
|||||||
|
|
||||||
void IndirectSender::ClearMessagesForRemovedChildren(void)
|
void IndirectSender::ClearMessagesForRemovedChildren(void)
|
||||||
{
|
{
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptValidOrRestoring))
|
||||||
{
|
{
|
||||||
if (iter.GetChild()->GetIndirectMessageCount() == 0)
|
if (child.GetIndirectMessageCount() == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearAllMessagesForSleepyChild(*iter.GetChild());
|
ClearAllMessagesForSleepyChild(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,11 +130,11 @@ otError KeyManager::SetMasterKey(const MasterKey &aKey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset child frame counters
|
// reset child frame counters
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
iter.GetChild()->SetKeySequence(0);
|
child.SetKeySequence(0);
|
||||||
iter.GetChild()->SetLinkFrameCounter(0);
|
child.SetLinkFrameCounter(0);
|
||||||
iter.GetChild()->SetMleFrameCounter(0);
|
child.SetMleFrameCounter(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -138,9 +138,9 @@ void MeshForwarder::RemoveMessage(Message &aMessage)
|
|||||||
if (queue == &mSendQueue)
|
if (queue == &mSendQueue)
|
||||||
{
|
{
|
||||||
#if OPENTHREAD_FTD
|
#if OPENTHREAD_FTD
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(aMessage, *iter.GetChild()));
|
IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(aMessage, child));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -80,11 +80,8 @@ otError MeshForwarder::SendMessage(Message &aMessage)
|
|||||||
ip6Header.GetDestination() == mle.GetRealmLocalAllThreadNodesAddress())
|
ip6Header.GetDestination() == mle.GetRealmLocalAllThreadNodesAddress())
|
||||||
{
|
{
|
||||||
// destined for all sleepy children
|
// destined for all sleepy children
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone();
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
iter++)
|
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (!child.IsRxOnWhenIdle())
|
if (!child.IsRxOnWhenIdle())
|
||||||
{
|
{
|
||||||
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
|
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
|
||||||
@@ -94,11 +91,8 @@ otError MeshForwarder::SendMessage(Message &aMessage)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// destined for some sleepy children which subscribed the multicast address.
|
// destined for some sleepy children which subscribed the multicast address.
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone();
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
iter++)
|
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (mle.IsSleepyChildSubscribed(ip6Header.GetDestination(), child))
|
if (mle.IsSleepyChildSubscribed(ip6Header.GetDestination(), child))
|
||||||
{
|
{
|
||||||
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
|
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
|
||||||
@@ -329,9 +323,9 @@ void MeshForwarder::RemoveDataResponseMessages(void)
|
|||||||
|
|
||||||
if (!(ip6Header.GetDestination().IsMulticast()))
|
if (!(ip6Header.GetDestination().IsMulticast()))
|
||||||
{
|
{
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(*message, *iter.GetChild()));
|
IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(*message, child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -330,11 +330,11 @@ void MleRouter::SetStateRouter(uint16_t aRloc16)
|
|||||||
Get<Mac::Mac>().SetBeaconEnabled(true);
|
Get<Mac::Mac>().SetBeaconEnabled(true);
|
||||||
|
|
||||||
// remove children that do not have matching RLOC16
|
// remove children that do not have matching RLOC16
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
if (RouterIdFromRloc16(iter.GetChild()->GetRloc16()) != mRouterId)
|
if (RouterIdFromRloc16(child.GetRloc16()) != mRouterId)
|
||||||
{
|
{
|
||||||
RemoveNeighbor(*iter.GetChild());
|
RemoveNeighbor(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,11 +370,11 @@ void MleRouter::SetStateLeader(uint16_t aRloc16)
|
|||||||
Get<AddressResolver>().Clear();
|
Get<AddressResolver>().Clear();
|
||||||
|
|
||||||
// remove children that do not have matching RLOC16
|
// remove children that do not have matching RLOC16
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
if (RouterIdFromRloc16(iter.GetChild()->GetRloc16()) != mRouterId)
|
if (RouterIdFromRloc16(child.GetRloc16()) != mRouterId)
|
||||||
{
|
{
|
||||||
RemoveNeighbor(*iter.GetChild());
|
RemoveNeighbor(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1835,9 +1835,8 @@ void MleRouter::HandleStateUpdateTimer(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update children state
|
// update children state
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
Child & child = *iter.GetChild();
|
|
||||||
uint32_t timeout = 0;
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
switch (child.GetState())
|
switch (child.GetState())
|
||||||
@@ -2124,14 +2123,14 @@ otError MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffse
|
|||||||
// table is timed out and then trying to register its globally unique
|
// table is timed out and then trying to register its globally unique
|
||||||
// IPv6 address as the new child.
|
// IPv6 address as the new child.
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
if (iter.GetChild() == &aChild)
|
if (&child == &aChild)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
IgnoreError(iter.GetChild()->RemoveIp6Address(address));
|
IgnoreError(child.RemoveIp6Address(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear EID-to-RLOC cache for the unicast address registered by the child.
|
// Clear EID-to-RLOC cache for the unicast address registered by the child.
|
||||||
@@ -2728,9 +2727,8 @@ void MleRouter::SynchronizeChildNetworkData(void)
|
|||||||
{
|
{
|
||||||
VerifyOrExit(IsRouterOrLeader(), OT_NOOP);
|
VerifyOrExit(IsRouterOrLeader(), OT_NOOP);
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
Child & child = *iter.GetChild();
|
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
|
|
||||||
if (child.IsRxOnWhenIdle())
|
if (child.IsRxOnWhenIdle())
|
||||||
@@ -3452,7 +3450,6 @@ Neighbor *MleRouter::GetNeighbor(const Mac::Address &aAddress)
|
|||||||
Neighbor *MleRouter::GetNeighbor(const Ip6::Address &aAddress)
|
Neighbor *MleRouter::GetNeighbor(const Ip6::Address &aAddress)
|
||||||
{
|
{
|
||||||
Lowpan::Context context;
|
Lowpan::Context context;
|
||||||
Child * child;
|
|
||||||
Neighbor * rval = nullptr;
|
Neighbor * rval = nullptr;
|
||||||
|
|
||||||
if (aAddress.IsLinkLocal())
|
if (aAddress.IsLinkLocal())
|
||||||
@@ -3468,19 +3465,17 @@ Neighbor *MleRouter::GetNeighbor(const Ip6::Address &aAddress)
|
|||||||
context.mContextId = 0xff;
|
context.mContextId = 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
child = iter.GetChild();
|
|
||||||
|
|
||||||
if ((context.mContextId == kMeshLocalPrefixContextId) && aAddress.GetIid().IsLocator() &&
|
if ((context.mContextId == kMeshLocalPrefixContextId) && aAddress.GetIid().IsLocator() &&
|
||||||
(aAddress.GetIid().GetLocator() == child->GetRloc16()))
|
(aAddress.GetIid().GetLocator() == child.GetRloc16()))
|
||||||
{
|
{
|
||||||
ExitNow(rval = child);
|
ExitNow(rval = &child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child->HasIp6Address(aAddress))
|
if (child.HasIp6Address(aAddress))
|
||||||
{
|
{
|
||||||
ExitNow(rval = child);
|
ExitNow(rval = &child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3752,9 +3747,9 @@ void MleRouter::RefreshStoredChildren(void)
|
|||||||
{
|
{
|
||||||
SuccessOrExit(Get<Settings>().DeleteChildInfo());
|
SuccessOrExit(Get<Settings>().DeleteChildInfo());
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateAnyExceptInvalid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||||
{
|
{
|
||||||
SuccessOrExit(StoreChild(*iter.GetChild()));
|
SuccessOrExit(StoreChild(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -4110,9 +4105,9 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Message * aMessage,
|
|||||||
IgnoreError(SendLinkRequest(nullptr));
|
IgnoreError(SendLinkRequest(nullptr));
|
||||||
|
|
||||||
// send child id responses
|
// send child id responses
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateChildIdRequest); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateChildIdRequest))
|
||||||
{
|
{
|
||||||
IgnoreError(SendChildIdResponse(*iter.GetChild()));
|
IgnoreError(SendChildIdResponse(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -4671,9 +4666,9 @@ bool MleRouter::HasChildren(void)
|
|||||||
|
|
||||||
void MleRouter::RemoveChildren(void)
|
void MleRouter::RemoveChildren(void)
|
||||||
{
|
{
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
RemoveNeighbor(*iter.GetChild());
|
RemoveNeighbor(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4711,10 +4706,8 @@ otError MleRouter::GetMaxChildTimeout(uint32_t &aTimeout) const
|
|||||||
|
|
||||||
VerifyOrExit(IsRouterOrLeader(), error = OT_ERROR_INVALID_STATE);
|
VerifyOrExit(IsRouterOrLeader(), error = OT_ERROR_INVALID_STATE);
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (child.IsFullThreadDevice())
|
if (child.IsFullThreadDevice())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -4783,10 +4776,8 @@ bool MleRouter::HasSleepyChildrenSubscribed(const Ip6::Address &aAddress)
|
|||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
if (child.IsRxOnWhenIdle())
|
if (child.IsRxOnWhenIdle())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -241,12 +241,10 @@ otError NetworkDiagnostic::AppendChildTable(Message &aMessage)
|
|||||||
|
|
||||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(ChildTableTlv)));
|
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(ChildTableTlv)));
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
VerifyOrExit(count--, OT_NOOP);
|
VerifyOrExit(count--, OT_NOOP);
|
||||||
|
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
while (static_cast<uint32_t>(1 << timeout) < child.GetTimeout())
|
while (static_cast<uint32_t>(1 << timeout) < child.GetTimeout())
|
||||||
|
|||||||
@@ -212,12 +212,12 @@ otError SourceMatchController::AddPendingEntries(void)
|
|||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValidOrRestoring); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
|
||||||
{
|
{
|
||||||
if (iter.GetChild()->IsIndirectSourceMatchPending())
|
if (child.IsIndirectSourceMatchPending())
|
||||||
{
|
{
|
||||||
SuccessOrExit(error = AddAddress(*iter.GetChild()));
|
SuccessOrExit(error = AddAddress(child));
|
||||||
iter.GetChild()->SetIndirectSourceMatchPending(false);
|
child.SetIndirectSourceMatchPending(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,10 +120,8 @@ void ChildSupervisor::HandleTimer(void)
|
|||||||
{
|
{
|
||||||
VerifyOrExit(mSupervisionInterval != 0, OT_NOOP);
|
VerifyOrExit(mSupervisionInterval != 0, OT_NOOP);
|
||||||
|
|
||||||
for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++)
|
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
|
||||||
{
|
{
|
||||||
Child &child = *iter.GetChild();
|
|
||||||
|
|
||||||
child.IncrementSecondsSinceLastSupervision();
|
child.IncrementSecondsSinceLastSupervision();
|
||||||
|
|
||||||
if ((child.GetSecondsSinceLastSupervision() >= mSupervisionInterval) && !child.IsRxOnWhenIdle())
|
if ((child.GetSecondsSinceLastSupervision() >= mSupervisionInterval) && !child.IsRxOnWhenIdle())
|
||||||
|
|||||||
@@ -144,97 +144,85 @@ void VerifyChildTableContent(ChildTable &aTable, uint16_t aChildListLength, cons
|
|||||||
VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(address) returned incorrect child");
|
VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(address) returned incorrect child");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify `ChildTable::Iterator` behavior when starting from different child entries.
|
// Verify `ChildTable::Iterator` behavior.
|
||||||
|
|
||||||
for (uint16_t listIndex = 0; listIndex <= aChildListLength; listIndex++)
|
|
||||||
{
|
{
|
||||||
Child *startingChild = nullptr;
|
ChildTable::Iterator iter(*sInstance, filter);
|
||||||
|
bool childObserved[kMaxChildren];
|
||||||
|
uint16_t numChildren = 0;
|
||||||
|
|
||||||
if (listIndex < aChildListLength)
|
memset(childObserved, 0, sizeof(childObserved));
|
||||||
|
|
||||||
|
// Use the iterator and verify that each returned `Child` entry is in the expected list.
|
||||||
|
|
||||||
|
for (; !iter.IsDone(); iter++)
|
||||||
{
|
{
|
||||||
startingChild = aTable.FindChild(aChildList[listIndex].mRloc16, Child::kInStateAnyExceptInvalid);
|
Child * child = iter.GetChild();
|
||||||
VerifyOrQuit(startingChild != nullptr, "FindChild() failed");
|
Child & childRef = *iter;
|
||||||
}
|
bool didFind = false;
|
||||||
|
uint16_t childIndex;
|
||||||
|
|
||||||
// Test an iterator starting from `startingChild`.
|
VerifyOrQuit(child != nullptr, "iter.GetChild() failed");
|
||||||
|
VerifyOrQuit(&childRef == child, "iter.operator*() failed");
|
||||||
|
VerifyOrQuit(iter->GetRloc16() == child->GetRloc16(), "iter.operator->() failed");
|
||||||
|
|
||||||
{
|
childIndex = aTable.GetChildIndex(*child);
|
||||||
ChildTable::Iterator iter(*sInstance, filter, startingChild);
|
VerifyOrQuit(childIndex < aTable.GetMaxChildrenAllowed(), "Child Index is out of bound");
|
||||||
bool childObserved[kMaxChildren];
|
VerifyOrQuit(aTable.GetChildAtIndex(childIndex) == child, "GetChildAtIndex() failed");
|
||||||
uint16_t numChildren = 0;
|
|
||||||
|
|
||||||
memset(childObserved, 0, sizeof(childObserved));
|
|
||||||
|
|
||||||
// Check if the first entry matches the `startingChild`
|
|
||||||
|
|
||||||
if ((startingChild != nullptr) && StateMatchesFilter(startingChild->GetState(), filter))
|
|
||||||
{
|
|
||||||
VerifyOrQuit(!iter.IsDone(), "iterator IsDone() failed");
|
|
||||||
VerifyOrQuit(iter.GetChild() != nullptr, "iterator GetChild() failed");
|
|
||||||
VerifyOrQuit(iter.GetChild() == startingChild,
|
|
||||||
"Iterator failed to start from the given child entry");
|
|
||||||
|
|
||||||
iter++;
|
|
||||||
iter.Reset();
|
|
||||||
VerifyOrQuit(iter.GetChild() == startingChild, "iterator Reset() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the iterator and verify that each returned `Child` entry is in the expected list.
|
|
||||||
|
|
||||||
for (; !iter.IsDone(); iter++)
|
|
||||||
{
|
|
||||||
Child * child = iter.GetChild();
|
|
||||||
bool didFind = false;
|
|
||||||
uint16_t childIndex;
|
|
||||||
|
|
||||||
VerifyOrQuit(child != nullptr, "iter.GetChild() failed");
|
|
||||||
|
|
||||||
childIndex = aTable.GetChildIndex(*child);
|
|
||||||
VerifyOrQuit(childIndex < aTable.GetMaxChildrenAllowed(), "Child Index is out of bound");
|
|
||||||
VerifyOrQuit(aTable.GetChildAtIndex(childIndex) == child, "GetChildAtIndex() failed");
|
|
||||||
|
|
||||||
for (uint16_t index = 0; index < aChildListLength; index++)
|
|
||||||
{
|
|
||||||
if (ChildMatches(*iter.GetChild(), aChildList[index]))
|
|
||||||
{
|
|
||||||
childObserved[index] = true;
|
|
||||||
numChildren++;
|
|
||||||
didFind = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VerifyOrQuit(didFind, "ChildTable::Iterator returned an entry not in the expected list");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that when iterator is done, it points to `nullptr`.
|
|
||||||
|
|
||||||
VerifyOrQuit(iter.GetChild() == nullptr, "iterator GetChild() failed");
|
|
||||||
|
|
||||||
iter++;
|
|
||||||
VerifyOrQuit(iter.IsDone(), "iterator Advance() (after iterator is done) failed");
|
|
||||||
VerifyOrQuit(iter.GetChild() == nullptr, "iterator GetChild() failed");
|
|
||||||
|
|
||||||
// Verify that the number of children matches the number of entries we get from iterator.
|
|
||||||
|
|
||||||
VerifyOrQuit(aTable.GetNumChildren(filter) == numChildren, "GetNumChildren() failed");
|
|
||||||
VerifyOrQuit(aTable.HasChildren(filter) == (numChildren != 0), "HasChildren() failed");
|
|
||||||
|
|
||||||
// Verify that there is no missing or extra entry between the expected list
|
|
||||||
// and what was observed/returned by the iterator.
|
|
||||||
|
|
||||||
for (uint16_t index = 0; index < aChildListLength; index++)
|
for (uint16_t index = 0; index < aChildListLength; index++)
|
||||||
{
|
{
|
||||||
if (StateMatchesFilter(aChildList[index].mState, filter))
|
if (ChildMatches(*iter.GetChild(), aChildList[index]))
|
||||||
{
|
{
|
||||||
VerifyOrQuit(childObserved[index], "iterator failed to return an expected entry");
|
childObserved[index] = true;
|
||||||
}
|
numChildren++;
|
||||||
else
|
didFind = true;
|
||||||
{
|
break;
|
||||||
VerifyOrQuit(!childObserved[index], "iterator returned an extra unexpected entry");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VerifyOrQuit(didFind, "ChildTable::Iterator returned an entry not in the expected list");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that when iterator is done, it points to `nullptr`.
|
||||||
|
|
||||||
|
VerifyOrQuit(iter.GetChild() == nullptr, "iterator GetChild() failed");
|
||||||
|
|
||||||
|
iter++;
|
||||||
|
VerifyOrQuit(iter.IsDone(), "iterator Advance() (after iterator is done) failed");
|
||||||
|
VerifyOrQuit(iter.GetChild() == nullptr, "iterator GetChild() failed");
|
||||||
|
|
||||||
|
// Verify that the number of children matches the number of entries we get from iterator.
|
||||||
|
|
||||||
|
VerifyOrQuit(aTable.GetNumChildren(filter) == numChildren, "GetNumChildren() failed");
|
||||||
|
VerifyOrQuit(aTable.HasChildren(filter) == (numChildren != 0), "HasChildren() failed");
|
||||||
|
|
||||||
|
// Verify that there is no missing or extra entry between the expected list
|
||||||
|
// and what was observed/returned by the iterator.
|
||||||
|
|
||||||
|
for (uint16_t index = 0; index < aChildListLength; index++)
|
||||||
|
{
|
||||||
|
if (StateMatchesFilter(aChildList[index].mState, filter))
|
||||||
|
{
|
||||||
|
VerifyOrQuit(childObserved[index], "iterator failed to return an expected entry");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VerifyOrQuit(!childObserved[index], "iterator returned an extra unexpected entry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the behavior of range-based `for` iteration.
|
||||||
|
|
||||||
|
iter.Reset();
|
||||||
|
|
||||||
|
for (Child &child : aTable.Iterate(filter))
|
||||||
|
{
|
||||||
|
VerifyOrQuit(&child == iter.GetChild(), "range-based for loop Iterate() failed");
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
VerifyOrQuit(iter.IsDone(), "range-based for loop Iterate() did not return all entries");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user