mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 17:39:51 +00:00
Support network diagnostic feature. (#652)
* support network diagnostic * add network diagnostic THCI implementation
This commit is contained in:
@@ -126,6 +126,9 @@ void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat
|
||||
case kLogRegionMeshCoP:
|
||||
LOG_PRINTF("MCOP ");
|
||||
break;
|
||||
|
||||
case kLogRegionNetDiag:
|
||||
LOG_PRINTF("NDG ");
|
||||
}
|
||||
|
||||
va_start(args, aFormat);
|
||||
|
||||
@@ -139,6 +139,8 @@ typedef enum ThreadError
|
||||
|
||||
#define OT_MASTER_KEY_SIZE 16 ///< Size of the Thread Master Key (bytes)
|
||||
|
||||
#define OT_NUM_NETDIAG_TLV_TYPES 18 ///< Number of Network Diagnostic TLV types
|
||||
|
||||
/**
|
||||
* This structure represents a Thread Master Key.
|
||||
*
|
||||
|
||||
@@ -2155,6 +2155,26 @@ ThreadError otBindUdpSocket(otUdpSocket *aSocket, otSockAddr *aSockName);
|
||||
*/
|
||||
ThreadError otSendUdp(otUdpSocket *aSocket, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
/**
|
||||
* Send a Network Diagnostic Get request
|
||||
*
|
||||
* @param[in] aDestination A pointer to destination address.
|
||||
* @param[in] aTlvTypes An array of Network Diagnostic TLV types.
|
||||
* @param[in] aCount Number of types in aTlvTypes
|
||||
*/
|
||||
ThreadError otSendDiagnosticGet(otInstance *aInstance, otIp6Address *aDestination, uint8_t aTlvTypes[], uint8_t aCount);
|
||||
|
||||
/**
|
||||
* Send a Network Diagnostic Reset request
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aDestination A pointer to destination address.
|
||||
* @param[in] aTlvTypes An array of Network Diagnostic TLV types. Currently only Type 9 is allowed.
|
||||
* @param[in] aCount Number of types in aTlvTypes
|
||||
*/
|
||||
ThreadError otSendDiagnosticReset(otInstance *aInstance, otIp6Address *aDestination, uint8_t aTlvTypes[],
|
||||
uint8_t aCount);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -87,6 +87,7 @@ typedef enum otLogRegion
|
||||
kLogRegionMem = 8, ///< Memory
|
||||
kLogRegionNcp = 9, ///< NCP
|
||||
kLogRegionMeshCoP = 10, ///< Mesh Commissioning Protocol
|
||||
kLogRegionNetDiag = 11, ///< Network Diagnostic
|
||||
} otLogRegion;
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,6 +103,7 @@ const struct Command Interpreter::sCommands[] =
|
||||
{ "masterkey", &Interpreter::ProcessMasterKey },
|
||||
{ "mode", &Interpreter::ProcessMode },
|
||||
{ "netdataregister", &Interpreter::ProcessNetworkDataRegister },
|
||||
{ "networkdiagnostic", &Interpreter::ProcessNetworkDiagnostic },
|
||||
{ "networkidtimeout", &Interpreter::ProcessNetworkIdTimeout },
|
||||
{ "networkname", &Interpreter::ProcessNetworkName },
|
||||
{ "panid", &Interpreter::ProcessPanId },
|
||||
@@ -2449,5 +2450,38 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Interpreter::ProcessNetworkDiagnostic(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct otIp6Address address;
|
||||
uint8_t index = 2;
|
||||
uint8_t tlvTypes[OT_NUM_NETDIAG_TLV_TYPES];
|
||||
uint8_t count = 0;
|
||||
|
||||
VerifyOrExit(argc > 1 + 1, error = kThreadError_Parse);
|
||||
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[1], &address));
|
||||
|
||||
while (index < argc && count < sizeof(tlvTypes))
|
||||
{
|
||||
long value;
|
||||
SuccessOrExit(error = ParseLong(argv[index], value));
|
||||
tlvTypes[count++] = static_cast<uint8_t>(value);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (strcmp(argv[0], "get") == 0)
|
||||
{
|
||||
otSendDiagnosticGet(mInstance, &address, tlvTypes, count);
|
||||
}
|
||||
else if (strcmp(argv[0], "reset") == 0)
|
||||
{
|
||||
otSendDiagnosticReset(mInstance, &address, tlvTypes, count);
|
||||
}
|
||||
|
||||
exit:
|
||||
AppendResult(error);
|
||||
}
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
@@ -175,6 +175,7 @@ private:
|
||||
void ProcessMasterKey(int argc, char *argv[]);
|
||||
void ProcessMode(int argc, char *argv[]);
|
||||
void ProcessNetworkDataRegister(int argc, char *argv[]);
|
||||
void ProcessNetworkDiagnostic(int argc, char *argv[]);
|
||||
void ProcessNetworkIdTimeout(int argc, char *argv[]);
|
||||
void ProcessNetworkName(int argc, char *argv[]);
|
||||
void ProcessPanId(int argc, char *argv[]);
|
||||
|
||||
@@ -79,6 +79,8 @@ libopenthread_a_SOURCES = \
|
||||
thread/network_data_local.cpp \
|
||||
thread/network_data_leader.cpp \
|
||||
thread/panid_query_server.cpp \
|
||||
thread/network_diag.cpp \
|
||||
thread/network_diag_tlvs.cpp \
|
||||
thread/thread_netif.cpp \
|
||||
thread/thread_tlvs.cpp \
|
||||
$(NULL)
|
||||
@@ -163,6 +165,8 @@ noinst_HEADERS = \
|
||||
thread/network_data_local.hpp \
|
||||
thread/network_data_tlvs.hpp \
|
||||
thread/panid_query_server.hpp \
|
||||
thread/network_diag.hpp \
|
||||
thread/network_diag_tlvs.hpp \
|
||||
thread/thread_netif.hpp \
|
||||
thread/thread_tlvs.hpp \
|
||||
thread/thread_uris.hpp \
|
||||
|
||||
@@ -1021,6 +1021,57 @@ extern "C" {
|
||||
#define otDumpDebgMem(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritNetDiag
|
||||
*
|
||||
* This method generates a log with level critical for the NETDIAG region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnNetDiag
|
||||
*
|
||||
* This method generates a log with level warning for the NETDIAG region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoNetDiag
|
||||
*
|
||||
* This method generates a log with level info for the NETDIAG region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgNetDiag
|
||||
*
|
||||
* This method generates a log with level debug for the NETDIAG region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_NETDIAG
|
||||
#define otLogCritNetDiag(aFormat, ...) otLogCrit(kLogRegionNetDiag, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnNetDiag(aFormat, ...) otLogWarn(kLogRegionNetDiag, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoNetDiag(aFormat, ...) otLogInfo(kLogRegionNetDiag, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgNetDiag(aFormat, ...) otLogDebg(kLogRegionNetDiag, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritNetDiag(aFormat, ...)
|
||||
#define otLogWarnNetDiag(aFormat, ...)
|
||||
#define otLogInfoNetDiag(aFormat, ...)
|
||||
#define otLogDebgNetDiag(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method dumps bytes to the log in a human-readable fashion.
|
||||
*
|
||||
|
||||
@@ -249,5 +249,14 @@
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_MEM
|
||||
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_NETDIAG
|
||||
*
|
||||
* Define to enable network diagnostic logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_NETDIAG
|
||||
|
||||
#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_
|
||||
|
||||
|
||||
@@ -957,6 +957,21 @@ exit:
|
||||
|
||||
#endif
|
||||
|
||||
ThreadError otSendDiagnosticGet(otInstance *aInstance, otIp6Address *aDestination, uint8_t aTlvTypes[], uint8_t aCount)
|
||||
{
|
||||
(void)aInstance;
|
||||
return sThreadNetif->GetNetworkDiagnostic().SendDiagnosticGet(*static_cast<Ip6::Address *>(aDestination), aTlvTypes,
|
||||
aCount);
|
||||
}
|
||||
|
||||
ThreadError otSendDiagnosticReset(otInstance *aInstance, otIp6Address *aDestination, uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
(void)aInstance;
|
||||
return sThreadNetif->GetNetworkDiagnostic().SendDiagnosticReset(*static_cast<Ip6::Address *>(aDestination), aTlvTypes,
|
||||
aCount);
|
||||
}
|
||||
|
||||
void otInstanceFinalize(otInstance *aInstance)
|
||||
{
|
||||
// Ensure we are disabled
|
||||
|
||||
@@ -792,15 +792,20 @@ ThreadError Mle::AppendLeaderData(Message &aMessage)
|
||||
return aMessage.Append(&mLeaderData, sizeof(mLeaderData));
|
||||
}
|
||||
|
||||
void Mle::FillNetworkDataTlv(NetworkDataTlv &aTlv, bool aStableOnly)
|
||||
{
|
||||
uint8_t length;
|
||||
mNetworkData.GetNetworkData(aStableOnly, aTlv.GetNetworkData(), length);
|
||||
aTlv.SetLength(length);
|
||||
}
|
||||
|
||||
ThreadError Mle::AppendNetworkData(Message &aMessage, bool aStableOnly)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
NetworkDataTlv tlv;
|
||||
uint8_t length;
|
||||
|
||||
tlv.Init();
|
||||
mNetworkData.GetNetworkData(aStableOnly, tlv.GetNetworkData(), length);
|
||||
tlv.SetLength(length);
|
||||
FillNetworkDataTlv(tlv, aStableOnly);
|
||||
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(Tlv) + tlv.GetLength()));
|
||||
|
||||
|
||||
@@ -662,6 +662,15 @@ public:
|
||||
*/
|
||||
static bool IsActiveRouter(uint16_t aRloc16) { return GetChildId(aRloc16) == 0; }
|
||||
|
||||
/**
|
||||
* This method fills the NetworkDataTlv.
|
||||
*
|
||||
* @param[out] aTlv The NetworkDataTlv.
|
||||
* @param[in] aStableOnly TRUE to append stable data, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void FillNetworkDataTlv(NetworkDataTlv &aTlv, bool aStableOnly);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This method appends an MLE header to a message.
|
||||
|
||||
@@ -3295,16 +3295,13 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError MleRouter::AppendConnectivity(Message &aMessage)
|
||||
void MleRouter::FillConnectivityTlv(ConnectivityTlv &aTlv)
|
||||
{
|
||||
ThreadError error;
|
||||
ConnectivityTlv tlv;
|
||||
ConnectivityTlv &tlv = aTlv;
|
||||
uint8_t cost;
|
||||
uint8_t lqi;
|
||||
uint8_t numChildren = 0;
|
||||
|
||||
tlv.Init();
|
||||
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
if (mChildren[i].mState == Neighbor::kStateValid)
|
||||
@@ -3405,6 +3402,15 @@ ThreadError MleRouter::AppendConnectivity(Message &aMessage)
|
||||
tlv.SetIdSequence(mRouterIdSequence);
|
||||
tlv.SetSedBufferSize(1280);
|
||||
tlv.SetSedDatagramCount(1);
|
||||
}
|
||||
|
||||
ThreadError MleRouter::AppendConnectivity(Message &aMessage)
|
||||
{
|
||||
ThreadError error;
|
||||
ConnectivityTlv tlv;
|
||||
|
||||
tlv.Init();
|
||||
FillConnectivityTlv(tlv);
|
||||
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
|
||||
|
||||
@@ -3455,14 +3461,11 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::AppendRoute(Message &aMessage)
|
||||
void MleRouter::FillRouteTlv(RouteTlv &tlv)
|
||||
{
|
||||
ThreadError error;
|
||||
RouteTlv tlv;
|
||||
uint8_t routeCount = 0;
|
||||
uint8_t cost;
|
||||
|
||||
tlv.Init();
|
||||
tlv.SetRouterIdSequence(mRouterIdSequence);
|
||||
tlv.ClearRouterIdMask();
|
||||
|
||||
@@ -3515,8 +3518,15 @@ ThreadError MleRouter::AppendRoute(Message &aMessage)
|
||||
}
|
||||
|
||||
tlv.SetRouteDataLength(routeCount);
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(Tlv) + tlv.GetLength()));
|
||||
}
|
||||
|
||||
ThreadError MleRouter::AppendRoute(Message &aMessage)
|
||||
{
|
||||
ThreadError error;
|
||||
RouteTlv tlv;
|
||||
tlv.Init();
|
||||
FillRouteTlv(tlv);
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(Tlv) + tlv.GetLength()));
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -481,6 +481,22 @@ public:
|
||||
*/
|
||||
static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
|
||||
|
||||
/**
|
||||
* This method fills an ConnectivityTlv.
|
||||
*
|
||||
* @param[out] aTlv A reference to the tlv to be filled.
|
||||
*
|
||||
*/
|
||||
void FillConnectivityTlv(ConnectivityTlv &aTlv);
|
||||
|
||||
/**
|
||||
* This method fills an RouteTlv.
|
||||
*
|
||||
* @param[out] aTlv A reference to the tlv to be filled.
|
||||
*
|
||||
*/
|
||||
void FillRouteTlv(RouteTlv &aTlv);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements Thread's Network Diagnostic processing.
|
||||
*/
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <net/netif.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <thread/mesh_forwarder.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_tlvs.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
#include <thread/network_diag.hpp>
|
||||
#include <thread/network_diag_tlvs.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
namespace NetworkDiagnostic {
|
||||
|
||||
NetworkDiagnostic::NetworkDiagnostic(ThreadNetif &aThreadNetif) :
|
||||
mDiagnosticGet(OPENTHREAD_URI_DIAGNOSTIC_GET, &HandleDiagnosticGet, this),
|
||||
mDiagnosticReset(OPENTHREAD_URI_DIAGNOSTIC_RESET, &HandleDiagnosticReset, this),
|
||||
mSocket(aThreadNetif.GetIp6().mUdp),
|
||||
mCoapServer(aThreadNetif.GetCoapServer()),
|
||||
mMle(aThreadNetif.GetMle()),
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
mCoapServer.AddResource(mDiagnosticGet);
|
||||
mCoapServer.AddResource(mDiagnosticReset);
|
||||
mCoapMessageId = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
ThreadError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestination, uint8_t aTlvTypes[], uint8_t aCount)
|
||||
{
|
||||
ThreadError error;
|
||||
Ip6::SockAddr sockaddr;
|
||||
Message *message;
|
||||
Coap::Header header;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
sockaddr.mPort = kCoapUdpPort;
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
mSocket.Bind(sockaddr);
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
header.Init();
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodeGet);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(mCoapToken, sizeof(mCoapToken));
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_DIAGNOSTIC_GET);
|
||||
header.Finalize();
|
||||
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
SuccessOrExit(error = message->Append(aTlvTypes, aCount));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr() = aDestination;
|
||||
messageInfo.GetSockAddr() = *mMle.GetMeshLocal16();
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoNetDiag("Sent diagnostic get\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
NetworkDiagnostic *obj = static_cast<NetworkDiagnostic *>(aContext);
|
||||
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Coap::Header header;
|
||||
|
||||
SuccessOrExit(header.FromMessage(aMessage));
|
||||
VerifyOrExit(header.GetType() == Coap::Header::kTypeAcknowledgment &&
|
||||
header.GetCode() == Coap::Header::kCodeChanged &&
|
||||
header.GetMessageId() == mCoapMessageId &&
|
||||
header.GetTokenLength() == sizeof(mCoapToken) &&
|
||||
memcmp(mCoapToken, header.GetToken(), sizeof(mCoapToken)) == 0, ;);
|
||||
|
||||
otLogInfoNetDiag("Network Diagnostic message acknowledged\n");
|
||||
|
||||
exit:
|
||||
(void)aMessageInfo;
|
||||
}
|
||||
|
||||
ThreadError NetworkDiagnostic::SendDiagnosticReset(const Ip6::Address &aDestination, uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
ThreadError error;
|
||||
Ip6::SockAddr sockaddr;
|
||||
Message *message;
|
||||
Coap::Header header;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
sockaddr.mPort = kCoapUdpPort;
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
mSocket.Bind(sockaddr);
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
header.Init();
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(mCoapToken, sizeof(mCoapToken));
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_DIAGNOSTIC_RESET);
|
||||
header.Finalize();
|
||||
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
SuccessOrExit(error = message->Append(aTlvTypes, aCount));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr() = aDestination;
|
||||
messageInfo.GetSockAddr() = *mMle.GetMeshLocal16();
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoNetDiag("Sent network diagnostic reset\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleDiagnosticGet(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
NetworkDiagnostic *obj = reinterpret_cast<NetworkDiagnostic *>(aContext);
|
||||
obj->HandleDiagnosticGet(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
ThreadError NetworkDiagnostic::AppendIPv6AddressList(Message &aMessage)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
IPv6AddressListTlv tlv;
|
||||
uint8_t count = 0;
|
||||
|
||||
tlv.Init();
|
||||
|
||||
for (const Ip6::NetifUnicastAddress *addr = mNetif.GetUnicastAddresses(); addr; addr = addr->GetNext())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
tlv.SetLength(count * sizeof(Ip6::Address));
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
|
||||
|
||||
for (const Ip6::NetifUnicastAddress *addr = mNetif.GetUnicastAddresses(); addr; addr = addr->GetNext())
|
||||
{
|
||||
SuccessOrExit(error = aMessage.Append(&addr->GetAddress(), sizeof(Ip6::Address)));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError NetworkDiagnostic::AppendChildTable(Message &aMessage)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t numChildren;
|
||||
const Child *children = mMle.GetChildren(&numChildren);
|
||||
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
for (int i = 0; i < numChildren; i++)
|
||||
{
|
||||
if (children[i].mState != Neighbor::kStateInvalid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
ChildTableTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetLength(count * sizeof(ChildTableEntry));
|
||||
|
||||
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(ChildTableTlv)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numChildren; i++)
|
||||
{
|
||||
if (children[i].mState != Neighbor::kStateInvalid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Child &child = children[i];
|
||||
ChildTableEntry entry;
|
||||
uint8_t timeout = 0;
|
||||
|
||||
while (static_cast<uint32_t>(1 << timeout) < child.mTimeout) { timeout++; }
|
||||
|
||||
entry.SetTimeout(timeout + 4);
|
||||
entry.SetChildId(child.mValid.mRloc16);
|
||||
entry.SetMode(child.mMode);
|
||||
|
||||
SuccessOrExit(error = aMessage.Append(&entry, sizeof(ChildTableEntry)));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleDiagnosticGet(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
uint8_t tlvTypeSet[kNumTlvTypes];
|
||||
uint16_t numTlvTypes;
|
||||
ThreadError error = kThreadError_None;
|
||||
Message *message = NULL;
|
||||
Coap::Header header;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeConfirmable &&
|
||||
aHeader.GetCode() == Coap::Header::kCodeGet, error = kThreadError_Drop);
|
||||
|
||||
otLogInfoNetDiag("Received diagnostic get request\n");
|
||||
|
||||
header.Init();
|
||||
header.SetType(Coap::Header::kTypeAcknowledgment);
|
||||
header.SetCode(Coap::Header::kCodeChanged);
|
||||
header.SetMessageId(aHeader.GetMessageId());
|
||||
header.SetToken(aHeader.GetToken(), aHeader.GetTokenLength());
|
||||
header.Finalize();
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
numTlvTypes = aMessage.Read(aMessage.GetOffset(), kNumTlvTypes, tlvTypeSet);
|
||||
|
||||
for (uint8_t i = 0; i < numTlvTypes; i++)
|
||||
{
|
||||
otLogInfoNetDiag("Received diagnostic get type %d\n", tlvTypeSet[i]);
|
||||
|
||||
switch (tlvTypeSet[i])
|
||||
{
|
||||
case NetworkDiagnosticTlv::kExtMacAddress:
|
||||
{
|
||||
ExtMacAddressTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetMacAddr(*mNetif.GetMac().GetExtAddress());
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kAddress16:
|
||||
{
|
||||
Address16Tlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetRloc16(mMle.GetRloc16());
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kMode:
|
||||
{
|
||||
ModeTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetMode(mMle.GetDeviceMode());
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kTimeout:
|
||||
{
|
||||
if ((mMle.GetDeviceMode() & ModeTlv::kModeRxOnWhenIdle) == 0)
|
||||
{
|
||||
TimeoutTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetTimeout(mMle.GetTimeout());
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kConnectivity:
|
||||
{
|
||||
ConnectivityTlv tlv;
|
||||
tlv.Init();
|
||||
mMle.FillConnectivityTlv(*reinterpret_cast<Mle::ConnectivityTlv *>(&tlv));
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kRoute:
|
||||
{
|
||||
RouteTlv tlv;
|
||||
tlv.Init();
|
||||
mMle.FillRouteTlv(*reinterpret_cast<Mle::RouteTlv *>(&tlv));
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kLeaderData:
|
||||
{
|
||||
LeaderDataTlv tlv;
|
||||
memcpy(&tlv, &mMle.GetLeaderDataTlv(), sizeof(tlv));
|
||||
tlv.Init();
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kNetworkData:
|
||||
{
|
||||
NetworkDataTlv tlv;
|
||||
tlv.Init();
|
||||
mMle.FillNetworkDataTlv((*reinterpret_cast<Mle::NetworkDataTlv *>(&tlv)), true);
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kIPv6AddressList:
|
||||
{
|
||||
SuccessOrExit(error = AppendIPv6AddressList(*message));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kMacCounters:
|
||||
{
|
||||
MacCountersTlv tlv;
|
||||
memset(&tlv, 0, sizeof(tlv));
|
||||
tlv.Init();
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kBatteryLevel:
|
||||
{
|
||||
// TODO Need more api from driver
|
||||
BatteryLevelTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetBatteryLevel(100);
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kSupplyVoltage:
|
||||
{
|
||||
// TODO Need more api from driver
|
||||
SupplyVoltageTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetSupplyVoltage(0);
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kChildTable:
|
||||
{
|
||||
SuccessOrExit(error = AppendChildTable(*message));
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kChannelPages:
|
||||
{
|
||||
ChannelPagesTlv tlv;
|
||||
tlv.Init();
|
||||
tlv.GetChannelPages()[0] = 0;
|
||||
tlv.SetLength(1);
|
||||
SuccessOrExit(error = message->Append(&tlv, tlv.GetSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&messageInfo, &aMessageInfo, sizeof(messageInfo));
|
||||
memset(&messageInfo.mSockAddr, 0, sizeof(messageInfo.mSockAddr));
|
||||
otLogInfoNetDiag("Sending diagnostic get acknowledgment\n");
|
||||
SuccessOrExit(error = mCoapServer.SendMessage(*message, messageInfo));
|
||||
|
||||
otLogInfoNetDiag("Sent diagnostic get acknowledgment\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleDiagnosticReset(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
NetworkDiagnostic *obj = reinterpret_cast<NetworkDiagnostic *>(aContext);
|
||||
obj->HandleDiagnosticReset(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void NetworkDiagnostic::HandleDiagnosticReset(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t tlvTypeSet[kNumResetTlvTypes];
|
||||
uint16_t numTlvTypes;
|
||||
Message *message = NULL;
|
||||
Coap::Header header;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
otLogInfoNetDiag("Received diagnostic reset request\n");
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeConfirmable &&
|
||||
aHeader.GetCode() == Coap::Header::kCodePost, error = kThreadError_Drop);
|
||||
|
||||
otLogInfoNetDiag("Received diagnostic reset request\n");
|
||||
numTlvTypes = aMessage.Read(aMessage.GetOffset(), kNumResetTlvTypes, tlvTypeSet);
|
||||
|
||||
otLogInfoNetDiag("Received diagnostic reset request\n");
|
||||
|
||||
for (uint8_t i = 0; i < numTlvTypes; i++)
|
||||
{
|
||||
switch (tlvTypeSet[i])
|
||||
{
|
||||
case NetworkDiagnosticTlv::kMacCounters:
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
otLogInfoNetDiag("Received diagnostic reset request\n");
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
otLogInfoNetDiag("Received diagnostic reset request\n");
|
||||
header.Init();
|
||||
header.SetType(Coap::Header::kTypeAcknowledgment);
|
||||
header.SetCode(Coap::Header::kCodeChanged);
|
||||
header.SetMessageId(aHeader.GetMessageId());
|
||||
header.SetToken(aHeader.GetToken(), aHeader.GetTokenLength());
|
||||
header.Finalize();
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
memcpy(&messageInfo, &aMessageInfo, sizeof(messageInfo));
|
||||
memset(&messageInfo.mSockAddr, 0, sizeof(messageInfo.mSockAddr));
|
||||
|
||||
SuccessOrExit(error = mCoapServer.SendMessage(*message, messageInfo));
|
||||
|
||||
otLogInfoNetDiag("Sent diagnostic reset acknowledgment\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace NetworkDiagnostic
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for handle network diagnostic.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_DIAGNOSTIC_HPP_
|
||||
#define NETWORK_DIAGNOSTIC_HPP_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread-types.h>
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class ThreadNetif;
|
||||
using namespace Coap;
|
||||
|
||||
namespace NetworkDiagnostic {
|
||||
|
||||
class IPv6AddressListTlv;
|
||||
class ChildTableTlv;
|
||||
|
||||
/**
|
||||
* @addtogroup core-netdiag
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for sending and handling Network Diagnostic Commands.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements the Network Diagnostic processing.
|
||||
*
|
||||
*/
|
||||
class NetworkDiagnostic
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
explicit NetworkDiagnostic(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method sends Diagnostic Get request.
|
||||
*
|
||||
* @param[in] aDestination A reference to the destination address.
|
||||
* @param[in] aTlvTypes An array of Network Diagnostic TLV types.
|
||||
* @param[in] aCount Number of types in aTlvTypes
|
||||
*
|
||||
*/
|
||||
ThreadError SendDiagnosticGet(const Ip6::Address &aDestination, uint8_t aTlvTypes[], uint8_t aCount);
|
||||
|
||||
/**
|
||||
* This method sends Diagnostic Reset request.
|
||||
*
|
||||
* @param[in] aDestination A reference to the destination address.
|
||||
* @param[in] aTlvTypes An array of Network Diagnostic TLV types.
|
||||
* @param[in] aCount Number of types in aTlvTypes
|
||||
*
|
||||
*/
|
||||
ThreadError SendDiagnosticReset(const Ip6::Address &aDestination, uint8_t aTlvTypes[], uint8_t aCount);
|
||||
|
||||
/**
|
||||
* This method fills IPv6AddressListTlv.
|
||||
*
|
||||
* @param[out] aTlv A reference to the tlv.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendIPv6AddressList(Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method fills ChildTableTlv.
|
||||
*
|
||||
* @param[out] aTlv A reference to the tlv.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendChildTable(Message &aMessage);
|
||||
|
||||
private:
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleDiagnosticGet(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleDiagnosticGet(Thread::Coap::Header &aHeader, Thread::Message &aMessage,
|
||||
const Thread::Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleDiagnosticReset(void *aContext, Thread::Coap::Header &aHeader, Thread::Message &,
|
||||
const Thread::Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleDiagnosticReset(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
Coap::Resource mDiagnosticGet;
|
||||
Coap::Resource mDiagnosticReset;
|
||||
Ip6::UdpSocket mSocket;
|
||||
|
||||
uint8_t mCoapToken[2];
|
||||
uint16_t mCoapMessageId;
|
||||
Coap::Server &mCoapServer;
|
||||
Mle::MleRouter &mMle;
|
||||
ThreadNetif &mNetif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
} // namespace NetworkDiagnostic
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NETWORK_DIAGNOSTIC_HPP_
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements common methods for manipulating Network Diagnostic TLVs.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <thread/network_diag_tlvs.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace NetworkDiagnostic {
|
||||
|
||||
ThreadError NetworkDiagnosticTlv::GetTlv(const Message &aMessage, Type aType, uint16_t aMaxLength,
|
||||
NetworkDiagnosticTlv &aTlv)
|
||||
{
|
||||
ThreadError error = kThreadError_Parse;
|
||||
uint16_t offset;
|
||||
|
||||
SuccessOrExit(error = GetOffset(aMessage, aType, offset));
|
||||
aMessage.Read(offset, sizeof(NetworkDiagnosticTlv), &aTlv);
|
||||
|
||||
if (aMaxLength > sizeof(aTlv) + aTlv.GetLength())
|
||||
{
|
||||
aMaxLength = sizeof(aTlv) + aTlv.GetLength();
|
||||
}
|
||||
|
||||
aMessage.Read(offset, aMaxLength, &aTlv);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError NetworkDiagnosticTlv::GetOffset(const Message &aMessage, Type aType, uint16_t &aOffset)
|
||||
{
|
||||
ThreadError error = kThreadError_Parse;
|
||||
uint16_t offset = aMessage.GetOffset();
|
||||
uint16_t end = aMessage.GetLength();
|
||||
NetworkDiagnosticTlv tlv;
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
aMessage.Read(offset, sizeof(NetworkDiagnosticTlv), &tlv);
|
||||
|
||||
if (tlv.GetType() == aType && (offset + sizeof(tlv) + tlv.GetLength()) <= end)
|
||||
{
|
||||
aOffset = offset;
|
||||
ExitNow(error = kThreadError_None);
|
||||
}
|
||||
|
||||
offset += sizeof(tlv) + tlv.GetLength();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace NetworkDiagnostic
|
||||
} // namespace Thread
|
||||
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,7 @@ ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6):
|
||||
mMleRouter(*this),
|
||||
mNetworkDataLocal(*this),
|
||||
mNetworkDataLeader(*this),
|
||||
mNetworkDiagnostic(*this),
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
mCommissioner(*this),
|
||||
#endif // OPENTHREAD_ENABLE_COMMISSIONER
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <net/netif.hpp>
|
||||
#include <thread/address_resolver.hpp>
|
||||
#include <thread/energy_scan_server.hpp>
|
||||
#include <thread/network_diag.hpp>
|
||||
#include <thread/key_manager.hpp>
|
||||
#include <thread/meshcop_dataset_manager.hpp>
|
||||
#include <thread/mesh_forwarder.hpp>
|
||||
@@ -159,6 +160,14 @@ public:
|
||||
*/
|
||||
AddressResolver &GetAddressResolver(void) { return mAddressResolver; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the network diagnostic object.
|
||||
*
|
||||
* @returns A reference to the address resolver object.
|
||||
*
|
||||
*/
|
||||
NetworkDiagnostic::NetworkDiagnostic &GetNetworkDiagnostic(void) { return mNetworkDiagnostic; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the coap server object.
|
||||
*
|
||||
@@ -262,6 +271,7 @@ private:
|
||||
Mle::MleRouter mMleRouter;
|
||||
NetworkData::Local mNetworkDataLocal;
|
||||
NetworkData::Leader mNetworkDataLeader;
|
||||
NetworkDiagnostic::NetworkDiagnostic mNetworkDiagnostic;
|
||||
bool mIsUp;
|
||||
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
|
||||
@@ -210,6 +210,22 @@ namespace Thread {
|
||||
*/
|
||||
#define OPENTHREAD_URI_COMMISSIONER_SET "c/cs"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_URI_DIAGNOSTIC_GET
|
||||
*
|
||||
* The URI Path for Network Diagnostic Get.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_URI_DIAGNOSTIC_GET "d/dg"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_URI_DIAG_RST
|
||||
*
|
||||
* The URI Path for Network Diagnostic Reset.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_URI_DIAGNOSTIC_RESET "d/dr"
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // THREAD_URIS_HPP_
|
||||
|
||||
@@ -1570,11 +1570,29 @@ class ARM(IThci):
|
||||
def setSleepyNodePollTime(self):
|
||||
pass
|
||||
|
||||
def diagnosticGet(self, strDestinationAddr, TLV_ids=0):
|
||||
pass
|
||||
def diagnosticGet(self, strDestinationAddr, listTLV_ids=[]):
|
||||
if not listTLV_ids:
|
||||
return
|
||||
|
||||
def diagnosticReset(self, strDestinationAddr, iTLV_id):
|
||||
pass
|
||||
if not len(listTLV_ids):
|
||||
return
|
||||
|
||||
cmd = 'networkdiagnostic get %s %s' % (strDestinationAddr, ' '.join([str(tlv) for tlv in listTLV_ids]))
|
||||
print(cmd)
|
||||
|
||||
return self.__sendCommand(cmd)
|
||||
|
||||
def diagnosticReset(self, strDestinationAddr, listTLV_ids=[]):
|
||||
if not listTLV_ids:
|
||||
return
|
||||
|
||||
if not len(listTLV_ids):
|
||||
return
|
||||
|
||||
cmd = 'networkdiagnostic reset %s %s' % (strDestinationAddr, ' '.join([str(tlv) for tlv in listTLV_ids]))
|
||||
print(cmd)
|
||||
|
||||
return self.__sendCommand(cmd)
|
||||
|
||||
def startNativeCommissioner(self, strPSKc='GRLpassWord'):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user