mirror of
https://github.com/espressif/openthread.git
synced 2026-08-25 03:39:52 +00:00
[mle] add otDeviceProperties to calculate local leader weight (#8670)
This commit adds `otDeviceProperties` which represents a set of device properties which are used to calculate and set the local Leader Weight on the device. The device property set contains a `otPowerSupplyConfig` enum value specifying the device power supply: - Battery powered. - Externally powered (mains-powered). - Stable external power with a battery backup or UPS. - Unstable external power (e.g., a light bulb powered via a switch). It also indicates whether or not device is a border router, supports CCM, and specifies a Leader Weight adjustment value. The `otDeviceProperties` can be set through the newly added OT public API `otThreadSetDeviceProperties()`. Its default value (upon OT stack start) can also be configured using OT configs: - Newly added `OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY` specifies the default power supply config to use. This config can also be set using the newly added CMake option `OT_POWER_SUPPLY`. - Existing `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` will indicate if device is acting as a BR. This commit also adds CLI command `deviceprops` for getting/setting the device config. It also adds a unit test to validate the Leader Weight calculation algorithm from a given device config.
This commit is contained in:
@@ -157,6 +157,23 @@ if(OT_FULL_LOGS)
|
||||
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1")
|
||||
endif()
|
||||
|
||||
set(OT_POWER_SUPPLY "" CACHE STRING "set the device power supply config")
|
||||
set(OT_POWER_SUPPLY_VALUES
|
||||
""
|
||||
"BATTERY"
|
||||
"EXTERNAL"
|
||||
"EXTERNAL_STABLE"
|
||||
"EXTERNAL_UNSTABLE"
|
||||
)
|
||||
set_property(CACHE OT_POWER_SUPPLY PROPERTY STRINGS ${OT_POWER_SUPPLY_VALUES})
|
||||
string(COMPARE EQUAL "${OT_POWER_SUPPLY}" "" is_empty)
|
||||
if (is_empty)
|
||||
message(STATUS "OT_POWER_SUPPLY=\"\"")
|
||||
else()
|
||||
message(STATUS "OT_POWER_SUPPLY=${OT_POWER_SUPPLY} --> OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY=OT_POWER_SUPPLY_${OT_POWER_SUPPLY}")
|
||||
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY=OT_POWER_SUPPLY_${OT_POWER_SUPPLY}")
|
||||
endif()
|
||||
|
||||
set(OT_MLE_MAX_CHILDREN "" CACHE STRING "set maximum number of children")
|
||||
if(OT_MLE_MAX_CHILDREN MATCHES "^[0-9]+$")
|
||||
message(STATUS "OT_MLE_MAX_CHILDREN=${OT_MLE_MAX_CHILDREN}")
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (302)
|
||||
#define OPENTHREAD_API_VERSION (303)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -196,6 +196,59 @@ otError otThreadSetRouterEligible(otInstance *aInstance, bool aEligible);
|
||||
*/
|
||||
otError otThreadSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This enumeration represents the power supply property on a device.
|
||||
*
|
||||
* This is used as a property in `otDeviceProperties` to calculate the leader weight.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
OT_POWER_SUPPLY_BATTERY = 0, ///< Battery powered.
|
||||
OT_POWER_SUPPLY_EXTERNAL = 1, ///< Externally powered (mains-powered).
|
||||
OT_POWER_SUPPLY_EXTERNAL_STABLE = 2, ///< Stable external power with a battery backup or UPS.
|
||||
OT_POWER_SUPPLY_EXTERNAL_UNSTABLE = 3, ///< Potentially unstable ext power (e.g. light bulb powered via a switch).
|
||||
} otPowerSupply;
|
||||
|
||||
/**
|
||||
* This structure represents the device properties which are used for calculating the local leader weight on a
|
||||
* device.
|
||||
*
|
||||
* The parameters are set based on device's capability, whether acting as border router, its power supply config, etc.
|
||||
*
|
||||
* `mIsUnstable` indicates operational stability of device and is determined via a vendor specific mechanism. It can
|
||||
* include the following cases:
|
||||
* - Device internally detects that it loses external power supply more often than usual. What is usual is
|
||||
* determined by the vendor.
|
||||
* - Device internally detects that it reboots more often than usual. What is usual is determined by the vendor.
|
||||
*
|
||||
*/
|
||||
typedef struct otDeviceProperties
|
||||
{
|
||||
otPowerSupply mPowerSupply; ///< Power supply config.
|
||||
bool mIsBorderRouter : 1; ///< Whether device is a border router.
|
||||
bool mSupportsCcm : 1; ///< Whether device supports CCM (can act as a CCM border router).
|
||||
bool mIsUnstable : 1; ///< Operational stability of device (vendor specific).
|
||||
int8_t mLeaderWeightAdjustment; ///< Weight adjustment. Should be -16 to +16 (clamped otherwise).
|
||||
} otDeviceProperties;
|
||||
|
||||
/**
|
||||
* Get the current device properties.
|
||||
*
|
||||
* @returns The device properties `otDeviceProperties`.
|
||||
*
|
||||
*/
|
||||
const otDeviceProperties *otThreadGetDeviceProperties(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Set the device properties which are then used to determine and set the Leader Weight.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aDeviceProperties The device properties.
|
||||
*
|
||||
*/
|
||||
void otThreadSetDeviceProperties(otInstance *aInstance, const otDeviceProperties *aDeviceProperties);
|
||||
|
||||
/**
|
||||
* Gets the Thread Leader Weight used when operating in the Leader role.
|
||||
*
|
||||
@@ -204,6 +257,7 @@ otError otThreadSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId);
|
||||
* @returns The Thread Leader Weight value.
|
||||
*
|
||||
* @sa otThreadSetLeaderWeight
|
||||
* @sa otThreadSetDeviceProperties
|
||||
*
|
||||
*/
|
||||
uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance);
|
||||
@@ -211,6 +265,9 @@ uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance);
|
||||
/**
|
||||
* Sets the Thread Leader Weight used when operating in the Leader role.
|
||||
*
|
||||
* This function directly sets the Leader Weight to the new value, replacing its previous value (which may have been
|
||||
* determined from the current `otDeviceProperties`).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aWeight The Thread Leader Weight value.
|
||||
*
|
||||
|
||||
@@ -41,6 +41,7 @@ Done
|
||||
- [csl](#csl)
|
||||
- [dataset](README_DATASET.md)
|
||||
- [delaytimermin](#delaytimermin)
|
||||
- [deviceprops](#deviceprops)
|
||||
- [diag](#diag)
|
||||
- [discover](#discover-channel)
|
||||
- [dns](#dns-config)
|
||||
@@ -1056,6 +1057,44 @@ Set the minimal delay timer (in seconds).
|
||||
Done
|
||||
```
|
||||
|
||||
### deviceprops
|
||||
|
||||
Get the current device properties.
|
||||
|
||||
```bash
|
||||
> deviceprops
|
||||
PowerSupply : external
|
||||
IsBorderRouter : yes
|
||||
SupportsCcm : no
|
||||
IsUnstable : no
|
||||
WeightAdjustment : 0
|
||||
Done
|
||||
```
|
||||
|
||||
### deviceprops \<power-supply\> \<is-br\> \<supports-ccm\> \<is-unstable\> \<weight-adjustment\>
|
||||
|
||||
Set the device properties which are then used to determine and set the Leader Weight.
|
||||
|
||||
- power-supply: `battery`, `external`, `external-stable`, or `external-unstable`.
|
||||
- weight-adjustment: Valid range is from -16 to +16. Clamped if not within the range.
|
||||
|
||||
```bash
|
||||
> deviceprops battery 0 0 0 -5
|
||||
Done
|
||||
|
||||
> deviceprops
|
||||
PowerSupply : battery
|
||||
IsBorderRouter : no
|
||||
SupportsCcm : no
|
||||
IsUnstable : no
|
||||
WeightAdjustment : -5
|
||||
Done
|
||||
|
||||
> leaderweight
|
||||
51
|
||||
Done
|
||||
```
|
||||
|
||||
### discover \[channel\]
|
||||
|
||||
Perform an MLE Discovery operation.
|
||||
|
||||
+103
@@ -4290,6 +4290,106 @@ template <> otError Interpreter::Process<Cmd("leaderweight")>(Arg aArgs[])
|
||||
*/
|
||||
return ProcessGetSet(aArgs, otThreadGetLocalLeaderWeight, otThreadSetLocalLeaderWeight);
|
||||
}
|
||||
|
||||
template <> otError Interpreter::Process<Cmd("deviceprops")>(Arg aArgs[])
|
||||
{
|
||||
static const char *const kPowerSupplyStrings[4] = {
|
||||
"battery", // (0) OT_POWER_SUPPLY_BATTERY
|
||||
"external", // (1) OT_POWER_SUPPLY_EXTERNAL
|
||||
"external-stable", // (2) OT_POWER_SUPPLY_EXTERNAL_STABLE
|
||||
"external-unstable", // (3) OT_POWER_SUPPLY_EXTERNAL_UNSTABLE
|
||||
};
|
||||
|
||||
static_assert(0 == OT_POWER_SUPPLY_BATTERY, "OT_POWER_SUPPLY_BATTERY value is incorrect");
|
||||
static_assert(1 == OT_POWER_SUPPLY_EXTERNAL, "OT_POWER_SUPPLY_EXTERNAL value is incorrect");
|
||||
static_assert(2 == OT_POWER_SUPPLY_EXTERNAL_STABLE, "OT_POWER_SUPPLY_EXTERNAL_STABLE value is incorrect");
|
||||
static_assert(3 == OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, "OT_POWER_SUPPLY_EXTERNAL_UNSTABLE value is incorrect");
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
/**
|
||||
* @cli deviceprops
|
||||
* @code
|
||||
* deviceprops
|
||||
* PowerSupply : external
|
||||
* IsBorderRouter : yes
|
||||
* SupportsCcm : no
|
||||
* IsUnstable : no
|
||||
* WeightAdjustment : 0
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otThreadGetDeviceProperties
|
||||
*/
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
const otDeviceProperties *props = otThreadGetDeviceProperties(GetInstancePtr());
|
||||
|
||||
OutputLine("PowerSupply : %s", Stringify(props->mPowerSupply, kPowerSupplyStrings));
|
||||
OutputLine("IsBorderRouter : %s", props->mIsBorderRouter ? "yes" : "no");
|
||||
OutputLine("SupportsCcm : %s", props->mSupportsCcm ? "yes" : "no");
|
||||
OutputLine("IsUnstable : %s", props->mIsUnstable ? "yes" : "no");
|
||||
OutputLine("WeightAdjustment : %d", props->mLeaderWeightAdjustment);
|
||||
}
|
||||
/**
|
||||
* @cli deviceprops (set)
|
||||
* @code
|
||||
* deviceprops battery 0 0 0 -5
|
||||
* Done
|
||||
* @endcode
|
||||
* @code
|
||||
* deviceprops
|
||||
* PowerSupply : battery
|
||||
* IsBorderRouter : no
|
||||
* SupportsCcm : no
|
||||
* IsUnstable : no
|
||||
* WeightAdjustment : -5
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam deviceprops @ca{powerSupply} @ca{isBr} @ca{supportsCcm} @ca{isUnstable} @ca{weightAdjustment}
|
||||
* `powerSupply`: should be 'battery', 'external', 'external-stable', 'external-unstable'.
|
||||
* @par
|
||||
* Sets the device properties.
|
||||
* @csa{leaderweight}
|
||||
* @csa{leaderweight (set)}
|
||||
* @sa #otThreadSetDeviceProperties
|
||||
*/
|
||||
else
|
||||
{
|
||||
otDeviceProperties props;
|
||||
bool value;
|
||||
uint8_t index;
|
||||
|
||||
for (index = 0; index < OT_ARRAY_LENGTH(kPowerSupplyStrings); index++)
|
||||
{
|
||||
if (aArgs[0] == kPowerSupplyStrings[index])
|
||||
{
|
||||
props.mPowerSupply = static_cast<otPowerSupply>(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(index < OT_ARRAY_LENGTH(kPowerSupplyStrings), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = aArgs[1].ParseAsBool(value));
|
||||
props.mIsBorderRouter = value;
|
||||
|
||||
SuccessOrExit(error = aArgs[2].ParseAsBool(value));
|
||||
props.mSupportsCcm = value;
|
||||
|
||||
SuccessOrExit(error = aArgs[3].ParseAsBool(value));
|
||||
props.mIsUnstable = value;
|
||||
|
||||
SuccessOrExit(error = aArgs[4].ParseAsInt8(props.mLeaderWeightAdjustment));
|
||||
|
||||
VerifyOrExit(aArgs[5].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
otThreadSetDeviceProperties(GetInstancePtr(), &props);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
@@ -8053,6 +8153,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
|
||||
#endif
|
||||
CmdEntry("detach"),
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
#if OPENTHREAD_FTD
|
||||
CmdEntry("deviceprops"),
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
CmdEntry("diag"),
|
||||
#endif
|
||||
|
||||
@@ -79,6 +79,16 @@ otError otThreadSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId)
|
||||
return AsCoreType(aInstance).Get<Mle::MleRouter>().SetPreferredRouterId(aRouterId);
|
||||
}
|
||||
|
||||
const otDeviceProperties *otThreadGetDeviceProperties(otInstance *aInstance)
|
||||
{
|
||||
return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetDeviceProperties();
|
||||
}
|
||||
|
||||
void otThreadSetDeviceProperties(otInstance *aInstance, const otDeviceProperties *aDeviceProperties)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Mle::MleRouter>().SetDeviceProperties(AsCoreType(aDeviceProperties));
|
||||
}
|
||||
|
||||
uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderWeight();
|
||||
|
||||
@@ -77,6 +77,19 @@
|
||||
#define OPENTHREAD_CONFIG_STACK_VERSION_MINOR 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY
|
||||
*
|
||||
* Specifies the default device power supply config. This config MUST use values from `otPowerSupply` enumeration.
|
||||
*
|
||||
* Device manufacturer can use this config to set the power supply config used by the device. This is then used as part
|
||||
* of default `otDeviceProperties` to determine the Leader Weight used by the device.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY
|
||||
#define OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY OT_POWER_SUPPLY_EXTERNAL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
*
|
||||
|
||||
@@ -88,6 +88,18 @@
|
||||
#define OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER (OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT
|
||||
*
|
||||
* Specifies the default value for `mLeaderWeightAdjustment` in `otDeviceProperties`. MUST be from -16 up to +16.
|
||||
*
|
||||
* This value is used to adjust the calculated Leader Weight from `otDeviceProperties`.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT
|
||||
#define OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
*
|
||||
|
||||
@@ -70,7 +70,6 @@ MleRouter::MleRouter(Instance &aInstance)
|
||||
, mNetworkIdTimeout(kNetworkIdTimeout)
|
||||
, mRouterUpgradeThreshold(kRouterUpgradeThreshold)
|
||||
, mRouterDowngradeThreshold(kRouterDowngradeThreshold)
|
||||
, mLeaderWeight(kLeaderWeight)
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
, mPreferredLeaderPartitionId(0)
|
||||
, mCcmEnabled(false)
|
||||
@@ -95,6 +94,7 @@ MleRouter::MleRouter(Instance &aInstance)
|
||||
#endif
|
||||
{
|
||||
mDeviceMode.Set(mDeviceMode.Get() | DeviceMode::kModeFullThreadDevice | DeviceMode::kModeFullNetworkData);
|
||||
mLeaderWeight = mDeviceProperties.CalculateLeaderWeight();
|
||||
|
||||
SetRouterId(kInvalidRouterId);
|
||||
|
||||
@@ -183,6 +183,13 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::SetDeviceProperties(const DeviceProperties &aDeviceProperties)
|
||||
{
|
||||
mDeviceProperties = aDeviceProperties;
|
||||
mDeviceProperties.ClampWeightAdjustment();
|
||||
SetLeaderWeight(mDeviceProperties.CalculateLeaderWeight());
|
||||
}
|
||||
|
||||
Error MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -143,6 +143,22 @@ public:
|
||||
*/
|
||||
Error BecomeLeader(void);
|
||||
|
||||
/**
|
||||
* This method gets the device properties which are used to determine the Leader Weight.
|
||||
*
|
||||
* @returns The current device properties.
|
||||
*
|
||||
*/
|
||||
const DeviceProperties &GetDeviceProperties(void) const { return mDeviceProperties; }
|
||||
|
||||
/**
|
||||
* This method sets the device properties which are then used to determine and set the Leader Weight.
|
||||
*
|
||||
* @param[in] aDeviceProperties The device properties.
|
||||
*
|
||||
*/
|
||||
void SetDeviceProperties(const DeviceProperties &aDeviceProperties);
|
||||
|
||||
/**
|
||||
* This method returns the Leader Weighting value for this Thread interface.
|
||||
*
|
||||
@@ -154,6 +170,9 @@ public:
|
||||
/**
|
||||
* This method sets the Leader Weighting value for this Thread interface.
|
||||
*
|
||||
* This method directly sets the Leader Weight to the new value replacing its previous value (which may have been
|
||||
* determined from a previous call to `SetDeviceProperties()`).
|
||||
*
|
||||
* @param[in] aWeight The Leader Weighting value.
|
||||
*
|
||||
*/
|
||||
@@ -636,6 +655,8 @@ private:
|
||||
|
||||
TrickleTimer mAdvertiseTrickleTimer;
|
||||
|
||||
DeviceProperties mDeviceProperties;
|
||||
|
||||
ChildTable mChildTable;
|
||||
RouterTable mRouterTable;
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
namespace ot {
|
||||
namespace Mle {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// DeviceMode
|
||||
|
||||
void DeviceMode::Get(ModeConfig &aModeConfig) const
|
||||
{
|
||||
aModeConfig.mRxOnWhenIdle = IsRxOnWhenIdle();
|
||||
@@ -64,6 +67,77 @@ DeviceMode::InfoString DeviceMode::ToString(void) const
|
||||
return string;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// DeviceProperties
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
DeviceProperties::DeviceProperties(void)
|
||||
{
|
||||
Clear();
|
||||
|
||||
mPowerSupply = OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY;
|
||||
mLeaderWeightAdjustment = kDefaultAdjustment;
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
mIsBorderRouter = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DeviceProperties::ClampWeightAdjustment(void)
|
||||
{
|
||||
mLeaderWeightAdjustment = Clamp(mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment);
|
||||
}
|
||||
|
||||
uint8_t DeviceProperties::CalculateLeaderWeight(void) const
|
||||
{
|
||||
static const int8_t kPowerSupplyIncs[] = {
|
||||
kPowerBatteryInc, // (0) kPowerSupplyBattery
|
||||
kPowerExternalInc, // (1) kPowerSupplyExternal
|
||||
kPowerExternalStableInc, // (2) kPowerSupplyExternalStable
|
||||
kPowerExternalUnstableInc, // (3) kPowerSupplyExternalUnstable
|
||||
};
|
||||
|
||||
static_assert(0 == kPowerSupplyBattery, "kPowerSupplyBattery value is incorrect");
|
||||
static_assert(1 == kPowerSupplyExternal, "kPowerSupplyExternal value is incorrect");
|
||||
static_assert(2 == kPowerSupplyExternalStable, "kPowerSupplyExternalStable value is incorrect");
|
||||
static_assert(3 == kPowerSupplyExternalUnstable, "kPowerSupplyExternalUnstable value is incorrect");
|
||||
|
||||
uint8_t weight = kBaseWeight;
|
||||
PowerSupply powerSupply = MapEnum(mPowerSupply);
|
||||
|
||||
if (mIsBorderRouter)
|
||||
{
|
||||
weight += (mSupportsCcm ? kCcmBorderRouterInc : kBorderRouterInc);
|
||||
}
|
||||
|
||||
if (powerSupply < GetArrayLength(kPowerSupplyIncs))
|
||||
{
|
||||
weight += kPowerSupplyIncs[powerSupply];
|
||||
}
|
||||
|
||||
if (mIsUnstable)
|
||||
{
|
||||
switch (powerSupply)
|
||||
{
|
||||
case kPowerSupplyBattery:
|
||||
case kPowerSupplyExternalUnstable:
|
||||
break;
|
||||
|
||||
default:
|
||||
weight += kIsUnstableInc;
|
||||
}
|
||||
}
|
||||
|
||||
weight += mLeaderWeightAdjustment;
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// RouterIdSet
|
||||
|
||||
uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const
|
||||
{
|
||||
uint8_t count = 0;
|
||||
@@ -76,6 +150,8 @@ uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const
|
||||
return count;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
const char *RoleToString(DeviceRole aRole)
|
||||
{
|
||||
static const char *const kRoleStrings[] = {
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread/thread.h>
|
||||
#if OPENTHREAD_FTD
|
||||
#include <openthread/thread_ftd.h>
|
||||
#endif
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
@@ -181,7 +184,6 @@ constexpr uint32_t kMaxLeaderToRouterTimeout = 90; ///< (in sec)
|
||||
constexpr uint32_t kReedAdvertiseInterval = 570; ///< (in sec)
|
||||
constexpr uint32_t kReedAdvertiseJitter = 60; ///< (in sec)
|
||||
|
||||
constexpr uint8_t kLeaderWeight = 64; ///< Default leader weight
|
||||
constexpr uint32_t kMleEndDeviceTimeout = OPENTHREAD_CONFIG_MLE_CHILD_TIMEOUT_DEFAULT; ///< (in sec)
|
||||
constexpr uint8_t kMeshLocalPrefixContextId = 0; ///< 0 is reserved for Mesh Local Prefix
|
||||
|
||||
@@ -435,6 +437,67 @@ private:
|
||||
uint8_t mMode;
|
||||
};
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
/**
|
||||
* This class 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:
|
||||
/**
|
||||
* This enumeration 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.
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes `DeviceProperties` with default values.
|
||||
*
|
||||
*/
|
||||
DeviceProperties(void);
|
||||
|
||||
/**
|
||||
* This method clamps the `mLeaderWeightAdjustment` value to the valid range.
|
||||
*
|
||||
*/
|
||||
void ClampWeightAdjustment(void);
|
||||
|
||||
/**
|
||||
* This method 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 // OPENTHREAD_FTD
|
||||
|
||||
/**
|
||||
* This class represents the Thread Leader Data.
|
||||
*
|
||||
@@ -693,6 +756,10 @@ const char *RoleToString(DeviceRole aRole);
|
||||
|
||||
DefineCoreType(otLeaderData, Mle::LeaderData);
|
||||
DefineMapEnum(otDeviceRole, Mle::DeviceRole);
|
||||
#if OPENTHREAD_FTD
|
||||
DefineCoreType(otDeviceProperties, Mle::DeviceProperties);
|
||||
DefineMapEnum(otPowerSupply, Mle::DeviceProperties::PowerSupply);
|
||||
#endif
|
||||
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -665,6 +665,27 @@ target_link_libraries(ot-test-message-queue
|
||||
|
||||
add_test(NAME ot-test-message-queue COMMAND ot-test-message-queue)
|
||||
|
||||
add_executable(ot-test-mle
|
||||
test_mle.cpp
|
||||
)
|
||||
|
||||
target_include_directories(ot-test-mle
|
||||
PRIVATE
|
||||
${COMMON_INCLUDES}
|
||||
)
|
||||
|
||||
target_compile_options(ot-test-mle
|
||||
PRIVATE
|
||||
${COMMON_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_link_libraries(ot-test-mle
|
||||
PRIVATE
|
||||
${COMMON_LIBS}
|
||||
)
|
||||
|
||||
add_test(NAME ot-test-mle COMMAND ot-test-mle)
|
||||
|
||||
add_executable(ot-test-multicast-listeners-table
|
||||
test_multicast_listeners_table.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "test_platform.h"
|
||||
#include "test_util.hpp"
|
||||
|
||||
#include "common/num_utils.hpp"
|
||||
#include "thread/mle_types.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
void TestDefaultDeviceProperties(void)
|
||||
{
|
||||
Instance *instance;
|
||||
const otDeviceProperties *props;
|
||||
uint8_t weight;
|
||||
|
||||
instance = static_cast<Instance *>(testInitInstance());
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
props = otThreadGetDeviceProperties(instance);
|
||||
|
||||
VerifyOrQuit(props->mPowerSupply == OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY);
|
||||
VerifyOrQuit(!props->mSupportsCcm);
|
||||
VerifyOrQuit(!props->mIsUnstable);
|
||||
VerifyOrQuit(props->mLeaderWeightAdjustment == OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT);
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
VerifyOrQuit(props->mIsBorderRouter);
|
||||
#else
|
||||
VerifyOrQuit(!props->mIsBorderRouter);
|
||||
#endif
|
||||
|
||||
weight = 64;
|
||||
|
||||
switch (props->mPowerSupply)
|
||||
{
|
||||
case OT_POWER_SUPPLY_BATTERY:
|
||||
weight -= 8;
|
||||
break;
|
||||
case OT_POWER_SUPPLY_EXTERNAL:
|
||||
break;
|
||||
case OT_POWER_SUPPLY_EXTERNAL_STABLE:
|
||||
weight += 4;
|
||||
break;
|
||||
case OT_POWER_SUPPLY_EXTERNAL_UNSTABLE:
|
||||
weight -= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
weight += props->mIsBorderRouter ? 1 : 0;
|
||||
|
||||
VerifyOrQuit(otThreadGetLocalLeaderWeight(instance) == weight);
|
||||
|
||||
printf("TestDefaultDeviceProperties passed\n");
|
||||
}
|
||||
|
||||
void CompareDevicePropertiess(const otDeviceProperties &aFirst, const otDeviceProperties &aSecond)
|
||||
{
|
||||
static constexpr int8_t kMinAdjustment = -16;
|
||||
static constexpr int8_t kMaxAdjustment = +16;
|
||||
|
||||
VerifyOrQuit(aFirst.mPowerSupply == aSecond.mPowerSupply);
|
||||
VerifyOrQuit(aFirst.mIsBorderRouter == aSecond.mIsBorderRouter);
|
||||
VerifyOrQuit(aFirst.mSupportsCcm == aSecond.mSupportsCcm);
|
||||
VerifyOrQuit(aFirst.mIsUnstable == aSecond.mIsUnstable);
|
||||
VerifyOrQuit(Clamp(aFirst.mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment) ==
|
||||
Clamp(aSecond.mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment));
|
||||
}
|
||||
|
||||
void TestLeaderWeightCalculation(void)
|
||||
{
|
||||
struct TestCase
|
||||
{
|
||||
otDeviceProperties mDeviceProperties;
|
||||
uint8_t mExpectedLeaderWeight;
|
||||
};
|
||||
|
||||
static const TestCase kTestCases[] = {
|
||||
{{OT_POWER_SUPPLY_BATTERY, false, false, false, 0}, 56},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, false, false, false, 0}, 64},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, 0}, 68},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, 0}, 60},
|
||||
|
||||
{{OT_POWER_SUPPLY_BATTERY, true, false, false, 0}, 57},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, true, false, false, 0}, 65},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, 0}, 69},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, 0}, 61},
|
||||
|
||||
{{OT_POWER_SUPPLY_BATTERY, true, true, false, 0}, 64},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, true, true, false, 0}, 72},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, true, false, 0}, 76},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, true, false, 0}, 68},
|
||||
|
||||
// Check when `mIsUnstable` is set.
|
||||
{{OT_POWER_SUPPLY_BATTERY, false, false, true, 0}, 56},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, false, false, true, 0}, 60},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, true, 0}, 64},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, true, 0}, 60},
|
||||
|
||||
{{OT_POWER_SUPPLY_BATTERY, true, false, true, 0}, 57},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, true, false, true, 0}, 61},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, true, 0}, 65},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, true, 0}, 61},
|
||||
|
||||
// Include non-zero `mLeaderWeightAdjustment`.
|
||||
{{OT_POWER_SUPPLY_BATTERY, true, false, false, 10}, 67},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, true, false, false, 10}, 75},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, 10}, 79},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, 10}, 71},
|
||||
|
||||
{{OT_POWER_SUPPLY_BATTERY, false, false, false, -10}, 46},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, false, false, false, -10}, 54},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, -10}, 58},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, -10}, 50},
|
||||
|
||||
// Use `mLeaderWeightAdjustment` larger than valid range
|
||||
// Make sure it clamps to -16 and +16.
|
||||
{{OT_POWER_SUPPLY_BATTERY, false, false, false, 20}, 72},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, false, false, false, 20}, 80},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, 20}, 84},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, 20}, 76},
|
||||
|
||||
{{OT_POWER_SUPPLY_BATTERY, true, false, false, -20}, 41},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL, true, false, false, -20}, 49},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, -20}, 53},
|
||||
{{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, -20}, 45},
|
||||
};
|
||||
|
||||
Instance *instance;
|
||||
|
||||
instance = static_cast<Instance *>(testInitInstance());
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
for (const TestCase &testCase : kTestCases)
|
||||
{
|
||||
otThreadSetDeviceProperties(instance, &testCase.mDeviceProperties);
|
||||
CompareDevicePropertiess(testCase.mDeviceProperties, *otThreadGetDeviceProperties(instance));
|
||||
VerifyOrQuit(otThreadGetLocalLeaderWeight(instance) == testCase.mExpectedLeaderWeight);
|
||||
}
|
||||
|
||||
printf("TestLeaderWeightCalculation passed\n");
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#if OPENTHREAD_FTD
|
||||
ot::TestDefaultDeviceProperties();
|
||||
ot::TestLeaderWeightCalculation();
|
||||
#endif
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user