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