From babbccd4c6dda6ab7054c6168b28bf1fde9548f9 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 28 Feb 2025 13:49:30 -0800 Subject: [PATCH] [srp-server] introduce "fast start mode" feature (#11305) This commit adds "Fast Start Mode" feature for SRP server. This feature is designed for scenarios where a device, often a mobile device, needs to act as a provisional SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only if no other Border Routers are already providing the SRP service within the Thread network. A common use case is a mobile device joining a Thread network where it may be the first, or only, BR. Importantly, Fast Start Mode allows the device to quickly start its SRP server functionality upon joining the network, allowing other Thread devices to quickly connect and register their services without the typical delays associated with standard Border Router initialization and SRP server startup (using NetData Publisher). --- etc/cmake/options.cmake | 1 + include/openthread/instance.h | 2 +- include/openthread/srp_server.h | 51 ++++++++ script/check-scan-build | 1 + script/cmake-build | 1 + script/test | 1 + src/cli/README_SRP_SERVER.md | 24 ++++ src/cli/cli_srp_server.cpp | 59 +++++++++ src/core/api/srp_server_api.cpp | 12 ++ src/core/common/notifier.cpp | 4 + src/core/config/srp_server.h | 18 +++ src/core/net/srp_server.cpp | 101 +++++++++++++++ src/core/net/srp_server.hpp | 39 ++++++ ...openthread-core-toranj-config-simulation.h | 2 + tests/unit/test_srp_server.cpp | 120 +++++++++++++++++- 15 files changed, 428 insertions(+), 8 deletions(-) diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index b6a342a7d..92a516a90 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -250,6 +250,7 @@ ot_option(OT_SNTP_CLIENT OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE "SNTP client") ot_option(OT_SRP_ADV_PROXY OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE "SRP advertising proxy") ot_option(OT_SRP_CLIENT OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE "SRP client") ot_option(OT_SRP_SERVER OPENTHREAD_CONFIG_SRP_SERVER_ENABLE "SRP server") +ot_option(OT_SRP_SERVER_FAST_START_MDOE OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE "SRP server fast start") ot_option(OT_TCP OPENTHREAD_CONFIG_TCP_ENABLE "TCP") ot_option(OT_TIME_SYNC OPENTHREAD_CONFIG_TIME_SYNC_ENABLE "time synchronization service") ot_option(OT_TREL OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE "TREL radio link for Thread over Infrastructure feature") diff --git a/include/openthread/instance.h b/include/openthread/instance.h index d638ca843..6fa803c65 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (480) +#define OPENTHREAD_API_VERSION (481) /** * @addtogroup api-instance diff --git a/include/openthread/srp_server.h b/include/openthread/srp_server.h index 45fa6e732..f825c84eb 100644 --- a/include/openthread/srp_server.h +++ b/include/openthread/srp_server.h @@ -272,6 +272,57 @@ void otSrpServerSetAutoEnableMode(otInstance *aInstance, bool aEnabled); */ bool otSrpServerIsAutoEnableMode(otInstance *aInstance); +/** + * Enables the "Fast Start Mode" on the SRP server. + * + * Requires the `OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE` feature to be enabled. + * + * The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a provisional + * SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only if no other + * Border Routers (BRs) are already providing the SRP service within the Thread network. A common use case is a mobile + * device joining a Thread network where it may be the first, or only, BR. Importantly, Fast Start Mode allows the + * device to quickly start its SRP server functionality upon joining the network, allowing other Thread devices to + * quickly connect and register their services without the typical delays associated with standard Border Router + * initialization (and SRP server startup). + * + * When Fast Start Mode is enabled, the SRP server manages when to start or stop based on the presence of other BRs, + * following this process: + * - Upon initial attachment to the Thread network, the device immediately inspects the received Network Data for any + * existing "SRP/DNS" entries. These entries indicate the presence of other active BRs providing SRP server service: + * - If no "SRP/DNS" entries from other BRs are found, the device immediately enables its own SRP server. This + * activation uses `OT_SRP_SERVER_ADDRESS_MODE_UNICAST_FORCE_ADD`, which bypasses the usual delay associated with + * the standard Network Data publisher, directly adding its own "SRP/DNS unicast" entry to the Network Data. + * - If "SRP/DNS" entries from other BRs are detected, the device will not enable its SRP server, deferring to the + * existing ones. + * - After starting its SRP server in Fast Start Mode, the device continuously monitors the Network Data. If, at any + * point, new "SRP/DNS" entries appear (indicating that another BR has become active), the device automatically + * disables its own SRP server functionality, relinquishing the role to the newly available BR. + * + * The Fast Start Mode can be enabled when the device is in the detached or disabled state, the SRP server is currently + * disabled, and "auto-enable mode" is not in use (i.e., `otSrpServerIsAutoEnableMode()` returns `false`). + * + * After successfully enabling Fast Start Mode, it can be disabled by a direct call to `otSrpServerSetEnabled()`, + * explicitly enabling or disabling the SRP server function. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * + * @retval OT_ERROR_NONE Fast Start Mode was successfully enabled. + * @retval OT_ERROR_INVALID_STATE Cannot enable Fast Start Mode (e.g., already attached or server already enabled). + */ +otError otSrpServerEnableFastStartMode(otInstance *aInstance); + +/** + * Indicates whether the Fast Start Mode is enabled or disabled. + * + * Requires `OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE` feature to be enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval TRUE The fast-start mode is enabled. + * @retval FALSE The fast-start mode is disabled. + */ +bool otSrpServerIsFastStartmodeEnabled(otInstance *aInstance); + /** * Returns SRP server TTL configuration. * diff --git a/script/check-scan-build b/script/check-scan-build index 142468f9c..51834cb8d 100755 --- a/script/check-scan-build +++ b/script/check-scan-build @@ -80,6 +80,7 @@ OT_BUILD_OPTIONS=( "-DOT_SRP_ADV_PROXY=ON" "-DOT_SRP_CLIENT=ON" "-DOT_SRP_SERVER=ON" + "-DOT_SRP_SERVER_FAST_START_MDOE=ON" "-DOT_UPTIME=ON" "-DOT_VENDOR_NAME=OpenThread" "-DOT_VENDOR_MODEL=Scan-build" diff --git a/script/cmake-build b/script/cmake-build index 2756d3d44..adcaf2569 100755 --- a/script/cmake-build +++ b/script/cmake-build @@ -110,6 +110,7 @@ OT_POSIX_SIM_COMMON_OPTIONS=( "-DOT_SNTP_CLIENT=ON" "-DOT_SRP_CLIENT=ON" "-DOT_SRP_SERVER=ON" + "-DOT_SRP_SERVER_FAST_START_MDOE=ON" "-DOT_UPTIME=ON" ) readonly OT_POSIX_SIM_COMMON_OPTIONS diff --git a/script/test b/script/test index aebc2fd6c..128b0ae09 100755 --- a/script/test +++ b/script/test @@ -109,6 +109,7 @@ build_simulation() "-DOT_SERVICE=ON" "-DOT_SRP_CLIENT=ON" "-DOT_SRP_SERVER=ON" + "-DOT_SRP_SERVER_FAST_START_MDOE=ON" "-DOT_UPTIME=ON" "-DOT_THREAD_VERSION=${version}" ) diff --git a/src/cli/README_SRP_SERVER.md b/src/cli/README_SRP_SERVER.md index f86e52fbe..791a2da45 100644 --- a/src/cli/README_SRP_SERVER.md +++ b/src/cli/README_SRP_SERVER.md @@ -33,6 +33,7 @@ auto disable domain enable +faststart help host lease @@ -129,6 +130,29 @@ Enable the SRP server. Done ``` +### faststart + +Usage: `srp server faststart [enable]` + +This command requires that `OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE` be enabled. + +Enables the "Fast Start Mode" on the SRP server. + +The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a provisional SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only if no other Border Routers (BRs) are already providing the SRP service within the Thread network. Importantly, Fast Start Mode allows the device to quickly start its SRP server functionality upon joining the network, allowing other Thread devices to quickly connect and register their services without the typical delays associated with standard Border Router initialization (and SRP server startup). + +The Fast Start Mode can be enabled when the device is in the detached or disabled state, the SRP server is currently disabled, and "auto-enable mode" is not in use. + +After successfully enabling Fast Start Mode, it can be disabled by a direct command to enable/disable the SRP server, using `srp server [enable/disable]`. + +```bash +> srp server faststart enable +Done + +> srp server faststart +Enabled +Done +``` + ### host Usage: `srp server host` diff --git a/src/cli/cli_srp_server.cpp b/src/cli/cli_srp_server.cpp index 0845c5de6..c8f7c9d91 100644 --- a/src/cli/cli_srp_server.cpp +++ b/src/cli/cli_srp_server.cpp @@ -166,6 +166,62 @@ template <> otError SrpServer::Process(Arg aArgs[]) return error; } +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE +/** + * @cli srp server faststart (enable) + * @code + * srp server faststart enable + * Done + * @endcode + * @code + * srp server faststart + * Enabled + * Done + * @endcode + * @cparam srp server faststart [@ca{enable}] + * @par + * Enables the "Fast Start Mode" on the SRP server. + * @par + * The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a provisional + * SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only if no other + * Border Routers (BRs) are already providing the SRP service within the Thread network. Importantly, Fast Start Mode + * allows the device to quickly start its SRP server functionality upon joining the network, allowing other Thread + * devices to quickly connect and register their services without the typical delays associated with standard Border + * Router initialization (and SRP server startup). + * @par + * The Fast Start Mode can be enabled when the device is in the detached or disabled state, the SRP server is currently + * disabled, and "auto-enable mode" is not in use. + * @par + * After successfully enabling Fast Start Mode, it can be disabled by a direct command to enable/disable the SRP + * server, using `srp server [enable/disable]`. + * @par + * This command requires that `OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE` be enabled. + * @moreinfo{@srp}. + * @sa otSrpServerIsFastStartmodeEnabled + * @sa otSrpServerEnableFastStartMode + */ +template <> otError SrpServer::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + if (aArgs[0].IsEmpty()) + { + OutputEnabledDisabledStatus(otSrpServerIsFastStartmodeEnabled(GetInstancePtr())); + } + else if (aArgs[0] == "enable") + { + error = otSrpServerEnableFastStartMode(GetInstancePtr()); + } + else + { + error = OT_ERROR_INVALID_ARGS; + } + + return error; +} + +#endif // OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + /** * @cli srp server state * @code @@ -552,6 +608,9 @@ otError SrpServer::Process(Arg aArgs[]) CmdEntry("disable"), CmdEntry("domain"), CmdEntry("enable"), +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + CmdEntry("faststart"), +#endif CmdEntry("host"), CmdEntry("lease"), CmdEntry("seqnum"), diff --git a/src/core/api/srp_server_api.cpp b/src/core/api/srp_server_api.cpp index ff1f87322..09a80a984 100644 --- a/src/core/api/srp_server_api.cpp +++ b/src/core/api/srp_server_api.cpp @@ -90,6 +90,18 @@ bool otSrpServerIsAutoEnableMode(otInstance *aInstance) } #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE +otError otSrpServerEnableFastStartMode(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().EnableFastStartMode(); +} + +bool otSrpServerIsFastStartmodeEnabled(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().IsFastStartModeEnabled(); +} +#endif + void otSrpServerGetTtlConfig(otInstance *aInstance, otSrpServerTtlConfig *aTtlConfig) { AsCoreType(aInstance).Get().GetTtlConfig(AsCoreType(aTtlConfig)); diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp index f59caace1..c6037fc2d 100644 --- a/src/core/common/notifier.cpp +++ b/src/core/common/notifier.cpp @@ -151,6 +151,10 @@ void Notifier::EmitEvents(void) #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE Get().HandleNotifierEvents(events); #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + Get().HandleNotifierEvents(events); +#endif + #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE // The `NetworkData::Publisher` is notified last (e.g., after SRP // client) to allow other modules to request changes to what is diff --git a/src/core/config/srp_server.h b/src/core/config/srp_server.h index 315fb6572..82c9ba053 100644 --- a/src/core/config/srp_server.h +++ b/src/core/config/srp_server.h @@ -120,6 +120,24 @@ #define OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + * + * The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a provisional + * SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only if no other + * Border Routers (BRs) are already providing the SRP service within the Thread network. A common use case is a mobile + * device joining a Thread network where it may be the first, or only, BR. Importantly, Fast Start Mode allows the + * device to quickly start its SRP server functionality upon joining the network, allowing other Thread devices to + * quickly connect and register their services without the typical delays associated with standard Border Router + * initialization (and SRP server startup). + * + * The Fast Start Mode can be enabled using `otSrpServerEnableFastStartMode()`. More details about behavior and + * restrictions are provided in the documentation of this API. + */ +#ifndef OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE +#define OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE 0 +#endif + /** * @} */ diff --git a/src/core/net/srp_server.cpp b/src/core/net/srp_server.cpp index 9dd3b0a8a..141854170 100644 --- a/src/core/net/srp_server.cpp +++ b/src/core/net/srp_server.cpp @@ -89,6 +89,9 @@ Server::Server(Instance &aInstance) #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE , mAutoEnable(false) #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + , mFastStartMode(false) +#endif { IgnoreError(SetDomain(kDefaultDomain)); } @@ -124,6 +127,9 @@ void Server::SetEnabled(bool aEnabled) #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE mAutoEnable = false; #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + mFastStartMode = false; +#endif if (aEnabled) { @@ -210,6 +216,101 @@ exit: } #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE +Error Server::EnableFastStartMode(void) +{ + Error error = kErrorNone; + + VerifyOrExit(!mFastStartMode); + + VerifyOrExit(!Get().IsAttached(), error = kErrorInvalidState); + VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState); +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + VerifyOrExit(!mAutoEnable, error = kErrorInvalidState); +#endif + + mFastStartMode = true; + LogInfo("FastStartMode enabled"); + +exit: + return error; +} + +void Server::HandleNotifierEvents(Events aEvents) +{ + VerifyOrExit(mFastStartMode); + + if (mState == kStateDisabled) + { + VerifyOrExit(aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadNetdataChanged)); + VerifyOrExit(Get().IsAttached()); + + if (!NetDataContainsOtherSrpServers()) + { + LogInfo("FastStartMode - No SRP server in NetData"); + + mPrevAddressMode = mAddressMode; + IgnoreError(SetAddressMode(kAddressModeUnicastForceAdd)); + Enable(); + } + } + else + { + VerifyOrExit(aEvents.Contains(kEventThreadNetdataChanged)); + + if (NetDataContainsOtherSrpServers()) + { + LogInfo("FastStartMode - New SRP server entry in NetData"); + + Disable(); + IgnoreError(SetAddressMode(mPrevAddressMode)); + } + } + +exit: + return; +} + +bool Server::NetDataContainsOtherSrpServers(void) const +{ + bool contains = false; + NetworkData::Service::DnsSrpAnycastInfo anycastInfo; + NetworkData::Service::DnsSrpUnicastInfo unicastInfo; + NetworkData::Service::Manager::Iterator iterator; + + if (Get().FindPreferredDnsSrpAnycastInfo(anycastInfo) == kErrorNone) + { + contains = true; + ExitNow(); + } + + iterator.Reset(); + + if (Get().GetNextDnsSrpUnicastInfo( + iterator, NetworkData::Service::kAddrInServiceData, unicastInfo) == kErrorNone) + { + contains = true; + ExitNow(); + } + + iterator.Reset(); + + while (Get().GetNextDnsSrpUnicastInfo( + iterator, NetworkData::Service::kAddrInServerData, unicastInfo) == kErrorNone) + { + if (!Get().HasRloc16(unicastInfo.mRloc16)) + { + contains = true; + ExitNow(); + } + } + +exit: + return contains; +} + +#endif // OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + Server::TtlConfig::TtlConfig(void) { mMinTtl = kDefaultMinTtl; diff --git a/src/core/net/srp_server.hpp b/src/core/net/srp_server.hpp index d2353e775..33006ca09 100644 --- a/src/core/net/srp_server.hpp +++ b/src/core/net/srp_server.hpp @@ -109,6 +109,7 @@ class AdvertisingProxy; */ class Server : public InstanceLocator, private NonCopyable { + friend class ot::Notifier; friend class NetworkData::Publisher; friend class UpdateMetadata; friend class Service; @@ -762,6 +763,34 @@ public: bool IsAutoEnableMode(void) const { return mAutoEnable; } #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + /** + * Enables the "Fast Start Mode" on the SRP server. + * + * The Fast Start Mode is designed for scenarios where a device, often a mobile device, needs to act as a + * provisional SRP server (e.g., functioning as a temporary Border Router). The SRP server function is enabled only + * if no other Border Routers (BRs) are already providing the SRP service within the Thread network. A common use + * case is a mobile device joining a Thread network where it may be the first, or only, BR. Importantly, Fast + * Start Mode allows the device to quickly start its SRP server functionality upon joining the network, allowing + * other Thread devices to quickly connect and register their services without the typical delays associated with + * standard Border Router initialization (and SRP server startup). + * + * Please refer to `otSrpServerEnableFastStartMode()` for more details. + * + * @retval kErrorNone Fast Start Mode was successfully enabled. + * @retval kErrorInvalidState Cannot enable Fast Start Mode (e.g., already attached or server already enabled). + */ + Error EnableFastStartMode(void); + + /** + * Indicates whether the Fast Start Mode is enabled or disabled. + * + * @retval TRUE The fast-start mode is enabled. + * @retval FALSE The fast-start mode is disabled. + */ + bool IsFastStartModeEnabled(void) const { return mFastStartMode; } +#endif + /** * Returns the TTL configuration. * @@ -919,6 +948,11 @@ private: Error HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + void HandleNotifierEvents(Events aEvents); + bool NetDataContainsOtherSrpServers(void) const; +#endif + void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent); ServiceUpdateId AllocateServiceUpdateId(void) { return mServiceUpdateId++; } @@ -1014,6 +1048,11 @@ private: bool mAutoEnable : 1; #endif +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + bool mFastStartMode : 1; + AddressMode mPrevAddressMode; +#endif + otSrpServerResponseCounters mResponseCounters; }; diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h index 1623abf72..c0f4dc03d 100644 --- a/tests/toranj/openthread-core-toranj-config-simulation.h +++ b/tests/toranj/openthread-core-toranj-config-simulation.h @@ -43,6 +43,8 @@ #define OPENTHREAD_CONFIG_PLATFORM_INFO "SIMULATION-toranj" #endif +#define OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE 1 + #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 #define OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE 1 diff --git a/tests/unit/test_srp_server.cpp b/tests/unit/test_srp_server.cpp index a9aa5ec30..5ac0ef9aa 100644 --- a/tests/unit/test_srp_server.cpp +++ b/tests/unit/test_srp_server.cpp @@ -185,7 +185,7 @@ void AdvanceTime(uint32_t aDuration) sNow = time; } -void InitTest(void) +void InitTest(bool aStartThread = true) { //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Initialize OT instance. @@ -208,15 +208,18 @@ void InitTest(void) otDatasetConvertToTlvs(&dataset, &datasetTlvs); SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs)); - SuccessOrQuit(otIp6SetEnabled(sInstance, true)); - SuccessOrQuit(otThreadSetEnabled(sInstance, true)); + if (aStartThread) + { + SuccessOrQuit(otIp6SetEnabled(sInstance, true)); + SuccessOrQuit(otThreadSetEnabled(sInstance, true)); - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Ensure device starts as leader. + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Ensure device starts as leader. - AdvanceTime(10000); + AdvanceTime(10000); - VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER); + VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER); + } } void FinalizeTest(void) @@ -1275,6 +1278,106 @@ void TestSrpServerAddressModeForceAdd(void) Log("End of TestSrpServerAddressModeForceAdd"); } +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + +void TestSrpServerFastStartMode(void) +{ + Srp::Server *srpServer; + otExternalRouteConfig route; + Ip6::Address address; + + Log("--------------------------------------------------------------------------------------------"); + Log("TestSrpServerFastStartMode"); + + InitTest(/* aStartThread */ false); + + srpServer = &sInstance->Get(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Configure SRP server to use the "Fast Start Mode"/ + + SuccessOrQuit(srpServer->EnableFastStartMode()); + VerifyOrQuit(srpServer->IsFastStartModeEnabled()); + + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Bring the IPv6 interface up and start Thread operation. + + SuccessOrQuit(otIp6SetEnabled(sInstance, true)); + SuccessOrQuit(otThreadSetEnabled(sInstance, true)); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Ensure that as soon as device attaches, the SRP server is started. + + while (otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_DETACHED) + { + AdvanceTime(100); + } + + VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER); + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning); + VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicastForceAdd); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Add new entries in Network Data to trigger an "NetDataChanged" event + // and ensure that the SRP server continues to run. + + AdvanceTime(10 * 1000); + + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning); + + ClearAllBytes(route); + route.mStable = true; + + SuccessOrQuit(otBorderRouterAddRoute(sInstance, &route)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); + + AdvanceTime(1 * 1000); + + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Publish an "DNS/SRP" entry in Network Data and ensure that this is + // correctly detected by the "Fast Start Mode" and triggers SRP server to be + // disabled. + + SuccessOrQuit(address.FromString("fd00::1")); + otNetDataPublishDnsSrpServiceUnicast(sInstance, &address, /* aPort */ 1234, 0); + + AdvanceTime(10 * 1000); + VerifyOrQuit(otNetDataIsDnsSrpServiceAdded(sInstance)); + + VerifyOrQuit(srpServer->IsFastStartModeEnabled()); + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled); + + // Ensure the original AddressMode is restored on SRP server + + VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Unpublish the "DNS/SRP" entry in Network Data and check that + // the "Fast Start Mode" causes the SRP server to start again. + + otNetDataUnpublishDnsSrpService(sInstance); + + AdvanceTime(25 * 1000); + VerifyOrQuit(!otNetDataIsDnsSrpServiceAdded(sInstance)); + + VerifyOrQuit(srpServer->IsFastStartModeEnabled()); + VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Finalize OT instance and validate all heap allocations are freed. + + Log("Finalizing OT instance"); + FinalizeTest(); + + Log("End of TestSrpServerFastStartMode"); +} + +#endif // OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + #endif // ENABLE_SRP_TEST } // namespace ot @@ -1292,6 +1395,9 @@ int main(void) ot::TestSrpClientDelayedResponse(); #endif ot::TestSrpServerAddressModeForceAdd(); +#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE + ot::TestSrpServerFastStartMode(); +#endif printf("All tests passed\n"); #else