Add support to ncp for parsing/handling a generic alternate (legacy) network stack. (#920)

This commit contains the following:

- APIs/typedefs in `ncp.h` to define handlers and callbacks
  for a generic alternate (legacy) network stack
- Support in `NcpBase` for parsing and handling of legacy network
  related commands/signals
- New legacy network related spinel properties
- Build feature "enable-legacy" to enable/disable this feature
This commit is contained in:
Abtin Keshavarzian
2016-11-04 08:54:19 -07:00
committed by Jonathan Hui
parent 85521db9af
commit 0509a139e2
6 changed files with 366 additions and 3 deletions
+32
View File
@@ -563,6 +563,37 @@ AC_SUBST(OPENTHREAD_ENABLE_DIAG)
AM_CONDITIONAL([OPENTHREAD_ENABLE_DIAG], [test "${enable_diag}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_DIAG],[${OPENTHREAD_ENABLE_DIAG}],[Define to 1 if you want to use diagnostics module])
#
# Legacy Network
#
AC_ARG_ENABLE(legacy,
[AS_HELP_STRING([--enable-legacy],[Enable legacy network support @<:@default=no@:>@.])],
[
case "${enableval}" in
no|yes)
enable_legacy=${enableval}
;;
*)
AC_MSG_ERROR([Invalid value ${enable_legacy} for --enable-legacy])
;;
esac
],
[enable_legacy=no])
if test "$enable_legacy" = "yes"; then
OPENTHREAD_ENABLE_LEGACY=1
else
OPENTHREAD_ENABLE_LEGACY=0
fi
AC_MSG_RESULT(${enable_legacy})
AC_SUBST(OPENTHREAD_ENABLE_LEGACY)
AM_CONDITIONAL([OPENTHREAD_ENABLE_LEGACY], [test "${enable_legacy}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_LEGACY],[${OPENTHREAD_ENABLE_LEGACY}],[Define to 1 if you want to use legacy network support])
#
# Cli Logging
#
@@ -939,6 +970,7 @@ AC_MSG_NOTICE([
OpenThread Joiner support : ${enable_joiner}
OpenThread DTLS support : ${enable_dtls}
OpenThread Diagnostics support : ${enable_diag}
OpenThread Legacy network support : ${enable_legacy}
OpenThread Cli logging support : ${enable_cli_logging}
OpenThread Certification log support : ${enable_cert_log}
OpenThread DHCPv6 Server support : ${enable_dhcp6_server}
+82
View File
@@ -73,6 +73,88 @@ void otNcpInit(otInstance *aInstance);
*/
ThreadError otNcpStreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen);
//-----------------------------------------------------------------------------------------
// Legacy network APIs
#define OT_NCP_LEGACY_ULA_PREFIX_LENGTH 8 ///< Legacy ULA size (in bytes)
/**
* Defines handler (function pointer) type for starting legacy network
*
* Invoked to start the legacy network.
*
*/
typedef void (*otNcpHandlerStartLegacy)(void);
/**
* Defines handler (function pointer) type for stopping legacy network
*
* Invoked to stop the legacy network.
*
*/
typedef void (*otNcpHandlerStopLegacy)(void);
/**
* Defines handler (function pointer) type for initiating joining process.
*
* @param[in] aExtAddress A pointer to the extended address for the node to join
* or NULL if desired to join any neighboring node.
*
* Invoked to initiate a legacy join procedure to any or a specific node.
*
*/
typedef void (*otNcpHandlerJoinLegacyNode)(const otExtAddress *aExtAddress);
/**
* Defines handler (function pointer) type for setting the legacy ULA prefix.
*
* @param[in] aUlaPrefix A pointer to buffer containing the legacy ULA prefix.
*
* Invoked to set the legacy ULA prefix.
*
*/
typedef void (*otNcpHandlerSetLegacyUlaPrefix)(const uint8_t *aUlaPrefix);
/**
* Defines a struct containing all the legacy handlers (function pointers).
*
*/
typedef struct otNcpLegacyHandlers
{
otNcpHandlerStartLegacy mStartLegacy;
otNcpHandlerStopLegacy mStopLegacy;
otNcpHandlerJoinLegacyNode mJoinLegacyNode;
otNcpHandlerSetLegacyUlaPrefix mSetLegacyUlaPrefix;
} otNcpLegacyHandlers;
/**
* This callback is invoked by the legacy stack to notify that a new
* legacy node did join the network.
*/
void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
/**
* This callback is invoked by the legacy stack to notify that the
* legacy ULA prefix has changed.
*/
void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
/**
* This method registers a set of legacy handlers with NCP.
*
* The set of handlers provided by the struct @p aHandlers are used by
* NCP code to start/stop legacy network.
* The @p aHandlers can be NULL to disable legacy support on NCP.
* Individual handlers in the given handlers struct can also be NULL.
*
* @param[in] aHandlers A pointer to a handler struct.
*
*/
void otNcpRegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers);
#ifdef __cplusplus
} // extern "C"
#endif
+4 -1
View File
@@ -32,6 +32,9 @@
/* Define to 1 if you want to use diagnostics module */
#define OPENTHREAD_ENABLE_DIAG 0
/* Define to 1 if you want to enable legacy network. */
#define OPENTHREAD_ENABLE_LEGACY 0
/* Define to 1 to enable dtls support. */
#define OPENTHREAD_ENABLE_DTLS 1
@@ -85,5 +88,5 @@
// Disable a few warnings that we don't care about
#pragma warning(disable:4200) // nonstandard extension used: zero-sized array in struct/union
#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
#pragma warning(disable:4291) // no matching operator delete found
#pragma warning(disable:4291) // no matching operator delete found
#pragma warning(disable:4815) // zero-sized array in stack object will have no elements
+213 -2
View File
@@ -30,6 +30,12 @@
* This file implements a Spinel interface to the OpenThread stack.
*/
#ifdef OPENTHREAD_CONFIG_FILE
#include OPENTHREAD_CONFIG_FILE
#else
#include <openthread-config.h>
#endif
#include <assert.h>
#include <stdlib.h>
#include <common/code_utils.hpp>
@@ -190,6 +196,10 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] =
{ SPINEL_PROP_CNTR_TX_SPINEL_TOTAL, &NcpBase::GetPropertyHandler_NCP_CNTR },
{ SPINEL_PROP_CNTR_RX_SPINEL_TOTAL, &NcpBase::GetPropertyHandler_NCP_CNTR },
{ SPINEL_PROP_CNTR_RX_SPINEL_ERR, &NcpBase::GetPropertyHandler_NCP_CNTR },
#if OPENTHREAD_ENABLE_LEGACY
{ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, &NcpBase::GetPropertyHandler_NEST_LEGACY_ULA_PREFIX },
#endif
};
const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] =
@@ -244,6 +254,10 @@ const NcpBase::SetPropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] =
#if OPENTHREAD_ENABLE_DIAG
{ SPINEL_PROP_NEST_STREAM_MFG, &NcpBase::SetPropertyHandler_NEST_STREAM_MFG },
#endif
#if OPENTHREAD_ENABLE_LEGACY
{ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, &NcpBase::SetPropertyHandler_NEST_LEGACY_ULA_PREFIX },
#endif
};
const NcpBase::InsertPropertyHandlerEntry NcpBase::mInsertPropertyHandlerTable[] =
@@ -450,10 +464,14 @@ NcpBase::NcpBase(otInstance *aInstance):
otSetIcmpEchoEnabled(mInstance, false);
mUpdateChangedPropsTask.Post();
#if OPENTHREAD_ENABLE_LEGACY
mLegacyNodeDidJoin = false;
mLegacyHandlers = NULL;
memset(mLegacyUlaPrefix, 0, sizeof(mLegacyUlaPrefix));
#endif
}
// ----------------------------------------------------------------------------
// MARK: Outbound Datagram Handling
// ----------------------------------------------------------------------------
@@ -756,6 +774,9 @@ void NcpBase::UpdateChangedProps(void)
if ( (otGetDeviceRole(mInstance) == kDeviceRoleLeader)
&& otIsSingleton(mInstance)
#if OPENTHREAD_ENABLE_LEGACY
&& !mLegacyNodeDidJoin
#endif
) {
mChangedFlags &= ~static_cast<uint32_t>(OT_NET_PARTITION_ID);
otThreadStop(mInstance);
@@ -1419,6 +1440,10 @@ ThreadError NcpBase::GetPropertyHandler_CAPS(uint8_t header, spinel_prop_key_t k
SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_ROLE_ROUTER));
#endif
#if OPENTHREAD_ENABLE_LEGACY
SuccessOrExit(errorCode = OutboundFrameFeedPacked(SPINEL_DATATYPE_UINT_PACKED_S, SPINEL_CAP_NEST_LEGACY_INTERFACE));
#endif
// End adding capabilities /////////////////////////////////////////////////
SuccessOrExit(errorCode = OutboundFrameSend());
@@ -2725,6 +2750,19 @@ ThreadError NcpBase::GetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(uint8_t header
);
}
#if OPENTHREAD_ENABLE_LEGACY
ThreadError NcpBase::GetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t header, spinel_prop_key_t key)
{
return SendPropertyUpdate(
header,
SPINEL_CMD_PROP_VALUE_IS,
key,
SPINEL_DATATYPE_DATA_S,
mLegacyUlaPrefix,
sizeof(mLegacyUlaPrefix)
);
}
#endif // OPENTHREAD_ENABLE_LEGACY
// ----------------------------------------------------------------------------
// MARK: Individual Property Setters
@@ -3171,10 +3209,32 @@ ThreadError NcpBase::SetPropertyHandler_NET_STACK_UP(uint8_t header, spinel_prop
if (value != false)
{
errorCode = otThreadStart(mInstance);
#if OPENTHREAD_ENABLE_LEGACY
mLegacyNodeDidJoin = false;
if (mLegacyHandlers != NULL)
{
if (mLegacyHandlers->mStartLegacy)
{
mLegacyHandlers->mStartLegacy();
}
}
#endif // OPENTHREAD_ENABLE_LEGACY
}
else
{
errorCode = otThreadStop(mInstance);
#if OPENTHREAD_ENABLE_LEGACY
mLegacyNodeDidJoin = false;
if (mLegacyHandlers != NULL)
{
if (mLegacyHandlers->mStopLegacy)
{
mLegacyHandlers->mStopLegacy();
}
}
#endif // OPENTHREAD_ENABLE_LEGACY
}
}
}
@@ -4266,6 +4326,47 @@ ThreadError NcpBase::SetPropertyHandler_NEST_STREAM_MFG(uint8_t header, spinel_p
}
#endif
#if OPENTHREAD_ENABLE_LEGACY
ThreadError NcpBase::SetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t header, spinel_prop_key_t key,
const uint8_t *value_ptr, uint16_t value_len)
{
ThreadError errorCode = kThreadError_None;
const uint8_t *ptr = NULL;
spinel_size_t len;
spinel_ssize_t parsedLength;
parsedLength = spinel_datatype_unpack(
value_ptr,
value_len,
SPINEL_DATATYPE_DATA_S,
&ptr,
&len
);
if ((parsedLength > 0) && (len <= sizeof(mLegacyUlaPrefix)))
{
memset(mLegacyUlaPrefix, 0, sizeof(mLegacyUlaPrefix));
memcpy(mLegacyUlaPrefix, ptr, len);
if (mLegacyHandlers)
{
if (mLegacyHandlers->mSetLegacyUlaPrefix)
{
mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
}
}
errorCode = HandleCommandPropertyGet(header, key);
}
else
{
errorCode = SendLastStatus(header, SPINEL_STATUS_PARSE_ERROR);
}
return errorCode;
}
#endif // OPENTHREAD_ENABLE_LEGACY
// ----------------------------------------------------------------------------
// MARK: Individual Property Inserters
// ----------------------------------------------------------------------------
@@ -4830,6 +4931,85 @@ ThreadError NcpBase::RemovePropertyHandler_MAC_WHITELIST(uint8_t header, spinel_
return errorCode;
}
#if OPENTHREAD_ENABLE_LEGACY
void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
{
mLegacyHandlers = aHandlers;
bool isEnabled;
VerifyOrExit(mLegacyHandlers != NULL, ;);
isEnabled = (otGetDeviceRole(mInstance) != kDeviceRoleDisabled);
if (isEnabled)
{
if (mLegacyHandlers->mStartLegacy)
{
mLegacyHandlers->mStartLegacy();
}
}
else
{
if (mLegacyHandlers->mStopLegacy)
{
mLegacyHandlers->mStopLegacy();
}
}
if (mLegacyHandlers->mSetLegacyUlaPrefix)
{
mLegacyHandlers->mSetLegacyUlaPrefix(mLegacyUlaPrefix);
}
exit:
return;
}
void NcpBase::HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
{
memcpy(mLegacyUlaPrefix, aUlaPrefix, OT_NCP_LEGACY_ULA_PREFIX_LENGTH);
SuccessOrExit(OutboundFrameBegin());
SuccessOrExit(
OutboundFrameFeedPacked(
"Cii" SPINEL_DATATYPE_DATA_S,
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_NEST_LEGACY_ULA_PREFIX,
aUlaPrefix, OT_NCP_LEGACY_ULA_PREFIX_LENGTH
));
OutboundFrameSend();
exit:
return;
}
void NcpBase::HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
{
mLegacyNodeDidJoin = true;
SuccessOrExit(OutboundFrameBegin());
SuccessOrExit(
OutboundFrameFeedPacked(
"Cii" SPINEL_DATATYPE_EUI64_S,
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_NEST_LEGACY_JOINED_NODE,
aExtAddr->m8
));
OutboundFrameSend();
exit:
return;
}
#endif // OPENTHREAD_ENABLE_LEGACY
} // namespace Thread
@@ -4852,3 +5032,34 @@ ThreadError otNcpStreamWrite(int aStreamId, const uint8_t* aDataPtr, int aDataLe
static_cast<uint16_t>(aDataLen)
);
}
// ----------------------------------------------------------------------------
// MARK: Legacy network APIs
// ----------------------------------------------------------------------------
void otNcpRegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
{
#if OPENTHREAD_ENABLE_LEGACY
Thread::sNcpContext->RegisterLegacyHandlers(aHandlers);
#else
(void)aHandlers;
#endif
}
void otNcpHandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix)
{
#if OPENTHREAD_ENABLE_LEGACY
Thread::sNcpContext->HandleDidReceiveNewLegacyUlaPrefix(aUlaPrefix);
#else
(void)aUlaPrefix;
#endif
}
void otNcpHandleLegacyNodeDidJoin(const otExtAddress *aExtAddr)
{
#if OPENTHREAD_ENABLE_LEGACY
Thread::sNcpContext->HandleLegacyNodeDidJoin(aExtAddr);
#else
(void)aExtAddr;
#endif
}
+24
View File
@@ -42,6 +42,7 @@
#include <openthread-types.h>
#include <common/message.hpp>
#include <common/tasklet.hpp>
#include <ncp/ncp.h>
#include "spinel.h"
@@ -344,6 +345,10 @@ private:
ThreadError GetPropertyHandler_THREAD_ON_MESH_NETS(uint8_t header, spinel_prop_key_t key);
ThreadError GetPropertyHandler_NET_REQUIRE_JOIN_EXISTING(uint8_t header, spinel_prop_key_t key);
#if OPENTHREAD_ENABLE_LEGACY
ThreadError GetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t header, spinel_prop_key_t key);
#endif
ThreadError SetPropertyHandler_POWER_STATE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr,
uint16_t value_len);
ThreadError SetPropertyHandler_PHY_TX_POWER(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr,
@@ -421,6 +426,11 @@ private:
uint16_t value_len);
#endif
#if OPENTHREAD_ENABLE_LEGACY
ThreadError SetPropertyHandler_NEST_LEGACY_ULA_PREFIX(uint8_t header, spinel_prop_key_t key,
const uint8_t *value_ptr, uint16_t value_len);
#endif
ThreadError InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr,
uint16_t value_len);
ThreadError InsertPropertyHandler_THREAD_LOCAL_ROUTES(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr,
@@ -445,6 +455,13 @@ private:
ThreadError RemovePropertyHandler_THREAD_ACTIVE_ROUTER_IDS(uint8_t header, spinel_prop_key_t key, const uint8_t *value_ptr,
uint16_t value_len);
#if OPENTHREAD_ENABLE_LEGACY
public:
void HandleLegacyNodeDidJoin(const otExtAddress *aExtAddr);
void HandleDidReceiveNewLegacyUlaPrefix(const uint8_t *aUlaPrefix);
void RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers);
#endif
private:
spinel_status_t mLastStatus;
@@ -478,6 +495,13 @@ private:
uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames.
uint32_t mDroppedOutboundIpFrameCounter; // Number of dropped outbound data/IP frames.
uint32_t mDroppedInboundIpFrameCounter; // Number of dropped inbound data/IP frames.
#if OPENTHREAD_ENABLE_LEGACY
const otNcpLegacyHandlers *mLegacyHandlers;
uint8_t mLegacyUlaPrefix[OT_NCP_LEGACY_ULA_PREFIX_LENGTH];
bool mLegacyNodeDidJoin;
#endif
};
} // namespace Thread
+11
View File
@@ -827,6 +827,17 @@ typedef enum
SPINEL_PROP_NEST__BEGIN = 15296,
SPINEL_PROP_NEST_STREAM_MFG = SPINEL_PROP_NEST__BEGIN + 0,
/// The legacy network ULA prefix (8 bytes)
/** Format: 'D' */
SPINEL_PROP_NEST_LEGACY_ULA_PREFIX
= SPINEL_PROP_NEST__BEGIN + 1,
/// A (newly) joined legacy node (this is signaled from NCP)
/** Format: 'E' */
SPINEL_PROP_NEST_LEGACY_JOINED_NODE
= SPINEL_PROP_NEST__BEGIN + 2,
SPINEL_PROP_NEST__END = 15360,
SPINEL_PROP_VENDOR__BEGIN = 15360,