• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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