From 8b3e51276b49c5b25333c9175176c59791e22b87 Mon Sep 17 00:00:00 2001 From: Li Cao Date: Sat, 2 Nov 2024 02:26:36 +0800 Subject: [PATCH] [ncp] implement ncp version of otPlatDnssd (#10882) This commit implements NCP based version of `otPlatDnssdGetState`. A unit test is added to verify the implementation. This commit also adjusts the unit test workflow to put the ncp unit tests into a separate item. The direct reason for this commit is that `otPlatDnssd` APIs haven't been implemented in `FakePlatform` and when `OT_PLATFORM_DNSSD` is turned, the build failed. Let's first run NCP unit tests separately and later try to merge the test items. --- .github/workflows/unit.yml | 7 ++- src/lib/spinel/spinel.c | 1 + src/lib/spinel/spinel.h | 11 ++++ src/ncp/ncp_base.cpp | 7 ++- src/ncp/ncp_base.hpp | 17 +++++- src/ncp/ncp_base_dispatcher.cpp | 9 +++- src/ncp/ncp_base_ftd.cpp | 23 ++++++++ src/ncp/platform/dnssd.cpp | 6 +-- tests/unit/CMakeLists.txt | 1 + tests/unit/test_ncp_dnssd.cpp | 95 +++++++++++++++++++++++++++++++++ 10 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 tests/unit/test_ncp_dnssd.cpp diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 5313febfb..0a6c78f34 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -79,13 +79,18 @@ jobs: sudo rm /etc/apt/sources.list.d/* && sudo apt-get update sudo apt-get --no-install-recommends install -y ninja-build lcov - name: Build Simulation - run: ./script/cmake-build simulation -DOT_BUILD_GTEST=ON -DOT_BORDER_ROUTING=ON -DOT_BORDER_ROUTING_DHCP6_PD=ON -DOT_NCP_INFRA_IF=ON -DOT_SRP_SERVER=ON + run: ./script/cmake-build simulation -DOT_BUILD_GTEST=ON -DOT_BORDER_ROUTING=ON -DOT_BORDER_ROUTING_DHCP6_PD=ON - name: Test Simulation run: cd build/simulation && ninja test - name: Build Multipan Simulation run: ./script/cmake-build simulation -DOT_BUILD_GTEST=ON -DOT_MULTIPAN_TEST=ON - name: Test Multipan Simulation run: cd build/simulation && ninja test + - name: Build NCP Simulation + run: ./script/cmake-build simulation -DOT_BUILD_GTEST=OFF -DOT_MTD=OFF -DOT_RCP=OFF -DOT_APP_CLI=OFF -DOT_APP_RCP=OFF \ + -DOT_BORDER_ROUTING=ON -DOT_NCP_INFRA_IF=ON -DOT_SRP_SERVER=ON -DOT_NCP_DNSSD=ON -DOT_PLATFORM_DNSSD=ON + - name: Test NCP Simulation + run: cd build/simulation && ninja test - name: Build POSIX run: ./script/cmake-build posix - name: Test POSIX diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index ae6fc6322..b5bc04fdd 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -1413,6 +1413,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_RCP_CSL_UNCERTAINTY, "CSL_UNCERTAINTY"}, {SPINEL_PROP_SRP_SERVER_ENABLED, "SPINEL_PROP_SRP_SERVER_ENABLED"}, {SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE, "SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE"}, + {SPINEL_PROP_DNSSD_STATE, "DNSSD_STATE"}, {SPINEL_PROP_PARENT_RESPONSE_INFO, "PARENT_RESPONSE_INFO"}, {SPINEL_PROP_SLAAC_ENABLED, "SLAAC_ENABLED"}, {SPINEL_PROP_SUPPORTED_RADIO_LINKS, "SUPPORTED_RADIO_LINKS"}, diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 526e57037..281f902bd 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -4785,6 +4785,17 @@ enum SPINEL_PROP_SRP_SERVER__BEGIN = 0x920, + SPINEL_PROP_DNSSD__BEGIN = 0x930, + + /// Dnssd State + /** Format `b`: Write-only + * + * `C`: The dnssd state. + */ + SPINEL_PROP_DNSSD_STATE = SPINEL_PROP_DNSSD__BEGIN + 1, + + SPINEL_PROP_DNSSD__END = 0x950, + /// SRP server state. /** Format `b` * Type: Read-Write diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 9307685d9..20b3d015a 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -317,10 +317,15 @@ NcpBase::NcpBase(Instance *aInstance) , mDidInitialUpdates(false) , mDatasetSendMgmtPendingSetResult(SPINEL_STATUS_OK) , mLogTimestampBase(0) -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE +#if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE , mInfraIfAddrCount(0) , mInfraIfIndex(0) #endif +#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + , mDnssdState(OT_PLAT_DNSSD_STOPPED) +#endif +#endif #if OPENTHREAD_CONFIG_DIAG_ENABLE , mDiagOutput(nullptr) , mDiagOutputLen(0) diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index f18e3a8df..a8e95b9ce 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -244,6 +244,15 @@ public: const uint8_t *aBuffer, uint16_t aBufferLength); +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + /** + * Gets the Dnssd state. + * + * Returns the platform dnssd state. + */ + otPlatDnssdState DnssdGetState(void); +#endif + protected: static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte. @@ -759,7 +768,8 @@ protected: uint64_t mLogTimestampBase; // Timestamp base used for logging -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE otError InfraIfAddAddress(const otIp6Address &aAddress); bool InfraIfContainsAddress(const otIp6Address &aAddress); @@ -769,6 +779,11 @@ protected: uint32_t mInfraIfIndex; #endif +#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + otPlatDnssdState mDnssdState; +#endif +#endif + #if OPENTHREAD_CONFIG_DIAG_ENABLE char *mDiagOutput; uint16_t mDiagOutputLen; diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 5b137e4d7..1dcb76027 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -524,16 +524,21 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) #if OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE), #endif -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_INFRA_IF_STATE), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_INFRA_IF_RECV_ICMP6), #endif -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_SRP_SERVER_ENABLE +#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_SERVER_ENABLED), #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE), #endif #endif +#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE && OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_DNSSD_STATE), +#endif +#endif // OPENTHREAD_FTD #if OPENTHREAD_MTD || OPENTHREAD_FTD OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER), #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index d588a48d1..a0db64948 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -1564,6 +1564,29 @@ exit: #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE +#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + +otPlatDnssdState NcpBase::DnssdGetState(void) { return mDnssdState; } + +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + uint8_t state; + + SuccessOrExit(error = mDecoder.ReadUint8(state)); + + if (state != mDnssdState) + { + mDnssdState = static_cast(state); + otPlatDnssdStateHandleStateChange(mInstance); + } + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + } // namespace Ncp } // namespace ot diff --git a/src/ncp/platform/dnssd.cpp b/src/ncp/platform/dnssd.cpp index 193e63375..2dbc39e8f 100644 --- a/src/ncp/platform/dnssd.cpp +++ b/src/ncp/platform/dnssd.cpp @@ -31,12 +31,12 @@ #include "ncp/ncp_base.hpp" -#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); - return OT_PLAT_DNSSD_STOPPED; + return ot::Ncp::NcpBase::GetNcpInstance()->DnssdGetState(); } void otPlatDnssdRegisterService(otInstance *aInstance, @@ -165,4 +165,4 @@ void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdA OT_UNUSED_VARIABLE(aResolver); } -#endif // OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 87f9c4d3f..70798603d 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -261,6 +261,7 @@ ot_unit_test(toolchain test_toolchain_c.c) ot_unit_test(trickle_timer) ot_unit_test(url) +ot_unit_ncp_test(dnssd) ot_unit_ncp_test(infra_if) ot_unit_ncp_test(srp_server) diff --git a/tests/unit/test_ncp_dnssd.cpp b/tests/unit/test_ncp_dnssd.cpp new file mode 100644 index 000000000..9c1c6e6d9 --- /dev/null +++ b/tests/unit/test_ncp_dnssd.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024, 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. + */ + +#include + +#include + +#include "test_platform.h" +#include "test_util.h" +#include "common/code_utils.hpp" +#include "lib/spinel/spinel_buffer.hpp" +#include "lib/spinel/spinel_encoder.hpp" +#include "ncp/ncp_base.hpp" + +#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + +namespace ot { + +constexpr uint16_t kMaxSpinelBufferSize = 2048; + +static otError GenerateSpinelDnssdSetStateFrame(otPlatDnssdState aState, uint8_t *aBuf, uint16_t &aLen) +{ + otError error = OT_ERROR_NONE; + uint8_t buf[kMaxSpinelBufferSize]; + Spinel::Buffer ncpBuffer(buf, kMaxSpinelBufferSize); + Spinel::Encoder encoder(ncpBuffer); + + uint8_t header = SPINEL_HEADER_FLAG | 0 /* Iid */ | 1 /* Tid */; + SuccessOrExit(error = encoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_DNSSD_STATE)); + SuccessOrExit(error = encoder.WriteUint8(aState)); + SuccessOrExit(error = encoder.EndFrame()); + + SuccessOrExit(ncpBuffer.OutFrameBegin()); + aLen = ncpBuffer.OutFrameGetLength(); + VerifyOrExit(ncpBuffer.OutFrameRead(aLen, aBuf) == aLen, error = OT_ERROR_FAILED); + +exit: + return error; +} + +void TestNcpDnssdGetState(void) +{ + Instance *instance = static_cast(testInitInstance()); + Ncp::NcpBase ncpBase(instance); + + uint8_t recvBuf[kMaxSpinelBufferSize]; + uint16_t recvLen; + otPlatDnssdState dnssdState; + + dnssdState = otPlatDnssdGetState(instance); + VerifyOrQuit(dnssdState == OT_PLAT_DNSSD_STOPPED); + + SuccessOrQuit(GenerateSpinelDnssdSetStateFrame(OT_PLAT_DNSSD_READY, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + dnssdState = otPlatDnssdGetState(instance); + VerifyOrQuit(dnssdState == OT_PLAT_DNSSD_READY); +} + +} // namespace ot + +#endif // OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + +int main(void) +{ +#if OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + ot::TestNcpDnssdGetState(); +#endif + printf("All tests passed\n"); + return 0; +}