[mle] fix implementation of IsMinimalEndDevice() (#11926)

A Minimal End Device (MED) is defined by the spec as an MTD whose
receiver is enabled all the time.

This commit fixes the implementation of `IsMinimalEndDevice()` to
match this definition. The previous implementation of this method
would incorrectly accept any MTD config (including SED or MED).

Within the core modules, `IsMinimalEndDevice()` is only used in
`MeshForwarder::UpdateIp6Route()`. This commit updates the logic
in this method to differentiate between an FTD (calling
`UpdateIp6RouteFtd`()) and an MTD (forwarding to parent) by
checking `IsFullThreadDevice()` instead of the previous check
against `IsMinimalEndDevice()` (which was effectively checking
MTD).

This commit also adds a new unit test, `TestDeviceMode()`, to
validate all configurations of `DeviceMode` (SED, MED, FTD) and
verify the behavior of `IsMinimalEndDevice()`.
This commit is contained in:
Abtin Keshavarzian
2025-09-15 11:31:43 -07:00
committed by GitHub
parent eba5bdc434
commit f60b00695e
4 changed files with 162 additions and 13 deletions
+154
View File
@@ -36,6 +36,158 @@
namespace ot {
void TestDeviceMode(void)
{
Mle::DeviceMode mode;
Mle::DeviceMode::ModeConfig config;
Mle::DeviceMode::ModeConfig readConfig;
//- - - - - - - - - - - - - - - - - - - - - - - -
// SED (stable subset netdata)
config.mRxOnWhenIdle = false;
config.mDeviceType = false;
config.mNetworkData = false;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(!readConfig.mRxOnWhenIdle);
VerifyOrQuit(!readConfig.mDeviceType);
VerifyOrQuit(!readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(!mode.IsRxOnWhenIdle());
VerifyOrQuit(!mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kStableSubset);
VerifyOrQuit(!mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// SED (full set netdata)
config.mRxOnWhenIdle = false;
config.mDeviceType = false;
config.mNetworkData = true;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(!readConfig.mRxOnWhenIdle);
VerifyOrQuit(!readConfig.mDeviceType);
VerifyOrQuit(readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(!mode.IsRxOnWhenIdle());
VerifyOrQuit(!mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kFullSet);
VerifyOrQuit(!mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// MED (stable subset netdata)
config.mRxOnWhenIdle = true;
config.mDeviceType = false;
config.mNetworkData = false;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(readConfig.mRxOnWhenIdle);
VerifyOrQuit(!readConfig.mDeviceType);
VerifyOrQuit(!readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(mode.IsRxOnWhenIdle());
VerifyOrQuit(!mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kStableSubset);
VerifyOrQuit(mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// MED (full set netdata)
config.mRxOnWhenIdle = true;
config.mDeviceType = false;
config.mNetworkData = true;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(readConfig.mRxOnWhenIdle);
VerifyOrQuit(!readConfig.mDeviceType);
VerifyOrQuit(readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(mode.IsRxOnWhenIdle());
VerifyOrQuit(!mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kFullSet);
VerifyOrQuit(mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// FTD (stable subset netdata)
config.mRxOnWhenIdle = true;
config.mDeviceType = true;
config.mNetworkData = false;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(readConfig.mRxOnWhenIdle);
VerifyOrQuit(readConfig.mDeviceType);
VerifyOrQuit(!readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(mode.IsRxOnWhenIdle());
VerifyOrQuit(mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kStableSubset);
VerifyOrQuit(!mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// FTD (full set netdata)
config.mRxOnWhenIdle = true;
config.mDeviceType = true;
config.mNetworkData = true;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(readConfig.mRxOnWhenIdle);
VerifyOrQuit(readConfig.mDeviceType);
VerifyOrQuit(readConfig.mNetworkData);
VerifyOrQuit(mode.IsValid());
VerifyOrQuit(mode.IsRxOnWhenIdle());
VerifyOrQuit(mode.IsFullThreadDevice());
VerifyOrQuit(mode.GetNetworkDataType() == NetworkData::kFullSet);
VerifyOrQuit(!mode.IsMinimalEndDevice());
//- - - - - - - - - - - - - - - - - - - - - - - -
// Invalid
config.mRxOnWhenIdle = false;
config.mDeviceType = true;
config.mNetworkData = true;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(!readConfig.mRxOnWhenIdle);
VerifyOrQuit(readConfig.mDeviceType);
VerifyOrQuit(readConfig.mNetworkData);
VerifyOrQuit(!mode.IsValid());
//- - - - - - - - - - - - - - - - - - - - - - - -
// Invalid
config.mRxOnWhenIdle = false;
config.mDeviceType = true;
config.mNetworkData = false;
mode.Set(config);
mode.Get(readConfig);
VerifyOrQuit(!readConfig.mRxOnWhenIdle);
VerifyOrQuit(readConfig.mDeviceType);
VerifyOrQuit(!readConfig.mNetworkData);
VerifyOrQuit(!mode.IsValid());
printf("TestDeviceMode passed\n");
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
void TestDefaultDeviceProperties(void)
@@ -176,6 +328,8 @@ void TestLeaderWeightCalculation(void)
int main(void)
{
ot::TestDeviceMode();
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
ot::TestDefaultDeviceProperties();
ot::TestLeaderWeightCalculation();