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