From 566930f7a8751f21a0e24cf05b34827679b911ac Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 9 Jun 2017 11:01:38 -0700 Subject: [PATCH] NcpBase: Update getter for `OFF_MESH_ROUTES` to include `NextHopIsThisDevcie` field (#1886) The spinel header file and spinel documentation are also updated accordingly. --- doc/spinel-protocol-src/spinel-tech-thread.md | 14 ++-- src/ncp/ncp_base.cpp | 84 +++++++++++++++---- src/ncp/spinel.h | 30 ++++++- 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/doc/spinel-protocol-src/spinel-tech-thread.md b/doc/spinel-protocol-src/spinel-tech-thread.md index 54dd847ba47..f410fd02ff2 100644 --- a/doc/spinel-protocol-src/spinel-tech-thread.md +++ b/doc/spinel-protocol-src/spinel-tech-thread.md @@ -89,7 +89,7 @@ The local stable network data. Data per item is: * `6`: IPv6 Prefix -* `C`: Prefix length, in bits +* `C`: Prefix length in bits * `b`: Stable flag * `C`: TLV flags * `b`: "Is defined locally" flag. Set if this network was locally @@ -98,18 +98,22 @@ Data per item is: ### PROP 91: PROP_THREAD_OFF_MESH_ROUTES * Type: Read-Write -* Packed-Encoding: `A(t(6CbCb))` +* Packed-Encoding: `A(t(6CbCbb))` Data per item is: -* `6`: IPv6 Prefix -* `C`: Prefix length, in bits +* `6`: Route Prefix +* `C`: Prefix length in bits * `b`: Stable flag -* `C`: Other flags +* `C`: Route preference flags * `b`: "Is defined locally" flag. Set if this route info was locally defined as part of local network data. Assumed to be true for set, insert and replace. Clear if the route is part of partition's network data. +* `b`: "Next hop is this device" flag. Set if the next hop for the + route is this device itself (i.e., route was added by this device) + This value is ignored when adding an external route. For any added + route the next hop is this device. ### PROP 92: PROP_THREAD_ASSISTING_PORTS * Type: Read-Write diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 6343e56193e..074fb3e9a4d 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -576,6 +576,58 @@ static uint8_t BorderRouterConfigToFlagByte(const otBorderRouterConfig &config) return flags; } +static uint8_t ExternalRoutePreferenceToFlagByte(int aPreference) +{ + uint8_t flags; + + switch (aPreference) + { + case OT_ROUTE_PREFERENCE_LOW: + flags = SPINEL_ROUTE_PREFERENCE_LOW; + break; + + case OT_ROUTE_PREFERENCE_MED: + flags = SPINEL_ROUTE_PREFERENCE_MEDIUM; + break; + + case OT_ROUTE_PREFERENCE_HIGH: + flags = SPINEL_ROUTE_PREFERENCE_HIGH; + break; + + default: + flags = SPINEL_ROUTE_PREFERENCE_MEDIUM; + break; + } + + return flags; +} + +#if OPENTHREAD_ENABLE_BORDER_ROUTER + +static int FlagByteToExternalRoutePreference(uint8_t aFlags) +{ + int route_preference = 0; + + switch (aFlags & SPINEL_NET_FLAG_PREFERENCE_MASK) + { + case SPINEL_ROUTE_PREFERENCE_HIGH: + route_preference = OT_ROUTE_PREFERENCE_HIGH; + break; + + case SPINEL_ROUTE_PREFERENCE_MEDIUM: + route_preference = OT_ROUTE_PREFERENCE_MED; + break; + + case SPINEL_ROUTE_PREFERENCE_LOW: + route_preference = OT_ROUTE_PREFERENCE_LOW; + break; + } + + return route_preference; +} + +#endif // OPENTHREAD_ENABLE_BORDER_ROUTER + // ---------------------------------------------------------------------------- // MARK: Class Boilerplate // ---------------------------------------------------------------------------- @@ -3248,7 +3300,6 @@ otError NcpBase::GetPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t header, spine otError errorCode = OT_ERROR_NONE; otExternalRouteConfig external_route_config; otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT; - uint8_t flags; mDisableStreamWrite = true; @@ -3263,46 +3314,44 @@ otError NcpBase::GetPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t header, spine while (otNetDataGetNextRoute(mInstance, &iter, &external_route_config) == OT_ERROR_NONE) { - flags = static_cast(external_route_config.mPreference); - flags <<= SPINEL_NET_FLAG_PREFERENCE_OFFSET; - SuccessOrExit( errorCode = OutboundFrameFeedPacked( SPINEL_DATATYPE_STRUCT_S( SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits) - SPINEL_DATATYPE_BOOL_S // isStable - SPINEL_DATATYPE_UINT8_S // Flags + SPINEL_DATATYPE_BOOL_S // IsStable + SPINEL_DATATYPE_UINT8_S // Route Preference Flags SPINEL_DATATYPE_BOOL_S // IsLocal + SPINEL_DATATYPE_BOOL_S // NextHopIsThisDevice ), &external_route_config.mPrefix.mPrefix, external_route_config.mPrefix.mLength, external_route_config.mStable, - flags, - false + ExternalRoutePreferenceToFlagByte(external_route_config.mPreference), + false, + external_route_config.mNextHopIsThisDevice )); } #if OPENTHREAD_ENABLE_BORDER_ROUTER while (otBorderRouterGetNextRoute(mInstance, &iter, &external_route_config) == OT_ERROR_NONE) { - flags = static_cast(external_route_config.mPreference); - flags <<= SPINEL_NET_FLAG_PREFERENCE_OFFSET; - SuccessOrExit( errorCode = OutboundFrameFeedPacked( SPINEL_DATATYPE_STRUCT_S( SPINEL_DATATYPE_IPv6ADDR_S // IPv6 Prefix SPINEL_DATATYPE_UINT8_S // Prefix Length (in bits) - SPINEL_DATATYPE_BOOL_S // isStable - SPINEL_DATATYPE_UINT8_S // Flags + SPINEL_DATATYPE_BOOL_S // IsStable + SPINEL_DATATYPE_UINT8_S // Route Preference Flags SPINEL_DATATYPE_BOOL_S // IsLocal + SPINEL_DATATYPE_BOOL_S // NextHopIsThisDevice ), &external_route_config.mPrefix.mPrefix, external_route_config.mPrefix.mLength, external_route_config.mStable, - flags, - true + ExternalRoutePreferenceToFlagByte(external_route_config.mPreference), + true, + external_route_config.mNextHopIsThisDevice )); } #endif // OPENTHREAD_ENABLE_BORDER_ROUTER @@ -7030,7 +7079,7 @@ otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t header, sp SPINEL_DATATYPE_IPv6ADDR_S // Route prefix SPINEL_DATATYPE_UINT8_S // Prefix length (in bits) SPINEL_DATATYPE_BOOL_S // Stable - SPINEL_DATATYPE_UINT8_S // Flags + SPINEL_DATATYPE_UINT8_S // Flags (Route Preference) ), &addr_ptr, &ext_route_config.mPrefix.mLength, @@ -7042,7 +7091,8 @@ otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t header, sp { ext_route_config.mPrefix.mPrefix = *addr_ptr; ext_route_config.mStable = stable; - ext_route_config.mPreference = ((flags & SPINEL_NET_FLAG_PREFERENCE_MASK) >> SPINEL_NET_FLAG_PREFERENCE_OFFSET); + ext_route_config.mPreference = FlagByteToExternalRoutePreference(flags); + errorCode = otBorderRouterAddRoute(mInstance, &ext_route_config); if (errorCode == OT_ERROR_NONE) diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 4a2a469348c..26e9fcbd6fc 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -216,6 +216,13 @@ enum SPINEL_NET_FLAG_PREFERENCE_MASK = (3 << SPINEL_NET_FLAG_PREFERENCE_OFFSET), }; +enum +{ + SPINEL_ROUTE_PREFERENCE_HIGH = (1 << SPINEL_NET_FLAG_PREFERENCE_OFFSET), + SPINEL_ROUTE_PREFERENCE_MEDIUM = (0 << SPINEL_NET_FLAG_PREFERENCE_OFFSET), + SPINEL_ROUTE_PREFERENCE_LOW = (3 << SPINEL_NET_FLAG_PREFERENCE_OFFSET), +}; + enum { SPINEL_GPIO_FLAG_DIR_INPUT = 0, SPINEL_GPIO_FLAG_DIR_OUTPUT = SPINEL_BIT_MASK(0, 8), @@ -744,7 +751,28 @@ typedef enum SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION = SPINEL_PROP_THREAD__BEGIN + 9, ///< [S] SPINEL_PROP_THREAD_ON_MESH_NETS = SPINEL_PROP_THREAD__BEGIN + 10, ///< array(ipv6prefix,prefixlen,stable,flags,isLocal) [A(t(6CbCb))] - SPINEL_PROP_THREAD_OFF_MESH_ROUTES = SPINEL_PROP_THREAD__BEGIN + 11, ///< array(ipv6prefix,prefixlen,stable,flags,isLocal) [A(t(6CbCb))] + + /// Off-mesh routes + /** Format: [A(t(6CbCbb))] + * + * Data per item is: + * + * `6`: Route Prefix + * `C`: Prefix length in bits + * `b`: Stable flag + * `C`: Route preference flags + * `b`: "Is defined locally" flag. Set if this route info was locally + * defined as part of local network data. Assumed to be true for set, + * insert and replace. Clear if the route is part of partition's network + * data. + * `b`: "Next hop is this device" flag. Set if the next hop for the + * route is this device itself (i.e., route was added by this device) + * This value is ignored when adding an external route. For any added + * route the next hop is this device. + * + */ + SPINEL_PROP_THREAD_OFF_MESH_ROUTES = SPINEL_PROP_THREAD__BEGIN + 11, + SPINEL_PROP_THREAD_ASSISTING_PORTS = SPINEL_PROP_THREAD__BEGIN + 12, ///< array(portn) [A(S)] SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE = SPINEL_PROP_THREAD__BEGIN + 13, ///< [b]