1 /* 2 * Copyright (c) 2018, 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 #ifndef ROUTER_TABLE_HPP_ 30 #define ROUTER_TABLE_HPP_ 31 32 #include "openthread-core-config.h" 33 34 #if OPENTHREAD_FTD 35 36 #include "common/array.hpp" 37 #include "common/const_cast.hpp" 38 #include "common/encoding.hpp" 39 #include "common/iterator_utils.hpp" 40 #include "common/locator.hpp" 41 #include "common/non_copyable.hpp" 42 #include "common/serial_number.hpp" 43 #include "common/tasklet.hpp" 44 #include "mac/mac_types.hpp" 45 #include "thread/mle_tlvs.hpp" 46 #include "thread/mle_types.hpp" 47 #include "thread/router.hpp" 48 #include "thread/thread_tlvs.hpp" 49 50 namespace ot { 51 52 class RouterTable : public InstanceLocator, private NonCopyable 53 { 54 friend class NeighborTable; 55 56 public: 57 /** 58 * Constructor. 59 * 60 * @param[in] aInstance A reference to the OpenThread instance. 61 * 62 */ 63 explicit RouterTable(Instance &aInstance); 64 65 /** 66 * Clears the router table. 67 * 68 */ 69 void Clear(void); 70 71 /** 72 * Removes all neighbor links to routers. 73 * 74 */ 75 void ClearNeighbors(void); 76 77 /** 78 * Allocates a router with a random Router ID. 79 * 80 * @returns A pointer to the allocated router or `nullptr` if a Router ID is not available. 81 * 82 */ 83 Router *Allocate(void); 84 85 /** 86 * Allocates a router with a specified Router ID. 87 * 88 * @param[in] aRouterId The Router ID to try to allocate. 89 * 90 * @returns A pointer to the allocated router or `nullptr` if the ID @p aRouterId could not be allocated. 91 * 92 */ 93 Router *Allocate(uint8_t aRouterId); 94 95 /** 96 * Releases a Router ID. 97 * 98 * @param[in] aRouterId The Router ID. 99 * 100 * @retval kErrorNone Successfully released the Router ID @p aRouterId. 101 * @retval kErrorInvalidState The device is not currently operating as a leader. 102 * @retval kErrorNotFound The Router ID @p aRouterId is not currently allocated. 103 * 104 */ 105 Error Release(uint8_t aRouterId); 106 107 /** 108 * Removes a router link. 109 * 110 * @param[in] aRouter A reference to the router. 111 * 112 */ 113 void RemoveRouterLink(Router &aRouter); 114 115 /** 116 * Returns the number of active routers in the Thread network. 117 * 118 * @returns The number of active routers in the Thread network. 119 * 120 */ GetActiveRouterCount(void) const121 uint8_t GetActiveRouterCount(void) const { return mRouters.GetLength(); } 122 123 /** 124 * Returns the leader in the Thread network. 125 * 126 * @returns A pointer to the Leader in the Thread network. 127 * 128 */ GetLeader(void)129 Router *GetLeader(void) { return AsNonConst(AsConst(this)->GetLeader()); } 130 131 /** 132 * Returns the leader in the Thread network. 133 * 134 * @returns A pointer to the Leader in the Thread network. 135 * 136 */ 137 const Router *GetLeader(void) const; 138 139 /** 140 * Returns the leader's age in seconds, i.e., seconds since the last Router ID Sequence update. 141 * 142 * @returns The leader's age. 143 * 144 */ 145 uint32_t GetLeaderAge(void) const; 146 147 /** 148 * Returns the link cost for a neighboring router. 149 * 150 * @param[in] aRouter A router. 151 * 152 * @returns The link cost to @p aRouter. 153 * 154 */ 155 uint8_t GetLinkCost(const Router &aRouter) const; 156 157 /** 158 * Returns the link cost to the given Router. 159 * 160 * @param[in] aRouterId The Router ID. 161 * 162 * @returns The link cost to the Router. 163 * 164 */ 165 uint8_t GetLinkCost(uint8_t aRouterId) const; 166 167 /** 168 * Returns the minimum mesh path cost to the given RLOC16 169 * 170 * @param[in] aDestRloc16 The RLOC16 of destination 171 * 172 * @returns The minimum mesh path cost to @p aDestRloc16 (via direct link or forwarding). 173 * 174 */ 175 uint8_t GetPathCost(uint16_t aDestRloc16) const; 176 177 /** 178 * Returns the mesh path cost to leader. 179 * 180 * @returns The path cost to leader. 181 * 182 */ 183 uint8_t GetPathCostToLeader(void) const; 184 185 /** 186 * Determines the next hop towards an RLOC16 destination. 187 * 188 * @param[in] aDestRloc16 The RLOC16 of the destination. 189 * 190 * @returns A RLOC16 of the next hop if a route is known, `Mle::kInvalidRloc16` otherwise. 191 * 192 */ 193 uint16_t GetNextHop(uint16_t aDestRloc16) const; 194 195 /** 196 * Determines the next hop and the path cost towards an RLOC16 destination. 197 * 198 * @param[in] aDestRloc16 The RLOC16 of the destination. 199 * @param[out] aNextHopRloc16 A reference to return the RLOC16 of next hop if known, or `Mle::kInvalidRloc16`. 200 * @param[out] aPathCost A reference to return the path cost. 201 * 202 */ 203 void GetNextHopAndPathCost(uint16_t aDestRloc16, uint16_t &aNextHopRloc16, uint8_t &aPathCost) const; 204 205 /** 206 * Finds the router for a given Router ID. 207 * 208 * @param[in] aRouterId The Router ID to search for. 209 * 210 * @returns A pointer to the router or `nullptr` if the router could not be found. 211 * 212 */ FindRouterById(uint8_t aRouterId)213 Router *FindRouterById(uint8_t aRouterId) { return AsNonConst(AsConst(this)->FindRouterById(aRouterId)); } 214 215 /** 216 * Finds the router for a given Router ID. 217 * 218 * @param[in] aRouterId The Router ID to search for. 219 * 220 * @returns A pointer to the router or `nullptr` if the router could not be found. 221 * 222 */ 223 const Router *FindRouterById(uint8_t aRouterId) const; 224 225 /** 226 * Finds the router for a given RLOC16. 227 * 228 * @param[in] aRloc16 The RLOC16 to search for. 229 * 230 * @returns A pointer to the router or `nullptr` if the router could not be found. 231 * 232 */ FindRouterByRloc16(uint16_t aRloc16)233 Router *FindRouterByRloc16(uint16_t aRloc16) { return AsNonConst(AsConst(this)->FindRouterByRloc16(aRloc16)); } 234 235 /** 236 * Finds the router for a given RLOC16. 237 * 238 * @param[in] aRloc16 The RLOC16 to search for. 239 * 240 * @returns A pointer to the router or `nullptr` if the router could not be found. 241 * 242 */ 243 const Router *FindRouterByRloc16(uint16_t aRloc16) const; 244 245 /** 246 * Finds the router that is the next hop of a given router. 247 * 248 * @param[in] aRouter The router to find next hop of. 249 * 250 * @returns A pointer to the router or `nullptr` if the router could not be found. 251 * 252 */ FindNextHopOf(const Router & aRouter)253 Router *FindNextHopOf(const Router &aRouter) { return AsNonConst(AsConst(this)->FindNextHopOf(aRouter)); } 254 255 /** 256 * Finds the router that is the next hop of a given router. 257 * 258 * @param[in] aRouter The router to find next hop of. 259 * 260 * @returns A pointer to the router or `nullptr` if the router could not be found. 261 * 262 */ 263 const Router *FindNextHopOf(const Router &aRouter) const; 264 265 /** 266 * Find the router for a given MAC Extended Address. 267 * 268 * @param[in] aExtAddress A reference to the MAC Extended Address. 269 * 270 * @returns A pointer to the router or `nullptr` if the router could not be found. 271 * 272 */ 273 Router *FindRouter(const Mac::ExtAddress &aExtAddress); 274 275 /** 276 * Indicates whether the router table contains a given `Neighbor` instance. 277 * 278 * @param[in] aNeighbor A reference to a `Neighbor`. 279 * 280 * @retval TRUE if @p aNeighbor is a `Router` in the router table. 281 * @retval FALSE if @p aNeighbor is not a `Router` in the router table 282 * (i.e. it can be the parent or parent candidate, or a `Child` of the child table). 283 * 284 */ Contains(const Neighbor & aNeighbor) const285 bool Contains(const Neighbor &aNeighbor) const 286 { 287 return mRouters.IsInArrayBuffer(&static_cast<const Router &>(aNeighbor)); 288 } 289 290 /** 291 * Retains diagnostic information for a given router. 292 * 293 * @param[in] aRouterId The router ID or RLOC16 for a given router. 294 * @param[out] aRouterInfo The router information. 295 * 296 * @retval kErrorNone Successfully retrieved the router info for given id. 297 * @retval kErrorInvalidArgs @p aRouterId is not a valid value for a router. 298 * @retval kErrorNotFound No router entry with the given id. 299 * 300 */ 301 Error GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo); 302 303 /** 304 * Returns the Router ID Sequence. 305 * 306 * @returns The Router ID Sequence. 307 * 308 */ GetRouterIdSequence(void) const309 uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; } 310 311 /** 312 * Returns the local time when the Router ID Sequence was last updated. 313 * 314 * @returns The local time when the Router ID Sequence was last updated. 315 * 316 */ GetRouterIdSequenceLastUpdated(void) const317 TimeMilli GetRouterIdSequenceLastUpdated(void) const { return mRouterIdSequenceLastUpdated; } 318 319 /** 320 * Determines whether the Router ID Sequence in a received Route TLV is more recent than the current 321 * Router ID Sequence being used by `RouterTable`. 322 * 323 * @param[in] aRouteTlv The Route TLV to compare. 324 * 325 * @retval TRUE The Router ID Sequence in @p aRouteTlv is more recent. 326 * @retval FALSE The Router ID Sequence in @p aRouteTlv is not more recent. 327 * 328 */ 329 bool IsRouteTlvIdSequenceMoreRecent(const Mle::RouteTlv &aRouteTlv) const; 330 331 /** 332 * Gets the number of router neighbors with `GetLinkQualityIn()` better than or equal to a given threshold. 333 * 334 * @param[in] aLinkQuality Link quality threshold. 335 * 336 * @returns Number of router neighbors with link quality of @o aLinkQuality or better. 337 * 338 */ 339 uint8_t GetNeighborCount(LinkQuality aLinkQuality) const; 340 341 /** 342 * Indicates whether or not a Router ID is allocated. 343 * 344 * @param[in] aRouterId The Router ID. 345 * 346 * @retval TRUE if @p aRouterId is allocated. 347 * @retval FALSE if @p aRouterId is not allocated. 348 * 349 */ IsAllocated(uint8_t aRouterId) const350 bool IsAllocated(uint8_t aRouterId) const { return mRouterIdMap.IsAllocated(aRouterId); } 351 352 /** 353 * Updates the Router ID allocation set. 354 * 355 * @param[in] aRouterIdSequence The Router ID Sequence. 356 * @param[in] aRouterIdSet The Router ID Set. 357 * 358 */ 359 void UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet); 360 361 /** 362 * Updates the routes based on a received `RouteTlv` from a neighboring router. 363 * 364 * @param[in] aRouteTlv The received `RouteTlv` 365 * @param[in] aNeighborId The router ID of neighboring router from which @p aRouteTlv is received. 366 * 367 */ 368 void UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aNeighborId); 369 370 /** 371 * Updates the routes on an FED based on a received `RouteTlv` from the parent. 372 * 373 * MUST be called when device is an FED child and @p aRouteTlv is received from its current parent. 374 * 375 * @param[in] aRouteTlv The received `RouteTlv` from parent. 376 * @param[in] aParentId The Router ID of parent. 377 * 378 */ 379 void UpdateRoutesOnFed(const Mle::RouteTlv &aRouteTlv, uint8_t aParentId); 380 381 /** 382 * Gets the allocated Router ID set. 383 * 384 * @param[out] aRouterIdSet A reference to output the allocated Router ID set. 385 * 386 */ GetRouterIdSet(Mle::RouterIdSet & aRouterIdSet) const387 void GetRouterIdSet(Mle::RouterIdSet &aRouterIdSet) const { return mRouterIdMap.GetAsRouterIdSet(aRouterIdSet); } 388 389 /** 390 * Fills a Route TLV. 391 * 392 * When @p aNeighbor is not `nullptr`, we limit the number of router entries to `kMaxRoutersInRouteTlvForLinkAccept` 393 * when populating `aRouteTlv`, so that the TLV can be appended in a Link Accept message. In this case, we ensure 394 * to include router entries associated with @p aNeighbor, leader, and this device itself. 395 * 396 * @param[out] aRouteTlv A Route TLV to be filled. 397 * @param[in] aNeighbor A pointer to the receiver (in case TLV is for a Link Accept message). 398 * 399 */ 400 void FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor = nullptr) const; 401 402 /** 403 * Updates the router table and must be called with a one second period. 404 * 405 */ 406 void HandleTimeTick(void); 407 408 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 409 /** 410 * Gets the range of Router IDs. 411 * 412 * All the Router IDs in the range `[aMinRouterId, aMaxRouterId]` are allowed. This is intended for testing only. 413 * 414 * @param[out] aMinRouterId Reference to return the minimum Router ID. 415 * @param[out] aMaxRouterId Reference to return the maximum Router ID. 416 * 417 */ 418 void GetRouterIdRange(uint8_t &aMinRouterId, uint8_t &aMaxRouterId) const; 419 420 /** 421 * Sets the range of Router IDs. 422 * 423 * All the Router IDs in the range `[aMinRouterId, aMaxRouterId]` are allowed. This is intended for testing only. 424 * 425 * @param[in] aMinRouterId The minimum Router ID. 426 * @param[in] aMaxRouterId The maximum Router ID. 427 * 428 * @retval kErrorNone Successfully set the Router ID range. 429 * @retval kErrorInvalidArgs The given range is not valid. 430 * 431 */ 432 Error SetRouterIdRange(uint8_t aMinRouterId, uint8_t aMaxRouterId); 433 #endif 434 435 // The following methods are intended to support range-based `for` 436 // loop iteration over the router and should not be used 437 // directly. 438 begin(void)439 Router *begin(void) { return mRouters.begin(); } end(void)440 Router *end(void) { return mRouters.end(); } begin(void) const441 const Router *begin(void) const { return mRouters.begin(); } end(void) const442 const Router *end(void) const { return mRouters.end(); } 443 444 private: 445 static constexpr uint32_t kRouterIdSequencePeriod = 10; // in sec 446 static constexpr uint8_t kLinkAcceptSequenceRollback = 64; 447 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 448 static constexpr uint8_t kMaxRoutersInRouteTlvForLinkAccept = 3; 449 #else 450 static constexpr uint8_t kMaxRoutersInRouteTlvForLinkAccept = 20; 451 #endif 452 453 Router *AddRouter(uint8_t aRouterId); 454 void RemoveRouter(Router &aRouter); 455 Router *FindNeighbor(uint16_t aRloc16); 456 Router *FindNeighbor(const Mac::ExtAddress &aExtAddress); 457 Router *FindNeighbor(const Mac::Address &aMacAddress); 458 const Router *FindRouter(const Router::AddressMatcher &aMatcher) const; FindRouter(const Router::AddressMatcher & aMatcher)459 Router *FindRouter(const Router::AddressMatcher &aMatcher) 460 { 461 return AsNonConst(AsConst(this)->FindRouter(aMatcher)); 462 } 463 464 void SignalTableChanged(void); 465 void HandleTableChanged(void); 466 void LogRouteTable(void) const; 467 468 class RouterIdMap : public Clearable<RouterIdMap> 469 { 470 public: 471 // The `RouterIdMap` tracks which Router IDs are allocated. 472 // For allocated IDs, tracks the index of the `Router` entry 473 // in `mRouters` array. For unallocated IDs, tracks the 474 // remaining reuse delay time (in seconds). 475 RouterIdMap(void)476 RouterIdMap(void) { Clear(); } IsAllocated(uint8_t aRouterId) const477 bool IsAllocated(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kAllocatedFlag); } GetIndex(uint8_t aRouterId) const478 uint8_t GetIndex(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kIndexMask); } SetIndex(uint8_t aRouterId,uint8_t aIndex)479 void SetIndex(uint8_t aRouterId, uint8_t aIndex) { mIndexes[aRouterId] = kAllocatedFlag | aIndex; } CanAllocate(uint8_t aRouterId) const480 bool CanAllocate(uint8_t aRouterId) const { return (mIndexes[aRouterId] == 0); } Release(uint8_t aRouterId)481 void Release(uint8_t aRouterId) { mIndexes[aRouterId] = kReuseDelay; } 482 void GetAsRouterIdSet(Mle::RouterIdSet &aRouterIdSet) const; 483 void HandleTimeTick(void); 484 485 private: 486 // The high bit in `mIndexes[aRouterId]` indicates whether or 487 // not the router ID is allocated. The lower 7 bits give either 488 // the index in `mRouter` array or remaining reuse delay time. 489 490 static constexpr uint8_t kReuseDelay = 100; // in sec 491 static constexpr uint8_t kAllocatedFlag = 1 << 7; 492 static constexpr uint8_t kIndexMask = 0x7f; 493 494 static_assert(kReuseDelay <= kIndexMask, "kReuseDelay does not fit in 7 bits"); 495 496 uint8_t mIndexes[Mle::kMaxRouterId + 1]; 497 }; 498 499 using ChangedTask = TaskletIn<RouterTable, &RouterTable::HandleTableChanged>; 500 501 Array<Router, Mle::kMaxRouters> mRouters; 502 ChangedTask mChangedTask; 503 RouterIdMap mRouterIdMap; 504 TimeMilli mRouterIdSequenceLastUpdated; 505 uint8_t mRouterIdSequence; 506 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 507 uint8_t mMinRouterId; 508 uint8_t mMaxRouterId; 509 #endif 510 }; 511 512 } // namespace ot 513 514 #endif // OPENTHREAD_FTD 515 516 #endif // ROUTER_TABLE_HPP_ 517