From 2388bc2264e14b6d1dd23cd98ecd06fdca6e2413 Mon Sep 17 00:00:00 2001 From: Li Cao Date: Wed, 25 Sep 2024 23:18:16 +0800 Subject: [PATCH] [ncp] extend border routing InfraIf setup for state synchronization (#10749) The commit extends `SPINEL_PROP_INFRA_IF_SETUP` to `SPINEL_PROP_INFRA_IF_STATE` so that it can be used to either do infra if setup (trigger border routing starting on NCP) or synchronize infra if state to the NCP (ON/OFF state, IP addresses). The current implementation on NCP will compare the `InfraIfIndex`. If the index is different the value on NCP, it will be regarded as an initialization or change of InfraIf. Thus the border routing module will be re-initialized. --- src/lib/spinel/spinel.h | 11 +++++--- src/ncp/ncp_base_dispatcher.cpp | 2 +- src/ncp/ncp_base_ftd.cpp | 23 +++++++++++----- tests/unit/test_ncp_infra_if.cpp | 45 +++++++++++++++++++++++++++++--- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 2a3a8a76a..140787e4a 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -4729,15 +4729,20 @@ enum SPINEL_PROP_INFRA_IF__BEGIN = 0x910, - /// Infrastructure interface setup. + /// Infrastructure interface state. /** Format: `LbA(6)` * Type: Write * * `L`: The infrastructure interface index. - * `b`: If the infrastrue interface is running. + * `b`: If the infrastructure interface is running. * `A(6)`: The IPv6 addresses of the infrastructure interface. + * + * If the InfraIf hasn't been set up on NCP or the InfraIf changes, NCP will re-initialize + * the border routing module. NCP will compare the infrastructure interface index and decide + * whether to re-initialize the border routing module. Otherwise, NCP will simply update the + * InfraIf state and addresses. */ - SPINEL_PROP_INFRA_IF_SETUP = SPINEL_PROP_INFRA_IF__BEGIN + 1, + SPINEL_PROP_INFRA_IF_STATE = SPINEL_PROP_INFRA_IF__BEGIN + 1, SPINEL_PROP_INFRA_IF__END = 0x920, diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index fe11d7fc5..622ca469c 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -513,7 +513,7 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE), #endif #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE - OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_INFRA_IF_SETUP), + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_INFRA_IF_STATE), #endif #if OPENTHREAD_MTD || OPENTHREAD_FTD OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER), diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index 866ae0098..b7fb9edce 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -1404,12 +1404,13 @@ exit: #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE #if OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE -template <> otError NcpBase::HandlePropertySet(void) +template <> otError NcpBase::HandlePropertySet(void) { - otError error = OT_ERROR_NONE; - bool isInfraRunning; + otError error = OT_ERROR_NONE; + uint32_t infraIfIndex; + bool isInfraRunning; - SuccessOrExit(error = mDecoder.ReadUint32(mInfraIfIndex)); + SuccessOrExit(error = mDecoder.ReadUint32(infraIfIndex)); SuccessOrExit(error = mDecoder.ReadBool(isInfraRunning)); mInfraIfAddrCount = 0; @@ -1421,9 +1422,17 @@ template <> otError NcpBase::HandlePropertySet(void) SuccessOrExit(error = InfraIfAddAddress(*addr)); } - IgnoreError(otBorderRoutingSetEnabled(mInstance, /* aEnabled */ false)); - SuccessOrExit(error = otBorderRoutingInit(mInstance, mInfraIfIndex, isInfraRunning)); - SuccessOrExit(error = otBorderRoutingSetEnabled(mInstance, /* aEnabled */ true)); + if (infraIfIndex != mInfraIfIndex) + { + mInfraIfIndex = infraIfIndex; + IgnoreError(otBorderRoutingSetEnabled(mInstance, /* aEnabled */ false)); + SuccessOrExit(error = otBorderRoutingInit(mInstance, mInfraIfIndex, isInfraRunning)); + SuccessOrExit(error = otBorderRoutingSetEnabled(mInstance, /* aEnabled */ true)); + } + else + { + SuccessOrExit(error = otPlatInfraIfStateChanged(mInstance, mInfraIfIndex, isInfraRunning)); + } exit: return error; diff --git a/tests/unit/test_ncp_infra_if.cpp b/tests/unit/test_ncp_infra_if.cpp index 692ef3f50..a5ad36cc3 100644 --- a/tests/unit/test_ncp_infra_if.cpp +++ b/tests/unit/test_ncp_infra_if.cpp @@ -44,7 +44,7 @@ namespace ot { constexpr uint16_t kMaxSpinelBufferSize = 2048; -static otError GenerateSpinelInfraIfSetUpFrame(uint32_t akInfraIfIndex, +static otError GenerateSpinelInfraIfStateFrame(uint32_t akInfraIfIndex, bool aIsRunning, const otIp6Address *aAddrs, uint8_t aAddrCount, @@ -57,7 +57,7 @@ static otError GenerateSpinelInfraIfSetUpFrame(uint32_t akInfraIfInde 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_INFRA_IF_SETUP)); + SuccessOrExit(error = encoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_INFRA_IF_STATE)); SuccessOrExit(error = encoder.WriteUint32(akInfraIfIndex)); SuccessOrExit(error = encoder.WriteBool(true)); for (uint8_t i = 0; i < aAddrCount; i++) @@ -89,7 +89,7 @@ void TestNcpInfraIfSetUp(void) VerifyOrQuit(otBorderRoutingGetState(instance) == OT_BORDER_ROUTING_STATE_UNINITIALIZED); - SuccessOrQuit(GenerateSpinelInfraIfSetUpFrame(kInfraIfIndex, true /* IsRunning */, infraIfAddresses, + SuccessOrQuit(GenerateSpinelInfraIfStateFrame(kInfraIfIndex, true /* IsRunning */, infraIfAddresses, sizeof(infraIfAddresses) / sizeof(infraIfAddresses[0]), recvBuf, recvLen)); ncpBase.HandleReceive(recvBuf, recvLen); @@ -98,7 +98,7 @@ void TestNcpInfraIfSetUp(void) VerifyOrQuit(!otPlatInfraIfHasAddress(kInfraIfIndex + 100, &infraIfAddresses[0])); SuccessOrQuit( - GenerateSpinelInfraIfSetUpFrame(kInfraIfIndex, true /* IsRunning */, infraIfAddresses, 0, recvBuf, recvLen)); + GenerateSpinelInfraIfStateFrame(kInfraIfIndex, true /* IsRunning */, infraIfAddresses, 0, recvBuf, recvLen)); ncpBase.HandleReceive(recvBuf, recvLen); VerifyOrQuit(otBorderRoutingGetState(instance) == OT_BORDER_ROUTING_STATE_STOPPED); VerifyOrQuit(!otPlatInfraIfHasAddress(kInfraIfIndex, &infraIfAddresses[0])); @@ -106,6 +106,42 @@ void TestNcpInfraIfSetUp(void) printf("Test Ncp Infra If SetUp passed.\n"); } +void TestNcpInfraIfUpdate(void) +{ + Instance *instance = static_cast(testInitInstance()); + Ncp::NcpBase ncpBase(instance); + + uint8_t recvBuf[kMaxSpinelBufferSize]; + uint16_t recvLen; + constexpr uint32_t kInfraIfIndex1 = 1; + constexpr uint32_t kInfraIfIndex2 = 2; + + const otIp6Address infraIfAddresses[] = { + {0xfd, 0x35, 0x7a, 0x7d, 0x0f, 0x16, 0xe7, 0xe3, 0xc9, 0x79, 0x59, 0x29, 0xc8, 0xc2, 0xa3, 0x7b}, + {0xfd, 0x35, 0x7a, 0x7d, 0x0f, 0x16, 0xe7, 0xe3, 0x7b, 0xa3, 0xc2, 0xc8, 0x29, 0x59, 0x79, 0xc9}, + }; + + SuccessOrQuit( + GenerateSpinelInfraIfStateFrame(kInfraIfIndex1, true /* IsRunning */, infraIfAddresses, 1, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + VerifyOrQuit(otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[0])); + VerifyOrQuit(!otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[1])); + + SuccessOrQuit( + GenerateSpinelInfraIfStateFrame(kInfraIfIndex1, true /* IsRunning */, infraIfAddresses, 2, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + VerifyOrQuit(otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[0])); + VerifyOrQuit(otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[1])); + + SuccessOrQuit( + GenerateSpinelInfraIfStateFrame(kInfraIfIndex2, true /* IsRunning */, infraIfAddresses, 2, recvBuf, recvLen)); + ncpBase.HandleReceive(recvBuf, recvLen); + VerifyOrQuit(!otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[0])); + VerifyOrQuit(!otPlatInfraIfHasAddress(kInfraIfIndex1, &infraIfAddresses[1])); + VerifyOrQuit(otPlatInfraIfHasAddress(kInfraIfIndex2, &infraIfAddresses[0])); + VerifyOrQuit(otPlatInfraIfHasAddress(kInfraIfIndex2, &infraIfAddresses[1])); +} + } // namespace ot #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE @@ -114,6 +150,7 @@ int main(void) { #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NCP_INFRA_IF_ENABLE ot::TestNcpInfraIfSetUp(); + ot::TestNcpInfraIfUpdate(); #endif printf("All tests passed\n"); return 0;