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 #if !OPENTHREAD_CONFIG_UPTIME_ENABLE
51 #error "OPENTHREAD_CONFIG_UPTIME_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE"
52 #endif
53 
54 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE && !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
55 #error "TRACK_PEER_BR_INFO_ENABLE feature requires OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE"
56 #endif
57 
58 #include <openthread/border_routing.h>
59 #include <openthread/nat64.h>
60 #include <openthread/netdata.h>
61 
62 #include "border_router/infra_if.hpp"
63 #include "common/array.hpp"
64 #include "common/callback.hpp"
65 #include "common/equatable.hpp"
66 #include "common/error.hpp"
67 #include "common/heap_allocatable.hpp"
68 #include "common/heap_array.hpp"
69 #include "common/heap_data.hpp"
70 #include "common/linked_list.hpp"
71 #include "common/locator.hpp"
72 #include "common/message.hpp"
73 #include "common/notifier.hpp"
74 #include "common/owning_list.hpp"
75 #include "common/pool.hpp"
76 #include "common/string.hpp"
77 #include "common/timer.hpp"
78 #include "crypto/sha256.hpp"
79 #include "net/ip6.hpp"
80 #include "net/nat64_translator.hpp"
81 #include "net/nd6.hpp"
82 #include "thread/network_data.hpp"
83 
84 namespace ot {
85 namespace BorderRouter {
86 
87 extern "C" void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength);
88 extern "C" void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance                            *aInstance,
89                                                         const otBorderRoutingPrefixTableEntry *aPrefixInfo);
90 
91 /**
92  * Implements bi-directional routing between Thread and Infrastructure networks.
93  *
94  * The Border Routing manager works on both Thread interface and infrastructure interface.
95  * All ICMPv6 messages are sent/received on the infrastructure interface.
96  *
97  */
98 class RoutingManager : public InstanceLocator
99 {
100     friend class ot::Notifier;
101     friend class ot::Instance;
102 
103 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
104     friend void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength);
105     friend void otPlatBorderRoutingProcessDhcp6PdPrefix(otInstance                            *aInstance,
106                                                         const otBorderRoutingPrefixTableEntry *aPrefixInfo);
107 #endif
108 
109 public:
110     typedef NetworkData::RoutePreference          RoutePreference;     ///< Route preference (high, medium, low).
111     typedef otBorderRoutingPrefixTableIterator    PrefixTableIterator; ///< Prefix Table Iterator.
112     typedef otBorderRoutingPrefixTableEntry       PrefixTableEntry;    ///< Prefix Table Entry.
113     typedef otBorderRoutingRouterEntry            RouterEntry;         ///< Router Entry.
114     typedef otBorderRoutingPeerBorderRouterEntry  PeerBrEntry;         ///< Peer Border Router Entry.
115     typedef otPdProcessedRaInfo                   PdProcessedRaInfo;   ///< Data of PdProcessedRaInfo.
116     typedef otBorderRoutingRequestDhcp6PdCallback PdCallback;          ///< DHCPv6 PD callback.
117 
118     /**
119      * This constant specifies the maximum number of route prefixes that may be published by `RoutingManager`
120      * in Thread Network Data.
121      *
122      * This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`.
123      *
124      * The number of published entries accounts for:
125      * - Route prefix `fc00::/7` or `::/0`
126      * - One entry for NAT64 published prefix.
127      * - One extra entry for transitions.
128      *
129      */
130     static constexpr uint16_t kMaxPublishedPrefixes = 3;
131 
132     /**
133      * Represents the states of `RoutingManager`.
134      *
135      */
136     enum State : uint8_t
137     {
138         kStateUninitialized = OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Uninitialized.
139         kStateDisabled      = OT_BORDER_ROUTING_STATE_DISABLED,      ///< Initialized but disabled.
140         kStateStopped       = OT_BORDER_ROUTING_STATE_STOPPED,       ///< Initialized & enabled, but currently stopped.
141         kStateRunning       = OT_BORDER_ROUTING_STATE_RUNNING,       ///< Initialized, enabled, and running.
142     };
143 
144     /**
145      * This enumeration represents the states of DHCPv6 PD in `RoutingManager`.
146      *
147      */
148     enum Dhcp6PdState : uint8_t
149     {
150         kDhcp6PdStateDisabled = OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, ///< Disabled.
151         kDhcp6PdStateStopped  = OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED,  ///< Enabled, but currently stopped.
152         kDhcp6PdStateRunning  = OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING,  ///< Enabled, and running.
153     };
154 
155     /**
156      * Initializes the routing manager.
157      *
158      * @param[in]  aInstance  A OpenThread instance.
159      *
160      */
161     explicit RoutingManager(Instance &aInstance);
162 
163     /**
164      * Initializes the routing manager on given infrastructure interface.
165      *
166      * @param[in]  aInfraIfIndex      An infrastructure network interface index.
167      * @param[in]  aInfraIfIsRunning  A boolean that indicates whether the infrastructure
168      *                                interface is running.
169      *
170      * @retval  kErrorNone         Successfully started the routing manager.
171      * @retval  kErrorInvalidArgs  The index of the infra interface is not valid.
172      *
173      */
174     Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning);
175 
176     /**
177      * Enables/disables the Border Routing Manager.
178      *
179      * @note  The Border Routing Manager is enabled by default.
180      *
181      * @param[in]  aEnabled   A boolean to enable/disable the Border Routing Manager.
182      *
183      * @retval  kErrorInvalidState   The Border Routing Manager is not initialized yet.
184      * @retval  kErrorNone           Successfully enabled/disabled the Border Routing Manager.
185      *
186      */
187     Error SetEnabled(bool aEnabled);
188 
189     /**
190      * Indicates whether or not it is currently running.
191      *
192      * In order for the `RoutingManager` to be running it needs to be initialized and enabled, and device being
193      * attached.
194      *
195      * @retval TRUE  The RoutingManager is currently running.
196      * @retval FALSE The RoutingManager is not running.
197      *
198      */
IsRunning(void) const199     bool IsRunning(void) const { return mIsRunning; }
200 
201     /**
202      * Gets the state of `RoutingManager`.
203      *
204      * @returns The current state of `RoutingManager`.
205      *
206      */
207     State GetState(void) const;
208 
209     /**
210      * Requests the Border Routing Manager to stop.
211      *
212      * If Border Routing Manager is running, calling this method immediately stops it and triggers the preparation
213      * and sending of a final Router Advertisement (RA) message on infrastructure interface which deprecates and/or
214      * removes any previously advertised PIO/RIO prefixes. If Routing Manager is not running (or not enabled), no
215      * action is taken.
216      *
217      * Note that this method does not change whether the Routing Manager is enabled or disabled (see `SetEnabled()`).
218      * It stops the Routing Manager temporarily. After calling this method if the device role gets changes (device
219      * gets attached) and/or the infra interface state gets changed, the Routing Manager may be started again.
220      *
221      */
RequestStop(void)222     void RequestStop(void) { Stop(); }
223 
224     /**
225      * Gets the current preference used when advertising Route Info Options (RIO) in Router Advertisement
226      * messages sent over the infrastructure link.
227      *
228      * The RIO preference is determined as follows:
229      *
230      * - If explicitly set by user by calling `SetRouteInfoOptionPreference()`, the given preference is used.
231      * - Otherwise, it is determined based on device's role: Medium preference when in router/leader role and low
232      *   preference when in child role.
233      *
234      * @returns The current Route Info Option preference.
235      *
236      */
GetRouteInfoOptionPreference(void) const237     RoutePreference GetRouteInfoOptionPreference(void) const { return mRioAdvertiser.GetPreference(); }
238 
239     /**
240      * Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router
241      * Advertisement messages sent over the infrastructure link.
242      *
243      * After a call to this method, BR will use the given preference for all its advertised RIOs. The preference can be
244      * cleared by calling `ClearRouteInfoOptionPreference`()`.
245      *
246      * @param[in] aPreference   The route preference to use.
247      *
248      */
SetRouteInfoOptionPreference(RoutePreference aPreference)249     void SetRouteInfoOptionPreference(RoutePreference aPreference) { mRioAdvertiser.SetPreference(aPreference); }
250 
251     /**
252      * Clears a previously set preference value for advertised Route Info Options.
253      *
254      * After a call to this method, BR will use device role to determine the RIO preference: Medium preference when
255      * in router/leader role and low preference when in child role.
256      *
257      */
ClearRouteInfoOptionPreference(void)258     void ClearRouteInfoOptionPreference(void) { mRioAdvertiser.ClearPreference(); }
259 
260     /**
261      * Sets additional options to append at the end of emitted Router Advertisement (RA) messages.
262      *
263      * The content of @p aOptions is copied internally, so can be a temporary stack variable.
264      *
265      * Subsequent calls to this method will overwrite the previously set value.
266      *
267      * @param[in] aOptions   A pointer to the encoded options. Can be `nullptr` to clear.
268      * @param[in] aLength    Number of bytes in @p aOptions.
269      *
270      * @retval kErrorNone     Successfully set the extra option bytes.
271      * @retval kErrorNoBufs   Could not allocate buffer to save the buffer.
272      *
273      */
274     Error SetExtraRouterAdvertOptions(const uint8_t *aOptions, uint16_t aLength);
275 
276     /**
277      * Gets the current preference used for published routes in Network Data.
278      *
279      * The preference is determined as follows:
280      *
281      * - If explicitly set by user by calling `SetRoutePreference()`, the given preference is used.
282      * - Otherwise, it is determined automatically by `RoutingManager` based on the device's role and link quality.
283      *
284      * @returns The current published route preference.
285      *
286      */
GetRoutePreference(void) const287     RoutePreference GetRoutePreference(void) const { return mRoutePublisher.GetPreference(); }
288 
289     /**
290      * Explicitly sets the preference of published routes in Network Data.
291      *
292      * After a call to this method, BR will use the given preference. The preference can be cleared by calling
293      * `ClearRoutePreference`()`.
294      *
295      * @param[in] aPreference   The route preference to use.
296      *
297      */
SetRoutePreference(RoutePreference aPreference)298     void SetRoutePreference(RoutePreference aPreference) { mRoutePublisher.SetPreference(aPreference); }
299 
300     /**
301      * Clears a previously set preference value for published routes in Network Data.
302      *
303      * After a call to this method, BR will determine the preference automatically based on the device's role and
304      * link quality (to the parent when acting as end-device).
305      *
306      */
ClearRoutePreference(void)307     void ClearRoutePreference(void) { mRoutePublisher.ClearPreference(); }
308 
309     /**
310      * Returns the local generated off-mesh-routable (OMR) prefix.
311      *
312      * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR
313      * prefix.
314      *
315      * @param[out]  aPrefix  A reference to where the prefix will be output to.
316      *
317      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
318      * @retval  kErrorNone          Successfully retrieved the OMR prefix.
319      *
320      */
321     Error GetOmrPrefix(Ip6::Prefix &aPrefix) const;
322 
323     /**
324      * Returns the currently favored off-mesh-routable (OMR) prefix.
325      *
326      * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix.
327      *
328      * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the
329      * sense defined by `Ip6::Prefix`) is favored.
330      *
331      * @param[out] aPrefix         A reference to output the favored prefix.
332      * @param[out] aPreference     A reference to output the preference associated with the favored OMR prefix.
333      *
334      * @retval  kErrorInvalidState  The Border Routing Manager is not running yet.
335      * @retval  kErrorNone          Successfully retrieved the OMR prefix.
336      *
337      */
338     Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const;
339 
340     /**
341      * Returns the on-link prefix for the adjacent infrastructure link.
342      *
343      * The randomly generated 64-bit prefix will be advertised
344      * on the infrastructure link if there isn't already a usable
345      * on-link prefix being advertised on the link.
346      *
347      * @param[out]  aPrefix  A reference to where the prefix will be output to.
348      *
349      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
350      * @retval  kErrorNone          Successfully retrieved the local on-link prefix.
351      *
352      */
353     Error GetOnLinkPrefix(Ip6::Prefix &aPrefix) const;
354 
355     /**
356      * Returns the favored on-link prefix for the adjacent infrastructure link.
357      *
358      * The favored prefix is either a discovered prefix on the infrastructure link or the local on-link prefix.
359      *
360      * @param[out]  aPrefix  A reference to where the prefix will be output to.
361      *
362      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
363      * @retval  kErrorNone          Successfully retrieved the favored on-link prefix.
364      *
365      */
366     Error GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
367 
368 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
369     /**
370      * Gets the state of NAT64 prefix publishing.
371      *
372      * @retval  kStateDisabled   NAT64 is disabled.
373      * @retval  kStateNotRunning NAT64 is enabled, but is not running since routing manager is not running.
374      * @retval  kStateIdle       NAT64 is enabled, but the border router is not publishing a NAT64 prefix. Usually
375      *                           when there is another border router publishing a NAT64 prefix with higher
376      *                           priority.
377      * @retval  kStateActive     The Border router is publishing a NAT64 prefix.
378      *
379      */
GetNat64PrefixManagerState(void) const380     Nat64::State GetNat64PrefixManagerState(void) const { return mNat64PrefixManager.GetState(); }
381 
382     /**
383      * Enable or disable NAT64 prefix publishing.
384      *
385      * @param[in]  aEnabled   A boolean to enable/disable NAT64 prefix publishing.
386      *
387      */
388     void SetNat64PrefixManagerEnabled(bool aEnabled);
389 
390     /**
391      * Returns the local NAT64 prefix.
392      *
393      * @param[out]  aPrefix  A reference to where the prefix will be output to.
394      *
395      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
396      * @retval  kErrorNone          Successfully retrieved the NAT64 prefix.
397      *
398      */
399     Error GetNat64Prefix(Ip6::Prefix &aPrefix);
400 
401     /**
402      * Returns the currently favored NAT64 prefix.
403      *
404      * The favored NAT64 prefix can be discovered from infrastructure link or can be the local NAT64 prefix.
405      *
406      * @param[out] aPrefix           A reference to output the favored prefix.
407      * @param[out] aRoutePreference  A reference to output the preference associated with the favored prefix.
408      *
409      * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
410      * @retval  kErrorNone          Successfully retrieved the NAT64 prefix.
411      *
412      */
413     Error GetFavoredNat64Prefix(Ip6::Prefix &aPrefix, RoutePreference &aRoutePreference);
414 
415     /**
416      * Informs `RoutingManager` of the result of the discovery request of NAT64 prefix on infrastructure
417      * interface (`InfraIf::DiscoverNat64Prefix()`).
418      *
419      * @param[in]  aPrefix  The discovered NAT64 prefix on `InfraIf`.
420      *
421      */
HandleDiscoverNat64PrefixDone(const Ip6::Prefix & aPrefix)422     void HandleDiscoverNat64PrefixDone(const Ip6::Prefix &aPrefix) { mNat64PrefixManager.HandleDiscoverDone(aPrefix); }
423 
424 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
425 
426     /**
427      * Processes a received ICMPv6 message from the infrastructure interface.
428      *
429      * Malformed or undesired messages are dropped silently.
430      *
431      * @param[in]  aPacket        The received ICMPv6 packet.
432      * @param[in]  aSrcAddress    The source address this message is sent from.
433      *
434      */
435     void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
436 
437     /**
438      * Handles infrastructure interface state changes.
439      *
440      */
HandleInfraIfStateChanged(void)441     void HandleInfraIfStateChanged(void) { EvaluateState(); }
442 
443     /**
444      * Checks whether the on-mesh prefix configuration is a valid OMR prefix.
445      *
446      * @param[in] aOnMeshPrefixConfig  The on-mesh prefix configuration to check.
447      *
448      * @retval   TRUE    The prefix is a valid OMR prefix.
449      * @retval   FALSE   The prefix is not a valid OMR prefix.
450      *
451      */
452     static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
453 
454     /**
455      * Checks whether a given prefix is a valid OMR prefix.
456      *
457      * @param[in]  aPrefix  The prefix to check.
458      *
459      * @retval   TRUE    The prefix is a valid OMR prefix.
460      * @retval   FALSE   The prefix is not a valid OMR prefix.
461      *
462      */
463     static bool IsValidOmrPrefix(const Ip6::Prefix &aPrefix);
464 
465     /**
466      * Initializes a `PrefixTableIterator`.
467      *
468      * An iterator can be initialized again to start from the beginning of the table.
469      *
470      * When iterating over entries in the table, to ensure the entry update times are consistent, they are given
471      * relative to the time the iterator was initialized.
472      *
473      * @param[out] aIterator  The iterator to initialize.
474      *
475      */
InitPrefixTableIterator(PrefixTableIterator & aIterator) const476     void InitPrefixTableIterator(PrefixTableIterator &aIterator) const { mRxRaTracker.InitIterator(aIterator); }
477 
478     /**
479      * Iterates over entries in the discovered prefix table.
480      *
481      * @param[in,out] aIterator  An iterator.
482      * @param[out]    aEntry     A reference to the entry to populate.
483      *
484      * @retval kErrorNone        Got the next entry, @p aEntry is updated and @p aIterator is advanced.
485      * @retval kErrorNotFound    No more entries in the table.
486      *
487      */
GetNextPrefixTableEntry(PrefixTableIterator & aIterator,PrefixTableEntry & aEntry) const488     Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const
489     {
490         return mRxRaTracker.GetNextEntry(aIterator, aEntry);
491     }
492 
493     /**
494      * Iterates over discovered router entries on infrastructure link.
495      *
496      * @param[in,out] aIterator  An iterator.
497      * @param[out]    aEntry     A reference to the entry to populate.
498      *
499      * @retval kErrorNone        Got the next router info, @p aEntry is updated and @p aIterator is advanced.
500      * @retval kErrorNotFound    No more routers.
501      *
502      */
GetNextRouterEntry(PrefixTableIterator & aIterator,RouterEntry & aEntry) const503     Error GetNextRouterEntry(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
504     {
505         return mRxRaTracker.GetNextRouter(aIterator, aEntry);
506     }
507 
508 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
509 
510     /**
511      * Iterates over the peer BRs found in the Network Data.
512      *
513      * @param[in,out] aIterator  An iterator.
514      * @param[out]    aEntry     A reference to the entry to populate.
515      *
516      * @retval kErrorNone        Got the next peer BR info, @p aEntry is updated and @p aIterator is advanced.
517      * @retval kErrorNotFound    No more PR beers in the list.
518      *
519      */
GetNextPeerBrEntry(PrefixTableIterator & aIterator,PeerBrEntry & aEntry) const520     Error GetNextPeerBrEntry(PrefixTableIterator &aIterator, PeerBrEntry &aEntry) const
521     {
522         return mNetDataPeerBrTracker.GetNext(aIterator, aEntry);
523     }
524 
525     /**
526      * Returns the number of peer BRs found in the Network Data.
527      *
528      * The count does not include this device itself (when it itself is acting as a BR).
529      *
530      * @param[out] aMinAge   Reference to an `uint32_t` to return the minimum age among all peer BRs.
531      *                       Age is represented as seconds since appearance of the BR entry in the Network Data.
532      *
533      * @returns The number of peer BRs.
534      *
535      */
CountPeerBrs(uint32_t & aMinAge) const536     uint16_t CountPeerBrs(uint32_t &aMinAge) const { return mNetDataPeerBrTracker.CountPeerBrs(aMinAge); }
537 
538 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
539 
540 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
541     /**
542      * Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server.
543      *
544      * This should be called from `Srp::Server` when auto-enable mode is changed.
545      *
546      */
547     void HandleSrpServerAutoEnableMode(void);
548 #endif
549 
550 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
551     /**
552      * Enables / Disables the DHCPv6 Prefix Delegation.
553      *
554      * @param[in] aEnabled  Whether to enable or disable.
555      *
556      */
SetDhcp6PdEnabled(bool aEnabled)557     void SetDhcp6PdEnabled(bool aEnabled) { return mPdPrefixManager.SetEnabled(aEnabled); }
558 
559     /**
560      * Returns the state DHCPv6 Prefix Delegation manager.
561      *
562      * @returns The DHCPv6 PD state.
563      *
564      */
GetDhcp6PdState(void) const565     Dhcp6PdState GetDhcp6PdState(void) const { return mPdPrefixManager.GetState(); }
566 
567     /**
568      * Sets the callback to notify when DHCPv6 Prefix Delegation manager state gets changed.
569      *
570      * @param[in] aCallback  A pointer to a callback function
571      * @param[in] aContext   A pointer to arbitrary context information.
572      *
573      */
SetRequestDhcp6PdCallback(PdCallback aCallback,void * aContext)574     void SetRequestDhcp6PdCallback(PdCallback aCallback, void *aContext)
575     {
576         mPdPrefixManager.SetStateCallback(aCallback, aContext);
577     }
578 
579     /**
580      * Returns the DHCPv6-PD based off-mesh-routable (OMR) prefix.
581      *
582      * @param[out] aPrefixInfo      A reference to where the prefix info will be output to.
583      *
584      * @retval kErrorNone           Successfully retrieved the OMR prefix.
585      * @retval kErrorNotFound       There are no valid PD prefix on this BR.
586      * @retval kErrorInvalidState   The Border Routing Manager is not initialized yet.
587      *
588      */
589     Error GetPdOmrPrefix(PrefixTableEntry &aPrefixInfo) const;
590 
591     /**
592      * Returns platform generated RA message processed counters and information.
593      *
594      * @param[out] aPdProcessedRaInfo  A reference to where the PD processed RA info will be output to.
595      *
596      * @retval kErrorNone           Successfully retrieved the Info.
597      * @retval kErrorNotFound       There are no valid RA process info on this BR.
598      * @retval kErrorInvalidState   The Border Routing Manager is not initialized yet.
599      *
600      */
601     Error GetPdProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo);
602 
603 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
604 
605 #if OPENTHREAD_CONFIG_BORDER_ROUTING_REACHABILITY_CHECK_ICMP6_ERROR_ENABLE
606     /**
607      * Determines whether to send an ICMPv6 Destination Unreachable error to the sender based on reachability and
608      * source address.
609      *
610      * Specifically, if the Border Router (BR) decides to forward a unicast IPv6 message outside the AIL and the
611      * message's source address matches a BR-generated ULA OMR prefix (with low preference), and the destination is
612      * unreachable using this source address, then an ICMPv6 Destination Unreachable message is sent back to the sender.
613      *
614      * @param[in] aMessage    The message.
615      * @param[in] aIp6Header  The IPv6 header of @p aMessage.
616      *
617      */
618     void CheckReachabilityToSendIcmpError(const Message &aMessage, const Ip6::Header &aIp6Header);
619 #endif
620 
621 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE
622     /**
623      * Sets the local on-link prefix.
624      *
625      * This is intended for testing only and using it will make a device non-compliant with the Thread Specification.
626      *
627      * @param[in]  aPrefix      The on-link prefix to use.
628      *
629      */
SetOnLinkPrefix(const Ip6::Prefix & aPrefix)630     void SetOnLinkPrefix(const Ip6::Prefix &aPrefix) { mOnLinkPrefixManager.SetLocalPrefix(aPrefix); }
631 #endif
632 
633 private:
634     //------------------------------------------------------------------------------------------------------------------
635     // Constants
636 
637     static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES;
638 
639     // Prefix length in bits.
640     static constexpr uint8_t kOmrPrefixLength    = 64;
641     static constexpr uint8_t kOnLinkPrefixLength = 64;
642     static constexpr uint8_t kBrUlaPrefixLength  = 48;
643     static constexpr uint8_t kNat64PrefixLength  = 96;
644 
645     // Subnet IDs for OMR and NAT64 prefixes.
646     static constexpr uint16_t kOmrPrefixSubnetId   = 1;
647     static constexpr uint16_t kNat64PrefixSubnetId = 2;
648 
649     // Default valid lifetime. In seconds.
650     static constexpr uint32_t kDefaultOmrPrefixLifetime    = 1800;
651     static constexpr uint32_t kDefaultOnLinkPrefixLifetime = 1800;
652     static constexpr uint32_t kDefaultNat64PrefixLifetime  = 300;
653 
654     // The entry stale time in seconds.
655     //
656     // The amount of time that can pass after the last time an RA from
657     // a particular router has been received advertising an on-link
658     // or route prefix before we assume the prefix entry is stale.
659     //
660     // If multiple routers advertise the same on-link or route prefix,
661     // the stale time for the prefix is determined by the latest
662     // stale time among all corresponding entries. Stale time
663     // expiration triggers tx of Router Solicitation (RS) messages
664 
665     static constexpr uint32_t kStaleTime = 600; // 10 minutes.
666 
667     // RA transmission constants (in milliseconds). Initially, three
668     // RAs are sent with a short interval of 16 seconds (± 2 seconds
669     // jitter). Subsequently, a longer, regular RA beacon interval of
670     // 3 minutes (± 15 seconds jitter) is used. The actual interval is
671     // randomly selected within the range [interval - jitter,
672     // interval + jitter].
673 
674     static constexpr uint32_t kInitalRaTxCount    = 3;
675     static constexpr uint32_t kInitalRaInterval   = Time::kOneSecondInMsec * 16;
676     static constexpr uint16_t kInitialRaJitter    = Time::kOneSecondInMsec * 2;
677     static constexpr uint32_t kRaBeaconInterval   = Time::kOneSecondInMsec * 180; // 3 minutes
678     static constexpr uint16_t kRaBeaconJitter     = Time::kOneSecondInMsec * 15;
679     static constexpr uint32_t kMinDelayBetweenRas = Time::kOneSecondInMsec * 3;
680     static constexpr uint32_t kRsReplyInterval    = 250;
681     static constexpr uint16_t kRsReplyJitter      = 250;
682     static constexpr uint32_t kEvaluationInterval = Time::kOneSecondInMsec * 3;
683     static constexpr uint16_t kEvaluationJitter   = Time::kOneSecondInMsec * 1;
684 
685     //------------------------------------------------------------------------------------------------------------------
686     // Typedefs
687 
688     using Option                 = Ip6::Nd::Option;
689     using PrefixInfoOption       = Ip6::Nd::PrefixInfoOption;
690     using RouteInfoOption        = Ip6::Nd::RouteInfoOption;
691     using RaFlagsExtOption       = Ip6::Nd::RaFlagsExtOption;
692     using RouterAdvert           = Ip6::Nd::RouterAdvert;
693     using NeighborAdvertMessage  = Ip6::Nd::NeighborAdvertMessage;
694     using NeighborSolicitMessage = Ip6::Nd::NeighborSolicitMessage;
695     using RouterSolicitMessage   = Ip6::Nd::RouterSolicitMessage;
696 
697     //------------------------------------------------------------------------------------------------------------------
698     // Enumerations
699 
700     enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()`
701     {
702         kInvalidateAllPrevPrefixes,
703         kAdvPrefixesFromNetData,
704     };
705 
706     enum RouterAdvOrigin : uint8_t // Origin of a received Router Advert message.
707     {
708         kAnotherRouter,        // From another router on infra-if.
709         kThisBrRoutingManager, // From this BR generated by `RoutingManager` itself.
710         kThisBrOtherEntity,    // From this BR generated by another sw entity.
711     };
712 
713     enum ScheduleMode : uint8_t // Used in `ScheduleRoutingPolicyEvaluation()`
714     {
715         kImmediately,
716         kForNextRa,
717         kAfterRandomDelay,
718         kToReplyToRs,
719     };
720 
721     //------------------------------------------------------------------------------------------------------------------
722     // Nested types
723 
724     class LifetimedPrefix
725     {
726         // Represents an IPv6 prefix with its valid lifetime. Used as
727         // base class for `OnLinkPrefix` or `RoutePrefix`.
728 
729     public:
730         struct ExpirationChecker
731         {
ExpirationCheckerot::BorderRouter::RoutingManager::LifetimedPrefix::ExpirationChecker732             explicit ExpirationChecker(TimeMilli aNow) { mNow = aNow; }
733             TimeMilli mNow;
734         };
735 
GetPrefix(void) const736         const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
GetPrefix(void)737         Ip6::Prefix       &GetPrefix(void) { return mPrefix; }
GetLastUpdateTime(void) const738         const TimeMilli   &GetLastUpdateTime(void) const { return mLastUpdateTime; }
GetValidLifetime(void) const739         uint32_t           GetValidLifetime(void) const { return mValidLifetime; }
GetExpireTime(void) const740         TimeMilli          GetExpireTime(void) const { return CalculateExpirationTime(mValidLifetime); }
741 
Matches(const Ip6::Prefix & aPrefix) const742         bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
Matches(const ExpirationChecker & aChecker) const743         bool Matches(const ExpirationChecker &aChecker) const { return (GetExpireTime() <= aChecker.mNow); }
744 
SetStaleTimeCalculated(bool aFlag)745         void SetStaleTimeCalculated(bool aFlag) { mStaleTimeCalculated = aFlag; }
IsStaleTimeCalculated(void) const746         bool IsStaleTimeCalculated(void) const { return mStaleTimeCalculated; }
747 
SetDisregardFlag(bool aFlag)748         void SetDisregardFlag(bool aFlag) { mDisregard = aFlag; }
ShouldDisregard(void) const749         bool ShouldDisregard(void) const { return mDisregard; }
750 
751     protected:
752         LifetimedPrefix(void) = default;
753 
754         TimeMilli CalculateExpirationTime(uint32_t aLifetime) const;
755 
756         Ip6::Prefix mPrefix;
757         bool        mDisregard : 1;
758         bool        mStaleTimeCalculated : 1;
759         uint32_t    mValidLifetime;
760         TimeMilli   mLastUpdateTime;
761     };
762 
763     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
764 
765     class OnLinkPrefix : public LifetimedPrefix, public Clearable<OnLinkPrefix>
766     {
767     public:
768         void      SetFrom(const PrefixInfoOption &aPio);
769         void      SetFrom(const PrefixTableEntry &aPrefixTableEntry);
GetPreferredLifetime(void) const770         uint32_t  GetPreferredLifetime(void) const { return mPreferredLifetime; }
ClearPreferredLifetime(void)771         void      ClearPreferredLifetime(void) { mPreferredLifetime = 0; }
772         bool      IsDeprecated(void) const;
773         TimeMilli GetDeprecationTime(void) const;
774         TimeMilli GetStaleTime(void) const;
775         void      AdoptValidAndPreferredLifetimesFrom(const OnLinkPrefix &aPrefix);
776         void      CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const;
777         bool      IsFavoredOver(const Ip6::Prefix &aPrefix) const;
778 
779     private:
780         static constexpr uint32_t kFavoredMinPreferredLifetime = 1800; // In sec.
781 
782         uint32_t mPreferredLifetime;
783     };
784 
785     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
786 
787     class RoutePrefix : public LifetimedPrefix, public Clearable<RoutePrefix>
788     {
789     public:
790         void            SetFrom(const RouteInfoOption &aRio);
791         void            SetFrom(const RouterAdvert::Header &aRaHeader);
ClearValidLifetime(void)792         void            ClearValidLifetime(void) { mValidLifetime = 0; }
793         TimeMilli       GetStaleTime(void) const;
GetRoutePreference(void) const794         RoutePreference GetRoutePreference(void) const { return mRoutePreference; }
795         void            CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const;
796 
797     private:
798         RoutePreference mRoutePreference;
799     };
800 
801     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
802 
803 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
804 
805     class RxRaTracker;
806 
807     class NetDataPeerBrTracker : public InstanceLocator
808     {
809         friend class RxRaTracker;
810 
811     public:
812         explicit NetDataPeerBrTracker(Instance &aInstance);
813 
814         uint16_t CountPeerBrs(uint32_t &aMinAge) const;
815         Error    GetNext(PrefixTableIterator &aIterator, PeerBrEntry &aEntry) const;
816 
817         void HandleNotifierEvents(Events aEvents);
818 
819     private:
820         struct PeerBr : LinkedListEntry<PeerBr>, Heap::Allocatable<PeerBr>
821         {
822             struct Filter
823             {
Filterot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr::Filter824                 Filter(const NetworkData::Rlocs &aRlocs)
825                     : mExcludeRlocs(aRlocs)
826                 {
827                 }
828 
829                 const NetworkData::Rlocs &mExcludeRlocs;
830             };
831 
GetAgeot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr832             uint32_t GetAge(uint32_t aUptime) const { return aUptime - mDiscoverTime; }
Matchesot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr833             bool     Matches(uint16_t aRloc16) const { return mRloc16 == aRloc16; }
Matchesot::BorderRouter::RoutingManager::NetDataPeerBrTracker::PeerBr834             bool     Matches(const Filter &aFilter) const { return !aFilter.mExcludeRlocs.Contains(mRloc16); }
835 
836             PeerBr  *mNext;
837             uint16_t mRloc16;
838             uint32_t mDiscoverTime;
839         };
840 
841         OwningList<PeerBr> mPeerBrs;
842     };
843 
844 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
845 
846     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
847 
HandleRxRaTrackerSignalTask(void)848     void HandleRxRaTrackerSignalTask(void) { mRxRaTracker.HandleSignalTask(); }
HandleRxRaTrackerExpirationTimer(void)849     void HandleRxRaTrackerExpirationTimer(void) { mRxRaTracker.HandleExpirationTimer(); }
HandleRxRaTrackerStaleTimer(void)850     void HandleRxRaTrackerStaleTimer(void) { mRxRaTracker.HandleStaleTimer(); }
HandleRxRaTrackerRouterTimer(void)851     void HandleRxRaTrackerRouterTimer(void) { mRxRaTracker.HandleRouterTimer(); }
852 
853     class RxRaTracker : public InstanceLocator
854     {
855         // Processes received RA and NA messages tracking a table of active
856         // routers and their advertised on-link and route prefixes. Also
857         // manages prefix lifetimes and router reachability (sending NS probes
858         // as needed).
859         //
860         // When there is any change in the table (an entry is added, removed,
861         // or modified), it signals the change to `RoutingManager` by calling
862         // `HandleRaPrefixTableChanged()` callback. A `Tasklet` is used for
863         // signalling which ensures that if there are multiple changes within
864         // the same flow of execution, the callback is invoked after all the
865         // changes are processed.
866 
867         friend class NetDataPeerBrTracker;
868 
869     public:
870         explicit RxRaTracker(Instance &aInstance);
871 
872         void Start(void);
873         void Stop(void);
874 
875         void ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage,
876                                         const Ip6::Address            &aSrcAddress,
877                                         RouterAdvOrigin                aRaOrigin);
878         void ProcessNeighborAdvertMessage(const NeighborAdvertMessage &aNaMessage);
879 
880         // Decision factors
ContainsDefaultOrNonUlaRoutePrefix(void) const881         bool ContainsDefaultOrNonUlaRoutePrefix(void) const { return mDecisionFactors.mHasNonUlaRoute; }
ContainsNonUlaOnLinkPrefix(void) const882         bool ContainsNonUlaOnLinkPrefix(void) const { return mDecisionFactors.mHasNonUlaOnLink; }
ContainsUlaOnLinkPrefix(void) const883         bool ContainsUlaOnLinkPrefix(void) const { return mDecisionFactors.mHasUlaOnLink; }
884 
GetFavoredOnLinkPrefix(void) const885         const Ip6::Prefix &GetFavoredOnLinkPrefix(void) const { return mDecisionFactors.mFavoredOnLinkPrefix; }
886         void               SetHeaderFlagsOn(RouterAdvert::Header &aHeader) const;
887 
GetLocalRaHeaderToMirror(void) const888         const RouterAdvert::Header &GetLocalRaHeaderToMirror(void) const { return mLocalRaHeader; }
889 
890         bool IsAddressOnLink(const Ip6::Address &aAddress) const;
891         bool IsAddressReachableThroughExplicitRoute(const Ip6::Address &aAddress) const;
892 
893         // Iterating over discovered items
894         void  InitIterator(PrefixTableIterator &aIterator) const;
895         Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
896         Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
897 
898         // Callbacks notifying of changes
899         void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold);
900         void HandleLocalOnLinkPrefixChanged(void);
901         void HandleNetDataChange(void);
902 
903         // Tasklet or timer callbacks
904         void HandleSignalTask(void);
905         void HandleExpirationTimer(void);
906         void HandleStaleTimer(void);
907         void HandleRouterTimer(void);
908 
909     private:
910         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
911 
912         template <class Type>
913         struct Entry : public Type,
914                        public LinkedListEntry<Entry<Type>>,
915 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
916                        public Heap::Allocatable<Entry<Type>>
917 #else
918                        public InstanceLocatorInit
919 #endif
920         {
921 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
Initot::BorderRouter::RoutingManager::RxRaTracker::Entry922             void Init(Instance &aInstance) { InstanceLocatorInit::Init(aInstance); }
923             void Free(void);
924 #endif
925 
926             Entry<Type> *mNext;
927         };
928 
929         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
930 
931         struct Router : public Clearable<Router>
932         {
933             // Reachability timeout intervals before starting Neighbor
934             // Solicitation (NS) probes. Generally 60 seconds (± 2
935             // seconds jitter) is used. For peer BRs a longer timeout
936             // of 200 seconds (3 min and 20 seconds) is used. This is
937             // selected to be longer than regular RA beacon interval
938             // of 3 minutes (± 15 seconds jitter).
939 
940             static constexpr uint32_t kReachableInterval = OPENTHREAD_CONFIG_BORDER_ROUTING_ROUTER_ACTIVE_CHECK_TIMEOUT;
941             static constexpr uint32_t kPeerBrReachableInterval = Time::kOneSecondInMsec * 200;
942 
943             static constexpr uint8_t  kMaxNsProbes          = 5;    // Max number of NS probe attempts.
944             static constexpr uint32_t kNsProbeRetryInterval = 1000; // In msec. Time between NS probe attempts.
945             static constexpr uint32_t kNsProbeTimeout       = 2000; // In msec. Max Wait time after last NS probe.
946             static constexpr uint32_t kJitter               = 2000; // In msec. Jitter to randomize probe starts.
947 
948             static_assert(kMaxNsProbes < 255, "kMaxNsProbes MUST not be 255");
949 
950             typedef LifetimedPrefix::ExpirationChecker EmptyChecker;
951 
IsReachableot::BorderRouter::RoutingManager::RxRaTracker::Router952             bool IsReachable(void) const { return mNsProbeCount <= kMaxNsProbes; }
953             bool ShouldCheckReachability(void) const;
954             void ResetReachabilityState(void);
955             void DetermineReachabilityTimeout(void);
Matchesot::BorderRouter::RoutingManager::RxRaTracker::Router956             bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
957             bool Matches(const EmptyChecker &aChecker);
958             bool IsPeerBr(void) const;
959             void CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow, uint32_t aUptime) const;
960 
961             using OnLinkPrefixList = OwningList<Entry<OnLinkPrefix>>;
962             using RoutePrefixList  = OwningList<Entry<RoutePrefix>>;
963 
964             // `mDiscoverTime` tracks the initial discovery time of
965             // this router. To accommodate longer durations, the
966             // `Uptime` is used, as `TimeMilli` (which uses `uint32_t`
967             // intervals) would be limited to tracking ~ 49 days.
968             //
969             // `mLastUpdateTime` tracks the most recent time an RA or
970             // NA was received from this router. It is bounded due to
971             // the frequency of reachability checks, so we can safely
972             // use `TimeMilli` for it.
973 
974             Ip6::Address     mAddress;
975             OnLinkPrefixList mOnLinkPrefixes;
976             RoutePrefixList  mRoutePrefixes;
977             uint32_t         mDiscoverTime;
978             TimeMilli        mLastUpdateTime;
979             TimeMilli        mTimeoutTime;
980             uint8_t          mNsProbeCount;
981             bool             mManagedAddressConfigFlag : 1;
982             bool             mOtherConfigFlag : 1;
983             bool             mStubRouterFlag : 1;
984             bool             mIsLocalDevice : 1;
985             bool             mAllEntriesDisregarded : 1;
986         };
987 
988         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
989 
990         class Iterator : public PrefixTableIterator
991         {
992         public:
993             enum Type : uint8_t
994             {
995                 kUnspecified,
996                 kRouterIterator,
997                 kPrefixIterator,
998                 kPeerBrIterator,
999             };
1000 
1001             enum EntryType : uint8_t
1002             {
1003                 kOnLinkPrefix,
1004                 kRoutePrefix,
1005             };
1006 
1007             void                 Init(const Entry<Router> *aRoutersHead, uint32_t aUptime);
1008             Error                AdvanceToNextRouter(Type aType);
1009             Error                AdvanceToNextEntry(void);
GetInitUptime(void) const1010             uint32_t             GetInitUptime(void) const { return mData0; }
GetInitTime(void) const1011             TimeMilli            GetInitTime(void) const { return TimeMilli(mData1); }
GetType(void) const1012             Type                 GetType(void) const { return static_cast<Type>(mData2); }
GetRouter(void) const1013             const Entry<Router> *GetRouter(void) const { return static_cast<const Entry<Router> *>(mPtr1); }
GetEntryType(void) const1014             EntryType            GetEntryType(void) const { return static_cast<EntryType>(mData3); }
1015 
GetEntry(void) const1016             template <class PrefixType> const Entry<PrefixType> *GetEntry(void) const
1017             {
1018                 return static_cast<const Entry<PrefixType> *>(mPtr2);
1019             }
1020 
1021 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
1022             using PeerBr = NetDataPeerBrTracker::PeerBr;
1023 
1024             Error         AdvanceToNextPeerBr(const PeerBr *aPeerBrsHead);
GetPeerBrEntry(void) const1025             const PeerBr *GetPeerBrEntry(void) const { return static_cast<const PeerBr *>(mPtr2); }
1026 #endif
1027 
1028         private:
SetRouter(const Entry<Router> * aRouter)1029             void SetRouter(const Entry<Router> *aRouter) { mPtr1 = aRouter; }
SetInitUptime(uint32_t aUptime)1030             void SetInitUptime(uint32_t aUptime) { mData0 = aUptime; }
SetInitTime(void)1031             void SetInitTime(void) { mData1 = TimerMilli::GetNow().GetValue(); }
SetEntry(const void * aEntry)1032             void SetEntry(const void *aEntry) { mPtr2 = aEntry; }
HasEntry(void) const1033             bool HasEntry(void) const { return mPtr2 != nullptr; }
SetEntryType(EntryType aType)1034             void SetEntryType(EntryType aType) { mData3 = aType; }
SetType(Type aType)1035             void SetType(Type aType) { mData2 = aType; }
1036         };
1037 
1038         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
1039 
1040 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1041         static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
1042         static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
1043 
1044         union SharedEntry
1045         {
SharedEntry(void)1046             SharedEntry(void) { mNext = nullptr; }
SetNext(SharedEntry * aNext)1047             void               SetNext(SharedEntry *aNext) { mNext = aNext; }
GetNext(void)1048             SharedEntry       *GetNext(void) { return mNext; }
GetNext(void) const1049             const SharedEntry *GetNext(void) const { return mNext; }
1050 
1051             template <class PrefixType> Entry<PrefixType> &GetEntry(void);
1052 
1053             SharedEntry        *mNext;
1054             Entry<OnLinkPrefix> mOnLinkEntry;
1055             Entry<RoutePrefix>  mRouteEntry;
1056         };
1057 #endif
1058 
1059         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
1060 
1061         struct DecisionFactors : public Clearable<DecisionFactors>, public Equatable<DecisionFactors>
1062         {
DecisionFactorsot::BorderRouter::RoutingManager::RxRaTracker::DecisionFactors1063             DecisionFactors(void) { Clear(); }
1064 
HasFavoredOnLinkot::BorderRouter::RoutingManager::RxRaTracker::DecisionFactors1065             bool HasFavoredOnLink(void) const { return (mFavoredOnLinkPrefix.GetLength() != 0); }
1066             void UpdateFlagsFrom(const Router &aRouter);
1067             void UpdateFrom(const OnLinkPrefix &aOnLinkPrefix);
1068             void UpdateFrom(const RoutePrefix &aRoutePrefix);
1069 
1070             Ip6::Prefix mFavoredOnLinkPrefix;
1071             bool        mHasNonUlaRoute : 1;
1072             bool        mHasNonUlaOnLink : 1;
1073             bool        mHasUlaOnLink : 1;
1074             bool        mHeaderManagedAddressConfigFlag : 1;
1075             bool        mHeaderOtherConfigFlag : 1;
1076         };
1077 
1078         //-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
1079 
1080         void ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter, RouterAdvOrigin aRaOrigin);
1081         void ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter);
1082         void ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter);
1083         void ProcessRaFlagsExtOption(const RaFlagsExtOption &aFlagsOption, Router &aRouter);
1084         void Evaluate(void);
1085         void DetermineStaleTimeFor(const OnLinkPrefix &aPrefix, NextFireTime &aStaleTime);
1086         void DetermineStaleTimeFor(const RoutePrefix &aPrefix, NextFireTime &aStaleTime);
1087         void SendNeighborSolicitToRouter(const Router &aRouter);
1088 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
AllocateEntry(void)1089         template <class Type> Entry<Type> *AllocateEntry(void) { return Entry<Type>::Allocate(); }
1090 #else
1091         template <class Type> Entry<Type> *AllocateEntry(void);
1092 #endif
1093 
1094         using SignalTask      = TaskletIn<RoutingManager, &RoutingManager::HandleRxRaTrackerSignalTask>;
1095         using ExpirationTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerExpirationTimer>;
1096         using StaleTimer      = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerStaleTimer>;
1097         using RouterTimer     = TimerMilliIn<RoutingManager, &RoutingManager::HandleRxRaTrackerRouterTimer>;
1098         using RouterList      = OwningList<Entry<Router>>;
1099 
1100         DecisionFactors      mDecisionFactors;
1101         RouterList           mRouters;
1102         ExpirationTimer      mExpirationTimer;
1103         StaleTimer           mStaleTimer;
1104         RouterTimer          mRouterTimer;
1105         SignalTask           mSignalTask;
1106         RouterAdvert::Header mLocalRaHeader;
1107         TimeMilli            mLocalRaHeaderUpdateTime;
1108 
1109 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1110         Pool<SharedEntry, kMaxEntries>   mEntryPool;
1111         Pool<Entry<Router>, kMaxRouters> mRouterPool;
1112 #endif
1113     };
1114 
1115     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1116 
1117     class OmrPrefixManager;
1118 
1119     class OmrPrefix : public Clearable<OmrPrefix>
1120     {
1121         friend class OmrPrefixManager;
1122 
1123     public:
OmrPrefix(void)1124         OmrPrefix(void) { Clear(); }
1125 
IsEmpty(void) const1126         bool               IsEmpty(void) const { return (mPrefix.GetLength() == 0); }
GetPrefix(void) const1127         const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
GetPreference(void) const1128         RoutePreference    GetPreference(void) const { return mPreference; }
IsDomainPrefix(void) const1129         bool               IsDomainPrefix(void) const { return mIsDomainPrefix; }
1130 
1131     protected:
1132         Ip6::Prefix     mPrefix;
1133         RoutePreference mPreference;
1134         bool            mIsDomainPrefix;
1135     };
1136 
1137     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1138 
1139     class FavoredOmrPrefix : public OmrPrefix
1140     {
1141         friend class OmrPrefixManager;
1142 
1143     public:
1144         bool IsInfrastructureDerived(void) const;
1145 
1146     private:
1147         void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
1148         void SetFrom(const OmrPrefix &aOmrPrefix);
1149         bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const;
1150     };
1151 
1152     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1153 
1154     class OmrPrefixManager : public InstanceLocator
1155     {
1156     public:
1157         explicit OmrPrefixManager(Instance &aInstance);
1158 
1159         void                    Init(const Ip6::Prefix &aBrUlaPrefix);
1160         void                    Start(void);
1161         void                    Stop(void);
1162         void                    Evaluate(void);
1163         void                    UpdateDefaultRouteFlag(bool aDefaultRoute);
1164         bool                    ShouldAdvertiseLocalAsRio(void) const;
GetGeneratedPrefix(void) const1165         const Ip6::Prefix      &GetGeneratedPrefix(void) const { return mGeneratedPrefix; }
GetLocalPrefix(void) const1166         const OmrPrefix        &GetLocalPrefix(void) const { return mLocalPrefix; }
GetFavoredPrefix(void) const1167         const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; }
1168 
1169     private:
1170         static constexpr uint16_t kInfoStringSize = 85;
1171 
1172         typedef String<kInfoStringSize> InfoString;
1173 
1174         void       DetermineFavoredPrefix(void);
1175         Error      AddLocalToNetData(void);
1176         Error      AddOrUpdateLocalInNetData(void);
1177         void       RemoveLocalFromNetData(void);
1178         InfoString LocalToString(void) const;
1179 
1180         OmrPrefix        mLocalPrefix;
1181         Ip6::Prefix      mGeneratedPrefix;
1182         FavoredOmrPrefix mFavoredPrefix;
1183         bool             mIsLocalAddedInNetData;
1184         bool             mDefaultRoute;
1185     };
1186 
1187     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1188 
HandleOnLinkPrefixManagerTimer(void)1189     void HandleOnLinkPrefixManagerTimer(void) { mOnLinkPrefixManager.HandleTimer(); }
1190 
1191     class OnLinkPrefixManager : public InstanceLocator
1192     {
1193     public:
1194         explicit OnLinkPrefixManager(Instance &aInstance);
1195 
1196         // Max number of old on-link prefixes to retain to deprecate.
1197         static constexpr uint16_t kMaxOldPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES;
1198 
1199         void               Init(void);
1200         void               Start(void);
1201         void               Stop(void);
1202         void               Evaluate(void);
GetLocalPrefix(void) const1203         const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
GetFavoredDiscoveredPrefix(void) const1204         const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; }
1205         bool               IsInitalEvaluationDone(void) const;
1206         void               HandleRaPrefixTableChanged(void);
1207         bool               ShouldPublishUlaRoute(void) const;
1208         Error              AppendAsPiosTo(RouterAdvert::TxMessage &aRaMessage);
1209         void               HandleNetDataChange(void);
1210         void               HandleExtPanIdChange(void);
1211         void               HandleTimer(void);
1212 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE
SetLocalPrefix(const Ip6::Prefix & aPrefix)1213         void SetLocalPrefix(const Ip6::Prefix &aPrefix) { mLocalPrefix = aPrefix; }
1214 #endif
1215 
1216     private:
1217         enum State : uint8_t // State of `mLocalPrefix`
1218         {
1219             kIdle,
1220             kPublishing,
1221             kAdvertising,
1222             kDeprecating,
1223         };
1224 
1225         struct OldPrefix
1226         {
Matchesot::BorderRouter::RoutingManager::OnLinkPrefixManager::OldPrefix1227             bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
1228 
1229             Ip6::Prefix mPrefix;
1230             TimeMilli   mExpireTime;
1231         };
1232 
GetState(void) const1233         State GetState(void) const { return mState; }
1234         void  SetState(State aState);
1235         bool  IsPublishingOrAdvertising(void) const;
1236         void  GenerateLocalPrefix(void);
1237         void  PublishAndAdvertise(void);
1238         void  Deprecate(void);
1239         void  ResetExpireTime(TimeMilli aNow);
1240         Error AppendCurPrefix(RouterAdvert::TxMessage &aRaMessage);
1241         Error AppendOldPrefixes(RouterAdvert::TxMessage &aRaMessage);
1242         void  DeprecateOldPrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime);
1243         void  SavePrefix(const Ip6::Prefix &aPrefix, TimeMilli aExpireTime);
1244 
1245         static const char *StateToString(State aState);
1246 
1247         using ExpireTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleOnLinkPrefixManagerTimer>;
1248 
1249         Ip6::Prefix                       mLocalPrefix;
1250         State                             mState;
1251         TimeMilli                         mExpireTime;
1252         Ip6::Prefix                       mFavoredDiscoveredPrefix;
1253         Array<OldPrefix, kMaxOldPrefixes> mOldLocalPrefixes;
1254         ExpireTimer                       mTimer;
1255     };
1256 
1257     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1258 
HandleRioAdvertiserimer(void)1259     void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); }
1260 
1261     class RioAdvertiser : public InstanceLocator
1262     {
1263         // Manages the list of prefixes advertised as RIO in emitted
1264         // RA. The RIO prefixes are discovered from on-mesh prefixes in
1265         // network data including OMR prefix from `OmrPrefixManager`.
1266         // It also handles deprecating removed prefixes.
1267 
1268     public:
1269         explicit RioAdvertiser(Instance &aInstance);
1270 
GetPreference(void) const1271         RoutePreference GetPreference(void) const { return mPreference; }
1272         void            SetPreference(RoutePreference aPreference);
1273         void            ClearPreference(void);
1274         void            HandleRoleChanged(void);
1275         Error           AppendRios(RouterAdvert::TxMessage &aRaMessage);
1276         Error           InvalidatPrevRios(RouterAdvert::TxMessage &aRaMessage);
HasAdvertised(const Ip6::Prefix & aPrefix) const1277         bool            HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); }
GetAdvertisedRioCount(void) const1278         uint16_t        GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); }
1279         void            HandleTimer(void);
1280 
1281     private:
1282         static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300);
1283 
1284         struct RioPrefix : public Clearable<RioPrefix>
1285         {
Matchesot::BorderRouter::RoutingManager::RioAdvertiser::RioPrefix1286             bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
1287 
1288             Ip6::Prefix mPrefix;
1289             bool        mIsDeprecating;
1290             TimeMilli   mExpirationTime;
1291         };
1292 
1293         struct RioPrefixArray :
1294 #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1295             public Heap::Array<RioPrefix>
1296 #else
1297             public Array<RioPrefix, 2 * kMaxOnMeshPrefixes>
1298 #endif
1299         {
1300             void Add(const Ip6::Prefix &aPrefix);
1301         };
1302 
1303         void  SetPreferenceBasedOnRole(void);
1304         void  UpdatePreference(RoutePreference aPreference);
1305         Error AppendRio(const Ip6::Prefix       &aPrefix,
1306                         uint32_t                 aRouteLifetime,
1307                         RoutePreference          aPreference,
1308                         RouterAdvert::TxMessage &aRaMessage);
1309 
1310         using RioTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRioAdvertiserimer>;
1311 
1312         RioPrefixArray  mPrefixes;
1313         RioTimer        mTimer;
1314         RoutePreference mPreference;
1315         bool            mUserSetPreference;
1316     };
1317 
1318     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1319 
1320 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
1321 
HandleNat64PrefixManagerTimer(void)1322     void HandleNat64PrefixManagerTimer(void) { mNat64PrefixManager.HandleTimer(); }
1323 
1324     class Nat64PrefixManager : public InstanceLocator
1325     {
1326     public:
1327         // This class manages the NAT64 related functions including
1328         // generation of local NAT64 prefix, discovery of infra
1329         // interface prefix, maintaining the discovered prefix
1330         // lifetime, and selection of the NAT64 prefix to publish in
1331         // Network Data.
1332         //
1333         // Calling methods except GenerateLocalPrefix and SetEnabled
1334         // when disabled becomes no-op.
1335 
1336         explicit Nat64PrefixManager(Instance &aInstance);
1337 
1338         void         SetEnabled(bool aEnabled);
1339         Nat64::State GetState(void) const;
1340 
1341         void Start(void);
1342         void Stop(void);
1343 
1344         void               GenerateLocalPrefix(const Ip6::Prefix &aBrUlaPrefix);
GetLocalPrefix(void) const1345         const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
1346         const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const;
1347         void               Evaluate(void);
1348         void               HandleDiscoverDone(const Ip6::Prefix &aPrefix);
1349         void               HandleTimer(void);
1350 
1351     private:
1352         void Discover(void);
1353         void Publish(void);
1354 
1355         using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>;
1356 
1357         bool mEnabled;
1358 
1359         Ip6::Prefix     mInfraIfPrefix;       // The latest NAT64 prefix discovered on the infrastructure interface.
1360         Ip6::Prefix     mLocalPrefix;         // The local prefix (from BR ULA prefix).
1361         Ip6::Prefix     mPublishedPrefix;     // The prefix to publish in Net Data (empty or local or from infra-if).
1362         RoutePreference mPublishedPreference; // The published prefix preference.
1363         Nat64Timer      mTimer;
1364     };
1365 
1366 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
1367 
1368     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1369 
HandleRoutePublisherTimer(void)1370     void HandleRoutePublisherTimer(void) { mRoutePublisher.HandleTimer(); }
1371 
1372     class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data
1373     {
1374     public:
1375         explicit RoutePublisher(Instance &aInstance);
1376 
Start(void)1377         void Start(void) { Evaluate(); }
Stop(void)1378         void Stop(void) { Unpublish(); }
1379         void Evaluate(void);
1380 
1381         void UpdateAdvPioFlags(bool aAdvPioFlag);
1382 
GetPreference(void) const1383         RoutePreference GetPreference(void) const { return mPreference; }
1384         void            SetPreference(RoutePreference aPreference);
1385         void            ClearPreference(void);
1386 
1387         void HandleNotifierEvents(Events aEvents);
1388         void HandleTimer(void);
1389 
GetUlaPrefix(void)1390         static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); }
1391 
1392     private:
1393         static constexpr uint32_t kDelayBeforePrfUpdateOnLinkQuality3 = TimeMilli::SecToMsec(5 * 60);
1394 
1395         static const otIp6Prefix kUlaPrefix;
1396 
1397         enum State : uint8_t
1398         {
1399             kDoNotPublish,   // Do not publish any routes in network data.
1400             kPublishDefault, // Publish "::/0" route in network data.
1401             kPublishUla,     // Publish "fc00::/7" route in network data.
1402         };
1403 
1404         void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const;
1405         void UpdatePublishedRoute(State aNewState);
1406         void Unpublish(void);
1407         void SetPreferenceBasedOnRole(void);
1408         void UpdatePreference(RoutePreference aPreference);
1409 
1410         static const char *StateToString(State aState);
1411 
1412         using DelayTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRoutePublisherTimer>;
1413 
1414         State           mState;
1415         RoutePreference mPreference;
1416         bool            mUserSetPreference;
1417         bool            mAdvPioFlag;
1418         DelayTimer      mTimer;
1419     };
1420 
1421     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1422 
1423     struct TxRaInfo
1424     {
1425         // Tracks info about emitted RA messages:
1426         //
1427         // - Number of RAs sent
1428         // - Last RA TX time
1429         // - Hashes of last TX RAs (to tell if a received RA is from
1430         //   `RoutingManager` itself).
1431 
1432         typedef Crypto::Sha256::Hash Hash;
1433 
1434         static constexpr uint16_t kNumHashEntries = 5;
1435 
TxRaInfoot::BorderRouter::RoutingManager::TxRaInfo1436         TxRaInfo(void)
1437             : mTxCount(0)
1438             , mLastTxTime(TimerMilli::GetNow() - kMinDelayBetweenRas)
1439             , mLastHashIndex(0)
1440         {
1441         }
1442 
1443         void        IncrementTxCountAndSaveHash(const InfraIf::Icmp6Packet &aRaMessage);
1444         bool        IsRaFromManager(const RouterAdvert::RxMessage &aRaMessage) const;
1445         static void CalculateHash(const RouterAdvert::RxMessage &aRaMessage, Hash &aHash);
1446 
1447         uint32_t  mTxCount;
1448         TimeMilli mLastTxTime;
1449         Hash      mHashes[kNumHashEntries];
1450         uint16_t  mLastHashIndex;
1451     };
1452 
1453     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1454 
HandleRsSenderTimer(void)1455     void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); }
1456 
1457     class RsSender : public InstanceLocator
1458     {
1459     public:
1460         // This class implements tx of Router Solicitation (RS)
1461         // messages to discover other routers. `Start()` schedules
1462         // a cycle of RS transmissions of `kMaxTxCount` separated
1463         // by `kTxInterval`. At the end of cycle the callback
1464         // `HandleRsSenderFinished()` is invoked to inform end of
1465         // the cycle to `RoutingManager`.
1466 
1467         explicit RsSender(Instance &aInstance);
1468 
IsInProgress(void) const1469         bool IsInProgress(void) const { return mTimer.IsRunning(); }
1470         void Start(void);
1471         void Stop(void);
1472         void HandleTimer(void);
1473 
1474     private:
1475         // All time intervals are in msec.
1476         static constexpr uint32_t kMaxStartDelay     = 1000;        // Max random delay to send the first RS.
1477         static constexpr uint32_t kTxInterval        = 4000;        // Interval between RS tx.
1478         static constexpr uint32_t kRetryDelay        = kTxInterval; // Interval to wait to retry a failed RS tx.
1479         static constexpr uint32_t kWaitOnLastAttempt = 1000;        // Wait interval after last RS tx.
1480         static constexpr uint8_t  kMaxTxCount        = 3;           // Number of RS tx in one cycle.
1481 
1482         Error SendRs(void);
1483 
1484         using RsTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleRsSenderTimer>;
1485 
1486         uint8_t   mTxCount;
1487         RsTimer   mTimer;
1488         TimeMilli mStartTime;
1489     };
1490 
1491     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1492 
1493 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1494 
HandlePdPrefixManagerTimer(void)1495     void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); }
1496 
1497     class PdPrefixManager : public InstanceLocator
1498     {
1499     public:
1500         // This class implements handling (including management of the
1501         // lifetime) of the prefix obtained from platform's DHCPv6 PD
1502         // client.
1503 
1504         typedef Dhcp6PdState State;
1505 
1506         explicit PdPrefixManager(Instance &aInstance);
1507 
1508         void               SetEnabled(bool aEnabled);
Start(void)1509         void               Start(void) { StartStop(/* aStart= */ true); }
Stop(void)1510         void               Stop(void) { StartStop(/* aStart= */ false); }
IsRunning(void) const1511         bool               IsRunning(void) const { return GetState() == kDhcp6PdStateRunning; }
HasPrefix(void) const1512         bool               HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); }
GetPrefix(void) const1513         const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); }
1514         State              GetState(void) const;
1515 
1516         void  ProcessRa(const uint8_t *aRouterAdvert, uint16_t aLength);
1517         void  ProcessPrefix(const PrefixTableEntry &aPrefixTableEntry);
1518         Error GetPrefixInfo(PrefixTableEntry &aInfo) const;
1519         Error GetProcessedRaInfo(PdProcessedRaInfo &aPdProcessedRaInfo) const;
HandleTimer(void)1520         void  HandleTimer(void) { WithdrawPrefix(); }
SetStateCallback(PdCallback aCallback,void * aContext)1521         void  SetStateCallback(PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); }
1522 
1523     private:
1524         class PrefixEntry : public OnLinkPrefix
1525         {
1526         public:
PrefixEntry(void)1527             PrefixEntry(void) { Clear(); }
IsEmpty(void) const1528             bool IsEmpty(void) const { return (GetPrefix().GetLength() == 0); }
1529             bool IsValidPdPrefix(void) const;
1530             bool IsFavoredOver(const PrefixEntry &aOther) const;
1531         };
1532 
1533         void Process(const RouterAdvert::Icmp6Packet *aRaPacket, const PrefixTableEntry *aPrefixTableEntry);
1534         bool ProcessPrefixEntry(PrefixEntry &aEntry, PrefixEntry &aFavoredEntry);
1535         void EvaluateStateChange(State aOldState);
1536         void WithdrawPrefix(void);
1537         void StartStop(bool aStart);
1538 
1539         static const char *StateToString(State aState);
1540 
1541         using PrefixTimer   = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>;
1542         using StateCallback = Callback<PdCallback>;
1543 
1544         bool          mEnabled;
1545         bool          mIsRunning;
1546         uint32_t      mNumPlatformPioProcessed;
1547         uint32_t      mNumPlatformRaReceived;
1548         TimeMilli     mLastPlatformRaTime;
1549         StateCallback mStateCallback;
1550         PrefixTimer   mTimer;
1551         PrefixEntry   mPrefix;
1552     };
1553 
1554 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1555 
1556     //------------------------------------------------------------------------------------------------------------------
1557     // Methods
1558 
1559     void  EvaluateState(void);
1560     void  Start(void);
1561     void  Stop(void);
1562     void  HandleNotifierEvents(Events aEvents);
IsInitialized(void) const1563     bool  IsInitialized(void) const { return mInfraIf.IsInitialized(); }
IsEnabled(void) const1564     bool  IsEnabled(void) const { return mIsEnabled; }
1565     Error LoadOrGenerateRandomBrUlaPrefix(void);
1566 
1567     void EvaluateRoutingPolicy(void);
1568     bool IsInitialPolicyEvaluationDone(void) const;
1569     void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
1570     void HandleRsSenderFinished(TimeMilli aStartTime);
1571     void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
1572 
1573     void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
1574     void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
1575     void HandleNeighborAdvertisement(const InfraIf::Icmp6Packet &aPacket);
1576     bool NetworkDataContainsUlaRoute(void) const;
1577 
1578     void HandleRaPrefixTableChanged(void);
1579     void HandleLocalOnLinkPrefixChanged(void);
1580 
1581     static TimeMilli CalculateExpirationTime(TimeMilli aUpdateTime, uint32_t aLifetime);
1582 
1583     static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
1584     static bool IsValidOnLinkPrefix(const PrefixInfoOption &aPio);
1585     static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
1586 
1587     static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
1588     static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference);
1589 
1590     static const char *RouterAdvOriginToString(RouterAdvOrigin aRaOrigin);
1591 
1592     //------------------------------------------------------------------------------------------------------------------
1593     // Variables
1594 
1595     using RoutingPolicyTimer = TimerMilliIn<RoutingManager, &RoutingManager::EvaluateRoutingPolicy>;
1596 
1597     // Indicates whether the Routing Manager is running (started).
1598     bool mIsRunning;
1599 
1600     // Indicates whether the Routing manager is enabled. The Routing
1601     // Manager will be stopped if we are disabled.
1602     bool mIsEnabled;
1603 
1604     InfraIf mInfraIf;
1605 
1606     // The /48 BR ULA prefix loaded from local persistent storage or
1607     // randomly generated if none is found in persistent storage.
1608     Ip6::Prefix mBrUlaPrefix;
1609 
1610     OmrPrefixManager mOmrPrefixManager;
1611 
1612     RioAdvertiser   mRioAdvertiser;
1613     RoutePreference mRioPreference;
1614     bool            mUserSetRioPreference;
1615 
1616     OnLinkPrefixManager mOnLinkPrefixManager;
1617 
1618 #if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
1619     NetDataPeerBrTracker mNetDataPeerBrTracker;
1620 #endif
1621 
1622     RxRaTracker mRxRaTracker;
1623 
1624     RoutePublisher mRoutePublisher;
1625 
1626 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
1627     Nat64PrefixManager mNat64PrefixManager;
1628 #endif
1629 
1630 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1631     PdPrefixManager mPdPrefixManager;
1632 #endif
1633 
1634     TxRaInfo   mTxRaInfo;
1635     RsSender   mRsSender;
1636     Heap::Data mExtraRaOptions;
1637 
1638     RoutingPolicyTimer mRoutingPolicyTimer;
1639 };
1640 
1641 #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1642 
1643 //----------------------------------------------------------------------------------------------------------------------
1644 // Template specializations and declarations
1645 
1646 template <>
1647 inline RoutingManager::RxRaTracker::Entry<RoutingManager::OnLinkPrefix>
GetEntry(void)1648     &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void)
1649 {
1650     return mOnLinkEntry;
1651 }
1652 
1653 template <>
1654 inline RoutingManager::RxRaTracker::Entry<RoutingManager::RoutePrefix>
GetEntry(void)1655     &RoutingManager::RxRaTracker::SharedEntry::GetEntry(void)
1656 {
1657     return mRouteEntry;
1658 }
1659 
1660 // Declare template (full) specializations for `Router` type.
1661 
1662 template <>
1663 RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router> *RoutingManager::RxRaTracker::AllocateEntry(
1664     void);
1665 
1666 template <> void RoutingManager::RxRaTracker::Entry<RoutingManager::RxRaTracker::Router>::Free(void);
1667 
1668 #endif // #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
1669 
1670 } // namespace BorderRouter
1671 
1672 DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State);
1673 
1674 } // namespace ot
1675 
1676 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
1677 
1678 #endif // ROUTING_MANAGER_HPP_
1679