blob: ae4dfdfa31d7546376bd65e3f5424065b99dd8c8 [file] [log] [blame]
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for MLE types and constants.
*/
#ifndef MLE_TYPES_HPP_
#define MLE_TYPES_HPP_
#include "openthread-core-config.h"
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <openthread/thread.h>
#if OPENTHREAD_FTD
#include <openthread/thread_ftd.h>
#endif
#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/extended_panid.hpp"
#include "net/ip6_address.hpp"
#include "thread/network_data_types.hpp"
namespace ot {
class Message;
namespace Mle {
/**
* @addtogroup core-mle-core
*
* @brief
* This module includes definition for MLE types and constants.
*
* @{
*
*/
constexpr uint16_t kUdpPort = 19788; ///< MLE UDP Port
constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN; ///< Maximum number of children
constexpr uint16_t kMinChildId = 1; ///< Minimum Child ID
constexpr uint16_t kMaxChildId = 511; ///< Maximum Child ID
constexpr uint8_t kMaxRouters = OPENTHREAD_CONFIG_MLE_MAX_ROUTERS; ///< Maximum number of routers
constexpr uint8_t kMaxRouterId = OT_NETWORK_MAX_ROUTER_ID; ///< Max Router ID
constexpr uint8_t kInvalidRouterId = kMaxRouterId + 1; ///< Value indicating invalid Router ID
constexpr uint8_t kRouterIdOffset = 10; ///< Bit offset of router ID in RLOC16
constexpr uint16_t kInvalidRloc16 = Mac::kShortAddrInvalid; ///< Invalid RLOC16.
#if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
constexpr uint8_t kMaxRouteCost = 127; ///< Maximum path cost
#else
constexpr uint8_t kMaxRouteCost = 16; ///< Maximum path cost
#endif
constexpr uint8_t kMeshLocalPrefixContextId = 0; ///< Reserved 6lowpan context ID for Mesh Local Prefix
/**
* Number of consecutive tx failures to child (with no-ack error) to consider child-parent link broken.
*
*/
constexpr uint8_t kFailedChildTransmissions = OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS;
/**
* Threshold to accept a router upgrade request with reason `kBorderRouterRequest` (number of BRs acting as router in
* Network Data).
*
*/
constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
/**
* Represents a Thread device role.
*
*/
enum DeviceRole : uint8_t
{
kRoleDisabled = OT_DEVICE_ROLE_DISABLED, ///< The Thread stack is disabled.
kRoleDetached = OT_DEVICE_ROLE_DETACHED, ///< Not currently participating in a Thread network/partition.
kRoleChild = OT_DEVICE_ROLE_CHILD, ///< The Thread Child role.
kRoleRouter = OT_DEVICE_ROLE_ROUTER, ///< The Thread Router role.
kRoleLeader = OT_DEVICE_ROLE_LEADER, ///< The Thread Leader role.
};
constexpr uint16_t kAloc16Leader = 0xfc00;
constexpr uint16_t kAloc16DhcpAgentStart = 0xfc01;
constexpr uint16_t kAloc16DhcpAgentEnd = 0xfc0f;
constexpr uint16_t kAloc16ServiceStart = 0xfc10;
constexpr uint16_t kAloc16ServiceEnd = 0xfc2f;
constexpr uint16_t kAloc16CommissionerStart = 0xfc30;
constexpr uint16_t kAloc16CommissionerEnd = 0xfc37;
constexpr uint16_t kAloc16BackboneRouterPrimary = 0xfc38;
constexpr uint16_t kAloc16CommissionerMask = 0x0007;
constexpr uint16_t kAloc16NeighborDiscoveryAgentStart = 0xfc40;
constexpr uint16_t kAloc16NeighborDiscoveryAgentEnd = 0xfc4e;
/**
* Specifies the leader role start mode.
*
* The start mode indicates whether device is starting normally as leader or restoring its role after reset.
*
*/
enum LeaderStartMode : uint8_t
{
kStartingAsLeader, ///< Starting as leader normally.
kRestoringLeaderRoleAfterReset, ///< Restoring leader role after reset.
};
/**
* Represents a MLE device mode.
*
*/
class DeviceMode : public Equatable<DeviceMode>
{
public:
static constexpr uint8_t kModeRxOnWhenIdle = 1 << 3; ///< If to keep receiver on when not transmitting.
static constexpr uint8_t kModeReserved = 1 << 2; ///< Set on transmission, ignore on reception.
static constexpr uint8_t kModeFullThreadDevice = 1 << 1; ///< If the device is an FTD.
static constexpr uint8_t kModeFullNetworkData = 1 << 0; ///< If the device requires the full Network Data.
static constexpr uint16_t kInfoStringSize = 45; ///< String buffer size used for `ToString()`.
/**
* Defines the fixed-length `String` object returned from `ToString()`.
*
*/
typedef String<kInfoStringSize> InfoString;
/**
* This structure represents an MLE Mode configuration.
*
*/
typedef otLinkModeConfig ModeConfig;
/**
* This is the default constructor for `DeviceMode` object.
*
*/
DeviceMode(void) = default;
/**
* Initializes a `DeviceMode` object from a given mode TLV bitmask.
*
* @param[in] aMode A mode TLV bitmask to initialize the `DeviceMode` object.
*
*/
explicit DeviceMode(uint8_t aMode) { Set(aMode); }
/**
* Initializes a `DeviceMode` object from a given mode configuration structure.
*
* @param[in] aModeConfig A mode configuration to initialize the `DeviceMode` object.
*
*/
explicit DeviceMode(ModeConfig aModeConfig) { Set(aModeConfig); }
/**
* Gets the device mode as a mode TLV bitmask.
*
* @returns The device mode as a mode TLV bitmask.
*
*/
uint8_t Get(void) const { return mMode; }
/**
* Sets the device mode from a given mode TLV bitmask.
*
* @param[in] aMode A mode TLV bitmask.
*
*/
void Set(uint8_t aMode) { mMode = aMode | kModeReserved; }
/**
* Gets the device mode as a mode configuration structure.
*
* @param[out] aModeConfig A reference to a mode configuration structure to output the device mode.
*
*/
void Get(ModeConfig &aModeConfig) const;
/**
* this method sets the device mode from a given mode configuration structure.
*
* @param[in] aModeConfig A mode configuration structure.
*
*/
void Set(const ModeConfig &aModeConfig);
/**
* Indicates whether or not the device is rx-on-when-idle.
*
* @retval TRUE If the device is rx-on-when-idle (non-sleepy).
* @retval FALSE If the device is not rx-on-when-idle (sleepy).
*
*/
bool IsRxOnWhenIdle(void) const { return (mMode & kModeRxOnWhenIdle) != 0; }
/**
* Indicates whether or not the device is a Full Thread Device.
*
* @retval TRUE If the device is Full Thread Device.
* @retval FALSE If the device if not Full Thread Device.
*
*/
bool IsFullThreadDevice(void) const { return (mMode & kModeFullThreadDevice) != 0; }
/**
* Gets the Network Data type (full set or stable subset) that the device requests.
*
* @returns The Network Data type requested by this device.
*
*/
NetworkData::Type GetNetworkDataType(void) const
{
return (mMode & kModeFullNetworkData) ? NetworkData::kFullSet : NetworkData::kStableSubset;
}
/**
* Indicates whether or not the device is a Minimal End Device.
*
* @retval TRUE If the device is a Minimal End Device.
* @retval FALSE If the device is not a Minimal End Device.
*
*/
bool IsMinimalEndDevice(void) const
{
return (mMode & (kModeFullThreadDevice | kModeRxOnWhenIdle)) != (kModeFullThreadDevice | kModeRxOnWhenIdle);
}
/**
* Indicates whether or not the device mode flags are valid.
*
* An FTD which is not rx-on-when-idle (is sleepy) is considered invalid.
*
* @returns TRUE if , FALSE otherwise.
* @retval TRUE If the device mode flags are valid.
* @retval FALSE If the device mode flags are not valid.
*
*/
bool IsValid(void) const { return !IsFullThreadDevice() || IsRxOnWhenIdle(); }
/**
* Converts the device mode into a human-readable string.
*
* @returns An `InfoString` object representing the device mode.
*
*/
InfoString ToString(void) const;
private:
uint8_t mMode;
};
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
/**
* Represents device properties.
*
* The device properties are used for calculating the local leader weight on the device.
*
*/
class DeviceProperties : public otDeviceProperties, public Clearable<DeviceProperties>
{
public:
/**
* Represents the device's power supply property.
*
*/
enum PowerSupply : uint8_t
{
kPowerSupplyBattery = OT_POWER_SUPPLY_BATTERY, ///< Battery powered.
kPowerSupplyExternal = OT_POWER_SUPPLY_EXTERNAL, ///< External powered.
kPowerSupplyExternalStable = OT_POWER_SUPPLY_EXTERNAL_STABLE, ///< Stable external power with backup.
kPowerSupplyExternalUnstable = OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, ///< Unstable external power.
};
/**
* Initializes `DeviceProperties` with default values.
*
*/
DeviceProperties(void);
/**
* Clamps the `mLeaderWeightAdjustment` value to the valid range.
*
*/
void ClampWeightAdjustment(void);
/**
* Calculates the leader weight based on the device properties.
*
* @returns The calculated leader weight.
*
*/
uint8_t CalculateLeaderWeight(void) const;
private:
static constexpr int8_t kDefaultAdjustment = OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT;
static constexpr uint8_t kBaseWeight = 64;
static constexpr int8_t kBorderRouterInc = +1;
static constexpr int8_t kCcmBorderRouterInc = +8;
static constexpr int8_t kIsUnstableInc = -4;
static constexpr int8_t kPowerBatteryInc = -8;
static constexpr int8_t kPowerExternalInc = 0;
static constexpr int8_t kPowerExternalStableInc = +4;
static constexpr int8_t kPowerExternalUnstableInc = -4;
static constexpr int8_t kMinAdjustment = -16;
static constexpr int8_t kMaxAdjustment = +16;
static_assert(kDefaultAdjustment >= kMinAdjustment, "Invalid default weight adjustment");
static_assert(kDefaultAdjustment <= kMaxAdjustment, "Invalid default weight adjustment");
};
#endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
/**
* Represents the Thread Leader Data.
*
*/
class LeaderData : public otLeaderData, public Clearable<LeaderData>
{
public:
/**
* Returns the Partition ID value.
*
* @returns The Partition ID value.
*
*/
uint32_t GetPartitionId(void) const { return mPartitionId; }
/**
* Sets the Partition ID value.
*
* @param[in] aPartitionId The Partition ID value.
*
*/
void SetPartitionId(uint32_t aPartitionId) { mPartitionId = aPartitionId; }
/**
* Returns the Weighting value.
*
* @returns The Weighting value.
*
*/
uint8_t GetWeighting(void) const { return mWeighting; }
/**
* Sets the Weighting value.
*
* @param[in] aWeighting The Weighting value.
*
*/
void SetWeighting(uint8_t aWeighting) { mWeighting = aWeighting; }
/**
* Returns the Data Version value for a type (full set or stable subset).
*
* @param[in] aType The Network Data type (full set or stable subset).
*
* @returns The Data Version value for @p aType.
*
*/
uint8_t GetDataVersion(NetworkData::Type aType) const
{
return (aType == NetworkData::kFullSet) ? mDataVersion : mStableDataVersion;
}
/**
* Sets the Data Version value.
*
* @param[in] aVersion The Data Version value.
*
*/
void SetDataVersion(uint8_t aVersion) { mDataVersion = aVersion; }
/**
* Sets the Stable Data Version value.
*
* @param[in] aVersion The Stable Data Version value.
*
*/
void SetStableDataVersion(uint8_t aVersion) { mStableDataVersion = aVersion; }
/**
* Returns the Leader Router ID value.
*
* @returns The Leader Router ID value.
*
*/
uint8_t GetLeaderRouterId(void) const { return mLeaderRouterId; }
/**
* Sets the Leader Router ID value.
*
* @param[in] aRouterId The Leader Router ID value.
*
*/
void SetLeaderRouterId(uint8_t aRouterId) { mLeaderRouterId = aRouterId; }
};
OT_TOOL_PACKED_BEGIN
class RouterIdSet : public Equatable<RouterIdSet>
{
public:
/**
* Clears the Router Id Set.
*
*/
void Clear(void) { memset(mRouterIdSet, 0, sizeof(mRouterIdSet)); }
/**
* Indicates whether or not a Router ID bit is set.
*
* @param[in] aRouterId The Router ID.
*
* @retval TRUE If the Router ID bit is set.
* @retval FALSE If the Router ID bit is not set.
*
*/
bool Contains(uint8_t aRouterId) const { return (mRouterIdSet[aRouterId / 8] & MaskFor(aRouterId)) != 0; }
/**
* Sets a given Router ID.
*
* @param[in] aRouterId The Router ID to set.
*
*/
void Add(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] |= MaskFor(aRouterId); }
/**
* Removes a given Router ID.
*
* @param[in] aRouterId The Router ID to remove.
*
*/
void Remove(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] &= ~MaskFor(aRouterId); }
/**
* Calculates the number of allocated Router IDs in the set.
*
* @returns The number of allocated Router IDs in the set.
*
*/
uint8_t GetNumberOfAllocatedIds(void) const;
private:
static uint8_t MaskFor(uint8_t aRouterId) { return (0x80 >> (aRouterId % 8)); }
uint8_t mRouterIdSet[BitVectorBytes(Mle::kMaxRouterId + 1)];
} OT_TOOL_PACKED_END;
class TxChallenge;
/**
* Represents a received Challenge data from an MLE message.
*
*/
class RxChallenge
{
public:
static constexpr uint8_t kMinSize = 4; ///< Minimum Challenge size in bytes.
static constexpr uint8_t kMaxSize = 8; ///< Maximum Challenge size in bytes.
/**
* Clears the challenge.
*
*/
void Clear(void) { mArray.Clear(); }
/**
* Indicates whether or not the challenge data is empty.
*
* @retval TRUE The challenge is empty.
* @retval FALSE The challenge is not empty.
*
*/
bool IsEmpty(void) const { return mArray.GetLength() == 0; }
/**
* Gets a pointer to challenge data bytes.
*
* @return A pointer to the challenge data bytes.
*
*/
const uint8_t *GetBytes(void) const { return mArray.GetArrayBuffer(); }
/**
* Gets the length of challenge data.
*
* @returns The length of challenge data in bytes.
*
*/
uint8_t GetLength(void) const { return mArray.GetLength(); }
/**
* Reads the challenge bytes from given message.
*
* If the given @p aLength is longer than `kMaxSize`, only `kMaxSize` bytes will be read.
*
* @param[in] aMessage The message to read the challenge from.
* @param[in] aOffset The offset in @p aMessage to read from.
* @param[in] aLength Number of bytes to read.
*
* @retval kErrorNone Successfully read the challenge data from @p aMessage.
* @retval kErrorParse Not enough bytes to read, or invalid @p aLength (smaller than `kMinSize`).
*
*/
Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
/**
* Compares the `RxChallenge` with a given `TxChallenge`.
*
* @param[in] aTxChallenge The `TxChallenge` to compare with.
*
* @retval TRUE The two challenges are equal.
* @retval FALSE The two challenges are not equal.
*
*/
bool operator==(const TxChallenge &aTxChallenge) const;
private:
Array<uint8_t, kMaxSize> mArray;
};
/**
* Represents a max-sized challenge data to send in MLE message.
*
* OpenThread always uses max size challenge when sending MLE messages.
*
*/
class TxChallenge : public Clearable<TxChallenge>
{
friend class RxChallenge;
public:
/**
* Generates a cryptographically secure random sequence to populate the challenge data.
*
*/
void GenerateRandom(void);
private:
uint8_t m8[RxChallenge::kMaxSize];
};
/**
* Represents a MLE Key Material
*
*/
typedef Mac::KeyMaterial KeyMaterial;
/**
* Represents a MLE Key.
*
*/
typedef Mac::Key Key;
/**
* Represents the Thread MLE counters.
*
*/
typedef otMleCounters Counters;
/**
* Derives the Child ID from a given RLOC16.
*
* @param[in] aRloc16 The RLOC16 value.
*
* @returns The Child ID portion of an RLOC16.
*
*/
inline uint16_t ChildIdFromRloc16(uint16_t aRloc16) { return aRloc16 & kMaxChildId; }
/**
* Derives the Router ID portion from a given RLOC16.
*
* @param[in] aRloc16 The RLOC16 value.
*
* @returns The Router ID portion of an RLOC16.
*
*/
inline uint8_t RouterIdFromRloc16(uint16_t aRloc16) { return aRloc16 >> kRouterIdOffset; }
/**
* Returns whether the two RLOC16 have the same Router ID.
*
* @param[in] aRloc16A The first RLOC16 value.
* @param[in] aRloc16B The second RLOC16 value.
*
* @returns true if the two RLOC16 have the same Router ID, false otherwise.
*
*/
inline bool RouterIdMatch(uint16_t aRloc16A, uint16_t aRloc16B)
{
return RouterIdFromRloc16(aRloc16A) == RouterIdFromRloc16(aRloc16B);
}
/**
* Returns the Service ID corresponding to a Service ALOC16.
*
* @param[in] aAloc16 The Service ALOC16 value.
*
* @returns The Service ID corresponding to given ALOC16.
*
*/
inline uint8_t ServiceIdFromAloc(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kAloc16ServiceStart); }
/**
* Returns the Service ALOC16 corresponding to a Service ID.
*
* @param[in] aServiceId The Service ID value.
*
* @returns The Service ALOC16 corresponding to given ID.
*
*/
inline uint16_t ServiceAlocFromId(uint8_t aServiceId)
{
return static_cast<uint16_t>(aServiceId + kAloc16ServiceStart);
}
/**
* Returns the Commissioner Aloc corresponding to a Commissioner Session ID.
*
* @param[in] aSessionId The Commissioner Session ID value.
*
* @returns The Commissioner ALOC16 corresponding to given ID.
*
*/
inline uint16_t CommissionerAloc16FromId(uint16_t aSessionId)
{
return static_cast<uint16_t>((aSessionId & kAloc16CommissionerMask) + kAloc16CommissionerStart);
}
/**
* Derives RLOC16 from a given Router ID.
*
* @param[in] aRouterId The Router ID value.
*
* @returns The RLOC16 corresponding to the given Router ID.
*
*/
inline uint16_t Rloc16FromRouterId(uint8_t aRouterId) { return static_cast<uint16_t>(aRouterId << kRouterIdOffset); }
/**
* Indicates whether or not @p aRloc16 refers to an active router.
*
* @param[in] aRloc16 The RLOC16 value.
*
* @retval TRUE If @p aRloc16 refers to an active router.
* @retval FALSE If @p aRloc16 does not refer to an active router.
*
*/
inline bool IsActiveRouter(uint16_t aRloc16) { return ChildIdFromRloc16(aRloc16) == 0; }
/**
* Converts a device role into a human-readable string.
*
* @param[in] aRole The device role to convert.
*
* @returns The string representation of @p aRole.
*
*/
const char *RoleToString(DeviceRole aRole);
/**
* @}
*
*/
} // namespace Mle
DefineCoreType(otLeaderData, Mle::LeaderData);
DefineMapEnum(otDeviceRole, Mle::DeviceRole);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
DefineCoreType(otDeviceProperties, Mle::DeviceProperties);
DefineMapEnum(otPowerSupply, Mle::DeviceProperties::PowerSupply);
#endif
} // namespace ot
#endif // MLE_TYPES_HPP_