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