1 /* 2 * Copyright (c) 2020, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for the RA-based routing management. 32 * 33 */ 34 35 #ifndef ROUTING_MANAGER_HPP_ 36 #define ROUTING_MANAGER_HPP_ 37 38 #include "openthread-core-config.h" 39 40 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 41 42 #if !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 43 #error "OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE." 44 #endif 45 46 #if !OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 47 #error "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE." 48 #endif 49 50 #include <openthread/netdata.h> 51 52 #include "border_router/infra_if.hpp" 53 #include "common/array.hpp" 54 #include "common/error.hpp" 55 #include "common/linked_list.hpp" 56 #include "common/locator.hpp" 57 #include "common/notifier.hpp" 58 #include "common/pool.hpp" 59 #include "common/string.hpp" 60 #include "common/timer.hpp" 61 #include "net/ip6.hpp" 62 #include "net/nd6.hpp" 63 #include "thread/network_data.hpp" 64 65 namespace ot { 66 67 namespace BorderRouter { 68 69 /** 70 * This class implements bi-directional routing between Thread and Infrastructure networks. 71 * 72 * The Border Routing manager works on both Thread interface and infrastructure interface. 73 * All ICMPv6 messages are sent/received on the infrastructure interface. 74 * 75 */ 76 class RoutingManager : public InstanceLocator 77 { 78 friend class ot::Notifier; 79 friend class ot::Instance; 80 81 public: 82 typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low). 83 typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator. 84 typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry. 85 86 /** 87 * This constructor initializes the routing manager. 88 * 89 * @param[in] aInstance A OpenThread instance. 90 * 91 */ 92 explicit RoutingManager(Instance &aInstance); 93 94 /** 95 * This method initializes the routing manager on given infrastructure interface. 96 * 97 * @param[in] aInfraIfIndex An infrastructure network interface index. 98 * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure 99 * interface is running. 100 * 101 * @retval kErrorNone Successfully started the routing manager. 102 * @retval kErrorInvalidArgs The index of the infra interface is not valid. 103 * 104 */ 105 Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning); 106 107 /** 108 * This method enables/disables the Border Routing Manager. 109 * 110 * @note The Border Routing Manager is enabled by default. 111 * 112 * @param[in] aEnabled A boolean to enable/disable the Border Routing Manager. 113 * 114 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 115 * @retval kErrorNone Successfully enabled/disabled the Border Routing Manager. 116 * 117 */ 118 Error SetEnabled(bool aEnabled); 119 120 /** 121 * This method gets the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in 122 * Router Advertisement messages sent over the infrastructure link. 123 * 124 * @returns The Route Info Option preference. 125 * 126 */ GetRouteInfoOptionPreference(void) const127 RoutePreference GetRouteInfoOptionPreference(void) const { return mRouteInfoOptionPreference; } 128 129 /** 130 * This method sets the preference to use when advertising Route Info Options (e.g., for discovered OMR prefixes) 131 * in Router Advertisement messages sent over the infrastructure link. 132 * 133 * By default BR will use 'medium' preference level but this method allows the default value to be changed. As an 134 * example, it can be set to 'low' preference in the case where device is a temporary BR (a mobile BR or a 135 * battery-powered BR) to indicate that other BRs (if any) should be preferred over this BR on the infrastructure 136 * link. 137 * 138 * @param[in] aPreference The route preference to use. 139 * 140 */ 141 void SetRouteInfoOptionPreference(RoutePreference aPreference); 142 143 /** 144 * This method returns the local off-mesh-routable (OMR) prefix. 145 * 146 * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR 147 * prefix. 148 * 149 * @param[out] aPrefix A reference to where the prefix will be output to. 150 * 151 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 152 * @retval kErrorNone Successfully retrieved the OMR prefix. 153 * 154 */ 155 Error GetOmrPrefix(Ip6::Prefix &aPrefix); 156 157 /** 158 * This method returns the currently favored off-mesh-routable (OMR) prefix. 159 * 160 * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix. 161 * 162 * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the 163 * sense defined by `Ip6::Prefix`) is favored. 164 * 165 * @param[out] aPrefix A reference to output the favored prefix. 166 * @param[out] aPreference A reference to output the preference associated with the favored OMR prefix. 167 * 168 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 169 * @retval kErrorNone Successfully retrieved the OMR prefix. 170 * 171 */ 172 Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference); 173 174 /** 175 * This method returns the on-link prefix for the adjacent infrastructure link. 176 * 177 * The randomly generated 64-bit prefix will be advertised 178 * on the infrastructure link if there isn't already a usable 179 * on-link prefix being advertised on the link. 180 * 181 * @param[out] aPrefix A reference to where the prefix will be output to. 182 * 183 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 184 * @retval kErrorNone Successfully retrieved the on-link prefix. 185 * 186 */ 187 Error GetOnLinkPrefix(Ip6::Prefix &aPrefix); 188 189 #if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE 190 /** 191 * This method returns the local NAT64 prefix. 192 * 193 * The local NAT64 prefix will be published in the Thread network 194 * if none exists. 195 * 196 * @param[out] aPrefix A reference to where the prefix will be output to. 197 * 198 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 199 * @retval kErrorNone Successfully retrieved the NAT64 prefix. 200 * 201 */ 202 Error GetNat64Prefix(Ip6::Prefix &aPrefix); 203 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE 204 205 /** 206 * This method processes a received ICMPv6 message from the infrastructure interface. 207 * 208 * Malformed or undesired messages are dropped silently. 209 * 210 * @param[in] aPacket The received ICMPv6 packet. 211 * @param[in] aSrcAddress The source address this message is sent from. 212 * 213 */ 214 void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 215 216 /** 217 * This method handles infrastructure interface state changes. 218 * 219 */ HandleInfraIfStateChanged(void)220 void HandleInfraIfStateChanged(void) { EvaluateState(); } 221 222 /** 223 * This method checks if the on-mesh prefix configuration is a valid OMR prefix. 224 * 225 * @param[in] aOnMeshPrefixConfig The on-mesh prefix configuration to check. 226 * 227 * @returns Whether the on-mesh prefix configuration is a valid OMR prefix. 228 * 229 */ 230 static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 231 232 /** 233 * This method checks if the OMR prefix is valid (i.e. GUA/ULA prefix with length being 64). 234 * 235 * @param[in] aOmrPrefix The OMR prefix to check. 236 * @returns Whether the OMR prefix is valid. 237 * 238 */ 239 static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix); 240 241 /** 242 * This method initializes a `PrefixTableIterator`. 243 * 244 * An iterator can be initialized again to start from the beginning of the table. 245 * 246 * When iterating over entries in the table, to ensure the entry update times are consistent, they are given 247 * relative to the time the iterator was initialized. 248 * 249 * @param[out] aIterator The iterator to initialize. 250 * 251 */ InitPrefixTableIterator(PrefixTableIterator & aIterator) const252 void InitPrefixTableIterator(PrefixTableIterator &aIterator) const 253 { 254 mDiscoveredPrefixTable.InitIterator(aIterator); 255 } 256 257 /** 258 * This method iterates over entries in the discovered prefix table. 259 * 260 * @param[in,out] aIterator An iterator. 261 * @param[out] aEntry A reference to the entry to populate. 262 * 263 * @retval kErrorNone Got the next entry, @p aEntry is updated and @p aIterator is advanced. 264 * @retval kErrorNotFound No more entries in the table. 265 * 266 */ GetNextPrefixTableEntry(PrefixTableIterator & aIterator,PrefixTableEntry & aEntry) const267 Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const 268 { 269 return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry); 270 } 271 272 private: 273 static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES; 274 275 static constexpr uint8_t kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits. 276 static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits. 277 static constexpr uint8_t kBrUlaPrefixLength = 48; // The length of a BR ULA prefix. In bits. 278 static constexpr uint8_t kNat64PrefixLength = 96; // The length of a NAT64 prefix. In bits. 279 280 static constexpr uint16_t kOmrPrefixSubnetId = 1; // The subnet ID of an OMR prefix within a BR ULA prefix. 281 static constexpr uint16_t kNat64PrefixSubnetId = 2; // The subnet ID of a NAT64 prefix within a BR ULA prefix. 282 283 // The maximum number of initial Router Advertisements. 284 static constexpr uint32_t kMaxInitRtrAdvertisements = 3; 285 286 // The maximum number of Router Solicitations before sending Router Advertisements. 287 static constexpr uint32_t kMaxRtrSolicitations = 3; 288 289 static constexpr uint32_t kDefaultOmrPrefixLifetime = 1800; // The default OMR prefix valid lifetime. In sec. 290 static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800; // The default on-link prefix valid lifetime. In sec. 291 static constexpr uint32_t kMaxRtrAdvInterval = 600; // Max Router Advertisement Interval. In sec. 292 static constexpr uint32_t kMinRtrAdvInterval = kMaxRtrAdvInterval / 3; // Min RA Interval. In sec. 293 static constexpr uint32_t kMaxInitRtrAdvInterval = 16; // Max Initial RA Interval. In sec. 294 static constexpr uint32_t kRaReplyJitter = 500; // Jitter for sending RA after rx RS. In msec. 295 static constexpr uint32_t kRtrSolicitationInterval = 4; // Interval between RSs. In sec. 296 static constexpr uint32_t kMaxRtrSolicitationDelay = 1; // Max delay for initial solicitation. In sec. 297 static constexpr uint32_t kRoutingPolicyEvaluationJitter = 1000; // Jitter for routing policy evaluation. In msec. 298 static constexpr uint32_t kRtrSolicitationRetryDelay = 299 kRtrSolicitationInterval; // The delay before retrying failed RS tx. In Sec. 300 static constexpr uint32_t kMinDelayBetweenRtrAdvs = 3000; // Min delay (msec) between consecutive RAs. 301 302 // The STALE_RA_TIME in seconds. The Routing Manager will consider the prefixes 303 // and learned RA parameters STALE when they are not refreshed in STALE_RA_TIME 304 // seconds. The Routing Manager will then start Router Solicitation to verify 305 // that the STALE prefix is not being advertised anymore and remove the STALE 306 // prefix. 307 // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`]. 308 static constexpr uint32_t kRtrAdvStaleTime = 1800; 309 310 static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals"); 311 static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime"); 312 static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime"); 313 static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime, 314 "invalid RA STALE time"); 315 316 enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()` 317 { 318 kInvalidateAllPrevPrefixes, 319 kAdvPrefixesFromNetData, 320 }; 321 322 class DiscoveredPrefixTable : public InstanceLocator 323 { 324 // This class maintains the discovered on-link and route prefixes 325 // from the received RA messages by processing PIO and RIO options 326 // from the message. It takes care of processing the RA message but 327 // delegates the decision whether to include or exclude a prefix to 328 // `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()` 329 // and `ShouldProcessRouteInfoOption()` methods. 330 // 331 // It manages the lifetime of the discovered entries and publishes 332 // and unpublishes the prefixes in the Network Data (as external 333 // route) as they are added or removed. 334 // 335 // When there is any change in the table (an entry is added, removed, 336 // or modified), it signals the change to `RoutingManager` by calling 337 // `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is 338 // used for signalling which ensures that if there are multiple 339 // changes within the same flow of execution, the callback is 340 // invoked after all the changes are processed. 341 342 public: 343 enum NetDataMode : uint8_t // Used in `Remove{}` methods 344 { 345 kUnpublishFromNetData, // Unpublish the entry from Network Data if previously published. 346 kKeepInNetData, // Keep entry in Network Data if previously published. 347 }; 348 349 explicit DiscoveredPrefixTable(Instance &aInstance); 350 351 void ProcessRouterAdvertMessage(const Ip6::Nd::RouterAdvertMessage &aRaMessage, 352 const Ip6::Address & aSrcAddress); 353 354 void SetAllowDefaultRouteInNetData(bool aAllow); 355 356 void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const; 357 bool ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const; 358 void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode); 359 360 bool ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const; 361 void RemoveRoutePrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode); 362 363 void RemoveAllEntries(void); 364 void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold); 365 366 TimeMilli CalculateNextStaleTime(TimeMilli aNow) const; 367 368 void InitIterator(PrefixTableIterator &aIterator) const; 369 Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const; 370 371 private: 372 static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS; 373 static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES; 374 375 class Entry : public LinkedListEntry<Entry>, public Unequatable<Entry>, private Clearable<Entry> 376 { 377 friend class LinkedListEntry<Entry>; 378 379 public: 380 enum Type : uint8_t 381 { 382 kTypeOnLink, 383 kTypeRoute, 384 }; 385 386 struct Matcher 387 { Matcherot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::Matcher388 Matcher(const Ip6::Prefix &aPrefix, Type aType) 389 : mPrefix(aPrefix) 390 , mType(aType) 391 { 392 } 393 394 const Ip6::Prefix &mPrefix; 395 bool mType; 396 }; 397 398 struct ExpirationChecker 399 { ExpirationCheckerot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::ExpirationChecker400 explicit ExpirationChecker(TimeMilli aNow) 401 : mNow(aNow) 402 { 403 } 404 405 TimeMilli mNow; 406 }; 407 408 void SetFrom(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader); 409 void SetFrom(const Ip6::Nd::PrefixInfoOption &aPio); 410 void SetFrom(const Ip6::Nd::RouteInfoOption &aRio); GetType(void) const411 Type GetType(void) const { return mType; } IsOnLinkPrefix(void) const412 bool IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); } GetPrefix(void) const413 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetLastUpdateTime(void) const414 const TimeMilli & GetLastUpdateTime(void) const { return mLastUpdateTime; } GetValidLifetime(void) const415 uint32_t GetValidLifetime(void) const { return mValidLifetime; } ClearValidLifetime(void)416 void ClearValidLifetime(void) { mValidLifetime = 0; } 417 TimeMilli GetExpireTime(void) const; 418 TimeMilli GetStaleTime(void) const; 419 RoutePreference GetPreference(void) const; 420 bool operator==(const Entry &aOther) const; 421 bool Matches(const Matcher &aMatcher) const; 422 bool Matches(const ExpirationChecker &aCheker) const; 423 424 // Methods to use when `IsOnLinkPrefix()` GetPreferredLifetime(void) const425 uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; } ClearPreferredLifetime(void)426 void ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; } 427 bool IsDeprecated(void) const; 428 void AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry); 429 430 // Method to use when `!IsOnlinkPrefix()` GetRoutePreference(void) const431 RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; } 432 433 private: 434 static uint32_t CalculateExpireDelay(uint32_t aValidLifetime); 435 436 Entry * mNext; 437 Ip6::Prefix mPrefix; 438 Type mType; 439 TimeMilli mLastUpdateTime; 440 uint32_t mValidLifetime; 441 union 442 { 443 uint32_t mPreferredLifetime; // Applicable when prefix is on-link. 444 RoutePreference mRoutePreference; // Applicable when prefix is not on-link 445 } mShared; 446 }; 447 448 struct Router 449 { 450 enum EmptyChecker : uint8_t 451 { 452 kContainsNoEntries 453 }; 454 Matchesot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Router455 bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; } Matchesot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Router456 bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); } 457 458 Ip6::Address mAddress; 459 LinkedList<Entry> mEntries; 460 }; 461 462 class Iterator : public PrefixTableIterator 463 { 464 public: GetRouter(void) const465 const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); } SetRouter(const Router * aRouter)466 void SetRouter(const Router *aRouter) { mPtr1 = aRouter; } GetEntry(void) const467 const Entry * GetEntry(void) const { return static_cast<const Entry *>(mPtr2); } SetEntry(const Entry * aEntry)468 void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; } GetInitTime(void) const469 TimeMilli GetInitTime(void) const { return TimeMilli(mData32); } SetInitTime(void)470 void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); } 471 }; 472 473 void ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter); 474 void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter); 475 void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter); 476 bool ContainsPrefix(const Entry::Matcher &aMatcher) const; 477 void RemovePrefix(const Entry::Matcher &aMatcher, NetDataMode aNetDataMode); 478 void RemoveRoutersWithNoEntries(void); AllocateEntry(void)479 Entry * AllocateEntry(void) { return mEntryPool.Allocate(); } FreeEntry(Entry & aEntry)480 void FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); } 481 void FreeEntries(LinkedList<Entry> &aEntries); 482 void UpdateNetworkDataOnChangeTo(Entry &aEntry); 483 Entry * FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix); 484 void PublishEntry(const Entry &aEntry); 485 void UnpublishEntry(const Entry &aEntry); 486 static void HandleTimer(Timer &aTimer); 487 void HandleTimer(void); 488 void RemoveExpiredEntries(void); 489 void SignalTableChanged(void); 490 static void HandleSignalTask(Tasklet &aTasklet); 491 492 Array<Router, kMaxRouters> mRouters; 493 Pool<Entry, kMaxEntries> mEntryPool; 494 TimerMilli mTimer; 495 Tasklet mSignalTask; 496 bool mAllowDefaultRouteInNetData; 497 }; 498 499 class LocalOmrPrefix; 500 501 class OmrPrefix : public Clearable<OmrPrefix> 502 { 503 public: OmrPrefix(void)504 OmrPrefix(void) { Clear(); } 505 IsEmpty(void) const506 bool IsEmpty(void) const { return (mPrefix.GetLength() == 0); } 507 void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 508 void SetFrom(const LocalOmrPrefix &aLocalOmrPrefix); GetPrefix(void) const509 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetPreference(void) const510 RoutePreference GetPreference(void) const { return mPreference; } 511 bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const; 512 513 private: 514 Ip6::Prefix mPrefix; 515 RoutePreference mPreference; 516 }; 517 518 class LocalOmrPrefix : InstanceLocator 519 { 520 public: 521 explicit LocalOmrPrefix(Instance &aInstance); 522 void GenerateFrom(const Ip6::Prefix &aBrUlaPrefix); GetPrefix(void) const523 const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } GetPreference(void) const524 RoutePreference GetPreference(void) const { return NetworkData::kRoutePreferenceLow; } 525 Error AddToNetData(void); 526 void RemoveFromNetData(void); IsAddedInNetData(void) const527 bool IsAddedInNetData(void) const { return mIsAddedInNetData; } 528 529 private: 530 Ip6::Prefix mPrefix; 531 bool mIsAddedInNetData; 532 }; 533 534 typedef Ip6::Prefix OnMeshPrefix; 535 536 class OnMeshPrefixArray : public Array<OnMeshPrefix, kMaxOnMeshPrefixes> 537 { 538 public: 539 void Add(const OnMeshPrefix &aPrefix); 540 void MarkAsDeleted(const OnMeshPrefix &aPrefix); 541 }; 542 543 void EvaluateState(void); 544 void Start(void); 545 void Stop(void); 546 void HandleNotifierEvents(Events aEvents); IsInitialized(void) const547 bool IsInitialized(void) const { return mInfraIf.IsInitialized(); } IsEnabled(void) const548 bool IsEnabled(void) const { return mIsEnabled; } 549 Error LoadOrGenerateRandomBrUlaPrefix(void); 550 void GenerateOnLinkPrefix(void); 551 552 void EvaluateOnLinkPrefix(void); 553 554 #if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE 555 void GenerateNat64Prefix(void); 556 void EvaluateNat64Prefix(void); 557 #endif 558 559 void EvaluateRoutingPolicy(void); 560 void StartRoutingPolicyEvaluationJitter(uint32_t aJitterMilli); 561 void StartRoutingPolicyEvaluationDelay(uint32_t aDelayMilli); 562 void EvaluateOmrPrefix(void); 563 Error PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false); 564 void UnpublishExternalRoute(const Ip6::Prefix &aPrefix); 565 void StartRouterSolicitationDelay(void); 566 Error SendRouterSolicitation(void); 567 void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode); 568 bool IsRouterSolicitationInProgress(void) const; 569 570 static void HandleRouterSolicitTimer(Timer &aTimer); 571 void HandleRouterSolicitTimer(void); 572 static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer); 573 void HandleDiscoveredPrefixInvalidTimer(void); 574 static void HandleDiscoveredPrefixStaleTimer(Timer &aTimer); 575 void HandleDiscoveredPrefixStaleTimer(void); 576 static void HandleRoutingPolicyTimer(Timer &aTimer); 577 void HandleOnLinkPrefixDeprecateTimer(void); 578 static void HandleOnLinkPrefixDeprecateTimer(Timer &aTimer); 579 580 void DeprecateOnLinkPrefix(void); 581 void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 582 void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); 583 bool ShouldProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix); 584 bool ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix); 585 void UpdateDiscoveredPrefixTableOnNetDataChange(void); 586 void HandleDiscoveredPrefixTableChanged(void); 587 bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const; 588 void UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage); 589 bool IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdvertMessage &aRaMessage) const; 590 void ResetDiscoveredPrefixStaleTimer(void); 591 592 static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix); 593 static bool IsValidOnLinkPrefix(const Ip6::Nd::PrefixInfoOption &aPio); 594 static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); 595 596 // Indicates whether the Routing Manager is running (started). 597 bool mIsRunning; 598 599 // Indicates whether the Routing manager is enabled. The Routing 600 // Manager will be stopped if we are disabled. 601 bool mIsEnabled; 602 603 InfraIf mInfraIf; 604 605 // The /48 BR ULA prefix loaded from local persistent storage or 606 // randomly generated if none is found in persistent storage. 607 Ip6::Prefix mBrUlaPrefix; 608 609 LocalOmrPrefix mLocalOmrPrefix; 610 OmrPrefix mFavoredOmrPrefix; 611 612 // List of on-mesh prefixes (discovered from Network Data) which 613 // were advertised as RIO in the last sent RA message. 614 OnMeshPrefixArray mAdvertisedPrefixes; 615 616 RoutePreference mRouteInfoOptionPreference; 617 618 // The currently favored (smallest) discovered on-link prefix. 619 // Prefix length of zero indicates there is none. 620 Ip6::Prefix mFavoredDiscoveredOnLinkPrefix; 621 622 // The on-link prefix loaded from local persistent storage or 623 // randomly generated if non is found in persistent storage. 624 Ip6::Prefix mLocalOnLinkPrefix; 625 626 bool mIsAdvertisingLocalOnLinkPrefix; 627 628 // The last time when the on-link prefix is advertised with 629 // non-zero preferred lifetime. 630 TimeMilli mTimeAdvertisedOnLinkPrefix; 631 TimerMilli mOnLinkPrefixDeprecateTimer; 632 633 // The NAT64 prefix allocated from the /48 BR ULA prefix. 634 Ip6::Prefix mLocalNat64Prefix; 635 636 // True if the local NAT64 prefix is advertised in Thread network. 637 bool mIsAdvertisingLocalNat64Prefix; 638 639 DiscoveredPrefixTable mDiscoveredPrefixTable; 640 641 // The RA header and parameters for the infra interface. 642 // This value is initialized with `RouterAdvMessage::SetToDefault` 643 // and updated with RA messages initiated from infra interface. 644 Ip6::Nd::RouterAdvertMessage::Header mRouterAdvertHeader; 645 TimeMilli mTimeRouterAdvMessageLastUpdate; 646 bool mLearntRouterAdvMessageFromHost; 647 648 TimerMilli mDiscoveredPrefixStaleTimer; 649 650 uint32_t mRouterAdvertisementCount; 651 TimeMilli mLastRouterAdvertisementSendTime; 652 653 TimerMilli mRouterSolicitTimer; 654 TimeMilli mTimeRouterSolicitStart; 655 uint8_t mRouterSolicitCount; 656 657 TimerMilli mRoutingPolicyTimer; 658 }; 659 660 } // namespace BorderRouter 661 662 } // namespace ot 663 664 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 665 666 #endif // ROUTING_MANAGER_HPP_ 667