diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index abb606ed779..37843dd2ebb 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -657,7 +657,6 @@ openthread_core_files = [ "thread/network_data_leader.cpp", "thread/network_data_leader.hpp", "thread/network_data_leader_ftd.cpp", - "thread/network_data_leader_ftd.hpp", "thread/network_data_local.cpp", "thread/network_data_local.hpp", "thread/network_data_notifier.cpp", diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 11c5441dc45..814b5d14a5e 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -55,18 +55,37 @@ namespace NetworkData { RegisterLogModule("NetworkData"); -void LeaderBase::Reset(void) +Leader::Leader(Instance &aInstance) + : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer)) + , mMaxLength(0) +#if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL + , mIsClone(false) +#endif + , mWaitingForNetDataSync(false) + , mContextIds(aInstance) + , mTimer(aInstance) +#endif +{ + Reset(); +} + +void Leader::Reset(void) { mVersion = Random::NonCrypto::GetUint8(); mStableVersion = Random::NonCrypto::GetUint8(); SetLength(0); SignalNetDataChanged(); + +#if OPENTHREAD_FTD + mContextIds.Clear(); +#endif } -Error LeaderBase::GetServiceId(uint32_t aEnterpriseNumber, - const ServiceData &aServiceData, - bool aServerStable, - uint8_t &aServiceId) const +Error Leader::GetServiceId(uint32_t aEnterpriseNumber, + const ServiceData &aServiceData, + bool aServerStable, + uint8_t &aServiceId) const { Error error = kErrorNotFound; Iterator iterator = kIteratorInit; @@ -89,7 +108,7 @@ Error LeaderBase::GetServiceId(uint32_t aEnterpriseNumber, return error; } -Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const +Error Leader::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const { Error error = kErrorNotFound; Iterator iterator = kIteratorInit; @@ -113,7 +132,7 @@ Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const return error; } -const PrefixTlv *LeaderBase::FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const +const PrefixTlv *Leader::FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const { // This method iterates over Prefix TLVs which match a given IPv6 // `aAddress`. If `aPrevTlv` is `nullptr` we start from the @@ -135,7 +154,7 @@ const PrefixTlv *LeaderBase::FindNextMatchingPrefixTlv(const Ip6::Address &aAddr return prefixTlv; } -Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const +Error Leader::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const { const PrefixTlv *prefixTlv = nullptr; const ContextTlv *contextTlv; @@ -168,7 +187,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound; } -Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const +Error Leader::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const { Error error = kErrorNotFound; TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd()); @@ -200,7 +219,7 @@ Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) cons return error; } -void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const +void Leader::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const { aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); aContext.mContextId = Mle::kMeshLocalPrefixContextId; @@ -208,7 +227,7 @@ void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const aContext.mIsValid = true; } -bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const +bool Leader::IsOnMesh(const Ip6::Address &aAddress) const { const PrefixTlv *prefixTlv = nullptr; bool isOnMesh = false; @@ -237,7 +256,7 @@ bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const return isOnMesh; } -Error LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint16_t &aRloc16) const +Error Leader::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint16_t &aRloc16) const { Error error = kErrorNoRoute; const PrefixTlv *prefixTlv = nullptr; @@ -264,18 +283,17 @@ Error LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &a return error; } -template -int LeaderBase::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const +template int Leader::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const { // `EntryType` can be `HasRouteEntry` or `BorderRouterEntry`. return CompareRouteEntries(aFirst.GetPreference(), aFirst.GetRloc(), aSecond.GetPreference(), aSecond.GetRloc()); } -int LeaderBase::CompareRouteEntries(int8_t aFirstPreference, - uint16_t aFirstRloc, - int8_t aSecondPreference, - uint16_t aSecondRloc) const +int Leader::CompareRouteEntries(int8_t aFirstPreference, + uint16_t aFirstRloc, + int8_t aSecondPreference, + uint16_t aSecondRloc) const { // Performs three-way comparison between two BR entries. @@ -312,7 +330,7 @@ int LeaderBase::CompareRouteEntries(int8_t aFirstPreference, return result; } -Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const +Error Leader::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const { Error error = kErrorNoRoute; const PrefixTlv *prefixTlv = nullptr; @@ -359,7 +377,7 @@ Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDe return error; } -Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const +Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const { Error error = kErrorNoRoute; TlvIterator subTlvIterator(aPrefix); @@ -392,12 +410,12 @@ Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16 return error; } -Error LeaderBase::SetNetworkData(uint8_t aVersion, - uint8_t aStableVersion, - Type aType, - const Message &aMessage, - uint16_t aOffset, - uint16_t aLength) +Error Leader::SetNetworkData(uint8_t aVersion, + uint8_t aStableVersion, + Type aType, + const Message &aMessage, + uint16_t aOffset, + uint16_t aLength) { Error error = kErrorNone; @@ -428,12 +446,12 @@ Error LeaderBase::SetNetworkData(uint8_t aVersion, return error; } -const CommissioningDataTlv *LeaderBase::FindCommissioningData(void) const +const CommissioningDataTlv *Leader::FindCommissioningData(void) const { return NetworkDataTlv::Find(GetTlvsStart(), GetTlvsEnd()); } -const MeshCoP::Tlv *LeaderBase::FindCommissioningDataSubTlv(uint8_t aType) const +const MeshCoP::Tlv *Leader::FindCommissioningDataSubTlv(uint8_t aType) const { const MeshCoP::Tlv *subTlv = nullptr; const NetworkDataTlv *dataTlv = FindCommissioningData(); @@ -445,7 +463,7 @@ const MeshCoP::Tlv *LeaderBase::FindCommissioningDataSubTlv(uint8_t aType) const return subTlv; } -Error LeaderBase::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const +Error Leader::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const { Error error = kErrorNone; const MeshCoP::Tlv *subTlv = FindCommissioningDataSubTlv(aType); @@ -458,7 +476,7 @@ Error LeaderBase::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, ui return error; } -void LeaderBase::GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) const +void Leader::GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) const { const CommissioningDataTlv *dataTlv = FindCommissioningData(); const MeshCoP::Tlv *subTlv; @@ -496,22 +514,22 @@ void LeaderBase::GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset return; } -Error LeaderBase::FindBorderAgentRloc(uint16_t &aRloc16) const +Error Leader::FindBorderAgentRloc(uint16_t &aRloc16) const { return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16); } -Error LeaderBase::FindCommissioningSessionId(uint16_t &aSessionId) const +Error Leader::FindCommissioningSessionId(uint16_t &aSessionId) const { return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kCommissionerSessionId, aSessionId); } -Error LeaderBase::FindJoinerUdpPort(uint16_t &aPort) const +Error Leader::FindJoinerUdpPort(uint16_t &aPort) const { return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kJoinerUdpPort, aPort); } -Error LeaderBase::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const +Error Leader::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const { Error error = kErrorNone; const MeshCoP::SteeringDataTlv *steeringDataTlv = FindInCommissioningData(); @@ -523,7 +541,7 @@ Error LeaderBase::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const return error; } -bool LeaderBase::IsJoiningAllowed(void) const +bool Leader::IsJoiningAllowed(void) const { bool isAllowed = false; MeshCoP::SteeringData steeringData; @@ -535,7 +553,7 @@ bool LeaderBase::IsJoiningAllowed(void) const return isAllowed; } -Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const +Error Leader::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const { Error error = kErrorInvalidState; MeshCoP::SteeringData steeringData; @@ -547,7 +565,7 @@ Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const return error; } -Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const +Error Leader::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const { FilterIndexes filterIndexes; Mac::ExtAddress joinerId; @@ -558,7 +576,7 @@ Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const return SteeringDataCheck(filterIndexes); } -Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const +Error Leader::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const { FilterIndexes filterIndexes; @@ -567,7 +585,7 @@ Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDisce return SteeringDataCheck(filterIndexes); } -void LeaderBase::SignalNetDataChanged(void) +void Leader::SignalNetDataChanged(void) { mMaxLength = Max(mMaxLength, GetLength()); Get().Signal(kEventThreadNetdataChanged); diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index a510844e8c4..4ad1a99f06c 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -40,10 +40,13 @@ #include "coap/coap.hpp" #include "common/const_cast.hpp" +#include "common/non_copyable.hpp" +#include "common/numeric_limits.hpp" #include "common/timer.hpp" #include "net/ip6_address.hpp" #include "thread/mle_router.hpp" #include "thread/network_data.hpp" +#include "thread/tmf.hpp" namespace ot { @@ -63,8 +66,11 @@ namespace NetworkData { * Implements the Thread Network Data maintained by the Leader. * */ -class LeaderBase : public MutableNetworkData +class Leader : public MutableNetworkData, private NonCopyable { + friend class Tmf::Agent; + friend class Notifier; + public: /** * Initializes the object. @@ -72,12 +78,7 @@ class LeaderBase : public MutableNetworkData * @param[in] aInstance A reference to the OpenThread instance. * */ - explicit LeaderBase(Instance &aInstance) - : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer)) - , mMaxLength(0) - { - Reset(); - } + explicit Leader(Instance &aInstance); /** * Reset the Thread Network Data. @@ -328,18 +329,112 @@ class LeaderBase : public MutableNetworkData */ Error GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const; -protected: - void SignalNetDataChanged(void); - const CommissioningDataTlv *FindCommissioningData(void) const; - CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); } - const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const; - MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) +#if OPENTHREAD_FTD + /** + * Defines the match mode constants to compare two RLOC16 values. + * + */ + enum MatchMode : uint8_t { - return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType)); - } + kMatchModeRloc16, ///< Perform exact RLOC16 match. + kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children). + }; - uint8_t mStableVersion; - uint8_t mVersion; + /** + * Starts the Leader services. + * + * The start mode indicates whether device is starting normally as leader or restoring its role as leader after + * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for + * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data + * before allowing new Network Data registrations. + * + * @param[in] aStartMode The start mode. + * + */ + void Start(Mle::LeaderStartMode aStartMode); + + /** + * Increments the Thread Network Data version. + * + */ + void IncrementVersion(void); + + /** + * Increments both the Thread Network Data version and stable version. + * + */ + void IncrementVersionAndStableVersion(void); + + /** + * Returns CONTEXT_ID_RESUSE_DELAY value. + * + * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds). + * + */ + uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); } + + /** + * Sets CONTEXT_ID_RESUSE_DELAY value. + * + * @warning This method should only be used for testing. + * + * @param[in] aDelay The CONTEXT_ID_REUSE_DELAY value (in seconds). + * + */ + void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); } + + /** + * Removes Network Data entries matching with a given RLOC16. + * + * @param[in] aRloc16 A RLOC16 value. + * @param[in] aMatchMode A match mode (@sa MatchMode). + * + */ + void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode); + + /** + * Updates Commissioning Data in Network Data. + * + * @param[in] aData A pointer to the Commissioning Data. + * @param[in] aDataLength The length of @p aData. + * + * @retval kErrorNone Successfully updated the Commissioning Data. + * @retval kErrorNoBufs Insufficient space to add the Commissioning Data. + * + */ + Error SetCommissioningData(const void *aData, uint8_t aDataLength); + + /** + * Synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data. + * + * Note that this method should be called only by the Leader once after reset. + * + */ + void HandleNetworkDataRestoredAfterReset(void); + + /** + * Scans network data for given Service ID and returns pointer to the respective TLV, if present. + * + * @param aServiceId Service ID to look for. + * @return Pointer to the Service TLV for given Service ID, or nullptr if not present. + * + */ + const ServiceTlv *FindServiceById(uint8_t aServiceId) const; + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + /** + * Indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data. + * + * @param[in] aPrefix The OMR prefix to check. + * + * @retval TRUE If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix. + * @retval FALSE Otherwise. + * + */ + bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix); +#endif + +#endif // OPENTHREAD_FTD private: using FilterIndexes = MeshCoP::SteeringData::HashBitIndexes; @@ -357,11 +452,201 @@ class LeaderBase : public MutableNetworkData Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const; void GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const; Error ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const; + void SignalNetDataChanged(void); + const CommissioningDataTlv *FindCommissioningData(void) const; + CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); } + const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const; + MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) + { + return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType)); + } +#if OPENTHREAD_FTD + static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec. + static constexpr uint8_t kMinServiceId = 0x00; + static constexpr uint8_t kMaxServiceId = 0x0f; + + class ChangedFlags + { + public: + ChangedFlags(void) + : mChanged(false) + , mStableChanged(false) + { + } + + void Update(const NetworkDataTlv &aTlv) + { + mChanged = true; + mStableChanged = (mStableChanged || aTlv.IsStable()); + } + + bool DidChange(void) const { return mChanged; } + bool DidStableChange(void) const { return mStableChanged; } + + private: + bool mChanged; // Any (stable or not) network data change (add/remove). + bool mStableChanged; // Stable network data change (add/remove). + }; + + enum UpdateStatus : uint8_t + { + kTlvRemoved, // TLV contained no sub TLVs and therefore is removed. + kTlvUpdated, // TLV stable flag is updated based on its sub TLVs. + }; + + class ContextIds : public InstanceLocator + { + public: + // This class tracks Context IDs. A Context ID can be in one + // of the 3 states: It is unallocated, or it is allocated + // and in-use, or it scheduled to be removed (after reuse delay + // interval is passed). + + static constexpr uint8_t kInvalidId = NumericLimits::kMax; + + explicit ContextIds(Instance &aInstance); + + void Clear(void); + Error GetUnallocatedId(uint8_t &aId); + void MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); } + void ScheduleToRemove(uint8_t aId); + uint32_t GetReuseDelay(void) const { return mReuseDelay; } + void SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; } + void HandleTimer(void); +#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL + void MarkAsClone(void) { mIsClone = true; } +#endif + + private: + static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds). + + static constexpr uint8_t kMinId = 1; + static constexpr uint8_t kMaxId = 15; + + // The `mRemoveTimes[id]` is used to track the state of a + // Context ID and its remove time. Two specific values + // `kUnallocated` and `kInUse` are used to indicate ID is in + // unallocated or in-use states. Other values indicate we + // are in remove state waiting to remove it at `mRemoveTime`. + + static constexpr uint32_t kUnallocated = 0; + static constexpr uint32_t kInUse = 1; + + bool IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; } + bool IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; } + TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; } + void SetRemoveTime(uint8_t aId, TimeMilli aTime); + void MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); } + + TimeMilli mRemoveTimes[kMaxId - kMinId + 1]; + uint32_t mReuseDelay; +#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL + bool mIsClone; +#endif + }; + + template void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + + void HandleTimer(void); + + void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData); + + Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags); + Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); + Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); + Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags); + Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags); + + Error AllocateServiceId(uint8_t &aServiceId) const; + + void RemoveContext(uint8_t aContextId); + void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId); + + void RemoveCommissioningData(void); + + void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags); + void RemoveRloc(uint16_t aRloc16, + MatchMode aMatchMode, + const NetworkData &aExcludeNetworkData, + ChangedFlags &aChangedFlags); + void RemoveRlocInPrefix(PrefixTlv &aPrefix, + uint16_t aRloc16, + MatchMode aMatchMode, + const PrefixTlv *aExcludePrefix, + ChangedFlags &aChangedFlags); + void RemoveRlocInService(ServiceTlv &aService, + uint16_t aRloc16, + MatchMode aMatchMode, + const ServiceTlv *aExcludeService, + ChangedFlags &aChangedFlags); + void RemoveRlocInHasRoute(PrefixTlv &aPrefix, + HasRouteTlv &aHasRoute, + uint16_t aRloc16, + MatchMode aMatchMode, + const PrefixTlv *aExcludePrefix, + ChangedFlags &aChangedFlags); + void RemoveRlocInBorderRouter(PrefixTlv &aPrefix, + BorderRouterTlv &aBorderRouter, + uint16_t aRloc16, + MatchMode aMatchMode, + const PrefixTlv *aExcludePrefix, + ChangedFlags &aChangedFlags); + + static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode); + + static Error Validate(const NetworkData &aNetworkData, uint16_t aRloc16); + static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16); + static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16); + + static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry); + static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry); + static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry); + static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry); + static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer); + + UpdateStatus UpdatePrefix(PrefixTlv &aPrefix); + UpdateStatus UpdateService(ServiceTlv &aService); + UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs); + + Error UpdateCommissioningData(uint16_t aDataLength, CommissioningDataTlv *&aDataTlv); + Error SetCommissioningData(const Message &aMessage); + + void SendCommissioningSetResponse(const Coap::Message &aRequest, + const Ip6::MessageInfo &aMessageInfo, + MeshCoP::StateTlv::State aState); + void IncrementVersions(bool aIncludeStable); + void IncrementVersions(const ChangedFlags &aFlags); + +#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL + void CheckForNetDataGettingFull(const NetworkData &aNetworkData, uint16_t aOldRloc16); + void MarkAsClone(void); +#endif + + using UpdateTimer = TimerMilliIn; +#endif // OPENTHREAD_FTD + + uint8_t mStableVersion; + uint8_t mVersion; uint8_t mTlvBuffer[kMaxSize]; uint8_t mMaxLength; + +#if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL + bool mIsClone; +#endif + bool mWaitingForNetDataSync; + ContextIds mContextIds; + UpdateTimer mTimer; +#endif }; +#if OPENTHREAD_FTD +DeclareTmfHandler(Leader, kUriServerData); +DeclareTmfHandler(Leader, kUriCommissionerGet); +DeclareTmfHandler(Leader, kUriCommissionerSet); +#endif + /** * @} */ @@ -369,20 +654,4 @@ class LeaderBase : public MutableNetworkData } // namespace NetworkData } // namespace ot -#if OPENTHREAD_MTD -namespace ot { -namespace NetworkData { -class Leader : public LeaderBase -{ -public: - using LeaderBase::LeaderBase; -}; -} // namespace NetworkData -} // namespace ot -#elif OPENTHREAD_FTD -#include "network_data_leader_ftd.hpp" -#else -#error "Please define OPENTHREAD_MTD=1 or OPENTHREAD_FTD=1" -#endif - #endif // NETWORK_DATA_LEADER_HPP_ diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index aa833f49e7b..fe423ef4f8e 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -58,25 +58,6 @@ namespace NetworkData { RegisterLogModule("NetworkData"); -Leader::Leader(Instance &aInstance) - : LeaderBase(aInstance) -#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL - , mIsClone(false) -#endif - , mWaitingForNetDataSync(false) - , mContextIds(aInstance) - , mTimer(aInstance) -{ - Reset(); -} - -void Leader::Reset(void) -{ - LeaderBase::Reset(); - - mContextIds.Clear(); -} - void Leader::Start(Mle::LeaderStartMode aStartMode) { #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp deleted file mode 100644 index 6b723ac7490..00000000000 --- a/src/core/thread/network_data_leader_ftd.hpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2016, The OpenThread Authors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * This file includes definitions for manipulating Thread Network Data managed by the Thread Leader. - */ - -#ifndef NETWORK_DATA_LEADER_FTD_HPP_ -#define NETWORK_DATA_LEADER_FTD_HPP_ - -#include "openthread-core-config.h" - -#if OPENTHREAD_FTD - -#include - -#include "common/non_copyable.hpp" -#include "common/numeric_limits.hpp" -#include "common/timer.hpp" -#include "net/ip6_address.hpp" -#include "thread/mle_router.hpp" -#include "thread/network_data.hpp" -#include "thread/tmf.hpp" - -namespace ot { - -namespace NetworkData { - -class Notifier; - -/** - * @addtogroup core-netdata-leader - * - * @brief - * This module includes definitions for manipulating Thread Network Data managed by the Thread Leader. - * - * @{ - * - */ - -/** - * Implements the Thread Network Data maintained by the Leader. - * - */ -class Leader : public LeaderBase, private NonCopyable -{ - friend class Tmf::Agent; - friend class Notifier; - -public: - /** - * Defines the match mode constants to compare two RLOC16 values. - * - */ - enum MatchMode : uint8_t - { - kMatchModeRloc16, ///< Perform exact RLOC16 match. - kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children). - }; - - /** - * Initializes the object. - * - * @param[in] aInstance A reference to the OpenThread instance. - * - */ - explicit Leader(Instance &aInstance); - - /** - * Reset the Thread Network Data. - * - */ - void Reset(void); - - /** - * Starts the Leader services. - * - * The start mode indicates whether device is starting normally as leader or restoring its role as leader after - * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for - * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data - * before allowing new Network Data registrations. - * - * @param[in] aStartMode The start mode. - * - */ - void Start(Mle::LeaderStartMode aStartMode); - - /** - * Increments the Thread Network Data version. - * - */ - void IncrementVersion(void); - - /** - * Increments both the Thread Network Data version and stable version. - * - */ - void IncrementVersionAndStableVersion(void); - - /** - * Returns CONTEXT_ID_RESUSE_DELAY value. - * - * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds). - * - */ - uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); } - - /** - * Sets CONTEXT_ID_RESUSE_DELAY value. - * - * @warning This method should only be used for testing. - * - * @param[in] aDelay The CONTEXT_ID_REUSE_DELAY value (in seconds). - * - */ - void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); } - - /** - * Removes Network Data entries matching with a given RLOC16. - * - * @param[in] aRloc16 A RLOC16 value. - * @param[in] aMatchMode A match mode (@sa MatchMode). - * - */ - void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode); - - /** - * Updates Commissioning Data in Network Data. - * - * @param[in] aData A pointer to the Commissioning Data. - * @param[in] aDataLength The length of @p aData. - * - * @retval kErrorNone Successfully updated the Commissioning Data. - * @retval kErrorNoBufs Insufficient space to add the Commissioning Data. - * - */ - Error SetCommissioningData(const void *aData, uint8_t aDataLength); - - /** - * Synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data. - * - * Note that this method should be called only by the Leader once after reset. - * - */ - void HandleNetworkDataRestoredAfterReset(void); - - /** - * Scans network data for given Service ID and returns pointer to the respective TLV, if present. - * - * @param aServiceId Service ID to look for. - * @return Pointer to the Service TLV for given Service ID, or nullptr if not present. - * - */ - const ServiceTlv *FindServiceById(uint8_t aServiceId) const; - -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE - /** - * Indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data. - * - * @param[in] aPrefix The OMR prefix to check. - * - * @retval TRUE If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix. - * @retval FALSE Otherwise. - * - */ - bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix); -#endif - -private: - static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec. - - static constexpr uint8_t kMinServiceId = 0x00; - static constexpr uint8_t kMaxServiceId = 0x0f; - - class ChangedFlags - { - public: - ChangedFlags(void) - : mChanged(false) - , mStableChanged(false) - { - } - - void Update(const NetworkDataTlv &aTlv) - { - mChanged = true; - mStableChanged = (mStableChanged || aTlv.IsStable()); - } - - bool DidChange(void) const { return mChanged; } - bool DidStableChange(void) const { return mStableChanged; } - - private: - bool mChanged; // Any (stable or not) network data change (add/remove). - bool mStableChanged; // Stable network data change (add/remove). - }; - - enum UpdateStatus : uint8_t - { - kTlvRemoved, // TLV contained no sub TLVs and therefore is removed. - kTlvUpdated, // TLV stable flag is updated based on its sub TLVs. - }; - - class ContextIds : public InstanceLocator - { - public: - // This class tracks Context IDs. A Context ID can be in one - // of the 3 states: It is unallocated, or it is allocated - // and in-use, or it scheduled to be removed (after reuse delay - // interval is passed). - - static constexpr uint8_t kInvalidId = NumericLimits::kMax; - - explicit ContextIds(Instance &aInstance); - - void Clear(void); - Error GetUnallocatedId(uint8_t &aId); - void MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); } - void ScheduleToRemove(uint8_t aId); - uint32_t GetReuseDelay(void) const { return mReuseDelay; } - void SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; } - void HandleTimer(void); -#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL - void MarkAsClone(void) { mIsClone = true; } -#endif - - private: - static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds). - - static constexpr uint8_t kMinId = 1; - static constexpr uint8_t kMaxId = 15; - - // The `mRemoveTimes[id]` is used to track the state of a - // Context ID and its remove time. Two specific values - // `kUnallocated` and `kInUse` are used to indicate ID is in - // unallocated or in-use states. Other values indicate we - // are in remove state waiting to remove it at `mRemoveTime`. - - static constexpr uint32_t kUnallocated = 0; - static constexpr uint32_t kInUse = 1; - - bool IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; } - bool IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; } - TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; } - void SetRemoveTime(uint8_t aId, TimeMilli aTime); - void MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); } - - TimeMilli mRemoveTimes[kMaxId - kMinId + 1]; - uint32_t mReuseDelay; -#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL - bool mIsClone; -#endif - }; - - template void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - - void HandleTimer(void); - - void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData); - - Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags); - Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); - Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); - Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags); - Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags); - - Error AllocateServiceId(uint8_t &aServiceId) const; - - void RemoveContext(uint8_t aContextId); - void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId); - - void RemoveCommissioningData(void); - - void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags); - void RemoveRloc(uint16_t aRloc16, - MatchMode aMatchMode, - const NetworkData &aExcludeNetworkData, - ChangedFlags &aChangedFlags); - void RemoveRlocInPrefix(PrefixTlv &aPrefix, - uint16_t aRloc16, - MatchMode aMatchMode, - const PrefixTlv *aExcludePrefix, - ChangedFlags &aChangedFlags); - void RemoveRlocInService(ServiceTlv &aService, - uint16_t aRloc16, - MatchMode aMatchMode, - const ServiceTlv *aExcludeService, - ChangedFlags &aChangedFlags); - void RemoveRlocInHasRoute(PrefixTlv &aPrefix, - HasRouteTlv &aHasRoute, - uint16_t aRloc16, - MatchMode aMatchMode, - const PrefixTlv *aExcludePrefix, - ChangedFlags &aChangedFlags); - void RemoveRlocInBorderRouter(PrefixTlv &aPrefix, - BorderRouterTlv &aBorderRouter, - uint16_t aRloc16, - MatchMode aMatchMode, - const PrefixTlv *aExcludePrefix, - ChangedFlags &aChangedFlags); - - static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode); - - static Error Validate(const NetworkData &aNetworkData, uint16_t aRloc16); - static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16); - static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16); - - static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry); - static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry); - static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry); - static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry); - static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer); - - UpdateStatus UpdatePrefix(PrefixTlv &aPrefix); - UpdateStatus UpdateService(ServiceTlv &aService); - UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs); - - Error UpdateCommissioningData(uint16_t aDataLength, CommissioningDataTlv *&aDataTlv); - Error SetCommissioningData(const Message &aMessage); - - void SendCommissioningSetResponse(const Coap::Message &aRequest, - const Ip6::MessageInfo &aMessageInfo, - MeshCoP::StateTlv::State aState); - void IncrementVersions(bool aIncludeStable); - void IncrementVersions(const ChangedFlags &aFlags); - -#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL - void CheckForNetDataGettingFull(const NetworkData &aNetworkData, uint16_t aOldRloc16); - void MarkAsClone(void); -#endif - - using UpdateTimer = TimerMilliIn; - -#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL - bool mIsClone; -#endif - bool mWaitingForNetDataSync; - ContextIds mContextIds; - UpdateTimer mTimer; -}; - -DeclareTmfHandler(Leader, kUriServerData); -DeclareTmfHandler(Leader, kUriCommissionerGet); -DeclareTmfHandler(Leader, kUriCommissionerSet); - -/** - * @} - */ - -} // namespace NetworkData -} // namespace ot - -#endif // OPENTHREAD_FTD - -#endif // NETWORK_DATA_LEADER_FTD_HPP_