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 #include <openthread/platform/infra_if.h> 52 53 #include "border_router/router_advertisement.hpp" 54 #include "common/array.hpp" 55 #include "common/error.hpp" 56 #include "common/locator.hpp" 57 #include "common/notifier.hpp" 58 #include "common/timer.hpp" 59 #include "net/ip6.hpp" 60 #include "thread/network_data.hpp" 61 62 namespace ot { 63 64 namespace BorderRouter { 65 66 /** 67 * This class implements bi-directional routing between Thread and Infrastructure networks. 68 * 69 * The Border Routing manager works on both Thread interface and infrastructure interface. 70 * All ICMPv6 messages are sent/received on the infrastructure interface. 71 * 72 */ 73 class RoutingManager : public InstanceLocator 74 { 75 friend class ot::Notifier; 76 77 public: 78 /** 79 * This constructor initializes the routing manager. 80 * 81 * @param[in] aInstance A OpenThread instance. 82 * 83 */ 84 explicit RoutingManager(Instance &aInstance); 85 86 /** 87 * This method initializes the routing manager on given infrastructure interface. 88 * 89 * @param[in] aInfraIfIndex An infrastructure network interface index. 90 * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure 91 * interface is running. 92 * 93 * @retval kErrorNone Successfully started the routing manager. 94 * @retval kErrorInvalidArgs The index of the infra interface is not valid. 95 * 96 */ 97 Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning); 98 99 /** 100 * This method enables/disables the Border Routing Manager. 101 * 102 * @note The Border Routing Manager is enabled by default. 103 * 104 * @param[in] aEnabled A boolean to enable/disable the Border Routing Manager. 105 * 106 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 107 * @retval kErrorNone Successfully enabled/disabled the Border Routing Manager. 108 * 109 */ 110 Error SetEnabled(bool aEnabled); 111 112 /** 113 * This method returns the off-mesh-routable (OMR) prefix. 114 * 115 * The randomly generated 64-bit prefix will be published 116 * in the Thread network if there isn't already an OMR prefix. 117 * 118 * @param[out] aPrefix A reference to where the prefix will be output to. 119 * 120 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 121 * @retval kErrorNone Successfully retrieved the OMR prefix. 122 * 123 */ 124 Error GetOmrPrefix(Ip6::Prefix &aPrefix); 125 126 /** 127 * This method returns the on-link prefix for the adjacent infrastructure link. 128 * 129 * The randomly generated 64-bit prefix will be advertised 130 * on the infrastructure link if there isn't already a usable 131 * on-link prefix being advertised on the link. 132 * 133 * @param[out] aPrefix A reference to where the prefix will be output to. 134 * 135 * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. 136 * @retval kErrorNone Successfully retrieved the on-link prefix. 137 * 138 */ 139 Error GetOnLinkPrefix(Ip6::Prefix &aPrefix); 140 141 /** 142 * This method receives an ICMPv6 message on the infrastructure interface. 143 * 144 * Malformed or undesired messages are dropped silently. 145 * 146 * @param[in] aInfraIfIndex The infrastructure interface index. 147 * @param[in] aSrcAddress The source address this message is sent from. 148 * @param[in] aBuffer THe ICMPv6 message buffer. 149 * @param[in] aLength The length of the ICMPv6 message buffer. 150 * 151 */ 152 void RecvIcmp6Message(uint32_t aInfraIfIndex, 153 const Ip6::Address &aSrcAddress, 154 const uint8_t * aBuffer, 155 uint16_t aBufferLength); 156 157 /** 158 * This method handles infrastructure interface state changes. 159 * 160 * @param[in] aInfraIfIndex The index of the infrastructure interface. 161 * @param[in] aIsRunning A boolean that indicates whether the infrastructure 162 * interface is running. 163 * 164 * @retval kErrorNone Successfully updated the infra interface status. 165 * @retval kErrorInvalidState The Routing Manager is not initialized. 166 * @retval kErrorInvalidArgs The @p aInfraIfIndex doesn't match the infra interface 167 * the Routing Manager is initialized with. 168 * 169 */ 170 Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning); 171 172 private: 173 typedef NetworkData::RoutePreference RoutePreference; 174 175 static constexpr uint16_t kMaxRouterAdvMessageLength = 256; // The maximum RA message length we can handle. 176 177 // The maximum number of the OMR prefixes to advertise. 178 static constexpr uint8_t kMaxOmrPrefixNum = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES; 179 180 // The maximum number of prefixes to discover on the infra link. 181 static constexpr uint8_t kMaxDiscoveredPrefixNum = 8; 182 183 static constexpr uint8_t kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits. 184 static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits. 185 186 // The maximum number of initial Router Advertisements. 187 static constexpr uint32_t kMaxInitRtrAdvertisements = 3; 188 189 // The maximum number of Router Solicitations before sending Router Advertisements. 190 static constexpr uint32_t kMaxRtrSolicitations = 3; 191 192 static constexpr uint32_t kDefaultOmrPrefixLifetime = 1800; // The default OMR prefix valid lifetime. In sec. 193 static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800; // The default on-link prefix valid lifetime. In sec. 194 static constexpr uint32_t kMaxRtrAdvInterval = 600; // Max Router Advertisement Interval. In sec. 195 static constexpr uint32_t kMinRtrAdvInterval = kMaxRtrAdvInterval / 3; // Min RA Interval. In sec. 196 static constexpr uint32_t kMaxInitRtrAdvInterval = 16; // Max Initial RA Interval. In sec. 197 static constexpr uint32_t kMaxRaDelayTime = 500; // Max delay of sending RA after rx RS. In msec. 198 static constexpr uint32_t kRtrSolicitationInterval = 4; // Interval between RSs. In sec. 199 static constexpr uint32_t kMaxRtrSolicitationDelay = 1; // Max delay for initial solicitation. In sec. 200 static constexpr uint32_t kMaxRoutingPolicyDelay = 1; // Max delay for routing policy evaluation. In sec. 201 202 // The STALE_RA_TIME in seconds. The Routing Manager will consider the prefixes 203 // and learned RA parameters STALE when they are not refreshed in STALE_RA_TIME 204 // seconds. The Routing Manager will then start Router Solicitation to verify 205 // that the STALE prefix is not being advertised anymore and remove the STALE 206 // prefix. 207 // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`]. 208 static constexpr uint32_t kRtrAdvStaleTime = 1800; 209 210 // The VICARIOUS_SOLICIT_TIME in seconds. The Routing Manager will consider 211 // the discovered prefixes invalid if they are not refreshed after receiving 212 // a Router Solicitation message. 213 // The value is equal to Router Solicitation timeout. 214 static constexpr uint32_t kVicariousSolicitationTime = 215 kRtrSolicitationInterval * (kMaxRtrSolicitations - 1) + kMaxRtrSolicitationDelay; 216 217 static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals"); 218 static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime"); 219 static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime"); 220 static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime, 221 "invalid RA STALE time"); 222 223 // This struct represents an external prefix which is 224 // discovered on the infrastructure interface. 225 struct ExternalPrefix : public Clearable<ExternalPrefix>, public Unequatable<ExternalPrefix> 226 { 227 Ip6::Prefix mPrefix; 228 uint32_t mValidLifetime; 229 230 union 231 { 232 // Preferred Lifetime of on-link prefix, available 233 // only when `mIsOnLinkPrefix` is TRUE. 234 uint32_t mPreferredLifetime; 235 236 // The preference of this route, available 237 // only when `mIsOnLinkPrefix` is FALSE. 238 RoutePreference mRoutePreference; 239 }; 240 TimeMilli mTimeLastUpdate; 241 bool mIsOnLinkPrefix; 242 operator ==ot::BorderRouter::RoutingManager::ExternalPrefix243 bool operator==(const ExternalPrefix &aPrefix) const 244 { 245 return mPrefix == aPrefix.mPrefix && mIsOnLinkPrefix == aPrefix.mIsOnLinkPrefix; 246 } 247 IsDeprecatedot::BorderRouter::RoutingManager::ExternalPrefix248 bool IsDeprecated(void) const 249 { 250 OT_ASSERT(mIsOnLinkPrefix); 251 252 return mTimeLastUpdate + TimeMilli::SecToMsec(mPreferredLifetime) <= TimerMilli::GetNow(); 253 } 254 GetExpireTimeot::BorderRouter::RoutingManager::ExternalPrefix255 TimeMilli GetExpireTime(void) const { return mTimeLastUpdate + GetPrefixExpireDelay(mValidLifetime); } GetStaleTimeot::BorderRouter::RoutingManager::ExternalPrefix256 TimeMilli GetStaleTime(void) const 257 { 258 uint32_t delay = OT_MIN(kRtrAdvStaleTime, mIsOnLinkPrefix ? mPreferredLifetime : mValidLifetime); 259 260 return mTimeLastUpdate + TimeMilli::SecToMsec(delay); 261 } 262 263 static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime); 264 }; 265 266 typedef Array<Ip6::Prefix, kMaxOmrPrefixNum> OmrPrefixArray; 267 typedef Array<ExternalPrefix, kMaxDiscoveredPrefixNum> ExternalPrefixArray; 268 269 void EvaluateState(void); 270 void Start(void); 271 void Stop(void); 272 void HandleNotifierEvents(Events aEvents); IsInitialized(void) const273 bool IsInitialized(void) const { return mInfraIfIndex != 0; } IsEnabled(void) const274 bool IsEnabled(void) const { return mIsEnabled; } 275 Error LoadOrGenerateRandomOmrPrefix(void); 276 Error LoadOrGenerateRandomOnLinkPrefix(void); 277 278 const Ip6::Prefix *EvaluateOnLinkPrefix(void); 279 280 void EvaluateRoutingPolicy(void); 281 void StartRoutingPolicyEvaluationDelay(void); 282 void EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes); 283 Error PublishLocalOmrPrefix(void); 284 void UnpublishLocalOmrPrefix(void); 285 Error AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference); 286 void RemoveExternalRoute(const Ip6::Prefix &aPrefix); 287 void StartRouterSolicitationDelay(void); 288 Error SendRouterSolicitation(void); 289 void SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefixes, const Ip6::Prefix *aNewOnLinkPrefix); 290 291 static void HandleRouterAdvertisementTimer(Timer &aTimer); 292 void HandleRouterAdvertisementTimer(void); 293 static void HandleVicariousRouterSolicitTimer(Timer &aTimer); 294 void HandleVicariousRouterSolicitTimer(void); 295 static void HandleRouterSolicitTimer(Timer &aTimer); 296 void HandleRouterSolicitTimer(void); 297 static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer); 298 void HandleDiscoveredPrefixInvalidTimer(void); 299 static void HandleDiscoveredPrefixStaleTimer(Timer &aTimer); 300 void HandleDiscoveredPrefixStaleTimer(void); 301 static void HandleRoutingPolicyTimer(Timer &aTimer); 302 void HandleOnLinkPrefixDeprecateTimer(void); 303 static void HandleOnLinkPrefixDeprecateTimer(Timer &aTimer); 304 305 void DeprecateOnLinkPrefix(void); 306 void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); 307 void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); 308 bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig); 309 bool UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio); 310 bool InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix = nullptr, bool aIsOnLinkPrefix = true); 311 void InvalidateAllDiscoveredPrefixes(void); 312 bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const; 313 bool UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage); 314 315 static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); 316 static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix); 317 static bool IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig); 318 static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); 319 320 // Indicates whether the Routing Manager is running (started). 321 bool mIsRunning; 322 323 // Indicates whether the Routing manager is enabled. The Routing 324 // Manager will be stopped if we are disabled. 325 bool mIsEnabled; 326 327 // Indicates whether the infra interface is running. The Routing 328 // Manager will be stopped when the Infra interface is not running. 329 bool mInfraIfIsRunning; 330 331 // The index of the infra interface on which Router Advertisement 332 // messages will be sent. 333 uint32_t mInfraIfIndex; 334 335 // The OMR prefix loaded from local persistent storage or randomly 336 // generated if non is found in persistent storage. 337 Ip6::Prefix mLocalOmrPrefix; 338 339 // The advertised OMR prefixes. For a stable Thread network without 340 // manually configured OMR prefixes, there should be a single OMR 341 // prefix that is being advertised because each BRs will converge to 342 // the smallest OMR prefix sorted by method IsPrefixSmallerThan. If 343 // manually configured OMR prefixes exist, they will also be 344 // advertised on infra link. 345 OmrPrefixArray mAdvertisedOmrPrefixes; 346 347 // The on-link prefix loaded from local persistent storage or 348 // randomly generated if non is found in persistent storage. 349 Ip6::Prefix mLocalOnLinkPrefix; 350 351 bool mIsAdvertisingLocalOnLinkPrefix; 352 353 // The last time when the on-link prefix is advertised with 354 // non-zero preferred lifetime. 355 TimeMilli mTimeAdvertisedOnLinkPrefix; 356 TimerMilli mOnLinkPrefixDeprecateTimer; 357 358 // The array of prefixes discovered on the infra link. Those 359 // prefixes consist of on-link prefix(es) and OMR prefixes 360 // advertised by BRs in another Thread Network which is connected to 361 // the same infra link. 362 ExternalPrefixArray mDiscoveredPrefixes; 363 364 // The RA header and parameters for the infra interface. 365 // This value is initialized with `RouterAdvMessage::SetToDefault` 366 // and updated with RA messages initiated from infra interface. 367 RouterAdv::RouterAdvMessage mRouterAdvMessage; 368 TimeMilli mTimeRouterAdvMessageLastUpdate; 369 370 TimerMilli mDiscoveredPrefixInvalidTimer; 371 TimerMilli mDiscoveredPrefixStaleTimer; 372 373 TimerMilli mRouterAdvertisementTimer; 374 uint32_t mRouterAdvertisementCount; 375 376 TimerMilli mVicariousRouterSolicitTimer; 377 TimeMilli mTimeVicariousRouterSolicitStart; 378 TimerMilli mRouterSolicitTimer; 379 TimeMilli mTimeRouterSolicitStart; 380 uint8_t mRouterSolicitCount; 381 382 TimerMilli mRoutingPolicyTimer; 383 }; 384 385 } // namespace BorderRouter 386 387 } // namespace ot 388 389 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 390 391 #endif // ROUTING_MANAGER_HPP_ 392