[netdata] simplify Leader class (#9563)

This commit updates the `NetworkData::Leader` sub-class model,
removing `LeaderBase` (which intended to provide common functions
shared between FTD and MTD) and instead adding all methods directly
in `Leader` class with all `FTD`-specific methods having conditional
`#if` check.
This commit is contained in:
Abtin Keshavarzian
2023-10-31 15:36:20 -07:00
committed by GitHub
parent c6ffe1ae2c
commit 4a9fb0609e
5 changed files with 359 additions and 473 deletions
-1
View File
@@ -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",
+57 -39
View File
@@ -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 @@ exit:
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 @@ exit:
return error;
}
void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
void Leader::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
{
aContext.mPrefix.Set(Get<Mle::MleRouter>().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 @@ exit:
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 @@ exit:
return error;
}
template <typename EntryType>
int LeaderBase::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const
template <typename EntryType> 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 @@ exit:
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 @@ exit:
return error;
}
const CommissioningDataTlv *LeaderBase::FindCommissioningData(void) const
const CommissioningDataTlv *Leader::FindCommissioningData(void) const
{
return NetworkDataTlv::Find<CommissioningDataTlv>(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 @@ exit:
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 @@ exit:
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 @@ exit:
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<MeshCoP::SteeringDataTlv>();
@@ -523,7 +541,7 @@ exit:
return error;
}
bool LeaderBase::IsJoiningAllowed(void) const
bool Leader::IsJoiningAllowed(void) const
{
bool isAllowed = false;
MeshCoP::SteeringData steeringData;
@@ -535,7 +553,7 @@ exit:
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 @@ exit:
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<ot::Notifier>().Signal(kEventThreadNetdataChanged);
+302 -33
View File
@@ -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 @@ public:
* @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 @@ public:
*/
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 @@ private:
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<uint8_t>::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 <Uri kUri> 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<Leader, &Leader::HandleTimer>;
#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 @@ private:
} // 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_
@@ -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
-381
View File
@@ -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 <stdint.h>
#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<uint8_t>::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 <Uri kUri> 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<Leader, &Leader::HandleTimer>;
#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_