1 /*
2  *  Copyright (c) 2016, 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 MLE functionality required by the Thread Child, Router, and Leader roles.
32  */
33 
34 #ifndef MLE_HPP_
35 #define MLE_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/callback.hpp"
40 #include "common/encoding.hpp"
41 #include "common/locator.hpp"
42 #include "common/log.hpp"
43 #include "common/non_copyable.hpp"
44 #include "common/notifier.hpp"
45 #include "common/timer.hpp"
46 #include "crypto/aes_ccm.hpp"
47 #include "mac/mac.hpp"
48 #include "mac/wakeup_tx_scheduler.hpp"
49 #include "meshcop/dataset.hpp"
50 #include "meshcop/joiner_router.hpp"
51 #include "meshcop/meshcop.hpp"
52 #include "net/udp6.hpp"
53 #include "thread/child.hpp"
54 #include "thread/link_metrics.hpp"
55 #include "thread/link_metrics_tlvs.hpp"
56 #include "thread/mle_tlvs.hpp"
57 #include "thread/mle_types.hpp"
58 #include "thread/neighbor_table.hpp"
59 #include "thread/network_data_types.hpp"
60 #include "thread/router.hpp"
61 
62 namespace ot {
63 
64 /**
65  * @addtogroup core-mle MLE
66  *
67  * @brief
68  *   This module includes definitions for the MLE protocol.
69  *
70  * @{
71  *
72  * @defgroup core-mle-core Core
73  * @defgroup core-mle-router Router
74  * @defgroup core-mle-tlvs TLVs
75  *
76  * @}
77  */
78 
79 class SupervisionListener;
80 class UnitTester;
81 
82 /**
83  * @namespace ot::Mle
84  *
85  * @brief
86  *   This namespace includes definitions for the MLE protocol.
87  */
88 
89 namespace Mle {
90 
91 /**
92  * @addtogroup core-mle-core
93  *
94  * @brief
95  *   This module includes definitions for MLE functionality required by the Thread Child, Router, and Leader roles.
96  *
97  * @{
98  */
99 
100 #if OPENTHREAD_FTD
101 class MleRouter;
102 #endif
103 
104 /**
105  * Implements MLE functionality required by the Thread EndDevices, Router, and Leader roles.
106  */
107 class Mle : public InstanceLocator, private NonCopyable
108 {
109 #if OPENTHREAD_FTD
110     friend class MleRouter;
111 #endif
112     friend class DiscoverScanner;
113     friend class ot::Instance;
114     friend class ot::Notifier;
115     friend class ot::SupervisionListener;
116 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
117     friend class ot::LinkMetrics::Initiator;
118 #endif
119     friend class ot::UnitTester;
120 
121 public:
122     typedef otDetachGracefullyCallback DetachCallback; ///< Callback to signal end of graceful detach.
123 
124     typedef otWakeupCallback WakeupCallback; ///< Callback to communicate the result of waking a Wake-up End Device
125 
126     /**
127      * Initializes the MLE object.
128      *
129      * @param[in]  aInstance     A reference to the OpenThread instance.
130      */
131     explicit Mle(Instance &aInstance);
132 
133     /**
134      * Enables MLE.
135      *
136      * @retval kErrorNone     Successfully enabled MLE.
137      * @retval kErrorAlready  MLE was already enabled.
138      */
139     Error Enable(void);
140 
141     /**
142      * Disables MLE.
143      *
144      * @retval kErrorNone     Successfully disabled MLE.
145      */
146     Error Disable(void);
147 
148     /**
149      * Starts the MLE protocol operation.
150      *
151      * @retval kErrorNone           Successfully started the protocol operation.
152      * @retval kErrorInvalidState   IPv6 interface is down or device is in raw-link mode.
153      */
Start(void)154     Error Start(void) { return Start(kNormalAttach); }
155 
156     /**
157      * Stops the MLE protocol operation.
158      */
Stop(void)159     void Stop(void) { Stop(kUpdateNetworkDatasets); }
160 
161     /**
162      * Restores network information from non-volatile memory (if any).
163      */
164     void Restore(void);
165 
166     /**
167      * Stores network information into non-volatile memory.
168      *
169      * @retval kErrorNone      Successfully store the network information.
170      * @retval kErrorNoBufs    Could not store the network information due to insufficient memory space.
171      */
172     Error Store(void);
173 
174     /**
175      * Generates an MLE Announce message.
176      *
177      * @param[in]  aChannel        The channel to use when transmitting.
178      */
SendAnnounce(uint8_t aChannel)179     void SendAnnounce(uint8_t aChannel) { SendAnnounce(aChannel, kNormalAnnounce); }
180 
181     /**
182      * Causes the Thread interface to detach from the Thread network.
183      *
184      * @retval kErrorNone          Successfully detached from the Thread network.
185      * @retval kErrorInvalidState  MLE is Disabled.
186      */
187     Error BecomeDetached(void);
188 
189     /**
190      * Causes the Thread interface to attempt an MLE attach.
191      *
192      * @retval kErrorNone          Successfully began the attach process.
193      * @retval kErrorInvalidState  MLE is Disabled.
194      * @retval kErrorBusy          An attach process is in progress.
195      */
196     Error BecomeChild(void);
197 
198     /**
199      * Notifies other nodes in the network (if any) and then stops Thread protocol operation.
200      *
201      * It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child.
202      *
203      * @param[in] aCallback A pointer to a function that is called upon finishing detaching.
204      * @param[in] aContext  A pointer to callback application-specific context.
205      *
206      * @retval kErrorNone   Successfully started detaching.
207      * @retval kErrorBusy   Detaching is already in progress.
208      */
209     Error DetachGracefully(DetachCallback aCallback, void *aContext);
210 
211     /**
212      * Indicates whether or not the Thread device is attached to a Thread network.
213      *
214      * @retval TRUE   Attached to a Thread network.
215      * @retval FALSE  Not attached to a Thread network.
216      */
217     bool IsAttached(void) const;
218 
219     /**
220      * Indicates whether device is currently attaching or not.
221      *
222      * Note that an already attached device may also be in attaching state. Examples of this include a leader/router
223      * trying to attach to a better partition, or a child trying to find a better parent (when feature
224      * `OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE` is enabled).
225      *
226      * @retval TRUE   Device is currently trying to attach.
227      * @retval FALSE  Device is not in middle of attach process.
228      */
IsAttaching(void) const229     bool IsAttaching(void) const { return (mAttachState != kAttachStateIdle); }
230 
231     /**
232      * Returns the current Thread device role.
233      *
234      * @returns The current Thread device role.
235      */
GetRole(void) const236     DeviceRole GetRole(void) const { return mRole; }
237 
238     /**
239      * Indicates whether device role is disabled.
240      *
241      * @retval TRUE   Device role is disabled.
242      * @retval FALSE  Device role is not disabled.
243      */
IsDisabled(void) const244     bool IsDisabled(void) const { return (mRole == kRoleDisabled); }
245 
246     /**
247      * Indicates whether device role is detached.
248      *
249      * @retval TRUE   Device role is detached.
250      * @retval FALSE  Device role is not detached.
251      */
IsDetached(void) const252     bool IsDetached(void) const { return (mRole == kRoleDetached); }
253 
254     /**
255      * Indicates whether device role is child.
256      *
257      * @retval TRUE   Device role is child.
258      * @retval FALSE  Device role is not child.
259      */
IsChild(void) const260     bool IsChild(void) const { return (mRole == kRoleChild); }
261 
262     /**
263      * Indicates whether device role is router.
264      *
265      * @retval TRUE   Device role is router.
266      * @retval FALSE  Device role is not router.
267      */
IsRouter(void) const268     bool IsRouter(void) const { return (mRole == kRoleRouter); }
269 
270     /**
271      * Indicates whether device role is leader.
272      *
273      * @retval TRUE   Device role is leader.
274      * @retval FALSE  Device role is not leader.
275      */
IsLeader(void) const276     bool IsLeader(void) const { return (mRole == kRoleLeader); }
277 
278     /**
279      * Indicates whether device role is either router or leader.
280      *
281      * @retval TRUE   Device role is either router or leader.
282      * @retval FALSE  Device role is neither router nor leader.
283      */
284     bool IsRouterOrLeader(void) const;
285 
286     /**
287      * Returns the Device Mode as reported in the Mode TLV.
288      *
289      * @returns The Device Mode as reported in the Mode TLV.
290      */
GetDeviceMode(void) const291     DeviceMode GetDeviceMode(void) const { return mDeviceMode; }
292 
293     /**
294      * Sets the Device Mode as reported in the Mode TLV.
295      *
296      * @param[in]  aDeviceMode  The device mode to set.
297      *
298      * @retval kErrorNone         Successfully set the Mode TLV.
299      * @retval kErrorInvalidArgs  The mode combination specified in @p aMode is invalid.
300      */
301     Error SetDeviceMode(DeviceMode aDeviceMode);
302 
303     /**
304      * Indicates whether or not the device is rx-on-when-idle.
305      *
306      * @returns TRUE if rx-on-when-idle, FALSE otherwise.
307      */
IsRxOnWhenIdle(void) const308     bool IsRxOnWhenIdle(void) const { return mDeviceMode.IsRxOnWhenIdle(); }
309 
310     /**
311      * Indicates whether or not the device is a Full Thread Device.
312      *
313      * @returns TRUE if a Full Thread Device, FALSE otherwise.
314      */
IsFullThreadDevice(void) const315     bool IsFullThreadDevice(void) const { return mDeviceMode.IsFullThreadDevice(); }
316 
317     /**
318      * Indicates whether or not the device is a Minimal End Device.
319      *
320      * @returns TRUE if the device is a Minimal End Device, FALSE otherwise.
321      */
IsMinimalEndDevice(void) const322     bool IsMinimalEndDevice(void) const { return mDeviceMode.IsMinimalEndDevice(); }
323 
324     /**
325      * Gets the Network Data type (full set or stable subset) that this device requests.
326      *
327      * @returns The Network Data type requested by this device.
328      */
GetNetworkDataType(void) const329     NetworkData::Type GetNetworkDataType(void) const { return mDeviceMode.GetNetworkDataType(); }
330 
331     /**
332      * Returns a pointer to the Mesh Local Prefix.
333      *
334      * @returns A reference to the Mesh Local Prefix.
335      */
GetMeshLocalPrefix(void) const336     const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
337 
338     /**
339      * Sets the Mesh Local Prefix.
340      *
341      * @param[in]  aMeshLocalPrefix  A reference to the Mesh Local Prefix.
342      */
343     void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix);
344 
345 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
346     /**
347      * Sets the Mesh Local IID.
348      *
349      * Available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
350      *
351      * @param[in] aMlIid  The Mesh Local IID.
352      *
353      * @retval kErrorNone           Successfully configured Mesh Local IID.
354      * @retval kErrorInvalidState   If the Thread stack is already enabled.
355      */
356     Error SetMeshLocalIid(const Ip6::InterfaceIdentifier &aMlIid);
357 #endif
358 
359     /**
360      * Returns a reference to the Thread link-local address.
361      *
362      * The Thread link local address is derived using IEEE802.15.4 Extended Address as Interface Identifier.
363      *
364      * @returns A reference to the Thread link local address.
365      */
GetLinkLocalAddress(void) const366     const Ip6::Address &GetLinkLocalAddress(void) const { return mLinkLocalAddress.GetAddress(); }
367 
368     /**
369      * Updates the link local address.
370      *
371      * Call this method when the IEEE 802.15.4 Extended Address has changed.
372      */
373     void UpdateLinkLocalAddress(void);
374 
375     /**
376      * Returns a reference to the link-local all Thread nodes multicast address.
377      *
378      * @returns A reference to the link-local all Thread nodes multicast address.
379      */
GetLinkLocalAllThreadNodesAddress(void) const380     const Ip6::Address &GetLinkLocalAllThreadNodesAddress(void) const { return mLinkLocalAllThreadNodes.GetAddress(); }
381 
382     /**
383      * Returns a reference to the realm-local all Thread nodes multicast address.
384      *
385      * @returns A reference to the realm-local all Thread nodes multicast address.
386      */
GetRealmLocalAllThreadNodesAddress(void) const387     const Ip6::Address &GetRealmLocalAllThreadNodesAddress(void) const
388     {
389         return mRealmLocalAllThreadNodes.GetAddress();
390     }
391 
392     /**
393      * Gets the parent's RLOC16.
394      *
395      * @returns  The parent's RLOC16, or `kInvalidRloc16` if parent's state is not valid.
396      */
397     uint16_t GetParentRloc16(void) const;
398 
399     /**
400      * Gets the parent when operating in End Device mode.
401      *
402      * @returns A reference to the parent.
403      */
GetParent(void)404     Parent &GetParent(void) { return mParent; }
405 
406     /**
407      * Gets the parent when operating in End Device mode.
408      *
409      * @returns A reference to the parent.
410      */
GetParent(void) const411     const Parent &GetParent(void) const { return mParent; }
412 
413     /**
414      * The method retrieves information about the parent.
415      *
416      * @param[out] aParentInfo     Reference to a parent information structure.
417      *
418      * @retval kErrorNone          Successfully retrieved the parent info and updated @p aParentInfo.
419      * @retval kErrorInvalidState  Device role is not child.
420      */
421     Error GetParentInfo(Router::Info &aParentInfo) const;
422 
423     /**
424      * Get the parent candidate.
425      *
426      * The parent candidate is valid when attempting to attach to a new parent.
427      */
GetParentCandidate(void)428     Parent &GetParentCandidate(void) { return mParentCandidate; }
429 
430     /**
431      * Starts the process for child to search for a better parent while staying attached to its current
432      * parent
433      *
434      * @retval kErrorNone          Successfully started the process to search for a better parent.
435      * @retval kErrorInvalidState  Device role is not child.
436      */
437     Error SearchForBetterParent(void);
438 
439     /**
440      * Indicates whether or not an IPv6 address is an RLOC.
441      *
442      * @retval TRUE   If @p aAddress is an RLOC.
443      * @retval FALSE  If @p aAddress is not an RLOC.
444      */
445     bool IsRoutingLocator(const Ip6::Address &aAddress) const;
446 
447     /**
448      * Indicates whether or not an IPv6 address is an ALOC.
449      *
450      * @retval TRUE   If @p aAddress is an ALOC.
451      * @retval FALSE  If @p aAddress is not an ALOC.
452      */
453     bool IsAnycastLocator(const Ip6::Address &aAddress) const;
454 
455     /**
456      * Indicates whether or not an IPv6 address is a Mesh Local Address.
457      *
458      * @retval TRUE   If @p aAddress is a Mesh Local Address.
459      * @retval FALSE  If @p aAddress is not a Mesh Local Address.
460      */
461     bool IsMeshLocalAddress(const Ip6::Address &aAddress) const;
462 
463     /**
464      * Returns the MLE Timeout value.
465      *
466      * @returns The MLE Timeout value in seconds.
467      */
GetTimeout(void) const468     uint32_t GetTimeout(void) const { return mTimeout; }
469 
470     /**
471      * Sets the MLE Timeout value.
472      *
473      * @param[in]  aTimeout  The Timeout value in seconds.
474      */
475     void SetTimeout(uint32_t aTimeout);
476 
477     /**
478      * Returns the RLOC16 assigned to the Thread interface.
479      *
480      * @returns The RLOC16 assigned to the Thread interface.
481      */
GetRloc16(void) const482     uint16_t GetRloc16(void) const { return mRloc16; }
483 
484     /**
485      * Indicates whether or not this device is using a given RLOC16.
486      *
487      * @param[in] aRloc16   The RLOC16 to check.
488      *
489      * @retval TRUE   This device is using @p aRloc16.
490      * @retval FALSE  This device is not using @p aRloc16.
491      */
HasRloc16(uint16_t aRloc16) const492     bool HasRloc16(uint16_t aRloc16) const { return mRloc16 == aRloc16; }
493 
494     /**
495      * Indicates whether or not this device RLOC16 matches a given Router ID.
496      *
497      * @param[in] aRouterId   The Router ID to check.
498      *
499      * @retval TRUE   This device's RLOC16 matches the @p aRouterId.
500      * @retval FALSE  This device's RLOC16 does not match the @p aRouterId.
501      */
MatchesRouterId(uint8_t aRouterId) const502     bool MatchesRouterId(uint8_t aRouterId) const { return RouterIdFromRloc16(mRloc16) == aRouterId; }
503 
504     /**
505      * Indicates whether or not this device's RLOC16 shares the same Router ID with a given RLOC16.
506      *
507      * A shared Router ID implies that this device and the @ aRloc16 are either directly related as parent and child,
508      * or are children of the same parent within the Thread network.
509      *
510      * @param[in] aRloc16   The RLOC16 to check.
511      *
512      * @retval TRUE   This device and @p aRloc16 have a matching router ID.
513      * @retval FALSE  This device and @p aRloc16 do not have a matching router ID.
514      */
HasMatchingRouterIdWith(uint16_t aRloc16) const515     bool HasMatchingRouterIdWith(uint16_t aRloc16) const { return RouterIdMatch(mRloc16, aRloc16); }
516 
517     /**
518      * Returns the mesh local RLOC IPv6 address assigned to the Thread interface.
519      *
520      * @returns The mesh local RLOC IPv6 address.
521      */
GetMeshLocalRloc(void) const522     const Ip6::Address &GetMeshLocalRloc(void) const { return mMeshLocalRloc.GetAddress(); }
523 
524     /**
525      * Returns the mesh local endpoint identifier (ML-EID) IPv6 address assigned to the Thread interface.
526      *
527      * @returns The ML-EID address.
528      */
GetMeshLocalEid(void) const529     const Ip6::Address &GetMeshLocalEid(void) const { return mMeshLocalEid.GetAddress(); }
530 
531     /**
532      * Returns a reference to the ML-EID as a `Netif::UnicastAddress`.
533      *
534      * @returns A reference to the ML-EID.
535      */
GetMeshLocalEidUnicastAddress(void)536     Ip6::Netif::UnicastAddress &GetMeshLocalEidUnicastAddress(void) { return mMeshLocalEid; }
537 
538     /**
539      * Returns the Router ID of the Leader.
540      *
541      * @returns The Router ID of the Leader.
542      */
GetLeaderId(void) const543     uint8_t GetLeaderId(void) const { return mLeaderData.GetLeaderRouterId(); }
544 
545     /**
546      * Returns the RLOC16 of the Leader.
547      *
548      * @returns The RLOC16 of the Leader.
549      */
GetLeaderRloc16(void) const550     uint16_t GetLeaderRloc16(void) const { return Rloc16FromRouterId(GetLeaderId()); }
551 
552     /**
553      * Retrieves the Leader's RLOC.
554      *
555      * @param[out]  aAddress  A reference to an address to return the Leader's RLOC.
556      */
557     void GetLeaderRloc(Ip6::Address &aAddress) const;
558 
559     /**
560      * Retrieves the Leader's ALOC.
561      *
562      * @param[out]  aAddress  A reference to an address to return the Leader's ALOC.
563      */
564     void GetLeaderAloc(Ip6::Address &aAddress) const;
565 
566     /**
567      * Retrieves the Commissioner's ALOC for a given session ID.
568      *
569      * @param[in]   aSessionId      Commissioner session id.
570      * @param[out]  aAddress        A reference to an address to return the Commissioner's ALOC.
571      */
572     void GetCommissionerAloc(uint16_t aSessionId, Ip6::Address &aAddress) const;
573 
574     /**
575      * Retrieves the Service ALOC for given Service ID.
576      *
577      * @param[in]   aServiceId Service ID to get ALOC for.
578      * @param[out]  aAddress   A reference to an address to return the Service ALOC.
579      */
580     void GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const;
581 
582     /**
583      * Returns the most recently received Leader Data.
584      *
585      * @returns  A reference to the most recently received Leader Data.
586      */
587     const LeaderData &GetLeaderData(void);
588 
589     /**
590      * Returns a reference to the send queue.
591      *
592      * @returns A reference to the send queue.
593      */
GetMessageQueue(void) const594     const MessageQueue &GetMessageQueue(void) const { return mDelayedSender.GetQueue(); }
595 
596     /**
597      * Gets the MLE counters.
598      *
599      * @returns A reference to the MLE counters.
600      */
601     const Counters &GetCounters(void);
602 
603     /**
604      * Resets the MLE counters.
605      */
606     void ResetCounters(void);
607 
608 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
609     /**
610      * Determines the current attach duration (number of seconds since the device last attached).
611      *
612      * @returns Current attach duration in seconds.
613      */
614     uint32_t GetCurrentAttachDuration(void) const;
615 #endif
616 
617 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
618     /**
619      * Registers the client callback that is called when processing an MLE Parent Response message.
620      *
621      * @param[in]  aCallback A pointer to a function that is called to deliver MLE Parent Response data.
622      * @param[in]  aContext  A pointer to application-specific context.
623      */
RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback,void * aContext)624     void RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCallback, void *aContext)
625     {
626         mParentResponseCallback.Set(aCallback, aContext);
627     }
628 #endif
629     /**
630      * Notifies MLE whether the Child ID Request message was transmitted successfully.
631      *
632      * @param[in]  aMessage  The transmitted message.
633      */
634     void HandleChildIdRequestTxDone(Message &aMessage);
635 
636     /**
637      * Requests MLE layer to prepare and send a shorter version of Child ID Request message by only
638      * including the mesh-local IPv6 address in the Address Registration TLV.
639      *
640      * Should be called when a previous MLE Child ID Request message would require fragmentation at 6LoWPAN
641      * layer.
642      */
643     void RequestShorterChildIdRequest(void);
644 
645     /**
646      * Schedules a Child Update Request.
647      */
648     void ScheduleChildUpdateRequest(void);
649 
650     /**
651      * Sends a Child Update Request to the parent.
652      *
653      * @retval kErrorNone     Successfully prepared and sent an MLE Child Update Request message.
654      * @retval kErrorNoBufs   Insufficient buffers to construct the MLE Child Update Request message.
655      */
656     Error SendChildUpdateRequestToParent(void);
657 
658     /*
659      * Indicates whether or not the device has restored the network information from
660      * non-volatile settings after boot.
661      *
662      * @retval true  Successfully restored the network information.
663      * @retval false No valid network information was found.
664      */
HasRestored(void) const665     bool HasRestored(void) const { return mHasRestored; }
666 
667     /**
668      * Indicates whether or not a given netif multicast address instance is a prefix-based address added by MLE and
669      * uses the mesh local prefix.
670      *
671      * @param[in] aAddress   A `Netif::MulticastAddress` address instance.
672      *
673      * @retval TRUE   If @p aAddress is a prefix-based address which uses the mesh local prefix.
674      * @retval FALSE  If @p aAddress is not a prefix-based address which uses the mesh local prefix.
675      */
IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress & aAddress) const676     bool IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress &aAddress) const
677     {
678         return (&aAddress == &mLinkLocalAllThreadNodes) || (&aAddress == &mRealmLocalAllThreadNodes);
679     }
680 
681     /**
682      * Schedules a "Child Update Request" transmission if the device is an MTD child.
683      *
684      * For example, the `Slaac` class, which manages SLAAC addresses, calls this method to notify `Mle` that an
685      * existing SLAAC address's Context ID has changed. This can occur due to Network Data updates where the same
686      * on-mesh prefix receives a new Context ID.
687      */
688     void ScheduleChildUpdateRequestIfMtdChild(void);
689 
690 #if OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE
691     /**
692      * Sets the store frame counter ahead.
693      *
694      * @param[in]  aStoreFrameCounterAhead  The store frame counter ahead to set.
695      */
SetStoreFrameCounterAhead(uint32_t aStoreFrameCounterAhead)696     void SetStoreFrameCounterAhead(uint32_t aStoreFrameCounterAhead)
697     {
698         mStoreFrameCounterAhead = aStoreFrameCounterAhead;
699     }
700 
701     /**
702      * Gets the current store frame counter ahead.
703      *
704      * @returns The current store frame counter ahead.
705      */
GetStoreFrameCounterAhead(void)706     uint32_t GetStoreFrameCounterAhead(void) { return mStoreFrameCounterAhead; }
707 #endif // OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE
708 
709 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
710     /**
711      * Gets the CSL timeout.
712      *
713      * @returns CSL timeout
714      */
GetCslTimeout(void) const715     uint32_t GetCslTimeout(void) const { return mCslTimeout; }
716 
717     /**
718      * Sets the CSL timeout.
719      *
720      * @param[in]  aTimeout  The CSL timeout in seconds.
721      */
722     void SetCslTimeout(uint32_t aTimeout);
723 
724     /**
725      * Calculates CSL metric of parent.
726      *
727      * @param[in] aCslAccuracy The CSL accuracy.
728      *
729      * @returns CSL metric.
730      */
731     uint64_t CalcParentCslMetric(const Mac::CslAccuracy &aCslAccuracy) const;
732 
733 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
734 
735 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
736     /**
737      * Attempts to wake a Wake-up End Device.
738      *
739      * @param[in] aWedAddress The extended address of the Wake-up End Device.
740      * @param[in] aIntervalUs An interval between consecutive wake-up frames (in microseconds).
741      * @param[in] aDurationMs Duration of the wake-up sequence (in milliseconds).
742      * @param[in] aCallback   A pointer to function that is called when the wake-up succeeds or fails.
743      * @param[in] aContext    A pointer to callback application-specific context.
744      *
745      * @retval kErrorNone         Successfully started the wake-up.
746      * @retval kErrorInvalidState Another wake-up request is still in progress.
747      * @retval kErrorInvalidArgs  The wake-up interval or duration are invalid.
748      */
749     Error Wakeup(const Mac::ExtAddress &aWedAddress,
750                  uint16_t               aIntervalUs,
751                  uint16_t               aDurationMs,
752                  WakeupCallback         aCallback,
753                  void                  *aCallbackContext);
754 #endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
755 
756 private:
757     //------------------------------------------------------------------------------------------------------------------
758     // Constants
759 
760     // All time intervals are in milliseconds
761     static constexpr uint32_t kParentRequestRouterTimeout    = 750;  // Wait time after tx of Parent Req to routers
762     static constexpr uint32_t kParentRequestReedTimeout      = 1250; // Wait timer after tx of Parent Req to REEDs
763     static constexpr uint32_t kParentRequestDuplicateMargin  = 50;   // Margin to detect duplicate received Parent Req
764     static constexpr uint32_t kChildIdResponseTimeout        = 1250; // Wait time to receive Child ID Response
765     static constexpr uint32_t kAttachStartJitter             = 50;   // Max jitter time added to start of attach
766     static constexpr uint32_t kAnnounceProcessTimeout        = 250;  // Delay after Announce rx before processing
767     static constexpr uint32_t kAnnounceTimeout               = 1400; // Total timeout for sending Announce messages
768     static constexpr uint16_t kMinAnnounceDelay              = 80;   // Min delay between Announcement messages
769     static constexpr uint32_t kParentResponseMaxDelayRouters = 500;  // Max response delay for Parent Req to routers
770     static constexpr uint32_t kParentResponseMaxDelayAll     = 1000; // Max response delay for Parent Req to all
771     static constexpr uint32_t kChildUpdateRequestDelay       = 100;  // Delay for aggregating Child Update Req
772     static constexpr uint32_t kMaxLinkRequestDelayOnRouter   = 1000; // Max delay to tx Link Request on Adv rx
773     static constexpr uint32_t kMinLinkRequestDelayOnChild    = 1500; // Min delay to tx Link Request on Adv rx (child)
774     static constexpr uint32_t kMaxLinkRequestDelayOnChild    = 3000; // Max delay to tx Link Request on Adv rx (child)
775     static constexpr uint32_t kMaxLinkAcceptDelay            = 1000; // Max delay to tx Link Accept for multicast Req
776     static constexpr uint32_t kChildIdRequestTimeout         = 5000; // Max delay to rx a Child ID Req after Parent Res
777     static constexpr uint32_t kLinkRequestTimeout            = 2000; // Max delay to rx a Link Accept
778     static constexpr uint32_t kDetachGracefullyTimeout       = 1000; // Timeout for graceful detach
779     static constexpr uint32_t kUnicastRetxDelay              = 1000; // Base delay for MLE unicast retx
780     static constexpr uint32_t kMulticastRetxDelay            = 5000; // Base delay for MLE multicast retx
781     static constexpr uint32_t kMulticastRetxDelayMin         = kMulticastRetxDelay * 9 / 10;  // 0.9 * base delay
782     static constexpr uint32_t kMulticastRetxDelayMax         = kMulticastRetxDelay * 11 / 10; // 1.1 * base delay
783     static constexpr uint32_t kAnnounceBackoffForPendingDataset = 60000; // Max delay left to block Announce processing.
784 
785     static constexpr uint8_t kMaxTxCount                = 3; // Max tx count for MLE message
786     static constexpr uint8_t kMaxCriticalTxCount        = 6; // Max tx count for critical MLE message
787     static constexpr uint8_t kMaxChildKeepAliveAttempts = 4; // Max keep alive attempts before reattach
788 
789     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
790     // Attach backoff feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds.
791 
792     static constexpr uint32_t kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL;
793     static constexpr uint32_t kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL;
794     static constexpr uint32_t kAttachBackoffJitter      = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL;
795     static constexpr uint32_t kAttachBackoffDelayToResetCounter =
796         OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL;
797 
798     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
799     // Number of Parent Requests in first and next attach cycles
800 
801 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3
802     // First attach cycle includes two Parent Requests to routers, followed by four to routers and REEDs.
803     static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 6;
804     static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 2;
805 #else
806     // First attach cycle in Thread 1.1/1.2 includes a Parent Requests to routers, followed by one to routers and REEDs.
807     static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 2;
808     static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 1;
809 #endif
810 
811     // Next attach cycles includes one Parent Request to routers, followed by one to routers and REEDs.
812     static constexpr uint8_t kNextAttachCycleTotalParentRequests       = 2;
813     static constexpr uint8_t kNextAttachCycleNumParentRequestToRouters = 1;
814 
815     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
816 
817 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
818     static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS + 1;
819 #else
820     static constexpr uint8_t kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS;
821 #endif
822 
823     static constexpr uint8_t  kMleHopLimit                   = 255;
824     static constexpr uint8_t  kMleSecurityTagSize            = 4;
825     static constexpr uint32_t kDefaultStoreFrameCounterAhead = OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
826     static constexpr uint8_t  kMaxIpAddressesToRegister      = OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER;
827     static constexpr uint32_t kDefaultChildTimeout           = OPENTHREAD_CONFIG_MLE_CHILD_TIMEOUT_DEFAULT;
828     static constexpr uint32_t kDefaultCslTimeout             = OPENTHREAD_CONFIG_CSL_TIMEOUT;
829 
830     //------------------------------------------------------------------------------------------------------------------
831     // Enumerations
832 
833     enum AttachMode : uint8_t
834     {
835         kAnyPartition,    // Attach to any Thread partition.
836         kSamePartition,   // Attach to the same Thread partition (when losing connectivity).
837         kBetterPartition, // Attach to a better (i.e. higher weight/partition id) Thread partition.
838         kDowngradeToReed, // Attach to the same Thread partition during downgrade process.
839         kBetterParent,    // Attach to a better parent.
840         kSelectedParent,  // Attach to a selected parent.
841     };
842 
843     enum AttachState : uint8_t
844     {
845         kAttachStateIdle,            // Not currently searching for a parent.
846         kAttachStateProcessAnnounce, // Waiting to process a received Announce (to switch channel/pan-id).
847         kAttachStateStart,           // Starting to look for a parent.
848         kAttachStateParentRequest,   // Send Parent Request (current number tracked by `mParentRequestCounter`).
849         kAttachStateAnnounce,        // Send Announce messages
850         kAttachStateChildIdRequest,  // Sending a Child ID Request message.
851     };
852 
853     enum ReattachState : uint8_t
854     {
855         kReattachStop,    // Reattach process is disabled or finished
856         kReattachStart,   // Start reattach process
857         kReattachActive,  // Reattach using stored Active Dataset
858         kReattachPending, // Reattach using stored Pending Dataset
859     };
860 
861     static constexpr uint16_t kMleMaxResponseDelay = 1000u; // Max delay before responding to a multicast request.
862 
863     enum AddressRegistrationMode : uint8_t // Used by `AppendAddressRegistrationTlv()`
864     {
865         kAppendAllAddresses,  // Append all addresses (unicast/multicast) in Address Registration TLV.
866         kAppendMeshLocalOnly, // Only append the Mesh Local (ML-EID) address in Address Registration TLV.
867     };
868 
869     enum StartMode : uint8_t // Used in `Start()`.
870     {
871         kNormalAttach,
872         kAnnounceAttach, // Try to attach on the announced thread network with newer active timestamp.
873     };
874 
875     enum StopMode : uint8_t // Used in `Stop()`.
876     {
877         kKeepNetworkDatasets,
878         kUpdateNetworkDatasets,
879     };
880 
881     enum AnnounceMode : uint8_t // Used in `SendAnnounce()`
882     {
883         kNormalAnnounce,
884         kOrphanAnnounce,
885     };
886 
887     enum ParentRequestType : uint8_t
888     {
889         kToRouters,         // Parent Request to routers only.
890         kToRoutersAndReeds, // Parent Request to all routers and REEDs.
891         kToSelectedRouter,  // Parent Request to a selected router (e.g., by `ParentSearch` module).
892     };
893 
894     enum ChildUpdateRequestMode : uint8_t // Used in `SendChildUpdateRequest()`
895     {
896         kNormalChildUpdateRequest, // Normal Child Update Request.
897         kAppendChallengeTlv,       // Append Challenge TLV to Child Update Request even if currently attached.
898         kAppendZeroTimeout,        // Use zero timeout when appending Timeout TLV (used for graceful detach).
899     };
900 
901     enum SecuritySuite : uint8_t
902     {
903         k154Security = 0,   // Security suite value indicating that MLE message is not secured.
904         kNoSecurity  = 255, // Security suite value indicating that MLE message is secured.
905     };
906 
907     enum MessageAction : uint8_t
908     {
909         kMessageSend,
910         kMessageReceive,
911         kMessageDelay,
912         kMessageRemoveDelayed,
913     };
914 
915     enum MessageType : uint8_t
916     {
917         kTypeAdvertisement,
918         kTypeAnnounce,
919         kTypeChildIdRequest,
920         kTypeChildIdRequestShort,
921         kTypeChildIdResponse,
922         kTypeChildUpdateRequestAsChild,
923         kTypeChildUpdateResponseAsChild,
924         kTypeDataRequest,
925         kTypeDataResponse,
926         kTypeDiscoveryRequest,
927         kTypeDiscoveryResponse,
928         kTypeGenericDelayed,
929         kTypeGenericUdp,
930         kTypeParentRequestToRouters,
931         kTypeParentRequestToRoutersReeds,
932         kTypeParentResponse,
933 #if OPENTHREAD_FTD
934         kTypeAddressRelease,
935         kTypeAddressReleaseReply,
936         kTypeAddressReply,
937         kTypeAddressSolicit,
938         kTypeChildUpdateRequestOfChild,
939         kTypeChildUpdateResponseOfChild,
940         kTypeChildUpdateResponseOfUnknownChild,
941         kTypeLinkAccept,
942         kTypeLinkAcceptAndRequest,
943         kTypeLinkReject,
944         kTypeLinkRequest,
945         kTypeParentRequest,
946 #endif
947 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
948         kTypeLinkMetricsManagementRequest,
949         kTypeLinkMetricsManagementResponse,
950         kTypeLinkProbe,
951 #endif
952 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
953         kTypeTimeSync,
954 #endif
955     };
956 
957 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
958     enum WedAttachState : uint8_t{
959         kWedDetached,
960         kWedAttaching,
961         kWedAttached,
962         kWedDetaching,
963     };
964 #endif
965 
966     //------------------------------------------------------------------------------------------------------------------
967     // Nested types
968 
969     static constexpr uint8_t kMaxTlvListSize = 32; // Maximum number of TLVs in a `TlvList`.
970 
971     class TlvList : public Array<uint8_t, kMaxTlvListSize>
972     {
973     public:
974         TlvList(void) = default;
975 
976         void Add(uint8_t aTlvType);
977         void AddElementsFrom(const TlvList &aTlvList);
978     };
979 
980     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
981 
982     class TxMessage : public Message
983     {
984     public:
985         Error AppendSourceAddressTlv(void);
986         Error AppendModeTlv(DeviceMode aMode);
987         Error AppendTimeoutTlv(uint32_t aTimeout);
988         Error AppendChallengeTlv(const TxChallenge &aChallenge);
989         Error AppendResponseTlv(const RxChallenge &aResponse);
990         Error AppendLinkFrameCounterTlv(void);
991         Error AppendMleFrameCounterTlv(void);
992         Error AppendLinkAndMleFrameCounterTlvs(void);
993         Error AppendAddress16Tlv(uint16_t aRloc16);
994         Error AppendNetworkDataTlv(NetworkData::Type aType);
995         Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength);
996         Error AppendLeaderDataTlv(void);
997         Error AppendScanMaskTlv(uint8_t aScanMask);
998         Error AppendStatusTlv(StatusTlv::Status aStatus);
999         Error AppendLinkMarginTlv(uint8_t aLinkMargin);
1000         Error AppendVersionTlv(void);
1001         Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses);
1002         Error AppendSupervisionIntervalTlvIfSleepyChild(void);
1003         Error AppendSupervisionIntervalTlv(uint16_t aInterval);
1004         Error AppendXtalAccuracyTlv(void);
1005         Error AppendActiveTimestampTlv(void);
1006         Error AppendPendingTimestampTlv(void);
1007         Error AppendActiveAndPendingTimestampTlvs(void);
1008 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1009         Error AppendTimeRequestTlv(void);
1010         Error AppendTimeParameterTlv(void);
1011 #endif
1012 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1013         Error AppendCslChannelTlv(void);
1014         Error AppendCslTimeoutTlv(void);
1015 #endif
1016 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1017         Error AppendCslClockAccuracyTlv(void);
1018 #endif
1019 #if OPENTHREAD_FTD
1020         Error AppendRouteTlv(Neighbor *aNeighbor = nullptr);
1021         Error AppendActiveDatasetTlv(void);
1022         Error AppendPendingDatasetTlv(void);
1023         Error AppendConnectivityTlv(void);
1024         Error AppendSteeringDataTlv(void);
1025         Error AppendAddressRegistrationTlv(Child &aChild);
1026 #endif
AppendTlvRequestTlv(const uint8_t (& aTlvArray)[kArrayLength])1027         template <uint8_t kArrayLength> Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength])
1028         {
1029             return AppendTlvRequestTlv(aTlvArray, kArrayLength);
1030         }
1031 
1032         Error SendTo(const Ip6::Address &aDestination);
1033 
1034     private:
1035         Error AppendCompressedAddressEntry(uint8_t aContextId, const Ip6::Address &aAddress);
1036         Error AppendAddressEntry(const Ip6::Address &aAddress);
1037         Error AppendDatasetTlv(MeshCoP::Dataset::Type aDatasetType);
1038     };
1039 
1040     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1041 
1042     class RxMessage : public Message
1043     {
1044     public:
1045         bool  ContainsTlv(Tlv::Type aTlvType) const;
1046         Error ReadModeTlv(DeviceMode &aMode) const;
1047         Error ReadVersionTlv(uint16_t &aVersion) const;
1048         Error ReadChallengeTlv(RxChallenge &aChallenge) const;
1049         Error ReadResponseTlv(RxChallenge &aResponse) const;
1050         Error ReadAndMatchResponseTlvWith(const TxChallenge &aChallenge) const;
1051         Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
1052         Error ReadTlvRequestTlv(TlvList &aTlvList) const;
1053         Error ReadLeaderDataTlv(LeaderData &aLeaderData) const;
1054         Error ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const;
1055         Error ReadAndSaveActiveDataset(const MeshCoP::Timestamp &aActiveTimestamp) const;
1056         Error ReadAndSavePendingDataset(const MeshCoP::Timestamp &aPendingTimestamp) const;
1057 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1058         Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const;
1059 #endif
1060 #if OPENTHREAD_FTD
1061         Error ReadRouteTlv(RouteTlv &aRouteTlv) const;
1062 #endif
1063 
1064     private:
1065         Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const;
1066         Error ReadAndSaveDataset(MeshCoP::Dataset::Type aDatasetType, const MeshCoP::Timestamp &aTimestamp) const;
1067     };
1068 
1069     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1070 
1071     struct RxInfo
1072     {
1073         enum Class : uint8_t
1074         {
1075             kUnknown,              // Unknown (default value, also indicates MLE message parse error).
1076             kAuthoritativeMessage, // Authoritative message (larger received key seq MUST be adopted).
1077             kPeerMessage,          // Peer message (adopt only if from a known neighbor and is greater by one).
1078         };
1079 
RxInfoot::Mle::Mle::RxInfo1080         RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
1081             : mMessage(static_cast<RxMessage &>(aMessage))
1082             , mMessageInfo(aMessageInfo)
1083             , mFrameCounter(0)
1084             , mKeySequence(0)
1085             , mNeighbor(nullptr)
1086             , mClass(kUnknown)
1087         {
1088         }
1089 
IsNeighborStateValidot::Mle::Mle::RxInfo1090         bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); }
1091 
1092         RxMessage              &mMessage;      // The MLE message.
1093         const Ip6::MessageInfo &mMessageInfo;  // The `MessageInfo` associated with the message.
1094         uint32_t                mFrameCounter; // The frame counter from aux security header.
1095         uint32_t                mKeySequence;  // The key sequence from aux security header.
1096         Neighbor               *mNeighbor;     // Neighbor from which message was received (can be `nullptr`).
1097         Class                   mClass;        // The message class (authoritative, peer, or unknown).
1098     };
1099 
1100     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1101 
1102 #if OPENTHREAD_FTD
1103     struct ParentResponseInfo
1104     {
1105         Mac::ExtAddress mChildExtAddress; // The child extended address.
1106         RxChallenge     mRxChallenge;     // The challenge from the Parent Request.
1107     };
1108 
1109     struct LinkAcceptInfo
1110     {
1111         Mac::ExtAddress mExtAddress;       // The neighbor/router extended address.
1112         TlvList         mRequestedTlvList; // The requested TLVs in Link Request.
1113         RxChallenge     mRxChallenge;      // The challenge in Link Request.
1114         uint8_t         mLinkMargin;       // Link margin of the received Link Request.
1115     };
1116 
1117     struct DiscoveryResponseInfo
1118     {
1119         Mac::PanId mPanId;
1120 #if OPENTHREAD_CONFIG_MULTI_RADIO
1121         Mac::RadioType mRadioType;
1122 #endif
1123     };
1124 
1125 #endif // OPENTHREAD_FTD
1126 
1127     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1128 
HandleDelayedSenderTimer(void)1129     void HandleDelayedSenderTimer(void) { mDelayedSender.HandleTimer(); }
1130 
1131     class DelayedSender : public InstanceLocator
1132     {
1133     public:
1134         explicit DelayedSender(Instance &aInstance);
1135 
1136         void Stop(void);
1137 
1138         void ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay);
1139         void ScheduleChildUpdateRequestToParent(uint16_t aDelay);
1140 #if OPENTHREAD_FTD
1141         void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
1142         void ScheduleAdvertisement(const Ip6::Address &aDestination, uint16_t aDelay);
1143         void ScheduleMulticastDataResponse(uint16_t aDelay);
1144         void ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay);
1145         void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay);
1146         void ScheduleDiscoveryResponse(const Ip6::Address          &aDestination,
1147                                        const DiscoveryResponseInfo &aInfo,
1148                                        uint16_t                     aDelay);
1149         void RemoveScheduledLinkRequest(const Router &aRouter);
1150 #endif
1151         void RemoveScheduledChildUpdateRequestToParent(void);
1152 
1153         void                HandleTimer(void);
GetQueue(void) const1154         const MessageQueue &GetQueue(void) const { return mSchedules; }
1155 
1156     private:
1157         typedef Message Schedule;
1158 
1159         struct Header
1160         {
ReadFromot::Mle::Mle::DelayedSender::Header1161             void ReadFrom(const Schedule &aSchedule) { IgnoreError(aSchedule.Read(/* aOffset */ 0, *this)); }
1162 
1163             TimeMilli    mSendTime;
1164             Ip6::Address mDestination;
1165             MessageType  mMessageType;
1166         };
1167 
1168         void AddSchedule(MessageType         aMessageType,
1169                          const Ip6::Address &aDestination,
1170                          uint16_t            aDelay,
1171                          const void         *aInfo,
1172                          uint16_t            aInfoSize);
1173         void Execute(const Schedule &aSchedule);
1174         bool HasMatchingSchedule(MessageType aMessageType, const Ip6::Address &aDestination) const;
1175         void RemoveMatchingSchedules(MessageType aMessageType, const Ip6::Address &aDestination);
1176 
1177         static bool Match(const Schedule &aSchedule, MessageType aMessageType, const Ip6::Address &aDestination);
1178 
1179         using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedSenderTimer>;
1180 
1181         MessageQueue mSchedules;
1182         DelayTimer   mTimer;
1183     };
1184 
1185     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1186 
1187     OT_TOOL_PACKED_BEGIN
1188     class SecurityHeader
1189     {
1190     public:
InitSecurityControl(void)1191         void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; }
IsSecurityControlValid(void) const1192         bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); }
1193 
GetFrameCounter(void) const1194         uint32_t GetFrameCounter(void) const { return LittleEndian::HostSwap32(mFrameCounter); }
SetFrameCounter(uint32_t aCounter)1195         void     SetFrameCounter(uint32_t aCounter) { mFrameCounter = LittleEndian::HostSwap32(aCounter); }
1196 
GetKeyId(void) const1197         uint32_t GetKeyId(void) const { return BigEndian::HostSwap32(mKeySource); }
SetKeyId(uint32_t aKeySequence)1198         void     SetKeyId(uint32_t aKeySequence)
1199         {
1200             mKeySource = BigEndian::HostSwap32(aKeySequence);
1201             mKeyIndex  = (aKeySequence & 0x7f) + 1;
1202         }
1203 
1204     private:
1205         static constexpr uint8_t kKeyIdMode2Mic32 =
1206             static_cast<uint8_t>(Mac::Frame::kKeyIdMode2) | static_cast<uint8_t>(Mac::Frame::kSecurityEncMic32);
1207 
1208         uint8_t  mSecurityControl;
1209         uint32_t mFrameCounter;
1210         uint32_t mKeySource;
1211         uint8_t  mKeyIndex;
1212     } OT_TOOL_PACKED_END;
1213 
1214     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1215 
1216     class ParentCandidate : public Parent
1217     {
1218     public:
Init(Instance & aInstance)1219         void Init(Instance &aInstance) { Parent::Init(aInstance); }
1220         void Clear(void);
1221         void CopyTo(Parent &aParent) const;
1222 
1223         RxChallenge mRxChallenge;
1224         int8_t      mPriority;
1225         uint8_t     mLinkQuality3;
1226         uint8_t     mLinkQuality2;
1227         uint8_t     mLinkQuality1;
1228         uint16_t    mSedBufferSize;
1229         uint8_t     mSedDatagramCount;
1230         uint8_t     mLinkMargin;
1231         LeaderData  mLeaderData;
1232         bool        mIsSingleton;
1233     };
1234 
1235     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1236 
1237 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1238     class ServiceAloc : public Ip6::Netif::UnicastAddress
1239     {
1240     public:
1241         static constexpr uint16_t kNotInUse = kInvalidRloc16;
1242 
1243         ServiceAloc(void);
1244 
IsInUse(void) const1245         bool     IsInUse(void) const { return GetAloc16() != kNotInUse; }
MarkAsNotInUse(void)1246         void     MarkAsNotInUse(void) { SetAloc16(kNotInUse); }
GetAloc16(void) const1247         uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); }
SetAloc16(uint16_t aAloc16)1248         void     SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); }
1249     };
1250 #endif
1251 
1252     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1253 
1254 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
HandleParentSearchTimer(void)1255     void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); }
1256 
1257     class ParentSearch : public InstanceLocator
1258     {
1259     public:
ParentSearch(Instance & aInstance)1260         explicit ParentSearch(Instance &aInstance)
1261             : InstanceLocator(aInstance)
1262             , mEnabled(false)
1263             , mIsInBackoff(false)
1264             , mBackoffWasCanceled(false)
1265             , mRecentlyDetached(false)
1266             , mBackoffCancelTime(0)
1267             , mTimer(aInstance)
1268         {
1269         }
1270 
1271         void SetEnabled(bool aEnabled);
IsEnabled(void) const1272         bool IsEnabled(void) const { return mEnabled; }
1273         void UpdateState(void);
SetRecentlyDetached(void)1274         void SetRecentlyDetached(void) { mRecentlyDetached = true; }
1275         void HandleTimer(void);
1276 #if OPENTHREAD_FTD
GetSelectedParent(void) const1277         const Neighbor &GetSelectedParent(void) const { return *mSelectedParent; }
1278 #endif
1279 
1280     private:
1281         // All timer intervals are converted to milliseconds.
1282         static constexpr uint32_t kCheckInterval   = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u);
1283         static constexpr uint32_t kBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u);
1284         static constexpr uint32_t kJitterInterval  = (15 * 1000u);
1285         static constexpr int8_t   kRssThreshold    = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD;
1286 
1287 #if OPENTHREAD_FTD
1288         static constexpr int8_t kRssMarginOverParent = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_MARGIN;
1289 
1290         Error SelectBetterParent(void);
1291         void  CompareAndUpdateSelectedParent(Router &aRouter);
1292 #endif
1293         void StartTimer(void);
1294 
1295         using SearchTimer = TimerMilliIn<Mle, &Mle::HandleParentSearchTimer>;
1296 
1297         bool        mEnabled : 1;
1298         bool        mIsInBackoff : 1;
1299         bool        mBackoffWasCanceled : 1;
1300         bool        mRecentlyDetached : 1;
1301         TimeMilli   mBackoffCancelTime;
1302         SearchTimer mTimer;
1303 #if OPENTHREAD_FTD
1304         Router *mSelectedParent;
1305 #endif
1306     };
1307 #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1308 
1309     //------------------------------------------------------------------------------------------------------------------
1310     // Methods
1311 
1312     Error      Start(StartMode aMode);
1313     void       Stop(StopMode aMode);
1314     TxMessage *NewMleMessage(Command aCommand);
1315     void       SetRole(DeviceRole aRole);
1316     void       Attach(AttachMode aMode);
1317     void       SetAttachState(AttachState aState);
1318     void       InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo);
ClearParentCandidate(void)1319     void       ClearParentCandidate(void) { mParentCandidate.Clear(); }
1320     Error      SendDataRequest(const Ip6::Address &aDestination);
1321     void       HandleNotifierEvents(Events aEvents);
1322     void       HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
1323     void       ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
1324     Error      SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode);
1325     Error      SendChildUpdateResponse(const TlvList      &aTlvList,
1326                                        const RxChallenge  &aChallenge,
1327                                        const Ip6::Address &aDestination);
1328     void       SetRloc16(uint16_t aRloc16);
1329     void       SetStateDetached(void);
1330     void       SetStateChild(uint16_t aRloc16);
1331     void       SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId);
1332     void       SetLeaderData(const LeaderData &aLeaderData);
1333     void       InformPreviousChannel(void);
IsAnnounceAttach(void) const1334     bool       IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
1335     void       ScheduleMessageTransmissionTimer(void);
1336     void       HandleAttachTimer(void);
1337     void       HandleMessageTransmissionTimer(void);
1338     void       ProcessKeySequence(RxInfo &aRxInfo);
1339     void       HandleAdvertisement(RxInfo &aRxInfo);
1340     void       HandleChildIdResponse(RxInfo &aRxInfo);
1341     void       HandleChildUpdateRequest(RxInfo &aRxInfo);
1342     void       HandleChildUpdateRequestOnChild(RxInfo &aRxInfo);
1343     void       HandleChildUpdateResponse(RxInfo &aRxInfo);
1344     void       HandleChildUpdateResponseOnChild(RxInfo &aRxInfo);
1345     void       HandleDataResponse(RxInfo &aRxInfo);
1346     void       HandleParentResponse(RxInfo &aRxInfo);
1347     void       HandleAnnounce(RxInfo &aRxInfo);
1348     Error      HandleLeaderData(RxInfo &aRxInfo);
1349     void       ProcessAnnounce(void);
1350     bool       HasUnregisteredAddress(void);
1351     uint32_t   GetAttachStartDelay(void) const;
1352     void       SendParentRequest(ParentRequestType aType);
1353     Error      SendChildIdRequest(void);
1354     Error      GetNextAnnounceChannel(uint8_t &aChannel) const;
1355     bool       HasMoreChannelsToAnnounce(void) const;
1356     bool       PrepareAnnounceState(void);
1357     void       SendAnnounce(uint8_t aChannel, AnnounceMode aMode);
1358     void       SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce);
1359     uint32_t   Reattach(void);
1360     bool       HasAcceptableParentCandidate(void) const;
1361     Error      DetermineParentRequestType(ParentRequestType &aType) const;
1362     bool       IsBetterParent(uint16_t                aRloc16,
1363                               uint8_t                 aTwoWayLinkMargin,
1364                               const ConnectivityTlv  &aConnectivityTlv,
1365                               uint16_t                aVersion,
1366                               const Mac::CslAccuracy &aCslAccuracy);
1367     bool       IsNetworkDataNewer(const LeaderData &aLeaderData);
1368     Error      ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
1369                                       Message                &aMessage,
1370                                       const Ip6::MessageInfo &aMessageInfo,
1371                                       uint16_t                aCmdOffset,
1372                                       const SecurityHeader   &aHeader);
1373 
1374 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
1375     void InformPreviousParent(void);
1376 #endif
1377 
1378 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1379     void UpdateRoleTimeCounters(DeviceRole aRole);
1380 #endif
1381 
1382 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1383     ServiceAloc *FindInServiceAlocs(uint16_t aAloc16);
1384     void         UpdateServiceAlocs(void);
1385 #endif
1386 
1387 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
1388     void CheckTrelPeerAddrOnSecureMleRx(const Message &aMessage);
1389 #endif
1390 
1391 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1392     void HandleTimeSync(RxInfo &aRxInfo);
1393 #endif
1394 
1395 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1396     void  HandleLinkMetricsManagementRequest(RxInfo &aRxInfo);
1397     void  HandleLinkProbe(RxInfo &aRxInfo);
1398     Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus);
1399 #endif
1400 
1401 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
1402     void  HandleLinkMetricsManagementResponse(RxInfo &aRxInfo);
1403     Error SendDataRequestForLinkMetricsReport(const Ip6::Address                      &aDestination,
1404                                               const LinkMetrics::Initiator::QueryInfo &aQueryInfo);
1405     Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv);
1406     Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength);
1407     Error SendDataRequest(const Ip6::Address                      &aDestination,
1408                           const uint8_t                           *aTlvs,
1409                           uint8_t                                  aTlvsLength,
1410                           const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr);
1411 #else
1412     Error       SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength);
1413 #endif
1414 
1415 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
1416     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress);
1417     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc);
1418 #else
Log(MessageAction,MessageType,const Ip6::Address &)1419     static void Log(MessageAction, MessageType, const Ip6::Address &) {}
Log(MessageAction,MessageType,const Ip6::Address &,uint16_t)1420     static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {}
1421 #endif
1422 
1423 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1424     void HandleWedAttachTimer(void);
1425 #endif
1426 
1427 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
1428     static const char *AttachModeToString(AttachMode aMode);
1429     static const char *AttachStateToString(AttachState aState);
1430     static const char *ReattachStateToString(ReattachState aState);
1431 #endif
1432 
1433 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
1434     static void        LogError(MessageAction aAction, MessageType aType, Error aError);
1435     static const char *MessageActionToString(MessageAction aAction);
1436     static const char *MessageTypeToString(MessageType aType);
1437     static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction);
1438     static void        LogProcessError(MessageType aType, Error aError);
1439     static void        LogSendError(MessageType aType, Error aError);
1440 #else
LogProcessError(MessageType,Error)1441     static void LogProcessError(MessageType, Error) {}
LogSendError(MessageType,Error)1442     static void LogSendError(MessageType, Error) {}
1443 #endif
1444 
1445     //------------------------------------------------------------------------------------------------------------------
1446     // Variables
1447 
1448     using AttachTimer = TimerMilliIn<Mle, &Mle::HandleAttachTimer>;
1449     using MsgTxTimer  = TimerMilliIn<Mle, &Mle::HandleMessageTransmissionTimer>;
1450     using MleSocket   = Ip6::Udp::SocketIn<Mle, &Mle::HandleUdpReceive>;
1451 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1452     using WedAttachTimer = TimerMicroIn<Mle, &Mle::HandleWedAttachTimer>;
1453 #endif
1454 
1455     static const otMeshLocalPrefix kMeshLocalPrefixInit;
1456 
1457     bool mRetrieveNewNetworkData : 1;
1458     bool mRequestRouteTlv : 1;
1459     bool mHasRestored : 1;
1460     bool mReceivedResponseFromParent : 1;
1461     bool mDetachingGracefully : 1;
1462     bool mInitiallyAttachedAsSleepy : 1;
1463     bool mWaitingForChildUpdateResponse : 1;
1464     bool mWaitingForDataResponse : 1;
1465 
1466     DeviceRole              mRole;
1467     DeviceRole              mLastSavedRole;
1468     DeviceMode              mDeviceMode;
1469     AttachState             mAttachState;
1470     ReattachState           mReattachState;
1471     AttachMode              mAttachMode;
1472     AddressRegistrationMode mAddressRegistrationMode;
1473 
1474     uint8_t  mParentRequestCounter;
1475     uint8_t  mChildUpdateAttempts;
1476     uint8_t  mDataRequestAttempts;
1477     uint8_t  mAnnounceChannel;
1478     uint8_t  mAlternateChannel;
1479     uint16_t mRloc16;
1480     uint16_t mPreviousParentRloc;
1481     uint16_t mAttachCounter;
1482     uint16_t mAnnounceDelay;
1483     uint16_t mAlternatePanId;
1484     uint32_t mStoreFrameCounterAhead;
1485     uint32_t mTimeout;
1486 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1487     uint32_t mCslTimeout;
1488 #endif
1489 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1490     uint32_t mLastAttachTime;
1491     uint64_t mLastUpdatedTimestamp;
1492 #endif
1493     uint64_t mAlternateTimestamp;
1494 
1495     LeaderData      mLeaderData;
1496     Parent          mParent;
1497     NeighborTable   mNeighborTable;
1498     DelayedSender   mDelayedSender;
1499     TxChallenge     mParentRequestChallenge;
1500     ParentCandidate mParentCandidate;
1501     MleSocket       mSocket;
1502     Counters        mCounters;
1503 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1504     ParentSearch mParentSearch;
1505 #endif
1506 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1507     ServiceAloc mServiceAlocs[kMaxServiceAlocs];
1508 #endif
1509     Callback<DetachCallback> mDetachGracefullyCallback;
1510 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
1511     Callback<otThreadParentResponseCallback> mParentResponseCallback;
1512 #endif
1513     AttachTimer                  mAttachTimer;
1514     MsgTxTimer                   mMessageTransmissionTimer;
1515     Ip6::NetworkPrefix           mMeshLocalPrefix;
1516     Ip6::Netif::UnicastAddress   mLinkLocalAddress;
1517     Ip6::Netif::UnicastAddress   mMeshLocalEid;
1518     Ip6::Netif::UnicastAddress   mMeshLocalRloc;
1519     Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes;
1520     Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes;
1521 
1522 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1523     WakeupTxScheduler        mWakeupTxScheduler;
1524     WedAttachState           mWedAttachState;
1525     WedAttachTimer           mWedAttachTimer;
1526     Callback<WakeupCallback> mWakeupCallback;
1527 #endif
1528 };
1529 
1530 } // namespace Mle
1531 
1532 /**
1533  * @}
1534  */
1535 
1536 } // namespace ot
1537 
1538 #endif // MLE_HPP_
1539