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