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 1098 { 1099 friend class OmrPrefixManager; 1100 1101 public: 1102 bool IsInfrastructureDerived(void) const; 1103 1104 private: 1105 void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 1106 void SetFrom(const OmrPrefix &aOmrPrefix); 1107 bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const; 1108 }; 1109 1110 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1111 1112 class OmrPrefixManager : public InstanceLocator 1113 { 1114 public: 1115 explicit OmrPrefixManager(Instance &aInstance); 1116 1117 void Init(const Ip6::Prefix &aBrUlaPrefix); 1118 void Start(void); 1119 void Stop(void); 1120 void Evaluate(void); 1121 void UpdateDefaultRouteFlag(bool aDefaultRoute); 1122 bool ShouldAdvertiseLocalAsRio(void) const; GetGeneratedPrefix(void) const1123 const Ip6::Prefix &GetGeneratedPrefix(void) const { return mGeneratedPrefix; } GetLocalPrefix(void) const1124 const OmrPrefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredPrefix(void) const1125 const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; } 1126 1127 private: 1128 static constexpr uint16_t kInfoStringSize = 85; 1129 1130 typedef String<kInfoStringSize> InfoString; 1131 1132 void DetermineFavoredPrefix(void); 1133 Error AddLocalToNetData(void); 1134 Error AddOrUpdateLocalInNetData(void); 1135 void RemoveLocalFromNetData(void); 1136 InfoString LocalToString(void) const; 1137 1138 OmrPrefix mLocalPrefix; 1139 Ip6::Prefix mGeneratedPrefix; 1140 FavoredOmrPrefix mFavoredPrefix; 1141 bool mIsLocalAddedInNetData; 1142 bool mDefaultRoute; 1143 }; 1144 1145 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1146 HandleOnLinkPrefixManagerTimer(void)1147 void HandleOnLinkPrefixManagerTimer(void) { mOnLinkPrefixManager.HandleTimer(); } 1148 1149 class OnLinkPrefixManager : public InstanceLocator 1150 { 1151 public: 1152 explicit OnLinkPrefixManager(Instance &aInstance); 1153 1154 // Max number of old on-link prefixes to retain to deprecate. 1155 static constexpr uint16_t kMaxOldPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES; 1156 1157 void Init(void); 1158 void Start(void); 1159 void Stop(void); 1160 void Evaluate(void); GetLocalPrefix(void) const1161 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } GetFavoredDiscoveredPrefix(void) const1162 const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; } 1163 bool AddressMatchesLocalPrefix(const Ip6::Address &aAddress) const; 1164 bool IsInitalEvaluationDone(void) const; 1165 void HandleRaPrefixTableChanged(void); 1166 bool ShouldPublishUlaRoute(void) const; 1167 Error AppendAsPiosTo(RouterAdvert::TxMessage &aRaMessage); 1168 void HandleNetDataChange(void); 1169 void HandleExtPanIdChange(void); 1170 void HandleTimer(void); 1171 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE SetLocalPrefix(const Ip6::Prefix & aPrefix)1172 void SetLocalPrefix(const Ip6::Prefix &aPrefix) { mLocalPrefix = aPrefix; } 1173 #endif 1174 1175 private: 1176 enum State : uint8_t // State of `mLocalPrefix` 1177 { 1178 kIdle, 1179 kPublishing, 1180 kAdvertising, 1181 kDeprecating, 1182 }; 1183 1184 struct OldPrefix 1185 { Matchesot::BorderRouter::RoutingManager::OnLinkPrefixManager::OldPrefix1186 bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; } 1187 1188 Ip6::Prefix mPrefix; 1189 TimeMilli mExpireTime; 1190 }; 1191 GetState(void) const1192 State GetState(void) const { return mState; } 1193 void SetState(State aState); 1194 bool IsPublishingOrAdvertising(void) const; 1195 void GenerateLocalPrefix(void); 1196 void PublishAndAdvertise(void); 1197 void Deprecate(void); 1198 void ResetExpireTime(TimeMilli aNow); 1199 Error AppendCurPrefix(RouterAdvert::TxMessage &aRaMessage); 1200 Error AppendOldPrefixes(RouterAdvert::TxMessage &aRaMessage); 1201 void DeprecateOldPrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 1202 void SavePrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime); 1203 1204 static const char *StateToString(State aState); 1205 1206 using ExpireTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleOnLinkPrefixManagerTimer>; 1207 1208 Ip6::Prefix mLocalPrefix; 1209 State mState; 1210 TimeMilli mExpireTime; 1211 Ip6::Prefix mFavoredDiscoveredPrefix; 1212 Array<OldPrefix, kMaxOldPrefixes> mOldLocalPrefixes; 1213 ExpireTimer mTimer; 1214 }; 1215 1216 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1217 HandleRioAdvertiserimer(void)1218 void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); } 1219 1220 class RioAdvertiser : public InstanceLocator 1221 { 1222 // Manages the list of prefixes advertised as RIO in emitted 1223 // RA. The RIO prefixes are discovered from on-mesh prefixes in 1224 // network data including OMR prefix from `OmrPrefixManager`. 1225 // It also handles deprecating removed prefixes. 1226 1227 public: 1228 explicit RioAdvertiser(Instance &aInstance); 1229 GetPreference(void) const1230 RoutePreference GetPreference(void) const { return mPreference; } 1231 void SetPreference(RoutePreference aPreference); 1232 void ClearPreference(void); 1233 void HandleRoleChanged(void); 1234 Error AppendRios(RouterAdvert::TxMessage &aRaMessage); 1235 Error InvalidatPrevRios(RouterAdvert::TxMessage &aRaMessage); HasAdvertised(const Ip6::Prefix & aPrefix) const1236 bool HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); } GetAdvertisedRioCount(void) const1237 uint16_t GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); } 1238 void HandleTimer(void); 1239 1240 private: 1241 static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300); 1242 1243 struct RioPrefix : public Clearable<RioPrefix> 1244 { Matchesot::BorderRouter::RoutingManager::RioAdvertiser::RioPrefix1245 bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); } 1246 1247 Ip6::Prefix mPrefix; 1248 bool mIsDeprecating; 1249 TimeMilli mExpirationTime; 1250 }; 1251 1252 struct RioPrefixArray : 1253 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1254 public Heap::Array<RioPrefix> 1255 #else 1256 public Array<RioPrefix, 2 * kMaxOnMeshPrefixes> 1257 #endif 1258 { 1259 void Add(const Ip6::Prefix &aPrefix); 1260 }; 1261 1262 void SetPreferenceBasedOnRole(void); 1263 void UpdatePreference(RoutePreference aPreference); 1264 Error AppendRio(const Ip6::Prefix &aPrefix, 1265 uint32_t aRouteLifetime, 1266 RoutePreference aPreference, 1267 RouterAdvert::TxMessage &aRaMessage); 1268 1269 using RioTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRioAdvertiserimer>; 1270 1271 RioPrefixArray mPrefixes; 1272 RioTimer mTimer; 1273 RoutePreference mPreference; 1274 bool mUserSetPreference; 1275 }; 1276 1277 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1278 1279 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1280 HandleNat64PrefixManagerTimer(void)1281 void HandleNat64PrefixManagerTimer(void) { mNat64PrefixManager.HandleTimer(); } 1282 1283 class Nat64PrefixManager : public InstanceLocator 1284 { 1285 public: 1286 // This class manages the NAT64 related functions including 1287 // generation of local NAT64 prefix, discovery of infra 1288 // interface prefix, maintaining the discovered prefix 1289 // lifetime, and selection of the NAT64 prefix to publish in 1290 // Network Data. 1291 // 1292 // Calling methods except GenerateLocalPrefix and SetEnabled 1293 // when disabled becomes no-op. 1294 1295 explicit Nat64PrefixManager(Instance &aInstance); 1296 1297 void SetEnabled(bool aEnabled); 1298 Nat64::State GetState(void) const; 1299 1300 void Start(void); 1301 void Stop(void); 1302 1303 void GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix); GetLocalPrefix(void) const1304 const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } 1305 const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const; 1306 void Evaluate(void); 1307 void HandleDiscoverDone(const Ip6::Prefix &aPrefix); 1308 void HandleTimer(void); 1309 1310 private: 1311 void Discover(void); 1312 void Publish(void); 1313 1314 using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>; 1315 1316 bool mEnabled; 1317 1318 Ip6::Prefix mInfraIfPrefix; // The latest NAT64 prefix discovered on the infrastructure interface. 1319 Ip6::Prefix mLocalPrefix; // The local prefix (from BR ULA prefix). 1320 Ip6::Prefix mPublishedPrefix; // The prefix to publish in Net Data (empty or local or from infra-if). 1321 RoutePreference mPublishedPreference; // The published prefix preference. 1322 Nat64Timer mTimer; 1323 }; 1324 1325 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1326 1327 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1328 HandleRoutePublisherTimer(void)1329 void HandleRoutePublisherTimer(void) { mRoutePublisher.HandleTimer(); } 1330 1331 class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data 1332 { 1333 public: 1334 explicit RoutePublisher(Instance &aInstance); 1335 Start(void)1336 void Start(void) { Evaluate(); } Stop(void)1337 void Stop(void) { Unpublish(); } 1338 void Evaluate(void); 1339 1340 void UpdateAdvPioFlags(bool aAdvPioFlag); 1341 GetPreference(void) const1342 RoutePreference GetPreference(void) const { return mPreference; } 1343 void SetPreference(RoutePreference aPreference); 1344 void ClearPreference(void); 1345 1346 void HandleNotifierEvents(Events aEvents); 1347 void HandleTimer(void); 1348 GetUlaPrefix(void)1349 static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); } 1350 1351 private: 1352 static constexpr uint32_t kDelayBeforePrfUpdateOnLinkQuality3 = TimeMilli::SecToMsec(5 * 60); 1353 1354 static const otIp6Prefix kUlaPrefix; 1355 1356 enum State : uint8_t 1357 { 1358 kDoNotPublish, // Do not publish any routes in network data. 1359 kPublishDefault, // Publish "::/0" route in network data. 1360 kPublishUla, // Publish "fc00::/7" route in network data. 1361 }; 1362 1363 void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const; 1364 void UpdatePublishedRoute(State aNewState); 1365 void Unpublish(void); 1366 void SetPreferenceBasedOnRole(void); 1367 void UpdatePreference(RoutePreference aPreference); 1368 1369 static const char *StateToString(State aState); 1370 1371 using DelayTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRoutePublisherTimer>; 1372 1373 State mState; 1374 RoutePreference mPreference; 1375 bool mUserSetPreference; 1376 bool mAdvPioFlag; 1377 DelayTimer mTimer; 1378 }; 1379 1380 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1381 1382 struct TxRaInfo 1383 { 1384 // Tracks info about emitted RA messages: 1385 // 1386 // - Number of RAs sent 1387 // - Last RA TX time 1388 // - Hashes of last TX RAs (to tell if a received RA is from 1389 // `RoutingManager` itself). 1390 1391 typedef Crypto::Sha256::Hash Hash; 1392 1393 static constexpr uint16_t kNumHashEntries = 5; 1394 TxRaInfoot::BorderRouter::RoutingManager::TxRaInfo1395 TxRaInfo(void) 1396 : mTxCount(0) 1397 , mLastTxTime(TimerMilli::GetNow() - kMinDelayBetweenRas) 1398 , mLastHashIndex(0) 1399 { 1400 } 1401 1402 void IncrementTxCountAndSaveHash(const InfraIf::Icmp6Packet &aRaMessage); 1403 bool IsRaFromManager(const RouterAdvert::RxMessage &aRaMessage) const; 1404 static void CalculateHash(const RouterAdvert::RxMessage &aRaMessage, Hash &aHash); 1405 1406 uint32_t mTxCount; 1407 TimeMilli mLastTxTime; 1408 Hash mHashes[kNumHashEntries]; 1409 uint16_t mLastHashIndex; 1410 }; 1411 1412 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1413 HandleRsSenderTimer(void)1414 void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); } 1415 1416 class RsSender : public InstanceLocator 1417 { 1418 public: 1419 // This class implements tx of Router Solicitation (RS) 1420 // messages to discover other routers. `Start()` schedules 1421 // a cycle of RS transmissions of `kMaxTxCount` separated 1422 // by `kTxInterval`. At the end of cycle the callback 1423 // `HandleRsSenderFinished()` is invoked to inform end of 1424 // the cycle to `RoutingManager`. 1425 1426 explicit RsSender(Instance &aInstance); 1427 IsInProgress(void) const1428 bool IsInProgress(void) const { return mTimer.IsRunning(); } 1429 void Start(void); 1430 void Stop(void); 1431 void HandleTimer(void); 1432 1433 private: 1434 // All time intervals are in msec. 1435 static constexpr uint32_t kMaxStartDelay = 1000; // Max random delay to send the first RS. 1436 static constexpr uint32_t kTxInterval = 4000; // Interval between RS tx. 1437 static constexpr uint32_t kRetryDelay = kTxInterval; // Interval to wait to retry a failed RS tx. 1438 static constexpr uint32_t kWaitOnLastAttempt = 1000; // Wait interval after last RS tx. 1439 static constexpr uint8_t kMaxTxCount = 3; // Number of RS tx in one cycle. 1440 1441 Error SendRs(void); 1442 1443 using RsTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRsSenderTimer>; 1444 1445 uint8_t mTxCount; 1446 RsTimer mTimer; 1447 TimeMilli mStartTime; 1448 }; 1449 1450 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1451 1452 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1453 HandlePdPrefixManagerTimer(void)1454 void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); } 1455 1456 class PdPrefixManager : public InstanceLocator 1457 { 1458 public: 1459 // This class implements handling (including management of the 1460 // lifetime) of the prefix obtained from platform's DHCPv6 PD 1461 // client. 1462 1463 typedef Dhcp6PdState State; 1464 1465 static constexpr RoutePreference kPdRoutePreference = RoutePreference::kRoutePreferenceMedium; 1466 1467 explicit PdPrefixManager(Instance &aInstance); 1468 1469 void SetEnabled(bool aEnabled); Start(void)1470 void Start(void) { StartStop(/* aStart= */ true); } Stop(void)1471 void Stop(void) { StartStop(/* aStart= */ false); } IsRunning(void) const1472 bool IsRunning(void) const { return GetState() == kDhcp6PdStateRunning; } HasPrefix(void) const1473 bool HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); } GetPrefix(void) const1474 const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); } 1475 State GetState(void) const; 1476 1477 void ProcessRa(const uint8_t *aRouterAdvert, uint16_t aLength); 1478 void ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry); 1479 Error GetPrefixInfo(PrefixTableEntry &aInfo) const; 1480 Error GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const; HandleTimer(void)1481 void HandleTimer(void) { WithdrawPrefix(); } SetStateCallback(PdCallback aCallback,void * aContext)1482 void SetStateCallback(PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); } 1483 void Evaluate(void); 1484 1485 private: 1486 class PrefixEntry : public OnLinkPrefix 1487 { 1488 public: PrefixEntry(void)1489 PrefixEntry(void) { Clear(); } IsEmpty(void) const1490 bool IsEmpty(void) const { return (GetPrefix().GetLength() == 0); } 1491 bool IsValidPdPrefix(void) const; 1492 bool IsFavoredOver(const PrefixEntry &aOther) const; 1493 }; 1494 1495 void Process(const InfraIf::Icmp6Packet *aRaPacket, const PrefixTableEntry *aPrefixTableEntry); 1496 bool ProcessPrefixEntry(PrefixEntry &aEntry, PrefixEntry &aFavoredEntry); 1497 void EvaluateStateChange(State aOldState); 1498 void WithdrawPrefix(void); 1499 void StartStop(bool aStart); 1500 void PauseResume(bool aPause); 1501 1502 static const char *StateToString(State aState); 1503 1504 using PrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>; 1505 using StateCallback = Callback<PdCallback>; 1506 1507 bool mEnabled; // Whether PdPrefixManager is enabled. (guards the overall PdPrefixManager functions) 1508 bool mIsStarted; // Whether PdPrefixManager is started. (monitoring prefixes) 1509 bool mIsPaused; // Whether PdPrefixManager is paused. (when there is another BR advertising another prefix) 1510 1511 uint32_t mNumPlatformPioProcessed; 1512 uint32_t mNumPlatformRaReceived; 1513 TimeMilli mLastPlatformRaTime; 1514 StateCallback mStateCallback; 1515 PrefixTimer mTimer; 1516 PrefixEntry mPrefix; 1517 }; 1518 1519 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1520 1521 //------------------------------------------------------------------------------------------------------------------ 1522 // Methods 1523 1524 void EvaluateState(void); 1525 void Start(void); 1526 void Stop(void); 1527 void HandleNotifierEvents(Events aEvents); IsInitialized(void) const1528 bool IsInitialized(void) const { return mInfraIf.IsInitialized(); } IsEnabled(void) const1529 bool IsEnabled(void) const { return mIsEnabled; } 1530 Error LoadOrGenerateRandomBrUlaPrefix(void); 1531 1532 void EvaluateRoutingPolicy(void); 1533 bool IsInitialPolicyEvaluationDone(void) const; 1534 void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode); 1535 void HandleRsSenderFinished(TimeMilli aStartTime); 1536 void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode); 1537 1538 void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1539 void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 1540 void HandleNeighborAdvertisement(const InfraIf::Icmp6Packet &aPacket); 1541 bool NetworkDataContainsUlaRoute(void) const; 1542 1543 void HandleRaPrefixTableChanged(void); 1544 void HandleLocalOnLinkPrefixChanged(void); 1545 1546 static TimeMilli CalculateExpirationTime(TimeMilli aUpdateTime, uint32_t aLifetime); 1547 1548 static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix); 1549 static bool IsValidOnLinkPrefix(const PrefixInfoOption &aPio); 1550 static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); 1551 1552 static void LogRaHeader(const RouterAdvert::Header &aRaHeader); 1553 static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime); 1554 static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference); 1555 1556 static const char *RouterAdvOriginToString(RouterAdvOrigin aRaOrigin); 1557 1558 //------------------------------------------------------------------------------------------------------------------ 1559 // Variables 1560 1561 using RoutingPolicyTimer = TimerMilliIn<RoutingManager, &RoutingManager::EvaluateRoutingPolicy>; 1562 1563 // Indicates whether the Routing Manager is running (started). 1564 bool mIsRunning; 1565 1566 // Indicates whether the Routing manager is enabled. The Routing 1567 // Manager will be stopped if we are disabled. 1568 bool mIsEnabled; 1569 1570 InfraIf mInfraIf; 1571 1572 // The /48 BR ULA prefix loaded from local persistent storage or 1573 // randomly generated if none is found in persistent storage. 1574 Ip6::Prefix mBrUlaPrefix; 1575 1576 OmrPrefixManager mOmrPrefixManager; 1577 1578 RioAdvertiser mRioAdvertiser; 1579 RoutePreference mRioPreference; 1580 bool mUserSetRioPreference; 1581 1582 OnLinkPrefixManager mOnLinkPrefixManager; 1583 1584 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE 1585 NetDataPeerBrTracker mNetDataPeerBrTracker; 1586 #endif 1587 1588 RxRaTracker mRxRaTracker; 1589 1590 RoutePublisher mRoutePublisher; 1591 1592 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1593 Nat64PrefixManager mNat64PrefixManager; 1594 #endif 1595 1596 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1597 PdPrefixManager mPdPrefixManager; 1598 #endif 1599 1600 TxRaInfo mTxRaInfo; 1601 RsSender mRsSender; 1602 Heap::Data mExtraRaOptions; 1603 1604 RoutingPolicyTimer mRoutingPolicyTimer; 1605 }; 1606 1607 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1608 1609 //---------------------------------------------------------------------------------------------------------------------- 1610 // Template specializations and declarations 1611 1612 template <> 1613 inline RoutingManager::RxRaTracker::Entry<RoutingManager::OnLinkPrefix> GetEntry(void)1614 &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void) 1615 { 1616 return mOnLinkEntry; 1617 } 1618 1619 template <> 1620 inline RoutingManager::RxRaTracker::Entry<RoutingManager::RoutePrefix> GetEntry(void)1621 &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void) 1622 { 1623 return mRouteEntry; 1624 } 1625 1626 // Declare template (full) specializations for `Router` type. 1627 1628 template <> 1629 RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router> *RoutingManager::RxRaTracker::AllocateEntry( 1630 void); 1631 1632 template <> void RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router>::Free(void); 1633 1634 #endif // #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1635 1636 } // namespace BorderRouter 1637 1638 DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State); 1639 1640 } // namespace ot 1641 1642 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1643 1644 #endif // ROUTING_MANAGER_HPP_ 1645