1 /*
2  *  Copyright (c) 2019, 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 types and constants.
32  */
33 
34 #ifndef MLE_TYPES_HPP_
35 #define MLE_TYPES_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 #include <string.h>
41 
42 #include <openthread/thread.h>
43 #if OPENTHREAD_FTD
44 #include <openthread/thread_ftd.h>
45 #endif
46 
47 #include "common/array.hpp"
48 #include "common/as_core_type.hpp"
49 #include "common/clearable.hpp"
50 #include "common/code_utils.hpp"
51 #include "common/encoding.hpp"
52 #include "common/equatable.hpp"
53 #include "common/numeric_limits.hpp"
54 #include "common/offset_range.hpp"
55 #include "common/string.hpp"
56 #include "mac/mac_types.hpp"
57 #include "meshcop/extended_panid.hpp"
58 #include "net/ip6_address.hpp"
59 #include "thread/network_data_types.hpp"
60 
61 namespace ot {
62 
63 class Message;
64 
65 namespace Mle {
66 
67 /**
68  * @addtogroup core-mle-core
69  *
70  * @brief
71  *   This module includes definition for MLE types and constants.
72  *
73  * @{
74  *
75  */
76 
77 constexpr uint16_t kUdpPort = 19788; ///< MLE UDP Port
78 
79 constexpr uint16_t kMaxChildren     = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN; ///< Maximum number of children
80 constexpr uint16_t kMinChildId      = 1;                                  ///< Minimum Child ID
81 constexpr uint16_t kMaxChildId      = 511;                                ///< Maximum Child ID
82 constexpr uint8_t  kMaxRouters      = OPENTHREAD_CONFIG_MLE_MAX_ROUTERS;  ///< Maximum number of routers
83 constexpr uint8_t  kMaxRouterId     = OT_NETWORK_MAX_ROUTER_ID;           ///< Max Router ID
84 constexpr uint8_t  kInvalidRouterId = kMaxRouterId + 1;                   ///< Value indicating invalid Router ID
85 constexpr uint8_t  kRouterIdOffset  = 10;                                 ///< Bit offset of router ID in RLOC16
86 constexpr uint16_t kInvalidRloc16   = Mac::kShortAddrInvalid;             ///< Invalid RLOC16.
87 
88 #if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
89 constexpr uint8_t kMaxRouteCost = 127; ///< Maximum path cost
90 #else
91 constexpr uint8_t kMaxRouteCost = 16; ///< Maximum path cost
92 #endif
93 
94 constexpr uint8_t kMeshLocalPrefixContextId = 0; ///< Reserved 6lowpan context ID for Mesh Local Prefix
95 
96 /**
97  * Number of consecutive tx failures to child (with no-ack error) to consider child-parent link broken.
98  *
99  */
100 constexpr uint8_t kFailedChildTransmissions = OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS;
101 
102 /**
103  * Threshold to accept a router upgrade request with reason `kBorderRouterRequest` (number of BRs acting as router in
104  * Network Data).
105  *
106  */
107 constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
108 
109 /**
110  * Represents a Thread device role.
111  *
112  */
113 enum DeviceRole : uint8_t
114 {
115     kRoleDisabled = OT_DEVICE_ROLE_DISABLED, ///< The Thread stack is disabled.
116     kRoleDetached = OT_DEVICE_ROLE_DETACHED, ///< Not currently participating in a Thread network/partition.
117     kRoleChild    = OT_DEVICE_ROLE_CHILD,    ///< The Thread Child role.
118     kRoleRouter   = OT_DEVICE_ROLE_ROUTER,   ///< The Thread Router role.
119     kRoleLeader   = OT_DEVICE_ROLE_LEADER,   ///< The Thread Leader role.
120 };
121 
122 constexpr uint16_t kAloc16Leader                      = 0xfc00;
123 constexpr uint16_t kAloc16DhcpAgentStart              = 0xfc01;
124 constexpr uint16_t kAloc16DhcpAgentEnd                = 0xfc0f;
125 constexpr uint16_t kAloc16ServiceStart                = 0xfc10;
126 constexpr uint16_t kAloc16ServiceEnd                  = 0xfc2f;
127 constexpr uint16_t kAloc16CommissionerStart           = 0xfc30;
128 constexpr uint16_t kAloc16CommissionerEnd             = 0xfc37;
129 constexpr uint16_t kAloc16BackboneRouterPrimary       = 0xfc38;
130 constexpr uint16_t kAloc16CommissionerMask            = 0x0007;
131 constexpr uint16_t kAloc16NeighborDiscoveryAgentStart = 0xfc40;
132 constexpr uint16_t kAloc16NeighborDiscoveryAgentEnd   = 0xfc4e;
133 
134 /**
135  * Specifies the leader role start mode.
136  *
137  * The start mode indicates whether device is starting normally as leader or restoring its role after reset.
138  *
139  */
140 enum LeaderStartMode : uint8_t
141 {
142     kStartingAsLeader,              ///< Starting as leader normally.
143     kRestoringLeaderRoleAfterReset, ///< Restoring leader role after reset.
144 };
145 
146 /**
147  * Represents a MLE device mode.
148  *
149  */
150 class DeviceMode : public Equatable<DeviceMode>
151 {
152 public:
153     static constexpr uint8_t kModeRxOnWhenIdle     = 1 << 3; ///< If to keep receiver on when not transmitting.
154     static constexpr uint8_t kModeReserved         = 1 << 2; ///< Set on transmission, ignore on reception.
155     static constexpr uint8_t kModeFullThreadDevice = 1 << 1; ///< If the device is an FTD.
156     static constexpr uint8_t kModeFullNetworkData  = 1 << 0; ///< If the device requires the full Network Data.
157 
158     static constexpr uint16_t kInfoStringSize = 45; ///< String buffer size used for `ToString()`.
159 
160     /**
161      * Defines the fixed-length `String` object returned from `ToString()`.
162      *
163      */
164     typedef String<kInfoStringSize> InfoString;
165 
166     /**
167      *  This structure represents an MLE Mode configuration.
168      *
169      */
170     typedef otLinkModeConfig ModeConfig;
171 
172     /**
173      * This is the default constructor for `DeviceMode` object.
174      *
175      */
176     DeviceMode(void) = default;
177 
178     /**
179      * Initializes a `DeviceMode` object from a given mode TLV bitmask.
180      *
181      * @param[in] aMode   A mode TLV bitmask to initialize the `DeviceMode` object.
182      *
183      */
DeviceMode(uint8_t aMode)184     explicit DeviceMode(uint8_t aMode) { Set(aMode); }
185 
186     /**
187      * Initializes a `DeviceMode` object from a given mode configuration structure.
188      *
189      * @param[in] aModeConfig   A mode configuration to initialize the `DeviceMode` object.
190      *
191      */
DeviceMode(ModeConfig aModeConfig)192     explicit DeviceMode(ModeConfig aModeConfig) { Set(aModeConfig); }
193 
194     /**
195      * Gets the device mode as a mode TLV bitmask.
196      *
197      * @returns The device mode as a mode TLV bitmask.
198      *
199      */
Get(void) const200     uint8_t Get(void) const { return mMode; }
201 
202     /**
203      * Sets the device mode from a given mode TLV bitmask.
204      *
205      * @param[in] aMode   A mode TLV bitmask.
206      *
207      */
Set(uint8_t aMode)208     void Set(uint8_t aMode) { mMode = aMode | kModeReserved; }
209 
210     /**
211      * Gets the device mode as a mode configuration structure.
212      *
213      * @param[out] aModeConfig   A reference to a mode configuration structure to output the device mode.
214      *
215      */
216     void Get(ModeConfig &aModeConfig) const;
217 
218     /**
219      * this method sets the device mode from a given mode configuration structure.
220      *
221      * @param[in] aModeConfig   A mode configuration structure.
222      *
223      */
224     void Set(const ModeConfig &aModeConfig);
225 
226     /**
227      * Indicates whether or not the device is rx-on-when-idle.
228      *
229      * @retval TRUE   If the device is rx-on-when-idle (non-sleepy).
230      * @retval FALSE  If the device is not rx-on-when-idle (sleepy).
231      *
232      */
IsRxOnWhenIdle(void) const233     bool IsRxOnWhenIdle(void) const { return (mMode & kModeRxOnWhenIdle) != 0; }
234 
235     /**
236      * Indicates whether or not the device is a Full Thread Device.
237      *
238      * @retval TRUE   If the device is Full Thread Device.
239      * @retval FALSE  If the device if not Full Thread Device.
240      *
241      */
IsFullThreadDevice(void) const242     bool IsFullThreadDevice(void) const { return (mMode & kModeFullThreadDevice) != 0; }
243 
244     /**
245      * Gets the Network Data type (full set or stable subset) that the device requests.
246      *
247      * @returns The Network Data type requested by this device.
248      *
249      */
GetNetworkDataType(void) const250     NetworkData::Type GetNetworkDataType(void) const
251     {
252         return (mMode & kModeFullNetworkData) ? NetworkData::kFullSet : NetworkData::kStableSubset;
253     }
254 
255     /**
256      * Indicates whether or not the device is a Minimal End Device.
257      *
258      * @retval TRUE   If the device is a Minimal End Device.
259      * @retval FALSE  If the device is not a Minimal End Device.
260      *
261      */
IsMinimalEndDevice(void) const262     bool IsMinimalEndDevice(void) const
263     {
264         return (mMode & (kModeFullThreadDevice | kModeRxOnWhenIdle)) != (kModeFullThreadDevice | kModeRxOnWhenIdle);
265     }
266 
267     /**
268      * Indicates whether or not the device mode flags are valid.
269      *
270      * An FTD which is not rx-on-when-idle (is sleepy) is considered invalid.
271      *
272      * @returns TRUE if , FALSE otherwise.
273      * @retval TRUE   If the device mode flags are valid.
274      * @retval FALSE  If the device mode flags are not valid.
275      *
276      */
IsValid(void) const277     bool IsValid(void) const { return !IsFullThreadDevice() || IsRxOnWhenIdle(); }
278 
279     /**
280      * Converts the device mode into a human-readable string.
281      *
282      * @returns An `InfoString` object representing the device mode.
283      *
284      */
285     InfoString ToString(void) const;
286 
287 private:
288     uint8_t mMode;
289 };
290 
291 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
292 /**
293  * Represents device properties.
294  *
295  * The device properties are used for calculating the local leader weight on the device.
296  *
297  */
298 class DeviceProperties : public otDeviceProperties, public Clearable<DeviceProperties>
299 {
300 public:
301     /**
302      * Represents the device's power supply property.
303      *
304      */
305     enum PowerSupply : uint8_t
306     {
307         kPowerSupplyBattery          = OT_POWER_SUPPLY_BATTERY,           ///< Battery powered.
308         kPowerSupplyExternal         = OT_POWER_SUPPLY_EXTERNAL,          ///< External powered.
309         kPowerSupplyExternalStable   = OT_POWER_SUPPLY_EXTERNAL_STABLE,   ///< Stable external power with backup.
310         kPowerSupplyExternalUnstable = OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, ///< Unstable external power.
311     };
312 
313     /**
314      * Initializes `DeviceProperties` with default values.
315      *
316      */
317     DeviceProperties(void);
318 
319     /**
320      * Clamps the `mLeaderWeightAdjustment` value to the valid range.
321      *
322      */
323     void ClampWeightAdjustment(void);
324 
325     /**
326      * Calculates the leader weight based on the device properties.
327      *
328      * @returns The calculated leader weight.
329      *
330      */
331     uint8_t CalculateLeaderWeight(void) const;
332 
333 private:
334     static constexpr int8_t  kDefaultAdjustment        = OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT;
335     static constexpr uint8_t kBaseWeight               = 64;
336     static constexpr int8_t  kBorderRouterInc          = +1;
337     static constexpr int8_t  kCcmBorderRouterInc       = +8;
338     static constexpr int8_t  kIsUnstableInc            = -4;
339     static constexpr int8_t  kPowerBatteryInc          = -8;
340     static constexpr int8_t  kPowerExternalInc         = 0;
341     static constexpr int8_t  kPowerExternalStableInc   = +4;
342     static constexpr int8_t  kPowerExternalUnstableInc = -4;
343     static constexpr int8_t  kMinAdjustment            = -16;
344     static constexpr int8_t  kMaxAdjustment            = +16;
345 
346     static_assert(kDefaultAdjustment >= kMinAdjustment, "Invalid default weight adjustment");
347     static_assert(kDefaultAdjustment <= kMaxAdjustment, "Invalid default weight adjustment");
348 };
349 
350 #endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
351 
352 /**
353  * Represents the Thread Leader Data.
354  *
355  */
356 class LeaderData : public otLeaderData, public Clearable<LeaderData>
357 {
358 public:
359     /**
360      * Returns the Partition ID value.
361      *
362      * @returns The Partition ID value.
363      *
364      */
GetPartitionId(void) const365     uint32_t GetPartitionId(void) const { return mPartitionId; }
366 
367     /**
368      * Sets the Partition ID value.
369      *
370      * @param[in]  aPartitionId  The Partition ID value.
371      *
372      */
SetPartitionId(uint32_t aPartitionId)373     void SetPartitionId(uint32_t aPartitionId) { mPartitionId = aPartitionId; }
374 
375     /**
376      * Returns the Weighting value.
377      *
378      * @returns The Weighting value.
379      *
380      */
GetWeighting(void) const381     uint8_t GetWeighting(void) const { return mWeighting; }
382 
383     /**
384      * Sets the Weighting value.
385      *
386      * @param[in]  aWeighting  The Weighting value.
387      *
388      */
SetWeighting(uint8_t aWeighting)389     void SetWeighting(uint8_t aWeighting) { mWeighting = aWeighting; }
390 
391     /**
392      * Returns the Data Version value for a type (full set or stable subset).
393      *
394      * @param[in] aType   The Network Data type (full set or stable subset).
395      *
396      * @returns The Data Version value for @p aType.
397      *
398      */
GetDataVersion(NetworkData::Type aType) const399     uint8_t GetDataVersion(NetworkData::Type aType) const
400     {
401         return (aType == NetworkData::kFullSet) ? mDataVersion : mStableDataVersion;
402     }
403 
404     /**
405      * Sets the Data Version value.
406      *
407      * @param[in]  aVersion  The Data Version value.
408      *
409      */
SetDataVersion(uint8_t aVersion)410     void SetDataVersion(uint8_t aVersion) { mDataVersion = aVersion; }
411 
412     /**
413      * Sets the Stable Data Version value.
414      *
415      * @param[in]  aVersion  The Stable Data Version value.
416      *
417      */
SetStableDataVersion(uint8_t aVersion)418     void SetStableDataVersion(uint8_t aVersion) { mStableDataVersion = aVersion; }
419 
420     /**
421      * Returns the Leader Router ID value.
422      *
423      * @returns The Leader Router ID value.
424      *
425      */
GetLeaderRouterId(void) const426     uint8_t GetLeaderRouterId(void) const { return mLeaderRouterId; }
427 
428     /**
429      * Sets the Leader Router ID value.
430      *
431      * @param[in]  aRouterId  The Leader Router ID value.
432      *
433      */
SetLeaderRouterId(uint8_t aRouterId)434     void SetLeaderRouterId(uint8_t aRouterId) { mLeaderRouterId = aRouterId; }
435 };
436 
437 OT_TOOL_PACKED_BEGIN
438 class RouterIdSet : public Equatable<RouterIdSet>, public Clearable<RouterIdSet>
439 {
440 public:
441     /**
442      * Indicates whether or not a Router ID bit is set.
443      *
444      * @param[in]  aRouterId  The Router ID.
445      *
446      * @retval TRUE   If the Router ID bit is set.
447      * @retval FALSE  If the Router ID bit is not set.
448      *
449      */
Contains(uint8_t aRouterId) const450     bool Contains(uint8_t aRouterId) const { return (mRouterIdSet[aRouterId / 8] & MaskFor(aRouterId)) != 0; }
451 
452     /**
453      * Sets a given Router ID.
454      *
455      * @param[in]  aRouterId  The Router ID to set.
456      *
457      */
Add(uint8_t aRouterId)458     void Add(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] |= MaskFor(aRouterId); }
459 
460     /**
461      * Removes a given Router ID.
462      *
463      * @param[in]  aRouterId  The Router ID to remove.
464      *
465      */
Remove(uint8_t aRouterId)466     void Remove(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] &= ~MaskFor(aRouterId); }
467 
468     /**
469      * Calculates the number of allocated Router IDs in the set.
470      *
471      * @returns The number of allocated Router IDs in the set.
472      *
473      */
474     uint8_t GetNumberOfAllocatedIds(void) const;
475 
476 private:
MaskFor(uint8_t aRouterId)477     static uint8_t MaskFor(uint8_t aRouterId) { return (0x80 >> (aRouterId % 8)); }
478 
479     uint8_t mRouterIdSet[BytesForBitSize(Mle::kMaxRouterId + 1)];
480 } OT_TOOL_PACKED_END;
481 
482 class TxChallenge;
483 
484 /**
485  * Represents a received Challenge data from an MLE message.
486  *
487  */
488 class RxChallenge
489 {
490 public:
491     static constexpr uint8_t kMinSize = 4; ///< Minimum Challenge size in bytes.
492     static constexpr uint8_t kMaxSize = 8; ///< Maximum Challenge size in bytes.
493 
494     /**
495      * Clears the challenge.
496      *
497      */
Clear(void)498     void Clear(void) { mArray.Clear(); }
499 
500     /**
501      * Indicates whether or not the challenge data is empty.
502      *
503      * @retval TRUE  The challenge is empty.
504      * @retval FALSE The challenge is not empty.
505      *
506      */
IsEmpty(void) const507     bool IsEmpty(void) const { return mArray.GetLength() == 0; }
508 
509     /**
510      * Gets a pointer to challenge data bytes.
511      *
512      * @return A pointer to the challenge data bytes.
513      *
514      */
GetBytes(void) const515     const uint8_t *GetBytes(void) const { return mArray.GetArrayBuffer(); }
516 
517     /**
518      * Gets the length of challenge data.
519      *
520      * @returns The length of challenge data in bytes.
521      *
522      */
GetLength(void) const523     uint8_t GetLength(void) const { return mArray.GetLength(); }
524 
525     /**
526      * Reads the challenge bytes from given message.
527      *
528      * If the given @p aLength is longer than `kMaxSize`, only `kMaxSize` bytes will be read.
529      *
530      * @param[in] aMessage     The message to read the challenge from.
531      * @param[in] aOffsetRange The offset range in @p aMessage to read from.
532      *
533      * @retval kErrorNone     Successfully read the challenge data from @p aMessage.
534      * @retval kErrorParse    Not enough bytes to read, or invalid length (smaller than `kMinSize`).
535      *
536      */
537     Error ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
538 
539     /**
540      * Compares the `RxChallenge` with a given `TxChallenge`.
541      *
542      * @param[in] aTxChallenge  The `TxChallenge` to compare with.
543      *
544      * @retval TRUE  The two challenges are equal.
545      * @retval FALSE The two challenges are not equal.
546      *
547      */
548     bool operator==(const TxChallenge &aTxChallenge) const;
549 
550 private:
551     Array<uint8_t, kMaxSize> mArray;
552 };
553 
554 /**
555  * Represents a max-sized challenge data to send in MLE message.
556  *
557  * OpenThread always uses max size challenge when sending MLE messages.
558  *
559  */
560 class TxChallenge : public Clearable<TxChallenge>
561 {
562     friend class RxChallenge;
563 
564 public:
565     /**
566      * Generates a cryptographically secure random sequence to populate the challenge data.
567      *
568      */
569     void GenerateRandom(void);
570 
571 private:
572     uint8_t m8[RxChallenge::kMaxSize];
573 };
574 
575 /**
576  * Represents a MLE Key Material
577  *
578  */
579 typedef Mac::KeyMaterial KeyMaterial;
580 
581 /**
582  * Represents a MLE Key.
583  *
584  */
585 typedef Mac::Key Key;
586 
587 /**
588  * Represents the Thread MLE counters.
589  *
590  */
591 typedef otMleCounters Counters;
592 
593 /**
594  * Derives the Child ID from a given RLOC16.
595  *
596  * @param[in]  aRloc16  The RLOC16 value.
597  *
598  * @returns The Child ID portion of an RLOC16.
599  *
600  */
ChildIdFromRloc16(uint16_t aRloc16)601 inline uint16_t ChildIdFromRloc16(uint16_t aRloc16) { return aRloc16 & kMaxChildId; }
602 
603 /**
604  * Derives the Router ID portion from a given RLOC16.
605  *
606  * @param[in]  aRloc16  The RLOC16 value.
607  *
608  * @returns The Router ID portion of an RLOC16.
609  *
610  */
RouterIdFromRloc16(uint16_t aRloc16)611 inline uint8_t RouterIdFromRloc16(uint16_t aRloc16) { return aRloc16 >> kRouterIdOffset; }
612 
613 /**
614  * Indicates whether or not a given Router ID is valid.
615  *
616  * @param[in]  aRouterId  The Router ID value to check.
617  *
618  * @retval TRUE   If @p aRouterId is in correct range [0..62].
619  * @retval FALSE  If @p aRouterId is not a valid Router ID.
620  *
621  */
IsRouterIdValid(uint8_t aRouterId)622 inline bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
623 
624 /**
625  * Returns whether the two RLOC16 have the same Router ID.
626  *
627  * @param[in]  aRloc16A  The first RLOC16 value.
628  * @param[in]  aRloc16B  The second RLOC16 value.
629  *
630  * @returns true if the two RLOC16 have the same Router ID, false otherwise.
631  *
632  */
RouterIdMatch(uint16_t aRloc16A,uint16_t aRloc16B)633 inline bool RouterIdMatch(uint16_t aRloc16A, uint16_t aRloc16B)
634 {
635     return RouterIdFromRloc16(aRloc16A) == RouterIdFromRloc16(aRloc16B);
636 }
637 
638 /**
639  * Returns the Service ID corresponding to a Service ALOC16.
640  *
641  * @param[in]  aAloc16  The Service ALOC16 value.
642  *
643  * @returns The Service ID corresponding to given ALOC16.
644  *
645  */
ServiceIdFromAloc(uint16_t aAloc16)646 inline uint8_t ServiceIdFromAloc(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kAloc16ServiceStart); }
647 
648 /**
649  * Returns the Service ALOC16 corresponding to a Service ID.
650  *
651  * @param[in]  aServiceId  The Service ID value.
652  *
653  * @returns The Service ALOC16 corresponding to given ID.
654  *
655  */
ServiceAlocFromId(uint8_t aServiceId)656 inline uint16_t ServiceAlocFromId(uint8_t aServiceId)
657 {
658     return static_cast<uint16_t>(aServiceId + kAloc16ServiceStart);
659 }
660 
661 /**
662  * Returns the Commissioner Aloc corresponding to a Commissioner Session ID.
663  *
664  * @param[in]  aSessionId   The Commissioner Session ID value.
665  *
666  * @returns The Commissioner ALOC16 corresponding to given ID.
667  *
668  */
CommissionerAloc16FromId(uint16_t aSessionId)669 inline uint16_t CommissionerAloc16FromId(uint16_t aSessionId)
670 {
671     return static_cast<uint16_t>((aSessionId & kAloc16CommissionerMask) + kAloc16CommissionerStart);
672 }
673 
674 /**
675  * Derives RLOC16 from a given Router ID.
676  *
677  * @param[in]  aRouterId  The Router ID value.
678  *
679  * @returns The RLOC16 corresponding to the given Router ID.
680  *
681  */
Rloc16FromRouterId(uint8_t aRouterId)682 inline uint16_t Rloc16FromRouterId(uint8_t aRouterId) { return static_cast<uint16_t>(aRouterId << kRouterIdOffset); }
683 
684 /**
685  * Derives the router RLOC16 corresponding to the parent of a given (child) RLOC16.
686  *
687  * If @p aRloc16 itself refers to a router, then the same RLOC16 value is returned.
688  *
689  * @param[in] aRloc16   An RLOC16.
690  *
691  * @returns The router RLOC16 corresponding to the parent associated with @p aRloc16.
692  *
693  */
ParentRloc16ForRloc16(uint16_t aRloc16)694 inline uint16_t ParentRloc16ForRloc16(uint16_t aRloc16) { return Rloc16FromRouterId(RouterIdFromRloc16(aRloc16)); }
695 
696 /**
697  * Indicates whether or not @p aRloc16 refers to a router.
698  *
699  * @param[in]  aRloc16  The RLOC16 value.
700  *
701  * @retval TRUE   If @p aRloc16 refers to a router.
702  * @retval FALSE  If @p aRloc16 does not refer to a router.
703  *
704  */
IsRouterRloc16(uint16_t aRloc16)705 inline bool IsRouterRloc16(uint16_t aRloc16) { return ChildIdFromRloc16(aRloc16) == 0; }
706 
707 /**
708  * Indicates whether or not @p aRloc16 refers to a child.
709  *
710  * @param[in]  aRloc16  The RLOC16 value.
711  *
712  * @retval TRUE   If @p aRloc16 refers to a child.
713  * @retval FALSE  If @p aRloc16 does not refer to a child.
714  *
715  */
IsChildRloc16(uint16_t aRloc16)716 inline bool IsChildRloc16(uint16_t aRloc16) { return ChildIdFromRloc16(aRloc16) != 0; }
717 
718 /**
719  * Converts a device role into a human-readable string.
720  *
721  * @param[in] aRole  The device role to convert.
722  *
723  * @returns The string representation of @p aRole.
724  *
725  */
726 const char *RoleToString(DeviceRole aRole);
727 
728 /**
729  * @}
730  *
731  */
732 
733 } // namespace Mle
734 
735 DefineCoreType(otLeaderData, Mle::LeaderData);
736 DefineMapEnum(otDeviceRole, Mle::DeviceRole);
737 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
738 DefineCoreType(otDeviceProperties, Mle::DeviceProperties);
739 DefineMapEnum(otPowerSupply, Mle::DeviceProperties::PowerSupply);
740 #endif
741 
742 } // namespace ot
743 
744 #endif // MLE_TYPES_HPP_
745