1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for manipulating Thread Network Data managed by the Thread Leader. 32 */ 33 34 #ifndef NETWORK_DATA_LEADER_FTD_HPP_ 35 #define NETWORK_DATA_LEADER_FTD_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_FTD 40 41 #include <stdint.h> 42 43 #include "common/non_copyable.hpp" 44 #include "common/numeric_limits.hpp" 45 #include "common/timer.hpp" 46 #include "net/ip6_address.hpp" 47 #include "thread/mle_router.hpp" 48 #include "thread/network_data.hpp" 49 #include "thread/tmf.hpp" 50 51 namespace ot { 52 53 namespace NetworkData { 54 55 /** 56 * @addtogroup core-netdata-leader 57 * 58 * @brief 59 * This module includes definitions for manipulating Thread Network Data managed by the Thread Leader. 60 * 61 * @{ 62 * 63 */ 64 65 /** 66 * This class implements the Thread Network Data maintained by the Leader. 67 * 68 */ 69 class Leader : public LeaderBase, private NonCopyable 70 { 71 friend class Tmf::Agent; 72 73 public: 74 /** 75 * This enumeration defines the match mode constants to compare two RLOC16 values. 76 * 77 */ 78 enum MatchMode : uint8_t 79 { 80 kMatchModeRloc16, ///< Perform exact RLOC16 match. 81 kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children). 82 }; 83 84 /** 85 * This constructor initializes the object. 86 * 87 * @param[in] aInstance A reference to the OpenThread instance. 88 * 89 */ 90 explicit Leader(Instance &aInstance); 91 92 /** 93 * This method reset the Thread Network Data. 94 * 95 */ 96 void Reset(void); 97 98 /** 99 * This method starts the Leader services. 100 * 101 * The start mode indicates whether device is starting normally as leader or restoring its role as leader after 102 * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for 103 * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data 104 * before allowing new Network Data registrations. 105 * 106 * @param[in] aStartMode The start mode. 107 * 108 */ 109 void Start(Mle::LeaderStartMode aStartMode); 110 111 /** 112 * This method increments the Thread Network Data version. 113 * 114 */ 115 void IncrementVersion(void); 116 117 /** 118 * This method increments both the Thread Network Data version and stable version. 119 * 120 */ 121 void IncrementVersionAndStableVersion(void); 122 123 /** 124 * This method returns CONTEXT_ID_RESUSE_DELAY value. 125 * 126 * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds). 127 * 128 */ GetContextIdReuseDelay(void) const129 uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); } 130 131 /** 132 * This method sets CONTEXT_ID_RESUSE_DELAY value. 133 * 134 * @warning This method should only be used for testing. 135 * 136 * @param[in] aDelay The CONTEXT_ID_REUSE_DELAY value (in seconds). 137 * 138 */ SetContextIdReuseDelay(uint32_t aDelay)139 void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); } 140 141 /** 142 * This method removes Network Data entries matching with a given RLOC16. 143 * 144 * @param[in] aRloc16 A RLOC16 value. 145 * @param[in] aMatchMode A match mode (@sa MatchMode). 146 * 147 */ 148 void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode); 149 150 /** 151 * This method synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data. 152 * 153 * Note that this method should be called only by the Leader once after reset. 154 * 155 */ 156 void HandleNetworkDataRestoredAfterReset(void); 157 158 /** 159 * This method scans network data for given Service ID and returns pointer to the respective TLV, if present. 160 * 161 * @param aServiceId Service ID to look for. 162 * @return Pointer to the Service TLV for given Service ID, or nullptr if not present. 163 * 164 */ 165 const ServiceTlv *FindServiceById(uint8_t aServiceId) const; 166 167 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 168 /** 169 * This method indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data. 170 * 171 * @param[in] aPrefix The OMR prefix to check. 172 * 173 * @retval TRUE If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix. 174 * @retval FALSE Otherwise. 175 * 176 */ 177 bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix); 178 #endif 179 180 private: 181 static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec. 182 183 class ChangedFlags 184 { 185 public: ChangedFlags(void)186 ChangedFlags(void) 187 : mChanged(false) 188 , mStableChanged(false) 189 { 190 } 191 Update(const NetworkDataTlv & aTlv)192 void Update(const NetworkDataTlv &aTlv) 193 { 194 mChanged = true; 195 mStableChanged = (mStableChanged || aTlv.IsStable()); 196 } 197 DidChange(void) const198 bool DidChange(void) const { return mChanged; } DidStableChange(void) const199 bool DidStableChange(void) const { return mStableChanged; } 200 201 private: 202 bool mChanged; // Any (stable or not) network data change (add/remove). 203 bool mStableChanged; // Stable network data change (add/remove). 204 }; 205 206 enum UpdateStatus : uint8_t 207 { 208 kTlvRemoved, // TLV contained no sub TLVs and therefore is removed. 209 kTlvUpdated, // TLV stable flag is updated based on its sub TLVs. 210 }; 211 212 class ContextIds : public InstanceLocator 213 { 214 public: 215 // This class tracks Context IDs. A Context ID can be in one 216 // of the 3 states: It is unallocated, or it is allocated 217 // and in-use, or it scheduled to be removed (after reuse delay 218 // interval is passed). 219 220 static constexpr uint8_t kInvalidId = NumericLimits<uint8_t>::kMax; 221 ContextIds(Instance & aInstance)222 explicit ContextIds(Instance &aInstance) 223 : InstanceLocator(aInstance) 224 , mReuseDelay(kReuseDelay) 225 { 226 } 227 228 void Clear(void); 229 Error GetUnallocatedId(uint8_t &aId); MarkAsInUse(uint8_t aId)230 void MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); } 231 void ScheduleToRemove(uint8_t aId); GetReuseDelay(void) const232 uint32_t GetReuseDelay(void) const { return mReuseDelay; } SetReuseDelay(uint32_t aDelay)233 void SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; } 234 void HandleTimer(void); 235 236 private: 237 static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds). 238 239 static constexpr uint8_t kMinId = 1; 240 static constexpr uint8_t kMaxId = 15; 241 242 // The `mRemoveTimes[id]` is used to track the state of a 243 // Context ID and its remove time. Two specific values 244 // `kUnallocated` and `kInUse` are used to indicate ID is in 245 // unallocated or in-use states. Other values indicate we 246 // are in remove state waiting to remove it at `mRemoveTime`. 247 248 static constexpr uint32_t kUnallocated = 0; 249 static constexpr uint32_t kInUse = 1; 250 IsUnallocated(uint8_t aId) const251 bool IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; } IsInUse(uint8_t aId) const252 bool IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; } GetRemoveTime(uint8_t aId) const253 TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; } 254 void SetRemoveTime(uint8_t aId, TimeMilli aTime); MarkAsUnallocated(uint8_t aId)255 void MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); } 256 257 TimeMilli mRemoveTimes[kMaxId - kMinId + 1]; 258 uint32_t mReuseDelay; 259 }; 260 261 template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 262 263 void HandleTimer(void); 264 265 void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData); 266 267 Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags); 268 Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); 269 Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags); 270 Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags); 271 Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags); 272 273 Error AllocateServiceId(uint8_t &aServiceId) const; 274 275 void RemoveContext(uint8_t aContextId); 276 void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId); 277 278 void RemoveCommissioningData(void); 279 280 void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags); 281 void RemoveRloc(uint16_t aRloc16, 282 MatchMode aMatchMode, 283 const NetworkData &aExcludeNetworkData, 284 ChangedFlags &aChangedFlags); 285 void RemoveRlocInPrefix(PrefixTlv &aPrefix, 286 uint16_t aRloc16, 287 MatchMode aMatchMode, 288 const PrefixTlv *aExcludePrefix, 289 ChangedFlags &aChangedFlags); 290 void RemoveRlocInService(ServiceTlv &aService, 291 uint16_t aRloc16, 292 MatchMode aMatchMode, 293 const ServiceTlv *aExcludeService, 294 ChangedFlags &aChangedFlags); 295 void RemoveRlocInHasRoute(PrefixTlv &aPrefix, 296 HasRouteTlv &aHasRoute, 297 uint16_t aRloc16, 298 MatchMode aMatchMode, 299 const PrefixTlv *aExcludePrefix, 300 ChangedFlags &aChangedFlags); 301 void RemoveRlocInBorderRouter(PrefixTlv &aPrefix, 302 BorderRouterTlv &aBorderRouter, 303 uint16_t aRloc16, 304 MatchMode aMatchMode, 305 const PrefixTlv *aExcludePrefix, 306 ChangedFlags &aChangedFlags); 307 308 static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode); 309 310 static Error Validate(const NetworkData &aNetworkData, uint16_t aRloc16); 311 static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16); 312 static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16); 313 314 static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry); 315 static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry); 316 static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry); 317 static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry); 318 static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer); 319 320 UpdateStatus UpdatePrefix(PrefixTlv &aPrefix); 321 UpdateStatus UpdateService(ServiceTlv &aService); 322 UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs); 323 324 void SendCommissioningGetResponse(const Coap::Message &aRequest, 325 uint16_t aLength, 326 const Ip6::MessageInfo &aMessageInfo); 327 void SendCommissioningSetResponse(const Coap::Message &aRequest, 328 const Ip6::MessageInfo &aMessageInfo, 329 MeshCoP::StateTlv::State aState); 330 void IncrementVersions(bool aIncludeStable); 331 void IncrementVersions(const ChangedFlags &aFlags); 332 333 using UpdateTimer = TimerMilliIn<Leader, &Leader::HandleTimer>; 334 335 bool mWaitingForNetDataSync; 336 ContextIds mContextIds; 337 UpdateTimer mTimer; 338 }; 339 340 DeclareTmfHandler(Leader, kUriServerData); 341 DeclareTmfHandler(Leader, kUriCommissionerGet); 342 DeclareTmfHandler(Leader, kUriCommissionerSet); 343 344 /** 345 * @} 346 */ 347 348 } // namespace NetworkData 349 } // namespace ot 350 351 #endif // OPENTHREAD_FTD 352 353 #endif // NETWORK_DATA_LEADER_FTD_HPP_ 354