From 0066be4c184e725472c4cbcba5c82daf6a73b99c Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Tue, 30 Aug 2016 11:52:43 -0700 Subject: [PATCH] ncp: Add the ability to get PROP_THREAD_ON_MESH_NETS (#491) This property will also be updated dynamically. --- src/ncp/ncp_base.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++- src/ncp/ncp_base.hpp | 2 + src/ncp/spinel.h | 13 +++-- 3 files changed, 127 insertions(+), 5 deletions(-) diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 850ddfadb..2f4be085f 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -132,6 +132,7 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] = { SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, &NcpBase::GetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD }, { SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY, &NcpBase::GetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY }, { SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT, &NcpBase::GetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT }, + { SPINEL_PROP_THREAD_ON_MESH_NETS, &NcpBase::NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS }, { SPINEL_PROP_IPV6_ML_PREFIX, &NcpBase::GetPropertyHandler_IPV6_ML_PREFIX }, { SPINEL_PROP_IPV6_ML_ADDR, &NcpBase::GetPropertyHandler_IPV6_ML_ADDR }, @@ -354,6 +355,45 @@ static spinel_status_t ResetReasonToSpinelStatus(otPlatResetReason reason) return ret; } +static uint8_t BorderRouterConfigToFlagByte(const otBorderRouterConfig &config) +{ + uint8_t flags(0); + + if (config.mPreferred) + { + flags |= SPINEL_NET_FLAG_PREFERRED; + } + + if (config.mSlaac) + { + flags |= SPINEL_NET_FLAG_SLAAC; + } + + if (config.mDhcp) + { + flags |= SPINEL_NET_FLAG_DHCP; + } + + if (config.mDefaultRoute) + { + flags |= SPINEL_NET_FLAG_DEFAULT_ROUTE; + } + + if (config.mConfigure) + { + flags |= SPINEL_NET_FLAG_CONFIGURE; + } + + if (config.mOnMesh) + { + flags |= SPINEL_NET_FLAG_ON_MESH; + } + + flags |= (config.mPreference << SPINEL_NET_FLAG_PREFERENCE_OFFSET); + + return flags; +} + // ---------------------------------------------------------------------------- // MARK: Class Boilerplate // ---------------------------------------------------------------------------- @@ -614,7 +654,10 @@ void NcpBase::UpdateChangedProps(void) } else if ((mChangedFlags & OT_THREAD_NETDATA_UPDATED) != 0) { - // TODO: Handle the netdata changed event. + SuccessOrExit(HandleCommandPropertyGet( + SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, + SPINEL_PROP_THREAD_ON_MESH_NETS + )); mChangedFlags &= ~static_cast(OT_THREAD_NETDATA_UPDATED); } @@ -1715,6 +1758,78 @@ ThreadError NcpBase::GetPropertyHandler_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE(uint8 ); } +ThreadError NcpBase::GetPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key) +{ + ThreadError errorCode = kThreadError_None; + otBorderRouterConfig border_router_config; + uint8_t flags; + + SuccessOrExit(errorCode = OutboundFrameBegin()); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked("Cii", header, SPINEL_CMD_PROP_VALUE_IS, key)); + + // Fill from non-local network data first + for (otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT ;;) + { + errorCode = otGetNextOnMeshPrefix(false, &iter, &border_router_config); + + if (errorCode != kThreadError_None) + { + break; + } + + flags = BorderRouterConfigToFlagByte(border_router_config); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked( + "T(" + 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 // isLocal + ").", + &border_router_config.mPrefix, + 64, + border_router_config.mStable, + flags, + true + )); + } + + // Fill from local network data last + for (otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT ;;) + { + errorCode = otGetNextOnMeshPrefix(true, &iter, &border_router_config); + + if (errorCode != kThreadError_None) + { + break; + } + + flags = BorderRouterConfigToFlagByte(border_router_config); + + SuccessOrExit(errorCode = OutboundFrameFeedPacked( + "T(" + 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 // isLocal + ").", + &border_router_config.mPrefix, + 64, + border_router_config.mStable, + flags, + false + )); + } + + SuccessOrExit(errorCode = OutboundFrameSend()); + +exit: + return errorCode; +} + ThreadError NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key) { diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 5a9b126d4..4bf2336ba 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -305,6 +305,8 @@ private: ThreadError GetPropertyHandler_THREAD_ROUTER_UPGRADE_THRESHOLD(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_THREAD_CONTEXT_REUSE_DELAY(uint8_t header, spinel_prop_key_t key); ThreadError GetPropertyHandler_THREAD_NETWORK_ID_TIMEOUT(uint8_t header, spinel_prop_key_t key); + ThreadError GetPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key); + ThreadError SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr, uint16_t value_len); diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 073ef4a01..c3f1464fb 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -149,10 +149,15 @@ typedef enum } spinel_power_state_t; enum { - SPINEL_NET_FLAG_CONFIGURE = 0x04, - SPINEL_NET_FLAG_DHCP = 0x08, - SPINEL_NET_FLAG_SLAAC_VALID = 0x10, - SPINEL_NET_FLAG_SLAAC_PREFERRED = 0x20, + SPINEL_NET_FLAG_ON_MESH = (1 << 0), + SPINEL_NET_FLAG_DEFAULT_ROUTE = (1 << 1), + SPINEL_NET_FLAG_CONFIGURE = (1 << 2), + SPINEL_NET_FLAG_DHCP = (1 << 3), + SPINEL_NET_FLAG_SLAAC = (1 << 4), + SPINEL_NET_FLAG_PREFERRED = (1 << 5), + + SPINEL_NET_FLAG_PREFERENCE_OFFSET = 6, + SPINEL_NET_FLAG_PREFERENCE_MASK = (3 << SPINEL_NET_FLAG_PREFERENCE_OFFSET), }; enum