• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
SetTimeout(uint32_t aTimeout)475     void SetTimeout(uint32_t aTimeout) { SetTimeout(aTimeout, kSendChildUpdateToParent); }
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 TimeoutAction : uint8_t // Used as input in `SetTimeout()` to determine whether or not to update the parent.
908     {
909         kSendChildUpdateToParent,
910         kDoNotSendChildUpdateToParent,
911     };
912 
913     enum MessageAction : uint8_t
914     {
915         kMessageSend,
916         kMessageReceive,
917         kMessageDelay,
918         kMessageRemoveDelayed,
919     };
920 
921     enum MessageType : uint8_t
922     {
923         kTypeAdvertisement,
924         kTypeAnnounce,
925         kTypeChildIdRequest,
926         kTypeChildIdRequestShort,
927         kTypeChildIdResponse,
928         kTypeChildUpdateRequestAsChild,
929         kTypeChildUpdateResponseAsChild,
930         kTypeDataRequest,
931         kTypeDataResponse,
932         kTypeDiscoveryRequest,
933         kTypeDiscoveryResponse,
934         kTypeGenericDelayed,
935         kTypeGenericUdp,
936         kTypeParentRequestToRouters,
937         kTypeParentRequestToRoutersReeds,
938         kTypeParentResponse,
939 #if OPENTHREAD_FTD
940         kTypeAddressRelease,
941         kTypeAddressReleaseReply,
942         kTypeAddressReply,
943         kTypeAddressSolicit,
944         kTypeChildUpdateRequestOfChild,
945         kTypeChildUpdateResponseOfChild,
946         kTypeChildUpdateResponseOfUnknownChild,
947         kTypeLinkAccept,
948         kTypeLinkAcceptAndRequest,
949         kTypeLinkReject,
950         kTypeLinkRequest,
951         kTypeParentRequest,
952 #endif
953 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
954         kTypeLinkMetricsManagementRequest,
955         kTypeLinkMetricsManagementResponse,
956         kTypeLinkProbe,
957 #endif
958 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
959         kTypeTimeSync,
960 #endif
961     };
962 
963 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
964     enum WedAttachState : uint8_t{
965         kWedDetached,
966         kWedAttaching,
967         kWedAttached,
968         kWedDetaching,
969     };
970 #endif
971 
972     //------------------------------------------------------------------------------------------------------------------
973     // Nested types
974 
975     static constexpr uint8_t kMaxTlvListSize = 32; // Maximum number of TLVs in a `TlvList`.
976 
977     class TlvList : public Array<uint8_t, kMaxTlvListSize>
978     {
979     public:
980         TlvList(void) = default;
981 
982         void Add(uint8_t aTlvType);
983         void AddElementsFrom(const TlvList &aTlvList);
984     };
985 
986     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
987 
988     class TxMessage : public Message
989     {
990     public:
991         Error AppendSourceAddressTlv(void);
992         Error AppendModeTlv(DeviceMode aMode);
993         Error AppendTimeoutTlv(uint32_t aTimeout);
994         Error AppendChallengeTlv(const TxChallenge &aChallenge);
995         Error AppendResponseTlv(const RxChallenge &aResponse);
996         Error AppendLinkFrameCounterTlv(void);
997         Error AppendMleFrameCounterTlv(void);
998         Error AppendLinkAndMleFrameCounterTlvs(void);
999         Error AppendAddress16Tlv(uint16_t aRloc16);
1000         Error AppendNetworkDataTlv(NetworkData::Type aType);
1001         Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength);
1002         Error AppendLeaderDataTlv(void);
1003         Error AppendScanMaskTlv(uint8_t aScanMask);
1004         Error AppendStatusTlv(StatusTlv::Status aStatus);
1005         Error AppendLinkMarginTlv(uint8_t aLinkMargin);
1006         Error AppendVersionTlv(void);
1007         Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses);
1008         Error AppendSupervisionIntervalTlvIfSleepyChild(void);
1009         Error AppendSupervisionIntervalTlv(uint16_t aInterval);
1010         Error AppendXtalAccuracyTlv(void);
1011         Error AppendActiveTimestampTlv(void);
1012         Error AppendPendingTimestampTlv(void);
1013         Error AppendActiveAndPendingTimestampTlvs(void);
1014 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1015         Error AppendTimeRequestTlv(void);
1016         Error AppendTimeParameterTlv(void);
1017 #endif
1018 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1019         Error AppendCslChannelTlv(void);
1020         Error AppendCslTimeoutTlv(void);
1021 #endif
1022 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1023         Error AppendCslClockAccuracyTlv(void);
1024 #endif
1025 #if OPENTHREAD_FTD
1026         Error AppendRouteTlv(Neighbor *aNeighbor = nullptr);
1027         Error AppendActiveDatasetTlv(void);
1028         Error AppendPendingDatasetTlv(void);
1029         Error AppendConnectivityTlv(void);
1030         Error AppendSteeringDataTlv(void);
1031         Error AppendAddressRegistrationTlv(Child &aChild);
1032 #endif
AppendTlvRequestTlv(const uint8_t (& aTlvArray)[kArrayLength])1033         template <uint8_t kArrayLength> Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength])
1034         {
1035             return AppendTlvRequestTlv(aTlvArray, kArrayLength);
1036         }
1037 
1038         Error SendTo(const Ip6::Address &aDestination);
1039 
1040     private:
1041         Error AppendAddressRegistrationEntry(const Ip6::Address &aAddress);
1042         Error AppendDatasetTlv(MeshCoP::Dataset::Type aDatasetType);
1043     };
1044 
1045     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1046 
1047     class RxMessage : public Message
1048     {
1049     public:
1050         bool  ContainsTlv(Tlv::Type aTlvType) const;
1051         Error ReadModeTlv(DeviceMode &aMode) const;
1052         Error ReadVersionTlv(uint16_t &aVersion) const;
1053         Error ReadChallengeTlv(RxChallenge &aChallenge) const;
1054         Error ReadResponseTlv(RxChallenge &aResponse) const;
1055         Error ReadAndMatchResponseTlvWith(const TxChallenge &aChallenge) const;
1056         Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
1057         Error ReadTlvRequestTlv(TlvList &aTlvList) const;
1058         Error ReadLeaderDataTlv(LeaderData &aLeaderData) const;
1059         Error ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const;
1060         Error ReadAndSaveActiveDataset(const MeshCoP::Timestamp &aActiveTimestamp) const;
1061         Error ReadAndSavePendingDataset(const MeshCoP::Timestamp &aPendingTimestamp) const;
1062 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1063         Error ReadCslClockAccuracyTlv(Mac::CslAccuracy &aCslAccuracy) const;
1064 #endif
1065 #if OPENTHREAD_FTD
1066         Error ReadRouteTlv(RouteTlv &aRouteTlv) const;
1067 #endif
1068 
1069     private:
1070         Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const;
1071         Error ReadAndSaveDataset(MeshCoP::Dataset::Type aDatasetType, const MeshCoP::Timestamp &aTimestamp) const;
1072     };
1073 
1074     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1075 
1076     struct RxInfo
1077     {
1078         enum Class : uint8_t
1079         {
1080             kUnknown,              // Unknown (default value, also indicates MLE message parse error).
1081             kAuthoritativeMessage, // Authoritative message (larger received key seq MUST be adopted).
1082             kPeerMessage,          // Peer message (adopt only if from a known neighbor and is greater by one).
1083         };
1084 
RxInfoot::Mle::Mle::RxInfo1085         RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
1086             : mMessage(static_cast<RxMessage &>(aMessage))
1087             , mMessageInfo(aMessageInfo)
1088             , mFrameCounter(0)
1089             , mKeySequence(0)
1090             , mNeighbor(nullptr)
1091             , mClass(kUnknown)
1092         {
1093         }
1094 
IsNeighborStateValidot::Mle::Mle::RxInfo1095         bool IsNeighborStateValid(void) const { return (mNeighbor != nullptr) && mNeighbor->IsStateValid(); }
1096 
1097         RxMessage              &mMessage;      // The MLE message.
1098         const Ip6::MessageInfo &mMessageInfo;  // The `MessageInfo` associated with the message.
1099         uint32_t                mFrameCounter; // The frame counter from aux security header.
1100         uint32_t                mKeySequence;  // The key sequence from aux security header.
1101         Neighbor               *mNeighbor;     // Neighbor from which message was received (can be `nullptr`).
1102         Class                   mClass;        // The message class (authoritative, peer, or unknown).
1103     };
1104 
1105     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1106 
1107 #if OPENTHREAD_FTD
1108     struct ParentResponseInfo
1109     {
1110         Mac::ExtAddress mChildExtAddress; // The child extended address.
1111         RxChallenge     mRxChallenge;     // The challenge from the Parent Request.
1112     };
1113 
1114     struct LinkAcceptInfo
1115     {
1116         Mac::ExtAddress mExtAddress;       // The neighbor/router extended address.
1117         TlvList         mRequestedTlvList; // The requested TLVs in Link Request.
1118         RxChallenge     mRxChallenge;      // The challenge in Link Request.
1119         uint8_t         mLinkMargin;       // Link margin of the received Link Request.
1120     };
1121 
1122     struct DiscoveryResponseInfo
1123     {
1124         Mac::PanId mPanId;
1125 #if OPENTHREAD_CONFIG_MULTI_RADIO
1126         Mac::RadioType mRadioType;
1127 #endif
1128     };
1129 
1130 #endif // OPENTHREAD_FTD
1131 
1132     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1133 
HandleDelayedSenderTimer(void)1134     void HandleDelayedSenderTimer(void) { mDelayedSender.HandleTimer(); }
1135 
1136     class DelayedSender : public InstanceLocator
1137     {
1138     public:
1139         explicit DelayedSender(Instance &aInstance);
1140 
1141         void Stop(void);
1142 
1143         void ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay);
1144         void ScheduleChildUpdateRequestToParent(uint16_t aDelay);
1145 #if OPENTHREAD_FTD
1146         void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
1147         void ScheduleAdvertisement(const Ip6::Address &aDestination, uint16_t aDelay);
1148         void ScheduleMulticastDataResponse(uint16_t aDelay);
1149         void ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay);
1150         void RemoveScheduledLinkRequest(const Router &aRouter);
1151         bool HasAnyScheduledLinkRequest(const Router &aRouter) const;
1152         void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay);
1153         void ScheduleDiscoveryResponse(const Ip6::Address          &aDestination,
1154                                        const DiscoveryResponseInfo &aInfo,
1155                                        uint16_t                     aDelay);
1156 #endif
1157         void RemoveScheduledChildUpdateRequestToParent(void);
1158 
1159         void                HandleTimer(void);
GetQueue(void) const1160         const MessageQueue &GetQueue(void) const { return mSchedules; }
1161 
1162     private:
1163         typedef Message Schedule;
1164 
1165         struct Header
1166         {
ReadFromot::Mle::Mle::DelayedSender::Header1167             void ReadFrom(const Schedule &aSchedule) { IgnoreError(aSchedule.Read(/* aOffset */ 0, *this)); }
1168 
1169             TimeMilli    mSendTime;
1170             Ip6::Address mDestination;
1171             MessageType  mMessageType;
1172         };
1173 
1174         void AddSchedule(MessageType         aMessageType,
1175                          const Ip6::Address &aDestination,
1176                          uint16_t            aDelay,
1177                          const void         *aInfo,
1178                          uint16_t            aInfoSize);
1179         void Execute(const Schedule &aSchedule);
1180         bool HasMatchingSchedule(MessageType aMessageType, const Ip6::Address &aDestination) const;
1181         void RemoveMatchingSchedules(MessageType aMessageType, const Ip6::Address &aDestination);
1182 
1183         static bool Match(const Schedule &aSchedule, MessageType aMessageType, const Ip6::Address &aDestination);
1184 
1185         using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedSenderTimer>;
1186 
1187         MessageQueue mSchedules;
1188         DelayTimer   mTimer;
1189     };
1190 
1191     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1192 
1193     OT_TOOL_PACKED_BEGIN
1194     class SecurityHeader
1195     {
1196     public:
InitSecurityControl(void)1197         void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; }
IsSecurityControlValid(void) const1198         bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); }
1199 
GetFrameCounter(void) const1200         uint32_t GetFrameCounter(void) const { return LittleEndian::HostSwap32(mFrameCounter); }
SetFrameCounter(uint32_t aCounter)1201         void     SetFrameCounter(uint32_t aCounter) { mFrameCounter = LittleEndian::HostSwap32(aCounter); }
1202 
GetKeyId(void) const1203         uint32_t GetKeyId(void) const { return BigEndian::HostSwap32(mKeySource); }
SetKeyId(uint32_t aKeySequence)1204         void     SetKeyId(uint32_t aKeySequence)
1205         {
1206             mKeySource = BigEndian::HostSwap32(aKeySequence);
1207             mKeyIndex  = (aKeySequence & 0x7f) + 1;
1208         }
1209 
1210     private:
1211         static constexpr uint8_t kKeyIdMode2Mic32 =
1212             static_cast<uint8_t>(Mac::Frame::kKeyIdMode2) | static_cast<uint8_t>(Mac::Frame::kSecurityEncMic32);
1213 
1214         uint8_t  mSecurityControl;
1215         uint32_t mFrameCounter;
1216         uint32_t mKeySource;
1217         uint8_t  mKeyIndex;
1218     } OT_TOOL_PACKED_END;
1219 
1220     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1221 
1222     class ParentCandidate : public Parent
1223     {
1224     public:
Init(Instance & aInstance)1225         void Init(Instance &aInstance) { Parent::Init(aInstance); }
1226         void Clear(void);
1227         void CopyTo(Parent &aParent) const;
1228 
1229         RxChallenge mRxChallenge;
1230         int8_t      mPriority;
1231         uint8_t     mLinkQuality3;
1232         uint8_t     mLinkQuality2;
1233         uint8_t     mLinkQuality1;
1234         uint16_t    mSedBufferSize;
1235         uint8_t     mSedDatagramCount;
1236         uint8_t     mLinkMargin;
1237         LeaderData  mLeaderData;
1238         bool        mIsSingleton;
1239     };
1240 
1241     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1242 
1243 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1244     class ServiceAloc : public Ip6::Netif::UnicastAddress
1245     {
1246     public:
1247         static constexpr uint16_t kNotInUse = kInvalidRloc16;
1248 
1249         ServiceAloc(void);
1250 
IsInUse(void) const1251         bool     IsInUse(void) const { return GetAloc16() != kNotInUse; }
MarkAsNotInUse(void)1252         void     MarkAsNotInUse(void) { SetAloc16(kNotInUse); }
GetAloc16(void) const1253         uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); }
SetAloc16(uint16_t aAloc16)1254         void     SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); }
1255     };
1256 #endif
1257 
1258     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1259 
1260 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
HandleParentSearchTimer(void)1261     void HandleParentSearchTimer(void) { mParentSearch.HandleTimer(); }
1262 
1263     class ParentSearch : public InstanceLocator
1264     {
1265     public:
ParentSearch(Instance & aInstance)1266         explicit ParentSearch(Instance &aInstance)
1267             : InstanceLocator(aInstance)
1268             , mEnabled(false)
1269             , mIsInBackoff(false)
1270             , mBackoffWasCanceled(false)
1271             , mRecentlyDetached(false)
1272             , mBackoffCancelTime(0)
1273             , mTimer(aInstance)
1274         {
1275         }
1276 
1277         void SetEnabled(bool aEnabled);
IsEnabled(void) const1278         bool IsEnabled(void) const { return mEnabled; }
1279         void UpdateState(void);
SetRecentlyDetached(void)1280         void SetRecentlyDetached(void) { mRecentlyDetached = true; }
1281         void HandleTimer(void);
1282 #if OPENTHREAD_FTD
GetSelectedParent(void) const1283         const Neighbor &GetSelectedParent(void) const { return *mSelectedParent; }
1284 #endif
1285 
1286     private:
1287         // All timer intervals are converted to milliseconds.
1288         static constexpr uint32_t kCheckInterval   = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u);
1289         static constexpr uint32_t kBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u);
1290         static constexpr uint32_t kJitterInterval  = (15 * 1000u);
1291         static constexpr int8_t   kRssThreshold    = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD;
1292 
1293 #if OPENTHREAD_FTD
1294         static constexpr int8_t kRssMarginOverParent = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_MARGIN;
1295 
1296         Error SelectBetterParent(void);
1297         void  CompareAndUpdateSelectedParent(Router &aRouter);
1298 #endif
1299         void StartTimer(void);
1300 
1301         using SearchTimer = TimerMilliIn<Mle, &Mle::HandleParentSearchTimer>;
1302 
1303         bool        mEnabled : 1;
1304         bool        mIsInBackoff : 1;
1305         bool        mBackoffWasCanceled : 1;
1306         bool        mRecentlyDetached : 1;
1307         TimeMilli   mBackoffCancelTime;
1308         SearchTimer mTimer;
1309 #if OPENTHREAD_FTD
1310         Router *mSelectedParent;
1311 #endif
1312     };
1313 #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1314 
1315     //------------------------------------------------------------------------------------------------------------------
1316     // Methods
1317 
1318     Error      Start(StartMode aMode);
1319     void       Stop(StopMode aMode);
1320     TxMessage *NewMleMessage(Command aCommand);
1321     void       SetRole(DeviceRole aRole);
1322     void       Attach(AttachMode aMode);
1323     void       SetAttachState(AttachState aState);
1324     void       InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo);
ClearParentCandidate(void)1325     void       ClearParentCandidate(void) { mParentCandidate.Clear(); }
1326     Error      SendDataRequest(const Ip6::Address &aDestination);
1327     void       HandleNotifierEvents(Events aEvents);
1328     void       HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
1329     void       ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
1330     Error      SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode);
1331     Error      SendChildUpdateResponse(const TlvList      &aTlvList,
1332                                        const RxChallenge  &aChallenge,
1333                                        const Ip6::Address &aDestination);
1334     void       SetRloc16(uint16_t aRloc16);
1335     void       SetStateDetached(void);
1336     void       SetStateChild(uint16_t aRloc16);
1337     void       SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId);
1338     void       SetLeaderData(const LeaderData &aLeaderData);
1339     void       SetTimeout(uint32_t aTimeout, TimeoutAction aAction);
1340     void       InformPreviousChannel(void);
IsAnnounceAttach(void) const1341     bool       IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
1342     void       ScheduleMessageTransmissionTimer(void);
1343     void       HandleAttachTimer(void);
1344     void       HandleMessageTransmissionTimer(void);
1345     void       ProcessKeySequence(RxInfo &aRxInfo);
1346     void       HandleAdvertisement(RxInfo &aRxInfo);
1347     void       HandleChildIdResponse(RxInfo &aRxInfo);
1348     void       HandleChildUpdateRequest(RxInfo &aRxInfo);
1349     void       HandleChildUpdateRequestOnChild(RxInfo &aRxInfo);
1350     void       HandleChildUpdateResponse(RxInfo &aRxInfo);
1351     void       HandleChildUpdateResponseOnChild(RxInfo &aRxInfo);
1352     void       HandleDataResponse(RxInfo &aRxInfo);
1353     void       HandleParentResponse(RxInfo &aRxInfo);
1354     void       HandleAnnounce(RxInfo &aRxInfo);
1355     Error      HandleLeaderData(RxInfo &aRxInfo);
1356     void       ProcessAnnounce(void);
1357     bool       HasUnregisteredAddress(void);
1358     uint32_t   GetAttachStartDelay(void) const;
1359     void       SendParentRequest(ParentRequestType aType);
1360     Error      SendChildIdRequest(void);
1361     Error      GetNextAnnounceChannel(uint8_t &aChannel) const;
1362     bool       HasMoreChannelsToAnnounce(void) const;
1363     bool       PrepareAnnounceState(void);
1364     void       SendAnnounce(uint8_t aChannel, AnnounceMode aMode);
1365     void       SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce);
1366     uint32_t   Reattach(void);
1367     bool       HasAcceptableParentCandidate(void) const;
1368     Error      DetermineParentRequestType(ParentRequestType &aType) const;
1369     bool       IsBetterParent(uint16_t                aRloc16,
1370                               uint8_t                 aTwoWayLinkMargin,
1371                               const ConnectivityTlv  &aConnectivityTlv,
1372                               uint16_t                aVersion,
1373                               const Mac::CslAccuracy &aCslAccuracy);
1374     bool       IsNetworkDataNewer(const LeaderData &aLeaderData);
1375     Error      ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
1376                                       Message                &aMessage,
1377                                       const Ip6::MessageInfo &aMessageInfo,
1378                                       uint16_t                aCmdOffset,
1379                                       const SecurityHeader   &aHeader);
1380 
1381 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
1382     void InformPreviousParent(void);
1383 #endif
1384 
1385 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1386     void UpdateRoleTimeCounters(DeviceRole aRole);
1387 #endif
1388 
1389 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1390     ServiceAloc *FindInServiceAlocs(uint16_t aAloc16);
1391     void         UpdateServiceAlocs(void);
1392 #endif
1393 
1394 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
1395     void CheckTrelPeerAddrOnSecureMleRx(const Message &aMessage);
1396 #endif
1397 
1398 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1399     void HandleTimeSync(RxInfo &aRxInfo);
1400 #endif
1401 
1402 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1403     void  HandleLinkMetricsManagementRequest(RxInfo &aRxInfo);
1404     void  HandleLinkProbe(RxInfo &aRxInfo);
1405     Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus);
1406 #endif
1407 
1408 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
1409     void  HandleLinkMetricsManagementResponse(RxInfo &aRxInfo);
1410     Error SendDataRequestForLinkMetricsReport(const Ip6::Address                      &aDestination,
1411                                               const LinkMetrics::Initiator::QueryInfo &aQueryInfo);
1412     Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv);
1413     Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength);
1414     Error SendDataRequest(const Ip6::Address                      &aDestination,
1415                           const uint8_t                           *aTlvs,
1416                           uint8_t                                  aTlvsLength,
1417                           const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr);
1418 #else
1419     Error       SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength);
1420 #endif
1421 
1422 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
1423     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress);
1424     static void Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress, uint16_t aRloc);
1425 #else
Log(MessageAction,MessageType,const Ip6::Address &)1426     static void Log(MessageAction, MessageType, const Ip6::Address &) {}
Log(MessageAction,MessageType,const Ip6::Address &,uint16_t)1427     static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {}
1428 #endif
1429 
1430 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1431     void HandleWedAttachTimer(void);
1432 #endif
1433 
1434 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
1435     static const char *AttachModeToString(AttachMode aMode);
1436     static const char *AttachStateToString(AttachState aState);
1437     static const char *ReattachStateToString(ReattachState aState);
1438 #endif
1439 
1440 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
1441     static void        LogError(MessageAction aAction, MessageType aType, Error aError);
1442     static const char *MessageActionToString(MessageAction aAction);
1443     static const char *MessageTypeToString(MessageType aType);
1444     static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction);
1445     static void        LogProcessError(MessageType aType, Error aError);
1446     static void        LogSendError(MessageType aType, Error aError);
1447 #else
LogProcessError(MessageType,Error)1448     static void LogProcessError(MessageType, Error) {}
LogSendError(MessageType,Error)1449     static void LogSendError(MessageType, Error) {}
1450 #endif
1451 
1452     //------------------------------------------------------------------------------------------------------------------
1453     // Variables
1454 
1455     using AttachTimer = TimerMilliIn<Mle, &Mle::HandleAttachTimer>;
1456     using MsgTxTimer  = TimerMilliIn<Mle, &Mle::HandleMessageTransmissionTimer>;
1457     using MleSocket   = Ip6::Udp::SocketIn<Mle, &Mle::HandleUdpReceive>;
1458 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1459     using WedAttachTimer = TimerMicroIn<Mle, &Mle::HandleWedAttachTimer>;
1460 #endif
1461 
1462     static const otMeshLocalPrefix kMeshLocalPrefixInit;
1463 
1464     bool mRetrieveNewNetworkData : 1;
1465     bool mRequestRouteTlv : 1;
1466     bool mHasRestored : 1;
1467     bool mReceivedResponseFromParent : 1;
1468     bool mDetachingGracefully : 1;
1469     bool mInitiallyAttachedAsSleepy : 1;
1470     bool mWaitingForChildUpdateResponse : 1;
1471     bool mWaitingForDataResponse : 1;
1472 
1473     DeviceRole              mRole;
1474     DeviceRole              mLastSavedRole;
1475     DeviceMode              mDeviceMode;
1476     AttachState             mAttachState;
1477     ReattachState           mReattachState;
1478     AttachMode              mAttachMode;
1479     AddressRegistrationMode mAddressRegistrationMode;
1480 
1481     uint8_t  mParentRequestCounter;
1482     uint8_t  mChildUpdateAttempts;
1483     uint8_t  mDataRequestAttempts;
1484     uint8_t  mAnnounceChannel;
1485     uint8_t  mAlternateChannel;
1486     uint16_t mRloc16;
1487     uint16_t mPreviousParentRloc;
1488     uint16_t mAttachCounter;
1489     uint16_t mAnnounceDelay;
1490     uint16_t mAlternatePanId;
1491     uint32_t mStoreFrameCounterAhead;
1492     uint32_t mTimeout;
1493 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1494     uint32_t mCslTimeout;
1495 #endif
1496 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
1497     uint32_t mLastAttachTime;
1498     uint64_t mLastUpdatedTimestamp;
1499 #endif
1500     uint64_t mAlternateTimestamp;
1501 
1502     LeaderData      mLeaderData;
1503     Parent          mParent;
1504     NeighborTable   mNeighborTable;
1505     DelayedSender   mDelayedSender;
1506     TxChallenge     mParentRequestChallenge;
1507     ParentCandidate mParentCandidate;
1508     MleSocket       mSocket;
1509     Counters        mCounters;
1510 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
1511     ParentSearch mParentSearch;
1512 #endif
1513 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
1514     ServiceAloc mServiceAlocs[kMaxServiceAlocs];
1515 #endif
1516     Callback<DetachCallback> mDetachGracefullyCallback;
1517 #if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
1518     Callback<otThreadParentResponseCallback> mParentResponseCallback;
1519 #endif
1520     AttachTimer                  mAttachTimer;
1521     MsgTxTimer                   mMessageTransmissionTimer;
1522     Ip6::NetworkPrefix           mMeshLocalPrefix;
1523     Ip6::Netif::UnicastAddress   mLinkLocalAddress;
1524     Ip6::Netif::UnicastAddress   mMeshLocalEid;
1525     Ip6::Netif::UnicastAddress   mMeshLocalRloc;
1526     Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes;
1527     Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes;
1528 
1529 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
1530     WakeupTxScheduler        mWakeupTxScheduler;
1531     WedAttachState           mWedAttachState;
1532     WedAttachTimer           mWedAttachTimer;
1533     Callback<WakeupCallback> mWakeupCallback;
1534 #endif
1535 };
1536 
1537 } // namespace Mle
1538 
1539 /**
1540  * @}
1541  */
1542 
1543 } // namespace ot
1544 
1545 #endif // MLE_HPP_
1546