Skip to content

Commit eac4696

Browse files
authored
[mlr] simplify MLR state tracking on Child (openthread#13166)
This commit simplifies MLR state tracking for child devices. Previously, `Child::Ip6AddrEntry` inherited from `Ip6::Address` to encapsulate the MLR registration check using the `Child` reference. This introduced tight coupling between `Child` and `Ip6AddrEntry`. The logic is refactored by removing `Ip6AddrEntry`. Instead, `Child` now directly manages a `Child::Ip6AddressArray` and encapsulates the MLR state querying/updating through new methods: - `SetAddressMlrRegistrationState()` - `GetAllMlrRegisteredAddresses()` - `ClearAllAddressesMlrRegistrationState()` In `Mlr::Manager`, the redundant `ChildAddressArray` typedef and `kMaxChildAddresses` constant are removed, reusing the `Child::Ip6AddressArray`. The method `UpdateProxiedSubscriptions()` is renamed to the more intuitive `UpdateChildRegistrations()`, and overloaded to allow calling it without an old address list during initial child registration.
1 parent 290919b commit eac4696

5 files changed

Lines changed: 94 additions & 120 deletions

File tree

src/core/thread/child.cpp

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,24 +71,6 @@ void Child::Info::SetFrom(const Child &aChild)
7171
mConnectionTime = aChild.GetConnectionTime();
7272
}
7373

74-
//---------------------------------------------------------------------------------------------------------------------
75-
// Child::Ip6AddrEntry
76-
77-
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
78-
79-
bool Child::Ip6AddrEntry::IsMlrRegistered(const Child &aChild) const
80-
{
81-
return aChild.mMlrRegisteredSet.Has(aChild.mIp6Addresses.IndexOf(*this));
82-
}
83-
84-
// NOLINTNEXTLINE(readability-make-member-function-const)
85-
void Child::Ip6AddrEntry::SetMlrRegistered(bool aRegistered, Child &aChild)
86-
{
87-
aChild.mMlrRegisteredSet.Update(aChild.mIp6Addresses.IndexOf(*this), aRegistered);
88-
}
89-
90-
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
91-
9274
//---------------------------------------------------------------------------------------------------------------------
9375
// Child
9476

@@ -182,7 +164,7 @@ Error Child::AddIp6Address(const Ip6::Address &aAddress)
182164
}
183165

184166
VerifyOrExit(!mIp6Addresses.ContainsMatching(aAddress), error = kErrorAlready);
185-
error = mIp6Addresses.PushBack(static_cast<const Ip6AddrEntry &>(aAddress));
167+
error = mIp6Addresses.PushBack(aAddress);
186168

187169
exit:
188170
return error;
@@ -191,7 +173,7 @@ Error Child::AddIp6Address(const Ip6::Address &aAddress)
191173
Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
192174
{
193175
Error error = kErrorNotFound;
194-
Ip6AddrEntry *entry;
176+
Ip6::Address *entry;
195177

196178
if (Get<Mle::Mle>().IsMeshLocalAddress(aAddress))
197179
{
@@ -271,18 +253,44 @@ Error Child::GetDomainUnicastAddress(Ip6::Address &aAddress) const
271253
bool Child::HasMlrRegisteredAddress(const Ip6::Address &aAddress) const
272254
{
273255
bool hasAddress = false;
274-
const Ip6AddrEntry *entry;
256+
const Ip6::Address *entry;
275257

276258
entry = mIp6Addresses.FindMatching(aAddress);
277259
VerifyOrExit(entry != nullptr);
278260

279-
hasAddress = entry->IsMlrRegistered(*this);
261+
hasAddress = mMlrRegisteredSet.Has(mIp6Addresses.IndexOf(*entry));
280262

281263
exit:
282264
return hasAddress;
283265
}
284266

285-
#endif
267+
void Child::SetAddressMlrRegistrationState(const Ip6::Address &aAddress, bool aRegistered)
268+
{
269+
Ip6::Address *entry;
270+
271+
entry = mIp6Addresses.FindMatching(aAddress);
272+
VerifyOrExit(entry != nullptr);
273+
274+
mMlrRegisteredSet.Update(mIp6Addresses.IndexOf(*entry), aRegistered);
275+
276+
exit:
277+
return;
278+
}
279+
280+
void Child::GetAllMlrRegisteredAddresses(Ip6AddressArray &aAddressArray) const
281+
{
282+
aAddressArray.Clear();
283+
284+
for (const Ip6::Address &entry : mIp6Addresses)
285+
{
286+
if (mMlrRegisteredSet.Has(mIp6Addresses.IndexOf(entry)))
287+
{
288+
IgnoreError(aAddressArray.PushBack(entry));
289+
}
290+
}
291+
}
292+
293+
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
286294

287295
#endif // OPENTHREAD_FTD
288296

src/core/thread/child.hpp

Lines changed: 27 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ class Child : public CslNeighbor
6060
*/
6161
static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1;
6262

63+
/**
64+
* Represents an array of IPv6 addresses registered by an MTD child.
65+
*
66+
* This array does not include the mesh-local EID.
67+
*/
68+
typedef Array<Ip6::Address, kNumIp6Addresses> Ip6AddressArray;
69+
6370
/**
6471
* Represents the iterator for registered IPv6 address list of an MTD child.
6572
*/
@@ -84,50 +91,6 @@ class Child : public CslNeighbor
8491
void SetFrom(const Child &aChild);
8592
};
8693

87-
/**
88-
* Represents an IPv6 address entry registered by an MTD child.
89-
*/
90-
class Ip6AddrEntry : public Ip6::Address
91-
{
92-
public:
93-
/**
94-
* Indicates whether the entry matches a given IPv6 address.
95-
*
96-
* @param[in] aAddress The IPv6 address.
97-
*
98-
* @retval TRUE The entry matches @p aAddress.
99-
* @retval FALSE The entry does not match @p aAddress.
100-
*/
101-
bool Matches(const Ip6::Address &aAddress) const { return (*this == aAddress); }
102-
103-
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
104-
/**
105-
* Indicates whether the IPv6 address is registered via Multicast Listener Registration (MLR) on a given child.
106-
*
107-
* @param[in] aChild The child associated with the address.
108-
*
109-
* @retval TRUE If the address is MLR registered on @p aChild.
110-
* @retval FALSE If the address is not MLR registered on @p aChild.
111-
*/
112-
bool IsMlrRegistered(const Child &aChild) const;
113-
114-
/**
115-
* Sets whether the IPv6 address is registered via Multicast Listener Registration (MLR) on a given child.
116-
*
117-
* @param[in] aRegistered TRUE if MLR registered, FALSE otherwise.
118-
* @param[in] aChild The child associated with the address.
119-
*/
120-
void SetMlrRegistered(bool aRegistered, Child &aChild);
121-
#endif
122-
};
123-
124-
/**
125-
* Represents an array of IPv6 address entries registered by an MTD child.
126-
*
127-
* This array does not include the mesh-local EID.
128-
*/
129-
typedef Array<Ip6AddrEntry, kNumIp6Addresses> Ip6AddressArray;
130-
13194
/**
13295
* Initializes the `Child` object.
13396
*
@@ -178,15 +141,6 @@ class Child : public CslNeighbor
178141
*/
179142
const Ip6AddressArray &GetIp6Addresses(void) const { return mIp6Addresses; }
180143

181-
/**
182-
* Gets an array of registered IPv6 address entries by the child.
183-
*
184-
* The array does not include the mesh-local EID. The ML-EID can retrieved using `GetMeshLocalIp6Address()`.
185-
*
186-
* @returns The array of registered IPv6 addresses by the child.
187-
*/
188-
Ip6AddressArray &GetIp6Addresses(void) { return mIp6Addresses; }
189-
190144
/**
191145
* Iterates over all registered IPv6 addresses (using an iterator).
192146
*
@@ -202,7 +156,7 @@ class Child : public CslNeighbor
202156
/**
203157
* Adds an IPv6 address to the list.
204158
*
205-
* @param[in] aAddress A reference to IPv6 address to be added.
159+
* @param[in] aAddress The IPv6 address to be added.
206160
*
207161
* @retval kErrorNone Successfully added the new address.
208162
* @retval kErrorAlready Address is already in the list.
@@ -214,7 +168,7 @@ class Child : public CslNeighbor
214168
/**
215169
* Removes an IPv6 address from the list.
216170
*
217-
* @param[in] aAddress A reference to IPv6 address to be removed.
171+
* @param[in] aAddress The IPv6 address to be removed.
218172
*
219173
* @retval kErrorNone Successfully removed the address.
220174
* @retval kErrorNotFound Address was not found in the list.
@@ -225,7 +179,7 @@ class Child : public CslNeighbor
225179
/**
226180
* Indicates whether an IPv6 address is in the list of IPv6 addresses of the child.
227181
*
228-
* @param[in] aAddress A reference to IPv6 address.
182+
* @param[in] aAddress The IPv6 address to check.
229183
*
230184
* @retval TRUE The address exists on the list.
231185
* @retval FALSE Address was not found in the list.
@@ -353,10 +307,11 @@ class Child : public CslNeighbor
353307
void SetBlockParentDowngrade(bool aBlock) { mBlockParentDowngrade = aBlock; }
354308

355309
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
310+
356311
/**
357-
* Clears the Multicast Listener Registration (MLR) registered state on all IPv6 addresses of the child.
312+
* Clears the Multicast Listener Registration (MLR) registration state of all IPv6 addresses of the child.
358313
*/
359-
void ClearMlrRegisteredStateOnAllIp6Addresses(void) { mMlrRegisteredSet.Clear(); }
314+
void ClearAllAddressesMlrRegistrationState(void) { mMlrRegisteredSet.Clear(); }
360315

361316
/**
362317
* Indicates whether the child has a given IPv6 address that is MLR registered.
@@ -369,12 +324,22 @@ class Child : public CslNeighbor
369324
bool HasMlrRegisteredAddress(const Ip6::Address &aAddress) const;
370325

371326
/**
372-
* Indicates whether the child has any IPv6 address that is MLR registered.
327+
* Sets the MLR registered state of a given IPv6 address of the child.
328+
*
329+
* If @p aAddress is not present on the list, calling this method does nothing.
373330
*
374-
* @retval TRUE If the child has any MLR registered IPv6 address.
375-
* @retval FALSE If the child does not have any MLR registered IPv6 address.
331+
* @param[in] aAddress The address.
332+
* @param[in] aRegistered TRUE if MLR registered, FALSE otherwise.
376333
*/
377-
bool HasAnyMlrRegisteredAddress(void) const { return !mMlrRegisteredSet.IsEmpty(); }
334+
void SetAddressMlrRegistrationState(const Ip6::Address &aAddress, bool aRegistered);
335+
336+
/**
337+
* Gets all the MLR registered IPv6 addresses of the child.
338+
*
339+
* @param[out] aAddressArray A reference to an array to output the addresses.
340+
*/
341+
void GetAllMlrRegisteredAddresses(Ip6AddressArray &aAddressArray) const;
342+
378343
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
379344

380345
private:

src/core/thread/mle_ftd.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,7 @@ Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
18301830
Ip6::Address oldDua;
18311831
#endif
18321832
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1833-
Mlr::Manager::ChildAddressArray oldMlrRegisteredAddresses;
1833+
Child::Ip6AddressArray oldMlrRegisteredAddresses;
18341834
#endif
18351835

18361836
OT_UNUSED_VARIABLE(storedCount);
@@ -1845,16 +1845,7 @@ Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
18451845
#endif
18461846

18471847
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1848-
if (aChild.HasAnyMlrRegisteredAddress())
1849-
{
1850-
for (const Child::Ip6AddrEntry &addrEntry : aChild.GetIp6Addresses())
1851-
{
1852-
if (addrEntry.IsMlrRegistered(aChild))
1853-
{
1854-
IgnoreError(oldMlrRegisteredAddresses.PushBack(addrEntry));
1855-
}
1856-
}
1857-
}
1848+
aChild.GetAllMlrRegisteredAddresses(oldMlrRegisteredAddresses);
18581849
#endif
18591850

18601851
aChild.ClearIp6Addresses();
@@ -1946,7 +1937,7 @@ Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
19461937
#endif
19471938

19481939
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
1949-
Get<Mlr::Manager>().UpdateProxiedSubscriptions(aChild, oldMlrRegisteredAddresses);
1940+
Get<Mlr::Manager>().UpdateChildRegistrations(aChild, oldMlrRegisteredAddresses);
19501941
#endif
19511942

19521943
if (count == 0)
@@ -3812,7 +3803,7 @@ void Mle::SetChildStateToValid(Child &aChild)
38123803
IgnoreError(mChildTable.StoreChild(aChild));
38133804

38143805
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
3815-
Get<Mlr::Manager>().UpdateProxiedSubscriptions(aChild, Mlr::Manager::ChildAddressArray());
3806+
Get<Mlr::Manager>().UpdateChildRegistrations(aChild);
38163807
#endif
38173808

38183809
mNeighborTable.Signal(NeighborTable::kChildAdded, aChild);

src/core/thread/mlr_manager.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void Manager::EnterState(State aState)
8282
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
8383
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
8484
{
85-
child.ClearMlrRegisteredStateOnAllIp6Addresses();
85+
child.ClearAllAddressesMlrRegistrationState();
8686
}
8787
#endif
8888
}
@@ -256,29 +256,36 @@ bool Manager::IsAddressRegisteredByAnyChildExcept(const Ip6::Address &aAddress,
256256
return isRegistered;
257257
}
258258

259-
void Manager::UpdateProxiedSubscriptions(Child &aChild, const ChildAddressArray &aOldRegisteredAddresses)
259+
void Manager::UpdateChildRegistrations(Child &aChild)
260+
{
261+
Child::Ip6AddressArray emptyArray;
262+
263+
UpdateChildRegistrations(aChild, emptyArray);
264+
}
265+
266+
void Manager::UpdateChildRegistrations(Child &aChild, const Child::Ip6AddressArray &aOldRegisteredAddresses)
260267
{
261268
bool hasUnregistered = false;
262269

263270
VerifyOrExit(aChild.IsStateValid());
264271

265-
for (Child::Ip6AddrEntry &addrEntry : aChild.GetIp6Addresses())
272+
for (const Ip6::Address &addr : aChild.GetIp6Addresses())
266273
{
267274
bool isRegistered;
268275

269-
if (!addrEntry.IsMulticastLargerThanRealmLocal())
276+
if (!addr.IsMulticastLargerThanRealmLocal())
270277
{
271278
continue;
272279
}
273280

274-
isRegistered = aOldRegisteredAddresses.Contains(addrEntry);
281+
isRegistered = aOldRegisteredAddresses.ContainsMatching(addr);
275282

276283
#if OPENTHREAD_CONFIG_MLR_ENABLE
277-
isRegistered = isRegistered || IsAddressRegisteredByNetif(addrEntry);
284+
isRegistered = isRegistered || IsAddressRegisteredByNetif(addr);
278285
#endif
279-
isRegistered = isRegistered || IsAddressRegisteredByAnyChildExcept(addrEntry, &aChild);
286+
isRegistered = isRegistered || IsAddressRegisteredByAnyChildExcept(addr, &aChild);
280287

281-
addrEntry.SetMlrRegistered(isRegistered, aChild);
288+
aChild.SetAddressMlrRegistrationState(addr, isRegistered);
282289

283290
if (!isRegistered)
284291
{
@@ -347,11 +354,11 @@ void Manager::DetermineAddressesToRegister(AddressArray &aAddresses) const
347354
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
348355
for (const Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
349356
{
350-
for (const Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
357+
for (const Ip6::Address &addr : child.GetIp6Addresses())
351358
{
352-
if (addrEntry.IsMulticastLargerThanRealmLocal() && !addrEntry.IsMlrRegistered(child))
359+
if (addr.IsMulticastLargerThanRealmLocal() && !child.HasMlrRegisteredAddress(addr))
353360
{
354-
SuccessOrExit(aAddresses.AddUnique(addrEntry));
361+
SuccessOrExit(aAddresses.AddUnique(addr));
355362
}
356363
}
357364
}
@@ -606,12 +613,12 @@ void Manager::ProcessResponse(Coap::Msg *aMsg, Error aResult)
606613
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
607614
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
608615
{
609-
for (Child::Ip6AddrEntry &addrEntry : child.GetIp6Addresses())
616+
for (const Ip6::Address &addr : child.GetIp6Addresses())
610617
{
611-
if (addrEntry.IsMulticastLargerThanRealmLocal() && !addrEntry.IsMlrRegistered(child) &&
612-
registeredAddresses.Contains(addrEntry))
618+
if (addr.IsMulticastLargerThanRealmLocal() && !child.HasMlrRegisteredAddress(addr) &&
619+
registeredAddresses.Contains(addr))
613620
{
614-
addrEntry.SetMlrRegistered(true, child);
621+
child.SetAddressMlrRegistrationState(addr, true);
615622
}
616623
}
617624
}

src/core/thread/mlr_manager.hpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ class Manager : public InstanceLocator, private NonCopyable
9797
void HandleBackboneRouterPrimaryUpdate(BackboneRouter::PrimaryEvent aEvent);
9898

9999
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
100-
static constexpr uint16_t kMaxChildAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; ///< Max MLR addresses
101-
102-
typedef Array<Ip6::Address, kMaxChildAddresses> ChildAddressArray; ///< Registered MLR addresses array.
100+
/**
101+
* Updates the MLR registration status of a given child's addresses.
102+
*
103+
* @param[in] aChild The child to update.
104+
*/
105+
void UpdateChildRegistrations(Child &aChild);
103106

104107
/**
105-
* Updates the Multicast Subscription Table according to the Child information.
108+
* Updates the MLR registration status of a given child's addresses.
106109
*
107-
* @param[in] aChild A reference to the child information.
108-
* @param[in] aOldRegisteredAddresses Array of the Child's previously registered IPv6 addresses.
110+
* @param[in] aChild The child to update.
111+
* @param[in] aOldRegisteredAddresses Child's previously registered addresses.
109112
*/
110-
void UpdateProxiedSubscriptions(Child &aChild, const ChildAddressArray &aOldRegisteredAddresses);
113+
void UpdateChildRegistrations(Child &aChild, const Child::Ip6AddressArray &aOldRegisteredAddresses);
111114
#endif
112115

113116
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE

0 commit comments

Comments
 (0)