blob: de91ec1c6f7422345f7c5bbb69672d8f6d29fd34 [file] [log] [blame]
/*
* 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);
/**
* 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);
void SendCommissioningGetResponse(const Coap::Message &aRequest,
uint16_t aLength,
const Ip6::MessageInfo &aMessageInfo);
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_