diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index 1878eee97..16bf8e7a4 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -163,12 +163,12 @@ exit: return error; } -void AddressResolver::Remove(uint8_t aRouterId) +void AddressResolver::RemoveEntriesForRouterId(uint8_t aRouterId) { Remove(Mle::Rloc16FromRouterId(aRouterId), /* aMatchRouterId */ true); } -void AddressResolver::Remove(uint16_t aRloc16) { Remove(aRloc16, /* aMatchRouterId */ false); } +void AddressResolver::RemoveEntriesForRloc16(uint16_t aRloc16) { Remove(aRloc16, /* aMatchRouterId */ false); } AddressResolver::CacheEntry *AddressResolver::GetEntryAfter(CacheEntry *aPrev, CacheEntryList &aList) { @@ -221,7 +221,7 @@ exit: return entry; } -void AddressResolver::Remove(const Ip6::Address &aEid) { Remove(aEid, kReasonRemovingEid); } +void AddressResolver::RemoveEntryForAddress(const Ip6::Address &aEid) { Remove(aEid, kReasonRemovingEid); } void AddressResolver::Remove(const Ip6::Address &aEid, Reason aReason) { @@ -239,6 +239,22 @@ exit: return; } +void AddressResolver::ReplaceEntriesForRloc16(uint16_t aOldRloc16, uint16_t aNewRloc16) +{ + CacheEntryList *lists[] = {&mCachedList, &mSnoopedList}; + + for (CacheEntryList *list : lists) + { + for (CacheEntry &entry : *list) + { + if (entry.GetRloc16() == aOldRloc16) + { + entry.SetRloc16(aNewRloc16); + } + } + } +} + AddressResolver::CacheEntry *AddressResolver::NewCacheEntry(bool aSnoopedEntry) { CacheEntry *newEntry = nullptr; diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp index 9c45df63a..81ee36be5 100644 --- a/src/core/thread/address_resolver.hpp +++ b/src/core/thread/address_resolver.hpp @@ -139,7 +139,7 @@ public: * @param[in] aRloc16 The RLOC16 address. * */ - void Remove(Mac::ShortAddress aRloc16); + void RemoveEntriesForRloc16(Mac::ShortAddress aRloc16); /** * This method removes all EID-to-RLOC cache entries associated with a Router ID. @@ -147,7 +147,7 @@ public: * @param[in] aRouterId The Router ID. * */ - void Remove(uint8_t aRouterId); + void RemoveEntriesForRouterId(uint8_t aRouterId); /** * This method removes the cache entry for the EID. @@ -155,7 +155,16 @@ public: * @param[in] aEid A reference to the EID. * */ - void Remove(const Ip6::Address &aEid); + void RemoveEntryForAddress(const Ip6::Address &aEid); + + /** + * This method replaces all EID-to-RLOC cache entries corresponding to an old RLOC16 with a new RLOC16. + * + * @param[in] aOldRloc16 The old RLOC16. + * @param[in] aNewRloc16 The new RLOC16. + * + */ + void ReplaceEntriesForRloc16(uint16_t aOldRloc16, uint16_t aNewRloc16); /** * This method updates an existing entry or adds a snooped cache entry for a given EID. diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 74071fc77..30d6f76c1 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1316,6 +1316,10 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, c DeviceMode::kModeFullNetworkData)); mNeighborTable.Signal(NeighborTable::kRouterAdded, *router); + + // Change the cache entries associated with the former child + // from using the old RLOC16 to its new RLOC16. + Get().ReplaceEntriesForRloc16(aRxInfo.mNeighbor->GetRloc16(), router->GetRloc16()); } // Send unicast link request if no link to router and no unicast/multicast link request in progress @@ -1955,7 +1959,7 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild) } // Clear EID-to-RLOC cache for the unicast address registered by the child. - Get().Remove(address); + Get().RemoveEntryForAddress(address); } #if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE // Dua is removed @@ -3254,7 +3258,7 @@ void MleRouter::RemoveNeighbor(Neighbor &aNeighbor) if (aNeighbor.IsFullThreadDevice()) { // Clear all EID-to-RLOC entries associated with the child. - Get().Remove(aNeighbor.GetRloc16()); + Get().RemoveEntriesForRloc16(aNeighbor.GetRloc16()); } mChildTable.RemoveStoredChild(static_cast(aNeighbor)); @@ -3675,6 +3679,21 @@ void MleRouter::SendAddressSolicitResponse(const Coap::Message &aRequest, Log(kMessageSend, kTypeAddressReply, aMessageInfo.GetPeerAddr()); + // If assigning a new RLOC16 (e.g., on promotion of a child to + // router role) we clear any address cache entries associated + // with the old RLOC16. + + if ((aResponseStatus == ThreadStatusTlv::kSuccess) && (aRouter != nullptr)) + { + uint16_t oldRloc16; + + VerifyOrExit(IsRoutingLocator(aMessageInfo.GetPeerAddr())); + oldRloc16 = aMessageInfo.GetPeerAddr().GetIid().GetLocator(); + + VerifyOrExit(oldRloc16 != aRouter->GetRloc16()); + Get().RemoveEntriesForRloc16(oldRloc16); + } + exit: FreeMessage(message); } diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index 8faced1ee..407f51117 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -216,7 +216,7 @@ Error RouterTable::Release(uint8_t aRouterId) mRouterIdSequence++; mRouterIdSequenceLastUpdated = TimerMilli::GetNow(); - Get().Remove(aRouterId); + Get().RemoveEntriesForRouterId(aRouterId); Get().RemoveBorderRouter(Mle::Rloc16FromRouterId(aRouterId), NetworkData::Leader::kMatchModeRouterId); Get().ResetAdvertiseInterval(); @@ -255,7 +255,7 @@ void RouterTable::RemoveRouterLink(Router &aRouter) Get().ResetAdvertiseInterval(); // Clear all EID-to-RLOC entries associated with the router. - Get().Remove(aRouter.GetRouterId()); + Get().RemoveEntriesForRouterId(aRouter.GetRouterId()); } }