From d56222a8dbb5255527882d6a2fb65eea82436516 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 30 Apr 2025 07:38:07 -0700 Subject: [PATCH] [border-agent] add API to enable/disable Border Agent service (#11458) This commit adds a new API to allow the Border Agent service to be enabled or disabled. By default, the Border Agent service is enabled when the `OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE` feature is used. This new API allows the user to explicitly control its state. This can be useful in scenarios such as: - The user code wishes to delay the start of the Border Agent service (and its mDNS advertisement of the `_meshcop._udp` service on the infrastructure link). This allows time to prepare or determine vendor-specific TXT data entries for inclusion. - Unit tests or test scripts might disable the Border Agent service to prevent it from interfering with specific test steps. For example, tests validating mDNS or DNS-SD functionality may disable the Border Agent to prevent its registration of the MeshCoP service. This commit also adds a corresponding CLI command for the new API and updates `test_border_agent` to validate this functionality. --- include/openthread/border_agent.h | 30 +++++++++++++++++++- include/openthread/instance.h | 2 +- src/cli/README.md | 28 ++++++++++++++++-- src/cli/cli.cpp | 37 +++++++++++++++++++++--- src/core/api/border_agent_api.cpp | 20 +++++++++---- src/core/meshcop/border_agent.cpp | 47 ++++++++++++++++++++++++------- src/core/meshcop/border_agent.hpp | 42 +++++++++++++++++++++------ tests/nexus/test_border_agent.cpp | 12 ++++++++ 8 files changed, 187 insertions(+), 31 deletions(-) diff --git a/include/openthread/border_agent.h b/include/openthread/border_agent.h index 6268bc795..3a5b3810c 100644 --- a/include/openthread/border_agent.h +++ b/include/openthread/border_agent.h @@ -151,7 +151,35 @@ typedef struct otBorderAgentMeshCoPServiceTxtData } otBorderAgentMeshCoPServiceTxtData; /** - * Indicates whether or not the Border Agent service is active and running. + * Enables or disables the Border Agent service on the device. + * + * By default, the Border Agent service is enabled when the `OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE` feature is used. + * This function allows higher-layer code to explicitly control its state. This can be useful in scenarios such as: + * + * - The higher-layer code wishes to delay the start of the Border Agent service (and its mDNS advertisement of the + * `_meshcop._udp` service on the infrastructure link). This allows time to prepare or determine vendor-specific TXT + * data entries for inclusion. + * - Unit tests or test scripts might disable the Border Agent service to prevent it from interfering with specific + * test steps. For example, tests validating mDNS or DNS-SD functionality may disable the Border Agent to prevent its + * registration of the MeshCoP service. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aEnabled A boolean to indicate whether to to enable (TRUE), or disable (FALSE). + */ +void otBorderAgentSetEnabled(otInstance *aInstance, bool aEnabled); + +/** + * Indicates whether or not the Border Agent service is enabled. + * + * @param[in] aInstance The OpenThread instance. + * + * @retval TRUE The Border Agent service is enabled. + * @retval FALSE The Border Agent service is disabled. + */ +bool otBorderAgentIsEnabled(otInstance *aInstance); + +/** + * Indicates whether or not the Border Agent service is enabled and also active. * * While the Border Agent is active, external commissioner candidates can try to connect to and establish secure DTLS * sessions with the Border Agent using PSKc. A connected commissioner can then petition to become a full commissioner. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index f7d9685bb..08a3203ea 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 (503) +#define OPENTHREAD_API_VERSION (504) /** * @addtogroup api-instance diff --git a/src/cli/README.md b/src/cli/README.md index 7cb2689c6..c7fe94831 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -361,6 +361,29 @@ Done Show current Border Agent information. +### ba enable + +Enables Border Agent service. + +By default, the Border Agent service is enabled. The `ba enable` and `ba disable` allow user to explicitly control its state. This can be useful in scenarios such as: + +- The user wishes to delay the start of the Border Agent service (and its mDNS advertisement of the `_meshcop._udp` service on the infrastructure link). This allows time to prepare or determine vendor-specific TXT data entries for inclusion. +- Unit tests or test scripts might disable the Border Agent service to prevent it from interfering with specific test steps. For example, tests validating mDNS or DNS-SD functionality may disable the Border Agent to prevent its registration of the MeshCoP service. + +``` +> ba enable +Done +``` + +### ba disable + +Disables Border Agent service. + +``` +> ba disable +Done +``` + ### ba port Print Border Agent's service port. @@ -377,8 +400,9 @@ Print Border Agent's state. Possible states are -- `Active`: Border Agent is active. -- `Inactive`: Border Agent is not active. +- `Disabled`: Border Agent service is disabled. +- `Inactive`: Border Agent service is enabled but not yet active. +- `Active`: Border Agent service is enabled and active. External commissioner can connect and establish secure DTLS sessions with the Border Agent using PSKc ```bash > ba state diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 461f15903..e90f3ff97 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -445,6 +445,23 @@ template <> otError Interpreter::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; + /** + * @cli ba (enable, disable) + * @code + * ba enable + * Done + * @endcode + * @code + * ba disable + * Done + * @endcode + * @cparam ba @ca{enable|disable} + * @par api_copy + * #otBorderAgentSetEnabled + */ + if (ProcessEnableDisable(aArgs, otBorderAgentSetEnabled) == OT_ERROR_NONE) + { + } /** * @cli ba port * @code @@ -455,7 +472,7 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @par api_copy * #otBorderAgentGetUdpPort */ - if (aArgs[0] == "port") + else if (aArgs[0] == "port") { OutputLine("%u", otBorderAgentGetUdpPort(GetInstancePtr())); } @@ -466,12 +483,24 @@ template <> otError Interpreter::Process(Arg aArgs[]) * Active * Done * @endcode - * @par api_copy - * #otBorderAgentIsActive + * @par + * Prints the current state of the Border Agent service. Possible states are: + * - `Disabled`: Border Agent service is disabled. + * - `Inactive`: Border Agent service is enabled but not yet active. + * - `Active`: Border Agent service is enabled and active. External commissioner can connect and establish secure + * DTLS sessions with the Border Agent using PSKc + * @sa #otBorderAgentIsActive */ else if (aArgs[0] == "state") { - OutputLine("%s", otBorderAgentIsActive(GetInstancePtr()) ? "Active" : "Inactive"); + if (!otBorderAgentIsEnabled(GetInstancePtr())) + { + OutputLine("Disabled"); + } + else + { + OutputLine("%s", otBorderAgentIsActive(GetInstancePtr()) ? "Active" : "Inactive"); + } } /** * @cli ba sessions diff --git a/src/core/api/border_agent_api.cpp b/src/core/api/border_agent_api.cpp index 0fd74d231..88eef3433 100644 --- a/src/core/api/border_agent_api.cpp +++ b/src/core/api/border_agent_api.cpp @@ -42,6 +42,21 @@ using namespace ot; +void otBorderAgentSetEnabled(otInstance *aInstance, bool aEnabled) +{ + AsCoreType(aInstance).Get().SetEnabled(aEnabled); +} + +bool otBorderAgentIsEnabled(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().IsEnabled(); +} + +bool otBorderAgentIsActive(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().IsRunning(); +} + #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId) { @@ -54,11 +69,6 @@ otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId) } #endif -bool otBorderAgentIsActive(otInstance *aInstance) -{ - return AsCoreType(aInstance).Get().IsRunning(); -} - uint16_t otBorderAgentGetUdpPort(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetUdpPort(); diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 8ee10baf6..b771988e6 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -47,6 +47,7 @@ RegisterLogModule("BorderAgent"); BorderAgent::BorderAgent(Instance &aInstance) : InstanceLocator(aInstance) + , mEnabled(true) , mIsRunning(false) , mDtlsTransport(aInstance, kNoLinkSecurity) #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE @@ -103,6 +104,29 @@ exit: } #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE +void BorderAgent::SetEnabled(bool aEnabled) +{ + VerifyOrExit(mEnabled != aEnabled); + mEnabled = aEnabled; + LogInfo("%sabling Border Agent", mEnabled ? "En" : "Dis"); + UpdateState(); + +exit: + return; +} + +void BorderAgent::UpdateState(void) +{ + if (mEnabled && Get().IsAttached()) + { + Start(); + } + else + { + Stop(); + } +} + void BorderAgent::Start(void) { Error error = kErrorNone; @@ -168,16 +192,11 @@ void BorderAgent::HandleNotifierEvents(Events aEvents) { if (aEvents.Contains(kEventThreadRoleChanged)) { - if (Get().IsAttached()) - { - Start(); - } - else - { - Stop(); - } + UpdateState(); } + VerifyOrExit(mEnabled); + if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadExtPanIdChanged | kEventThreadNetworkNameChanged | kEventThreadBackboneRouterStateChanged | kEventActiveDatasetChanged)) { @@ -353,11 +372,19 @@ exit: FreeMessageOnError(message, error); } -void BorderAgent::HandleServiceTask(void) { mServiceChangedCallback.InvokeIfSet(); } +void BorderAgent::HandleServiceTask(void) +{ + VerifyOrExit(mEnabled); + + mServiceChangedCallback.InvokeIfSet(); + +exit: + return; +} void BorderAgent::PostServiceTask(void) { - if (mServiceChangedCallback.IsSet()) + if (mEnabled && mServiceChangedCallback.IsSet()) { mServiceTask.Post(); } diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp index 2df3e7287..7df6c5bcd 100644 --- a/src/core/meshcop/border_agent.hpp +++ b/src/core/meshcop/border_agent.hpp @@ -120,6 +120,38 @@ public: */ explicit BorderAgent(Instance &aInstance); + /** + * Enables or disables the Border Agent service. + * + * By default, the Border Agent service is enabled. This method allows us to explicitly control its state. This can + * be useful in scenarios such as: + * - The code wishes to delay the start of the Border Agent service (and its mDNS advertisement of the + * `_meshcop._udp` service on the infrastructure link). This allows time to prepare or determine vendor-specific + * TXT data entries for inclusion. + * - Unit tests or test scripts might disable the Border Agent service to prevent it from interfering with specific + * test steps. For example, tests validating mDNS or DNS-SD functionality may disable the Border Agent to prevent + * its registration of the MeshCoP service. + * + * @param[in] aEnabled Whether to enable or disable. + */ + void SetEnabled(bool aEnabled); + + /** + * Indicated whether or not the Border Agent is enabled. + * + * @retval TRUE The Border Agent is enabled. + * @retval FALSE The Border Agent is disabled. + */ + bool IsEnabled(void) const { return mEnabled; } + + /** + * Indicates whether the Border Agent service is enabled and running. + * + * @retval TRUE Border Agent service is running. + * @retval FALSE Border Agent service is not running. + */ + bool IsRunning(void) const { return mIsRunning; } + #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE /** * Represents a Border Agent Identifier. @@ -172,14 +204,6 @@ public: */ uint16_t GetUdpPort(void) const; - /** - * Indicates whether the Border Agent service is running. - * - * @retval TRUE Border Agent service is running. - * @retval FALSE Border Agent service is not running. - */ - bool IsRunning(void) const { return mIsRunning; } - /** * Sets the callback function used by the Border Agent to notify any changes on the MeshCoP service TXT values. * @@ -549,6 +573,7 @@ private: Appender mAppender; }; + void UpdateState(void); void Start(void); void Stop(void); void HandleNotifierEvents(Events aEvents); @@ -576,6 +601,7 @@ private: using ServiceTask = TaskletIn; + bool mEnabled; bool mIsRunning; Dtls::Transport mDtlsTransport; #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE diff --git a/tests/nexus/test_border_agent.cpp b/tests/nexus/test_border_agent.cpp index 569bec65e..ac90898d4 100644 --- a/tests/nexus/test_border_agent.cpp +++ b/tests/nexus/test_border_agent.cpp @@ -85,6 +85,18 @@ void TestBorderAgent(void) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log("Check Border Agent initial state"); + VerifyOrQuit(node0.Get().IsEnabled()); + VerifyOrQuit(node0.Get().IsRunning()); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Log("Check disabling and re-enabling of Border Agent"); + + node0.Get().SetEnabled(false); + VerifyOrQuit(!node0.Get().IsEnabled()); + VerifyOrQuit(!node0.Get().IsRunning()); + + node0.Get().SetEnabled(true); + VerifyOrQuit(node0.Get().IsEnabled()); VerifyOrQuit(node0.Get().IsRunning()); SuccessOrQuit(node0.Get().AddUnsecurePort(node0.Get().GetUdpPort()));