1 /* 2 * Copyright (c) 2020, 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 the RA-based routing management. 32 * 33 */ 34 35 #ifndef ROUTING_MANAGER_HPP_ 36 #define ROUTING_MANAGER_HPP_ 37 38 #include "openthread-core-config.h" 39 40 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 41 42 #if !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 43 #error "OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE." 44 #endif 45 46 #if !OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 47 #error "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE." 48 #endif 49 50 #if !OPENTHREAD_CONFIG_UPTIME_ENABLE 51 #error "OPENTHREAD_CONFIG_UPTIME_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE" 52 #endif 53 54 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE && !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 55 #error "TRACK_PEER_BR_INFO_ENABLE feature requires OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE" 56 #endif 57 58 #include <openthread/border_routing.h> 59 #include <openthread/nat64.h> 60 #include <openthread/netdata.h> 61 62 #include "border_router/infra_if.hpp" 63 #include "common/array.hpp" 64 #include "common/callback.hpp" 65 #include "common/equatable.hpp" 66 #include "common/error.hpp" 67 #include "common/heap_allocatable.hpp" 68 #include "common/heap_array.hpp" 69 #include "common/heap_data.hpp" 70 #include "common/linked_list.hpp" 71 #include "common/locator.hpp" 72 #include "common/message.hpp" 73 #include "common/notifier.hpp" 74 #include "common/owning_list.hpp" 75 #include "common/pool.hpp" 76 #include "common/string.hpp" 77 #include "common/timer.hpp" 78 #include "crypto/sha256.hpp" 79 #include "net/ip6.hpp" 80 #include "net/nat64_translator.hpp" 81 #include "net/nd6.hpp" 82 #include "thread/network_data.hpp" 83 84 namespace ot { 85 namespace BorderRouter { 86 87 extern "C" void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength); 88 extern "C" void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance *aInstance, 89 const otBorderRoutingPrefixTableEntry *aPrefixInfo); 90 91 /** 92 * Implements bi-directional routing between Thread and Infrastructure networks. 93 * 94 * The Border Routing manager works on both Thread interface and infrastructure interface. 95 * All ICMPv6 messages are sent/received on the infrastructure interface. 96 * 97 */ 98 class RoutingManager : public InstanceLocator 99 { 100 friend class ot::Notifier; 101 friend class ot::Instance; 102 103 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 104 friend void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength); 105 friend void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance *aInstance, 106 const otBorderRoutingPrefixTableEntry *aPrefixInfo); 107 #endif 108 109 public: 110 typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low). 111 typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator. 112 typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry. 113 typedef otBorderRoutingRouterEntry RouterEntry; ///< Router Entry. 114 typedef otBorderRoutingPeerBorderRouterEntry PeerBrEntry; ///< Peer Border Router Entry. 115 typedef otPdProcessedRaInfo PdProcessedRaInfo; ///< Data of PdProcessedRaInfo. 116 typedef otBorderRoutingRequestDhcp6PdCallback PdCallback; ///< DHCPv6 PD callback. 117 118 /** 119 * This constant specifies the maximum number of route prefixes that may be published by `RoutingManager` 120 * in Thread Network Data. 121 * 122 * This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`. 123 * 124 * The number of published entries accounts for: 125 * - Route prefix `fc00::/7` or `::/0` 126 * - One entry for NAT64 published prefix. 127 * - One extra entry for transitions. 128 * 129 */ 130 static constexpr uint16_t kMaxPublishedPrefixes = 3; 131 132 /** 133 * Represents the states of `RoutingManager`. 134 * 135 */ 136 enum State : uint8_t 137 { 138 kStateUninitialized = OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Uninitialized. 139 kStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Initialized but disabled. 140 kStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Initialized & enabled, but currently stopped. 141 kStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Initialized, enabled, and running. 142 }; 143 144 /** 145 * This enumeration represents the states of DHCPv6 PD in `RoutingManager`. 146 * 147 */ 148 enum Dhcp6PdState : uint8_t 149 { 150 kDhcp6PdStateDisabled = OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, ///< Disabled. 151 kDhcp6PdStateStopped = OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED, ///< Enabled, but currently stopped. 152 kDhcp6PdStateRunning = OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING, ///< Enabled, and running. 153 }; 154 155 /** 156 * Initializes the routing manager. 157 * 158 * @param[in] aInstance A OpenThread instance. 159 * 160 */ 161 explicit RoutingManager(Instance &aInstance); 162 163 /** 164 * Initializes the routing manager on given infrastructure interface. 165 * 166 * @param[in] aInfraIfIndex An infrastructure network interface index. 167 * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure 168 * interface is running. 169 * 170 * @retval kErrorNone Successfully started the routing manager. 171 * @retval kErrorInvalidArgs The index of the infra interface is not valid. 172 * 173 */ 174 Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning); 175 176 /** 177 * Enables/disables the Border Routing Manager. 178 * 179 * @note The Border Routing Manager is enabled by default. 180 * 181 * @param[in] aEnabled A boolean to enable/disable the Border Routing Manager. 182 * 183 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 184 * @retval kErrorNone Successfully enabled/disabled the Border Routing Manager. 185 * 186 */ 187 Error SetEnabled(bool aEnabled); 188 189 /** 190 * Indicates whether or not it is currently running. 191 * 192 * In order for the `RoutingManager` to be running it needs to be initialized and enabled, and device being 193 * attached. 194 * 195 * @retval TRUE The RoutingManager is currently running. 196 * @retval FALSE The RoutingManager is not running. 197 * 198 */ IsRunning(void) const199 bool IsRunning(void) const { return mIsRunning; } 200 201 /** 202 * Gets the state of `RoutingManager`. 203 * 204 * @returns The current state of `RoutingManager`. 205 * 206 */ 207 State GetState(void) const; 208 209 /** 210 * Requests the Border Routing Manager to stop. 211 * 212 * If Border Routing Manager is running, calling this method immediately stops it and triggers the preparation 213 * and sending of a final Router Advertisement (RA) message on infrastructure interface which deprecates and/or 214 * removes any previously advertised PIO/RIO prefixes. If Routing Manager is not running (or not enabled), no 215 * action is taken. 216 * 217 * Note that this method does not change whether the Routing Manager is enabled or disabled (see `SetEnabled()`). 218 * It stops the Routing Manager temporarily. After calling this method if the device role gets changes (device 219 * gets attached) and/or the infra interface state gets changed, the Routing Manager may be started again. 220 * 221 */ RequestStop(void)222 void RequestStop(void) { Stop(); } 223 224 /** 225 * Gets the current preference used when advertising Route Info Options (RIO) in Router Advertisement 226 * messages sent over the infrastructure link. 227 * 228 * The RIO preference is determined as follows: 229 * 230 * - If explicitly set by user by calling `SetRouteInfoOptionPreference()`, the given preference is used. 231 * - Otherwise, it is determined based on device's role: Medium preference when in router/leader role and low 232 * preference when in child role. 233 * 234 * @returns The current Route Info Option preference. 235 * 236 */ GetRouteInfoOptionPreference(void) const237 RoutePreference GetRouteInfoOptionPreference(void) const { return mRioAdvertiser.GetPreference(); } 238 239 /** 240 * Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router 241 * Advertisement messages sent over the infrastructure link. 242 * 243 * After a call to this method, BR will use the given preference for all its advertised RIOs. The preference can be 244 * cleared by calling `ClearRouteInfoOptionPreference`()`. 245 * 246 * @param[in] aPreference The route preference to use. 247 * 248 */ SetRouteInfoOptionPreference(RoutePreference aPreference)249 void SetRouteInfoOptionPreference(RoutePreference aPreference) { mRioAdvertiser.SetPreference(aPreference); } 250 251 /** 252 * Clears a previously set preference value for advertised Route Info Options. 253 * 254 * After a call to this method, BR will use device role to determine the RIO preference: Medium preference when 255 * in router/leader role and low preference when in child role. 256 * 257 */ ClearRouteInfoOptionPreference(void)258 void ClearRouteInfoOptionPreference(void) { mRioAdvertiser.ClearPreference(); } 259 260 /** 261 * Sets additional options to append at the end of emitted Router Advertisement (RA) messages. 262 * 263 * The content of @p aOptions is copied internally, so can be a temporary stack variable. 264 * 265 * Subsequent calls to this method will overwrite the previously set value. 266 * 267 * @param[in] aOptions A pointer to the encoded options. Can be `nullptr` to clear. 268 * @param[in] aLength Number of bytes in @p aOptions. 269 * 270 * @retval kErrorNone Successfully set the extra option bytes. 271 * @retval kErrorNoBufs Could not allocate buffer to save the buffer. 272 * 273 */ 274 Error SetExtraRouterAdvertOptions(const uint8_t *aOptions, uint16_t aLength); 275 276 /** 277 * Gets the current preference used for published routes in Network Data. 278 * 279 * The preference is determined as follows: 280 * 281 * - If explicitly set by user by calling `SetRoutePreference()`, the given preference is used. 282 * - Otherwise, it is determined automatically by `RoutingManager` based on the device's role and link quality. 283 * 284 * @returns The current published route preference. 285 * 286 */ GetRoutePreference(void) const287 RoutePreference GetRoutePreference(void) const { return mRoutePublisher.GetPreference(); } 288 289 /** 290 * Explicitly sets the preference of published routes in Network Data. 291 * 292 * After a call to this method, BR will use the given preference. The preference can be cleared by calling 293 * `ClearRoutePreference`()`. 294 * 295 * @param[in] aPreference The route preference to use. 296 * 297 */ SetRoutePreference(RoutePreference aPreference)298 void SetRoutePreference(RoutePreference aPreference) { mRoutePublisher.SetPreference(aPreference); } 299 300 /** 301 * Clears a previously set preference value for published routes in Network Data. 302 * 303 * After a call to this method, BR will determine the preference automatically based on the device's role and 304 * link quality (to the parent when acting as end-device). 305 * 306 */ ClearRoutePreference(void)307 void ClearRoutePreference(void) { mRoutePublisher.ClearPreference(); } 308 309 /** 310 * Returns the local generated off-mesh-routable (OMR) prefix. 311 * 312 * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR 313 * prefix. 314 * 315 * @param[out] aPrefix A reference to where the prefix will be output to. 316 * 317 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 318 * @retval kErrorNone Successfully retrieved the OMR prefix. 319 * 320 */ 321 Error GetOmrPrefix(Ip6::Prefix &aPrefix) const; 322 323 /** 324 * Returns the currently favored off-mesh-routable (OMR) prefix. 325 * 326 * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix. 327 * 328 * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the 329 * sense defined by `Ip6::Prefix`) is favored. 330 * 331 * @param[out] aPrefix A reference to output the favored prefix. 332 * @param[out] aPreference A reference to output the preference associated with the favored OMR prefix. 333 * 334 * @retval kErrorInvalidState The Border Routing Manager is not running yet. 335 * @retval kErrorNone Successfully retrieved the OMR prefix. 336 * 337 */ 338 Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const; 339 340 /** 341 * Returns the on-link prefix for the adjacent infrastructure link. 342 * 343 * The randomly generated 64-bit prefix will be advertised 344 * on the infrastructure link if there isn't already a usable 345 * on-link prefix being advertised on the link. 346 * 347 * @param[out] aPrefix A reference to where the prefix will be output to. 348 * 349 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 350 * @retval kErrorNone Successfully retrieved the local on-link prefix. 351 * 352 */ 353 Error GetOnLinkPrefix(Ip6::Prefix &aPrefix) const; 354 355 /** 356 * Returns the favored on-link prefix for the adjacent infrastructure link. 357 * 358 * The favored prefix is either a discovered prefix on the infrastructure link or the local on-link prefix. 359 * 360 * @param[out] aPrefix A reference to where the prefix will be output to. 361 * 362 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 363 * @retval kErrorNone Successfully retrieved the favored on-link prefix. 364 * 365 */ 366 Error GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const; 367 368 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 369 /** 370 * Gets the state of NAT64 prefix publishing. 371 * 372 * @retval kStateDisabled NAT64 is disabled. 373 * @retval kStateNotRunning NAT64 is enabled, but is not running since routing manager is not running. 374 * @retval kStateIdle NAT64 is enabled, but the border router is not publishing a NAT64 prefix. Usually 375 * when there is another border router publishing a NAT64 prefix with higher 376 * priority. 377 * @retval kStateActive The Border router is publishing a NAT64 prefix. 378 * 379 */ GetNat64PrefixManagerState(void) const380 Nat64::State GetNat64PrefixManagerState(void) const { return mNat64PrefixManager.GetState(); } 381 382 /** 383 * Enable or disable NAT64 prefix publishing. 384 * 385 * @param[in] aEnabled A boolean to enable/disable NAT64 prefix publishing. 386 * 387 */ 388 void SetNat64PrefixManagerEnabled(bool aEnabled); 389 390 /** 391 * Returns the local NAT64 prefix. 392 * 393 * @param[out] aPrefix A reference to where the prefix will be output to. 394 * 395 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 396 * @retval kErrorNone Successfully retrieved the NAT64 prefix. 397 * 398 */ 399 Error GetNat64Prefix(Ip6::Prefix &aPrefix); 400 401 /** 402 * Returns the currently favored NAT64 prefix. 403 * 404 * The favored NAT64 prefix can be discovered from infrastructure link or can be the local NAT64 prefix. 405 * 406 * @param[out] aPrefix A reference to output the favored prefix. 407 * @param[out] aRoutePreference A reference to output the preference associated with the favored prefix. 408 * 409 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 410 * @retval kErrorNone Successfully retrieved the NAT64 prefix. 411 * 412 */ 413 Error GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreference &aRoutePreference); 414 415 /** 416 * Informs `RoutingManager` of the result of the discovery request of NAT64 prefix on infrastructure 417 * interface (`InfraIf::DiscoverNat64Prefix()`). 418 * 419 * @param[in] aPrefix The discovered NAT64 prefix on `InfraIf`. 420 * 421 */ HandleDiscoverNat64PrefixDone(const Ip6::Prefix & aPrefix)422 void HandleDiscoverNat64PrefixDone(const Ip6::Prefix &aPrefix) { mNat64PrefixManager.HandleDiscoverDone(aPrefix); } 423 424 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 425 426 /** 427 * Processes a received ICMPv6 message from the infrastructure interface. 428 * 429 * Malformed or undesired messages are dropped silently. 430 * 431 * @param[in] aPacket The received ICMPv6 packet. 432 * @param[in] aSrcAddress The source address this message is sent from. 433 * 434 */ 435 void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 436 437 /** 438 * Handles infrastructure interface state changes. 439 * 440 */ HandleInfraIfStateChanged(void)441 void HandleInfraIfStateChanged(void) { EvaluateState(); } 442 443 /** 444 * Checks whether the on-mesh prefix configuration is a valid OMR prefix. 445 * 446 * @param[in] aOnMeshPrefixConfig The on-mesh prefix configuration to check. 447 * 448 * @retval TRUE The prefix is a valid OMR prefix. 449 * @retval FALSE The prefix is not a valid OMR prefix. 450 * 451 */ 452 static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 453 454 /** 455 * Checks whether a given prefix is a valid OMR prefix. 456 * 457 * @param[in] aPrefix The prefix to check. 458 * 459 * @retval TRUE The prefix is a valid OMR prefix. 460 * @retval FALSE The prefix is not a valid OMR prefix. 461 * 462 */ 463 static bool IsValidOmrPrefix(const Ip6::Prefix &aPrefix); 464 465 /** 466 * Initializes a `PrefixTableIterator`. 467 * 468 * An iterator can be initialized again to start from the beginning of the table. 469 * 470 * When iterating over entries in the table, to ensure the entry update times are consistent, they are given 471 * relative to the time the iterator was initialized. 472 * 473 * @param[out] aIterator The iterator to initialize. 474 * 475 */ InitPrefixTableIterator(PrefixTableIterator & aIterator) const476 void InitPrefixTableIterator(PrefixTableIterator &aIterator) const { mRxRaTracker.InitIterator(aIterator); } 477 478 /** 479 * Iterates over entries in the discovered prefix table. 480 * 481 * @param[in,out] aIterator An iterator. 482 * @param[out] aEntry A reference to the entry to populate. 483 * 484 * @retval kErrorNone Got the next entry, @p aEntry is updated and @p aIterator is advanced. 485 * @retval kErrorNotFound No more entries in the table. 486 * 487 */ GetNextPrefixTableEntry(PrefixTableIterator & aIterator,PrefixTableEntry & aEntry) const488 Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const 489 { 490 return mRxRaTracker.GetNextEntry(aIterator, aEntry); 491 } 492 493 /** 494 * Iterates over discovered router entries on infrastructure link. 495 * 496 * @param[in,out] aIterator An iterator. 497 * @param[out] aEntry A reference to the entry to populate. 498 * 499 * @retval kErrorNone Got the next router info, @p aEntry is updated and @p aIterator is advanced. 500 * @retval kErrorNotFound No more routers. 501 * 502 */ GetNextRouterEntry(PrefixTableIterator & aIterator,RouterEntry & aEntry) const503 Error GetNextRouterEntry(PrefixTableIterator &aIterator, RouterEntry &aEntry) const 504 { 505 return mRxRaTracker.GetNextRouter(aIterator, aEntry); 506 } 507 508 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 509 510 /** 511 * Iterates over the peer BRs found in the Network Data. 512 * 513 * @param[in,out] aIterator An iterator. 514 * @param[out] aEntry A reference to the entry to populate. 515 * 516 * @retval kErrorNone Got the next peer BR info, @p aEntry is updated and @p aIterator is advanced. 517 * @retval kErrorNotFound No more PR beers in the list. 518 * 519 */ GetNextPeerBrEntry(PrefixTableIterator & aIterator,PeerBrEntry & aEntry) const520 Error GetNextPeerBrEntry(PrefixTableIterator &aIterator, PeerBrEntry &aEntry) const 521 { 522 return mNetDataPeerBrTracker.GetNext(aIterator, aEntry); 523 } 524 525 /** 526 * Returns the number of peer BRs found in the Network Data. 527 * 528 * The count does not include this device itself (when it itself is acting as a BR). 529 * 530 * @param[out] aMinAge Reference to an `uint32_t` to return the minimum age among all peer BRs. 531 * Age is represented as seconds since appearance of the BR entry in the Network Data. 532 * 533 * @returns The number of peer BRs. 534 * 535 */ CountPeerBrs(uint32_t & aMinAge) const536 uint16_t CountPeerBrs(uint32_t &aMinAge) const { return mNetDataPeerBrTracker.CountPeerBrs(aMinAge); } 537 538 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 539 540 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 541 /** 542 * Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server. 543 * 544 * This should be called from `Srp::Server` when auto-enable mode is changed. 545 * 546 */ 547 void HandleSrpServerAutoEnableMode(void); 548 #endif 549 550 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 551 /** 552 * Enables / Disables the DHCPv6 Prefix Delegation. 553 * 554 * @param[in] aEnabled Whether to enable or disable. 555 * 556 */ SetDhcp6PdEnabled(bool aEnabled)557 void SetDhcp6PdEnabled(bool aEnabled) { return mPdPrefixManager.SetEnabled(aEnabled); } 558 559 /** 560 * Returns the state DHCPv6 Prefix Delegation manager. 561 * 562 * @returns The DHCPv6 PD state. 563 * 564 */ GetDhcp6PdState(void) const565 Dhcp6PdState GetDhcp6PdState(void) const { return mPdPrefixManager.GetState(); } 566 567 /** 568 * Sets the callback to notify when DHCPv6 Prefix Delegation manager state gets changed. 569 * 570 * @param[in] aCallback A pointer to a callback function 571 * @param[in] aContext A pointer to arbitrary context information. 572 * 573 */ SetRequestDhcp6PdCallback(PdCallback aCallback,void * aContext)574 void SetRequestDhcp6PdCallback(PdCallback aCallback, void *aContext) 575 { 576 mPdPrefixManager.SetStateCallback(aCallback, aContext); 577 } 578 579 /** 580 * Returns the DHCPv6-PD based off-mesh-routable (OMR) prefix. 581 * 582 * @param[out] aPrefixInfo A reference to where the prefix info will be output to. 583 * 584 * @retval kErrorNone Successfully retrieved the OMR prefix. 585 * @retval kErrorNotFound There are no valid PD prefix on this BR. 586 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 587 * 588 */ 589 Error GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const; 590 591 /** 592 * Returns platform generated RA message processed counters and information. 593 * 594 * @param[out] aPdProcessedRaInfo A reference to where the PD processed RA info will be output to. 595 * 596 * @retval kErrorNone Successfully retrieved the Info. 597 * @retval kErrorNotFound There are no valid RA process info on this BR. 598 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 599 * 600 */ 601 Error GetPdProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo); 602 603 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 604 605 #if OPENTHREAD_CONFIG_BORDER_ROUTING_REACHABILITY_CHECK_ICMP6_ERROR_ENABLE 606 /** 607 * Determines whether to send an ICMPv6 Destination Unreachable error to the sender based on reachability and 608 * source address. 609 * 610 * Specifically, if the Border Router (BR) decides to forward a unicast IPv6 message outside the AIL and the 611 * message's source address matches a BR-generated ULA OMR prefix (with low preference), and the destination is 612 * unreachable using this source address, then an ICMPv6 Destination Unreachable message is sent back to the sender. 613 * 614 * @param[in] aMessage The message. 615 * @param[in] aIp6Header The IPv6 header of @p aMessage. 616 * 617 */ 618 void CheckReachabilityToSendIcmpError(const Message &aMessage, const Ip6::Header &aIp6Header); 619 #endif 620 621 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE 622 /** 623 * Sets the local on-link prefix. 624 * 625 * This is intended for testing only and using it will make a device non-compliant with the Thread Specification. 626 * 627 * @param[in] aPrefix The on-link prefix to use. 628 * 629 */ SetOnLinkPrefix(const Ip6::Prefix & aPrefix)630 void SetOnLinkPrefix(const Ip6::Prefix &aPrefix) { mOnLinkPrefixManager.SetLocalPrefix(aPrefix); } 631 #endif 632 633 private: 634 //------------------------------------------------------------------------------------------------------------------ 635 // Constants 636 637 static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES; 638 639 // Prefix length in bits. 640 static constexpr uint8_t kOmrPrefixLength = 64; 641 static constexpr uint8_t kOnLinkPrefixLength = 64; 642 static constexpr uint8_t kBrUlaPrefixLength = 48; 643 static constexpr uint8_t kNat64PrefixLength = 96; 644 645 // Subnet IDs for OMR and NAT64 prefixes. 646 static constexpr uint16_t kOmrPrefixSubnetId = 1; 647 static constexpr uint16_t kNat64PrefixSubnetId = 2; 648 649 // Default valid lifetime. In seconds. 650 static constexpr uint32_t kDefaultOmrPrefixLifetime = 1800; 651 static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800; 652 static constexpr uint32_t kDefaultNat64PrefixLifetime = 300; 653 654 // The entry stale time in seconds. 655 // 656 // The amount of time that can pass after the last time an RA from 657 // a particular router has been received advertising an on-link 658 // or route prefix before we assume the prefix entry is stale. 659 // 660 // If multiple routers advertise the same on-link or route prefix, 661 // the stale time for the prefix is determined by the latest 662 // stale time among all corresponding entries. Stale time 663 // expiration triggers tx of Router Solicitation (RS) messages 664 665 static constexpr uint32_t kStaleTime = 600; // 10 minutes. 666 667 // RA transmission constants (in milliseconds). Initially, three 668 // RAs are sent with a short interval of 16 seconds (± 2 seconds 669 // jitter). Subsequently, a longer, regular RA beacon interval of 670 // 3 minutes (± 15 seconds jitter) is used. The actual interval is 671 // randomly selected within the range [interval - jitter, 672 // interval + jitter]. 673 674 static constexpr uint32_t kInitalRaTxCount = 3; 675 static constexpr uint32_t kInitalRaInterval = Time::kOneSecondInMsec * 16; 676 static constexpr uint16_t kInitialRaJitter = Time::kOneSecondInMsec * 2; 677 static constexpr uint32_t kRaBeaconInterval = Time::kOneSecondInMsec * 180; // 3 minutes 678 static constexpr uint16_t kRaBeaconJitter = Time::kOneSecondInMsec * 15; 679 static constexpr uint32_t kMinDelayBetweenRas = Time::kOneSecondInMsec * 3; 680 static constexpr uint32_t kRsReplyInterval = 250; 681 static constexpr uint16_t kRsReplyJitter = 250; 682 static constexpr uint32_t kEvaluationInterval = Time::kOneSecondInMsec * 3; 683 static constexpr uint16_t kEvaluationJitter = Time::kOneSecondInMsec * 1; 684 685 //------------------------------------------------------------------------------------------------------------------ 686 // Typedefs 687 688 using Option = Ip6::Nd::Option; 689 using PrefixInfoOption = Ip6::Nd::PrefixInfoOption; 690 using RouteInfoOption = Ip6::Nd::RouteInfoOption; 691 using RaFlagsExtOption = Ip6::Nd::RaFlagsExtOption; 692 using RouterAdvert = Ip6::Nd::RouterAdvert; 693 using NeighborAdvertMessage = Ip6::Nd::NeighborAdvertMessage; 694 using NeighborSolicitMessage = Ip6::Nd::NeighborSolicitMessage; 695 using RouterSolicitMessage = Ip6::Nd::RouterSolicitMessage; 696 697 //------------------------------------------------------------------------------------------------------------------ 698 // Enumerations 699 700 enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()` 701 { 702 kInvalidateAllPrevPrefixes, 703 kAdvPrefixesFromNetData, 704 }; 705 706 enum RouterAdvOrigin : uint8_t // Origin of a received Router Advert message. 707 { 708 kAnotherRouter, // From another router on infra-if. 709 kThisBrRoutingManager, // From this BR generated by `RoutingManager` itself. 710 kThisBrOtherEntity, // From this BR generated by another sw entity. 711 }; 712 713 enum ScheduleMode : uint8_t // Used in `ScheduleRoutingPolicyEvaluation()` 714 { 715 kImmediately, 716 kForNextRa, 717 kAfterRandomDelay, 718 kToReplyToRs, 719 }; 720 721 //------------------------------------------------------------------------------------------------------------------ 722 // Nested types 723 724 class LifetimedPrefix 725 { 726 // Represents an IPv6 prefix with its valid lifetime. Used as 727 // base class for `OnLinkPrefix` or `RoutePrefix`. 728 729 public: 730 struct ExpirationChecker 731 { ExpirationCheckerot::BorderRouter::RoutingManager::LifetimedPrefix::ExpirationChecker732 explicit ExpirationChecker(TimeMilli aNow) { mNow = aNow; } 733 TimeMilli mNow; 734 }; 735 GetPrefix(void) const736 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetPrefix(void)737 Ip6::Prefix &GetPrefix(void) { return mPrefix; } GetLastUpdateTime(void) const738 const TimeMilli &GetLastUpdateTime(void) const { return mLastUpdateTime; } GetValidLifetime(void) const739 uint32_t GetValidLifetime(void) const { return mValidLifetime; } GetExpireTime(void) const740 TimeMilli GetExpireTime(void) const { return CalculateExpirationTime(mValidLifetime); } 741 Matches(const Ip6::Prefix & aPrefix) const742 bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); } Matches(const ExpirationChecker & aChecker) const743 bool Matches(const ExpirationChecker &aChecker) const { return (GetExpireTime() <= aChecker.mNow); } 744 SetStaleTimeCalculated(bool aFlag)745 void SetStaleTimeCalculated(bool aFlag) { mStaleTimeCalculated = aFlag; } IsStaleTimeCalculated(void) const746 bool IsStaleTimeCalculated(void) const { return mStaleTimeCalculated; } 747 SetDisregardFlag(bool aFlag)748 void SetDisregardFlag(bool aFlag) { mDisregard = aFlag; } ShouldDisregard(void) const749 bool ShouldDisregard(void) const { return mDisregard; } 750 751 protected: 752 LifetimedPrefix(void) = default; 753 754 TimeMilli CalculateExpirationTime(uint32_t aLifetime) const; 755 756 Ip6::Prefix mPrefix; 757 bool mDisregard : 1; 758 bool mStaleTimeCalculated : 1; 759 uint32_t mValidLifetime; 760 TimeMilli mLastUpdateTime; 761 }; 762 763 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 764 765 class OnLinkPrefix : public LifetimedPrefix, public Clearable<OnLinkPrefix> 766 { 767 public: 768 void SetFrom(const PrefixInfoOption &aPio); 769 void SetFrom(const PrefixTableEntry &aPrefixTableEntry); GetPreferredLifetime(void) const770 uint32_t GetPreferredLifetime(void) const { return mPreferredLifetime; } ClearPreferredLifetime(void)771 void ClearPreferredLifetime(void) { mPreferredLifetime = 0; } 772 bool IsDeprecated(void) const; 773 TimeMilli GetDeprecationTime(void) const; 774 TimeMilli GetStaleTime(void) const; 775 void AdoptValidAndPreferredLifetimesFrom(const OnLinkPrefix &aPrefix); 776 void CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const; 777 bool IsFavoredOver(const Ip6::Prefix &aPrefix) const; 778 779 private: 780 static constexpr uint32_t kFavoredMinPreferredLifetime = 1800; // In sec. 781 782 uint32_t mPreferredLifetime; 783 }; 784 785 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 786 787 class RoutePrefix : public LifetimedPrefix, public Clearable<RoutePrefix> 788 { 789 public: 790 void SetFrom(const RouteInfoOption &aRio); 791 void SetFrom(const RouterAdvert::Header &aRaHeader); ClearValidLifetime(void)792 void ClearValidLifetime(void) { mValidLifetime = 0; } 793 TimeMilli GetStaleTime(void) const; GetRoutePreference(void) const794 RoutePreference GetRoutePreference(void) const { return mRoutePreference; } 795 void CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const; 796 797 private: 798 RoutePreference mRoutePreference; 799 }; 800 801 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 802 803 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 804 805 class RxRaTracker; 806 807 class NetDataPeerBrTracker : public InstanceLocator 808 { 809 friend class RxRaTracker; 810 811 public: 812 explicit NetDataPeerBrTracker(Instance &aInstance); 813 814 uint16_t CountPeerBrs(uint32_t &aMinAge) const; 815 Error GetNext(PrefixTableIterator &aIterator, PeerBrEntry &aEntry) const; 816 817 void HandleNotifierEvents(Events aEvents); 818 819 private: 820 struct PeerBr : LinkedListEntry<PeerBr>, Heap::Allocatable<PeerBr> 821 { 822 struct Filter 823 { Filterot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr::Filter824 Filter(const NetworkData::Rlocs &aRlocs) 825 : mExcludeRlocs(aRlocs) 826 { 827 } 828 829 const NetworkData::Rlocs &mExcludeRlocs; 830 }; 831 GetAgeot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr832 uint32_t GetAge(uint32_t aUptime) const { return aUptime - mDiscoverTime; } Matchesot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr833 bool Matches(uint16_t aRloc16) const { return mRloc16 == aRloc16; } Matchesot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr834 bool Matches(const Filter &aFilter) const { return !aFilter.mExcludeRlocs.Contains(mRloc16); } 835 836 PeerBr *mNext; 837 uint16_t mRloc16; 838 uint32_t mDiscoverTime; 839 }; 840 841 OwningList<PeerBr> mPeerBrs; 842 }; 843 844 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 845 846 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 847 HandleRxRaTrackerSignalTask(void)848 void HandleRxRaTrackerSignalTask(void) { mRxRaTracker.HandleSignalTask(); } HandleRxRaTrackerExpirationTimer(void)849 void HandleRxRaTrackerExpirationTimer(void) { mRxRaTracker.HandleExpirationTimer(); } HandleRxRaTrackerStaleTimer(void)850 void HandleRxRaTrackerStaleTimer(void) { mRxRaTracker.HandleStaleTimer(); } HandleRxRaTrackerRouterTimer(void)851 void HandleRxRaTrackerRouterTimer(void) { mRxRaTracker.HandleRouterTimer(); } 852 853 class RxRaTracker : public InstanceLocator 854 { 855 // Processes received RA and NA messages tracking a table of active 856 // routers and their advertised on-link and route prefixes. Also 857 // manages prefix lifetimes and router reachability (sending NS probes 858 // as needed). 859 // 860 // When there is any change in the table (an entry is added, removed, 861 // or modified), it signals the change to `RoutingManager` by calling 862 // `HandleRaPrefixTableChanged()` callback. A `Tasklet` is used for 863 // signalling which ensures that if there are multiple changes within 864 // the same flow of execution, the callback is invoked after all the 865 // changes are processed. 866 867 friend class NetDataPeerBrTracker; 868 869 public: 870 explicit RxRaTracker(Instance &aInstance); 871 872 void Start(void); 873 void Stop(void); 874 875 void ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage, 876 const Ip6::Address &aSrcAddress, 877 RouterAdvOrigin aRaOrigin); 878 void ProcessNeighborAdvertMessage(const NeighborAdvertMessage &aNaMessage); 879 880 // Decision factors ContainsDefaultOrNonUlaRoutePrefix(void) const881 bool ContainsDefaultOrNonUlaRoutePrefix(void) const { return mDecisionFactors.mHasNonUlaRoute; } ContainsNonUlaOnLinkPrefix(void) const882 bool ContainsNonUlaOnLinkPrefix(void) const { return mDecisionFactors.mHasNonUlaOnLink; } ContainsUlaOnLinkPrefix(void) const883 bool ContainsUlaOnLinkPrefix(void) const { return mDecisionFactors.mHasUlaOnLink; } 884 GetFavoredOnLinkPrefix(void) const885 const Ip6::Prefix &GetFavoredOnLinkPrefix(void) const { return mDecisionFactors.mFavoredOnLinkPrefix; } 886 void SetHeaderFlagsOn(RouterAdvert::Header &aHeader) const; 887 GetLocalRaHeaderToMirror(void) const888 const RouterAdvert::Header &GetLocalRaHeaderToMirror(void) const { return mLocalRaHeader; } 889 890 bool IsAddressOnLink(const Ip6::Address &aAddress) const; 891 bool IsAddressReachableThroughExplicitRoute(const Ip6::Address &aAddress) const; 892 893 // Iterating over discovered items 894 void InitIterator(PrefixTableIterator &aIterator) const; 895 Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const; 896 Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const; 897 898 // Callbacks notifying of changes 899 void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold); 900 void HandleLocalOnLinkPrefixChanged(void); 901 void HandleNetDataChange(void); 902 903 // Tasklet or timer callbacks 904 void HandleSignalTask(void); 905 void HandleExpirationTimer(void); 906 void HandleStaleTimer(void); 907 void HandleRouterTimer(void); 908 909 private: 910 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 911 912 template <class Type> 913 struct Entry : public Type, 914 public LinkedListEntry<Entry<Type>>, 915 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 916 public Heap::Allocatable<Entry<Type>> 917 #else 918 public InstanceLocatorInit 919 #endif 920 { 921 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE Initot::BorderRouter::RoutingManager::RxRaTracker::Entry922 void Init(Instance &aInstance) { InstanceLocatorInit::Init(aInstance); } 923 void Free(void); 924 #endif 925 926 Entry<Type> *mNext; 927 }; 928 929 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 930 931 struct Router : public Clearable<Router> 932 { 933 // Reachability timeout intervals before starting Neighbor 934 // Solicitation (NS) probes. Generally 60 seconds (± 2 935 // seconds jitter) is used. For peer BRs a longer timeout 936 // of 200 seconds (3 min and 20 seconds) is used. This is 937 // selected to be longer than regular RA beacon interval 938 // of 3 minutes (± 15 seconds jitter). 939 940 static constexpr uint32_t kReachableInterval = OPENTHREAD_CONFIG_BORDER_ROUTING_ROUTER_ACTIVE_CHECK_TIMEOUT; 941 static constexpr uint32_t kPeerBrReachableInterval = Time::kOneSecondInMsec * 200; 942 943 static constexpr uint8_t kMaxNsProbes = 5; // Max number of NS probe attempts. 944 static constexpr uint32_t kNsProbeRetryInterval = 1000; // In msec. Time between NS probe attempts. 945 static constexpr uint32_t kNsProbeTimeout = 2000; // In msec. Max Wait time after last NS probe. 946 static constexpr uint32_t kJitter = 2000; // In msec. Jitter to randomize probe starts. 947 948 static_assert(kMaxNsProbes < 255, "kMaxNsProbes MUST not be 255"); 949 950 typedef LifetimedPrefix::ExpirationChecker EmptyChecker; 951 IsReachableot::BorderRouter::RoutingManager::RxRaTracker::Router952 bool IsReachable(void) const { return mNsProbeCount <= kMaxNsProbes; } 953 bool ShouldCheckReachability(void) const; 954 void ResetReachabilityState(void); 955 void DetermineReachabilityTimeout(void); Matchesot::BorderRouter::RoutingManager::RxRaTracker::Router956 bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; } 957 bool Matches(const EmptyChecker &aChecker); 958 bool IsPeerBr(void) const; 959 void CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow, uint32_t aUptime) const; 960 961 using OnLinkPrefixList = OwningList<Entry<OnLinkPrefix>>; 962 using RoutePrefixList = OwningList<Entry<RoutePrefix>>; 963 964 // `mDiscoverTime` tracks the initial discovery time of 965 // this router. To accommodate longer durations, the 966 // `Uptime` is used, as `TimeMilli` (which uses `uint32_t` 967 // intervals) would be limited to tracking ~ 49 days. 968 // 969 // `mLastUpdateTime` tracks the most recent time an RA or 970 // NA was received from this router. It is bounded due to 971 // the frequency of reachability checks, so we can safely 972 // use `TimeMilli` for it. 973 974 Ip6::Address mAddress; 975 OnLinkPrefixList mOnLinkPrefixes; 976 RoutePrefixList mRoutePrefixes; 977 uint32_t mDiscoverTime; 978 TimeMilli mLastUpdateTime; 979 TimeMilli mTimeoutTime; 980 uint8_t mNsProbeCount; 981 bool mManagedAddressConfigFlag : 1; 982 bool mOtherConfigFlag : 1; 983 bool mStubRouterFlag : 1; 984 bool mIsLocalDevice : 1; 985 bool mAllEntriesDisregarded : 1; 986 }; 987 988 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 989 990 class Iterator : public PrefixTableIterator 991 { 992 public: 993 enum Type : uint8_t 994 { 995 kUnspecified, 996 kRouterIterator, 997 kPrefixIterator, 998 kPeerBrIterator, 999 }; 1000 1001 enum EntryType : uint8_t 1002 { 1003 kOnLinkPrefix, 1004 kRoutePrefix, 1005 }; 1006 1007 void Init(const Entry<Router> *aRoutersHead, uint32_t aUptime); 1008 Error AdvanceToNextRouter(Type aType); 1009 Error AdvanceToNextEntry(void); GetInitUptime(void) const1010 uint32_t GetInitUptime(void) const { return mData0; } GetInitTime(void) const1011 TimeMilli GetInitTime(void) const { return TimeMilli(mData1); } GetType(void) const1012 Type GetType(void) const { return static_cast<Type>(mData2); } GetRouter(void) const1013 const Entry<Router> *GetRouter(void) const { return static_cast<const Entry<Router> *>(mPtr1); } GetEntryType(void) const1014 EntryType GetEntryType(void) const { return static_cast<EntryType>(mData3); } 1015 GetEntry(void) const1016 template <class PrefixType> const Entry<PrefixType> *GetEntry(void) const 1017 { 1018 return static_cast<const Entry<PrefixType> *>(mPtr2); 1019 } 1020 1021 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 1022 using PeerBr = NetDataPeerBrTracker::PeerBr; 1023 1024 Error AdvanceToNextPeerBr(const PeerBr *aPeerBrsHead); GetPeerBrEntry(void) const1025 const PeerBr *GetPeerBrEntry(void) const { return static_cast<const PeerBr *>(mPtr2); } 1026 #endif 1027 1028 private: SetRouter(const Entry<Router> * aRouter)1029 void SetRouter(const Entry<Router> *aRouter) { mPtr1 = aRouter; } SetInitUptime(uint32_t aUptime)1030 void SetInitUptime(uint32_t aUptime) { mData0 = aUptime; } SetInitTime(void)1031 void SetInitTime(void) { mData1 = TimerMilli::GetNow().GetValue(); } SetEntry(const void * aEntry)1032 void SetEntry(const void *aEntry) { mPtr2 = aEntry; } HasEntry(void) const1033 bool HasEntry(void) const { return mPtr2 != nullptr; } SetEntryType(EntryType aType)1034 void SetEntryType(EntryType aType) { mData3 = aType; } SetType(Type aType)1035 void SetType(Type aType) { mData2 = aType; } 1036 }; 1037 1038 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1039 1040 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1041 static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS; 1042 static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES; 1043 1044 union SharedEntry 1045 { SharedEntry(void)1046 SharedEntry(void) { mNext = nullptr; } SetNext(SharedEntry * aNext)1047 void SetNext(SharedEntry *aNext) { mNext = aNext; } GetNext(void)1048 SharedEntry *GetNext(void) { return mNext; } GetNext(void) const1049 const SharedEntry *GetNext(void) const { return mNext; } 1050 1051 template <class PrefixType> Entry<PrefixType> &GetEntry(void); 1052 1053 SharedEntry *mNext; 1054 Entry<OnLinkPrefix> mOnLinkEntry; 1055 Entry<RoutePrefix> mRouteEntry; 1056 }; 1057 #endif 1058 1059 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1060 1061 struct DecisionFactors : public Clearable<DecisionFactors>, public Equatable<DecisionFactors> 1062 { DecisionFactorsot::BorderRouter::RoutingManager::RxRaTracker::DecisionFactors1063 DecisionFactors(void) { Clear(); } 1064 HasFavoredOnLinkot::BorderRouter::RoutingManager::RxRaTracker::DecisionFactors1065 bool HasFavoredOnLink(void) const { return (mFavoredOnLinkPrefix.GetLength() != 0); } 1066 void UpdateFlagsFrom(const Router &aRouter); 1067 void UpdateFrom(const OnLinkPrefix &aOnLinkPrefix); 1068 void UpdateFrom(const RoutePrefix &aRoutePrefix); 1069 1070 Ip6::Prefix mFavoredOnLinkPrefix; 1071 bool mHasNonUlaRoute : 1; 1072 bool mHasNonUlaOnLink : 1; 1073 bool mHasUlaOnLink : 1; 1074 bool mHeaderManagedAddressConfigFlag : 1; 1075 bool mHeaderOtherConfigFlag : 1; 1076 }; 1077 1078 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1079 1080 void ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter, RouterAdvOrigin aRaOrigin); 1081 void ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter); 1082 void ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter); 1083 void ProcessRaFlagsExtOption(const RaFlagsExtOption &aFlagsOption, Router &aRouter); 1084 void Evaluate(void); 1085 void DetermineStaleTimeFor(const OnLinkPrefix &aPrefix, NextFireTime &aStaleTime); 1086 void DetermineStaleTimeFor(const RoutePrefix &aPrefix, NextFireTime &aStaleTime); 1087 void SendNeighborSolicitToRouter(const Router &aRouter); 1088 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE AllocateEntry(void)1089 template <class Type> Entry<Type> *AllocateEntry(void) { return Entry<Type>::Allocate(); } 1090 #else 1091 template <class Type> Entry<Type> *AllocateEntry(void); 1092 #endif 1093 1094 using SignalTask = TaskletIn<RoutingManager, &RoutingManager::HandleRxRaTrackerSignalTask>; 1095 using ExpirationTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerExpirationTimer>; 1096 using StaleTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerStaleTimer>; 1097 using RouterTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerRouterTimer>; 1098 using RouterList = OwningList<Entry<Router>>; 1099 1100 DecisionFactors mDecisionFactors; 1101 RouterList mRouters; 1102 ExpirationTimer mExpirationTimer; 1103 StaleTimer mStaleTimer; 1104 RouterTimer mRouterTimer; 1105 SignalTask mSignalTask; 1106 RouterAdvert::Header mLocalRaHeader; 1107 TimeMilli mLocalRaHeaderUpdateTime; 1108 1109 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1110 Pool<SharedEntry, kMaxEntries> mEntryPool; 1111 Pool<Entry<Router>, kMaxRouters> mRouterPool; 1112 #endif 1113 }; 1114 1115 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1116 1117 class OmrPrefixManager; 1118 1119 class OmrPrefix : public Clearable<OmrPrefix> 1120 { 1121 friend class OmrPrefixManager; 1122 1123 public: OmrPrefix(void)1124 OmrPrefix(void) { Clear(); } 1125 IsEmpty(void) const1126 bool IsEmpty(void) const { return (mPrefix.GetLength() == 0); } GetPrefix(void) const1127 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetPreference(void) const1128 RoutePreference GetPreference(void) const { return mPreference; } IsDomainPrefix(void) const1129 bool IsDomainPrefix(void) const { return mIsDomainPrefix; } 1130 1131 protected: 1132 Ip6::Prefix mPrefix; 1133 RoutePreference mPreference; 1134 bool mIsDomainPrefix; 1135 }; 1136 1137 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1138 1139 class FavoredOmrPrefix : public OmrPrefix 1140 { 1141 friend class OmrPrefixManager; 1142 1143 public: 1144 bool IsInfrastructureDerived(void) const; 1145 1146 private: 1147 void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 1148 void SetFrom(const OmrPrefix &aOmrPrefix); 1149 bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const; 1150 }; 1151 1152 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1153 1154 class OmrPrefixManager : public InstanceLocator 1155 { 1156 public: 1157 explicit OmrPrefixManager(Instance &aInstance); 1158 1159 void Init(const Ip6::Prefix &aBrUlaPrefix); 1160 void Start(void); 1161 void Stop(void); 1162 void Evaluate(void); 1163 void UpdateDefaultRouteFlag(bool aDefaultRoute); 1164 bool ShouldAdvertiseLocalAsRio(void) const; GetGeneratedPrefix(void) const1165 const Ip6::Prefix &GetGeneratedPrefix(void) const { return mGeneratedPrefix; } GetLocalPrefix(void) const1166 const OmrPrefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredPrefix(void) const1167 const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; } 1168 1169 private: 1170 static constexpr uint16_t kInfoStringSize = 85; 1171 1172 typedef String<kInfoStringSize> InfoString; 1173 1174 void DetermineFavoredPrefix(void); 1175 Error AddLocalToNetData(void); 1176 Error AddOrUpdateLocalInNetData(void); 1177 void RemoveLocalFromNetData(void); 1178 InfoString LocalToString(void) const; 1179 1180 OmrPrefix mLocalPrefix; 1181 Ip6::Prefix mGeneratedPrefix; 1182 FavoredOmrPrefix mFavoredPrefix; 1183 bool mIsLocalAddedInNetData; 1184 bool mDefaultRoute; 1185 }; 1186 1187 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1188 HandleOnLinkPrefixManagerTimer(void)1189 void HandleOnLinkPrefixManagerTimer(void) { mOnLinkPrefixManager.HandleTimer(); } 1190 1191 class OnLinkPrefixManager : public InstanceLocator 1192 { 1193 public: 1194 explicit OnLinkPrefixManager(Instance &aInstance); 1195 1196 // Max number of old on-link prefixes to retain to deprecate. 1197 static constexpr uint16_t kMaxOldPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES; 1198 1199 void Init(void); 1200 void Start(void); 1201 void Stop(void); 1202 void Evaluate(void); GetLocalPrefix(void) const1203 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredDiscoveredPrefix(void) const1204 const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; } 1205 bool IsInitalEvaluationDone(void) const; 1206 void HandleRaPrefixTableChanged(void); 1207 bool ShouldPublishUlaRoute(void) const; 1208 Error AppendAsPiosTo(RouterAdvert::TxMessage &aRaMessage); 1209 void HandleNetDataChange(void); 1210 void HandleExtPanIdChange(void); 1211 void HandleTimer(void); 1212 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE SetLocalPrefix(const Ip6::Prefix & aPrefix)1213 void SetLocalPrefix(const Ip6::Prefix &aPrefix) { mLocalPrefix = aPrefix; } 1214 #endif 1215 1216 private: 1217 enum State : uint8_t // State of `mLocalPrefix` 1218 { 1219 kIdle, 1220 kPublishing, 1221 kAdvertising, 1222 kDeprecating, 1223 }; 1224 1225 struct OldPrefix 1226 { Matchesot::BorderRouter::RoutingManager::OnLinkPrefixManager::OldPrefix1227 bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; } 1228 1229 Ip6::Prefix mPrefix; 1230 TimeMilli mExpireTime; 1231 }; 1232 GetState(void) const1233 State GetState(void) const { return mState; } 1234 void SetState(State aState); 1235 bool IsPublishingOrAdvertising(void) const; 1236 void GenerateLocalPrefix(void); 1237 void PublishAndAdvertise(void); 1238 void Deprecate(void); 1239 void ResetExpireTime(TimeMilli aNow); 1240 Error AppendCurPrefix(RouterAdvert::TxMessage &aRaMessage); 1241 Error AppendOldPrefixes(RouterAdvert::TxMessage &aRaMessage); 1242 void DeprecateOldPrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 1243 void SavePrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 1244 1245 static const char *StateToString(State aState); 1246 1247 using ExpireTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleOnLinkPrefixManagerTimer>; 1248 1249 Ip6::Prefix mLocalPrefix; 1250 State mState; 1251 TimeMilli mExpireTime; 1252 Ip6::Prefix mFavoredDiscoveredPrefix; 1253 Array<OldPrefix, kMaxOldPrefixes> mOldLocalPrefixes; 1254 ExpireTimer mTimer; 1255 }; 1256 1257 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1258 HandleRioAdvertiserimer(void)1259 void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); } 1260 1261 class RioAdvertiser : public InstanceLocator 1262 { 1263 // Manages the list of prefixes advertised as RIO in emitted 1264 // RA. The RIO prefixes are discovered from on-mesh prefixes in 1265 // network data including OMR prefix from `OmrPrefixManager`. 1266 // It also handles deprecating removed prefixes. 1267 1268 public: 1269 explicit RioAdvertiser(Instance &aInstance); 1270 GetPreference(void) const1271 RoutePreference GetPreference(void) const { return mPreference; } 1272 void SetPreference(RoutePreference aPreference); 1273 void ClearPreference(void); 1274 void HandleRoleChanged(void); 1275 Error AppendRios(RouterAdvert::TxMessage &aRaMessage); 1276 Error InvalidatPrevRios(RouterAdvert::TxMessage &aRaMessage); HasAdvertised(const Ip6::Prefix & aPrefix) const1277 bool HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); } GetAdvertisedRioCount(void) const1278 uint16_t GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); } 1279 void HandleTimer(void); 1280 1281 private: 1282 static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300); 1283 1284 struct RioPrefix : public Clearable<RioPrefix> 1285 { Matchesot::BorderRouter::RoutingManager::RioAdvertiser::RioPrefix1286 bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); } 1287 1288 Ip6::Prefix mPrefix; 1289 bool mIsDeprecating; 1290 TimeMilli mExpirationTime; 1291 }; 1292 1293 struct RioPrefixArray : 1294 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1295 public Heap::Array<RioPrefix> 1296 #else 1297 public Array<RioPrefix, 2 * kMaxOnMeshPrefixes> 1298 #endif 1299 { 1300 void Add(const Ip6::Prefix &aPrefix); 1301 }; 1302 1303 void SetPreferenceBasedOnRole(void); 1304 void UpdatePreference(RoutePreference aPreference); 1305 Error AppendRio(const Ip6::Prefix &aPrefix, 1306 uint32_t aRouteLifetime, 1307 RoutePreference aPreference, 1308 RouterAdvert::TxMessage &aRaMessage); 1309 1310 using RioTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRioAdvertiserimer>; 1311 1312 RioPrefixArray mPrefixes; 1313 RioTimer mTimer; 1314 RoutePreference mPreference; 1315 bool mUserSetPreference; 1316 }; 1317 1318 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1319 1320 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1321 HandleNat64PrefixManagerTimer(void)1322 void HandleNat64PrefixManagerTimer(void) { mNat64PrefixManager.HandleTimer(); } 1323 1324 class Nat64PrefixManager : public InstanceLocator 1325 { 1326 public: 1327 // This class manages the NAT64 related functions including 1328 // generation of local NAT64 prefix, discovery of infra 1329 // interface prefix, maintaining the discovered prefix 1330 // lifetime, and selection of the NAT64 prefix to publish in 1331 // Network Data. 1332 // 1333 // Calling methods except GenerateLocalPrefix and SetEnabled 1334 // when disabled becomes no-op. 1335 1336 explicit Nat64PrefixManager(Instance &aInstance); 1337 1338 void SetEnabled(bool aEnabled); 1339 Nat64::State GetState(void) const; 1340 1341 void Start(void); 1342 void Stop(void); 1343 1344 void GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix); GetLocalPrefix(void) const1345 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } 1346 const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const; 1347 void Evaluate(void); 1348 void HandleDiscoverDone(const Ip6::Prefix &aPrefix); 1349 void HandleTimer(void); 1350 1351 private: 1352 void Discover(void); 1353 void Publish(void); 1354 1355 using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>; 1356 1357 bool mEnabled; 1358 1359 Ip6::Prefix mInfraIfPrefix; // The latest NAT64 prefix discovered on the infrastructure interface. 1360 Ip6::Prefix mLocalPrefix; // The local prefix (from BR ULA prefix). 1361 Ip6::Prefix mPublishedPrefix; // The prefix to publish in Net Data (empty or local or from infra-if). 1362 RoutePreference mPublishedPreference; // The published prefix preference. 1363 Nat64Timer mTimer; 1364 }; 1365 1366 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1367 1368 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1369 HandleRoutePublisherTimer(void)1370 void HandleRoutePublisherTimer(void) { mRoutePublisher.HandleTimer(); } 1371 1372 class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data 1373 { 1374 public: 1375 explicit RoutePublisher(Instance &aInstance); 1376 Start(void)1377 void Start(void) { Evaluate(); } Stop(void)1378 void Stop(void) { Unpublish(); } 1379 void Evaluate(void); 1380 1381 void UpdateAdvPioFlags(bool aAdvPioFlag); 1382 GetPreference(void) const1383 RoutePreference GetPreference(void) const { return mPreference; } 1384 void SetPreference(RoutePreference aPreference); 1385 void ClearPreference(void); 1386 1387 void HandleNotifierEvents(Events aEvents); 1388 void HandleTimer(void); 1389 GetUlaPrefix(void)1390 static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); } 1391 1392 private: 1393 static constexpr uint32_t kDelayBeforePrfUpdateOnLinkQuality3 = TimeMilli::SecToMsec(5 * 60); 1394 1395 static const otIp6Prefix kUlaPrefix; 1396 1397 enum State : uint8_t 1398 { 1399 kDoNotPublish, // Do not publish any routes in network data. 1400 kPublishDefault, // Publish "::/0" route in network data. 1401 kPublishUla, // Publish "fc00::/7" route in network data. 1402 }; 1403 1404 void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const; 1405 void UpdatePublishedRoute(State aNewState); 1406 void Unpublish(void); 1407 void SetPreferenceBasedOnRole(void); 1408 void UpdatePreference(RoutePreference aPreference); 1409 1410 static const char *StateToString(State aState); 1411 1412 using DelayTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRoutePublisherTimer>; 1413 1414 State mState; 1415 RoutePreference mPreference; 1416 bool mUserSetPreference; 1417 bool mAdvPioFlag; 1418 DelayTimer mTimer; 1419 }; 1420 1421 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1422 1423 struct TxRaInfo 1424 { 1425 // Tracks info about emitted RA messages: 1426 // 1427 // - Number of RAs sent 1428 // - Last RA TX time 1429 // - Hashes of last TX RAs (to tell if a received RA is from 1430 // `RoutingManager` itself). 1431 1432 typedef Crypto::Sha256::Hash Hash; 1433 1434 static constexpr uint16_t kNumHashEntries = 5; 1435 TxRaInfoot::BorderRouter::RoutingManager::TxRaInfo1436 TxRaInfo(void) 1437 : mTxCount(0) 1438 , mLastTxTime(TimerMilli::GetNow() - kMinDelayBetweenRas) 1439 , mLastHashIndex(0) 1440 { 1441 } 1442 1443 void IncrementTxCountAndSaveHash(const InfraIf::Icmp6Packet &aRaMessage); 1444 bool IsRaFromManager(const RouterAdvert::RxMessage &aRaMessage) const; 1445 static void CalculateHash(const RouterAdvert::RxMessage &aRaMessage, Hash &aHash); 1446 1447 uint32_t mTxCount; 1448 TimeMilli mLastTxTime; 1449 Hash mHashes[kNumHashEntries]; 1450 uint16_t mLastHashIndex; 1451 }; 1452 1453 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1454 HandleRsSenderTimer(void)1455 void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); } 1456 1457 class RsSender : public InstanceLocator 1458 { 1459 public: 1460 // This class implements tx of Router Solicitation (RS) 1461 // messages to discover other routers. `Start()` schedules 1462 // a cycle of RS transmissions of `kMaxTxCount` separated 1463 // by `kTxInterval`. At the end of cycle the callback 1464 // `HandleRsSenderFinished()` is invoked to inform end of 1465 // the cycle to `RoutingManager`. 1466 1467 explicit RsSender(Instance &aInstance); 1468 IsInProgress(void) const1469 bool IsInProgress(void) const { return mTimer.IsRunning(); } 1470 void Start(void); 1471 void Stop(void); 1472 void HandleTimer(void); 1473 1474 private: 1475 // All time intervals are in msec. 1476 static constexpr uint32_t kMaxStartDelay = 1000; // Max random delay to send the first RS. 1477 static constexpr uint32_t kTxInterval = 4000; // Interval between RS tx. 1478 static constexpr uint32_t kRetryDelay = kTxInterval; // Interval to wait to retry a failed RS tx. 1479 static constexpr uint32_t kWaitOnLastAttempt = 1000; // Wait interval after last RS tx. 1480 static constexpr uint8_t kMaxTxCount = 3; // Number of RS tx in one cycle. 1481 1482 Error SendRs(void); 1483 1484 using RsTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRsSenderTimer>; 1485 1486 uint8_t mTxCount; 1487 RsTimer mTimer; 1488 TimeMilli mStartTime; 1489 }; 1490 1491 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1492 1493 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1494 HandlePdPrefixManagerTimer(void)1495 void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); } 1496 1497 class PdPrefixManager : public InstanceLocator 1498 { 1499 public: 1500 // This class implements handling (including management of the 1501 // lifetime) of the prefix obtained from platform's DHCPv6 PD 1502 // client. 1503 1504 typedef Dhcp6PdState State; 1505 1506 explicit PdPrefixManager(Instance &aInstance); 1507 1508 void SetEnabled(bool aEnabled); Start(void)1509 void Start(void) { StartStop(/* aStart= */ true); } Stop(void)1510 void Stop(void) { StartStop(/* aStart= */ false); } IsRunning(void) const1511 bool IsRunning(void) const { return GetState() == kDhcp6PdStateRunning; } HasPrefix(void) const1512 bool HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); } GetPrefix(void) const1513 const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); } 1514 State GetState(void) const; 1515 1516 void ProcessRa(const uint8_t *aRouterAdvert, uint16_t aLength); 1517 void ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry); 1518 Error GetPrefixInfo(PrefixTableEntry &aInfo) const; 1519 Error GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const; HandleTimer(void)1520 void HandleTimer(void) { WithdrawPrefix(); } SetStateCallback(PdCallback aCallback,void * aContext)1521 void SetStateCallback(PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); } 1522 1523 private: 1524 class PrefixEntry : public OnLinkPrefix 1525 { 1526 public: PrefixEntry(void)1527 PrefixEntry(void) { Clear(); } IsEmpty(void) const1528 bool IsEmpty(void) const { return (GetPrefix().GetLength() == 0); } 1529 bool IsValidPdPrefix(void) const; 1530 bool IsFavoredOver(const PrefixEntry &aOther) const; 1531 }; 1532 1533 void Process(const RouterAdvert::Icmp6Packet *aRaPacket, const PrefixTableEntry *aPrefixTableEntry); 1534 bool ProcessPrefixEntry(PrefixEntry &aEntry, PrefixEntry &aFavoredEntry); 1535 void EvaluateStateChange(State aOldState); 1536 void WithdrawPrefix(void); 1537 void StartStop(bool aStart); 1538 1539 static const char *StateToString(State aState); 1540 1541 using PrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>; 1542 using StateCallback = Callback<PdCallback>; 1543 1544 bool mEnabled; 1545 bool mIsRunning; 1546 uint32_t mNumPlatformPioProcessed; 1547 uint32_t mNumPlatformRaReceived; 1548 TimeMilli mLastPlatformRaTime; 1549 StateCallback mStateCallback; 1550 PrefixTimer mTimer; 1551 PrefixEntry mPrefix; 1552 }; 1553 1554 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1555 1556 //------------------------------------------------------------------------------------------------------------------ 1557 // Methods 1558 1559 void EvaluateState(void); 1560 void Start(void); 1561 void Stop(void); 1562 void HandleNotifierEvents(Events aEvents); IsInitialized(void) const1563 bool IsInitialized(void) const { return mInfraIf.IsInitialized(); } IsEnabled(void) const1564 bool IsEnabled(void) const { return mIsEnabled; } 1565 Error LoadOrGenerateRandomBrUlaPrefix(void); 1566 1567 void EvaluateRoutingPolicy(void); 1568 bool IsInitialPolicyEvaluationDone(void) const; 1569 void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode); 1570 void HandleRsSenderFinished(TimeMilli aStartTime); 1571 void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode); 1572 1573 void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1574 void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1575 void HandleNeighborAdvertisement(const InfraIf::Icmp6Packet &aPacket); 1576 bool NetworkDataContainsUlaRoute(void) const; 1577 1578 void HandleRaPrefixTableChanged(void); 1579 void HandleLocalOnLinkPrefixChanged(void); 1580 1581 static TimeMilli CalculateExpirationTime(TimeMilli aUpdateTime, uint32_t aLifetime); 1582 1583 static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix); 1584 static bool IsValidOnLinkPrefix(const PrefixInfoOption &aPio); 1585 static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); 1586 1587 static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime); 1588 static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference); 1589 1590 static const char *RouterAdvOriginToString(RouterAdvOrigin aRaOrigin); 1591 1592 //------------------------------------------------------------------------------------------------------------------ 1593 // Variables 1594 1595 using RoutingPolicyTimer = TimerMilliIn<RoutingManager, &RoutingManager::EvaluateRoutingPolicy>; 1596 1597 // Indicates whether the Routing Manager is running (started). 1598 bool mIsRunning; 1599 1600 // Indicates whether the Routing manager is enabled. The Routing 1601 // Manager will be stopped if we are disabled. 1602 bool mIsEnabled; 1603 1604 InfraIf mInfraIf; 1605 1606 // The /48 BR ULA prefix loaded from local persistent storage or 1607 // randomly generated if none is found in persistent storage. 1608 Ip6::Prefix mBrUlaPrefix; 1609 1610 OmrPrefixManager mOmrPrefixManager; 1611 1612 RioAdvertiser mRioAdvertiser; 1613 RoutePreference mRioPreference; 1614 bool mUserSetRioPreference; 1615 1616 OnLinkPrefixManager mOnLinkPrefixManager; 1617 1618 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 1619 NetDataPeerBrTracker mNetDataPeerBrTracker; 1620 #endif 1621 1622 RxRaTracker mRxRaTracker; 1623 1624 RoutePublisher mRoutePublisher; 1625 1626 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1627 Nat64PrefixManager mNat64PrefixManager; 1628 #endif 1629 1630 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1631 PdPrefixManager mPdPrefixManager; 1632 #endif 1633 1634 TxRaInfo mTxRaInfo; 1635 RsSender mRsSender; 1636 Heap::Data mExtraRaOptions; 1637 1638 RoutingPolicyTimer mRoutingPolicyTimer; 1639 }; 1640 1641 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1642 1643 //---------------------------------------------------------------------------------------------------------------------- 1644 // Template specializations and declarations 1645 1646 template <> 1647 inline RoutingManager::RxRaTracker::Entry<RoutingManager::OnLinkPrefix> GetEntry(void)1648 &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void) 1649 { 1650 return mOnLinkEntry; 1651 } 1652 1653 template <> 1654 inline RoutingManager::RxRaTracker::Entry<RoutingManager::RoutePrefix> GetEntry(void)1655 &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void) 1656 { 1657 return mRouteEntry; 1658 } 1659 1660 // Declare template (full) specializations for `Router` type. 1661 1662 template <> 1663 RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router> *RoutingManager::RxRaTracker::AllocateEntry( 1664 void); 1665 1666 template <> void RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router>::Free(void); 1667 1668 #endif // #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1669 1670 } // namespace BorderRouter 1671 1672 DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State); 1673 1674 } // namespace ot 1675 1676 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1677 1678 #endif // ROUTING_MANAGER_HPP_ 1679