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