diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 1a44f534e..5313febfb 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -79,7 +79,7 @@ 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 + 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 - name: Test Simulation run: cd build/simulation && ninja test - name: Build Multipan Simulation diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index 230aafa89..60e4f0c59 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -1410,6 +1410,8 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_RCP_ENH_ACK_PROBING, "ENH_ACK_PROBING"}, {SPINEL_PROP_RCP_CSL_ACCURACY, "CSL_ACCURACY"}, {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_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 d6ae7159a..4f914c61a 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -4775,6 +4775,26 @@ enum SPINEL_PROP_INFRA_IF__END = 0x920, + SPINEL_PROP_SRP_SERVER__BEGIN = 0x920, + + /// SRP server state. + /** Format `b` + * Type: Read-Write + * + * `b`: Whether to enable or disable the SRP server. + */ + SPINEL_PROP_SRP_SERVER_ENABLED = SPINEL_PROP_SRP_SERVER__BEGIN + 1, + + /// SRP server auto enable mode. + /** Format `b` + * Type: Read-Write + * + * `b`: A boolean that indicates the SRP server auto enable mode. + */ + SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE = SPINEL_PROP_SRP_SERVER__BEGIN + 2, + + SPINEL_PROP_SRP_SERVER__END = 0x930, + SPINEL_PROP_NEST__BEGIN = 0x3BC0, SPINEL_PROP_NEST_STREAM_MFG = SPINEL_PROP_NEST__BEGIN + 0, diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index f6567e17a..a1884e3c2 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -222,6 +222,12 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE), #endif #if OPENTHREAD_MTD || OPENTHREAD_FTD +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_SERVER_ENABLED), +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE), +#endif +#endif OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_LIST), #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE @@ -519,6 +525,12 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) 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 + 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_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 41c1be77c..d588a48d1 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -1508,6 +1508,62 @@ exit: #endif // OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + bool enable; + + SuccessOrExit(error = mDecoder.ReadBool(enable)); + otSrpServerSetEnabled(mInstance, enable); + +exit: + return error; +} + +template <> otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0; + otSrpServerState srpServerState = otSrpServerGetState(mInstance); + + SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_SRP_SERVER_ENABLED)); + SuccessOrExit(error = mEncoder.WriteBool(srpServerState != OT_SRP_SERVER_STATE_DISABLED)); + SuccessOrExit(error = mEncoder.EndFrame()); + +exit: + return error; +} + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + bool enable; + + SuccessOrExit(error = mDecoder.ReadBool(enable)); + otSrpServerSetAutoEnableMode(mInstance, enable); + +exit: + return error; +} + +template <> otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0; + + SuccessOrExit(error = + mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE)); + SuccessOrExit(error = mEncoder.WriteBool(otSrpServerIsAutoEnableMode(mInstance))); + SuccessOrExit(error = mEncoder.EndFrame()); + +exit: + return error; +} +#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + } // namespace Ncp } // namespace ot diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index dd4cdbdb0..87f9c4d3f 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -262,6 +262,7 @@ ot_unit_test(trickle_timer) ot_unit_test(url) ot_unit_ncp_test(infra_if) +ot_unit_ncp_test(srp_server) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/unit/test_ncp_srp_server.cpp b/tests/unit/test_ncp_srp_server.cpp new file mode 100644 index 000000000..ee0c720e4 --- /dev/null +++ b/tests/unit/test_ncp_srp_server.cpp @@ -0,0 +1,132 @@ +/* + * 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_SRP_SERVER_ENABLE + +namespace ot { + +constexpr uint16_t kMaxSpinelBufferSize = 2048; + +static otError GenerateSpinelSrpServerFrame(spinel_prop_key_t aProp, bool aEnable, 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, aProp)); + SuccessOrExit(error = encoder.WriteBool(aEnable)); + SuccessOrExit(error = encoder.EndFrame()); + + SuccessOrExit(ncpBuffer.OutFrameBegin()); + aLen = ncpBuffer.OutFrameGetLength(); + VerifyOrExit(ncpBuffer.OutFrameRead(aLen, aBuf) == aLen, error = OT_ERROR_FAILED); + +exit: + return error; +} + +void TestNcpSrpServerSetEnabled(void) +{ + Instance *instance = static_cast(testInitInstance()); + Ncp::NcpBase ncpBase(instance); + + uint8_t recvBuf[kMaxSpinelBufferSize]; + uint16_t recvLen; + otSrpServerState state; + + state = otSrpServerGetState(instance); + VerifyOrQuit(state == OT_SRP_SERVER_STATE_DISABLED); + + SuccessOrQuit(GenerateSpinelSrpServerFrame(SPINEL_PROP_SRP_SERVER_ENABLED, true, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + state = otSrpServerGetState(instance); + VerifyOrQuit(state == OT_SRP_SERVER_STATE_STOPPED); + + SuccessOrQuit(GenerateSpinelSrpServerFrame(SPINEL_PROP_SRP_SERVER_ENABLED, false, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + state = otSrpServerGetState(instance); + VerifyOrQuit(state == OT_SRP_SERVER_STATE_DISABLED); + + printf("TestNcpSrpServerSetEnabled passed.\n"); +} + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +void TestNcpSrpServerSetAutoEnableMode(void) +{ + Instance *instance = static_cast(testInitInstance()); + Ncp::NcpBase ncpBase(instance); + + uint8_t recvBuf[kMaxSpinelBufferSize]; + uint16_t recvLen; + bool isAutoEnableMode; + + isAutoEnableMode = otSrpServerIsAutoEnableMode(instance); + VerifyOrQuit(isAutoEnableMode == false); + + SuccessOrQuit(GenerateSpinelSrpServerFrame(SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE, true, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + isAutoEnableMode = otSrpServerIsAutoEnableMode(instance); + VerifyOrQuit(isAutoEnableMode == true); + + SuccessOrQuit(GenerateSpinelSrpServerFrame(SPINEL_PROP_SRP_SERVER_AUTO_ENABLE_MODE, false, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + isAutoEnableMode = otSrpServerIsAutoEnableMode(instance); + VerifyOrQuit(isAutoEnableMode == false); + + printf("TestNcpSrpServerSetAutoEnableMode passed.\n"); +} +#endif + +} // namespace ot + +#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + +int main(void) +{ +#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + ot::TestNcpSrpServerSetEnabled(); +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + ot::TestNcpSrpServerSetAutoEnableMode(); +#endif +#endif + printf("All tests passed\n"); + return 0; +}