From 5111bbee65c6031892f29e13ec1bf5738f50acd8 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 24 Nov 2020 13:44:09 -0800 Subject: [PATCH] [spinel] add RCP API Version and compatibility check (#5863) This commit adds a new compatibility check model for RCP and host. It updates the compatibility guideline documentation stating how the compatibility policy for NCP versus RCP are handled differently. For NCP, we continue to require new NCP firmware to remain backward compatible and work with an older host driver. For RCP and host, this commit introduces the RCP API Version model. The API version numbers are used to check the compatibility between host implementation and RCP firmware. Generally, a newer host side implementation would work with a range of previous or older RCP firmware versions. This commit adds `SPINEL_RCP_API_VERSION` definition which specifies the current spinel RCP API version. This number MUST be incremented anytime there is a change in any of RCP specific spinel definitions. `SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION` specifies the minimum spinel RCP API version which is supported by the host-side implementation. This commit also reserves a block of spinel properties value ranges from `0xB0 - 0xFF` for RCP related property definitions. The smaller property values help decrease the encoded byte stream length, resulting in shorter spinel frames exchanged between RCP and host. --- src/lib/spinel/spinel.c | 8 ++++ src/lib/spinel/spinel.h | 81 ++++++++++++++++++++++++++++++--- src/ncp/ncp_base.cpp | 4 ++ src/ncp/ncp_base_dispatcher.cpp | 5 ++ src/ncp/ncp_base_radio.cpp | 7 +++ 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index 3c180d38f..f314f8142 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -2003,6 +2003,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "SERVER_LEADER_SERVICES"; break; + case SPINEL_PROP_RCP_API_VERSION: + ret = "RCP_API_VERSION"; + break; + case SPINEL_PROP_UART_BITRATE: ret = "UART_BITRATE"; break; @@ -2615,6 +2619,10 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability) ret = "NET_THREAD_1_1"; break; + case SPINEL_CAP_RCP_API_VERSION: + ret = "RCP_API_VERSION"; + break; + case SPINEL_CAP_MAC_ALLOWLIST: ret = "MAC_ALLOWLIST"; break; diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index fd0722e55..e98f78f26 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -292,7 +292,10 @@ * * --------------------------------------------------------------------------- * - * Spinel definition guideline: + * Spinel definition compatibility guideline: + * + * The compatibility policy for NCP versus RCP and host side are handled + * differently in spinel. * * New NCP firmware should work with an older host driver, i.e., NCP * implementation should remain backward compatible. @@ -305,6 +308,24 @@ * optional (i.e., a driver not aware of and therefore not using the * new fields should continue to function as before). * + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * + * For RCP and host, the "RCP API Version" numbers are used to check the + * compatibility between host implementation and RCP firmware. Generally, + * a newer host side implementation would work with a range of previous + * or older RCP firmware versions. + * + * - SPINEL_RCP_API_VERSION specifies the current spinel RCP API version. + * This number MUST be incremented anytime there is a change in any of RCP + * specific spinel definitions. + * + * - SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION specifies the minimum spinel + * RCP API Version which is supported by the host-side implementation. + * + * - On start, host implementation queries the RCP API version and accepts + * any version number from SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION up to + * and including SPINEL_RCP_API_VERSION. + * * --------------------------------------------------------------------------- */ @@ -345,6 +366,31 @@ #define SPINEL_PROTOCOL_VERSION_THREAD_MAJOR 4 #define SPINEL_PROTOCOL_VERSION_THREAD_MINOR 3 +/** + * @def SPINEL_RCP_API_VERSION + * + * The RCP API version number. + * + * This number MUST increase by one each time any of the spinel definitions used by RCP change (independent of whether + * the change is backward-compatible or not). + * + * Please see section "Spinel definition compatibility guideline" for more details. + * + */ +#define SPINEL_RCP_API_VERSION 1 + +/** + * @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION + * + * The minimum RCP API version supported by the host implementation. + * + * This number MUST increase when there is a non-compatible RCP spinel related change on host implementation. + * + * Please see section "Spinel definition compatibility guideline" for more details. + * + */ +#define SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION 1 + /** * @def SPINEL_FRAME_MAX_SIZE * @@ -1079,6 +1125,10 @@ enum SPINEL_CAP_NET_THREAD_1_1 = (SPINEL_CAP_NET__BEGIN + 1), SPINEL_CAP_NET__END = 64, + SPINEL_CAP_RCP__BEGIN = 64, + SPINEL_CAP_RCP_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 0), + SPINEL_CAP_RCP__END = 80, + SPINEL_CAP_OPENTHREAD__BEGIN = 512, SPINEL_CAP_MAC_ALLOWLIST = (SPINEL_CAP_OPENTHREAD__BEGIN + 0), SPINEL_CAP_MAC_RAW = (SPINEL_CAP_OPENTHREAD__BEGIN + 1), @@ -1137,10 +1187,11 @@ typedef uint32_t spinel_capability_t; * MeshCop | 0x080 - 0x08F, 0x1800 - 0x18FF | Thread Mesh Commissioning * OpenThread | 0x1900 - 0x19FF | OpenThread specific * Server | 0x0A0 - 0x0AF | ALOC Service Server + * RCP | 0x0B0 - 0x0FF | RCP specific * Interface | 0x100 - 0x1FF | Interface (e.g., UART) * PIB | 0x400 - 0x4FF | 802.15.4 PIB * Counter | 0x500 - 0x7FF | Counters (MAC, IP, etc). - * RCP | 0x800 - 0x8FF | RCP specific property + * RCP | 0x800 - 0x8FF | RCP specific property (extended) * Nest | 0x3BC0 - 0x3BFF | Nest (legacy) * Vendor | 0x3C00 - 0x3FFF | Vendor specific * Debug | 0x4000 - 0x43FF | Debug related @@ -3585,6 +3636,22 @@ enum SPINEL_PROP_SERVER__END = 0xB0, + SPINEL_PROP_RCP__BEGIN = 0xB0, + + /// RCP API Version number + /** Format: `i` (read-only) + * + * Required capability: SPINEL_CAP_RADIO and SPINEL_CAP_RCP_API_VERSION. + * + * This property gives the RCP API Version number. + * + * Please see "Spinel definition compatibility guideline" section. + * + */ + SPINEL_PROP_RCP_API_VERSION = SPINEL_PROP_RCP__BEGIN + 0, + + SPINEL_PROP_RCP__END = 0xFF, + SPINEL_PROP_INTERFACE__BEGIN = 0x100, /// UART Bitrate @@ -3973,7 +4040,7 @@ enum SPINEL_PROP_CNTR__END = 0x800, - SPINEL_PROP_RCP__BEGIN = 0x800, + SPINEL_PROP_RCP_EXT__BEGIN = 0x800, /// MAC Key /** Format: `CCddd`. @@ -3987,7 +4054,7 @@ enum * The Spinel property is used to set/get MAC key materials to and from RCP. * */ - SPINEL_PROP_RCP_MAC_KEY = SPINEL_PROP_RCP__BEGIN + 0, + SPINEL_PROP_RCP_MAC_KEY = SPINEL_PROP_RCP_EXT__BEGIN + 0, /// MAC Frame Counter /** Format: `L`. @@ -3997,7 +4064,7 @@ enum * The Spinel property is used to set MAC frame counter to RCP. * */ - SPINEL_PROP_RCP_MAC_FRAME_COUNTER = SPINEL_PROP_RCP__BEGIN + 1, + SPINEL_PROP_RCP_MAC_FRAME_COUNTER = SPINEL_PROP_RCP_EXT__BEGIN + 1, /// Timestamps when Spinel frame is received and transmitted /** Format: `X`. @@ -4007,9 +4074,9 @@ enum * The Spinel property is used to get timestamp from RCP to calculate host and RCP timer difference. * */ - SPINEL_PROP_RCP_TIMESTAMP = SPINEL_PROP_RCP__BEGIN + 2, + SPINEL_PROP_RCP_TIMESTAMP = SPINEL_PROP_RCP_EXT__BEGIN + 2, - SPINEL_PROP_RCP__END = 0x900, + SPINEL_PROP_RCP_EXT__END = 0x900, SPINEL_PROP_NEST__BEGIN = 0x3BC0, diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 682344dff..bdd7b8bc0 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -1796,6 +1796,10 @@ template <> otError NcpBase::HandlePropertyGet(void) SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MAC_RAW)); #endif +#if OPENTHREAD_RADIO + SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_API_VERSION)); +#endif + #if OPENTHREAD_PLATFORM_POSIX SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX)); #endif diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 8b3dbb859..2d13ea430 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -149,6 +149,11 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SERVER_SERVICES), #endif OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SERVER_LEADER_SERVICES), +#endif // OPENTHREAD_MTD || OPENTHREAD_FTD +#if OPENTHREAD_RADIO + OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_RCP_API_VERSION), +#endif +#if OPENTHREAD_MTD || OPENTHREAD_FTD OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CNTR_TX_PKT_TOTAL), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CNTR_TX_PKT_ACK_REQ), OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CNTR_TX_PKT_ACKED), diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp index cac86387f..3be08286f 100644 --- a/src/ncp/ncp_base_radio.cpp +++ b/src/ncp/ncp_base_radio.cpp @@ -48,6 +48,13 @@ namespace ot { namespace Ncp { +#if OPENTHREAD_RADIO +template <> otError NcpBase::HandlePropertyGet(void) +{ + return mEncoder.WriteUintPacked(SPINEL_RCP_API_VERSION); +} +#endif + // ---------------------------------------------------------------------------- // MARK: Raw Link-Layer Datapath Glue // ----------------------------------------------------------------------------