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/nat64.h> 51 #include <openthread/netdata.h> 52 53 #include "border_router/infra_if.hpp" 54 #include "common/array.hpp" 55 #include "common/error.hpp" 56 #include "common/linked_list.hpp" 57 #include "common/locator.hpp" 58 #include "common/message.hpp" 59 #include "common/notifier.hpp" 60 #include "common/pool.hpp" 61 #include "common/string.hpp" 62 #include "common/timer.hpp" 63 #include "net/ip6.hpp" 64 #include "net/nat64_translator.hpp" 65 #include "net/nd6.hpp" 66 #include "thread/network_data.hpp" 67 68 namespace ot { 69 70 namespace BorderRouter { 71 72 /** 73 * Implements bi-directional routing between Thread and Infrastructure networks. 74 * 75 * The Border Routing manager works on both Thread interface and infrastructure interface. 76 * All ICMPv6 messages are sent/received on the infrastructure interface. 77 * 78 */ 79 class RoutingManager : public InstanceLocator 80 { 81 friend class ot::Notifier; 82 friend class ot::Instance; 83 84 public: 85 typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low). 86 typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator. 87 typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry. 88 89 /** 90 * This constant specifies the maximum number of route prefixes that may be published by `RoutingManager` 91 * in Thread Network Data. 92 * 93 * This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`. 94 * 95 * The number of published entries accounts for: 96 * - Route prefix `fc00::/7` or `::/0` 97 * - One entry for NAT64 published prefix. 98 * - One extra entry for transitions. 99 * 100 */ 101 static constexpr uint16_t kMaxPublishedPrefixes = 3; 102 103 /** 104 * Represents the states of `RoutingManager`. 105 * 106 */ 107 enum State : uint8_t 108 { 109 kStateUninitialized = OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Uninitialized. 110 kStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Initialized but disabled. 111 kStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Initialized & enabled, but currently stopped. 112 kStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Initialized, enabled, and running. 113 }; 114 115 /** 116 * This enumeration represents the states of DHCPv6 PD in `RoutingManager`. 117 * 118 */ 119 enum Dhcp6PdState : uint8_t 120 { 121 kDhcp6PdStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Disabled. 122 kDhcp6PdStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Enabled, but currently stopped. 123 kDhcp6PdStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Enabled, and running. 124 }; 125 126 /** 127 * Initializes the routing manager. 128 * 129 * @param[in] aInstance A OpenThread instance. 130 * 131 */ 132 explicit RoutingManager(Instance &aInstance); 133 134 /** 135 * Initializes the routing manager on given infrastructure interface. 136 * 137 * @param[in] aInfraIfIndex An infrastructure network interface index. 138 * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure 139 * interface is running. 140 * 141 * @retval kErrorNone Successfully started the routing manager. 142 * @retval kErrorInvalidArgs The index of the infra interface is not valid. 143 * 144 */ 145 Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning); 146 147 /** 148 * Enables/disables the Border Routing Manager. 149 * 150 * @note The Border Routing Manager is enabled by default. 151 * 152 * @param[in] aEnabled A boolean to enable/disable the Border Routing Manager. 153 * 154 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 155 * @retval kErrorNone Successfully enabled/disabled the Border Routing Manager. 156 * 157 */ 158 Error SetEnabled(bool aEnabled); 159 160 /** 161 * Indicates whether or not it is currently running. 162 * 163 * In order for the `RoutingManager` to be running it needs to be initialized and enabled, and device being 164 * attached. 165 * 166 * @retval TRUE The RoutingManager is currently running. 167 * @retval FALSE The RoutingManager is not running. 168 * 169 */ IsRunning(void) const170 bool IsRunning(void) const { return mIsRunning; } 171 172 /** 173 * Gets the state of `RoutingManager`. 174 * 175 * @returns The current state of `RoutingManager`. 176 * 177 */ 178 State GetState(void) const; 179 180 /** 181 * Requests the Border Routing Manager to stop. 182 * 183 * If Border Routing Manager is running, calling this method immediately stops it and triggers the preparation 184 * and sending of a final Router Advertisement (RA) message on infrastructure interface which deprecates and/or 185 * removes any previously advertised PIO/RIO prefixes. If Routing Manager is not running (or not enabled), no 186 * action is taken. 187 * 188 * Note that this method does not change whether the Routing Manager is enabled or disabled (see `SetEnabled()`). 189 * It stops the Routing Manager temporarily. After calling this method if the device role gets changes (device 190 * gets attached) and/or the infra interface state gets changed, the Routing Manager may be started again. 191 * 192 */ RequestStop(void)193 void RequestStop(void) { Stop(); } 194 195 /** 196 * Gets the current preference used when advertising Route Info Options (RIO) in Router Advertisement 197 * messages sent over the infrastructure link. 198 * 199 * The RIO preference is determined as follows: 200 * 201 * - If explicitly set by user by calling `SetRouteInfoOptionPreference()`, the given preference is used. 202 * - Otherwise, it is determined based on device's role: Medium preference when in router/leader role and low 203 * preference when in child role. 204 * 205 * @returns The current Route Info Option preference. 206 * 207 */ GetRouteInfoOptionPreference(void) const208 RoutePreference GetRouteInfoOptionPreference(void) const { return mRioPreference; } 209 210 /** 211 * Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router 212 * Advertisement messages sent over the infrastructure link. 213 * 214 * After a call to this method, BR will use the given preference for all its advertised RIOs. The preference can be 215 * cleared by calling `ClearRouteInfoOptionPreference`()`. 216 * 217 * @param[in] aPreference The route preference to use. 218 * 219 */ 220 void SetRouteInfoOptionPreference(RoutePreference aPreference); 221 222 /** 223 * Clears a previously set preference value for advertised Route Info Options. 224 * 225 * After a call to this method, BR will use device role to determine the RIO preference: Medium preference when 226 * in router/leader role and low preference when in child role. 227 * 228 */ 229 void ClearRouteInfoOptionPreference(void); 230 231 /** 232 * Gets the current preference used for published routes in Network Data. 233 * 234 * The preference is determined as follows: 235 * 236 * - If explicitly set by user by calling `SetRoutePreference()`, the given preference is used. 237 * - Otherwise, it is determined automatically by `RoutingManager` based on the device's role and link quality. 238 * 239 * @returns The current published route preference. 240 * 241 */ GetRoutePreference(void) const242 RoutePreference GetRoutePreference(void) const { return mRoutePublisher.GetPreference(); } 243 244 /** 245 * Explicitly sets the preference of published routes in Network Data. 246 * 247 * After a call to this method, BR will use the given preference. The preference can be cleared by calling 248 * `ClearRoutePreference`()`. 249 * 250 * @param[in] aPreference The route preference to use. 251 * 252 */ SetRoutePreference(RoutePreference aPreference)253 void SetRoutePreference(RoutePreference aPreference) { mRoutePublisher.SetPreference(aPreference); } 254 255 /** 256 * Clears a previously set preference value for published routes in Network Data. 257 * 258 * After a call to this method, BR will determine the preference automatically based on the device's role and 259 * link quality (to the parent when acting as end-device). 260 * 261 */ ClearRoutePreference(void)262 void ClearRoutePreference(void) { mRoutePublisher.ClearPreference(); } 263 264 /** 265 * Returns the local generated off-mesh-routable (OMR) prefix. 266 * 267 * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR 268 * prefix. 269 * 270 * @param[out] aPrefix A reference to where the prefix will be output to. 271 * 272 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 273 * @retval kErrorNone Successfully retrieved the OMR prefix. 274 * 275 */ 276 Error GetOmrPrefix(Ip6::Prefix &aPrefix) const; 277 278 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 279 /** 280 * Returns the platform provided off-mesh-routable (OMR) prefix. 281 * 282 * The prefix is extracted from the platform generated RA messages handled by `ProcessPlatfromGeneratedNd()`. 283 * 284 * @param[out] aPrefixInfo A reference to where the prefix info will be output to. 285 * 286 * @retval kErrorNone Successfully retrieved the OMR prefix. 287 * @retval kErrorNotFound There are no valid PD prefix on this BR. 288 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 289 * 290 */ 291 Error GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const; 292 #endif 293 294 /** 295 * Returns the currently favored off-mesh-routable (OMR) prefix. 296 * 297 * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix. 298 * 299 * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the 300 * sense defined by `Ip6::Prefix`) is favored. 301 * 302 * @param[out] aPrefix A reference to output the favored prefix. 303 * @param[out] aPreference A reference to output the preference associated with the favored OMR prefix. 304 * 305 * @retval kErrorInvalidState The Border Routing Manager is not running yet. 306 * @retval kErrorNone Successfully retrieved the OMR prefix. 307 * 308 */ 309 Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const; 310 311 /** 312 * Returns the on-link prefix for the adjacent infrastructure link. 313 * 314 * The randomly generated 64-bit prefix will be advertised 315 * on the infrastructure link if there isn't already a usable 316 * on-link prefix being advertised on the link. 317 * 318 * @param[out] aPrefix A reference to where the prefix will be output to. 319 * 320 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 321 * @retval kErrorNone Successfully retrieved the local on-link prefix. 322 * 323 */ 324 Error GetOnLinkPrefix(Ip6::Prefix &aPrefix) const; 325 326 /** 327 * Returns the favored on-link prefix for the adjacent infrastructure link. 328 * 329 * The favored prefix is either a discovered prefix on the infrastructure link or the local on-link prefix. 330 * 331 * @param[out] aPrefix A reference to where the prefix will be output to. 332 * 333 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 334 * @retval kErrorNone Successfully retrieved the favored on-link prefix. 335 * 336 */ 337 Error GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const; 338 339 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 340 /** 341 * Gets the state of NAT64 prefix publishing. 342 * 343 * @retval kStateDisabled NAT64 is disabled. 344 * @retval kStateNotRunning NAT64 is enabled, but is not running since routing manager is not running. 345 * @retval kStateIdle NAT64 is enabled, but the border router is not publishing a NAT64 prefix. Usually 346 * when there is another border router publishing a NAT64 prefix with higher 347 * priority. 348 * @retval kStateActive The Border router is publishing a NAT64 prefix. 349 * 350 */ GetNat64PrefixManagerState(void) const351 Nat64::State GetNat64PrefixManagerState(void) const { return mNat64PrefixManager.GetState(); } 352 353 /** 354 * Enable or disable NAT64 prefix publishing. 355 * 356 * @param[in] aEnabled A boolean to enable/disable NAT64 prefix publishing. 357 * 358 */ 359 void SetNat64PrefixManagerEnabled(bool aEnabled); 360 361 /** 362 * Returns the local NAT64 prefix. 363 * 364 * @param[out] aPrefix A reference to where the prefix will be output to. 365 * 366 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 367 * @retval kErrorNone Successfully retrieved the NAT64 prefix. 368 * 369 */ 370 Error GetNat64Prefix(Ip6::Prefix &aPrefix); 371 372 /** 373 * Returns the currently favored NAT64 prefix. 374 * 375 * The favored NAT64 prefix can be discovered from infrastructure link or can be the local NAT64 prefix. 376 * 377 * @param[out] aPrefix A reference to output the favored prefix. 378 * @param[out] aPreference A reference to output the preference associated with the favored prefix. 379 * 380 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 381 * @retval kErrorNone Successfully retrieved the NAT64 prefix. 382 * 383 */ 384 Error GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreference &aRoutePreference); 385 386 /** 387 * Informs `RoutingManager` of the result of the discovery request of NAT64 prefix on infrastructure 388 * interface (`InfraIf::DiscoverNat64Prefix()`). 389 * 390 * @param[in] aPrefix The discovered NAT64 prefix on `InfraIf`. 391 * 392 */ HandleDiscoverNat64PrefixDone(const Ip6::Prefix & aPrefix)393 void HandleDiscoverNat64PrefixDone(const Ip6::Prefix &aPrefix) { mNat64PrefixManager.HandleDiscoverDone(aPrefix); } 394 395 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 396 397 /** 398 * Processes a received ICMPv6 message from the infrastructure interface. 399 * 400 * Malformed or undesired messages are dropped silently. 401 * 402 * @param[in] aPacket The received ICMPv6 packet. 403 * @param[in] aSrcAddress The source address this message is sent from. 404 * 405 */ 406 void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 407 408 /** 409 * Handles infrastructure interface state changes. 410 * 411 */ HandleInfraIfStateChanged(void)412 void HandleInfraIfStateChanged(void) { EvaluateState(); } 413 414 /** 415 * Checks whether the on-mesh prefix configuration is a valid OMR prefix. 416 * 417 * @param[in] aOnMeshPrefixConfig The on-mesh prefix configuration to check. 418 * 419 * @retval TRUE The prefix is a valid OMR prefix. 420 * @retval FALSE The prefix is not a valid OMR prefix. 421 * 422 */ 423 static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 424 425 /** 426 * Checks whether a given prefix is a valid OMR prefix. 427 * 428 * @param[in] aPrefix The prefix to check. 429 * 430 * @retval TRUE The prefix is a valid OMR prefix. 431 * @retval FALSE The prefix is not a valid OMR prefix. 432 * 433 */ 434 static bool IsValidOmrPrefix(const Ip6::Prefix &aPrefix); 435 436 /** 437 * Initializes a `PrefixTableIterator`. 438 * 439 * An iterator can be initialized again to start from the beginning of the table. 440 * 441 * When iterating over entries in the table, to ensure the entry update times are consistent, they are given 442 * relative to the time the iterator was initialized. 443 * 444 * @param[out] aIterator The iterator to initialize. 445 * 446 */ InitPrefixTableIterator(PrefixTableIterator & aIterator) const447 void InitPrefixTableIterator(PrefixTableIterator &aIterator) const 448 { 449 mDiscoveredPrefixTable.InitIterator(aIterator); 450 } 451 452 /** 453 * Iterates over entries in the discovered prefix table. 454 * 455 * @param[in,out] aIterator An iterator. 456 * @param[out] aEntry A reference to the entry to populate. 457 * 458 * @retval kErrorNone Got the next entry, @p aEntry is updated and @p aIterator is advanced. 459 * @retval kErrorNotFound No more entries in the table. 460 * 461 */ GetNextPrefixTableEntry(PrefixTableIterator & aIterator,PrefixTableEntry & aEntry) const462 Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const 463 { 464 return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry); 465 } 466 467 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 468 /** 469 * Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server. 470 * 471 * This should be called from `Srp::Server` when auto-enable mode is changed. 472 * 473 */ 474 void HandleSrpServerAutoEnableMode(void); 475 #endif 476 477 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 478 /** 479 * Handles a router advertisement message received on platform's Thread interface. 480 * 481 * Note: This method is a part of DHCPv6 PD support on Thread border routers. The message should be generated by the 482 * software like dnamasq, radvd, systemd-networkd on the platform as a part of the DHCPv6 prefix delegation process 483 * for distributing the prefix to the interfaces (links). 484 * 485 * @param[in] aRouterAdvert A pointer to the buffer of the router advertisement message. 486 * @param[in] aLength The length of the router advertisement message. 487 * 488 */ ProcessPlatfromGeneratedRa(const uint8_t * aRouterAdvert,uint16_t aLength)489 void ProcessPlatfromGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength) 490 { 491 mPdPrefixManager.ProcessPlatformGeneratedRa(aRouterAdvert, aLength); 492 } 493 494 /** 495 * Enables / Disables the functions for DHCPv6 PD. 496 * 497 * @param[in] aEnabled Whether to accept platform generated RA messages. 498 * 499 */ SetDhcp6PdEnabled(bool aEnabled)500 void SetDhcp6PdEnabled(bool aEnabled) { return mPdPrefixManager.SetEnabled(aEnabled); } 501 502 /** 503 * Returns the state of accpeting RouterAdvertisement messages on platform interface. 504 * 505 * @retval kDhcp6PdStateRunning DHCPv6 PD should be enabled and running on this border router. 506 * @retval kDhcp6PdStateDisabled DHCPv6 PD should be disabled on this border router.. 507 * 508 */ GetDhcp6PdState(void) const509 Dhcp6PdState GetDhcp6PdState(void) const { return mPdPrefixManager.GetState(); } 510 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 511 512 private: 513 static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES; 514 515 static constexpr uint8_t kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits. 516 static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits. 517 static constexpr uint8_t kBrUlaPrefixLength = 48; // The length of a BR ULA prefix. In bits. 518 static constexpr uint8_t kNat64PrefixLength = 96; // The length of a NAT64 prefix. In bits. 519 520 static constexpr uint16_t kOmrPrefixSubnetId = 1; // The subnet ID of an OMR prefix within a BR ULA prefix. 521 static constexpr uint16_t kNat64PrefixSubnetId = 2; // The subnet ID of a NAT64 prefix within a BR ULA prefix. 522 523 // The maximum number of initial Router Advertisements. 524 static constexpr uint32_t kMaxInitRtrAdvertisements = 3; 525 526 static constexpr uint32_t kDefaultOmrPrefixLifetime = 1800; // The default OMR prefix valid lifetime. In sec. 527 static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800; // The default on-link prefix valid lifetime. In sec. 528 static constexpr uint32_t kDefaultNat64PrefixLifetime = 300; // The default NAT64 prefix valid lifetime. In sec. 529 static constexpr uint32_t kMaxRtrAdvInterval = 600; // Max Router Advertisement Interval. In sec. 530 static constexpr uint32_t kMinRtrAdvInterval = kMaxRtrAdvInterval / 3; // Min RA Interval. In sec. 531 static constexpr uint32_t kMaxInitRtrAdvInterval = 16; // Max Initial RA Interval. In sec. 532 static constexpr uint32_t kRaReplyJitter = 500; // Jitter for sending RA after rx RS. In msec. 533 static constexpr uint32_t kPolicyEvaluationMinDelay = 2000; // Min delay for policy evaluation. In msec. 534 static constexpr uint32_t kPolicyEvaluationMaxDelay = 4000; // Max delay for policy evaluation. In msec. 535 static constexpr uint32_t kMinDelayBetweenRtrAdvs = 3000; // Min delay (msec) between consecutive RAs. 536 537 // The STALE_RA_TIME in seconds. The Routing Manager will consider the prefixes 538 // and learned RA parameters STALE when they are not refreshed in STALE_RA_TIME 539 // seconds. The Routing Manager will then start Router Solicitation to verify 540 // that the STALE prefix is not being advertised anymore and remove the STALE 541 // prefix. 542 // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`]. 543 static constexpr uint32_t kRtrAdvStaleTime = 1800; 544 545 static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals"); 546 static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime"); 547 static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime"); 548 static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime, 549 "invalid RA STALE time"); 550 static_assert(kPolicyEvaluationMaxDelay > kPolicyEvaluationMinDelay, 551 "kPolicyEvaluationMaxDelay must be larger than kPolicyEvaluationMinDelay"); 552 553 enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()` 554 { 555 kInvalidateAllPrevPrefixes, 556 kAdvPrefixesFromNetData, 557 }; 558 559 enum ScheduleMode : uint8_t // Used in `ScheduleRoutingPolicyEvaluation()` 560 { 561 kImmediately, 562 kForNextRa, 563 kAfterRandomDelay, 564 kToReplyToRs, 565 }; 566 567 void HandleDiscoveredPrefixTableChanged(void); // Declare early so we can use in `mSignalTask` HandleDiscoveredPrefixTableEntryTimer(void)568 void HandleDiscoveredPrefixTableEntryTimer(void) { mDiscoveredPrefixTable.HandleEntryTimer(); } HandleDiscoveredPrefixTableRouterTimer(void)569 void HandleDiscoveredPrefixTableRouterTimer(void) { mDiscoveredPrefixTable.HandleRouterTimer(); } 570 571 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 572 class PdPrefixManager; // For DiscoveredPrefixTable::Entry 573 #endif 574 575 class DiscoveredPrefixTable : public InstanceLocator 576 { 577 // This class maintains the discovered on-link and route prefixes 578 // from the received RA messages by processing PIO and RIO options 579 // from the message. It takes care of processing the RA message but 580 // delegates the decision whether to include or exclude a prefix to 581 // `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()` 582 // and `ShouldProcessRouteInfoOption()` methods. 583 // 584 // It manages the lifetime of the discovered entries and publishes 585 // and unpublishes the prefixes in the Network Data (as external 586 // route) as they are added or removed. 587 // 588 // When there is any change in the table (an entry is added, removed, 589 // or modified), it signals the change to `RoutingManager` by calling 590 // `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is 591 // used for signalling which ensures that if there are multiple 592 // changes within the same flow of execution, the callback is 593 // invoked after all the changes are processed. 594 595 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 596 friend class PdPrefixManager; // For DiscoveredPrefixTable::Entry 597 #endif 598 599 public: 600 explicit DiscoveredPrefixTable(Instance &aInstance); 601 602 void ProcessRouterAdvertMessage(const Ip6::Nd::RouterAdvertMessage &aRaMessage, 603 const Ip6::Address &aSrcAddress); 604 void ProcessNeighborAdvertMessage(const Ip6::Nd::NeighborAdvertMessage &aNaMessage); 605 606 bool ContainsDefaultOrNonUlaRoutePrefix(void) const; 607 bool ContainsNonUlaOnLinkPrefix(void) const; 608 bool ContainsUlaOnLinkPrefix(void) const; 609 610 void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const; 611 612 void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix); 613 void RemoveRoutePrefix(const Ip6::Prefix &aPrefix); 614 615 void RemoveAllEntries(void); 616 void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold); 617 618 TimeMilli CalculateNextStaleTime(TimeMilli aNow) const; 619 620 void InitIterator(PrefixTableIterator &aIterator) const; 621 Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const; 622 623 void HandleEntryTimer(void); 624 void HandleRouterTimer(void); 625 626 private: 627 static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS; 628 static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES; 629 630 class Entry : public LinkedListEntry<Entry>, public Unequatable<Entry>, private Clearable<Entry> 631 { 632 friend class LinkedListEntry<Entry>; 633 friend class Clearable<Entry>; 634 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 635 friend class PdPrefixManager; 636 #endif 637 638 public: 639 enum Type : uint8_t 640 { 641 kTypeOnLink, 642 kTypeRoute, 643 }; 644 645 struct Matcher 646 { Matcherot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::Matcher647 Matcher(const Ip6::Prefix &aPrefix, Type aType) 648 : mPrefix(aPrefix) 649 , mType(aType) 650 { 651 } 652 653 const Ip6::Prefix &mPrefix; 654 Type mType; 655 }; 656 657 struct Checker 658 { 659 enum Mode : uint8_t 660 { 661 kIsUla, 662 kIsNotUla, 663 }; 664 Checkerot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::Checker665 Checker(Mode aMode, Type aType) 666 : mMode(aMode) 667 , mType(aType) 668 669 { 670 } 671 672 Mode mMode; 673 Type mType; 674 }; 675 676 struct ExpirationChecker 677 { ExpirationCheckerot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::ExpirationChecker678 explicit ExpirationChecker(TimeMilli aNow) 679 : mNow(aNow) 680 { 681 } 682 683 TimeMilli mNow; 684 }; 685 686 void SetFrom(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader); 687 void SetFrom(const Ip6::Nd::PrefixInfoOption &aPio); 688 void SetFrom(const Ip6::Nd::RouteInfoOption &aRio); GetType(void) const689 Type GetType(void) const { return mType; } IsOnLinkPrefix(void) const690 bool IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); } IsRoutePrefix(void) const691 bool IsRoutePrefix(void) const { return (mType == kTypeRoute); } GetPrefix(void) const692 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetLastUpdateTime(void) const693 const TimeMilli &GetLastUpdateTime(void) const { return mLastUpdateTime; } GetValidLifetime(void) const694 uint32_t GetValidLifetime(void) const { return mValidLifetime; } ClearValidLifetime(void)695 void ClearValidLifetime(void) { mValidLifetime = 0; } 696 TimeMilli GetExpireTime(void) const; 697 TimeMilli GetStaleTime(void) const; 698 RoutePreference GetPreference(void) const; 699 bool operator==(const Entry &aOther) const; 700 bool Matches(const Matcher &aMatcher) const; 701 bool Matches(const Checker &aChecker) const; 702 bool Matches(const ExpirationChecker &aChecker) const; 703 704 // Methods to use when `IsOnLinkPrefix()` GetPreferredLifetime(void) const705 uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; } ClearPreferredLifetime(void)706 void ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; } 707 bool IsDeprecated(void) const; 708 void AdoptValidAndPreferredLifetimesFrom(const Entry &aEntry); 709 710 // Method to use when `!IsOnlinkPrefix()` GetRoutePreference(void) const711 RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; } 712 713 private: 714 static uint32_t CalculateExpireDelay(uint32_t aValidLifetime); 715 716 Entry *mNext; 717 Ip6::Prefix mPrefix; 718 Type mType; 719 TimeMilli mLastUpdateTime; 720 uint32_t mValidLifetime; 721 union 722 { 723 uint32_t mPreferredLifetime; // Applicable when prefix is on-link. 724 RoutePreference mRoutePreference; // Applicable when prefix is not on-link 725 } mShared; 726 }; 727 728 struct Router 729 { 730 // The timeout (in msec) for router staying in active state 731 // before starting the Neighbor Solicitation (NS) probes. 732 static constexpr uint32_t kActiveTimeout = OPENTHREAD_CONFIG_BORDER_ROUTING_ROUTER_ACTIVE_CHECK_TIMEOUT; 733 734 static constexpr uint8_t kMaxNsProbes = 5; // Max number of NS probe attempts. 735 static constexpr uint32_t kNsProbeRetryInterval = 1000; // In msec. Time between NS probe attempts. 736 static constexpr uint32_t kNsProbeTimeout = 2000; // In msec. Max Wait time after last NS probe. 737 static constexpr uint32_t kJitter = 2000; // In msec. Jitter to randomize probe starts. 738 739 static_assert(kMaxNsProbes < 255, "kMaxNsProbes MUST not be 255"); 740 741 enum EmptyChecker : uint8_t 742 { 743 kContainsNoEntries 744 }; 745 Matchesot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Router746 bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; } Matchesot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Router747 bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); } 748 749 Ip6::Address mAddress; 750 LinkedList<Entry> mEntries; 751 TimeMilli mTimeout; 752 uint8_t mNsProbeCount; 753 }; 754 755 class Iterator : public PrefixTableIterator 756 { 757 public: GetRouter(void) const758 const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); } SetRouter(const Router * aRouter)759 void SetRouter(const Router *aRouter) { mPtr1 = aRouter; } GetEntry(void) const760 const Entry *GetEntry(void) const { return static_cast<const Entry *>(mPtr2); } SetEntry(const Entry * aEntry)761 void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; } GetInitTime(void) const762 TimeMilli GetInitTime(void) const { return TimeMilli(mData32); } SetInitTime(void)763 void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); } 764 }; 765 766 void ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter); 767 void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter); 768 void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter); 769 bool Contains(const Entry::Checker &aChecker) const; 770 void RemovePrefix(const Entry::Matcher &aMatcher); 771 void RemoveOrDeprecateEntriesFromInactiveRouters(void); 772 void RemoveRoutersWithNoEntries(void); AllocateEntry(void)773 Entry *AllocateEntry(void) { return mEntryPool.Allocate(); } FreeEntry(Entry & aEntry)774 void FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); } 775 void FreeEntries(LinkedList<Entry> &aEntries); 776 void UpdateNetworkDataOnChangeTo(Entry &aEntry); 777 const Entry *FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix) const; 778 void RemoveExpiredEntries(void); 779 void SignalTableChanged(void); 780 void UpdateRouterOnRx(Router &aRouter); 781 void SendNeighborSolicitToRouter(const Router &aRouter); 782 783 using SignalTask = TaskletIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableChanged>; 784 using EntryTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableEntryTimer>; 785 using RouterTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableRouterTimer>; 786 787 Array<Router, kMaxRouters> mRouters; 788 Pool<Entry, kMaxEntries> mEntryPool; 789 EntryTimer mEntryTimer; 790 RouterTimer mRouterTimer; 791 SignalTask mSignalTask; 792 }; 793 794 class OmrPrefixManager; 795 796 class OmrPrefix : public Clearable<OmrPrefix> 797 { 798 friend class OmrPrefixManager; 799 800 public: OmrPrefix(void)801 OmrPrefix(void) { Clear(); } 802 IsEmpty(void) const803 bool IsEmpty(void) const { return (mPrefix.GetLength() == 0); } GetPrefix(void) const804 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetPreference(void) const805 RoutePreference GetPreference(void) const { return mPreference; } IsDomainPrefix(void) const806 bool IsDomainPrefix(void) const { return mIsDomainPrefix; } 807 808 protected: 809 Ip6::Prefix mPrefix; 810 RoutePreference mPreference; 811 bool mIsDomainPrefix; 812 }; 813 814 class FavoredOmrPrefix : public OmrPrefix 815 { 816 friend class OmrPrefixManager; 817 818 public: 819 bool IsInfrastructureDerived(void) const; 820 821 private: 822 void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 823 void SetFrom(const OmrPrefix &aOmrPrefix); 824 bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const; 825 }; 826 827 class OmrPrefixManager : public InstanceLocator 828 { 829 public: 830 explicit OmrPrefixManager(Instance &aInstance); 831 832 void Init(const Ip6::Prefix &aBrUlaPrefix); 833 void Start(void); 834 void Stop(void); 835 void Evaluate(void); 836 void UpdateDefaultRouteFlag(bool aDefaultRoute); IsLocalAddedInNetData(void) const837 bool IsLocalAddedInNetData(void) const { return mIsLocalAddedInNetData; } GetGeneratedPrefix(void) const838 const Ip6::Prefix &GetGeneratedPrefix(void) const { return mGeneratedPrefix; } GetLocalPrefix(void) const839 const OmrPrefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredPrefix(void) const840 const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; } 841 842 private: 843 static constexpr uint16_t kInfoStringSize = 85; 844 845 typedef String<kInfoStringSize> InfoString; 846 847 void DetermineFavoredPrefix(void); 848 Error AddLocalToNetData(void); 849 Error AddOrUpdateLocalInNetData(void); 850 void RemoveLocalFromNetData(void); 851 InfoString LocalToString(void) const; 852 853 OmrPrefix mLocalPrefix; 854 Ip6::Prefix mGeneratedPrefix; 855 FavoredOmrPrefix mFavoredPrefix; 856 bool mIsLocalAddedInNetData; 857 bool mDefaultRoute; 858 }; 859 HandleOnLinkPrefixManagerTimer(void)860 void HandleOnLinkPrefixManagerTimer(void) { mOnLinkPrefixManager.HandleTimer(); } 861 862 class OnLinkPrefixManager : public InstanceLocator 863 { 864 public: 865 explicit OnLinkPrefixManager(Instance &aInstance); 866 867 // Max number of old on-link prefixes to retain to deprecate. 868 static constexpr uint16_t kMaxOldPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES; 869 870 void Init(void); 871 void Start(void); 872 void Stop(void); 873 void Evaluate(void); GetLocalPrefix(void) const874 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredDiscoveredPrefix(void) const875 const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; } 876 bool IsInitalEvaluationDone(void) const; 877 void HandleDiscoveredPrefixTableChanged(void); 878 bool ShouldPublishUlaRoute(void) const; 879 void AppendAsPiosTo(Ip6::Nd::RouterAdvertMessage &aRaMessage); 880 bool IsPublishingOrAdvertising(void) const; 881 void HandleNetDataChange(void); 882 void HandleExtPanIdChange(void); 883 void HandleTimer(void); 884 885 private: 886 enum State : uint8_t // State of `mLocalPrefix` 887 { 888 kIdle, 889 kPublishing, 890 kAdvertising, 891 kDeprecating, 892 }; 893 894 struct OldPrefix 895 { Matchesot::BorderRouter::RoutingManager::OnLinkPrefixManager::OldPrefix896 bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; } 897 898 Ip6::Prefix mPrefix; 899 TimeMilli mExpireTime; 900 }; 901 GetState(void) const902 State GetState(void) const { return mState; } 903 void SetState(State aState); 904 void GenerateLocalPrefix(void); 905 void PublishAndAdvertise(void); 906 void Deprecate(void); 907 void ResetExpireTime(TimeMilli aNow); 908 void AppendCurPrefix(Ip6::Nd::RouterAdvertMessage &aRaMessage); 909 void AppendOldPrefixes(Ip6::Nd::RouterAdvertMessage &aRaMessage); 910 void DeprecateOldPrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 911 void SavePrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 912 913 static const char *StateToString(State aState); 914 915 using ExpireTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleOnLinkPrefixManagerTimer>; 916 917 Ip6::Prefix mLocalPrefix; 918 State mState; 919 TimeMilli mExpireTime; 920 Ip6::Prefix mFavoredDiscoveredPrefix; 921 Array<OldPrefix, kMaxOldPrefixes> mOldLocalPrefixes; 922 ExpireTimer mTimer; 923 }; 924 925 typedef Ip6::Prefix OnMeshPrefix; 926 927 class OnMeshPrefixArray : public Array<OnMeshPrefix, kMaxOnMeshPrefixes> 928 { 929 public: 930 void Add(const OnMeshPrefix &aPrefix); 931 void MarkAsDeleted(const OnMeshPrefix &aPrefix); 932 }; 933 934 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE HandleNat64PrefixManagerTimer(void)935 void HandleNat64PrefixManagerTimer(void) { mNat64PrefixManager.HandleTimer(); } 936 937 class Nat64PrefixManager : public InstanceLocator 938 { 939 public: 940 // This class manages the NAT64 related functions including 941 // generation of local NAT64 prefix, discovery of infra 942 // interface prefix, maintaining the discovered prefix 943 // lifetime, and selection of the NAT64 prefix to publish in 944 // Network Data. 945 // 946 // Calling methods except GenerateLocalPrefix and SetEnabled 947 // when disabled becomes no-op. 948 949 explicit Nat64PrefixManager(Instance &aInstance); 950 951 void SetEnabled(bool aEnabled); 952 Nat64::State GetState(void) const; 953 954 void Start(void); 955 void Stop(void); 956 957 void GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix); GetLocalPrefix(void) const958 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } 959 const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const; 960 void Evaluate(void); 961 void HandleDiscoverDone(const Ip6::Prefix &aPrefix); 962 void HandleTimer(void); 963 964 private: 965 void Discover(void); 966 void Publish(void); 967 968 using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>; 969 970 bool mEnabled; 971 972 Ip6::Prefix mInfraIfPrefix; // The latest NAT64 prefix discovered on the infrastructure interface. 973 Ip6::Prefix mLocalPrefix; // The local prefix (from BR ULA prefix). 974 Ip6::Prefix mPublishedPrefix; // The prefix to publish in Net Data (empty or local or from infra-if). 975 RoutePreference mPublishedPreference; // The published prefix preference. 976 Nat64Timer mTimer; 977 }; 978 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 979 HandleRoutePublisherTimer(void)980 void HandleRoutePublisherTimer(void) { mRoutePublisher.HandleTimer(); } 981 982 class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data 983 { 984 public: 985 explicit RoutePublisher(Instance &aInstance); 986 Start(void)987 void Start(void) { Evaluate(); } Stop(void)988 void Stop(void) { Unpublish(); } 989 void Evaluate(void); 990 991 void UpdateAdvPioFlags(bool aAdvPioFlag); 992 GetPreference(void) const993 RoutePreference GetPreference(void) const { return mPreference; } 994 void SetPreference(RoutePreference aPreference); 995 void ClearPreference(void); 996 997 void HandleNotifierEvents(Events aEvents); 998 void HandleTimer(void); 999 GetUlaPrefix(void)1000 static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); } 1001 1002 private: 1003 static constexpr uint32_t kDelayBeforePrfUpdateOnLinkQuality3 = TimeMilli::SecToMsec(5 * 60); 1004 1005 static const otIp6Prefix kUlaPrefix; 1006 1007 enum State : uint8_t 1008 { 1009 kDoNotPublish, // Do not publish any routes in network data. 1010 kPublishDefault, // Publish "::/0" route in network data. 1011 kPublishUla, // Publish "fc00::/7" route in network data. 1012 }; 1013 1014 void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const; 1015 void UpdatePublishedRoute(State aNewState); 1016 void Unpublish(void); 1017 void SetPreferenceBasedOnRole(void); 1018 void UpdatePreference(RoutePreference aPreference); 1019 1020 static const char *StateToString(State aState); 1021 1022 using DelayTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRoutePublisherTimer>; 1023 1024 State mState; 1025 RoutePreference mPreference; 1026 bool mUserSetPreference; 1027 bool mAdvPioFlag; 1028 DelayTimer mTimer; 1029 }; 1030 1031 struct RaInfo 1032 { 1033 // Tracks info about emitted RA messages: Number of RAs sent, 1034 // last tx time, header to use and whether the header is 1035 // discovered from receiving RAs from the host itself. This 1036 // ensures that if an entity on host is advertising certain 1037 // info in its RA header (e.g., a default route), the RAs we 1038 // emit from `RoutingManager` also include the same header. 1039 RaInfoot::BorderRouter::RoutingManager::RaInfo1040 RaInfo(void) 1041 : mHeaderUpdateTime(TimerMilli::GetNow()) 1042 , mIsHeaderFromHost(false) 1043 , mTxCount(0) 1044 , mLastTxTime(TimerMilli::GetNow() - kMinDelayBetweenRtrAdvs) 1045 { 1046 } 1047 1048 Ip6::Nd::RouterAdvertMessage::Header mHeader; 1049 TimeMilli mHeaderUpdateTime; 1050 bool mIsHeaderFromHost; 1051 uint32_t mTxCount; 1052 TimeMilli mLastTxTime; 1053 }; 1054 HandleRsSenderTimer(void)1055 void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); } 1056 1057 class RsSender : public InstanceLocator 1058 { 1059 public: 1060 // This class implements tx of Router Solicitation (RS) 1061 // messages to discover other routers. `Start()` schedules 1062 // a cycle of RS transmissions of `kMaxTxCount` separated 1063 // by `kTxInterval`. At the end of cycle the callback 1064 // `HandleRsSenderFinished()` is invoked to inform end of 1065 // the cycle to `RoutingManager`. 1066 1067 explicit RsSender(Instance &aInstance); 1068 IsInProgress(void) const1069 bool IsInProgress(void) const { return mTimer.IsRunning(); } 1070 void Start(void); 1071 void Stop(void); 1072 void HandleTimer(void); 1073 1074 private: 1075 // All time intervals are in msec. 1076 static constexpr uint32_t kMaxStartDelay = 1000; // Max random delay to send the first RS. 1077 static constexpr uint32_t kTxInterval = 4000; // Interval between RS tx. 1078 static constexpr uint32_t kRetryDelay = kTxInterval; // Interval to wait to retry a failed RS tx. 1079 static constexpr uint32_t kWaitOnLastAttempt = 1000; // Wait interval after last RS tx. 1080 static constexpr uint8_t kMaxTxCount = 3; // Number of RS tx in one cycle. 1081 1082 Error SendRs(void); 1083 1084 using RsTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRsSenderTimer>; 1085 1086 uint8_t mTxCount; 1087 RsTimer mTimer; 1088 TimeMilli mStartTime; 1089 }; 1090 1091 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE HandlePdPrefixManagerTimer(void)1092 void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); } 1093 1094 class PdPrefixManager : public InstanceLocator 1095 { 1096 public: 1097 // This class implements handling (including management of the lifetime) of the prefix obtained from platform's 1098 // DHCPv6 PD client. We expect the platform will send ICMP6 RA messages to the platform's interface for the 1099 // information of the prefix. 1100 // This class manages the state of the PD prefix in OmrPrefixManager 1101 1102 explicit PdPrefixManager(Instance &aInstance); 1103 1104 void SetEnabled(bool aEnabled); IsRunning(void) const1105 bool IsRunning(void) const { return GetState() == Dhcp6PdState::kDhcp6PdStateRunning; } HasPrefix(void) const1106 bool HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); } GetPrefix(void) const1107 const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); } GetState(void) const1108 Dhcp6PdState GetState(void) const 1109 { 1110 // TODO: We need to stop and inform the platform when there is already a GUA prefix advertised in the 1111 // network. 1112 return mEnabled ? kDhcp6PdStateRunning : kDhcp6PdStateDisabled; 1113 } 1114 1115 void ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength); 1116 Error GetPrefixInfo(PrefixTableEntry &aInfo) const; HandleTimer(void)1117 void HandleTimer(void) { WithdrawPrefix(); } 1118 IsValidPdPrefix(const Ip6::Prefix & aPrefix)1119 static bool IsValidPdPrefix(const Ip6::Prefix &aPrefix) 1120 { 1121 // We should accept ULA prefix since it could be used by the internet infrastructure like NAT64. 1122 return aPrefix.GetLength() != 0 && aPrefix.GetLength() <= kOmrPrefixLength && !aPrefix.IsLinkLocal() && 1123 !aPrefix.IsMulticast(); 1124 } 1125 1126 private: 1127 Error Process(const Ip6::Nd::RouterAdvertMessage &aMessage); 1128 void WithdrawPrefix(void); 1129 1130 using PlatformOmrPrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>; 1131 1132 bool mEnabled; 1133 PlatformOmrPrefixTimer mTimer; 1134 DiscoveredPrefixTable::Entry mPrefix; 1135 }; 1136 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1137 1138 void EvaluateState(void); 1139 void Start(void); 1140 void Stop(void); 1141 void HandleNotifierEvents(Events aEvents); IsInitialized(void) const1142 bool IsInitialized(void) const { return mInfraIf.IsInitialized(); } IsEnabled(void) const1143 bool IsEnabled(void) const { return mIsEnabled; } 1144 void SetRioPreferenceBasedOnRole(void); 1145 void UpdateRioPreference(RoutePreference aPreference); 1146 Error LoadOrGenerateRandomBrUlaPrefix(void); 1147 1148 void EvaluateRoutingPolicy(void); 1149 bool IsInitalPolicyEvaluationDone(void) const; 1150 void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode); 1151 void HandleRsSenderFinished(TimeMilli aStartTime); 1152 void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode); 1153 1154 void HandleDiscoveredPrefixStaleTimer(void); 1155 1156 void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1157 void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1158 void HandleNeighborAdvertisement(const InfraIf::Icmp6Packet &aPacket); 1159 bool ShouldProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix); 1160 bool ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix); 1161 void UpdateDiscoveredPrefixTableOnNetDataChange(void); 1162 bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const; 1163 bool NetworkDataContainsUlaRoute(void) const; 1164 void UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage); 1165 bool IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdvertMessage &aRaMessage) const; 1166 void ResetDiscoveredPrefixStaleTimer(void); 1167 1168 static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix); 1169 static bool IsValidOnLinkPrefix(const Ip6::Nd::PrefixInfoOption &aPio); 1170 static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); 1171 1172 static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime); 1173 static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference); 1174 1175 using RoutingPolicyTimer = TimerMilliIn<RoutingManager, &RoutingManager::EvaluateRoutingPolicy>; 1176 using DiscoveredPrefixStaleTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixStaleTimer>; 1177 1178 // Indicates whether the Routing Manager is running (started). 1179 bool mIsRunning; 1180 1181 // Indicates whether the Routing manager is enabled. The Routing 1182 // Manager will be stopped if we are disabled. 1183 bool mIsEnabled; 1184 1185 InfraIf mInfraIf; 1186 1187 // The /48 BR ULA prefix loaded from local persistent storage or 1188 // randomly generated if none is found in persistent storage. 1189 Ip6::Prefix mBrUlaPrefix; 1190 1191 OmrPrefixManager mOmrPrefixManager; 1192 1193 // List of on-mesh prefixes (discovered from Network Data) which 1194 // were advertised as RIO in the last sent RA message. 1195 OnMeshPrefixArray mAdvertisedPrefixes; 1196 1197 RoutePreference mRioPreference; 1198 bool mUserSetRioPreference; 1199 1200 OnLinkPrefixManager mOnLinkPrefixManager; 1201 1202 DiscoveredPrefixTable mDiscoveredPrefixTable; 1203 1204 RoutePublisher mRoutePublisher; 1205 1206 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1207 Nat64PrefixManager mNat64PrefixManager; 1208 #endif 1209 1210 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1211 PdPrefixManager mPdPrefixManager; 1212 #endif 1213 1214 RaInfo mRaInfo; 1215 RsSender mRsSender; 1216 1217 DiscoveredPrefixStaleTimer mDiscoveredPrefixStaleTimer; 1218 RoutingPolicyTimer mRoutingPolicyTimer; 1219 }; 1220 1221 } // namespace BorderRouter 1222 1223 DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State); 1224 1225 } // namespace ot 1226 1227 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1228 1229 #endif // ROUTING_MANAGER_HPP_ 1230