[dua] remove OPENTHREAD_CONFIG_DUA_ENABLE build feature (#13165)

This commit completely removes the local Domain Unicast Address (DUA)
registration feature flag (OPENTHREAD_CONFIG_DUA_ENABLE) and all of
its associated implementation, public APIs, CLI commands, Spinel
property handlers, and certification tests.

Thread 1.2 FTD Border Router/Router DUA proxying features for MTD
children (OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) are preserved and
updated to only compile/instantiate components when proxy DUA
features are active.

Detailed Changes:
- Remove default definition of OPENTHREAD_CONFIG_DUA_ENABLE from
  misc.h.
- Remove OT_DUA and openthread_config_dua_enable from CMake/GN
  configs.
- Remove otThreadSetFixedDuaInterfaceIdentifier and
  otThreadGetFixedDuaInterfaceIdentifier from
  include/openthread/thread.h
  and implementation src/core/api/thread_api.cpp.
- Remove CLI DUA interpreter from src/cli/cli.cpp.
- Remove SPINEL_CAP_DUA capability and SPINEL_PROP_THREAD_DUA_ID
  Spinel property handlers and dispatchers from NCP.
- Strip local DUA management features (conflict checking, SLAAC DUA
  interface identifiers, and dad info settings) from DuaManager, MLE,
  Address Resolver, and settings.
- Clean up Notifier, TimeTicker, and TMF dispatcher guards.
- Clean up -DOT_DUA=ON compilation flags across build/test scripts.
- Delete obsolete DUA certification tests:
  - v1_2_test_domain_unicast_address
  - v1_2_test_domain_unicast_address_registration
  - v1_2_test_dua_handle_address_error
This commit is contained in:
Jonathan Hui
2026-06-01 15:16:19 -07:00
committed by GitHub
parent 675162556b
commit 136bdb6e2a
36 changed files with 25 additions and 1601 deletions
-1
View File
@@ -210,7 +210,6 @@ ot_option(OT_DNS_DSO OPENTHREAD_CONFIG_DNS_DSO_ENABLE "DNS Stateful Operations (
ot_option(OT_DNS_UPSTREAM_QUERY OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE "Allow sending DNS queries to upstream") ot_option(OT_DNS_UPSTREAM_QUERY OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE "Allow sending DNS queries to upstream")
ot_option(OT_DNSSD_DISCOVERY_PROXY OPENTHREAD_CONFIG_DNSSD_DISCOVERY_PROXY_ENABLE "DNS-SD discovery proxy") ot_option(OT_DNSSD_DISCOVERY_PROXY OPENTHREAD_CONFIG_DNSSD_DISCOVERY_PROXY_ENABLE "DNS-SD discovery proxy")
ot_option(OT_DNSSD_SERVER OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE "DNS-SD server") ot_option(OT_DNSSD_SERVER OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE "DNS-SD server")
ot_option(OT_DUA OPENTHREAD_CONFIG_DUA_ENABLE "Domain Unicast Address (DUA)")
ot_option(OT_DYNAMIC_STORE_FRAME_AHEAD_COUNTER OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE "dynamic store frame ahead counter") ot_option(OT_DYNAMIC_STORE_FRAME_AHEAD_COUNTER OPENTHREAD_CONFIG_DYNAMIC_STORE_FRAME_AHEAD_COUNTER_ENABLE "dynamic store frame ahead counter")
ot_option(OT_ECDSA OPENTHREAD_CONFIG_ECDSA_ENABLE "ECDSA") ot_option(OT_ECDSA OPENTHREAD_CONFIG_ECDSA_ENABLE "ECDSA")
ot_option(OT_EXTERNAL_HEAP OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE "external heap") ot_option(OT_EXTERNAL_HEAP OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE "external heap")
-3
View File
@@ -138,9 +138,6 @@ if (openthread_enable_core_config_args) {
# Enable ECDSA support # Enable ECDSA support
openthread_config_ecdsa_enable = false openthread_config_ecdsa_enable = false
# Enable Domain Unicast Address feature for Thread 1.2
openthread_config_dua_enable = false
# Enable Multicast Listener Registration feature for Thread 1.2 # Enable Multicast Listener Registration feature for Thread 1.2
openthread_config_mlr_enable = false openthread_config_mlr_enable = false
@@ -60,7 +60,6 @@
#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1 #define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 1 #define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 1
#define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 1 #define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 1
#define OPENTHREAD_CONFIG_DUA_ENABLE 1
#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 #define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 1 #define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 1
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 1 #define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 1
@@ -59,7 +59,6 @@
#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1 #define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 0 #define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 0
#define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 0 #define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 0
#define OPENTHREAD_CONFIG_DUA_ENABLE 1
#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 #define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 0 #define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 0
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 0 #define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 0
@@ -59,7 +59,6 @@
#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1 #define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 0 #define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 0
#define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 0 #define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE 0
#define OPENTHREAD_CONFIG_DUA_ENABLE 1
#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 #define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 0 #define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 0
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 0 #define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 0
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
* *
* @note This number versions both OpenThread platform and user APIs. * @note This number versions both OpenThread platform and user APIs.
*/ */
#define OPENTHREAD_API_VERSION (601) #define OPENTHREAD_API_VERSION (602)
/** /**
* @addtogroup api-instance * @addtogroup api-instance
-32
View File
@@ -628,38 +628,6 @@ const char *otThreadGetDomainName(otInstance *aInstance);
*/ */
otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName); otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName);
/**
* Sets or clears the Interface Identifier manually specified for the Thread Domain Unicast Address.
*
* Available when `OPENTHREAD_CONFIG_DUA_ENABLE` is enabled.
*
* @note Only available since Thread 1.2.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aIid A pointer to the Interface Identifier to set or NULL to clear.
*
* @retval OT_ERROR_NONE Successfully set/cleared the Interface Identifier.
* @retval OT_ERROR_INVALID_ARGS The specified Interface Identifier is reserved.
*
* @sa otThreadGetFixedDuaInterfaceIdentifier
*/
otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid);
/**
* Gets the Interface Identifier manually specified for the Thread Domain Unicast Address.
*
* Available when `OPENTHREAD_CONFIG_DUA_ENABLE` is enabled.
*
* @note Only available since Thread 1.2.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the Interface Identifier which was set manually, or NULL if none was set.
*
* @sa otThreadSetFixedDuaInterfaceIdentifier
*/
const otIp6InterfaceIdentifier *otThreadGetFixedDuaInterfaceIdentifier(otInstance *aInstance);
/** /**
* Gets the thrKeySequenceCounter. * Gets the thrKeySequenceCounter.
* *
-1
View File
@@ -54,7 +54,6 @@ build_nrf52840()
"-DOT_DIAGNOSTIC=ON" "-DOT_DIAGNOSTIC=ON"
"-DOT_DNSSD_SERVER=ON" "-DOT_DNSSD_SERVER=ON"
"-DOT_DNS_CLIENT=ON" "-DOT_DNS_CLIENT=ON"
"-DOT_DUA=ON"
"-DOT_ECDSA=ON" "-DOT_ECDSA=ON"
"-DOT_FULL_LOGS=ON" "-DOT_FULL_LOGS=ON"
"-DOT_JAM_DETECTION=ON" "-DOT_JAM_DETECTION=ON"
+5 -5
View File
@@ -158,23 +158,23 @@ build_all_features()
# Build Thread 1.4 with full features # Build Thread 1.4 with full features
reset_source reset_source
CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \ CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON "$(dirname "$0")"/cmake-build simulation "${options[@]}"
# Build Thread 1.4 with external heap and msg pool using heap # Build Thread 1.4 with external heap and msg pool using heap
reset_source reset_source
CFLAGS="${cppflags[*]} ${CFLAGS} -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1" \ CFLAGS="${cppflags[*]} ${CFLAGS} -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1" \
CXXFLAGS="${cppflags[*]} ${CXXFLAGS} -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1" \ CXXFLAGS="${cppflags[*]} ${CXXFLAGS} -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1" \
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON "$(dirname "$0")"/cmake-build simulation "${options[@]}"
# Build Thread 1.4 with full features and no log # Build Thread 1.4 with full features and no log
reset_source reset_source
CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \ CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_LOG_OUTPUT=NONE "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_LOG_OUTPUT=NONE
# Build Thread 1.4 with full features and full logs # Build Thread 1.4 with full features and full logs
reset_source reset_source
CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \ CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_FULL_LOGS=ON "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_FULL_LOGS=ON
# Build with Vendor Extension # Build with Vendor Extension
reset_source reset_source
@@ -188,7 +188,7 @@ build_all_features()
# Build Thread 1.4 with full features and OT_ASSERT=OFF # Build Thread 1.4 with full features and OT_ASSERT=OFF
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_ASSERT=OFF "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_ASSERT=OFF
# Build with RAM settings # Build with RAM settings
reset_source reset_source
-1
View File
@@ -112,7 +112,6 @@ OT_CLANG_TIDY_BUILD_OPTS=(
'-DOT_DNS_UPSTREAM_QUERY=ON' '-DOT_DNS_UPSTREAM_QUERY=ON'
"-DOT_DNSSD_DISCOVERY_PROXY=ON" "-DOT_DNSSD_DISCOVERY_PROXY=ON"
'-DOT_DNSSD_SERVER=ON' '-DOT_DNSSD_SERVER=ON'
'-DOT_DUA=ON'
'-DOT_MLR=ON' '-DOT_MLR=ON'
'-DOT_ECDSA=ON' '-DOT_ECDSA=ON'
'-DOT_HISTORY_TRACKER=ON' '-DOT_HISTORY_TRACKER=ON'
-3
View File
@@ -125,7 +125,6 @@ build_simulation()
fi fi
if [[ ${version} != "1.1" ]]; then if [[ ${version} != "1.1" ]]; then
options+=("-DOT_DUA=ON")
options+=("-DOT_MLR=ON") options+=("-DOT_MLR=ON")
fi fi
@@ -184,7 +183,6 @@ build_posix()
) )
if [[ ${version} != "1.1" ]]; then if [[ ${version} != "1.1" ]]; then
options+=("-DOT_DUA=ON")
options+=("-DOT_MLR=ON") options+=("-DOT_MLR=ON")
options+=("-DOT_LINK_METRICS_INITIATOR=ON") options+=("-DOT_LINK_METRICS_INITIATOR=ON")
options+=("-DOT_LINK_METRICS_SUBJECT=ON") options+=("-DOT_LINK_METRICS_SUBJECT=ON")
@@ -346,7 +344,6 @@ do_build_otbr_docker()
"-DOT_ANYCAST_LOCATOR=ON" "-DOT_ANYCAST_LOCATOR=ON"
"-DOT_COVERAGE=ON" "-DOT_COVERAGE=ON"
"-DOT_DNS_CLIENT=ON" "-DOT_DNS_CLIENT=ON"
"-DOT_DUA=ON"
"-DOT_MLR=ON" "-DOT_MLR=ON"
"-DOT_NETDATA_PUBLISHER=ON" "-DOT_NETDATA_PUBLISHER=ON"
"-DOT_SLAAC=ON" "-DOT_SLAAC=ON"
-67
View File
@@ -1102,70 +1102,6 @@ template <> otError Interpreter::Process<Cmd("domainname")>(Arg aArgs[])
return ProcessGetSet(aArgs, otThreadGetDomainName, otThreadSetDomainName); return ProcessGetSet(aArgs, otThreadGetDomainName, otThreadSetDomainName);
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE
template <> otError Interpreter::Process<Cmd("dua")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
/**
* @cli dua iid
* @code
* dua iid
* 0004000300020001
* Done
* @endcode
* @par api_copy
* #otThreadGetFixedDuaInterfaceIdentifier
*/
if (aArgs[0] == "iid")
{
if (aArgs[1].IsEmpty())
{
const otIp6InterfaceIdentifier *iid = otThreadGetFixedDuaInterfaceIdentifier(GetInstancePtr());
if (iid != nullptr)
{
OutputBytesLine(iid->mFields.m8);
}
}
/**
* @cli dua iid (set,clear)
* @code
* dua iid 0004000300020001
* Done
* @endcode
* @code
* dua iid clear
* Done
* @endcode
* @cparam dua iid @ca{iid|clear}
* `dua iid clear` passes a `nullptr` to #otThreadSetFixedDuaInterfaceIdentifier.
* Otherwise, you can pass the `iid`.
* @par api_copy
* #otThreadSetFixedDuaInterfaceIdentifier
*/
else if (aArgs[1] == "clear")
{
error = otThreadSetFixedDuaInterfaceIdentifier(GetInstancePtr(), nullptr);
}
else
{
otIp6InterfaceIdentifier iid;
SuccessOrExit(error = aArgs[1].ParseAsHexString(iid.mFields.m8));
error = otThreadSetFixedDuaInterfaceIdentifier(GetInstancePtr(), &iid);
}
}
else
{
error = OT_ERROR_INVALID_COMMAND;
}
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
/** /**
@@ -8671,9 +8607,6 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
CmdEntry("domainname"), CmdEntry("domainname"),
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
CmdEntry("dua"),
#endif
#if OPENTHREAD_FTD #if OPENTHREAD_FTD
CmdEntry("eidcache"), CmdEntry("eidcache"),
#endif #endif
-4
View File
@@ -103,10 +103,6 @@ if (openthread_enable_core_config_args) {
macro = "OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE" macro = "OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE"
value = openthread_config_dns_client_enable value = openthread_config_dns_client_enable
}, },
{
macro = "OPENTHREAD_CONFIG_DUA_ENABLE"
value = openthread_config_dua_enable
},
{ {
macro = "OPENTHREAD_CONFIG_ECDSA_ENABLE" macro = "OPENTHREAD_CONFIG_ECDSA_ENABLE"
value = openthread_config_ecdsa_enable value = openthread_config_ecdsa_enable
-31
View File
@@ -238,37 +238,6 @@ exit:
return error; return error;
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE
otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid)
{
Error error = kErrorNone;
if (aIid)
{
error = AsCoreType(aInstance).Get<DuaManager>().SetFixedDuaInterfaceIdentifier(AsCoreType(aIid));
}
else
{
AsCoreType(aInstance).Get<DuaManager>().ClearFixedDuaInterfaceIdentifier();
}
return error;
}
const otIp6InterfaceIdentifier *otThreadGetFixedDuaInterfaceIdentifier(otInstance *aInstance)
{
Instance &instance = AsCoreType(aInstance);
const otIp6InterfaceIdentifier *iid = nullptr;
if (instance.Get<DuaManager>().IsFixedDuaInterfaceIdentifierSet())
{
iid = &instance.Get<DuaManager>().GetFixedDuaInterfaceIdentifier();
}
return iid;
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance) uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance)
+2 -2
View File
@@ -208,7 +208,7 @@ void Leader::UpdateBackboneRouterPrimary(void)
Get<Mlr::Manager>().HandleBackboneRouterPrimaryUpdate(event); Get<Mlr::Manager>().HandleBackboneRouterPrimaryUpdate(event);
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
Get<DuaManager>().HandleBackboneRouterPrimaryUpdate(event); Get<DuaManager>().HandleBackboneRouterPrimaryUpdate(event);
#endif #endif
@@ -253,7 +253,7 @@ void Leader::UpdateDomainPrefixConfig(void)
Get<Local>().HandleDomainPrefixUpdate(event); Get<Local>().HandleDomainPrefixUpdate(event);
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
Get<DuaManager>().HandleDomainPrefixUpdate(event); Get<DuaManager>().HandleDomainPrefixUpdate(event);
#endif #endif
+1 -1
View File
@@ -143,7 +143,7 @@ void Notifier::EmitEvents(void)
#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
Get<Mlr::Manager>().HandleNotifierEvents(events); Get<Mlr::Manager>().HandleNotifierEvents(events);
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
Get<DuaManager>().HandleNotifierEvents(events); Get<DuaManager>().HandleNotifierEvents(events);
#endif #endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+1 -14
View File
@@ -71,13 +71,6 @@ void SettingsBase::ChildInfo::Log(Action aAction) const
} }
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
void SettingsBase::DadInfo::Log(Action aAction) const
{
LogInfo("%s DadInfo {DadCounter:%2d}", ActionToString(aAction), GetDadCounter());
}
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
void SettingsBase::LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix) void SettingsBase::LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix)
{ {
@@ -151,7 +144,7 @@ const char *SettingsBase::KeyToString(Key aKey)
_(kKeyChildInfo, "ChildInfo") \ _(kKeyChildInfo, "ChildInfo") \
_(6, "") \ _(6, "") \
_(kKeySlaacIidSecretKey, "SlaacIidSecretKey") \ _(kKeySlaacIidSecretKey, "SlaacIidSecretKey") \
_(kKeyDadInfo, "DadInfo") \ _(8, "") \
_(9, "") \ _(9, "") \
_(10, "") \ _(10, "") \
_(kKeySrpEcdsaKey, "SrpEcdsaKey") \ _(kKeySrpEcdsaKey, "SrpEcdsaKey") \
@@ -487,12 +480,6 @@ void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
break; break;
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
case kKeyDadInfo:
reinterpret_cast<const DadInfo *>(aValue)->Log(aAction);
break;
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
case kKeyBrUlaPrefix: case kKeyBrUlaPrefix:
LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue)); LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
-40
View File
@@ -112,7 +112,6 @@ public:
kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO, kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO,
kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO, kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO,
kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY, kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY, kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO, kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO, kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
@@ -486,45 +485,6 @@ public:
}; };
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
/**
* Represents the duplicate address detection information for settings storage.
*/
OT_TOOL_PACKED_BEGIN
class DadInfo : private Clearable<DadInfo>
{
friend class Settings;
friend class Clearable<DadInfo>;
public:
static constexpr Key kKey = kKeyDadInfo; ///< The associated key.
/**
* Initializes the `DadInfo` object.
*/
void Init(void) { Clear(); }
/**
* Returns the Dad Counter.
*
* @returns The Dad Counter value.
*/
uint8_t GetDadCounter(void) const { return mDadCounter; }
/**
* Sets the Dad Counter.
*
* @param[in] aDadCounter The Dad Counter value.
*/
void SetDadCounter(uint8_t aDadCounter) { mDadCounter = aDadCounter; }
private:
void Log(Action aAction) const;
uint8_t mDadCounter; ///< Dad Counter used to resolve address conflict in Thread 1.2 DUA feature.
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
/** /**
* Defines constants and types for BR ULA prefix settings. * Defines constants and types for BR ULA prefix settings.
+1 -1
View File
@@ -104,7 +104,7 @@ void TimeTicker::HandleTimer(void)
} }
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
if (mReceivers & Mask(kDuaManager)) if (mReceivers & Mask(kDuaManager))
{ {
Get<DuaManager>().HandleTimeTick(); Get<DuaManager>().HandleTimeTick();
-9
View File
@@ -524,15 +524,6 @@
#define OPENTHREAD_CONFIG_OTNS_ENABLE 0 #define OPENTHREAD_CONFIG_OTNS_ENABLE 0
#endif #endif
/**
* @def OPENTHREAD_CONFIG_DUA_ENABLE
*
* Define as 1 to support Thread 1.2 Domain Unicast Address feature.
*/
#ifndef OPENTHREAD_CONFIG_DUA_ENABLE
#define OPENTHREAD_CONFIG_DUA_ENABLE 0
#endif
/** /**
* @def OPENTHREAD_CONFIG_MLR_ENABLE * @def OPENTHREAD_CONFIG_MLR_ENABLE
* *
+1 -1
View File
@@ -216,7 +216,7 @@ Instance::Instance(void)
, mMlrManager(*this) , mMlrManager(*this)
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
, mDuaManager(*this) , mDuaManager(*this)
#endif #endif
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+2 -2
View File
@@ -769,7 +769,7 @@ private:
Mlr::Manager mMlrManager; Mlr::Manager mMlrManager;
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
DuaManager mDuaManager; DuaManager mDuaManager;
#endif #endif
@@ -1252,7 +1252,7 @@ template <> inline BackboneRouter::BackboneTmfAgent &Instance::Get(void)
template <> inline Mlr::Manager &Instance::Get(void) { return mMlrManager; } template <> inline Mlr::Manager &Instance::Get(void) { return mMlrManager; }
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
template <> inline DuaManager &Instance::Get(void) { return mDuaManager; } template <> inline DuaManager &Instance::Get(void) { return mDuaManager; }
#endif #endif
+1 -11
View File
@@ -754,17 +754,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressError>(Coap::Msg &aMsg)
if (address.GetAddress() == target && Get<Mle::Mle>().GetMeshLocalEid().GetIid() != meshLocalIid) if (address.GetAddress() == target && Get<Mle::Mle>().GetMeshLocalEid().GetIid() != meshLocalIid)
{ {
// Target EID matches address and Mesh Local EID differs // Target EID matches address and Mesh Local EID differs
#if OPENTHREAD_CONFIG_DUA_ENABLE Get<ThreadNetif>().RemoveUnicastAddress(address);
if (Get<BackboneRouter::Leader>().IsDomainUnicast(address.GetAddress()))
{
Get<DuaManager>().NotifyDuplicateDomainUnicastAddress();
}
else
#endif
{
Get<ThreadNetif>().RemoveUnicastAddress(address);
}
ExitNow(); ExitNow();
} }
} }
+5 -334
View File
@@ -33,7 +33,7 @@
#include "dua_manager.hpp" #include "dua_manager.hpp"
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
#include "instance/instance.hpp" #include "instance/instance.hpp"
@@ -45,22 +45,12 @@ DuaManager::DuaManager(Instance &aInstance)
: InstanceLocator(aInstance) : InstanceLocator(aInstance)
, mRegistrationTask(aInstance) , mRegistrationTask(aInstance)
, mIsDuaPending(false) , mIsDuaPending(false)
#if OPENTHREAD_CONFIG_DUA_ENABLE
, mDuaState(kNotExist)
, mDadCounter(0)
, mLastRegistrationTime(0)
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
, mChildIndexDuaRegistering(Mle::kMaxChildren) , mChildIndexDuaRegistering(Mle::kMaxChildren)
#endif #endif
{ {
mDelay.mValue = 0; mDelay.mValue = 0;
#if OPENTHREAD_CONFIG_DUA_ENABLE
mDomainUnicastAddress.InitAsThreadOriginGlobalScope();
mFixedDuaInterfaceIdentifier.Clear();
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
mChildDuaMask.Clear(); mChildDuaMask.Clear();
mChildDuaRegisteredMask.Clear(); mChildDuaRegisteredMask.Clear();
@@ -76,183 +66,14 @@ void DuaManager::HandleDomainPrefixUpdate(BackboneRouter::DomainPrefixEvent aEve
IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleDuaResponse, this)); IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleDuaResponse, this));
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE
RemoveDomainUnicastAddress();
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
if (!mChildDuaMask.IsEmpty()) if (!mChildDuaMask.IsEmpty())
{ {
mChildDuaMask.Clear(); mChildDuaMask.Clear();
mChildDuaRegisteredMask.Clear(); mChildDuaRegisteredMask.Clear();
} }
#endif
}
#if OPENTHREAD_CONFIG_DUA_ENABLE
switch (aEvent)
{
case BackboneRouter::kDomainPrefixRefreshed:
case BackboneRouter::kDomainPrefixAdded:
{
const Ip6::Prefix *prefix = Get<BackboneRouter::Leader>().GetDomainPrefix();
OT_ASSERT(prefix != nullptr);
mDomainUnicastAddress.mPrefixLength = prefix->GetLength();
mDomainUnicastAddress.GetAddress().Clear();
mDomainUnicastAddress.GetAddress().SetPrefix(*prefix);
}
break;
case BackboneRouter::kDomainPrefixRemoved:
ExitNow();
}
// Apply cached DUA Interface Identifier manually specified.
if (IsFixedDuaInterfaceIdentifierSet())
{
mDomainUnicastAddress.GetAddress().SetIid(mFixedDuaInterfaceIdentifier);
}
else
{
SuccessOrExit(GenerateDomainUnicastAddressIid());
}
AddDomainUnicastAddress();
exit:
return;
#endif
}
#if OPENTHREAD_CONFIG_DUA_ENABLE
Error DuaManager::GenerateDomainUnicastAddressIid(void)
{
Error error;
uint8_t dadCounter = mDadCounter;
if ((error = Get<Ip6::Slaac>().GenerateIid(mDomainUnicastAddress, dadCounter)) == kErrorNone)
{
if (dadCounter != mDadCounter)
{
mDadCounter = dadCounter;
Store();
}
LogInfo("Generated DUA: %s", mDomainUnicastAddress.GetAddress().ToString().AsCString());
}
else
{
LogWarnOnError(error, "generate DUA");
}
return error;
}
Error DuaManager::SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid)
{
Error error = kErrorNone;
VerifyOrExit(!aIid.IsReserved(), error = kErrorInvalidArgs);
VerifyOrExit(mFixedDuaInterfaceIdentifier.IsUnspecified() || mFixedDuaInterfaceIdentifier != aIid);
mFixedDuaInterfaceIdentifier = aIid;
LogInfo("Set DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
if (Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
{
RemoveDomainUnicastAddress();
mDomainUnicastAddress.GetAddress().SetIid(mFixedDuaInterfaceIdentifier);
AddDomainUnicastAddress();
}
exit:
return error;
}
void DuaManager::ClearFixedDuaInterfaceIdentifier(void)
{
// Nothing to clear.
VerifyOrExit(IsFixedDuaInterfaceIdentifierSet());
if (GetDomainUnicastAddress().GetIid() == mFixedDuaInterfaceIdentifier &&
Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
{
RemoveDomainUnicastAddress();
if (GenerateDomainUnicastAddressIid() == kErrorNone)
{
AddDomainUnicastAddress();
}
}
LogInfo("Cleared DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
mFixedDuaInterfaceIdentifier.Clear();
exit:
return;
}
void DuaManager::Restore(void)
{
Settings::DadInfo dadInfo;
SuccessOrExit(Get<Settings>().Read(dadInfo));
mDadCounter = dadInfo.GetDadCounter();
exit:
return;
}
void DuaManager::Store(void)
{
Settings::DadInfo dadInfo;
dadInfo.SetDadCounter(mDadCounter);
Get<Settings>().Save(dadInfo);
}
void DuaManager::AddDomainUnicastAddress(void)
{
mDuaState = kToRegister;
mLastRegistrationTime = TimerMilli::GetNow();
Get<ThreadNetif>().AddUnicastAddress(mDomainUnicastAddress);
}
void DuaManager::RemoveDomainUnicastAddress(void)
{
if (mDuaState == kRegistering && mIsDuaPending)
{
IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleDuaResponse, this));
}
mDuaState = kNotExist;
mDomainUnicastAddress.mPreferred = false;
Get<ThreadNetif>().RemoveUnicastAddress(mDomainUnicastAddress);
}
void DuaManager::UpdateRegistrationDelay(uint8_t aDelay)
{
if (mDelay.mFields.mRegistrationDelay == 0 || mDelay.mFields.mRegistrationDelay > aDelay)
{
mDelay.mFields.mRegistrationDelay = aDelay;
LogDebg("update regdelay %d", mDelay.mFields.mRegistrationDelay);
UpdateTimeTickerRegistration();
} }
} }
void DuaManager::NotifyDuplicateDomainUnicastAddress(void)
{
RemoveDomainUnicastAddress();
mDadCounter++;
if (GenerateDomainUnicastAddressIid() == kErrorNone)
{
AddDomainUnicastAddress();
}
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
void DuaManager::UpdateReregistrationDelay(void) void DuaManager::UpdateReregistrationDelay(void)
{ {
uint16_t delay; uint16_t delay;
@@ -285,20 +106,6 @@ void DuaManager::UpdateCheckDelay(uint8_t aDelay)
void DuaManager::HandleNotifierEvents(Events aEvents) void DuaManager::HandleNotifierEvents(Events aEvents)
{ {
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (aEvents.Contains(kEventThreadNetdataChanged) && Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
{
Lowpan::Context context;
Get<NetworkData::Leader>().FindContextForAddress(GetDomainUnicastAddress(), context);
if (!context.IsValid())
{
RemoveDomainUnicastAddress();
}
}
#endif
VerifyOrExit(Get<Mle::Mle>().IsAttached(), mDelay.mValue = 0); VerifyOrExit(Get<Mle::Mle>().IsAttached(), mDelay.mValue = 0);
if (aEvents.Contains(kEventThreadRoleChanged)) if (aEvents.Contains(kEventThreadRoleChanged))
@@ -307,27 +114,8 @@ void DuaManager::HandleNotifierEvents(Events aEvents)
{ {
UpdateReregistrationDelay(); UpdateReregistrationDelay();
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE && OPENTHREAD_FTD
else if (Get<Mle::Mle>().IsRouter())
{
// Wait for link establishment with neighboring routers.
UpdateRegistrationDelay(kNewRouterRegistrationDelay);
}
else if (Get<Mle::Mle>().WillBecomeRouterSoon())
{
// Will check again in case the device decides to stay REED when jitter timeout expires.
UpdateRegistrationDelay(Get<Mle::Mle>().GetRouterRoleTransitionTimeout() + kNewRouterRegistrationDelay + 1);
}
#endif
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (aEvents.ContainsAny(kEventIp6AddressAdded))
{
UpdateRegistrationDelay(kNewDuaRegistrationDelay);
}
#endif
exit: exit:
return; return;
} }
@@ -336,12 +124,7 @@ void DuaManager::HandleBackboneRouterPrimaryUpdate(BackboneRouter::PrimaryEvent
{ {
if (aEvent == BackboneRouter::kPrimaryAdded || aEvent == BackboneRouter::kPrimaryUpdatedReregister) if (aEvent == BackboneRouter::kPrimaryAdded || aEvent == BackboneRouter::kPrimaryUpdatedReregister)
{ {
#if OPENTHREAD_CONFIG_DUA_ENABLE UpdateReregistrationDelay();
if (Get<Mle::Mle>().IsFullThreadDevice() || Get<Mle::Mle>().GetParent().IsThreadVersion1p1())
#endif
{
UpdateReregistrationDelay();
}
} }
} }
@@ -349,23 +132,7 @@ void DuaManager::HandleTimeTick(void)
{ {
bool attempt = false; bool attempt = false;
#if OPENTHREAD_CONFIG_DUA_ENABLE
LogDebg("regdelay %d, reregdelay %d, checkdelay %d", mDelay.mFields.mRegistrationDelay,
mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
if ((mDuaState != kNotExist) &&
(TimerMilli::GetNow() > (mLastRegistrationTime + TimeMilli::SecToMsec(kDuaDadPeriod))))
{
mDomainUnicastAddress.mPreferred = true;
}
if ((mDelay.mFields.mRegistrationDelay > 0) && (--mDelay.mFields.mRegistrationDelay == 0))
{
attempt = true;
}
#else
LogDebg("reregdelay %d, checkdelay %d", mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay); LogDebg("reregdelay %d, checkdelay %d", mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
#endif
if ((mDelay.mFields.mCheckDelay > 0) && (--mDelay.mFields.mCheckDelay == 0)) if ((mDelay.mFields.mCheckDelay > 0) && (--mDelay.mFields.mCheckDelay == 0))
{ {
@@ -374,13 +141,6 @@ void DuaManager::HandleTimeTick(void)
if ((mDelay.mFields.mReregistrationDelay > 0) && (--mDelay.mFields.mReregistrationDelay == 0)) if ((mDelay.mFields.mReregistrationDelay > 0) && (--mDelay.mFields.mReregistrationDelay == 0))
{ {
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (mDuaState != kNotExist)
{
mDuaState = kToRegister;
}
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
mChildDuaRegisteredMask.Clear(); mChildDuaRegisteredMask.Clear();
#endif #endif
@@ -420,48 +180,13 @@ void DuaManager::PerformNextRegistration(void)
// Only allow one outgoing DUA.req // Only allow one outgoing DUA.req
VerifyOrExit(!mIsDuaPending); VerifyOrExit(!mIsDuaPending);
// Only send DUA.req when necessary VerifyOrExit(!mChildDuaMask.IsEmpty() && mChildDuaMask != mChildDuaRegisteredMask);
#if OPENTHREAD_CONFIG_DUA_ENABLE
#if OPENTHREAD_FTD
if (!Get<Mle::Mle>().IsRouterOrLeader() && Get<Mle::Mle>().WillBecomeRouterSoon())
{
UpdateRegistrationDelay(Get<Mle::Mle>().GetRouterRoleTransitionTimeout() + kNewRouterRegistrationDelay + 1);
ExitNow();
}
#endif
VerifyOrExit(Get<Mle::Mle>().IsFullThreadDevice() || Get<Mle::Mle>().GetParent().IsThreadVersion1p1());
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
{
bool needReg = false;
#if OPENTHREAD_CONFIG_DUA_ENABLE
needReg = (mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0);
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
needReg = needReg || (!mChildDuaMask.IsEmpty() && mChildDuaMask != mChildDuaRegisteredMask);
#endif
VerifyOrExit(needReg);
}
// Prepare DUA.req // Prepare DUA.req
message = Get<Tmf::Agent>().AllocateAndInitPriorityConfirmablePostMessage(kUriDuaRegistrationRequest); message = Get<Tmf::Agent>().AllocateAndInitPriorityConfirmablePostMessage(kUriDuaRegistrationRequest);
VerifyOrExit(message != nullptr, error = kErrorNoBufs); VerifyOrExit(message != nullptr, error = kErrorNoBufs);
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0)
{ {
dua = GetDomainUnicastAddress();
SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, dua));
SuccessOrExit(error = Tlv::Append<ThreadMeshLocalEidTlv>(*message, Get<Mle::Mle>().GetMeshLocalEid().GetIid()));
mDuaState = kRegistering;
mLastRegistrationTime = TimerMilli::GetNow();
}
else
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
{
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
uint32_t lastTransactionTime; uint32_t lastTransactionTime;
Child *child = nullptr; Child *child = nullptr;
@@ -486,21 +211,9 @@ void DuaManager::PerformNextRegistration(void)
lastTransactionTime = Time::MsecToSec(TimerMilli::GetNow() - child->GetLastHeard()); lastTransactionTime = Time::MsecToSec(TimerMilli::GetNow() - child->GetLastHeard());
SuccessOrExit(error = Tlv::Append<ThreadLastTransactionTimeTlv>(*message, lastTransactionTime)); SuccessOrExit(error = Tlv::Append<ThreadLastTransactionTimeTlv>(*message, lastTransactionTime));
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
} }
if (!Get<Mle::Mle>().IsFullThreadDevice() && Get<Mle::Mle>().GetParent().IsThreadVersion1p1()) destAddr.InitAsRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(), Get<BackboneRouter::Leader>().GetServer16());
{
uint8_t pbbrServiceId;
SuccessOrExit(error = Get<BackboneRouter::Leader>().GetServiceId(pbbrServiceId));
Get<Mle::Mle>().GetServiceAloc(pbbrServiceId, destAddr);
}
else
{
destAddr.InitAsRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
Get<BackboneRouter::Leader>().GetServer16());
}
SuccessOrExit(error = Get<Tmf::Agent>().SendMessageTo(*message, destAddr, HandleDuaResponse, this)); SuccessOrExit(error = Get<Tmf::Agent>().SendMessageTo(*message, destAddr, HandleDuaResponse, this));
@@ -508,14 +221,6 @@ void DuaManager::PerformNextRegistration(void)
mRegisteringDua = dua; mRegisteringDua = dua;
mDelay.mValue = 0; mDelay.mValue = 0;
// Generally Thread 1.2 Router would send DUA.req on behalf for DUA registered by its MTD child.
// When Thread 1.2 MTD attaches to Thread 1.1 parent, 1.2 MTD should send DUA.req to PBBR itself.
// In this case, Thread 1.2 sleepy end device relies on fast data poll to fetch the response timely.
if (!Get<Mle::Mle>().IsRxOnWhenIdle())
{
Get<DataPollSender>().SendFastPolls();
}
LogInfo("Sent %s for DUA %s", UriToString<kUriDuaRegistrationRequest>(), dua.ToString().AsCString()); LogInfo("Sent %s for DUA %s", UriToString<kUriDuaRegistrationRequest>(), dua.ToString().AsCString());
exit: exit:
@@ -594,39 +299,6 @@ Error DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
VerifyOrExit(Get<BackboneRouter::Leader>().IsDomainUnicast(target), error = kErrorDrop); VerifyOrExit(Get<BackboneRouter::Leader>().IsDomainUnicast(target), error = kErrorDrop);
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (Get<ThreadNetif>().HasUnicastAddress(target))
{
switch (static_cast<DuaStatus>(status))
{
case kDuaSuccess:
mLastRegistrationTime = TimerMilli::GetNow();
mDuaState = kRegistered;
break;
case kDuaReRegister:
if (Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
{
RemoveDomainUnicastAddress();
AddDomainUnicastAddress();
}
break;
case kDuaInvalid:
// Domain Prefix might be invalid.
RemoveDomainUnicastAddress();
break;
case kDuaDuplicate:
NotifyDuplicateDomainUnicastAddress();
break;
case kDuaNoResources:
case kDuaNotPrimary:
case kDuaGeneralFailure:
UpdateReregistrationDelay();
break;
}
}
else
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
{ {
Child *child = nullptr; Child *child = nullptr;
uint16_t childIndex; uint16_t childIndex;
@@ -676,7 +348,6 @@ Error DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
SendAddressNotification(target, static_cast<DuaStatus>(status), *child); SendAddressNotification(target, static_cast<DuaStatus>(status), *child);
} }
} }
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
exit: exit:
UpdateTimeTickerRegistration(); UpdateTimeTickerRegistration();
@@ -745,4 +416,4 @@ void DuaManager::HandleChildDuaAddressEvent(const Child &aChild, ChildDuaAddress
} // namespace ot } // namespace ot
#endif // OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
+4 -94
View File
@@ -36,15 +36,7 @@
#include "openthread-core-config.h" #include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
#if OPENTHREAD_CONFIG_DUA_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_DUA_ENABLE"
#endif
#if OPENTHREAD_CONFIG_DUA_ENABLE && !OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
#error "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE is required for OPENTHREAD_CONFIG_DUA_ENABLE"
#endif
#include "backbone_router/bbr_leader.hpp" #include "backbone_router/bbr_leader.hpp"
#include "coap/coap_message.hpp" #include "coap/coap_message.hpp"
@@ -120,57 +112,6 @@ public:
*/ */
void HandleBackboneRouterPrimaryUpdate(BackboneRouter::PrimaryEvent aEvent); void HandleBackboneRouterPrimaryUpdate(BackboneRouter::PrimaryEvent aEvent);
#if OPENTHREAD_CONFIG_DUA_ENABLE
/**
* Returns a reference to the Domain Unicast Address.
*
* @returns A reference to the Domain Unicast Address.
*/
const Ip6::Address &GetDomainUnicastAddress(void) const { return mDomainUnicastAddress.GetAddress(); }
/**
* Sets the Interface Identifier manually specified for the Thread Domain Unicast Address.
*
* @param[in] aIid A reference to the Interface Identifier to set.
*
* @retval kErrorNone Successfully set the Interface Identifier.
* @retval kErrorInvalidArgs The specified Interface Identifier is reserved.
*/
Error SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid);
/**
* Clears the Interface Identifier manually specified for the Thread Domain Unicast Address.
*/
void ClearFixedDuaInterfaceIdentifier(void);
/**
* Indicates whether or not there is Interface Identifier manually specified for the Thread
* Domain Unicast Address.
*
* @retval true If there is Interface Identifier manually specified.
* @retval false If there is no Interface Identifier manually specified.
*/
bool IsFixedDuaInterfaceIdentifierSet(void) { return !mFixedDuaInterfaceIdentifier.IsUnspecified(); }
/**
* Gets the Interface Identifier for the Thread Domain Unicast Address if manually specified.
*
* @returns A reference to the Interface Identifier.
*/
const Ip6::InterfaceIdentifier &GetFixedDuaInterfaceIdentifier(void) const { return mFixedDuaInterfaceIdentifier; }
/*
* Restores duplicate address detection information from non-volatile memory.
*/
void Restore(void);
/**
* Notifies duplicated Domain Unicast Address.
*/
void NotifyDuplicateDomainUnicastAddress(void);
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
/** /**
* Events related to a Child DUA address. * Events related to a Child DUA address.
@@ -193,20 +134,8 @@ public:
#endif #endif
private: private:
static constexpr uint32_t kDuaDadPeriod = 100; // DAD wait time to become "Preferred" (in sec). static constexpr uint8_t kNoBufDelay = 5; // In sec.
static constexpr uint8_t kNoBufDelay = 5; // In sec. static constexpr uint8_t KResponseTimeoutDelay = 30; // In sec.
static constexpr uint8_t KResponseTimeoutDelay = 30; // In sec.
static constexpr uint8_t kNewRouterRegistrationDelay = 3; // Delay (in sec) to establish link for a new router.
static constexpr uint8_t kNewDuaRegistrationDelay = 1; // Delay (in sec) for newly added DUA.
#if OPENTHREAD_CONFIG_DUA_ENABLE
Error GenerateDomainUnicastAddressIid(void);
void Store(void);
void AddDomainUnicastAddress(void);
void RemoveDomainUnicastAddress(void);
void UpdateRegistrationDelay(uint8_t aDelay);
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
void SendAddressNotification(Ip6::Address &aAddress, DuaStatus aStatus, const Child &aChild); void SendAddressNotification(Ip6::Address &aAddress, DuaStatus aStatus, const Child &aChild);
@@ -234,31 +163,12 @@ private:
Ip6::Address mRegisteringDua; Ip6::Address mRegisteringDua;
bool mIsDuaPending : 1; bool mIsDuaPending : 1;
#if OPENTHREAD_CONFIG_DUA_ENABLE
enum DuaState : uint8_t
{
kNotExist, ///< DUA is not available.
kToRegister, ///< DUA is to be registered.
kRegistering, ///< DUA is being registered.
kRegistered, ///< DUA is registered.
};
DuaState mDuaState;
uint8_t mDadCounter;
TimeMilli mLastRegistrationTime; // The time (in milliseconds) when sent last DUA.req or received DUA.rsp.
Ip6::InterfaceIdentifier mFixedDuaInterfaceIdentifier;
Ip6::Netif::UnicastAddress mDomainUnicastAddress;
#endif
union union
{ {
struct struct
{ {
uint16_t mReregistrationDelay; // Delay (in seconds) for DUA re-registration. uint16_t mReregistrationDelay; // Delay (in seconds) for DUA re-registration.
uint8_t mCheckDelay; // Delay (in seconds) for checking whether or not registration is required. uint8_t mCheckDelay; // Delay (in seconds) for checking whether or not registration is required.
#if OPENTHREAD_CONFIG_DUA_ENABLE
uint8_t mRegistrationDelay; // Delay (in seconds) for DUA registration.
#endif
} mFields; } mFields;
uint32_t mValue; // Non-zero indicates timer should start. uint32_t mValue; // Non-zero indicates timer should start.
} mDelay; } mDelay;
@@ -277,5 +187,5 @@ DeclareTmfHandler(DuaManager, kUriDuaRegistrationNotify);
} // namespace ot } // namespace ot
#endif // OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
#endif // OT_CORE_THREAD_DUA_MANAGER_HPP_ #endif // OT_CORE_THREAD_DUA_MANAGER_HPP_
-19
View File
@@ -356,10 +356,6 @@ void Mle::Restore(void)
IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore()); IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore()); IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore());
#if OPENTHREAD_CONFIG_DUA_ENABLE
Get<DuaManager>().Restore();
#endif
SuccessOrExit(Get<Settings>().Read(networkInfo)); SuccessOrExit(Get<Settings>().Read(networkInfo));
Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence(), Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence(),
@@ -3670,14 +3666,6 @@ Error Mle::TxMessage::AppendAddressRegistrationTlv(AddressRegistrationMode aMode
// Continue to append the other addresses if not `kAppendMeshLocalOnly` mode // Continue to append the other addresses if not `kAppendMeshLocalOnly` mode
VerifyOrExit(aMode != kAppendMeshLocalOnly); VerifyOrExit(aMode != kAppendMeshLocalOnly);
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (Get<ThreadNetif>().HasUnicastAddress(Get<DuaManager>().GetDomainUnicastAddress()))
{
// Prioritize DUA, compressed entry
SuccessOrExit(error = AppendAddressRegistrationEntry(Get<DuaManager>().GetDomainUnicastAddress()));
}
#endif
for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses()) for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
{ {
if (!Get<Mle>().ShouldRegisterUnicastAddrWithParent(addr)) if (!Get<Mle>().ShouldRegisterUnicastAddrWithParent(addr))
@@ -3690,13 +3678,6 @@ Error Mle::TxMessage::AppendAddressRegistrationTlv(AddressRegistrationMode aMode
continue; continue;
} }
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (addr.GetAddress() == Get<DuaManager>().GetDomainUnicastAddress())
{
continue;
}
#endif
SuccessOrExit(error = AppendAddressRegistrationEntry(addr.GetAddress())); SuccessOrExit(error = AppendAddressRegistrationEntry(addr.GetAddress()));
} }
+1 -1
View File
@@ -123,7 +123,7 @@ bool Agent::HandleResource(const char *aUriPath, Msg &aMsg)
Case(kUriRelayRx, Agent); Case(kUriRelayRx, Agent);
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
Case(kUriDuaRegistrationNotify, DuaManager); Case(kUriDuaRegistrationNotify, DuaManager);
#endif #endif
-4
View File
@@ -2151,10 +2151,6 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_LINK_METRICS)); SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_LINK_METRICS));
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_DUA));
#endif
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_REFERENCE_DEVICE)); SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_REFERENCE_DEVICE));
#endif #endif
-6
View File
@@ -335,9 +335,6 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DOMAIN_NAME), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DOMAIN_NAME),
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DUA_ID),
#endif
#endif // OPENTHREAD_FTD #endif // OPENTHREAD_FTD
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY),
@@ -651,9 +648,6 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MLR_REQUEST), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MLR_REQUEST),
#endif #endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_DUA_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DUA_ID),
#endif
#if OPENTHREAD_FTD #if OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE),
-47
View File
@@ -385,53 +385,6 @@ exit:
} }
#endif #endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DUA_ID>(void)
{
const otIp6InterfaceIdentifier *iid = otThreadGetFixedDuaInterfaceIdentifier(mInstance);
otError error = OT_ERROR_NONE;
if (iid == nullptr)
{
// send empty response
}
else
{
for (uint8_t i : iid->mFields.m8)
{
SuccessOrExit(error = mEncoder.WriteUint8(i));
}
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DUA_ID>(void)
{
otError error = OT_ERROR_NONE;
if (mDecoder.GetRemainingLength() == 0)
{
SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, nullptr));
}
else
{
otIp6InterfaceIdentifier iid;
for (uint8_t &i : iid.mFields.m8)
{
SuccessOrExit(error = mDecoder.ReadUint8(i));
}
SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, &iid));
}
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_BORDER_AGENT_EPHEMERAL_KEY_ENABLE>(void) template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_BORDER_AGENT_EPHEMERAL_KEY_ENABLE>(void)
@@ -1,320 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2020, 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.
#
import unittest
import command
import config
import ipaddress
import mle
import thread_cert
BBR_1 = 1 # Collapsed with Leader Role
ROUTER_1_1 = 2
ROUTER_1_2 = 3
MED_1_2 = 4
SED_1_2 = 5
WAIT_ATTACH = 5
WAIT_REDUNDANCE = 3
ROUTER_SELECTION_JITTER = 1
BBR_REGISTRATION_JITTER = 5
SED_POLL_PERIOD = 2000 # 2s
MED_TIMEOUT = 20 # 20s
DUA_IID_MANUAL1 = '4444333322221111'
DUA_IID_MANUAL2 = '5555444433332222'
TEST_PREFIX1 = '2001:0:0:1::/64'
TEST_PREFIX2 = '2001:0:0:2::/64'
TEST_PREFIX3 = '2001:0:0:3::/64'
"""
Topology
SED_1_2
|
|
ROUTER_1_1 MED_1_2
| |
| |
BBR_1 (LEADER) --- ROUTER_1_2
1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain
Prefix without `P_slaac`.
2) Bring up ROUTER_1_1, no DUA was added due to that `P_slaac` flag is not set.
3) Bring up ROUTER_1_2, verify that it has DUA generated.
4) Bring up MED_1_2 with DUA_IID_MANUAL1 set in advance, verify
a) DUA_IID_MANUAL1 is registered in Address Registration TLV via Child Update Request.
b) Remove DUA_IID_MANUAL1, a new DUA generated via SLAAC would be registered in Address
Registration TLV via Child Update Request.
c) Set DUA_IID_MANUAL2 which should override the generated one and be registered in Address
Registration TLV via Child Update Request.
d) Remove DUA_IID_MANUAL2, a new DUA generated via SLAAC, the same as in above b) would
be registered in Address Registration TLV via Child Update Request.
5) Change BBR_1 from config.DOMAIN_PREFIX to config.DOMAIN_PRFIX_ALTER. Verify that MED_1_2
generate a new Interface Identifier different from the one generated in 4d) due to the
Domain Prefix change.
6) Recover config.Domain_Prefix on BBR_1. Verify that MED_1_2 generates and registers the same
DUA as in step 4b).
7) Configure ROUTER_1_1 as Border Router with 3 SLAAC prefixes, verify MED_1_2 would register
its DUA in Address Registration TLV.
8) Bring up SED_1_2, verify it generates one DUA, and registers it to its parent, though the parent
is a Thread 1.1 device.
"""
class TestDomainUnicastAddress(thread_cert.TestCase):
TOPOLOGY = {
BBR_1: {
'version': '1.2',
'allowlist': [ROUTER_1_1, ROUTER_1_2],
'is_bbr': True
},
ROUTER_1_1: {
'version': '1.1',
'allowlist': [BBR_1, SED_1_2]
},
ROUTER_1_2: {
'version': '1.2',
'allowlist': [BBR_1, MED_1_2]
},
MED_1_2: {
'mode': 'rn',
'version': '1.2',
'allowlist': [ROUTER_1_2],
},
SED_1_2: {
'mode': 'n',
'version': '1.2',
'allowlist': [ROUTER_1_1],
},
}
"""All nodes are created with default configurations"""
def __get_iid(self, address):
''' Get the interface identifier of an IPv6 address.
Args:
address (string): An IPv6 address;
'''
return ''.join(ipaddress.ip_address(address).exploded.split(':')[4:])
def __check_dua_registration(self, node, iid, dp_cid):
''' Check whether or not the specified Domain Unicast Address is registered in Address
Registration TLV.
Args:
node (int) : The device id
iid (string): The Interface Identifier
dp_cid (int): The context id of the domain prefix.
'''
messages = self.simulator.get_messages_sent_by(node)
msg = messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST)
command.check_compressed_address_registration_tlv(msg, dp_cid, iid, cid_present_once=True)
def test(self):
# starting context id
context_id = 1
# 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain
# Prefix without `P_slaac`.
self.nodes[BBR_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].set_backbone_router(seqno=1)
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME * 2)
self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
self.nodes[BBR_1].enable_backbone_router()
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(), 'Primary')
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX)
domain_prefix_cid = context_id
# 2) Bring up ROUTER_1_1, no DUA was added due to that `P_slaac` flag is not set.
self.nodes[ROUTER_1_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.nodes[ROUTER_1_1].start()
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router')
dua = self.nodes[ROUTER_1_1].get_addr(config.DOMAIN_PREFIX)
assert not dua, 'Error: Unexpected DUA ({})'.format(dua)
# 3) Bring up ROUTER_1_2, verify that it has DUA generated.
self.nodes[ROUTER_1_2].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[ROUTER_1_2].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[ROUTER_1_2].get_state(), 'router')
dua = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua, 'Error: Expected DUA not found'
self.assertTrue(self.nodes[BBR_1].ping(dua))
# 4) Bring up MED_1_2 with DUA_IID_MANUAL1 set in advance
self.nodes[MED_1_2].set_dua_iid(DUA_IID_MANUAL1)
self.nodes[MED_1_2].set_timeout(MED_TIMEOUT)
self.nodes[MED_1_2].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[MED_1_2].get_state(), 'child')
# 4a) DUA_IID_MANUAL1 is registered in Address Registration TLV via Child Update Request.
self.__check_dua_registration(MED_1_2, DUA_IID_MANUAL1, domain_prefix_cid)
# 4b) Remove DUA_IID_MANUAL1, a new DUA generated via SLAAC would be registered in Address
# Registration TLV via Child Update Request.
# Flush relative message queues.
messages = self.simulator.get_messages_sent_by(MED_1_2)
self.nodes[MED_1_2].clear_dua_iid()
WAIT_TIME = MED_TIMEOUT + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
med_1_2_dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX)
assert med_1_2_dua, 'Error: Expected DUA not found'
med_1_2_dua_iid = self.__get_iid(med_1_2_dua)
self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid)
# 4c) Set DUA_IID_MANUAL2 which should override the generated one and be registered in Address
# Registration TLV via Child Update Request.
# Flush relative message queues.
messages = self.simulator.get_messages_sent_by(MED_1_2)
self.nodes[MED_1_2].set_dua_iid(DUA_IID_MANUAL2)
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX)
self.__check_dua_registration(MED_1_2, DUA_IID_MANUAL2, domain_prefix_cid)
# 4d) Remove DUA_IID_MANUAL2, a new DUA generated via SLAAC, the same as in above b) would
# be registered in Address Registration TLV via Child Update Request.
# Flush relative message queues.
messages = self.simulator.get_messages_sent_by(MED_1_2)
self.nodes[MED_1_2].clear_dua_iid()
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX)
self.assertEqual(ipaddress.ip_address(dua), ipaddress.ip_address(med_1_2_dua))
self.assertEqual(ipaddress.ip_address(med_1_2_dua), ipaddress.ip_address(dua))
self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid)
# 5) Change BBR_1 from config.DOMAIN_PREFIX to config.DOMAIN_PRFIX_ALTER. Verify that MED_1_2
# generates a new Interface Identifier different from the one generated in 4d) due to the
# Domain Prefix change.
context_id += 1
self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX_ALTER)
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX_ALTER)
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
med_1_2_dua2 = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX_ALTER)
med_1_2_dua2_iid = self.__get_iid(med_1_2_dua2)
self.__check_dua_registration(MED_1_2, med_1_2_dua2_iid, context_id)
#6) Recover config.Domain_Prefix on BBR_1. Verify that MED_1_2 generates and registers the same
# DUA as in step 4b).
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX)
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua, 'Error: Expected DUA not found'
self.assertEqual(ipaddress.ip_address(med_1_2_dua), ipaddress.ip_address(dua))
self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid)
#7) Configure ROUTER_1_1 as Border Router with 3 SLAAC prefixes, verify MED_1_2 would register
# its DUA in Address Registration TLV.
# Flush relative message queues.
messages = self.simulator.get_messages_sent_by(MED_1_2)
context_id += 1
self.simulator.set_lowpan_context(context_id, TEST_PREFIX1)
self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX1)
context_id += 1
self.simulator.set_lowpan_context(context_id, TEST_PREFIX2)
self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX2)
context_id += 1
self.simulator.set_lowpan_context(context_id, TEST_PREFIX3)
self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX3)
self.nodes[ROUTER_1_1].register_netdata()
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
WAIT_TIME = MED_TIMEOUT
self.simulator.go(WAIT_TIME)
dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua, 'Error: Expected DUA not found'
self.assertEqual(ipaddress.ip_address(med_1_2_dua), ipaddress.ip_address(dua))
self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid)
#8) Bring up SED_1_2, verify that it generates one DUA, and registers it to its parent, though the parent
# is a Thread 1.1 device.
self.nodes[SED_1_2].set_pollperiod(SED_POLL_PERIOD)
self.nodes[SED_1_2].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
dua = self.nodes[SED_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua, 'Error: Expected DUA not found'
dua_iid = self.__get_iid(dua)
self.__check_dua_registration(SED_1_2, dua_iid, domain_prefix_cid)
self.assertTrue(self.nodes[BBR_1].ping(dua))
if __name__ == '__main__':
unittest.main()
@@ -1,370 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2020, 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.
#
import unittest
import command
import config
import ipaddress
import mle
import network_layer
import thread_cert
BBR_1 = 1 # Collapsed with Leader Role
ROUTER_1_1 = 2
ROUTER_1_2 = 3
FED_1_2_1 = 4
MED_1_2_1 = 5
SED_1_2_1 = 6
FED_1_2_2 = 7
MED_1_2_2 = 8
SED_1_2_2 = 9
WAIT_ATTACH = 5
WAIT_REDUNDANCE = 3
ROUTER_SELECTION_JITTER = 1
BBR_REGISTRATION_JITTER = 5
SED_POLL_PERIOD = 2000 # 2s
MED_TIMEOUT = 20 # 20s
PARENT_AGGREGATE_DELAY = 5 # 5s
DUA_IID_MANUAL1 = '4444333322221111'
ST_DUA_SUCCESS = 0
ST_DUA_REREGISTER = 1
ST_DUA_INVALID = 2
ST_DUA_DUPLICATE = 3
ST_DUA_NO_RESOURCES = 4
ST_DUA_BBR_NOT_PRIMARY = 5
ST_DUA_GENERAL_FAILURE = 6
BBR_REREGISTRATION_DELAY = 10
"""
Topology
MED_1_2_1 SED_1_2_1
\ |
\ |
FED_1_2_1 --- ROUTER_1_1 FED_1_2_2 MED_1_2_2
| | /
| | /
BBR_1 (LEADER) --- ROUTER_1_2 --- SED_1_2_2
1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain
Prefix without `P_slaac`.
2) Test behaviors of ROUTER_1_2 under various response status:
a) Bring up ROUTER_1_2 with DUA_IID_MANUAL1, one DUA.req should happen to register DUA.
b) Remove DUA_IID_MANUAL1, one DUA.req should happen for the new generated DUA via SLAAC.
c) Configure BBR_1 to respond with the fatal error ST_DUA_INVALID, update BBR_1 with
BBR_REREGISTRATION_DELAY, ROUTER_1_2 should re-register its DUA within BBR_REREGISTRATION_DELAY.
- ROUTER_1_2 should remove its dua
- update network data, ROUTER_1_2 would regenerate and register the same dua
d) Configure BBR_1 to respond with the fatal error ST_DUA_DUPLICATE, update seqno to trigger reregistration.
After received DUA.rsp with ST_DUA_DUPLICATE, ROUTER_1_2 should
- increase dad counter
- regenerate a new DUA
- send DUA.req
e) (repeated) Configure BBR_1 to respond with per remaining error status:
- increase BBR seqno to trigger reregistration
- ROUTER_1_2 should re-register within BBR_REREGISTRATION_DELAY. For the not fatal errors, ROUTER_1_2
should re-register within another BBR_REREGISTRATION_DELAY (with least delay if ST_DUA_REREGISTER)
3) Bring up FED_1_2_1, MED_1_2_1, SED_1_2_1, they should send DUA.req by themselves as the parent
is of Thread 1.1 version.
4) Bring up FED_1_2_2, it sends DUA.req itself as it it FTD.
5) MED_1_2_2, SED_1_2_2, MTDs should should register their DUA to their parent
by Child Update Request, and the parent would send DUA.req for them on behalf.
6) Increase seqno on BBR_1, within BBR_REREGISTRATION_DELAY, there should be one DUA.req from
per [FED_1_2_1, MED_1_2_1, SED_1_2_1, FED_1_2_2], and 3 DUA.req from ROUTER_1_2 among which
2 DUA.req are for its MTD children.
"""
class TestDomainUnicastAddressRegistration(thread_cert.TestCase):
TOPOLOGY = {
BBR_1: {
'version': '1.2',
'allowlist': [ROUTER_1_1, ROUTER_1_2],
'is_bbr': True
},
ROUTER_1_1: {
'version': '1.1',
'allowlist': [BBR_1, FED_1_2_1, MED_1_2_1, SED_1_2_1]
},
ROUTER_1_2: {
'version': '1.2',
'allowlist': [BBR_1, FED_1_2_2, MED_1_2_2, SED_1_2_2]
},
FED_1_2_1: {
'version': '1.2',
'allowlist': [ROUTER_1_1],
},
MED_1_2_1: {
'mode': 'rn',
'version': '1.2',
'allowlist': [ROUTER_1_1],
},
SED_1_2_1: {
'mode': 'n',
'version': '1.2',
'allowlist': [ROUTER_1_1],
},
FED_1_2_2: {
'version': '1.2',
'allowlist': [ROUTER_1_2],
},
MED_1_2_2: {
'mode': 'rn',
'version': '1.2',
'allowlist': [ROUTER_1_2],
},
SED_1_2_2: {
'mode': 'n',
'version': '1.2',
'allowlist': [ROUTER_1_2],
},
}
"""All nodes are created with default configurations"""
def __get_iid(self, address):
''' Get the interface identifier of an IPv6 address.
Args:
address (string): An IPv6 address;
'''
return ''.join(ipaddress.ip_address(address).exploded.split(':')[4:])
def __check_dua_registration_tmf(self, node, occurrences=1, ml_eid=None):
messages = self.simulator.get_messages_sent_by(node)
for i in range(occurrences):
msg = messages.next_coap_message('0.02', '/n/dr', False)
assert msg, 'Expected {}, but {}th not found\n node: {}(extaddr: {})'.format(
occurrences, i + 1, node, self.nodes[node].get_addr64())
if ml_eid:
ml_eid_tlv = msg.get_coap_message_tlv(network_layer.MlEid)
self.assertEqual(ml_eid, ml_eid_tlv.ml_eid.hex())
def test(self):
# starting context id
context_id = 1
seq_num = 1
# 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain
# Prefix without `P_slaac`.
self.nodes[BBR_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].set_backbone_router(seqno=seq_num, reg_delay=BBR_REREGISTRATION_DELAY)
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME * 2)
self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
self.nodes[BBR_1].enable_backbone_router()
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(), 'Primary')
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX)
domain_prefix_cid = context_id
# 2) Test behaviors of ROUTER_1_2 under various response status:
# a) Bring up ROUTER_1_2 with DUA_IID_MANUAL1, one DUA.req should happen to register DUA.
# Flush relative message queues.
self.flush_nodes([ROUTER_1_2])
self.nodes[ROUTER_1_2].set_dua_iid(DUA_IID_MANUAL1)
self.nodes[ROUTER_1_2].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[ROUTER_1_2].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[ROUTER_1_2].get_state(), 'router')
mliid = self.__get_iid(self.nodes[ROUTER_1_2].get_mleid())
WAIT_TIME = WAIT_ATTACH + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 1, self.nodes[ROUTER_1_2].get_mleid_iid())
# b) Remove DUA_IID_MANUAL1, one DUA.req should happen for the new generated DUA via SLAAC.
# Flush relative message queues.
self.flush_nodes([ROUTER_1_2])
self.nodes[ROUTER_1_2].clear_dua_iid()
WAIT_TIME = WAIT_ATTACH + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 1, self.nodes[ROUTER_1_2].get_mleid_iid())
#c) Configure BBR_1 to respond with the fatal error ST_DUA_INVALID, update BBR_1 with
# BBR_REREGISTRATION_DELAY, ROUTER_1_2 should re-register its DUA within BBR_REREGISTRATION_DELAY.
# - ROUTER_1_2 should remove its dua
# - update network data, ROUTER_1_2 would regenerate and register the same dua
# Flush relative message queues.
self.flush_nodes([ROUTER_1_2])
seq_num = seq_num + 1
self.nodes[BBR_1].set_next_dua_response(ST_DUA_INVALID, mliid)
self.nodes[BBR_1].set_backbone_router(seqno=seq_num)
WAIT_TIME = BBR_REREGISTRATION_DELAY + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 1, self.nodes[ROUTER_1_2].get_mleid_iid())
dua = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX)
assert not dua, 'Error: Unexpected DUA ({}) found'.format(dua)
# Retry after new network data is available
seq_num = seq_num + 1
dua = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX)
self.nodes[BBR_1].set_backbone_router(seqno=seq_num)
WAIT_TIME = BBR_REREGISTRATION_DELAY + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 1, self.nodes[ROUTER_1_2].get_mleid_iid())
dua = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua, 'Error: Expected DUA ({}) not found'.format(dua)
#d) Configure BBR_1 to respond with the fatal error ST_DUA_DUPLICATE, update seqno to trigger reregistration.
# After received DUA.rsp with ST_DUA_DUPLICATE, ROUTER_1_2 should
# - increase dad counter
# - regenerate a new DUA
# - send DUA.req
# Flush relative message queues.
self.flush_nodes([ROUTER_1_2])
seq_num = seq_num + 1
self.nodes[BBR_1].set_next_dua_response(ST_DUA_DUPLICATE, mliid)
self.nodes[BBR_1].set_backbone_router(seqno=seq_num)
WAIT_TIME = BBR_REREGISTRATION_DELAY * 2 + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 2, self.nodes[ROUTER_1_2].get_mleid_iid())
dua2 = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX)
assert dua2, 'Error: Expected DUA ({}) not found'.format(dua2)
self.assertNotEqual(dua2, dua)
# e) (repeated) Configure BBR_1 to respond with per remaining error status:
# - increase BBR seqno to trigger reregistration
# - ROUTER_1_2 should re-register within BBR_REREGISTRATION_DELAY. For the not fatal errors, ROUTER_1_2
# should re-register within another BBR_REREGISTRATION_DELAY (with least delay if ST_DUA_REREGISTER)
for status in ['5.00', ST_DUA_REREGISTER, ST_DUA_NO_RESOURCES, ST_DUA_BBR_NOT_PRIMARY, ST_DUA_GENERAL_FAILURE]:
print(f'Testing Status {status}...')
# Flush relative message queues.
self.flush_nodes([ROUTER_1_2])
seq_num = seq_num + 1
self.nodes[BBR_1].set_next_dua_response(status, mliid)
self.nodes[BBR_1].set_backbone_router(seqno=seq_num)
WAIT_TIME = BBR_REREGISTRATION_DELAY + WAIT_REDUNDANCE
if status != ST_DUA_REREGISTER:
WAIT_TIME += BBR_REREGISTRATION_DELAY
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 2, self.nodes[ROUTER_1_2].get_mleid_iid())
# Bring up Router_1_1
self.nodes[ROUTER_1_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[ROUTER_1_1].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router')
dua = self.nodes[ROUTER_1_1].get_addr(config.DOMAIN_PREFIX)
assert not dua, 'Error: Unexpected DUA ({}) found'.format(dua)
# Configure children
for node in [FED_1_2_1, FED_1_2_2]:
self.nodes[node].set_routereligible(False)
for node in [SED_1_2_1, SED_1_2_2]:
self.nodes[node].set_pollperiod(SED_POLL_PERIOD)
for node in [MED_1_2_1, MED_1_2_2]:
self.nodes[node].set_timeout(MED_TIMEOUT)
# 3) Bring up FED_1_2_1, MED_1_2_1, SED_1_2_1, they should send DUA.req by themselves as the parent
# is of Thread 1.1 version.
# 4) Bring up FED_1_2_2, it sends DUA.req itself as it it FTD.
for node in [FED_1_2_1, MED_1_2_1, SED_1_2_1, FED_1_2_2]:
print("Starting child {} (extaddr: {})...".format(node, self.nodes[node].get_addr64()))
# Flush all message queues.
self.flush_all()
self.nodes[node].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[node].get_state(), 'child')
WAIT_TIME = PARENT_AGGREGATE_DELAY + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(node, 1, self.nodes[node].get_mleid_iid())
# 5) MED_1_2_2, SED_1_2_2, MTDs should should register their DUA to their parent
# by Child Update Request, and the parent would send DUA.req for them on behalf.
for node in [MED_1_2_2, SED_1_2_2]:
print("Starting child {} (extaddr: {})...".format(node, self.nodes[node].get_addr64()))
# Flush all message queues.
self.flush_all()
self.nodes[node].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[node].get_state(), 'child')
WAIT_TIME = PARENT_AGGREGATE_DELAY + WAIT_REDUNDANCE
print("waiting {}".format(WAIT_TIME))
self.simulator.go(WAIT_TIME)
self.__check_dua_registration_tmf(ROUTER_1_2, 1, self.nodes[node].get_mleid_iid())
# 6) Increase seqno on BBR_1, within BBR_REREGISTRATION_DELAY, there should be one DUA.req from
# per [FED_1_2_1, MED_1_2_1, SED_1_2_1, FED_1_2_2], and 3 DUA.req from ROUTER_1_2 among which
# 2 DUA.req are for its MTD children.
# Flush all message queues.
self.flush_all()
seq_num = seq_num + 1
self.nodes[BBR_1].set_backbone_router(seqno=seq_num)
WAIT_TIME = BBR_REREGISTRATION_DELAY + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
WAIT_TIME = BBR_REREGISTRATION_DELAY + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
for node in [FED_1_2_1, MED_1_2_1, SED_1_2_1, FED_1_2_2]:
self.__check_dua_registration_tmf(node, 1, self.nodes[node].get_mleid_iid())
self.__check_dua_registration_tmf(ROUTER_1_2, 3)
if __name__ == '__main__':
unittest.main()
@@ -1,148 +0,0 @@
#!/usr/bin/env python3
#
# Copyright (c) 2020, 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.
#
# This script tests how node would handle duplicated Domain Unicast Address.
#
import unittest
import config
import thread_cert
BBR_1 = 1 # Collapsed with Leader Role
ROUTER = 2
FED = 3
MED = 4
WAIT_ATTACH = 5
WAIT_REDUNDANCE = 3
BBR_REGISTRATION_JITTER = 5
SED_POLL_PERIOD = 2000 # 2s
MED_TIMEOUT = 20 # 20s
"""
Topology
BBR_1 (Leader)
|
ROUTER_1---FED
|
MED
"""
WAIT_REDUNDANCE = 3
REG_DELAY = 5
class TestDomainUnicastAddress(thread_cert.TestCase):
TOPOLOGY = {
BBR_1: {
'version': '1.2',
'allowlist': [ROUTER],
'is_bbr': True
},
ROUTER: {
'version': '1.2',
'allowlist': [BBR_1, FED, MED],
},
FED: {
'version': '1.2',
'allowlist': [ROUTER],
'router_eligible': False,
'mode': 'rdn',
},
MED: {
'version': '1.2',
'is_mtd': True,
'allowlist': [ROUTER],
'mode': 'rn',
},
}
def test(self):
self.simulator.set_lowpan_context(1, config.DOMAIN_PREFIX)
# 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain
# Prefix without `P_slaac`.
self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].set_backbone_router(seqno=1, reg_delay=REG_DELAY)
self.nodes[BBR_1].start()
self.simulator.go(WAIT_ATTACH * 2 + config.DEFAULT_ROUTER_SELECTION_JITTER)
self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
self.nodes[BBR_1].enable_backbone_router()
self.simulator.go(BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(), 'Primary')
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
self.simulator.go(WAIT_REDUNDANCE)
# 2) Bring up ROUTER_1
self.nodes[ROUTER].start()
self.simulator.go(WAIT_ATTACH + REG_DELAY + WAIT_REDUNDANCE)
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
# Bring up FED
self.nodes[FED].start()
self.simulator.go(WAIT_ATTACH + REG_DELAY + WAIT_REDUNDANCE)
self.assertEqual(self.nodes[FED].get_state(), 'child')
# Bring up MED
self.nodes[MED].start()
self.simulator.go(WAIT_ATTACH + config.PARENT_AGGREGATIOIN_DELAY + REG_DELAY + WAIT_REDUNDANCE)
self.assertEqual(self.nodes[MED].get_state(), 'child')
self._verify_dua_handle_address_error(ROUTER)
self._verify_dua_handle_address_error(FED)
self._verify_dua_handle_address_error(MED, is_med=True)
def _verify_dua_handle_address_error(self, nodeid, is_med=False):
dua = self.nodes[nodeid].get_addr(config.DOMAIN_PREFIX)
self.assertIsNotNone(dua)
# Ping the DUA to verify reachability, and also fill the EID cache on BBR_1
self.assertTrue(self.nodes[BBR_1].ping(dua))
self.simulator.go(WAIT_REDUNDANCE)
# Send fake /a/an from ROUTER to BBR_1 for the node's DUA
pbbr_rloc = self.nodes[BBR_1].get_ip6_address(config.ADDRESS_TYPE.RLOC)
self.nodes[ROUTER].send_address_notification(pbbr_rloc, dua, f'000000000000{nodeid:04x}')
self.simulator.go(config.PARENT_AGGREGATIOIN_DELAY * is_med + REG_DELAY + WAIT_REDUNDANCE + 50)
# Make sure device handles /a/ae correctly by generating new DUA
new_dua = self.nodes[nodeid].get_addr(config.DOMAIN_PREFIX)
self.assertNotEqual(dua, new_dua)
self.assertTrue(self.nodes[BBR_1].ping(new_dua))
self.assertFalse(self.nodes[BBR_1].ping(dua))
self.simulator.go(3)
if __name__ == '__main__':
unittest.main()
@@ -20,7 +20,6 @@ ot_build:
- "-DOPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS=8" - "-DOPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS=8"
options: options:
- "-DOT_REFERENCE_DEVICE=ON" - "-DOT_REFERENCE_DEVICE=ON"
- "-DOT_DUA=ON"
- "-DOT_MLR=ON" - "-DOT_MLR=ON"
- "-DOT_COMMISSIONER=ON" - "-DOT_COMMISSIONER=ON"
- "-DOT_JOINER=ON" - "-DOT_JOINER=ON"
@@ -35,7 +34,6 @@ ot_build:
- "-DOPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS=8" - "-DOPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS=8"
options: options:
- "-DOT_REFERENCE_DEVICE=ON" - "-DOT_REFERENCE_DEVICE=ON"
- "-DOT_DUA=ON"
- "-DOT_MLR=ON" - "-DOT_MLR=ON"
- "-DOT_COMMISSIONER=ON" - "-DOT_COMMISSIONER=ON"
- "-DOT_JOINER=ON" - "-DOT_JOINER=ON"
@@ -57,7 +55,6 @@ ot_build:
- OT_COMMISSIONER=1 - OT_COMMISSIONER=1
options: options:
- "-DOTBR_DUA_ROUTING=ON" - "-DOTBR_DUA_ROUTING=ON"
- "-DOT_DUA=ON"
- "-DOT_MLR=ON" - "-DOT_MLR=ON"
rcp_subpath: build/ot12/simulation rcp_subpath: build/ot12/simulation
rcp_options: rcp_options:
@@ -76,7 +73,6 @@ ot_build:
- EXTERNAL_COMMISSIONER=1 - EXTERNAL_COMMISSIONER=1
options: options:
- "-DOTBR_DUA_ROUTING=ON" - "-DOTBR_DUA_ROUTING=ON"
- "-DOT_DUA=ON"
- "-DOT_MLR=ON" - "-DOT_MLR=ON"
rcp_subpath: build/ot13/simulation rcp_subpath: build/ot13/simulation
rcp_options: rcp_options:
-17
View File
@@ -2594,23 +2594,6 @@ class OTCI(object):
"""Set the Thread Domain Name for Thread 1.2 device.""" """Set the Thread Domain Name for Thread 1.2 device."""
self.execute_command(f'domainname {self.__escape_escapable(name)}') self.execute_command(f'domainname {self.__escape_escapable(name)}')
def get_dua_iid(self) -> str:
"""Get the DUA IID for Thread 1.2 device."""
raw_iid = self.execute_command('dua iid')
if raw_iid:
return self.__parse_iid(raw_iid)
else:
return ''
def set_dua_iid(self, iid: str):
"""Set the DUA IID for Thread 1.2 device."""
self.__validate_iid(iid)
self.execute_command(f'dua iid {iid}')
def clear_dua_iid(self):
"""Clear the DUA IID for Thread 1.2 device."""
self.execute_command('dua iid clear')
# TODO: mlr reg <ipaddr> ... [timeout] # TODO: mlr reg <ipaddr> ... [timeout]
# #
-4
View File
@@ -135,10 +135,6 @@ class TestOTCI(unittest.TestCase):
self.assertEqual('fd00:dba::/64', leader.get_mesh_local_prefix()) self.assertEqual('fd00:dba::/64', leader.get_mesh_local_prefix())
leader.set_mesh_local_prefix(TEST_MESH_LOCAL_PREFIX + '/64') leader.set_mesh_local_prefix(TEST_MESH_LOCAL_PREFIX + '/64')
leader.set_ml_iid('b1a5ed57a71571c5') leader.set_ml_iid('b1a5ed57a71571c5')
leader.set_dua_iid('ad4a011dad4a011d')
self.assertEqual('ad4a011dad4a011d', leader.get_dua_iid())
leader.clear_dua_iid()
self.assertEqual('', leader.get_dua_iid())
self.assertFalse(leader.get_ifconfig_state()) self.assertFalse(leader.get_ifconfig_state())
# ifconfig up # ifconfig up