[netdata] update Publisher to reserve entries for RoutingManager (#8148)

This commit updates `NetworkData::Publisher` to reserve a set of
prefix entries for use by `RoutingManager` only. This allow us to
simplify how `RoutingManager` publishes route prefixes in Network
Data (assert on failure). In particular, this commit defines a new
enum `Requester` which specifies the requester (`kFromUser` or
`kFromRoutingManager`) associated with a published prefix. This is
used by methods `PublishExternalRoute()`/`PublishOnMeshPrefix()`.
When allocating new entries, we ensure that each requester is
limited to its maximum number of entries.
This commit is contained in:
Abtin Keshavarzian
2022-10-11 12:57:33 -07:00
committed by GitHub
parent ee83b1cb5d
commit 04feddc458
6 changed files with 122 additions and 75 deletions
+4 -2
View File
@@ -82,12 +82,14 @@ void otNetDataUnpublishDnsSrpService(otInstance *aInstance)
otError otNetDataPublishOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig)
{
return AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishOnMeshPrefix(AsCoreType(aConfig));
return AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishOnMeshPrefix(AsCoreType(aConfig),
NetworkData::Publisher::kFromUser);
}
otError otNetDataPublishExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig)
{
return AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishExternalRoute(AsCoreType(aConfig));
return AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishExternalRoute(AsCoreType(aConfig),
NetworkData::Publisher::kFromUser);
}
bool otNetDataIsPrefixAdded(otInstance *aInstance, const otIp6Prefix *aPrefix)
+10 -19
View File
@@ -458,9 +458,8 @@ exit:
return;
}
Error RoutingManager::PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64)
void RoutingManager::PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64)
{
Error error;
NetworkData::ExternalRouteConfig routeConfig;
OT_ASSERT(mIsRunning);
@@ -471,14 +470,8 @@ Error RoutingManager::PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePref
routeConfig.mNat64 = aNat64;
routeConfig.mPreference = aRoutePreference;
error = Get<NetworkData::Publisher>().PublishExternalRoute(routeConfig);
if (error != kErrorNone)
{
LogWarn("Failed to publish external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
}
return error;
SuccessOrAssert(
Get<NetworkData::Publisher>().PublishExternalRoute(routeConfig, NetworkData::Publisher::kFromRoutingManager));
}
void RoutingManager::UnpublishExternalRoute(const Ip6::Prefix &aPrefix)
@@ -507,7 +500,7 @@ void RoutingManager::EvaluateOnLinkPrefix(void)
// and therefore is the same for all BRs on the same Thread
// mesh.
SuccessOrExit(mLocalOnLinkPrefix.Advertise());
mLocalOnLinkPrefix.Advertise();
// We remove the local on-link prefix from discovered prefix
// table, in case it was previously discovered and included in
@@ -1616,7 +1609,7 @@ exit:
void RoutingManager::DiscoveredPrefixTable::PublishEntry(const Entry &aEntry)
{
IgnoreError(Get<RoutingManager>().PublishExternalRoute(aEntry.GetPrefix(), aEntry.GetPreference()));
Get<RoutingManager>().PublishExternalRoute(aEntry.GetPrefix(), aEntry.GetPreference());
}
void RoutingManager::DiscoveredPrefixTable::UnpublishEntry(const Entry &aEntry)
@@ -2015,24 +2008,22 @@ exit:
return;
}
Error RoutingManager::LocalOnLinkPrefix::Advertise(void)
void RoutingManager::LocalOnLinkPrefix::Advertise(void)
{
// Start advertising the local on-link prefix if not already. This
// will also publish it in the Network Data as an external route
// entry.
Error error = kErrorNone;
VerifyOrExit(mState != kAdvertising);
SuccessOrExit(error = Get<RoutingManager>().PublishExternalRoute(mPrefix, NetworkData::kRoutePreferenceMedium));
Get<RoutingManager>().PublishExternalRoute(mPrefix, NetworkData::kRoutePreferenceMedium);
mState = kAdvertising;
mExpireTime = TimerMilli::GetNow() + TimeMilli::SecToMsec(kDefaultOnLinkPrefixLifetime);
LogInfo("Start advertising on-link prefix %s", mPrefix.ToString().AsCString());
exit:
return error;
return;
}
void RoutingManager::LocalOnLinkPrefix::Deprecate(void)
@@ -2316,9 +2307,9 @@ void RoutingManager::Nat64PrefixManager::Evaluate(void)
mPublishedPrefix.Clear();
}
if (shouldPublish && (prefix != mPublishedPrefix) &&
(Get<RoutingManager>().PublishExternalRoute(prefix, preference, /* aNat64 */ true) == kErrorNone))
if (shouldPublish && (prefix != mPublishedPrefix))
{
Get<RoutingManager>().PublishExternalRoute(prefix, preference, /* aNat64 */ true);
mPublishedPrefix = prefix;
}
+24 -10
View File
@@ -85,6 +85,20 @@ public:
typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry.
/**
* This constant specifies the maximum number of route prefixes that may be published by `RoutingManager`
* in Thread Network Data.
*
* This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`.
*
* The number of published entries accounts for:
* - Max number of discovered prefix entries,
* - Two entries for local on-link prefixes (current prefix and old one deprecating on extended PAN ID change),
* - One entry for NAT64 published prefix.
*
*/
static constexpr uint16_t kMaxPublishedPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 3;
/**
* This constructor initializes the routing manager.
*
@@ -605,7 +619,7 @@ private:
void Generate(void);
void Start(void);
void Stop(void);
Error Advertise(void);
void Advertise(void);
void Deprecate(void);
void AppendAsPiosTo(Ip6::Nd::RouterAdvertMessage &aRaMessage);
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
@@ -747,15 +761,15 @@ private:
bool IsEnabled(void) const { return mIsEnabled; }
Error LoadOrGenerateRandomBrUlaPrefix(void);
void EvaluateOnLinkPrefix(void);
void EvaluateRoutingPolicy(void);
bool IsInitalPolicyEvaluationDone(void) const;
void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
void EvaluateOmrPrefix(void);
Error PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
void UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
void HandleRsSenderFinished(TimeMilli aStartTime);
void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
void EvaluateOnLinkPrefix(void);
void EvaluateRoutingPolicy(void);
bool IsInitalPolicyEvaluationDone(void) const;
void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
void EvaluateOmrPrefix(void);
void PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
void UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
void HandleRsSenderFinished(TimeMilli aStartTime);
void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
void HandleDiscoveredPrefixStaleTimer(void);
+2 -7
View File
@@ -148,17 +148,12 @@
/**
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
*
* Specifies maximum number of prefix (on-mesh prefix or external route) entries supported by Publisher.
* Specifies maximum number of prefix (on-mesh prefix or external route) entries reserved by Publisher for use by
* user (through OT public APIs).
*
*/
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES \
(OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 5)
#else
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3
#endif
#endif
#endif // CONFIG_NETDATA_PUBLISHER_H_
+46 -17
View File
@@ -87,7 +87,7 @@ void Publisher::SetPrefixCallback(PrefixCallback aCallback, void *aContext)
mPrefixCallbackContext = aContext;
}
Error Publisher::PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
Error Publisher::PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig, Requester aRequester)
{
Error error = kErrorNone;
PrefixEntry *entry;
@@ -95,16 +95,16 @@ Error Publisher::PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
VerifyOrExit(aConfig.mStable, error = kErrorInvalidArgs);
entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix());
entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix(), aRequester);
VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
entry->Publish(aConfig);
entry->Publish(aConfig, aRequester);
exit:
return error;
}
Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig)
Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig, Requester aRequester)
{
Error error = kErrorNone;
PrefixEntry *entry;
@@ -112,10 +112,10 @@ Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig)
VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
VerifyOrExit(aConfig.mStable, error = kErrorInvalidArgs);
entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix());
entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix(), aRequester);
VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
entry->Publish(aConfig);
entry->Publish(aConfig, aRequester);
exit:
return error;
@@ -149,24 +149,48 @@ exit:
return error;
}
Publisher::PrefixEntry *Publisher::FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix)
Publisher::PrefixEntry *Publisher::FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix, Requester aRequester)
{
// Returns a matching prefix entry if found, otherwise tries
// to allocate a new entry.
PrefixEntry *prefixEntry = FindMatchingPrefixEntry(aPrefix);
VerifyOrExit(prefixEntry == nullptr);
PrefixEntry *prefixEntry = nullptr;
uint16_t numEntries = 0;
uint8_t maxEntries = 0;
for (PrefixEntry &entry : mPrefixEntries)
{
if (!entry.IsInUse())
if (entry.IsInUse())
{
if (entry.GetRequester() == aRequester)
{
numEntries++;
}
if (entry.Matches(aPrefix))
{
prefixEntry = &entry;
ExitNow();
}
}
else if (prefixEntry == nullptr)
{
prefixEntry = &entry;
ExitNow();
}
}
switch (aRequester)
{
case kFromUser:
maxEntries = kMaxUserPrefixEntries;
break;
case kFromRoutingManager:
maxEntries = kMaxRoutingManagerPrefixEntries;
break;
}
VerifyOrExit(numEntries < maxEntries, prefixEntry = nullptr);
exit:
return prefixEntry;
}
@@ -786,22 +810,27 @@ Publisher::DnsSrpServiceEntry::Info::Info(Type aType, uint16_t aPortOrSeqNumber,
//---------------------------------------------------------------------------------------------------------------------
// Publisher::PrefixEntry
void Publisher::PrefixEntry::Publish(const OnMeshPrefixConfig &aConfig)
void Publisher::PrefixEntry::Publish(const OnMeshPrefixConfig &aConfig, Requester aRequester)
{
LogInfo("Publishing OnMeshPrefix %s", aConfig.GetPrefix().ToString().AsCString());
Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeOnMeshPrefix);
Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeOnMeshPrefix, aRequester);
}
void Publisher::PrefixEntry::Publish(const ExternalRouteConfig &aConfig)
void Publisher::PrefixEntry::Publish(const ExternalRouteConfig &aConfig, Requester aRequester)
{
LogInfo("Publishing ExternalRoute %s", aConfig.GetPrefix().ToString().AsCString());
Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeExternalRoute);
Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeExternalRoute, aRequester);
}
void Publisher::PrefixEntry::Publish(const Ip6::Prefix &aPrefix, uint16_t aNewFlags, Type aNewType)
void Publisher::PrefixEntry::Publish(const Ip6::Prefix &aPrefix,
uint16_t aNewFlags,
Type aNewType,
Requester aRequester)
{
mRequester = aRequester;
if (GetState() != kNoEntry)
{
// If this is an existing entry, first we check that there is
+36 -20
View File
@@ -43,14 +43,9 @@
"or OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE"
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && (OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES < \
(OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 4))
#error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES needs to support more entries when "\
"OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE is enabled to accommodate for max on-link prefixes"
#endif
#include <openthread/netdata_publisher.h>
#include "border_router/routing_manager.hpp"
#include "common/clearable.hpp"
#include "common/equatable.hpp"
#include "common/error.hpp"
@@ -87,6 +82,16 @@ public:
kEventEntryRemoved = OT_NETDATA_PUBLISHER_EVENT_ENTRY_REMOVED, ///< Entry is removed from Network Data.
};
/**
* This enumeration represents the requester associated with a published prefix.
*
*/
enum Requester : uint8_t
{
kFromUser, ///< Requested by user (public OT API).
kFromRoutingManager, ///< Requested by `RoutingManager` module.
};
/**
* This constructor initializes `Publisher` object.
*
@@ -222,6 +227,7 @@ public:
* same prefix with the same or higher preference.
*
* @param[in] aConfig The on-mesh prefix config to publish.
* @param[in] aRequester The requester (`kFromUser` or `kFromRoutingManager` module).
*
* @retval kErrorNone The on-mesh prefix is published successfully.
* @retval kErrorInvalidArgs The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
@@ -232,7 +238,7 @@ public:
*
*
*/
Error PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig);
Error PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig, Requester aRequester);
/**
* This method requests an external route prefix to be published in the Thread Network Data.
@@ -247,6 +253,7 @@ public:
* same prefix with the same or higher preference.
*
* @param[in] aConfig The external route config to publish.
* @param[in] aRequester The requester (`kFromUser` or `kFromRoutingManager` module).
*
* @retval kErrorNone The external route is published successfully.
* @retval kErrorInvalidArgs The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
@@ -256,7 +263,7 @@ public:
*
*
*/
Error PublishExternalRoute(const ExternalRouteConfig &aConfig);
Error PublishExternalRoute(const ExternalRouteConfig &aConfig, Requester aRequester);
/**
* This method indicates whether or not currently a published prefix entry (on-mesh or external route) is added to
@@ -401,22 +408,30 @@ private:
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
// Max number of prefix (on-mesh or external route) entries.
static constexpr uint16_t kMaxPrefixEntries = OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES;
static constexpr uint16_t kMaxUserPrefixEntries = OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
static constexpr uint16_t kMaxRoutingManagerPrefixEntries = BorderRouter::RoutingManager::kMaxPublishedPrefixes;
#else
static constexpr uint16_t kMaxRoutingManagerPrefixEntries = 0;
#endif
class PrefixEntry : public Entry, private NonCopyable
{
friend class Entry;
public:
void Init(Instance &aInstance) { Entry::Init(aInstance); }
bool IsInUse(void) const { return GetState() != kNoEntry; }
bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
void Publish(const OnMeshPrefixConfig &aConfig);
void Publish(const ExternalRouteConfig &aConfig);
void Unpublish(void);
void HandleTimer(void) { Entry::HandleTimer(); }
void HandleNotifierEvents(Events aEvents);
void Init(Instance &aInstance) { Entry::Init(aInstance); }
bool IsInUse(void) const { return GetState() != kNoEntry; }
bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
void Publish(const OnMeshPrefixConfig &aConfig, Requester aRequester);
void Publish(const ExternalRouteConfig &aConfig, Requester aRequester);
Requester GetRequester(void) const { return mRequester; }
void Unpublish(void);
void HandleTimer(void) { Entry::HandleTimer(); }
void HandleNotifierEvents(Events aEvents);
private:
static constexpr uint8_t kDesiredNumOnMeshPrefix =
@@ -431,7 +446,7 @@ private:
kTypeExternalRoute,
};
void Publish(const Ip6::Prefix &aPrefix, uint16_t aNewFlags, Type aNewType);
void Publish(const Ip6::Prefix &aPrefix, uint16_t aNewFlags, Type aNewType, Requester aRequester);
void Add(void);
Error AddOnMeshPrefix(void);
Error AddExternalRoute(void);
@@ -441,6 +456,7 @@ private:
void CountExternalRouteEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
Type mType;
Requester mRequester;
Ip6::Prefix mPrefix;
uint16_t mFlags;
};
@@ -451,7 +467,7 @@ private:
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
PrefixEntry * FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix);
PrefixEntry * FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix, Requester aRequester);
PrefixEntry * FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix);
const PrefixEntry *FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix) const;
bool IsAPrefixEntry(const Entry &aEntry) const;
@@ -469,7 +485,7 @@ private:
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
PrefixEntry mPrefixEntries[kMaxPrefixEntries];
PrefixEntry mPrefixEntries[kMaxUserPrefixEntries + kMaxRoutingManagerPrefixEntries];
PrefixCallback mPrefixCallback;
void * mPrefixCallbackContext;
#endif