From 517679e1afa9b520d62143e2f6af459d04640bb4 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 12 Feb 2020 15:06:07 -0800 Subject: [PATCH] Add new properties related to multi radio link feature --- src/ncp-spinel/SpinelNCPInstance.cpp | 163 ++++++++++++++++++++++++ src/wpantund/wpan-properties.h | 3 + third_party/openthread/src/ncp/spinel.c | 45 +++++++ third_party/openthread/src/ncp/spinel.h | 50 ++++++++ 4 files changed, 261 insertions(+) diff --git a/src/ncp-spinel/SpinelNCPInstance.cpp b/src/ncp-spinel/SpinelNCPInstance.cpp index de4064f8..c9e5435b 100644 --- a/src/ncp-spinel/SpinelNCPInstance.cpp +++ b/src/ncp-spinel/SpinelNCPInstance.cpp @@ -509,11 +509,16 @@ SpinelNCPInstance::get_supported_property_keys()const properties.insert(kWPANTUNDProperty_ThreadActiveDataset); properties.insert(kWPANTUNDProperty_ThreadPendingDataset); properties.insert(kWPANTUNDProperty_ThreadAddressCacheTable); + properties.insert(kWPANTUNDProperty_OpenThreadSupportedRadioLinks); if (mCapabilities.count(SPINEL_CAP_ERROR_RATE_TRACKING)) { properties.insert(kWPANTUNDProperty_ThreadNeighborTableErrorRates); } + if (mCapabilities.count(SPINEL_CAP_MULTI_RADIO)) { + properties.insert(kWPANTUNDProperty_OpenThreadNeighborTableMultiRadioInfo); + } + if (mCapabilities.count(SPINEL_CAP_THREAD_COMMISSIONER)) { properties.insert(kWPANTUNDProperty_CommissionerState); properties.insert(kWPANTUNDProperty_CommissionerProvisioningUrl); @@ -1667,6 +1672,150 @@ unpack_address_cache_table(const uint8_t *data_in, spinel_size_t data_len, boost return ret; } +static int +unpack_supported_radio_links(const uint8_t *data_in, spinel_size_t data_len, boost::any &value) +{ + std::list result; + int ret = kWPANTUNDStatus_Ok; + + while (data_len > 0) { + spinel_ssize_t len; + unsigned int value; + + len = spinel_packed_uint_decode(data_in, data_len, &value); + require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure); + + data_in += len; + data_len -= len; + + result.push_back(std::string(spinel_radio_link_to_cstr(value))); + } + + value = result; + +bail: + return ret; +} +static int +unpack_neighbor_table_multi_radio_info(const uint8_t *data_in, spinel_size_t data_len, boost::any &value) +{ + int ret = kWPANTUNDStatus_Ok; + std::list result; + char c_string[200]; + int index; + + while (data_len > 0) { + spinel_ssize_t len = 0; + const uint8_t *entry_data; + spinel_size_t entry_len; + const spinel_eui64_t *eui64 = NULL; + uint16_t rloc16; + bool first_radio; + + len = spinel_datatype_unpack( + data_in, + data_len, + SPINEL_DATATYPE_DATA_WLEN_S, + &entry_data, + &entry_len + ); + + require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure); + + data_in += len; + data_len -= len; + + // Parse the entry_data (which contains info about a neighbor) + + len = spinel_datatype_unpack( + entry_data, + entry_len, + ( + SPINEL_DATATYPE_EUI64_S // EUI64 Address + SPINEL_DATATYPE_UINT16_S // Rloc16 + ), + &eui64, + &rloc16 + ); + + require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure); + + index = 0; + + index += snprintf(c_string + index, sizeof(c_string) - index, + "%02X%02X%02X%02X%02X%02X%02X%02X, RLOC16:%04x, Radios:[", + eui64->bytes[0], eui64->bytes[1], eui64->bytes[2], eui64->bytes[3], + eui64->bytes[4], eui64->bytes[5], eui64->bytes[6], eui64->bytes[7], + rloc16 + ); + + require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure); + + entry_data += len; + entry_len -= len; + + first_radio = true; + + while (entry_len > 0) { + const uint8_t *struct_data; + spinel_size_t struct_len; + unsigned int radio; + uint8_t preference; + + len = spinel_datatype_unpack( + entry_data, + entry_len, + SPINEL_DATATYPE_DATA_WLEN_S, + &struct_data, + &struct_len + ); + + require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure); + + entry_data += len; + entry_len -= len; + + // Parse struct_data (contains info about a supported radio link type) + + len = spinel_datatype_unpack( + struct_data, + struct_len, + ( + SPINEL_DATATYPE_UINT_PACKED_S // Radio link + SPINEL_DATATYPE_UINT8_S // Preference + ), + &radio, + &preference + ); + + require_action(len > 0, bail, ret = kWPANTUNDStatus_Failure); + + struct_data += len; + struct_len -= len; + + index += snprintf(c_string + index, sizeof(c_string) - index, + "%s%s(%d)", + first_radio ? "" : ", ", + spinel_radio_link_to_cstr(radio), + preference + ); + + require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure); + first_radio = false; + } + + index += snprintf(c_string + index, sizeof(c_string) - index, "]"); + require_action(index < sizeof(c_string), bail, ret = kWPANTUNDStatus_Failure); + + result.push_back(std::string(c_string)); + } + + value = result; + +bail: + return ret; +} + static int unpack_mesh_local_prefix(const uint8_t *data_in, spinel_size_t data_len, boost::any &value) { @@ -2316,6 +2465,9 @@ SpinelNCPInstance::regsiter_all_get_handlers(void) register_get_handler_spinel_simple( kWPANTUNDProperty_OpenThreadLogTimestampBase, SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE, SPINEL_DATATYPE_UINT64_S); + register_get_handler_spinel_simple( + kWPANTUNDProperty_OpenThreadTrelTestModeEnable, + SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE, SPINEL_DATATYPE_BOOL_S); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Properties requiring capability check and associated with a spinel property @@ -2643,6 +2795,10 @@ SpinelNCPInstance::regsiter_all_get_handlers(void) kWPANTUNDProperty_ThreadAddressCacheTableAsValMap, SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE, boost::bind(unpack_address_cache_table, _1, _2, _3, /* as_val_map */ true)); + register_get_handler_spinel_unpacker( + kWPANTUNDProperty_OpenThreadSupportedRadioLinks, + SPINEL_PROP_SUPPORTED_RADIO_LINKS, + unpack_supported_radio_links); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Properties requiring capability check and associated with a spinel property @@ -2756,6 +2912,10 @@ SpinelNCPInstance::regsiter_all_get_handlers(void) kWPANTUNDProperty_NCPCoexMetricsAsValMap, SPINEL_CAP_RADIO_COEX, SPINEL_PROP_RADIO_COEX_METRICS, boost::bind(unpack_coex_metrics, _1, _2, _3, true)); + register_get_handler_capability_spinel_unpacker( + kWPANTUNDProperty_OpenThreadNeighborTableMultiRadioInfo, + SPINEL_CAP_MULTI_RADIO, + SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO, boost::bind(unpack_neighbor_table_multi_radio_info, _1, _2, _3)); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Properties with a dedicated handler method @@ -3522,6 +3682,9 @@ SpinelNCPInstance::regsiter_all_set_handlers(void) register_set_handler_spinel( kWPANTUNDProperty_ThreadRouterDowngradeThreshold, SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, SPINEL_DATATYPE_UINT8_C); + register_set_handler_spinel( + kWPANTUNDProperty_OpenThreadTrelTestModeEnable, + SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE, SPINEL_DATATYPE_BOOL_C); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Properties requiring persistence (saving in settings) and associated with a diff --git a/src/wpantund/wpan-properties.h b/src/wpantund/wpan-properties.h index 82ec01cd..3b8e63bf 100644 --- a/src/wpantund/wpan-properties.h +++ b/src/wpantund/wpan-properties.h @@ -173,6 +173,8 @@ #define kWPANTUNDProperty_POSIXAppRCPVersion "POSIXApp:RCPVersion" #define kWPANTUNDProperty_POSIXAppRCPVersionCached "POSIXApp:RCPVersion:Cached" +#define kWPANTUNDProperty_OpenThreadSupportedRadioLinks "OpenThread:SupportedRadioLinks" +#define kWPANTUNDProperty_OpenThreadNeighborTableMultiRadioInfo "OpenThread:NeighborTable::MultiRadioInfo" #define kWPANTUNDProperty_OpenThreadLogLevel "OpenThread:LogLevel" #define kWPANTUNDProperty_OpenThreadLogTimestampBase "OpenThread:LogTimestampBase" #define kWPANTUNDProperty_OpenThreadSLAACEnabled "OpenThread:SLAAC:Enabled" @@ -182,6 +184,7 @@ #define kWPANTUNDProperty_OpenThreadMsgBufferCountersAsString "OpenThread:MsgBufferCounters:AsString" #define kWPANTUNDProperty_OpenThreadDebugTestAssert "OpenThread:Debug:TestAssert" #define kWPANTUNDProperty_OpenThreadDebugTestWatchdog "OpenThread:Debug:TestWatchdog" +#define kWPANTUNDProperty_OpenThreadTrelTestModeEnable "OpenThread:Trel:TestMode:Enable" #define kWPANTUNDProperty_DebugIPv6GlobalIPAddressList "Debug:IPv6:GlobalIPAddressList" diff --git a/third_party/openthread/src/ncp/spinel.c b/third_party/openthread/src/ncp/spinel.c index f8217893..c5eb5c25 100644 --- a/third_party/openthread/src/ncp/spinel.c +++ b/third_party/openthread/src/ncp/spinel.c @@ -1987,6 +1987,14 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "SLAAC_ENABLED"; break; + case SPINEL_PROP_SUPPORTED_RADIO_LINKS: + ret = "SUPPORTED_RADIO_LINKS"; + break; + + case SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO: + ret = "NEIGHBOR_TABLE_MULTI_RADIO_INFO"; + break; + case SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE: ret = "SERVER_ALLOW_LOCAL_DATA_CHANGE"; break; @@ -2247,6 +2255,14 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "DEBUG_TEST_WATCHDOG"; break; + case SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE: + ret = "DEBUG_LOG_TIMESTAMP_BASE"; + break; + + case SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE: + ret = "DEBUG_TREL_TEST_MODE_ENABLE"; + break; + default: break; } @@ -2651,6 +2667,10 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability) ret = "MAC_RETRY_HISTOGRAM"; break; + case SPINEL_CAP_MULTI_RADIO: + ret = "MULTI_RADIO"; + break; + case SPINEL_CAP_ERROR_RATE_TRACKING: ret = "ERROR_RATE_TRACKING"; break; @@ -2698,6 +2718,31 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability) return ret; } +const char *spinel_radio_link_to_cstr(uint32_t radio) +{ + const char *ret = "UNKNOWN"; + + switch (radio) + { + case SPINEL_RADIO_LINK_IEEE_802_15_4: + ret = "IEEE_802_15_4"; + break; + + case SPINEL_RADIO_LINK_TOBLE: + ret = "TOBLE"; + break; + + case SPINEL_RADIO_LINK_TREL_UDP6: + ret = "TREL_UDP6"; + break; + + default: + break; + } + + return ret; +} + // LCOV_EXCL_STOP /* -------------------------------------------------------------------------- */ diff --git a/third_party/openthread/src/ncp/spinel.h b/third_party/openthread/src/ncp/spinel.h index ba0461ab..4aa5105f 100644 --- a/third_party/openthread/src/ncp/spinel.h +++ b/third_party/openthread/src/ncp/spinel.h @@ -661,6 +661,13 @@ enum SPINEL_ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY = 3, // Entry is in retry mode (a prior query did not a response). }; +enum +{ + SPINEL_RADIO_LINK_IEEE_802_15_4 = 0, + SPINEL_RADIO_LINK_TOBLE = 1, + SPINEL_RADIO_LINK_TREL_UDP6 = 2, +}; + typedef struct { uint8_t bytes[8]; @@ -1091,6 +1098,7 @@ enum SPINEL_CAP_SLAAC = (SPINEL_CAP_OPENTHREAD__BEGIN + 10), SPINEL_CAP_RADIO_COEX = (SPINEL_CAP_OPENTHREAD__BEGIN + 11), SPINEL_CAP_MAC_RETRY_HISTOGRAM = (SPINEL_CAP_OPENTHREAD__BEGIN + 12), + SPINEL_CAP_MULTI_RADIO = (SPINEL_CAP_OPENTHREAD__BEGIN + 13), SPINEL_CAP_OPENTHREAD__END = 640, SPINEL_CAP_THREAD__BEGIN = 1024, @@ -3530,6 +3538,34 @@ enum */ SPINEL_PROP_SLAAC_ENABLED = SPINEL_PROP_OPENTHREAD__BEGIN + 14, + // Supported Radio Links (by device) + /** + * Format `A(i)` - Read only + * + * This property returns list of supported radio links by the device itself. Enumeration `SPINEL_RADIO_LINK_{TYPE}` + * values indicate different radio link types. + * + */ + SPINEL_PROP_SUPPORTED_RADIO_LINKS = SPINEL_PROP_OPENTHREAD__BEGIN + 15, + + /// Neighbor Table Multi Radio Link Info + /** Format: `A(t(ESA(t(iC))))` - Read only + * Required capability: `SPINEL_CAP_MULTI_RADIO`. + * + * Each item represents info about a neighbor: + * + * `E`: Neighbor's Extended Address + * `S`: Neighbor's RLOC16 + * + * This is then followed by an array of radio link info structures indicating which radio links are supported by + * the neighbor: + * + * `i` : Radio link type (enumeration `SPINEL_RADIO_LINK_{TYPE}`). + * `C` : Preference value associated with radio link. + * + */ + SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO = SPINEL_PROP_OPENTHREAD__BEGIN + 16, + SPINEL_PROP_OPENTHREAD__END = 0x2000, SPINEL_PROP_SERVER__BEGIN = 0xA0, @@ -4059,6 +4095,18 @@ enum */ SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE = SPINEL_PROP_DEBUG__BEGIN + 3, + /// TREL Radio Link - test mode enable + /** Format `b` (read-write) + * + * This property is intended for testing TREL (Thread Radio Encapsulation Link) radio type only (during simulation). + * It allows the TREL interface to be temporarily disabled and (re)enabled. While disabled all traffic through + * TREL interface is dropped silently (to emulate a radio/interface down scenario). + * + * This property is only available when the TREL radio link type is supported. + * + */ + SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE = SPINEL_PROP_DEBUG__BEGIN + 4, + SPINEL_PROP_DEBUG__END = 0x4400, SPINEL_PROP_EXPERIMENTAL__BEGIN = 2000000, @@ -4250,6 +4298,8 @@ SPINEL_API_EXTERN const char *spinel_status_to_cstr(spinel_status_t status); SPINEL_API_EXTERN const char *spinel_capability_to_cstr(spinel_capability_t capability); +SPINEL_API_EXTERN const char *spinel_radio_link_to_cstr(uint32_t radio); + // ---------------------------------------------------------------------------- #if defined(__cplusplus)