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