mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 21:57:47 +00:00
[routing-manager] fix small OMR prefix election issue (#7405)
This commit fixes two small issues regarding OMR prefix election:
- This commit handles the case where `mLocalOmrPrefix` is already in
Leader's Network Data, but not locally added. It is possible when
the BR restores the Network Data from Leader. In such case the BR
should re-add `mLocalOmrPrefix` to local Network Data so that it
keeps advertising OMR Prefix. Otherwise, the OMR Prefix will be
removed from Leader's Network Data because of Network Data
inconsistentency, and then all BRs start to re-elect OMR Prefix. So,
the change will make the OMR Prefix more stable in some corner
cases.
- The change here checks if `mLocalOmrPrefix` was added to the Local
Network Data, instead of checking if `mLocalOmrPrefix` is added to
the Leader's Network Data. Here the BR has already decided that it
should not be advertising `mLocalOmrPrefix`. Whether or not
`mLocalOmrPrefix` is in Leader's Network Data is relevant. The BR
only needs to remove `mLocalOmrPrefix` from Local Network Data and
eventually Local Network Data will synchronize with Leader's Network
Data. The original code also has a potential issue that the BR may
send `NET_DATA.ntf` to Leader indefinitely when these conditions are
met:
- `mLocalOmrPrefix` was added to Local Network Data
- `mLocalOmrPrefix` is not added to Leader' Network Data because
there is no more space in Leader's Network Data
This commit is contained in:
@@ -462,18 +462,29 @@ void RoutingManager::EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes)
|
||||
// The `aNewOmrPrefixes` remains empty if we fail to publish
|
||||
// the local OMR prefix.
|
||||
}
|
||||
else if (publishedLocalOmrPrefix != nullptr && smallestOmrPrefix != publishedLocalOmrPrefix)
|
||||
else
|
||||
{
|
||||
LogInfo("EvaluateOmrPrefix: There is already a smaller OMR prefix %s in the Thread network",
|
||||
smallestOmrPrefix->ToString().AsCString());
|
||||
OT_ASSERT(smallestOmrPrefix != nullptr);
|
||||
|
||||
UnpublishLocalOmrPrefix();
|
||||
if (*smallestOmrPrefix == mLocalOmrPrefix)
|
||||
{
|
||||
IgnoreError(PublishLocalOmrPrefix());
|
||||
}
|
||||
else if (IsOmrPrefixAddedToLocalNetworkData())
|
||||
{
|
||||
LogInfo("EvaluateOmrPrefix: There is already a smaller OMR prefix %s in the Thread network",
|
||||
smallestOmrPrefix->ToString().AsCString());
|
||||
|
||||
// Remove the local OMR prefix from the list by overwriting it
|
||||
// with the last element and then popping it from the list.
|
||||
UnpublishLocalOmrPrefix();
|
||||
|
||||
*publishedLocalOmrPrefix = *aNewOmrPrefixes.Back();
|
||||
aNewOmrPrefixes.PopBack();
|
||||
// Remove the local OMR prefix from the list by overwriting it
|
||||
// with the last element and then popping it from the list.
|
||||
if (publishedLocalOmrPrefix != nullptr)
|
||||
{
|
||||
*publishedLocalOmrPrefix = *aNewOmrPrefixes.Back();
|
||||
aNewOmrPrefixes.PopBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +495,8 @@ Error RoutingManager::PublishLocalOmrPrefix(void)
|
||||
|
||||
OT_ASSERT(mIsRunning);
|
||||
|
||||
VerifyOrExit(!IsOmrPrefixAddedToLocalNetworkData());
|
||||
|
||||
omrPrefixConfig.Clear();
|
||||
omrPrefixConfig.mPrefix = mLocalOmrPrefix;
|
||||
omrPrefixConfig.mStable = true;
|
||||
@@ -505,6 +518,7 @@ Error RoutingManager::PublishLocalOmrPrefix(void)
|
||||
LogInfo("Publishing local OMR prefix %s in Thread network", mLocalOmrPrefix.ToString().AsCString());
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -514,6 +528,8 @@ void RoutingManager::UnpublishLocalOmrPrefix(void)
|
||||
|
||||
VerifyOrExit(mIsRunning);
|
||||
|
||||
VerifyOrExit(IsOmrPrefixAddedToLocalNetworkData());
|
||||
|
||||
SuccessOrExit(error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mLocalOmrPrefix));
|
||||
|
||||
Get<NetworkData::Notifier>().HandleServerDataUpdated();
|
||||
@@ -527,6 +543,11 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
bool RoutingManager::IsOmrPrefixAddedToLocalNetworkData(void) const
|
||||
{
|
||||
return Get<NetworkData::Local>().ContainsOnMeshPrefix(mLocalOmrPrefix);
|
||||
}
|
||||
|
||||
Error RoutingManager::AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64)
|
||||
{
|
||||
Error error;
|
||||
|
||||
@@ -305,6 +305,7 @@ private:
|
||||
void EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes);
|
||||
Error PublishLocalOmrPrefix(void);
|
||||
void UnpublishLocalOmrPrefix(void);
|
||||
bool IsOmrPrefixAddedToLocalNetworkData(void) const;
|
||||
Error AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
|
||||
void RemoveExternalRoute(const Ip6::Prefix &aPrefix);
|
||||
void StartRouterSolicitationDelay(void);
|
||||
|
||||
@@ -69,6 +69,20 @@ Error Local::RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix)
|
||||
return RemovePrefix(aPrefix, NetworkDataTlv::kTypeBorderRouter);
|
||||
}
|
||||
|
||||
bool Local::ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
const PrefixTlv *tlv;
|
||||
bool contains = false;
|
||||
|
||||
VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr);
|
||||
VerifyOrExit(tlv->FindSubTlv(NetworkDataTlv::kTypeBorderRouter) != nullptr);
|
||||
|
||||
contains = true;
|
||||
|
||||
exit:
|
||||
return contains;
|
||||
}
|
||||
|
||||
Error Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
|
||||
{
|
||||
Error error = kErrorInvalidArgs;
|
||||
|
||||
@@ -97,6 +97,17 @@ public:
|
||||
*/
|
||||
Error RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Thread Network Data contains a given on mesh prefix.
|
||||
*
|
||||
* @param[in] aPrefix The on mesh prefix to check.
|
||||
*
|
||||
* @retval TRUE if Network Data contains mesh prefix @p aPrefix.
|
||||
* @retval FALSE if Network Data does not contain mesh prefix @p aPrefix.
|
||||
*
|
||||
*/
|
||||
bool ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const;
|
||||
|
||||
/**
|
||||
* This method adds a Has Route entry to the Thread Network data.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user