From 012fe7ebee437f8dba118ee94d8eeed8f9ea6114 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Sat, 11 Jun 2016 12:44:23 -0700 Subject: [PATCH] Implement known missing OpenThread APIs needed for NCP support. (#122) This change adds the following APIs: * otGetLeaderRloc * otGetMeshLocalEid * otGetMeshLocalPrefix * otSetMeshLocalPrefix * otGetNetworkDataLeader * otGetNetworkDataLocal * otGetShortAddress * otSetRawIp6ReceivedCallback * otSendRawIp6 --- include/openthread-types.h | 5 ++ include/openthread.h | 106 +++++++++++++++++++++++++++++++++++++ src/core/net/ip6.cpp | 14 +++-- src/core/net/ip6.hpp | 17 ++---- src/core/openthread.cpp | 67 +++++++++++++++++++++++ src/core/thread/mle.cpp | 25 ++++----- src/ncp/ncp_base.cpp | 34 ++++++------ src/ncp/ncp_base.hpp | 2 +- 8 files changed, 220 insertions(+), 50 deletions(-) diff --git a/include/openthread-types.h b/include/openthread-types.h index 2bccd7dfb..ba1bc2027 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -75,6 +75,11 @@ typedef enum ThreadError */ kThreadError_ChannelAccessFailure = 17, + /** + * Not currently attached to a Thread Partition. + */ + kThreadError_Detached = 18, + kThreadError_Error = 255, } ThreadError; diff --git a/include/openthread.h b/include/openthread.h index 19b0b4d7b..b01a4fd02 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -56,6 +56,7 @@ extern "C" { * @defgroup config Configuration * @defgroup diags Diagnostics * @defgroup messages Message Buffers + * @defgroup ip6 IPv6 * @defgroup udp UDP * * @} @@ -277,6 +278,18 @@ const uint8_t *otGetExtendedPanId(void); */ void otSetExtendedPanId(const uint8_t *aExtendedPanId); +/** + * This function returns a pointer to the Leader's RLOC. + * + * @param[out] aLeaderRloc A pointer to where the Leader's RLOC will be written. + * + * @retval kThreadError_None The Leader's RLOC was successfully written to @p aLeaderRloc. + * @retval kThreadError_InvalidArgs @p aLeaderRloc was NULL. + * @retval kThreadError_Detached Not currently attached to a Thread Partition. + * + */ +ThreadError otGetLeaderRloc(otIp6Address *aLeaderRloc); + /** * Get the MLE Link Mode configuration. * @@ -322,6 +335,52 @@ const uint8_t *otGetMasterKey(uint8_t *aKeyLength); */ ThreadError otSetMasterKey(const uint8_t *aKey, uint8_t aKeyLength); +/** + * This function returns a pointer to the Mesh Local EID. + * + * @returns A pointer to the Mesh Local EID. + * + */ +const otIp6Address *otGetMeshLocalEid(void); + +/** + * This function returns a pointer to the Mesh Local Prefix. + * + * @returns A pointer to the Mesh Local Prefix. + * + */ +const uint8_t *otGetMeshLocalPrefix(void); + +/** + * This function sets the Mesh Local Prefix. + * + * @param[in] aMeshLocalPrefix A pointer to the Mesh Local Prefix. + * + * @retval kThreadError_None Successfully set the Mesh Local Prefix. + * + */ +ThreadError otSetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix); + +/** + * This method provides a full or stable copy of the Leader's Thread Network Data. + * + * @param[in] aStable TRUE when copying the stable version, FALSE when copying the full version. + * @param[out] aData A pointer to the data buffer. + * @param[inout] aDataLength On entry, size of the data buffer pointed to by @p aData. + * On exit, number of copied bytes. + */ +ThreadError otGetNetworkDataLeader(bool aStable, uint8_t *aData, uint8_t *aDataLength); + +/** + * This method provides a full or stable copy of the local Thread Network Data. + * + * @param[in] aStable TRUE when copying the stable version, FALSE when copying the full version. + * @param[out] aData A pointer to the data buffer. + * @param[inout] aDataLength On entry, size of the data buffer pointed to by @p aData. + * On exit, number of copied bytes. + */ +ThreadError otGetNetworkDataLocal(bool aStable, uint8_t *aData, uint8_t *aDataLength); + /** * Get the Thread Network Name. * @@ -363,6 +422,13 @@ otPanId otGetPanId(void); */ ThreadError otSetPanId(otPanId aPanId); +/** + * Get the IEEE 802.15.4 Short Address. + * + * @returns A pointer to the IEEE 802.15.4 Short Address. + */ +otShortAddress otGetShortAddress(void); + /** * Get the list of IPv6 addresses assigned to the Thread interface. * @@ -989,6 +1055,46 @@ int otReadMessage(otMessage aMessage, uint16_t aOffset, void *aBuf, uint16_t aLe */ int otWriteMessage(otMessage aMessage, uint16_t aOffset, const void *aBuf, uint16_t aLength); +/** + * @} + * + */ + +/** + * @addtogroup ip6 IPv6 + * + * @brief + * This module includes functions that control IPv6 communication. + * + * @{ + * + */ + +/** + * This function pointer is called when an IPv6 datagram is received. + * + * @param[in] aMessage A pointer to the message buffer containing the received IPv6 datagram. + * + */ +typedef void (*otReceiveIp6DatagramCallback)(otMessage aMessage); + +/** + * This function registers a callback to provide received IPv6 datagrams. + * + * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received or NULL to disable + * the callback. + * + */ +void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback); + +/** + * This function sends an IPv6 datagram via the Thread interface. + * + * @param[in] aMessage A pointer to the message buffer containing the IPv6 datagram. + * + */ +ThreadError otSendIp6Datagram(otMessage aMessage); + /** * @} * diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index e2c3e6372..d5b2a0ebd 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -47,8 +47,7 @@ namespace Thread { namespace Ip6 { static Mpl sMpl; -static Ip6::NcpReceivedDatagramHandler sNcpReceivedHandler = NULL; -static void *sNcpReceivedHandlerContext = NULL; +static otReceiveIp6DatagramCallback sReceiveIp6DatagramCallback = NULL; static ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo); @@ -93,10 +92,9 @@ uint16_t Ip6::ComputePseudoheaderChecksum(const Address &src, const Address &dst return checksum; } -void Ip6::SetNcpReceivedHandler(NcpReceivedDatagramHandler handler, void *context) +void Ip6::SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback) { - sNcpReceivedHandler = handler; - sNcpReceivedHandlerContext = context; + sReceiveIp6DatagramCallback = aCallback; } ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength) @@ -307,7 +305,7 @@ exit: } ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, uint8_t interfaceId, const void *linkMessageInfo, - bool fromNcpHost) + bool fromLocalHost) { ThreadError error = kThreadError_Drop; MessageInfo messageInfo; @@ -387,9 +385,9 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, uint8_t interfac { SuccessOrExit(HandlePayload(message, messageInfo, nextHeader)); - if (sNcpReceivedHandler != NULL && fromNcpHost == false) + if (sReceiveIp6DatagramCallback != NULL && fromLocalHost == false) { - sNcpReceivedHandler(sNcpReceivedHandlerContext, message); + sReceiveIp6DatagramCallback(&message); ExitNow(error = kThreadError_None); } } diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index edd06e317..c309a1f06 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -563,22 +563,13 @@ public: uint16_t aLength, IpProto aProto); /** - * This function pointer is called when an IPv6 message is received. + * This function registers a callback to provide receivd raw IPv6 datagrams. * - * @param[in] aContext A pointer to arbitrary context information. - * @param[in] aMessage A reference to the IPv6 message. + * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received or NULL to disable + * the callback. * */ - typedef void (*NcpReceivedDatagramHandler)(void *aContext, Message &aMessage); - - /** - * This method sets the NCP receive handler. - * - * @param[in] aHandler A pointer to a function that is called when IPv6 messages are received. - * @param[in] aContext A pointer to arbitrary context information. - * - */ - static void SetNcpReceivedHandler(NcpReceivedDatagramHandler aHandler, void *aContext); + static void SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback); }; diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 2fe1ebafd..8f25f0b13 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -110,6 +110,18 @@ void otSetExtendedPanId(const uint8_t *aExtendedPanId) sThreadNetif->GetMle().SetMeshLocalPrefix(aExtendedPanId); } +ThreadError otGetLeaderRloc(otIp6Address *aAddress) +{ + ThreadError error; + + VerifyOrExit(aAddress != NULL, error = kThreadError_InvalidArgs); + + error = sThreadNetif->GetMle().GetLeaderAddress(*static_cast(aAddress)); + +exit: + return error; +} + otLinkModeConfig otGetLinkMode(void) { otLinkModeConfig config = {}; @@ -175,6 +187,45 @@ ThreadError otSetMasterKey(const uint8_t *aKey, uint8_t aKeyLength) return sThreadNetif->GetKeyManager().SetMasterKey(aKey, aKeyLength); } +const otIp6Address *otGetMeshLocalEid(void) +{ + return sThreadNetif->GetMle().GetMeshLocal64(); +} + +const uint8_t *otGetMeshLocalPrefix(void) +{ + return sThreadNetif->GetMle().GetMeshLocalPrefix(); +} + +ThreadError otSetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix) +{ + return sThreadNetif->GetMle().SetMeshLocalPrefix(aMeshLocalPrefix); +} + +ThreadError otGetNetworkDataLeader(bool aStable, uint8_t *aData, uint8_t *aDataLength) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs); + + sThreadNetif->GetNetworkDataLeader().GetNetworkData(aStable, aData, *aDataLength); + +exit: + return error; +} + +ThreadError otGetNetworkDataLocal(bool aStable, uint8_t *aData, uint8_t *aDataLength) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs); + + sThreadNetif->GetNetworkDataLocal().GetNetworkData(aStable, aData, *aDataLength); + +exit: + return error; +} + const char *otGetNetworkName(void) { return sThreadNetif->GetMac().GetNetworkName(); @@ -195,6 +246,11 @@ ThreadError otSetPanId(otPanId aPanId) return sThreadNetif->GetMac().SetPanId(aPanId); } +otShortAddress otGetShortAddress(void) +{ + return sThreadNetif->GetMac().GetShortAddress(); +} + uint8_t otGetLocalLeaderWeight(void) { return sThreadNetif->GetMle().GetLeaderWeight(); @@ -523,6 +579,17 @@ exit: return; } +void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback) +{ + Ip6::Ip6::SetReceiveDatagramCallback(aCallback); +} + +ThreadError otSendIp6Datagram(otMessage aMessage) +{ + return Ip6::Ip6::HandleDatagram(*static_cast(aMessage), NULL, sThreadNetif->GetInterfaceId(), + NULL, true); +} + otMessage otNewUdpMessage(void) { return Ip6::Udp::NewMessage(0); diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index fa60cb8f3..731edd534 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -97,6 +97,13 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mLinkLocal16.mPreferredLifetime = 0xffffffff; mLinkLocal16.mValidLifetime = 0xffffffff; + // initialize Mesh Local Prefix + mMeshLocal64.GetAddress().m8[0] = 0xfd; + memcpy(mMeshLocal64.GetAddress().m8 + 1, mMac.GetExtendedPanId(), 5); + mMeshLocal64.GetAddress().m8[6] = 0x00; + mMeshLocal64.GetAddress().m8[7] = 0x00; + SetMeshLocalPrefix(mMeshLocal64.GetAddress().m8); + // mesh-local 64 for (int i = 8; i < 16; i++) { @@ -128,8 +135,6 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mRealmLocalAllThreadNodes.GetAddress().m16[7] = HostSwap16(0x0001); mNetif.SubscribeMulticast(mRealmLocalAllThreadNodes); - SetMeshLocalPrefix(mMac.GetExtendedPanId()); - mNetif.RegisterHandler(mNetifHandler); } @@ -326,20 +331,16 @@ const uint8_t *Mle::GetMeshLocalPrefix(void) const return mMeshLocal16.GetAddress().m8; } -ThreadError Mle::SetMeshLocalPrefix(const uint8_t *aExtendedPanId) +ThreadError Mle::SetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix) { - mMeshLocal64.GetAddress().m8[0] = 0xfd; - memcpy(mMeshLocal64.GetAddress().m8 + 1, aExtendedPanId, 5); - mMeshLocal64.GetAddress().m8[6] = 0x00; - mMeshLocal64.GetAddress().m8[7] = 0x00; - - memcpy(&mMeshLocal16.GetAddress(), &mMeshLocal64.GetAddress(), 8); + memcpy(mMeshLocal64.GetAddress().m8, aMeshLocalPrefix, 8); + memcpy(mMeshLocal16.GetAddress().m8, mMeshLocal64.GetAddress().m8, 8); mLinkLocalAllThreadNodes.GetAddress().m8[3] = 64; - memcpy(mLinkLocalAllThreadNodes.GetAddress().m8 + 4, &mMeshLocal64.GetAddress(), 8); + memcpy(mLinkLocalAllThreadNodes.GetAddress().m8 + 4, mMeshLocal64.GetAddress().m8, 8); mRealmLocalAllThreadNodes.GetAddress().m8[3] = 64; - memcpy(mRealmLocalAllThreadNodes.GetAddress().m8 + 4, &mMeshLocal64.GetAddress(), 8); + memcpy(mRealmLocalAllThreadNodes.GetAddress().m8 + 4, mMeshLocal64.GetAddress().m8, 8); return kThreadError_None; } @@ -416,7 +417,7 @@ ThreadError Mle::GetLeaderAddress(Ip6::Address &aAddress) const { ThreadError error = kThreadError_None; - VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kThreadError_Error); + VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kThreadError_Detached); memcpy(&aAddress, &mMeshLocal16.GetAddress(), 8); aAddress.m16[4] = HostSwap16(0x0000); diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 2052c7ebf..92cea3abc 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -42,6 +42,8 @@ namespace Thread { extern ThreadNetif *sThreadNetif; +static NcpBase *sNcpContext = NULL; + // ---------------------------------------------------------------------------- // MARK: Command/Property Jump Tables // ---------------------------------------------------------------------------- @@ -228,20 +230,20 @@ NcpBase::NcpBase(): mSupportedChannelMask = (0xFFFF << 11); // Default to 2.4GHz 802.15.4 channels. mChannelMask = mSupportedChannelMask; mScanPeriod = 200; // ms + sNcpContext = this; assert(sThreadNetif != NULL); sThreadNetif->RegisterHandler(mNetifHandler); - Ip6::Ip6::SetNcpReceivedHandler(&HandleDatagramFromStack, this); + otSetReceiveIp6DatagramCallback(&HandleDatagramFromStack); } // ---------------------------------------------------------------------------- // MARK: Outbound Datagram Handling // ---------------------------------------------------------------------------- -void NcpBase::HandleDatagramFromStack(void *context, Message &message) +void NcpBase::HandleDatagramFromStack(otMessage message) { - NcpBase *obj = reinterpret_cast(context); - obj->HandleDatagramFromStack(message); + sNcpContext->HandleDatagramFromStack(*static_cast(message)); } void NcpBase::HandleDatagramFromStack(Message &message) @@ -1138,7 +1140,7 @@ void NcpBase::GetPropertyHandler_MAC_15_4_SADDR(uint8_t header, spinel_prop_key_ SPINEL_CMD_PROP_VALUE_IS, key, SPINEL_DATATYPE_UINT16_S, - sThreadNetif->GetMac().GetShortAddress() + otGetShortAddress() ); } @@ -1313,10 +1315,10 @@ void NcpBase::GetPropertyHandler_THREAD_NETWORK_DATA(uint8_t header, spinel_prop if (errorCode == kThreadError_None) { - sThreadNetif->GetNetworkDataLocal().GetNetworkData( + otGetNetworkDataLocal( false, // Stable? network_data, - network_data_len + &network_data_len ); errorCode = OutboundFrameFeedData(network_data, network_data_len); @@ -1346,10 +1348,10 @@ void NcpBase::GetPropertyHandler_THREAD_STABLE_NETWORK_DATA(uint8_t header, spin if (errorCode == kThreadError_None) { - sThreadNetif->GetNetworkDataLocal().GetNetworkData( + otGetNetworkDataLocal( true, // Stable? network_data, - network_data_len + &network_data_len ); errorCode = OutboundFrameFeedData(network_data, network_data_len); @@ -1402,8 +1404,8 @@ void NcpBase::GetPropertyHandler_THREAD_LEADER_WEIGHT(uint8_t header, spinel_pro void NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key) { ThreadError errorCode; - Ip6::Address address; - errorCode = sThreadNetif->GetMle().GetLeaderAddress(address); + otIp6Address address; + errorCode = otGetLeaderRloc(&address); if (errorCode == kThreadError_None) { @@ -1423,7 +1425,7 @@ void NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_ void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key) { - const uint8_t *ml_prefix = sThreadNetif->GetMle().GetMeshLocalPrefix(); + const uint8_t *ml_prefix = otGetMeshLocalPrefix(); if (ml_prefix) { @@ -1456,7 +1458,7 @@ void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ void NcpBase::GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key) { - const Ip6::Address *ml64 = sThreadNetif->GetMle().GetMeshLocal64(); + const otIp6Address *ml64 = otGetMeshLocalEid(); if (ml64) { @@ -2186,7 +2188,7 @@ void NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spinel_prop if (errorCode == kThreadError_None) { - errorCode = Ip6::Ip6::HandleDatagram(*message, NULL, sThreadNetif->GetInterfaceId(), NULL, true); + errorCode = otSendIp6Datagram(message); } if (errorCode == kThreadError_None) @@ -2244,7 +2246,7 @@ void NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_key_t ke if (errorCode == kThreadError_None) { - errorCode = Ip6::Ip6::HandleDatagram(*message, NULL, sThreadNetif->GetInterfaceId(), NULL, true); + errorCode = otSendIp6Datagram(message); } if (errorCode == kThreadError_None) @@ -2269,7 +2271,7 @@ void NcpBase::SetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_ if (value_len >= 8) { - errorCode = sThreadNetif->GetMle().SetMeshLocalPrefix(value_ptr); + errorCode = otSetMeshLocalPrefix(value_ptr); HandleCommandPropertyGet(header, key); } else diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 1b0175903..2ff05bc80 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -76,7 +76,7 @@ private: /** * Trampoline for HandleDatagramFromStack(). */ - static void HandleDatagramFromStack(void *context, Message &message); + static void HandleDatagramFromStack(otMessage message); void HandleDatagramFromStack(Message &message);