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