From 54d10720f62be8d28b912c732f8fa2010cb3c0ce Mon Sep 17 00:00:00 2001 From: Li Cao Date: Tue, 6 Aug 2024 06:09:52 +0800 Subject: [PATCH] [spinel] add spinel property to get/set dataset in raw TLVs (#10569) This commit adds two new spinel properties: `SPINEL_PROP_THREAD_ACTIVE_DATASET_TLVS` and `SPINEL_PROP_THREAD_PENDING_DATASET_TLVS`, as well as the get/set property handler on NCP side. Currently we can only transport dataset through spinel with fixed format. Using Tlvs allows us to append TLVs are not defined in the current Thread Specification. --- src/lib/spinel/spinel.h | 24 ++++++++++++++ src/ncp/ncp_base_dispatcher.cpp | 4 +++ src/ncp/ncp_base_mtd.cpp | 58 +++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 9941dba75..d04743dcb 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -3388,6 +3388,30 @@ enum */ SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER = SPINEL_PROP_THREAD_EXT__BEGIN + 59, + /// Thread Active Operational Dataset in raw TLVs format. + /** Format: `D` - Read-Write + * + * This property provides access to the current Thread Active Operational Dataset. A Thread device maintains the + * Operational Dataset that it has stored locally and the one currently in use by the partition to which it is + * attached. This property corresponds to the locally stored Dataset on the device. + * + * On write, any unknown/unsupported TLVs must be ignored. + * + */ + SPINEL_PROP_THREAD_ACTIVE_DATASET_TLVS = SPINEL_PROP_THREAD_EXT__BEGIN + 60, + + /// Thread Pending Operational Dataset in raw TLVs format. + /** Format: `D` - Read-Write + * + * This property provides access to the current locally stored Pending Operational Dataset. + * + * The formatting of this property follows the same rules as in SPINEL_PROP_THREAD_ACTIVE_DATASET_TLVS. + * + * On write, any unknown/unsupported TLVs must be ignored. + * + */ + SPINEL_PROP_THREAD_PENDING_DATASET_TLVS = SPINEL_PROP_THREAD_EXT__BEGIN + 61, + SPINEL_PROP_THREAD_EXT__END = 0x1600, SPINEL_PROP_IPV6__BEGIN = 0x60, diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 167b7348a..5d2362b0c 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -334,6 +334,8 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER), #endif + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_ACTIVE_DATASET_TLVS), + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_PENDING_DATASET_TLVS), #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CHANNEL_MANAGER_DELAY), @@ -603,6 +605,8 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER), #endif + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_ACTIVE_DATASET_TLVS), + OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_PENDING_DATASET_TLVS), #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN), diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 07047217f..fe15134c7 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -1370,6 +1370,30 @@ template <> otError NcpBase::HandlePropertyGet otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + otOperationalDatasetTlvs dataset; + + SuccessOrExit(error = otDatasetGetActiveTlvs(mInstance, &dataset)); + SuccessOrExit(error = mEncoder.WriteData(dataset.mTlvs, dataset.mLength)); + +exit: + return error; +} + +template <> otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + otOperationalDatasetTlvs dataset; + + SuccessOrExit(error = otDatasetGetPendingTlvs(mInstance, &dataset)); + SuccessOrExit(error = mEncoder.WriteData(dataset.mTlvs, dataset.mLength)); + +exit: + return error; +} + otError NcpBase::DecodeOperationalDataset(otOperationalDataset &aDataset, const uint8_t **aTlvs, uint8_t *aTlvsLength, @@ -1651,6 +1675,40 @@ exit: return error; } +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + const uint8_t *tlvs = nullptr; + uint16_t len = 0; + otOperationalDatasetTlvs dataset; + + SuccessOrExit(error = mDecoder.ReadData(tlvs, len)); + VerifyOrExit(len <= OT_OPERATIONAL_DATASET_MAX_LENGTH, error = OT_ERROR_PARSE); + memcpy(&dataset.mTlvs, tlvs, len); + dataset.mLength = static_cast(len); + SuccessOrExit(error = otDatasetSetActiveTlvs(mInstance, &dataset)); + +exit: + return error; +} + +template <> otError NcpBase::HandlePropertySet(void) +{ + otError error = OT_ERROR_NONE; + const uint8_t *tlvs = nullptr; + uint16_t len = 0; + otOperationalDatasetTlvs dataset; + + SuccessOrExit(error = mDecoder.ReadData(tlvs, len)); + VerifyOrExit(len <= OT_OPERATIONAL_DATASET_MAX_LENGTH, error = OT_ERROR_PARSE); + memcpy(&dataset.mTlvs, tlvs, len); + dataset.mLength = static_cast(len); + SuccessOrExit(error = otDatasetSetPendingTlvs(mInstance, &dataset)); + +exit: + return error; +} + template <> otError NcpBase::HandlePropertySet(void) { otError error = OT_ERROR_NONE;