• 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/nat64.h>
51 #include <openthread/netdata.h>
52 
53 #include "border_router/infra_if.hpp"
54 #include "common/array.hpp"
55 #include "common/error.hpp"
56 #include "common/heap_allocatable.hpp"
57 #include "common/heap_array.hpp"
58 #include "common/heap_data.hpp"
59 #include "common/linked_list.hpp"
60 #include "common/locator.hpp"
61 #include "common/message.hpp"
62 #include "common/notifier.hpp"
63 #include "common/pool.hpp"
64 #include "common/string.hpp"
65 #include "common/timer.hpp"
66 #include "crypto/sha256.hpp"
67 #include "net/ip6.hpp"
68 #include "net/nat64_translator.hpp"
69 #include "net/nd6.hpp"
70 #include "thread/network_data.hpp"
71 
72 namespace ot {
73 
74 namespace BorderRouter {
75 
76 /**
77  * Implements bi-directional routing between Thread and Infrastructure networks.
78  *
79  * The Border Routing manager works on both Thread interface and infrastructure interface.
80  * All ICMPv6 messages are sent/received on the infrastructure interface.
81  *
82  */
83 class RoutingManager : public InstanceLocator
84 {
85     friend class ot::Notifier;
86     friend class ot::Instance;
87 
88 public:
89     typedef NetworkData::RoutePreference       RoutePreference;     ///< Route preference (high, medium, low).
90     typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
91     typedef otBorderRoutingPrefixTableEntry    PrefixTableEntry;    ///< Prefix Table Entry.
92     typedef otBorderRoutingRouterEntry         RouterEntry;         ///< Router Entry.
93     typedef otPdProcessedRaInfo                PdProcessedRaInfo;   ///< Data of PdProcessedRaInfo.
94 
95     /**
96      * This constant specifies the maximum number of route prefixes that may be published by `RoutingManager`
97      * in Thread Network Data.
98      *
99      * This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`.
100      *
101      * The number of published entries accounts for:
102      * - Route prefix `fc00::/7` or `::/0`
103      * - One entry for NAT64 published prefix.
104      * - One extra entry for transitions.
105      *
106      */
107     static constexpr uint16_t kMaxPublishedPrefixes = 3;
108 
109     /**
110      * Represents the states of `RoutingManager`.
111      *
112      */
113     enum State : uint8_t
114     {
115         kStateUninitialized = OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Uninitialized.
116         kStateDisabled      = OT_BORDER_ROUTING_STATE_DISABLED,      ///< Initialized but disabled.
117         kStateStopped       = OT_BORDER_ROUTING_STATE_STOPPED,       ///< Initialized & enabled, but currently stopped.
118         kStateRunning       = OT_BORDER_ROUTING_STATE_RUNNING,       ///< Initialized, enabled, and running.
119     };
120 
121     /**
122      * This enumeration represents the states of DHCPv6 PD in `RoutingManager`.
123      *
124      */
125     enum Dhcp6PdState : uint8_t
126     {
127         kDhcp6PdStateDisabled = OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, ///< Disabled.
128         kDhcp6PdStateStopped  = OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED,  ///< Enabled, but currently stopped.
129         kDhcp6PdStateRunning  = OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING,  ///< Enabled, and running.
130     };
131 
132     /**
133      * Initializes the routing manager.
134      *
135      * @param[in]  aInstance  A OpenThread instance.
136      *
137      */
138     explicit RoutingManager(Instance &aInstance);
139 
140     /**
141      * Initializes the routing manager on given infrastructure interface.
142      *
143      * @param[in]  aInfraIfIndex      An infrastructure network interface index.
144      * @param[in]  aInfraIfIsRunning  A boolean that indicates whether the infrastructure
145      *                                interface is running.
146      *
147      * @retval  kErrorNone         Successfully started the routing manager.
148      * @retval  kErrorInvalidArgs  The index of the infra interface is not valid.
149      *
150      */
151     Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning);
152 
153     /**
154      * Enables/disables the Border Routing Manager.
155      *
156      * @note  The Border Routing Manager is enabled by default.
157      *
158      * @param[in]  aEnabled   A boolean to enable/disable the Border Routing Manager.
159      *
160      * @retval  kErrorInvalidState   The Border Routing Manager is not initialized yet.
161      * @retval  kErrorNone           Successfully enabled/disabled the Border Routing Manager.
162      *
163      */
164     Error SetEnabled(bool aEnabled);
165 
166     /**
167      * Indicates whether or not it is currently running.
168      *
169      * In order for the `RoutingManager` to be running it needs to be initialized and enabled, and device being
170      * attached.
171      *
172      * @retval TRUE  The RoutingManager is currently running.
173      * @retval FALSE The RoutingManager is not running.
174      *
175      */
IsRunning(void) const176     bool IsRunning(void) const { return mIsRunning; }
177 
178     /**
179      * Gets the state of `RoutingManager`.
180      *
181      * @returns The current state of `RoutingManager`.
182      *
183      */
184     State GetState(void) const;
185 
186     /**
187      * Requests the Border Routing Manager to stop.
188      *
189      * If Border Routing Manager is running, calling this method immediately stops it and triggers the preparation
190      * and sending of a final Router Advertisement (RA) message on infrastructure interface which deprecates and/or
191      * removes any previously advertised PIO/RIO prefixes. If Routing Manager is not running (or not enabled), no
192      * action is taken.
193      *
194      * Note that this method does not change whether the Routing Manager is enabled or disabled (see `SetEnabled()`).
195      * It stops the Routing Manager temporarily. After calling this method if the device role gets changes (device
196      * gets attached) and/or the infra interface state gets changed, the Routing Manager may be started again.
197      *
198      */
RequestStop(void)199     void RequestStop(void) { Stop(); }
200 
201     /**
202      * Gets the current preference used when advertising Route Info Options (RIO) in Router Advertisement
203      * messages sent over the infrastructure link.
204      *
205      * The RIO preference is determined as follows:
206      *
207      * - If explicitly set by user by calling `SetRouteInfoOptionPreference()`, the given preference is used.
208      * - Otherwise, it is determined based on device's role: Medium preference when in router/leader role and low
209      *   preference when in child role.
210      *
211      * @returns The current Route Info Option preference.
212      *
213      */
GetRouteInfoOptionPreference(void) const214     RoutePreference GetRouteInfoOptionPreference(void) const { return mRioAdvertiser.GetPreference(); }
215 
216     /**
217      * Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router
218      * Advertisement messages sent over the infrastructure link.
219      *
220      * After a call to this method, BR will use the given preference for all its advertised RIOs. The preference can be
221      * cleared by calling `ClearRouteInfoOptionPreference`()`.
222      *
223      * @param[in] aPreference   The route preference to use.
224      *
225      */
SetRouteInfoOptionPreference(RoutePreference aPreference)226     void SetRouteInfoOptionPreference(RoutePreference aPreference) { mRioAdvertiser.SetPreference(aPreference); }
227 
228     /**
229      * Clears a previously set preference value for advertised Route Info Options.
230      *
231      * After a call to this method, BR will use device role to determine the RIO preference: Medium preference when
232      * in router/leader role and low preference when in child role.
233      *
234      */
ClearRouteInfoOptionPreference(void)235     void ClearRouteInfoOptionPreference(void) { mRioAdvertiser.ClearPreference(); }
236 
237     /**
238      * Sets additional options to append at the end of emitted Router Advertisement (RA) messages.
239      *
240      * The content of @p aOptions is copied internally, so can be a temporary stack variable.
241      *
242      * Subsequent calls to this method will overwrite the previously set value.
243      *
244      * @param[in] aOptions   A pointer to the encoded options. Can be `nullptr` to clear.
245      * @param[in] aLength    Number of bytes in @p aOptions.
246      *
247      * @retval kErrorNone     Successfully set the extra option bytes.
248      * @retval kErrorNoBufs   Could not allocate buffer to save the buffer.
249      *
250      */
251     Error SetExtraRouterAdvertOptions(const uint8_t *aOptions, uint16_t aLength);
252 
253     /**
254      * Gets the current preference used for published routes in Network Data.
255      *
256      * The preference is determined as follows:
257      *
258      * - If explicitly set by user by calling `SetRoutePreference()`, the given preference is used.
259      * - Otherwise, it is determined automatically by `RoutingManager` based on the device's role and link quality.
260      *
261      * @returns The current published route preference.
262      *
263      */
GetRoutePreference(void) const264     RoutePreference GetRoutePreference(void) const { return mRoutePublisher.GetPreference(); }
265 
266     /**
267      * Explicitly sets the preference of published routes in Network Data.
268      *
269      * After a call to this method, BR will use the given preference. The preference can be cleared by calling
270      * `ClearRoutePreference`()`.
271      *
272      * @param[in] aPreference   The route preference to use.
273      *
274      */
SetRoutePreference(RoutePreference aPreference)275     void SetRoutePreference(RoutePreference aPreference) { mRoutePublisher.SetPreference(aPreference); }
276 
277     /**
278      * Clears a previously set preference value for published routes in Network Data.
279      *
280      * After a call to this method, BR will determine the preference automatically based on the device's role and
281      * link quality (to the parent when acting as end-device).
282      *
283      */
ClearRoutePreference(void)284     void ClearRoutePreference(void) { mRoutePublisher.ClearPreference(); }
285 
286     /**
287      * Returns the local generated off-mesh-routable (OMR) prefix.
288      *
289      * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR
290      * prefix.
291      *
292      * @param[out]  aPrefix  A reference to where the prefix will be output to.
293      *
294      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
295      * @retval  kErrorNone          Successfully retrieved the OMR prefix.
296      *
297      */
298     Error GetOmrPrefix(Ip6::Prefix &aPrefix) const;
299 
300 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
301     /**
302      * Returns the platform provided off-mesh-routable (OMR) prefix.
303      *
304      * The prefix is extracted from the platform generated RA messages handled by `ProcessPlatformGeneratedNd()`.
305      *
306      * @param[out] aPrefixInfo      A reference to where the prefix info will be output to.
307      *
308      * @retval kErrorNone           Successfully retrieved the OMR prefix.
309      * @retval kErrorNotFound       There are no valid PD prefix on this BR.
310      * @retval kErrorInvalidState   The Border Routing Manager is not initialized yet.
311      *
312      */
313     Error GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const;
314 
315     /**
316      * Returns platform generated RA message processed information.
317      *
318      * @param[out] aPdProcessedRaInfo      A reference to where the PD processed RA info will be output to.
319      *
320      * @retval kErrorNone           Successfully retrieved the Info.
321      * @retval kErrorNotFound       There are no valid RA process info on this BR.
322      * @retval kErrorInvalidState   The Border Routing Manager is not initialized yet.
323      *
324      */
325     Error GetPdProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo);
326 #endif
327 
328     /**
329      * Returns the currently favored off-mesh-routable (OMR) prefix.
330      *
331      * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix.
332      *
333      * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the
334      * sense defined by `Ip6::Prefix`) is favored.
335      *
336      * @param[out] aPrefix         A reference to output the favored prefix.
337      * @param[out] aPreference     A reference to output the preference associated with the favored OMR prefix.
338      *
339      * @retval  kErrorInvalidState  The Border Routing Manager is not running yet.
340      * @retval  kErrorNone          Successfully retrieved the OMR prefix.
341      *
342      */
343     Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const;
344 
345     /**
346      * Returns the on-link prefix for the adjacent infrastructure link.
347      *
348      * The randomly generated 64-bit prefix will be advertised
349      * on the infrastructure link if there isn't already a usable
350      * on-link prefix being advertised on the link.
351      *
352      * @param[out]  aPrefix  A reference to where the prefix will be output to.
353      *
354      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
355      * @retval  kErrorNone          Successfully retrieved the local on-link prefix.
356      *
357      */
358     Error GetOnLinkPrefix(Ip6::Prefix &aPrefix) const;
359 
360     /**
361      * Returns the favored on-link prefix for the adjacent infrastructure link.
362      *
363      * The favored prefix is either a discovered prefix on the infrastructure link or the local on-link prefix.
364      *
365      * @param[out]  aPrefix  A reference to where the prefix will be output to.
366      *
367      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
368      * @retval  kErrorNone          Successfully retrieved the favored on-link prefix.
369      *
370      */
371     Error GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
372 
373 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
374     /**
375      * Gets the state of NAT64 prefix publishing.
376      *
377      * @retval  kStateDisabled   NAT64 is disabled.
378      * @retval  kStateNotRunning NAT64 is enabled, but is not running since routing manager is not running.
379      * @retval  kStateIdle       NAT64 is enabled, but the border router is not publishing a NAT64 prefix. Usually
380      *                           when there is another border router publishing a NAT64 prefix with higher
381      *                           priority.
382      * @retval  kStateActive     The Border router is publishing a NAT64 prefix.
383      *
384      */
GetNat64PrefixManagerState(void) const385     Nat64::State GetNat64PrefixManagerState(void) const { return mNat64PrefixManager.GetState(); }
386 
387     /**
388      * Enable or disable NAT64 prefix publishing.
389      *
390      * @param[in]  aEnabled   A boolean to enable/disable NAT64 prefix publishing.
391      *
392      */
393     void SetNat64PrefixManagerEnabled(bool aEnabled);
394 
395     /**
396      * Returns the local NAT64 prefix.
397      *
398      * @param[out]  aPrefix  A reference to where the prefix will be output to.
399      *
400      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
401      * @retval  kErrorNone          Successfully retrieved the NAT64 prefix.
402      *
403      */
404     Error GetNat64Prefix(Ip6::Prefix &aPrefix);
405 
406     /**
407      * Returns the currently favored NAT64 prefix.
408      *
409      * The favored NAT64 prefix can be discovered from infrastructure link or can be the local NAT64 prefix.
410      *
411      * @param[out] aPrefix           A reference to output the favored prefix.
412      * @param[out] aRoutePreference  A reference to output the preference associated with the favored prefix.
413      *
414      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
415      * @retval  kErrorNone          Successfully retrieved the NAT64 prefix.
416      *
417      */
418     Error GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreference &aRoutePreference);
419 
420     /**
421      * Informs `RoutingManager` of the result of the discovery request of NAT64 prefix on infrastructure
422      * interface (`InfraIf::DiscoverNat64Prefix()`).
423      *
424      * @param[in]  aPrefix  The discovered NAT64 prefix on `InfraIf`.
425      *
426      */
HandleDiscoverNat64PrefixDone(const Ip6::Prefix & aPrefix)427     void HandleDiscoverNat64PrefixDone(const Ip6::Prefix &aPrefix) { mNat64PrefixManager.HandleDiscoverDone(aPrefix); }
428 
429 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
430 
431     /**
432      * Processes a received ICMPv6 message from the infrastructure interface.
433      *
434      * Malformed or undesired messages are dropped silently.
435      *
436      * @param[in]  aPacket        The received ICMPv6 packet.
437      * @param[in]  aSrcAddress    The source address this message is sent from.
438      *
439      */
440     void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
441 
442     /**
443      * Handles infrastructure interface state changes.
444      *
445      */
HandleInfraIfStateChanged(void)446     void HandleInfraIfStateChanged(void) { EvaluateState(); }
447 
448     /**
449      * Checks whether the on-mesh prefix configuration is a valid OMR prefix.
450      *
451      * @param[in] aOnMeshPrefixConfig  The on-mesh prefix configuration to check.
452      *
453      * @retval   TRUE    The prefix is a valid OMR prefix.
454      * @retval   FALSE   The prefix is not a valid OMR prefix.
455      *
456      */
457     static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
458 
459     /**
460      * Checks whether a given prefix is a valid OMR prefix.
461      *
462      * @param[in]  aPrefix  The prefix to check.
463      *
464      * @retval   TRUE    The prefix is a valid OMR prefix.
465      * @retval   FALSE   The prefix is not a valid OMR prefix.
466      *
467      */
468     static bool IsValidOmrPrefix(const Ip6::Prefix &aPrefix);
469 
470     /**
471      * Initializes a `PrefixTableIterator`.
472      *
473      * An iterator can be initialized again to start from the beginning of the table.
474      *
475      * When iterating over entries in the table, to ensure the entry update times are consistent, they are given
476      * relative to the time the iterator was initialized.
477      *
478      * @param[out] aIterator  The iterator to initialize.
479      *
480      */
InitPrefixTableIterator(PrefixTableIterator & aIterator) const481     void InitPrefixTableIterator(PrefixTableIterator &aIterator) const
482     {
483         mDiscoveredPrefixTable.InitIterator(aIterator);
484     }
485 
486     /**
487      * Iterates over entries in the discovered prefix table.
488      *
489      * @param[in,out] aIterator  An iterator.
490      * @param[out]    aEntry     A reference to the entry to populate.
491      *
492      * @retval kErrorNone        Got the next entry, @p aEntry is updated and @p aIterator is advanced.
493      * @retval kErrorNotFound    No more entries in the table.
494      *
495      */
GetNextPrefixTableEntry(PrefixTableIterator & aIterator,PrefixTableEntry & aEntry) const496     Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const
497     {
498         return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry);
499     }
500 
501     /**
502      * Iterates over discovered router entries on infrastructure link.
503      *
504      * @param[in,out] aIterator  An iterator.
505      * @param[out]    aEntry     A reference to the entry to populate.
506      *
507      * @retval kErrorNone        Got the next router info, @p aEntry is updated and @p aIterator is advanced.
508      * @retval kErrorNotFound    No more routers.
509      *
510      */
GetNextRouterEntry(PrefixTableIterator & aIterator,RouterEntry & aEntry) const511     Error GetNextRouterEntry(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
512     {
513         return mDiscoveredPrefixTable.GetNextRouter(aIterator, aEntry);
514     }
515 
516 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
517     /**
518      * Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server.
519      *
520      * This should be called from `Srp::Server` when auto-enable mode is changed.
521      *
522      */
523     void HandleSrpServerAutoEnableMode(void);
524 #endif
525 
526 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
527     /**
528      * Handles a router advertisement message received on platform's Thread interface.
529      *
530      * Note: This method is a part of DHCPv6 PD support on Thread border routers. The message should be generated by the
531      * software like dnamasq, radvd, systemd-networkd on the platform as a part of the DHCPv6 prefix delegation process
532      * for distributing the prefix to the interfaces (links).
533      *
534      * @param[in] aRouterAdvert A pointer to the buffer of the router advertisement message.
535      * @param[in] aLength       The length of the router advertisement message.
536      *
537      */
ProcessPlatformGeneratedRa(const uint8_t * aRouterAdvert,uint16_t aLength)538     void ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength)
539     {
540         mPdPrefixManager.ProcessPlatformGeneratedRa(aRouterAdvert, aLength);
541     }
542 
543     /**
544      * Enables / Disables the functions for DHCPv6 PD.
545      *
546      * @param[in] aEnabled  Whether to accept platform generated RA messages.
547      *
548      */
SetDhcp6PdEnabled(bool aEnabled)549     void SetDhcp6PdEnabled(bool aEnabled) { return mPdPrefixManager.SetEnabled(aEnabled); }
550 
551     /**
552      * Returns the state of accpeting RouterAdvertisement messages on platform interface.
553      *
554      * @retval kDhcp6PdStateRunning  DHCPv6 PD should be enabled and running on this border router.
555      * @retval kDhcp6PdStateDisabled DHCPv6 PD should be disabled on this border router..
556      *
557      */
GetDhcp6PdState(void) const558     Dhcp6PdState GetDhcp6PdState(void) const { return mPdPrefixManager.GetState(); }
559 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
560 
561 private:
562     static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES;
563 
564     static constexpr uint8_t kOmrPrefixLength    = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits.
565     static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits.
566     static constexpr uint8_t kBrUlaPrefixLength  = 48;                    // The length of a BR ULA prefix. In bits.
567     static constexpr uint8_t kNat64PrefixLength  = 96;                    // The length of a NAT64 prefix. In bits.
568 
569     static constexpr uint16_t kOmrPrefixSubnetId   = 1; // The subnet ID of an OMR prefix within a BR ULA prefix.
570     static constexpr uint16_t kNat64PrefixSubnetId = 2; // The subnet ID of a NAT64 prefix within a BR ULA prefix.
571 
572     // The maximum number of initial Router Advertisements.
573     static constexpr uint32_t kMaxInitRtrAdvertisements = 3;
574 
575     static constexpr uint32_t kDefaultOmrPrefixLifetime    = 1800; // The default OMR prefix valid lifetime. In sec.
576     static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800; // The default on-link prefix valid lifetime. In sec.
577     static constexpr uint32_t kDefaultNat64PrefixLifetime  = 300;  // The default NAT64 prefix valid lifetime. In sec.
578     static constexpr uint32_t kMaxRtrAdvInterval           = 600;  // Max Router Advertisement Interval. In sec.
579     static constexpr uint32_t kMinRtrAdvInterval           = kMaxRtrAdvInterval / 3; // Min RA Interval. In sec.
580     static constexpr uint32_t kMaxInitRtrAdvInterval       = 16;                     // Max Initial RA Interval. In sec.
581     static constexpr uint32_t kRaReplyJitter               = 500;  // Jitter for sending RA after rx RS. In msec.
582     static constexpr uint32_t kPolicyEvaluationMinDelay    = 2000; // Min delay for policy evaluation. In msec.
583     static constexpr uint32_t kPolicyEvaluationMaxDelay    = 4000; // Max delay for policy evaluation. In msec.
584     static constexpr uint32_t kMinDelayBetweenRtrAdvs      = 3000; // Min delay (msec) between consecutive RAs.
585 
586     // The STALE_RA_TIME in seconds. The Routing Manager will consider the prefixes
587     // and learned RA parameters STALE when they are not refreshed in STALE_RA_TIME
588     // seconds. The Routing Manager will then start Router Solicitation to verify
589     // that the STALE prefix is not being advertised anymore and remove the STALE
590     // prefix.
591     // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`].
592     static constexpr uint32_t kRtrAdvStaleTime = 1800;
593 
594     static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals");
595     static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime");
596     static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime");
597     static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime,
598                   "invalid RA STALE time");
599     static_assert(kPolicyEvaluationMaxDelay > kPolicyEvaluationMinDelay,
600                   "kPolicyEvaluationMaxDelay must be larger than kPolicyEvaluationMinDelay");
601 
602     using Option                 = Ip6::Nd::Option;
603     using PrefixInfoOption       = Ip6::Nd::PrefixInfoOption;
604     using RouteInfoOption        = Ip6::Nd::RouteInfoOption;
605     using RaFlagsExtOption       = Ip6::Nd::RaFlagsExtOption;
606     using RouterAdvert           = Ip6::Nd::RouterAdvert;
607     using NeighborAdvertMessage  = Ip6::Nd::NeighborAdvertMessage;
608     using NeighborSolicitMessage = Ip6::Nd::NeighborSolicitMessage;
609     using RouterSolicitMessage   = Ip6::Nd::RouterSolicitMessage;
610 
611     enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()`
612     {
613         kInvalidateAllPrevPrefixes,
614         kAdvPrefixesFromNetData,
615     };
616 
617     enum ScheduleMode : uint8_t // Used in `ScheduleRoutingPolicyEvaluation()`
618     {
619         kImmediately,
620         kForNextRa,
621         kAfterRandomDelay,
622         kToReplyToRs,
623     };
624 
625     void HandleDiscoveredPrefixTableChanged(void); // Declare early so we can use in `mSignalTask`
HandleDiscoveredPrefixTableEntryTimer(void)626     void HandleDiscoveredPrefixTableEntryTimer(void) { mDiscoveredPrefixTable.HandleEntryTimer(); }
HandleDiscoveredPrefixTableRouterTimer(void)627     void HandleDiscoveredPrefixTableRouterTimer(void) { mDiscoveredPrefixTable.HandleRouterTimer(); }
628 
629 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
630     class PdPrefixManager; // For DiscoveredPrefixTable::Entry
631 #endif
632 
633     class DiscoveredPrefixTable : public InstanceLocator
634     {
635         // This class maintains the discovered on-link and route prefixes
636         // from the received RA messages by processing PIO and RIO options
637         // from the message. It takes care of processing the RA message but
638         // delegates the decision whether to include or exclude a prefix to
639         // `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()`
640         // and `ShouldProcessRouteInfoOption()` methods.
641         //
642         // It manages the lifetime of the discovered entries and publishes
643         // and unpublishes the prefixes in the Network Data (as external
644         // route) as they are added or removed.
645         //
646         // When there is any change in the table (an entry is added, removed,
647         // or modified), it signals the change to `RoutingManager` by calling
648         // `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is
649         // used for signalling which ensures that if there are multiple
650         // changes within the same flow of execution, the callback is
651         // invoked after all the changes are processed.
652 
653 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
654         friend class PdPrefixManager; // For DiscoveredPrefixTable::Entry
655 #endif
656 
657     public:
658         explicit DiscoveredPrefixTable(Instance &aInstance);
659 
660         void ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage, const Ip6::Address &aSrcAddress);
661         void ProcessNeighborAdvertMessage(const NeighborAdvertMessage &aNaMessage);
662 
663         bool ContainsDefaultOrNonUlaRoutePrefix(void) const;
664         bool ContainsNonUlaOnLinkPrefix(void) const;
665         bool ContainsUlaOnLinkPrefix(void) const;
666 
667         void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
668 
669         void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix);
670         void RemoveRoutePrefix(const Ip6::Prefix &aPrefix);
671 
672         void RemoveAllEntries(void);
673         void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold);
674 
675         TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
676 
677         void DetermineAndSetFlags(RouterAdvert::Header &aHeader) const;
678 
679         void  InitIterator(PrefixTableIterator &aIterator) const;
680         Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
681         Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
682 
683         void HandleEntryTimer(void);
684         void HandleRouterTimer(void);
685 
686     private:
687         static constexpr uint32_t kFavoredOnLinkPrefixMinPreferredLifetime = 1800; // In sec.
688 
689 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
690         static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
691         static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
692 #endif
693 
694         class Entry : public LinkedListEntry<Entry>,
695                       public Unequatable<Entry>,
696 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
697                       public Heap::Allocatable<Entry>,
698 #endif
699                       private Clearable<Entry>
700         {
701             friend class LinkedListEntry<Entry>;
702             friend class Clearable<Entry>;
703 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
704             friend class PdPrefixManager;
705 #endif
706 
707         public:
708             enum Type : uint8_t
709             {
710                 kTypeOnLink,
711                 kTypeRoute,
712             };
713 
714             struct Matcher
715             {
Matcherot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::Matcher716                 Matcher(const Ip6::Prefix &aPrefix, Type aType)
717                     : mPrefix(aPrefix)
718                     , mType(aType)
719                 {
720                 }
721 
722                 const Ip6::Prefix &mPrefix;
723                 Type               mType;
724             };
725 
726             struct Checker
727             {
728                 enum Mode : uint8_t
729                 {
730                     kIsUla,
731                     kIsNotUla,
732                 };
733 
Checkerot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::Checker734                 Checker(Mode aMode, Type aType)
735                     : mMode(aMode)
736                     , mType(aType)
737 
738                 {
739                 }
740 
741                 Mode mMode;
742                 Type mType;
743             };
744 
745             struct ExpirationChecker
746             {
ExpirationCheckerot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Entry::ExpirationChecker747                 explicit ExpirationChecker(TimeMilli aNow)
748                     : mNow(aNow)
749                 {
750                 }
751 
752                 TimeMilli mNow;
753             };
754 
755             void               SetFrom(const RouterAdvert::Header &aRaHeader);
756             void               SetFrom(const PrefixInfoOption &aPio);
757             void               SetFrom(const RouteInfoOption &aRio);
GetType(void) const758             Type               GetType(void) const { return mType; }
IsOnLinkPrefix(void) const759             bool               IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); }
IsRoutePrefix(void) const760             bool               IsRoutePrefix(void) const { return (mType == kTypeRoute); }
GetPrefix(void) const761             const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
GetLastUpdateTime(void) const762             const TimeMilli   &GetLastUpdateTime(void) const { return mLastUpdateTime; }
GetValidLifetime(void) const763             uint32_t           GetValidLifetime(void) const { return mValidLifetime; }
ClearValidLifetime(void)764             void               ClearValidLifetime(void) { mValidLifetime = 0; }
765             TimeMilli          GetExpireTime(void) const;
766             TimeMilli          GetStaleTime(void) const;
767             RoutePreference    GetPreference(void) const;
768             bool               operator==(const Entry &aOther) const;
769             bool               Matches(const Matcher &aMatcher) const;
770             bool               Matches(const Checker &aChecker) const;
771             bool               Matches(const ExpirationChecker &aChecker) const;
772 
773             // Methods to use when `IsOnLinkPrefix()`
GetPreferredLifetime(void) const774             uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; }
ClearPreferredLifetime(void)775             void     ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; }
776             bool     IsDeprecated(void) const;
777             void     AdoptValidAndPreferredLifetimesFrom(const Entry &aEntry);
778 
779             // Method to use when `!IsOnlinkPrefix()`
GetRoutePreference(void) const780             RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; }
781 
782         private:
783             static uint32_t CalculateExpireDelay(uint32_t aValidLifetime);
784 
785             Entry      *mNext;
786             Ip6::Prefix mPrefix;
787             Type        mType;
788             TimeMilli   mLastUpdateTime;
789             uint32_t    mValidLifetime;
790             union
791             {
792                 uint32_t        mPreferredLifetime; // Applicable when prefix is on-link.
793                 RoutePreference mRoutePreference;   // Applicable when prefix is not on-link
794             } mShared;
795         };
796 
797         struct Router : public LinkedListEntry<Router>,
798 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
799                         public Heap::Allocatable<Router>,
800 #endif
801                         public Clearable<Router>
802         {
803             // The timeout (in msec) for router staying in active state
804             // before starting the Neighbor Solicitation (NS) probes.
805             static constexpr uint32_t kActiveTimeout = OPENTHREAD_CONFIG_BORDER_ROUTING_ROUTER_ACTIVE_CHECK_TIMEOUT;
806 
807             static constexpr uint8_t  kMaxNsProbes          = 5;    // Max number of NS probe attempts.
808             static constexpr uint32_t kNsProbeRetryInterval = 1000; // In msec. Time between NS probe attempts.
809             static constexpr uint32_t kNsProbeTimeout       = 2000; // In msec. Max Wait time after last NS probe.
810             static constexpr uint32_t kJitter               = 2000; // In msec. Jitter to randomize probe starts.
811 
812             static_assert(kMaxNsProbes < 255, "kMaxNsProbes MUST not be 255");
813 
814             enum EmptyChecker : uint8_t
815             {
816                 kContainsNoEntriesOrFlags
817             };
818 
Matchesot::BorderRouter::RoutingManager::DiscoveredPrefixTable::Router819             bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
820             bool Matches(EmptyChecker aChecker) const;
821             void CopyInfoTo(RouterEntry &aEntry) const;
822 
823             Router           *mNext;
824             Ip6::Address      mAddress;
825             LinkedList<Entry> mEntries;
826             TimeMilli         mTimeout;
827             uint8_t           mNsProbeCount;
828             bool              mManagedAddressConfigFlag : 1;
829             bool              mOtherConfigFlag : 1;
830             bool              mStubRouterFlag : 1;
831         };
832 
833         class Iterator : public PrefixTableIterator
834         {
835         public:
836             enum AdvanceMode : uint8_t
837             {
838                 kToNextEntry,
839                 kToNextRouter,
840             };
841 
842             void Init(const LinkedList<Router> &aRouters);
843             void Advance(AdvanceMode aMode);
844 
GetRouter(void) const845             const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); }
GetEntry(void) const846             const Entry  *GetEntry(void) const { return static_cast<const Entry *>(mPtr2); }
GetInitTime(void) const847             TimeMilli     GetInitTime(void) const { return TimeMilli(mData32); }
848 
849         private:
SetRouter(const Router * aRouter)850             void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
SetEntry(const Entry * aEntry)851             void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
SetInitTime(void)852             void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
853         };
854 
855         void         ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter);
856         void         ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter);
857         void         ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter);
858         void         ProcessRaFlagsExtOption(const RaFlagsExtOption &aFlagsOption, Router &aRouter);
859         bool         Contains(const Entry::Checker &aChecker) const;
860         void         RemovePrefix(const Entry::Matcher &aMatcher);
861         void         RemoveOrDeprecateEntriesFromInactiveRouters(void);
862         void         RemoveRoutersWithNoEntriesOrFlags(void);
863         void         FreeRouters(LinkedList<Router> &aRouters);
864         void         FreeEntries(LinkedList<Entry> &aEntries);
865         void         UpdateNetworkDataOnChangeTo(Entry &aEntry);
866         const Entry *FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix) const;
867         void         RemoveExpiredEntries(void);
868         void         SignalTableChanged(void);
869         void         UpdateRouterOnRx(Router &aRouter);
870         void         SendNeighborSolicitToRouter(const Router &aRouter);
871 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
AllocateRouter(void)872         Router *AllocateRouter(void) { return Router::Allocate(); }
AllocateEntry(void)873         Entry  *AllocateEntry(void) { return Entry::Allocate(); }
FreeRouter(Router & aRouter)874         void    FreeRouter(Router &aRouter) { aRouter.Free(); }
FreeEntry(Entry & aEntry)875         void    FreeEntry(Entry &aEntry) { aEntry.Free(); }
876 #else
AllocateRouter(void)877         Router *AllocateRouter(void) { return mRouterPool.Allocate(); }
AllocateEntry(void)878         Entry  *AllocateEntry(void) { return mEntryPool.Allocate(); }
FreeRouter(Router & aRouter)879         void    FreeRouter(Router &aRouter) { mRouterPool.Free(aRouter); }
FreeEntry(Entry & aEntry)880         void    FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); }
881 #endif
882 
883         using SignalTask  = TaskletIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableChanged>;
884         using EntryTimer  = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableEntryTimer>;
885         using RouterTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableRouterTimer>;
886 
887         LinkedList<Router> mRouters;
888         EntryTimer         mEntryTimer;
889         RouterTimer        mRouterTimer;
890         SignalTask         mSignalTask;
891 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
892         Pool<Entry, kMaxEntries>  mEntryPool;
893         Pool<Router, kMaxRouters> mRouterPool;
894 #endif
895     };
896 
897     class OmrPrefixManager;
898 
899     class OmrPrefix : public Clearable<OmrPrefix>
900     {
901         friend class OmrPrefixManager;
902 
903     public:
OmrPrefix(void)904         OmrPrefix(void) { Clear(); }
905 
IsEmpty(void) const906         bool               IsEmpty(void) const { return (mPrefix.GetLength() == 0); }
GetPrefix(void) const907         const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
GetPreference(void) const908         RoutePreference    GetPreference(void) const { return mPreference; }
IsDomainPrefix(void) const909         bool               IsDomainPrefix(void) const { return mIsDomainPrefix; }
910 
911     protected:
912         Ip6::Prefix     mPrefix;
913         RoutePreference mPreference;
914         bool            mIsDomainPrefix;
915     };
916 
917     class FavoredOmrPrefix : public OmrPrefix
918     {
919         friend class OmrPrefixManager;
920 
921     public:
922         bool IsInfrastructureDerived(void) const;
923 
924     private:
925         void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
926         void SetFrom(const OmrPrefix &aOmrPrefix);
927         bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const;
928     };
929 
930     class OmrPrefixManager : public InstanceLocator
931     {
932     public:
933         explicit OmrPrefixManager(Instance &aInstance);
934 
935         void                    Init(const Ip6::Prefix &aBrUlaPrefix);
936         void                    Start(void);
937         void                    Stop(void);
938         void                    Evaluate(void);
939         void                    UpdateDefaultRouteFlag(bool aDefaultRoute);
940         bool                    ShouldAdvertiseLocalAsRio(void) const;
GetGeneratedPrefix(void) const941         const Ip6::Prefix      &GetGeneratedPrefix(void) const { return mGeneratedPrefix; }
GetLocalPrefix(void) const942         const OmrPrefix        &GetLocalPrefix(void) const { return mLocalPrefix; }
GetFavoredPrefix(void) const943         const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; }
944 
945     private:
946         static constexpr uint16_t kInfoStringSize = 85;
947 
948         typedef String<kInfoStringSize> InfoString;
949 
950         void       DetermineFavoredPrefix(void);
951         Error      AddLocalToNetData(void);
952         Error      AddOrUpdateLocalInNetData(void);
953         void       RemoveLocalFromNetData(void);
954         InfoString LocalToString(void) const;
955 
956         OmrPrefix        mLocalPrefix;
957         Ip6::Prefix      mGeneratedPrefix;
958         FavoredOmrPrefix mFavoredPrefix;
959         bool             mIsLocalAddedInNetData;
960         bool             mDefaultRoute;
961     };
962 
HandleOnLinkPrefixManagerTimer(void)963     void HandleOnLinkPrefixManagerTimer(void) { mOnLinkPrefixManager.HandleTimer(); }
964 
965     class OnLinkPrefixManager : public InstanceLocator
966     {
967     public:
968         explicit OnLinkPrefixManager(Instance &aInstance);
969 
970         // Max number of old on-link prefixes to retain to deprecate.
971         static constexpr uint16_t kMaxOldPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES;
972 
973         void               Init(void);
974         void               Start(void);
975         void               Stop(void);
976         void               Evaluate(void);
GetLocalPrefix(void) const977         const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
GetFavoredDiscoveredPrefix(void) const978         const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; }
979         bool               IsInitalEvaluationDone(void) const;
980         void               HandleDiscoveredPrefixTableChanged(void);
981         bool               ShouldPublishUlaRoute(void) const;
982         Error              AppendAsPiosTo(RouterAdvert::TxMessage &aRaMessage);
983         bool               IsPublishingOrAdvertising(void) const;
984         void               HandleNetDataChange(void);
985         void               HandleExtPanIdChange(void);
986         void               HandleTimer(void);
987 
988     private:
989         enum State : uint8_t // State of `mLocalPrefix`
990         {
991             kIdle,
992             kPublishing,
993             kAdvertising,
994             kDeprecating,
995         };
996 
997         struct OldPrefix
998         {
Matchesot::BorderRouter::RoutingManager::OnLinkPrefixManager::OldPrefix999             bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
1000 
1001             Ip6::Prefix mPrefix;
1002             TimeMilli   mExpireTime;
1003         };
1004 
GetState(void) const1005         State GetState(void) const { return mState; }
1006         void  SetState(State aState);
1007         void  GenerateLocalPrefix(void);
1008         void  PublishAndAdvertise(void);
1009         void  Deprecate(void);
1010         void  ResetExpireTime(TimeMilli aNow);
1011         Error AppendCurPrefix(RouterAdvert::TxMessage &aRaMessage);
1012         Error AppendOldPrefixes(RouterAdvert::TxMessage &aRaMessage);
1013         void  DeprecateOldPrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime);
1014         void  SavePrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime);
1015 
1016         static const char *StateToString(State aState);
1017 
1018         using ExpireTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleOnLinkPrefixManagerTimer>;
1019 
1020         Ip6::Prefix                       mLocalPrefix;
1021         State                             mState;
1022         TimeMilli                         mExpireTime;
1023         Ip6::Prefix                       mFavoredDiscoveredPrefix;
1024         Array<OldPrefix, kMaxOldPrefixes> mOldLocalPrefixes;
1025         ExpireTimer                       mTimer;
1026     };
1027 
HandleRioAdvertiserimer(void)1028     void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); }
1029 
1030     class RioAdvertiser : public InstanceLocator
1031     {
1032         // Manages the list of prefixes advertised as RIO in emitted
1033         // RA. The RIO prefixes are discovered from on-mesh prefixes in
1034         // network data including OMR prefix from `OmrPrefixManager`.
1035         // It also handles deprecating removed prefixes.
1036 
1037     public:
1038         explicit RioAdvertiser(Instance &aInstance);
1039 
GetPreference(void) const1040         RoutePreference GetPreference(void) const { return mPreference; }
1041         void            SetPreference(RoutePreference aPreference);
1042         void            ClearPreference(void);
1043         void            HandleRoleChanged(void);
1044         Error           AppendRios(RouterAdvert::TxMessage &aRaMessage);
1045         Error           InvalidatPrevRios(RouterAdvert::TxMessage &aRaMessage);
HasAdvertised(const Ip6::Prefix & aPrefix) const1046         bool            HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); }
GetAdvertisedRioCount(void) const1047         uint16_t        GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); }
1048         void            HandleTimer(void);
1049 
1050     private:
1051         static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300);
1052 
1053         struct RioPrefix : public Clearable<RioPrefix>
1054         {
Matchesot::BorderRouter::RoutingManager::RioAdvertiser::RioPrefix1055             bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
1056 
1057             Ip6::Prefix mPrefix;
1058             bool        mIsDeprecating;
1059             TimeMilli   mExpirationTime;
1060         };
1061 
1062         struct RioPrefixArray :
1063 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1064             public Heap::Array<RioPrefix>
1065 #else
1066             public Array<RioPrefix, 2 * kMaxOnMeshPrefixes>
1067 #endif
1068         {
1069             void Add(const Ip6::Prefix &aPrefix);
1070         };
1071 
1072         void  SetPreferenceBasedOnRole(void);
1073         void  UpdatePreference(RoutePreference aPreference);
1074         Error AppendRio(const Ip6::Prefix &aPrefix, uint32_t aRouteLifetime, RouterAdvert::TxMessage &aRaMessage);
1075 
1076         using RioTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRioAdvertiserimer>;
1077 
1078         RioPrefixArray  mPrefixes;
1079         RioTimer        mTimer;
1080         RoutePreference mPreference;
1081         bool            mUserSetPreference;
1082     };
1083 
1084 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
HandleNat64PrefixManagerTimer(void)1085     void HandleNat64PrefixManagerTimer(void) { mNat64PrefixManager.HandleTimer(); }
1086 
1087     class Nat64PrefixManager : public InstanceLocator
1088     {
1089     public:
1090         // This class manages the NAT64 related functions including
1091         // generation of local NAT64 prefix, discovery of infra
1092         // interface prefix, maintaining the discovered prefix
1093         // lifetime, and selection of the NAT64 prefix to publish in
1094         // Network Data.
1095         //
1096         // Calling methods except GenerateLocalPrefix and SetEnabled
1097         // when disabled becomes no-op.
1098 
1099         explicit Nat64PrefixManager(Instance &aInstance);
1100 
1101         void         SetEnabled(bool aEnabled);
1102         Nat64::State GetState(void) const;
1103 
1104         void Start(void);
1105         void Stop(void);
1106 
1107         void               GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix);
GetLocalPrefix(void) const1108         const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
1109         const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const;
1110         void               Evaluate(void);
1111         void               HandleDiscoverDone(const Ip6::Prefix &aPrefix);
1112         void               HandleTimer(void);
1113 
1114     private:
1115         void Discover(void);
1116         void Publish(void);
1117 
1118         using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>;
1119 
1120         bool mEnabled;
1121 
1122         Ip6::Prefix     mInfraIfPrefix;       // The latest NAT64 prefix discovered on the infrastructure interface.
1123         Ip6::Prefix     mLocalPrefix;         // The local prefix (from BR ULA prefix).
1124         Ip6::Prefix     mPublishedPrefix;     // The prefix to publish in Net Data (empty or local or from infra-if).
1125         RoutePreference mPublishedPreference; // The published prefix preference.
1126         Nat64Timer      mTimer;
1127     };
1128 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
1129 
HandleRoutePublisherTimer(void)1130     void HandleRoutePublisherTimer(void) { mRoutePublisher.HandleTimer(); }
1131 
1132     class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data
1133     {
1134     public:
1135         explicit RoutePublisher(Instance &aInstance);
1136 
Start(void)1137         void Start(void) { Evaluate(); }
Stop(void)1138         void Stop(void) { Unpublish(); }
1139         void Evaluate(void);
1140 
1141         void UpdateAdvPioFlags(bool aAdvPioFlag);
1142 
GetPreference(void) const1143         RoutePreference GetPreference(void) const { return mPreference; }
1144         void            SetPreference(RoutePreference aPreference);
1145         void            ClearPreference(void);
1146 
1147         void HandleNotifierEvents(Events aEvents);
1148         void HandleTimer(void);
1149 
GetUlaPrefix(void)1150         static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); }
1151 
1152     private:
1153         static constexpr uint32_t kDelayBeforePrfUpdateOnLinkQuality3 = TimeMilli::SecToMsec(5 * 60);
1154 
1155         static const otIp6Prefix kUlaPrefix;
1156 
1157         enum State : uint8_t
1158         {
1159             kDoNotPublish,   // Do not publish any routes in network data.
1160             kPublishDefault, // Publish "::/0" route in network data.
1161             kPublishUla,     // Publish "fc00::/7" route in network data.
1162         };
1163 
1164         void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const;
1165         void UpdatePublishedRoute(State aNewState);
1166         void Unpublish(void);
1167         void SetPreferenceBasedOnRole(void);
1168         void UpdatePreference(RoutePreference aPreference);
1169 
1170         static const char *StateToString(State aState);
1171 
1172         using DelayTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRoutePublisherTimer>;
1173 
1174         State           mState;
1175         RoutePreference mPreference;
1176         bool            mUserSetPreference;
1177         bool            mAdvPioFlag;
1178         DelayTimer      mTimer;
1179     };
1180 
1181     struct RaInfo
1182     {
1183         // Tracks info about emitted RA messages:
1184         //
1185         // - Number of RAs sent
1186         // - Last RA TX time
1187         // - Hashes of last TX RAs (to tell if a received RA is from
1188         //   `RoutingManager` itself)
1189         // - RA header to use, and
1190         // - Whether the RA header is discovered from receiving RAs
1191         //   from the host itself.
1192         //
1193         // This ensures that if an entity on host is advertising certain
1194         // info in its RA header (e.g., a default route), the RAs we
1195         // emit from `RoutingManager` also include the same header.
1196 
1197         typedef Crypto::Sha256::Hash Hash;
1198 
1199         static constexpr uint16_t kNumHashEntries = 5;
1200 
RaInfoot::BorderRouter::RoutingManager::RaInfo1201         RaInfo(void)
1202             : mHeaderUpdateTime(TimerMilli::GetNow())
1203             , mIsHeaderFromHost(false)
1204             , mTxCount(0)
1205             , mLastTxTime(TimerMilli::GetNow() - kMinDelayBetweenRtrAdvs)
1206             , mLastHashIndex(0)
1207         {
1208         }
1209 
1210         void        IncrementTxCountAndSaveHash(const InfraIf::Icmp6Packet &aRaMessage);
1211         bool        IsRaFromManager(const Ip6::Nd::RouterAdvert::RxMessage &aRaMessage) const;
1212         static void CalculateHash(const InfraIf::Icmp6Packet &aRaMessage, Hash &aHash);
1213 
1214         RouterAdvert::Header mHeader;
1215         TimeMilli            mHeaderUpdateTime;
1216         bool                 mIsHeaderFromHost;
1217         uint32_t             mTxCount;
1218         TimeMilli            mLastTxTime;
1219         Hash                 mHashes[kNumHashEntries];
1220         uint16_t             mLastHashIndex;
1221     };
1222 
HandleRsSenderTimer(void)1223     void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); }
1224 
1225     class RsSender : public InstanceLocator
1226     {
1227     public:
1228         // This class implements tx of Router Solicitation (RS)
1229         // messages to discover other routers. `Start()` schedules
1230         // a cycle of RS transmissions of `kMaxTxCount` separated
1231         // by `kTxInterval`. At the end of cycle the callback
1232         // `HandleRsSenderFinished()` is invoked to inform end of
1233         // the cycle to `RoutingManager`.
1234 
1235         explicit RsSender(Instance &aInstance);
1236 
IsInProgress(void) const1237         bool IsInProgress(void) const { return mTimer.IsRunning(); }
1238         void Start(void);
1239         void Stop(void);
1240         void HandleTimer(void);
1241 
1242     private:
1243         // All time intervals are in msec.
1244         static constexpr uint32_t kMaxStartDelay     = 1000;        // Max random delay to send the first RS.
1245         static constexpr uint32_t kTxInterval        = 4000;        // Interval between RS tx.
1246         static constexpr uint32_t kRetryDelay        = kTxInterval; // Interval to wait to retry a failed RS tx.
1247         static constexpr uint32_t kWaitOnLastAttempt = 1000;        // Wait interval after last RS tx.
1248         static constexpr uint8_t  kMaxTxCount        = 3;           // Number of RS tx in one cycle.
1249 
1250         Error SendRs(void);
1251 
1252         using RsTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRsSenderTimer>;
1253 
1254         uint8_t   mTxCount;
1255         RsTimer   mTimer;
1256         TimeMilli mStartTime;
1257     };
1258 
1259 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
HandlePdPrefixManagerTimer(void)1260     void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); }
1261 
1262     class PdPrefixManager : public InstanceLocator
1263     {
1264     public:
1265         // This class implements handling (including management of the lifetime) of the prefix obtained from platform's
1266         // DHCPv6 PD client. We expect the platform will send ICMP6 RA messages to the platform's interface for the
1267         // information of the prefix.
1268         // This class manages the state of the PD prefix in OmrPrefixManager
1269 
1270         explicit PdPrefixManager(Instance &aInstance);
1271 
1272         void               SetEnabled(bool aEnabled);
Start(void)1273         void               Start(void) { StartStop(/* aStart= */ true); }
Stop(void)1274         void               Stop(void) { StartStop(/* aStart= */ false); }
IsRunning(void) const1275         bool               IsRunning(void) const { return GetState() == Dhcp6PdState::kDhcp6PdStateRunning; }
HasPrefix(void) const1276         bool               HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); }
GetPrefix(void) const1277         const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); }
1278         Dhcp6PdState       GetState(void) const;
1279 
1280         void  ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength);
1281         Error GetPrefixInfo(PrefixTableEntry &aInfo) const;
1282         Error GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const;
HandleTimer(void)1283         void  HandleTimer(void) { WithdrawPrefix(); }
1284 
1285         static const char *StateToString(Dhcp6PdState aState);
1286 
IsValidPdPrefix(const Ip6::Prefix & aPrefix)1287         static bool IsValidPdPrefix(const Ip6::Prefix &aPrefix)
1288         {
1289             // We should accept ULA prefix since it could be used by the internet infrastructure like NAT64.
1290             return aPrefix.GetLength() != 0 && aPrefix.GetLength() <= kOmrPrefixLength && !aPrefix.IsLinkLocal() &&
1291                    !aPrefix.IsMulticast();
1292         }
1293 
1294     private:
1295         Error Process(const RouterAdvert::RxMessage &aMessage);
1296         void  EvaluateStateChange(Dhcp6PdState aOldState);
1297         void  WithdrawPrefix(void);
1298         void  StartStop(bool aStart);
1299 
1300         using PlatformOmrPrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>;
1301 
1302         bool                         mEnabled;
1303         bool                         mIsRunning;
1304         uint32_t                     mNumPlatformPioProcessed;
1305         uint32_t                     mNumPlatformRaReceived;
1306         TimeMilli                    mLastPlatformRaTime;
1307         PlatformOmrPrefixTimer       mTimer;
1308         DiscoveredPrefixTable::Entry mPrefix;
1309     };
1310 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1311 
1312     void  EvaluateState(void);
1313     void  Start(void);
1314     void  Stop(void);
1315     void  HandleNotifierEvents(Events aEvents);
IsInitialized(void) const1316     bool  IsInitialized(void) const { return mInfraIf.IsInitialized(); }
IsEnabled(void) const1317     bool  IsEnabled(void) const { return mIsEnabled; }
1318     Error LoadOrGenerateRandomBrUlaPrefix(void);
1319 
1320     void EvaluateRoutingPolicy(void);
1321     bool IsInitalPolicyEvaluationDone(void) const;
1322     void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
1323     void HandleRsSenderFinished(TimeMilli aStartTime);
1324     void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
1325 
1326     void HandleDiscoveredPrefixStaleTimer(void);
1327 
1328     void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
1329     void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
1330     void HandleNeighborAdvertisement(const InfraIf::Icmp6Packet &aPacket);
1331     bool ShouldProcessPrefixInfoOption(const PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix);
1332     bool ShouldProcessRouteInfoOption(const RouteInfoOption &aRio, const Ip6::Prefix &aPrefix);
1333     void UpdateDiscoveredPrefixTableOnNetDataChange(void);
1334     bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
1335     bool NetworkDataContainsUlaRoute(void) const;
1336     void UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRouterAdvertMessage);
1337     void ResetDiscoveredPrefixStaleTimer(void);
1338 
1339     static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
1340     static bool IsValidOnLinkPrefix(const PrefixInfoOption &aPio);
1341     static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
1342 
1343     static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
1344     static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference);
1345 
1346     using RoutingPolicyTimer         = TimerMilliIn<RoutingManager, &RoutingManager::EvaluateRoutingPolicy>;
1347     using DiscoveredPrefixStaleTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixStaleTimer>;
1348 
1349     // Indicates whether the Routing Manager is running (started).
1350     bool mIsRunning;
1351 
1352     // Indicates whether the Routing manager is enabled. The Routing
1353     // Manager will be stopped if we are disabled.
1354     bool mIsEnabled;
1355 
1356     InfraIf mInfraIf;
1357 
1358     // The /48 BR ULA prefix loaded from local persistent storage or
1359     // randomly generated if none is found in persistent storage.
1360     Ip6::Prefix mBrUlaPrefix;
1361 
1362     OmrPrefixManager mOmrPrefixManager;
1363 
1364     RioAdvertiser   mRioAdvertiser;
1365     RoutePreference mRioPreference;
1366     bool            mUserSetRioPreference;
1367 
1368     OnLinkPrefixManager mOnLinkPrefixManager;
1369 
1370     DiscoveredPrefixTable mDiscoveredPrefixTable;
1371 
1372     RoutePublisher mRoutePublisher;
1373 
1374 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
1375     Nat64PrefixManager mNat64PrefixManager;
1376 #endif
1377 
1378 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1379     PdPrefixManager mPdPrefixManager;
1380 #endif
1381 
1382     RaInfo     mRaInfo;
1383     RsSender   mRsSender;
1384     Heap::Data mExtraRaOptions;
1385 
1386     DiscoveredPrefixStaleTimer mDiscoveredPrefixStaleTimer;
1387     RoutingPolicyTimer         mRoutingPolicyTimer;
1388 };
1389 
1390 } // namespace BorderRouter
1391 
1392 DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State);
1393 
1394 } // namespace ot
1395 
1396 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1397 
1398 #endif // ROUTING_MANAGER_HPP_
1399