From 6e07db089893ade15f65aaa73021f1e4748af20d Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 8 Jul 2025 17:03:17 -0700 Subject: [PATCH] [mdns] introduce auto-enable mode (#11669) This commit introduces "auto-enable mode" in mDNS module. When this mode is enabled, the mDNS module uses the same infrastructure network interface as the Border Routing manager. The mDNS module is then automatically enabled or disabled based on the operational state of that interface. It is recommended to use the auto-enable mode on Border Routers. New APIs and CLI commands are added to manage this mode. This commit also makes the if-index argument optional in `mdns enable` CLI command. If an index is not provided, the command defaults to using the Border Router's infrastructure interface. This help simplify controlling the mDNS state in test scripts. --- include/openthread/instance.h | 2 +- include/openthread/mdns.h | 33 ++++++++++++++++ src/cli/cli_mdns.cpp | 29 +++++++++++++- src/core/api/mdns_api.cpp | 12 ++++++ src/core/border_router/infra_if.cpp | 2 +- src/core/net/mdns.cpp | 52 ++++++++++++++++++++++--- src/core/net/mdns.hpp | 59 ++++++++++++++++++++++++----- 7 files changed, 170 insertions(+), 19 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 545cd4a73..eae1d96ea 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 (516) +#define OPENTHREAD_API_VERSION (517) /** * @addtogroup api-instance diff --git a/include/openthread/mdns.h b/include/openthread/mdns.h index c2c2d9b21..481bf20fb 100644 --- a/include/openthread/mdns.h +++ b/include/openthread/mdns.h @@ -184,6 +184,39 @@ otError otMdnsSetEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfI */ bool otMdnsIsEnabled(otInstance *aInstance); +/** + * Enables or disables the mDNS auto-enable mode. + * + * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`. + * + * When this mode is enabled, the mDNS module uses the same infrastructure network interface as the Border Routing + * manager. The mDNS module is then automatically enabled or disabled based on the operational state of that interface + * (see `otBorderRoutingInit()` and `otPlatInfraIfStateChanged()`). + * + * It is recommended to use the auto-enable mode on Border Routers. The default state of this mode at initialization + * is controlled by the `OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF` configuration. + * + * The auto-enable mode can be disabled by a call to `otMdnsSetAutoEnableMode(false)` or by an explicit call to + * `otMdnsSetEnabled()`. Deactivating the auto-enable mode with `otMdnsSetAutoEnableMode(false)` will not change the + * current operational state of the mDNS module (e.g., if it is currently enabled, it remains enabled). + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aEnable A boolean to enable or disable the auto-enable mode. + */ +void otMdnsSetAutoEnableMode(otInstance *aInstance, bool aEnable); + +/** + * Indicates whether the auto-enable mode is enabled or disabled. + * + * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`. + * + * @param[in] aInstance The OpenThread instance. + * + * @retval TRUE The auto-enable mode is enabled. + * @retval FALSE The auto-enable mode is disabled. + */ +bool otMdnsGetAutoEnableMode(otInstance *aInstance); + /** * Sets whether the mDNS module is allowed to send questions requesting unicast responses referred to as "QU" questions. * diff --git a/src/cli/cli_mdns.cpp b/src/cli/cli_mdns.cpp index 32b7399b2..df56bcd46 100644 --- a/src/cli/cli_mdns.cpp +++ b/src/cli/cli_mdns.cpp @@ -48,8 +48,23 @@ template <> otError Mdns::Process(Arg aArgs[]) otError error; uint32_t infraIfIndex; - SuccessOrExit(error = aArgs[0].ParseAsUint32(infraIfIndex)); - VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS); +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + if (aArgs[0].IsEmpty()) + { + bool isRunning; + + // If no if-index is provided, we use the Border Router's + // infrastructure if-index (if any). + + SuccessOrExit(error = otBorderRoutingGetInfraIfInfo(GetInstancePtr(), &infraIfIndex, &isRunning)); + VerifyOrExit(isRunning, error = OT_ERROR_INVALID_STATE); + } + else +#endif + { + SuccessOrExit(error = aArgs[0].ParseAsUint32(infraIfIndex)); + VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + } SuccessOrExit(error = otMdnsSetEnabled(GetInstancePtr(), true, infraIfIndex)); @@ -81,6 +96,13 @@ exit: return error; } +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +template <> otError Mdns::Process(Arg aArgs[]) +{ + return ProcessEnableDisable(aArgs, otMdnsGetAutoEnableMode, otMdnsSetAutoEnableMode); +} +#endif + template <> otError Mdns::Process(Arg aArgs[]) { return ProcessEnableDisable(aArgs, otMdnsIsQuestionUnicastAllowed, otMdnsSetQuestionUnicastAllowed); @@ -1241,6 +1263,9 @@ otError Mdns::Process(Arg aArgs[]) } static constexpr Command kCommands[] = { +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + CmdEntry("auto"), +#endif CmdEntry("browser"), #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE CmdEntry("browsers"), diff --git a/src/core/api/mdns_api.cpp b/src/core/api/mdns_api.cpp index 1df04df0b..6a44b2826 100644 --- a/src/core/api/mdns_api.cpp +++ b/src/core/api/mdns_api.cpp @@ -46,6 +46,18 @@ otError otMdnsSetEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfI bool otMdnsIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsEnabled(); } +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +void otMdnsSetAutoEnableMode(otInstance *aInstance, bool aEnable) +{ + AsCoreType(aInstance).Get().SetAutoEnableMode(aEnable); +} + +bool otMdnsGetAutoEnableMode(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().GetAutoEnableMode(); +} +#endif + void otMdnsSetQuestionUnicastAllowed(otInstance *aInstance, bool aAllow) { AsCoreType(aInstance).Get().SetQuestionUnicastAllowed(aAllow); diff --git a/src/core/border_router/infra_if.cpp b/src/core/border_router/infra_if.cpp index 7ad4fb331..c01751c79 100644 --- a/src/core/border_router/infra_if.cpp +++ b/src/core/border_router/infra_if.cpp @@ -164,7 +164,7 @@ Error InfraIf::HandleStateChanged(uint32_t aIfIndex, bool aIsRunning) Get().HandleInfraIfStateChanged(); #endif -#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF +#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE Get().HandleInfraIfStateChanged(); #endif diff --git a/src/core/net/mdns.cpp b/src/core/net/mdns.cpp index e5973072b..10b286d9b 100644 --- a/src/core/net/mdns.cpp +++ b/src/core/net/mdns.cpp @@ -80,6 +80,7 @@ const char Core::kServicesDnssdLabels[] = "_services._dns-sd._udp"; Core::Core(Instance &aInstance) : InstanceLocator(aInstance) , mIsEnabled(false) + , mAutoEnable(kDefaultAutoEnable) , mIsQuestionUnicastAllowed(kDefaultQuAllowed) , mMaxMessageSize(kMaxMessageSize) , mInfraIfIndex(0) @@ -109,10 +110,15 @@ void Core::AfterInstanceInit(void) mLocalHost.GenerateName(); } -Error Core::SetEnabled(bool aEnable, uint32_t aInfraIfIndex) +Error Core::SetEnabled(bool aEnable, uint32_t aInfraIfIndex, Requester aRequester) { Error error = kErrorNone; + if (aRequester == kRequesterUser) + { + mAutoEnable = false; + } + VerifyOrExit(aEnable != mIsEnabled, error = kErrorAlready); mIsEnabled = aEnable; @@ -122,11 +128,12 @@ Error Core::SetEnabled(bool aEnable, uint32_t aInfraIfIndex) if (mIsEnabled) { - LogInfo("Enabling on infra-if-index %lu", ToUlong(mInfraIfIndex)); + LogInfo("%snabling on infra-if-index %lu", (aRequester == kRequesterAuto) ? "Auto-e" : "E", + ToUlong(mInfraIfIndex)); } else { - LogInfo("Disabling"); + LogInfo("%sisabling", (aRequester == kRequesterAuto) ? "Auto-d" : "D"); mLocalHost.ClearAddresses(); mHostEntries.Clear(); @@ -151,12 +158,45 @@ exit: return error; } -#if OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + +void Core::SetAutoEnableMode(bool aEnable) +{ + VerifyOrExit(mAutoEnable != aEnable); + + mAutoEnable = aEnable; + + if (mAutoEnable) + { + if (!Get().IsRunning()) + { + IgnoreError(SetEnabled(false, mInfraIfIndex, kRequesterAuto)); + ExitNow(); + } + + if (IsEnabled()) + { + VerifyOrExit(Get().GetIfIndex() != mInfraIfIndex); + IgnoreError(SetEnabled(false, mInfraIfIndex, kRequesterAuto)); + } + + IgnoreError(SetEnabled(true, Get().GetIfIndex(), kRequesterAuto)); + } + +exit: + return; +} + void Core::HandleInfraIfStateChanged(void) { - IgnoreError(SetEnabled(Get().IsRunning(), Get().GetIfIndex())); + VerifyOrExit(mAutoEnable); + IgnoreError(SetEnabled(Get().IsRunning(), Get().GetIfIndex(), + kRequesterAuto)); +exit: + return; } -#endif + +#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE template Error Core::Register(const ItemInfo &aItemInfo, RequestId aRequestId, RegisterCallback aCallback) diff --git a/src/core/net/mdns.hpp b/src/core/net/mdns.hpp index def39fa30..2b574a9f3 100644 --- a/src/core/net/mdns.hpp +++ b/src/core/net/mdns.hpp @@ -69,6 +69,11 @@ struct otMdnsIterator }; namespace ot { + +namespace BorderRouter { +class InfraIf; +} + namespace Dns { namespace Multicast { @@ -90,6 +95,7 @@ extern "C" void otPlatMdnsHandleHostAddressRemoveAll(otInstance *aInstance, uint class Core : public InstanceLocator, private NonCopyable { friend class ot::Instance; + friend class ot::BorderRouter::InfraIf; friend void otPlatMdnsHandleReceive(otInstance *aInstance, otMessage *aMessage, @@ -172,7 +178,10 @@ public: * @retval kErrorAlready mDNS is already enabled on an enable request, or is already disabled on a disable request. * @retval kErrorFailed Failed to enable/disable mDNS. */ - Error SetEnabled(bool aEnable, uint32_t aInfraIfIndex); + Error SetEnabled(bool aEnable, uint32_t aInfraIfIndex) + { + return SetEnabled(aEnable, aInfraIfIndex, kRequesterUser); + } /** * Indicates whether or not mDNS module is enabled. @@ -182,6 +191,35 @@ public: */ bool IsEnabled(void) const { return mIsEnabled; } +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + /** + * Enables or disables the mDNS auto-enable mode. + * + * When this mode is enabled, the mDNS module uses the same infrastructure network interface as the Border Routing + * manager. The mDNS module is then automatically enabled or disabled based on the operational state of that + * interface. + * + * It is recommended to use the auto-enable mode on Border Routers. The default state of this mode at + * initialization is controlled by the `OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF` configuration. + * + * The auto-enable mode can be disabled by a call to `SetAutoEnableMode(false)` or by an explicit call to + * `SetEnabled()`. Deactivating the auto-enable mode with `SetAutoEnableMode(false)` will not change the current + * operational state of the mDNS module (e.g., if it is currently enabled, it remains enabled). + * + * @param[in] aEnable A boolean to enable or disable the auto-enable mode. + */ + void SetAutoEnableMode(bool aEnable); + + /** + * Indicates whether the auto-enable mode is enabled or disabled. + * + * @retval TRUE The auto-enable mode is enabled. + * @retval FALSE The auto-enable mode is disabled. + */ + bool GetAutoEnableMode(void) const { return mAutoEnable; } + +#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + /** * Gets the local host name. * @@ -202,13 +240,6 @@ public: */ Error SetLocalHostName(const char *aName) { return mLocalHost.SetName(aName); } -#if OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF - /** - * Notifies `AdvertisingProxy` that `InfraIf` state changed. - */ - void HandleInfraIfStateChanged(void); -#endif - /** * Sets whether mDNS module is allowed to send questions requesting unicast responses referred to as "QU" questions. * @@ -815,7 +846,8 @@ private: static constexpr uint16_t kUdpPort = 5353; - static constexpr bool kDefaultQuAllowed = OPENTHREAD_CONFIG_MULTICAST_DNS_DEFAULT_QUESTION_UNICAST_ALLOWED; + static constexpr bool kDefaultAutoEnable = OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF; + static constexpr bool kDefaultQuAllowed = OPENTHREAD_CONFIG_MULTICAST_DNS_DEFAULT_QUESTION_UNICAST_ALLOWED; static constexpr uint32_t kMaxMessageSize = 1200; @@ -855,6 +887,12 @@ private: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + enum Requester : uint8_t // Used by `SetEnabled()`. + { + kRequesterUser, + kRequesterAuto, + }; + enum Section : uint8_t { kQuestionSection, @@ -2229,6 +2267,8 @@ private: Error Stop(const BrowserResolverType &aBrowserOrResolver); void AfterInstanceInit(void); + Error SetEnabled(bool aEnable, uint32_t aInfraIfIndex, Requester aRequester); + void HandleInfraIfStateChanged(void); void HandleHostAddressEvent(const Ip6::Address &aAddress, bool aAdded, uint32_t aInfraIfIndex); void HandleHostAddressRemoveAll(uint32_t aInfraIfIndex); void InvokeConflictCallback(const char *aName, const char *aServiceType); @@ -2266,6 +2306,7 @@ private: static const char kServicesDnssdLabels[]; // "_services._dns-sd._udp" bool mIsEnabled; + bool mAutoEnable; bool mIsQuestionUnicastAllowed; uint16_t mMaxMessageSize; uint32_t mInfraIfIndex;