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