From 56b8fc08621cdf19cfc847e80382c6c5a2f32337 Mon Sep 17 00:00:00 2001 From: Li Cao Date: Thu, 20 Mar 2025 21:28:05 +0800 Subject: [PATCH] [ncp] implement backbone router multicast forwarding (#11350) This commit adds a few NCP properties for Backbone Router multicast forwarding to work in NCP design. --- src/lib/spinel/spinel.c | 3 ++ src/lib/spinel/spinel.h | 34 +++++++++++++++++++ src/ncp/changed_props_set.cpp | 3 +- src/ncp/ncp_base.hpp | 9 +++++ src/ncp/ncp_base_dispatcher.cpp | 6 ++++ src/ncp/ncp_base_ftd.cpp | 58 +++++++++++++++++++++++++++++++++ src/ncp/ncp_base_mtd.cpp | 1 + 7 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index 35988d4b1..ba23b8947 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -1419,6 +1419,9 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_DNSSD_SERVICE, "DNSSD_SERVICE"}, {SPINEL_PROP_DNSSD_KEY_RECORD, "DNSSD_KEY_RECORD"}, {SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE, "BORDER_AGENT_MESHCOP_SERVICE_STATE"}, + {SPINEL_PROP_BACKBONE_ROUTER_STATE, "BACKBONE_ROUTER_STATE"}, + {SPINEL_PROP_BACKBONE_ROUTER_ENABLE, "BACKBONE_ROUTER_ENABLE"}, + {SPINEL_PROP_BACKBONE_ROUTER_MULTICAST_LISTENER, "BACKBONE_ROUTER_MULTICAST_LISTENER"}, {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 667437bd8..355eb627f 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -4898,6 +4898,40 @@ enum SPINEL_PROP_BORDER_AGENT__END = 0x970, + SPINEL_PROP_BACKBONE_ROUTER__BEGIN = 0x970, + + /// Backbone Router State + /** + * Format: `C` - Unsolicited notifications only + * + * `C`: The Backbone Router state. The value is the same as `otBackboneRouterState`. + * + * This property is used to notify the host the state of the Backbone Router. + */ + SPINEL_PROP_BACKBONE_ROUTER_STATE = SPINEL_PROP_BACKBONE_ROUTER__BEGIN + 1, + + /// Enablement/Disablement of Backbone Router function. + /** + * Format: `b` - Write-Only + * + * `b`: Whether to enable or disable the Backbone Router function. + * + * Host uses this property to enable or disable the Backbone Router function on NCP. + */ + SPINEL_PROP_BACKBONE_ROUTER_ENABLE = SPINEL_PROP_BACKBONE_ROUTER__BEGIN + 2, + + /// BackBone Router Multicast Listener. + /** + * Format: `6` - Inserted/Removed + * + * `6`: The multicast address that is subscribed by a multicast listener. + * + * NCP uses this property to subscribe or unsubscribe a multicast listener on the host. + */ + SPINEL_PROP_BACKBONE_ROUTER_MULTICAST_LISTENER = SPINEL_PROP_BACKBONE_ROUTER__BEGIN + 3, + + SPINEL_PROP_BACKBONE_ROUTER__END = 0x990, + SPINEL_PROP_NEST__BEGIN = 0x3BC0, SPINEL_PROP_NEST_STREAM_MFG = SPINEL_PROP_NEST__BEGIN + 0, diff --git a/src/ncp/changed_props_set.cpp b/src/ncp/changed_props_set.cpp index 6706c8362..124d7d35f 100644 --- a/src/ncp/changed_props_set.cpp +++ b/src/ncp/changed_props_set.cpp @@ -94,8 +94,9 @@ const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = { {SPINEL_PROP_PARENT_RESPONSE_INFO, SPINEL_STATUS_OK, true}, {SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET_TLVS, SPINEL_STATUS_OK, false}, #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE - {SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE, SPINEL_STATUS_OK, false} + {SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE, SPINEL_STATUS_OK, false}, #endif + {SPINEL_PROP_BACKBONE_ROUTER_STATE, SPINEL_STATUS_OK, false}, }; uint8_t ChangedPropsSet::GetNumEntries(void) const diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 2e9ec3e89..8da1bfb42 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -878,6 +878,15 @@ protected: otPlatDnssdState mDnssdState; #endif // OPENTHREAD_CONFIG_NCP_DNSSD_ENABLE && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE + +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE && OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE + static void HandleBackboneRouterMulticastListenerEvent(void *aContext, + otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address *aAddress); + void HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address *aAddress); +#endif + #endif // OPENTHREAD_FTD #if OPENTHREAD_CONFIG_DIAG_ENABLE diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 2e72d04b8..1cadfb6f5 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -230,6 +230,9 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_BORDER_AGENT_MESHCOP_SERVICE_STATE), #endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_BACKBONE_ROUTER_STATE), +#endif #endif OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_LIST), @@ -543,6 +546,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_DNSSD_STATE), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_DNSSD_REQUEST_RESULT), #endif +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_BACKBONE_ROUTER_ENABLE), +#endif #endif // OPENTHREAD_FTD #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 f3435989e..9996ebdfb 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -1666,6 +1666,64 @@ exit: #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +template <> otError NcpBase::HandlePropertyGet(void) +{ + otBackboneRouterState state = otBackboneRouterGetState(mInstance); + + return mEncoder.WriteUint8(static_cast(state)); +} + +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + bool enable; + + SuccessOrExit(error = mDecoder.ReadBool(enable)); + +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE + if (enable) + { + otBackboneRouterSetMulticastListenerCallback(mInstance, HandleBackboneRouterMulticastListenerEvent, this); + } + else + { + otBackboneRouterSetMulticastListenerCallback(mInstance, nullptr, nullptr); + } +#endif + otBackboneRouterSetEnabled(mInstance, enable); + +exit: + return error; +} + +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE +void NcpBase::HandleBackboneRouterMulticastListenerEvent(void *aContext, + otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address *aAddress) +{ + static_cast(aContext)->HandleBackboneRouterMulticastListenerEvent(aEvent, aAddress); +} + +void NcpBase::HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address *aAddress) +{ + uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID; + spinel_command_t cmd = aEvent == OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED ? SPINEL_CMD_PROP_VALUE_INSERTED + : SPINEL_CMD_PROP_VALUE_REMOVED; + VerifyOrExit(aAddress != nullptr); + + SuccessOrExit(mEncoder.BeginFrame(header, cmd)); + SuccessOrExit(mEncoder.WriteUintPacked(SPINEL_PROP_BACKBONE_ROUTER_MULTICAST_LISTENER)); + SuccessOrExit(mEncoder.WriteIp6Address(*aAddress)); + SuccessOrExit(mEncoder.EndFrame()); + +exit: + return; +} +#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE +#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + } // namespace Ncp } // namespace ot diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 0fbaf7574..f2ae0f1f9 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -4709,6 +4709,7 @@ void NcpBase::ProcessThreadChangedFlags(void) {OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC}, {OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL}, {OT_CHANGED_SUPPORTED_CHANNEL_MASK, SPINEL_PROP_PHY_CHAN_SUPPORTED}, + {OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE, SPINEL_PROP_BACKBONE_ROUTER_STATE}, }; VerifyOrExit(mThreadChangedFlags != 0);