From 34ecac8536f6a8e23391b7f25b7ec401bf1ae305 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Sat, 29 Apr 2023 10:41:45 -0700 Subject: [PATCH] [mle] clear/update address cache entries on promotion of child to router (#8987) This commit contains two related changes: - On a parent, when we detect a former child has been promoted to router role by receiving an MLE Advertisement from it, we replace the address cache entries associated with the old (child) RLOC16 with it new RLOC16. - On leader, when we successfully reply to an "Address Solicit" message and assign a new RLOC16 to a node, we clear all entries associated with old RLOC16. We do not change to new RLOC16 since we cannot be sure that child will successfully receive the Address Solicit" response. --- src/core/thread/address_resolver.cpp | 22 +++++++++++++++++++--- src/core/thread/address_resolver.hpp | 15 ++++++++++++--- src/core/thread/mle_router.cpp | 23 +++++++++++++++++++++-- src/core/thread/router_table.cpp | 4 ++-- 4 files changed, 54 insertions(+), 10 deletions(-) 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()); } }