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