mirror of
https://github.com/espressif/openthread.git
synced 2026-10-04 06:47:36 +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:
@@ -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