mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 10:27:49 +00:00
[network-diagnostic] improve usability of Network Diagnostic API (#4619)
This commit improves usability of Network Diagnostic API by: - Define native structures to represent various Network Diagnostic TLV values. - Add facility function otThreadGetNextDiagnosticTlv to parse plain otMessage into structured data. - Dump parsed DIAG_GET.ans/.rsp message in readable format for networkdiagnostic CLI command.
This commit is contained in:
@@ -148,6 +148,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/api/logging_api.cpp \
|
||||
src/core/api/message_api.cpp \
|
||||
src/core/api/netdata_api.cpp \
|
||||
src/core/api/netdiag_api.cpp \
|
||||
src/core/api/random_crypto_api.cpp \
|
||||
src/core/api/random_noncrypto_api.cpp \
|
||||
src/core/api/server_api.cpp \
|
||||
|
||||
@@ -71,6 +71,7 @@ openthread_headers = \
|
||||
message.h \
|
||||
ncp.h \
|
||||
netdata.h \
|
||||
netdiag.h \
|
||||
network_time.h \
|
||||
random_crypto.h \
|
||||
random_noncrypto.h \
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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
|
||||
* @brief
|
||||
* This file defines the OpenThread Network Diagnostic API.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_NETDIAG_H_
|
||||
#define OPENTHREAD_NETDIAG_H_
|
||||
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/thread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-thread-general
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maximum Number of Network Diagnostic TLV Types to Request or Reset.
|
||||
*/
|
||||
#define OT_NETWORK_DIAGNOSTIC_TYPELIST_MAX_ENTRIES 19
|
||||
|
||||
/**
|
||||
* Size of Network Diagnostic Child Table entry.
|
||||
*/
|
||||
#define OT_NETWORK_DIAGNOSTIC_CHILD_TABLE_ENTRY_SIZE 3
|
||||
|
||||
/**
|
||||
* Initializer for otNetworkDiagIterator.
|
||||
*/
|
||||
#define OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT 0
|
||||
|
||||
enum
|
||||
{
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS = 0, ///< MAC Extended Address TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS = 1, ///< Address16 TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_MODE = 2, ///< Mode TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT = 3, ///< Timeout TLV (the maximum polling time period for SEDs)
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY = 4, ///< Connectivity TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_ROUTE = 5, ///< Route64 TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA = 6, ///< Leader Data TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA = 7, ///< Network Data TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST = 8, ///< IPv6 Address List TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS = 9, ///< MAC Counters TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL = 14, ///< Battery Level TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE = 15, ///< Supply Voltage TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE = 16, ///< Child Table TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES = 17, ///< Channel Pages TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST = 18, ///< Type List TLV
|
||||
OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT = 19, ///< Max Child Timeout TLV
|
||||
};
|
||||
|
||||
typedef uint16_t otNetworkDiagIterator; ///< Used to iterate through Network Diagnostic TLV.
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic Connectivity value.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagConnectivity
|
||||
{
|
||||
/**
|
||||
* The priority of the sender as a parent.
|
||||
*/
|
||||
int8_t mParentPriority;
|
||||
|
||||
/**
|
||||
* The number of neighboring devices with which the sender shares a link of quality 3.
|
||||
*/
|
||||
uint8_t mLinkQuality3;
|
||||
|
||||
/**
|
||||
* The number of neighboring devices with which the sender shares a link of quality 2.
|
||||
*/
|
||||
uint8_t mLinkQuality2;
|
||||
|
||||
/**
|
||||
* The number of neighboring devices with which the sender shares a link of quality 1.
|
||||
*/
|
||||
uint8_t mLinkQuality1;
|
||||
|
||||
/**
|
||||
* The sender's routing cost to the Leader.
|
||||
*/
|
||||
uint8_t mLeaderCost;
|
||||
|
||||
/**
|
||||
* The most recent ID sequence number received by the sender.
|
||||
*/
|
||||
uint8_t mIdSequence;
|
||||
|
||||
/**
|
||||
* The number of active Routers in the sender's Thread Network Partition.
|
||||
*/
|
||||
uint8_t mActiveRouters;
|
||||
|
||||
/**
|
||||
* The guaranteed buffer capacity in octets for all IPv6 datagrams destined to a given SED. Optional.
|
||||
*/
|
||||
uint16_t mSedBufferSize;
|
||||
|
||||
/**
|
||||
* The guaranteed queue capacity in number of IPv6 datagrams destined to a given SED. Optional.
|
||||
*/
|
||||
uint8_t mSedDatagramCount;
|
||||
} otNetworkDiagConnectivity;
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic Route data.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagRouteData
|
||||
{
|
||||
uint8_t mRouterId; ///< The Assigned Router ID.
|
||||
uint8_t mLinkQualityOut : 2; ///< Link Quality Out.
|
||||
uint8_t mLinkQualityIn : 2; ///< Link Quality In.
|
||||
uint8_t mRouteCost : 4; ///< Routing Cost. Infinite routing cost is represented by value 0.
|
||||
} otNetworkDiagRouteData;
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic Route TLV value.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagRoute
|
||||
{
|
||||
/**
|
||||
* The sequence number associated with the set of Router ID assignments in #mRouteData.
|
||||
*/
|
||||
uint8_t mIdSequence;
|
||||
|
||||
/**
|
||||
* Number of elements in #mRouteData.
|
||||
*/
|
||||
uint8_t mRouteCount;
|
||||
|
||||
/**
|
||||
* Link Quality and Routing Cost data.
|
||||
*/
|
||||
otNetworkDiagRouteData mRouteData[OT_NETWORK_MAX_ROUTER_ID + 1];
|
||||
} otNetworkDiagRoute;
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic Mac Counters value.
|
||||
*
|
||||
* See <a href="https://www.ietf.org/rfc/rfc2863">RFC 2863</a> for definitions of member fields.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagMacCounters
|
||||
{
|
||||
uint32_t mIfInUnknownProtos;
|
||||
uint32_t mIfInErrors;
|
||||
uint32_t mIfOutErrors;
|
||||
uint32_t mIfInUcastPkts;
|
||||
uint32_t mIfInBroadcastPkts;
|
||||
uint32_t mIfInDiscards;
|
||||
uint32_t mIfOutUcastPkts;
|
||||
uint32_t mIfOutBroadcastPkts;
|
||||
uint32_t mIfOutDiscards;
|
||||
} otNetworkDiagMacCounters;
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic Child Table Entry.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagChildEntry
|
||||
{
|
||||
/**
|
||||
* Expected poll time expressed as 2^(Timeout-4) seconds.
|
||||
*/
|
||||
uint16_t mTimeout : 5;
|
||||
|
||||
/**
|
||||
* Child ID from which an RLOC can be generated.
|
||||
*/
|
||||
uint16_t mChildId : 9;
|
||||
|
||||
/**
|
||||
* Link mode bits.
|
||||
*/
|
||||
otLinkModeConfig mMode;
|
||||
} otNetworkDiagChildEntry;
|
||||
|
||||
/**
|
||||
* This structure represents a Network Diagnostic TLV.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetworkDiagTlv
|
||||
{
|
||||
/**
|
||||
* The Network Diagnostic TLV type.
|
||||
*/
|
||||
uint8_t mType;
|
||||
|
||||
union
|
||||
{
|
||||
otExtAddress mExtAddress;
|
||||
uint16_t mAddr16;
|
||||
otLinkModeConfig mMode;
|
||||
uint32_t mTimeout;
|
||||
otNetworkDiagConnectivity mConnectivity;
|
||||
otNetworkDiagRoute mRoute;
|
||||
otLeaderData mLeaderData;
|
||||
otNetworkDiagMacCounters mMacCounters;
|
||||
uint8_t mBatteryLevel;
|
||||
uint16_t mSupplyVoltage;
|
||||
uint32_t mMaxChildTimeout;
|
||||
struct
|
||||
{
|
||||
uint8_t mNetworkDataCount;
|
||||
uint8_t mNetworkData[OT_NETWORK_BASE_TLV_MAX_LENGTH];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t mIp6AddrCount;
|
||||
otIp6Address mIp6AddrList[OT_NETWORK_BASE_TLV_MAX_LENGTH / OT_IP6_ADDRESS_SIZE];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t mChildCount;
|
||||
otNetworkDiagChildEntry
|
||||
mChildTable[OT_NETWORK_BASE_TLV_MAX_LENGTH / OT_NETWORK_DIAGNOSTIC_CHILD_TABLE_ENTRY_SIZE];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t mChannelPageCount;
|
||||
uint8_t mChannelPages[OT_NETWORK_BASE_TLV_MAX_LENGTH];
|
||||
};
|
||||
};
|
||||
} otNetworkDiagTlv;
|
||||
|
||||
/**
|
||||
* This function gets the next Network Diagnostic TLV in the message.
|
||||
*
|
||||
* @param[in] aMessage A pointer to a message.
|
||||
* @param[inout] aIterator A pointer to the Network Diagnostic iterator context. To get the first
|
||||
* Network Diagnostic TLV it should be set to OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT.
|
||||
* @param[out] aNetworkDiagTlv A pointer to where the Network Diagnostic TLV information will be placed.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully found the next Network Diagnostic TLV.
|
||||
* @retval OT_ERROR_NOT_FOUND No subsequent Network Diagnostic TLV exists in the message.
|
||||
* @retval OT_ERROR_PARSE Parsing the next Network Diagnostic failed.
|
||||
*
|
||||
* @Note A subsequent call to this function is allowed only when current return value is OT_ERROR_NONE.
|
||||
*
|
||||
*/
|
||||
otError otThreadGetNextDiagnosticTlv(const otMessage * aMessage,
|
||||
otNetworkDiagIterator *aIterator,
|
||||
otNetworkDiagTlv * aNetworkDiagTlv);
|
||||
|
||||
/**
|
||||
* This function pointer is called when Network Diagnostic Get response is received.
|
||||
*
|
||||
* @param[in] aMessage A pointer to the message buffer containing the received Network Diagnostic
|
||||
* Get response payload.
|
||||
* @param[in] aMessageInfo A pointer to the message info for @p aMessage.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otReceiveDiagnosticGetCallback)(otMessage *aMessage, const otMessageInfo *aMessageInfo, void *aContext);
|
||||
|
||||
/**
|
||||
* This function registers a callback to provide received raw Network Diagnostic Get response payload.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCallback A pointer to a function that is called when Network Diagnostic Get response
|
||||
* is received or NULL to disable the callback.
|
||||
* @param[in] aCallbackContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
|
||||
otReceiveDiagnosticGetCallback aCallback,
|
||||
void * aCallbackContext);
|
||||
|
||||
/**
|
||||
* Send a Network Diagnostic Get 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.
|
||||
* @param[in] aCount Number of types in aTlvTypes.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully queued the DIAG_GET.req.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to send DIAG_GET.req.
|
||||
*
|
||||
*/
|
||||
otError otThreadSendDiagnosticGet(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const 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
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully queued the DIAG_RST.ntf.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to send DIAG_RST.ntf.
|
||||
*
|
||||
*/
|
||||
otError otThreadSendDiagnosticReset(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_NETDIAG_H_
|
||||
@@ -54,9 +54,11 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maximum Number of Network Diagnostic TLV Types to Request or Reset.
|
||||
* Maximum value length of Thread Base TLV.
|
||||
*/
|
||||
#define OT_NETWORK_DIAGNOSTIC_TYPELIST_MAX_ENTRIES 19
|
||||
#define OT_NETWORK_BASE_TLV_MAX_LENGTH 254
|
||||
|
||||
#define OT_NETWORK_MAX_ROUTER_ID 62 ///< Maximum Router ID
|
||||
|
||||
/**
|
||||
* Represents a Thread device role.
|
||||
@@ -662,58 +664,6 @@ otError otThreadGetParentAverageRssi(otInstance *aInstance, int8_t *aParentRssi)
|
||||
*/
|
||||
otError otThreadGetParentLastRssi(otInstance *aInstance, int8_t *aLastRssi);
|
||||
|
||||
/**
|
||||
* This function pointer is called when Network Diagnostic Get response is received.
|
||||
*
|
||||
* @param[in] aMessage A pointer to the message buffer containing the received Network Diagnostic
|
||||
* Get response payload.
|
||||
* @param[in] aMessageInfo A pointer to the message info for @p aMessage.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otReceiveDiagnosticGetCallback)(otMessage *aMessage, const otMessageInfo *aMessageInfo, void *aContext);
|
||||
|
||||
/**
|
||||
* This function registers a callback to provide received raw Network Diagnostic Get response payload.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCallback A pointer to a function that is called when Network Diagnostic Get response
|
||||
* is received or NULL to disable the callback.
|
||||
* @param[in] aCallbackContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
|
||||
otReceiveDiagnosticGetCallback aCallback,
|
||||
void * aCallbackContext);
|
||||
|
||||
/**
|
||||
* Send a Network Diagnostic Get 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.
|
||||
* @param[in] aCount Number of types in aTlvTypes
|
||||
*
|
||||
*/
|
||||
otError otThreadSendDiagnosticGet(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const 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
|
||||
*
|
||||
*/
|
||||
otError otThreadSendDiagnosticReset(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount);
|
||||
|
||||
/**
|
||||
* Get the IPv6 counters.
|
||||
*
|
||||
|
||||
+19
-4
@@ -972,12 +972,27 @@ If \<addr\> is unicast address, `Diagnostic Get` will be sent.
|
||||
if \<addr\> is multicast address, `Diagnostic Query` will be sent.
|
||||
|
||||
```bash
|
||||
> networkdiagnostic get fdde:ad00:beef:0:0:ff:fe00:f400 0 1 6
|
||||
DIAG_GET.rsp: 00088e18ad17a24b0b740102f400060841dcb82d40bac63d
|
||||
> networkdiagnostic get fdde:ad00:beef:0:0:ff:fe00:fc00 0 1 6
|
||||
> DIAG_GET.rsp/ans: 00080e336e1c41494e1c01020c000608640b0f674074c503
|
||||
Ext Address: '0e336e1c41494e1c'
|
||||
Rloc16: 0x0c00
|
||||
Leader Data:
|
||||
PartitionId: 0x640b0f67
|
||||
Weighting: 64
|
||||
DataVersion: 116
|
||||
StableDataVersion: 197
|
||||
LeaderRouterId: 0x03
|
||||
Done
|
||||
|
||||
> networkdiagnostic get ff02::1 0 1
|
||||
DIAG_GET.rsp: 0008567e31a79667a8cc0102f000
|
||||
DIAG_GET.rsp: 0008aaa7e584759e4e6401025400
|
||||
> DIAG_GET.rsp/ans: 00080e336e1c41494e1c01020c00
|
||||
Ext Address: '0e336e1c41494e1c'
|
||||
Rloc16: 0x0c00
|
||||
Done
|
||||
DIAG_GET.rsp/ans: 00083efcdb7e3f9eb0f201021800
|
||||
Ext Address: '3efcdb7e3f9eb0f2'
|
||||
Rloc16: 0x1800
|
||||
Done
|
||||
```
|
||||
|
||||
### networkdiagnostic reset \<addr\> \<type\> ..
|
||||
|
||||
+245
-9
@@ -94,6 +94,8 @@
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::HostSwap32;
|
||||
|
||||
#define INDENT_SIZE (4)
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Cli {
|
||||
@@ -3865,27 +3867,29 @@ exit:
|
||||
AppendResult(error);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
void Interpreter::HandleDiagnosticGetResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, void *aContext)
|
||||
{
|
||||
static_cast<Interpreter *>(aContext)->HandleDiagnosticGetResponse(
|
||||
*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
*aMessage, *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void Interpreter::HandleDiagnosticGetResponse(Message &aMessage, const Ip6::MessageInfo &)
|
||||
void Interpreter::HandleDiagnosticGetResponse(const otMessage &aMessage, const Ip6::MessageInfo &)
|
||||
{
|
||||
uint8_t buf[16];
|
||||
uint16_t bytesToPrint;
|
||||
uint16_t bytesPrinted = 0;
|
||||
uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
|
||||
uint8_t buf[16];
|
||||
uint16_t bytesToPrint;
|
||||
uint16_t bytesPrinted = 0;
|
||||
uint16_t length = otMessageGetLength(&aMessage) - otMessageGetOffset(&aMessage);
|
||||
otNetworkDiagTlv diagTlv;
|
||||
otNetworkDiagIterator iterator = OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
mServer->OutputFormat("DIAG_GET.rsp/ans: ");
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
bytesToPrint = (length < sizeof(buf)) ? length : sizeof(buf);
|
||||
aMessage.Read(aMessage.GetOffset() + bytesPrinted, bytesToPrint, buf);
|
||||
otMessageRead(&aMessage, otMessageGetOffset(&aMessage) + bytesPrinted, buf, bytesToPrint);
|
||||
|
||||
OutputBytes(buf, static_cast<uint8_t>(bytesToPrint));
|
||||
|
||||
@@ -3895,9 +3899,241 @@ void Interpreter::HandleDiagnosticGetResponse(Message &aMessage, const Ip6::Mess
|
||||
|
||||
mServer->OutputFormat("\r\n");
|
||||
|
||||
AppendResult(OT_ERROR_NONE);
|
||||
// Output Network Diagnostic TLV values in standard YAML format.
|
||||
while ((error = otThreadGetNextDiagnosticTlv(&aMessage, &iterator, &diagTlv)) == OT_ERROR_NONE)
|
||||
{
|
||||
uint16_t column = 0;
|
||||
switch (diagTlv.mType)
|
||||
{
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS:
|
||||
mServer->OutputFormat("Ext Address: '");
|
||||
OutputBytes(diagTlv.mExtAddress.m8, sizeof(diagTlv.mExtAddress.m8));
|
||||
mServer->OutputFormat("'\r\n");
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS:
|
||||
mServer->OutputFormat("Rloc16: 0x%04x\r\n", diagTlv.mAddr16);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_MODE:
|
||||
mServer->OutputFormat("Mode:\r\n");
|
||||
OutputMode(diagTlv.mMode, column + INDENT_SIZE);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT:
|
||||
mServer->OutputFormat("Timeout: %u\r\n", diagTlv.mTimeout);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY:
|
||||
mServer->OutputFormat("Connectivity:\r\n");
|
||||
OutputConnectivity(diagTlv.mConnectivity, column + INDENT_SIZE);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_ROUTE:
|
||||
mServer->OutputFormat("Route:\r\n");
|
||||
OutputRoute(diagTlv.mRoute, column + INDENT_SIZE);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA:
|
||||
mServer->OutputFormat("Leader Data:\r\n");
|
||||
OutputLeaderData(diagTlv.mLeaderData, column + INDENT_SIZE);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA:
|
||||
mServer->OutputFormat("Network Data: '");
|
||||
OutputBytes(diagTlv.mNetworkData, diagTlv.mNetworkDataCount);
|
||||
mServer->OutputFormat("'\r\n");
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST:
|
||||
mServer->OutputFormat("IP6 Address List:\r\n");
|
||||
for (uint16_t i = 0; i < diagTlv.mIp6AddrCount; ++i)
|
||||
{
|
||||
OutputSpaces(column + INDENT_SIZE);
|
||||
mServer->OutputFormat("- ");
|
||||
OutputIp6Address(diagTlv.mIp6AddrList[i]);
|
||||
mServer->OutputFormat("\r\n");
|
||||
}
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS:
|
||||
mServer->OutputFormat("MAC Counters:\r\n");
|
||||
OutputNetworkDiagMacCounters(diagTlv.mMacCounters, column + INDENT_SIZE);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL:
|
||||
mServer->OutputFormat("Battery Level: %u%%\r\n", diagTlv.mBatteryLevel);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE:
|
||||
mServer->OutputFormat("Supply Voltage: %umV\r\n", diagTlv.mSupplyVoltage);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE:
|
||||
mServer->OutputFormat("Child Table:\r\n");
|
||||
for (uint16_t i = 0; i < diagTlv.mChildCount; ++i)
|
||||
{
|
||||
OutputSpaces(column + INDENT_SIZE);
|
||||
mServer->OutputFormat("- ");
|
||||
OutputChildTableEntry(diagTlv.mChildTable[i], column + INDENT_SIZE + 2);
|
||||
}
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES:
|
||||
mServer->OutputFormat("Channel Pages: '");
|
||||
OutputBytes(diagTlv.mChannelPages, diagTlv.mChannelPageCount);
|
||||
mServer->OutputFormat("'\r\n");
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT:
|
||||
mServer->OutputFormat("Max Child Timeout: %u\r\n", diagTlv.mMaxChildTimeout);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AppendResult(error == OT_ERROR_NOT_FOUND ? OT_ERROR_NONE : error);
|
||||
}
|
||||
|
||||
void Interpreter::OutputSpaces(uint16_t aCount)
|
||||
{
|
||||
static const uint16_t kSpaceStrLen = 16;
|
||||
char spaceStr[kSpaceStrLen + 1];
|
||||
|
||||
memset(spaceStr, ' ', kSpaceStrLen);
|
||||
spaceStr[kSpaceStrLen] = '\0';
|
||||
|
||||
for (uint16_t i = 0; i < aCount; i += kSpaceStrLen)
|
||||
{
|
||||
uint16_t idx = (i + kSpaceStrLen <= aCount) ? 0 : (i + kSpaceStrLen - aCount);
|
||||
mServer->OutputFormat(&spaceStr[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::OutputMode(const otLinkModeConfig &aMode, uint16_t aColumn)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("RxOnWhenIdle: %d\r\n", aMode.mRxOnWhenIdle);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("SecureDataRequests: %d\r\n", aMode.mSecureDataRequests);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("DeviceType: %d\r\n", aMode.mDeviceType);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("NetworkData: %d\r\n", aMode.mNetworkData);
|
||||
}
|
||||
|
||||
void Interpreter::OutputConnectivity(const otNetworkDiagConnectivity &aConnectivity, uint16_t aColumn)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("ParentPriority: %d\r\n", aConnectivity.mParentPriority);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LinkQuality3: %u\r\n", aConnectivity.mLinkQuality3);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LinkQuality2: %u\r\n", aConnectivity.mLinkQuality2);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LinkQuality1: %u\r\n", aConnectivity.mLinkQuality1);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LeaderCost: %u\r\n", aConnectivity.mLeaderCost);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IdSequence: %u\r\n", aConnectivity.mIdSequence);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("ActiveRouters: %u\r\n", aConnectivity.mActiveRouters);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("SedBufferSize: %u\r\n", aConnectivity.mSedBufferSize);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("SedDatagramCount: %u\r\n", aConnectivity.mSedDatagramCount);
|
||||
}
|
||||
|
||||
void Interpreter::OutputRoute(const otNetworkDiagRoute &aRoute, uint16_t aColumn)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IdSequence: %u\r\n", aRoute.mIdSequence);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("RouteData:\r\n");
|
||||
|
||||
aColumn += INDENT_SIZE;
|
||||
for (uint16_t i = 0; i < aRoute.mRouteCount; ++i)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("- ");
|
||||
|
||||
OutputRouteData(aRoute.mRouteData[i], aColumn + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::OutputRouteData(const otNetworkDiagRouteData &aRouteData, uint16_t aColumn)
|
||||
{
|
||||
mServer->OutputFormat("RouteId: 0x%02x\r\n", aRouteData.mRouterId);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LinkQualityOut: %u\r\n", aRouteData.mLinkQualityOut);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LinkQualityIn: %u\r\n", aRouteData.mLinkQualityIn);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("RouteCost: %u\r\n", aRouteData.mRouteCost);
|
||||
}
|
||||
|
||||
void Interpreter::OutputLeaderData(const otLeaderData &aLeaderData, uint16_t aColumn)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("PartitionId: 0x%08x\r\n", aLeaderData.mPartitionId);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("Weighting: %u\r\n", aLeaderData.mWeighting);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("DataVersion: %u\r\n", aLeaderData.mDataVersion);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("StableDataVersion: %u\r\n", aLeaderData.mStableDataVersion);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("LeaderRouterId: 0x%02x\r\n", aLeaderData.mLeaderRouterId);
|
||||
}
|
||||
|
||||
void Interpreter::OutputNetworkDiagMacCounters(const otNetworkDiagMacCounters &aMacCounters, uint16_t aColumn)
|
||||
{
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfInUnknownProtos: %u\r\n", aMacCounters.mIfInUnknownProtos);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfInErrors: %u\r\n", aMacCounters.mIfInErrors);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfOutErrors: %u\r\n", aMacCounters.mIfOutErrors);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfInUcastPkts: %u\r\n", aMacCounters.mIfInUcastPkts);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfInBroadcastPkts: %u\r\n", aMacCounters.mIfInBroadcastPkts);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfInDiscards: %u\r\n", aMacCounters.mIfInDiscards);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfOutUcastPkts: %u\r\n", aMacCounters.mIfOutUcastPkts);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfOutBroadcastPkts: %u\r\n", aMacCounters.mIfOutBroadcastPkts);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("IfOutDiscards: %u\r\n", aMacCounters.mIfOutDiscards);
|
||||
}
|
||||
|
||||
void Interpreter::OutputChildTableEntry(const otNetworkDiagChildEntry &aChildEntry, uint16_t aColumn)
|
||||
{
|
||||
mServer->OutputFormat("ChildId: 0x%04x\r\n", aChildEntry.mChildId);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("Timeout: %u\r\n", aChildEntry.mTimeout);
|
||||
|
||||
OutputSpaces(aColumn);
|
||||
mServer->OutputFormat("Mode:\r\n");
|
||||
|
||||
OutputMode(aChildEntry.mMode, aColumn + INDENT_SIZE);
|
||||
}
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
void Interpreter::SetUserCommands(const otCliCommand *aCommands, uint8_t aLength)
|
||||
{
|
||||
mUserCommands = aCommands;
|
||||
|
||||
+12
-1
@@ -359,7 +359,19 @@ private:
|
||||
static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
|
||||
static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
|
||||
static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
void HandleDiagnosticGetResponse(const otMessage &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
static void HandleDiagnosticGetResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, void *aContext);
|
||||
void OutputSpaces(uint16_t aCount);
|
||||
void OutputMode(const otLinkModeConfig &aMode, uint16_t aColumn);
|
||||
void OutputConnectivity(const otNetworkDiagConnectivity &aConnectivity, uint16_t aColumn);
|
||||
void OutputRoute(const otNetworkDiagRoute &aRoute, uint16_t aColumn);
|
||||
void OutputRouteData(const otNetworkDiagRouteData &aRouteData, uint16_t aColumn);
|
||||
void OutputLeaderData(const otLeaderData &aLeaderData, uint16_t aColumn);
|
||||
void OutputNetworkDiagMacCounters(const otNetworkDiagMacCounters &aMacCounters, uint16_t aColumn);
|
||||
void OutputChildTableEntry(const otNetworkDiagChildEntry &aChildEntry, uint16_t aColumn);
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
|
||||
static void HandleDnsResponse(void * aContext,
|
||||
@@ -378,7 +390,6 @@ private:
|
||||
void HandleActiveScanResult(otActiveScanResult *aResult);
|
||||
void HandleEnergyScanResult(otEnergyScanResult *aResult);
|
||||
void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
|
||||
void HandleDiagnosticGetResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
|
||||
void HandleDnsResponse(const char *aHostname, const Ip6::Address *aAddress, uint32_t aTtl, otError aResult);
|
||||
#endif
|
||||
|
||||
@@ -96,6 +96,7 @@ set(COMMON_SOURCES
|
||||
api/logging_api.cpp
|
||||
api/message_api.cpp
|
||||
api/netdata_api.cpp
|
||||
api/netdiag_api.cpp
|
||||
api/network_time_api.cpp
|
||||
api/random_crypto_api.cpp
|
||||
api/random_noncrypto_api.cpp
|
||||
|
||||
@@ -134,6 +134,7 @@ SOURCES_COMMON = \
|
||||
api/logging_api.cpp \
|
||||
api/message_api.cpp \
|
||||
api/netdata_api.cpp \
|
||||
api/netdiag_api.cpp \
|
||||
api/network_time_api.cpp \
|
||||
api/random_crypto_api.cpp \
|
||||
api/random_noncrypto_api.cpp \
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 the OpenThread Network Diagnostic API.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/netdiag.h>
|
||||
|
||||
#include "common/instance.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
otError otThreadGetNextDiagnosticTlv(const otMessage * aMessage,
|
||||
otNetworkDiagIterator *aIterator,
|
||||
otNetworkDiagTlv * aNetworkDiagTlv)
|
||||
{
|
||||
return NetworkDiagnostic::NetworkDiagnostic::GetNextDiagTlv(*static_cast<const Coap::Message *>(aMessage),
|
||||
*aIterator, *aNetworkDiagTlv);
|
||||
}
|
||||
|
||||
void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
|
||||
otReceiveDiagnosticGetCallback aCallback,
|
||||
void * aCallbackContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SetReceiveDiagnosticGetCallback(aCallback, aCallbackContext);
|
||||
}
|
||||
|
||||
otError otThreadSendDiagnosticGet(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SendDiagnosticGet(
|
||||
*static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount);
|
||||
}
|
||||
|
||||
otError otThreadSendDiagnosticReset(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SendDiagnosticReset(
|
||||
*static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "common/debug.hpp"
|
||||
#include "common/instance.hpp"
|
||||
#include "common/locator-getters.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "common/settings.hpp"
|
||||
|
||||
using namespace ot;
|
||||
@@ -363,39 +362,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
|
||||
otReceiveDiagnosticGetCallback aCallback,
|
||||
void * aCallbackContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SetReceiveDiagnosticGetCallback(aCallback, aCallbackContext);
|
||||
}
|
||||
|
||||
otError otThreadSendDiagnosticGet(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SendDiagnosticGet(
|
||||
*static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount);
|
||||
}
|
||||
|
||||
otError otThreadSendDiagnosticReset(otInstance * aInstance,
|
||||
const otIp6Address *aDestination,
|
||||
const uint8_t aTlvTypes[],
|
||||
uint8_t aCount)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SendDiagnosticReset(
|
||||
*static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount);
|
||||
}
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/error.h>
|
||||
#include <openthread/thread.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kBaseTlvMaxLength = 254, ///< The maximum length of the Base TLV format.
|
||||
kBaseTlvMaxLength = OT_NETWORK_BASE_TLV_MAX_LENGTH, ///< The maximum length of the Base TLV format.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -142,7 +142,7 @@ enum
|
||||
#else
|
||||
kMaxRouteCost = 16, ///< MAX_ROUTE_COST
|
||||
#endif
|
||||
kMaxRouterId = 62, ///< MAX_ROUTER_ID
|
||||
kMaxRouterId = OT_NETWORK_MAX_ROUTER_ID, ///< MAX_ROUTER_ID
|
||||
kInvalidRouterId = kMaxRouterId + 1, ///< Value indicating incorrect Router Id
|
||||
kMaxRouters = OPENTHREAD_CONFIG_MLE_MAX_ROUTERS, ///< MAX_ROUTERS
|
||||
kMinDowngradeNeighbors = 7, ///< MIN_DOWNGRADE_NEIGHBORS
|
||||
|
||||
@@ -720,6 +720,317 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void ParseMode(const Mle::DeviceMode &aMode, otLinkModeConfig &aLinkModeConfig)
|
||||
{
|
||||
aLinkModeConfig.mRxOnWhenIdle = aMode.IsRxOnWhenIdle();
|
||||
aLinkModeConfig.mSecureDataRequests = aMode.IsSecureDataRequest();
|
||||
aLinkModeConfig.mDeviceType = aMode.IsFullThreadDevice();
|
||||
aLinkModeConfig.mNetworkData = aMode.IsFullNetworkData();
|
||||
}
|
||||
|
||||
static inline void ParseConnectivity(const ConnectivityTlv & aConnectivityTlv,
|
||||
otNetworkDiagConnectivity &aNetworkDiagConnectivity)
|
||||
{
|
||||
aNetworkDiagConnectivity.mParentPriority = aConnectivityTlv.GetParentPriority();
|
||||
aNetworkDiagConnectivity.mLinkQuality3 = aConnectivityTlv.GetLinkQuality3();
|
||||
aNetworkDiagConnectivity.mLinkQuality2 = aConnectivityTlv.GetLinkQuality2();
|
||||
aNetworkDiagConnectivity.mLinkQuality1 = aConnectivityTlv.GetLinkQuality1();
|
||||
aNetworkDiagConnectivity.mLeaderCost = aConnectivityTlv.GetLeaderCost();
|
||||
aNetworkDiagConnectivity.mIdSequence = aConnectivityTlv.GetIdSequence();
|
||||
aNetworkDiagConnectivity.mActiveRouters = aConnectivityTlv.GetActiveRouters();
|
||||
aNetworkDiagConnectivity.mSedBufferSize = aConnectivityTlv.GetSedBufferSize();
|
||||
aNetworkDiagConnectivity.mSedDatagramCount = aConnectivityTlv.GetSedDatagramCount();
|
||||
}
|
||||
|
||||
static void ParseRoute(const RouteTlv &aRouteTlv, otNetworkDiagRoute &aNetworkDiagRoute)
|
||||
{
|
||||
uint8_t routeCount = 0;
|
||||
|
||||
for (uint8_t i = 0; i <= Mle::kMaxRouterId; ++i)
|
||||
{
|
||||
if (!aRouteTlv.IsRouterIdSet(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
aNetworkDiagRoute.mRouteData[routeCount].mRouterId = i;
|
||||
aNetworkDiagRoute.mRouteData[routeCount].mRouteCost = aRouteTlv.GetRouteCost(routeCount);
|
||||
aNetworkDiagRoute.mRouteData[routeCount].mLinkQualityIn = aRouteTlv.GetLinkQualityIn(routeCount);
|
||||
aNetworkDiagRoute.mRouteData[routeCount].mLinkQualityOut = aRouteTlv.GetLinkQualityOut(routeCount);
|
||||
++routeCount;
|
||||
}
|
||||
aNetworkDiagRoute.mRouteCount = routeCount;
|
||||
aNetworkDiagRoute.mIdSequence = aRouteTlv.GetRouterIdSequence();
|
||||
}
|
||||
|
||||
static inline void ParseLeaderData(const LeaderDataTlv &aLeaderDataTlv, otLeaderData &aLeaderData)
|
||||
{
|
||||
aLeaderData.mPartitionId = aLeaderDataTlv.GetPartitionId();
|
||||
aLeaderData.mWeighting = aLeaderDataTlv.GetWeighting();
|
||||
aLeaderData.mDataVersion = aLeaderDataTlv.GetDataVersion();
|
||||
aLeaderData.mStableDataVersion = aLeaderDataTlv.GetStableDataVersion();
|
||||
aLeaderData.mLeaderRouterId = aLeaderDataTlv.GetLeaderRouterId();
|
||||
}
|
||||
|
||||
static inline void ParseMacCounters(const MacCountersTlv &aMacCountersTlv, otNetworkDiagMacCounters &aMacCounters)
|
||||
{
|
||||
aMacCounters.mIfInUnknownProtos = aMacCountersTlv.GetIfInUnknownProtos();
|
||||
aMacCounters.mIfInErrors = aMacCountersTlv.GetIfInErrors();
|
||||
aMacCounters.mIfOutErrors = aMacCountersTlv.GetIfOutErrors();
|
||||
aMacCounters.mIfInUcastPkts = aMacCountersTlv.GetIfInUcastPkts();
|
||||
aMacCounters.mIfInBroadcastPkts = aMacCountersTlv.GetIfInBroadcastPkts();
|
||||
aMacCounters.mIfInDiscards = aMacCountersTlv.GetIfInDiscards();
|
||||
aMacCounters.mIfOutUcastPkts = aMacCountersTlv.GetIfOutUcastPkts();
|
||||
aMacCounters.mIfOutBroadcastPkts = aMacCountersTlv.GetIfOutBroadcastPkts();
|
||||
aMacCounters.mIfOutDiscards = aMacCountersTlv.GetIfOutDiscards();
|
||||
}
|
||||
|
||||
static inline void ParseChildEntry(const ChildTableEntry &aChildTableTlvEntry, otNetworkDiagChildEntry &aChildEntry)
|
||||
{
|
||||
aChildEntry.mTimeout = aChildTableTlvEntry.GetTimeout();
|
||||
aChildEntry.mChildId = aChildTableTlvEntry.GetChildId();
|
||||
ParseMode(aChildTableTlvEntry.GetMode(), aChildEntry.mMode);
|
||||
}
|
||||
|
||||
otError NetworkDiagnostic::GetNextDiagTlv(const otMessage & aMessage,
|
||||
otNetworkDiagIterator &aIterator,
|
||||
otNetworkDiagTlv & aNetworkDiagTlv)
|
||||
{
|
||||
otError error = OT_ERROR_PARSE;
|
||||
const Coap::Message &message = static_cast<const Coap::Message &>(aMessage);
|
||||
uint16_t offset = message.GetOffset();
|
||||
NetworkDiagnosticTlv tlv;
|
||||
|
||||
offset += aIterator;
|
||||
|
||||
while (true)
|
||||
{
|
||||
uint16_t tlvTotalLength;
|
||||
|
||||
VerifyOrExit(message.Read(offset, sizeof(tlv), &tlv) == sizeof(tlv), error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
switch (tlv.GetType())
|
||||
{
|
||||
case NetworkDiagnosticTlv::kExtMacAddress:
|
||||
{
|
||||
ExtMacAddressTlv extMacAddr;
|
||||
|
||||
tlvTotalLength = sizeof(extMacAddr);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &extMacAddr) == tlvTotalLength);
|
||||
VerifyOrExit(extMacAddr.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mExtAddress = *extMacAddr.GetMacAddr();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kAddress16:
|
||||
{
|
||||
Address16Tlv addr16;
|
||||
|
||||
tlvTotalLength = sizeof(addr16);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &addr16) == tlvTotalLength);
|
||||
VerifyOrExit(addr16.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mAddr16 = addr16.GetRloc16();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kMode:
|
||||
{
|
||||
ModeTlv linkMode;
|
||||
|
||||
tlvTotalLength = sizeof(linkMode);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &linkMode) == tlvTotalLength);
|
||||
VerifyOrExit(linkMode.IsValid());
|
||||
|
||||
ParseMode(linkMode.GetMode(), aNetworkDiagTlv.mMode);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kTimeout:
|
||||
{
|
||||
TimeoutTlv timeout;
|
||||
|
||||
tlvTotalLength = sizeof(timeout);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &timeout) == tlvTotalLength);
|
||||
VerifyOrExit(timeout.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mTimeout = timeout.GetTimeout();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kConnectivity:
|
||||
{
|
||||
ConnectivityTlv connectivity;
|
||||
|
||||
tlvTotalLength = sizeof(connectivity);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &connectivity) == tlvTotalLength);
|
||||
VerifyOrExit(connectivity.IsValid());
|
||||
|
||||
ParseConnectivity(connectivity, aNetworkDiagTlv.mConnectivity);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kRoute:
|
||||
{
|
||||
RouteTlv route;
|
||||
|
||||
tlvTotalLength = sizeof(tlv) + tlv.GetLength();
|
||||
VerifyOrExit(tlvTotalLength <= sizeof(route));
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &route) == tlvTotalLength);
|
||||
VerifyOrExit(route.IsValid());
|
||||
|
||||
ParseRoute(route, aNetworkDiagTlv.mRoute);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kLeaderData:
|
||||
{
|
||||
LeaderDataTlv leaderData;
|
||||
|
||||
tlvTotalLength = sizeof(leaderData);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &leaderData) == tlvTotalLength);
|
||||
VerifyOrExit(leaderData.IsValid());
|
||||
|
||||
ParseLeaderData(leaderData, aNetworkDiagTlv.mLeaderData);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kNetworkData:
|
||||
{
|
||||
NetworkDataTlv networkData;
|
||||
|
||||
tlvTotalLength = sizeof(tlv) + tlv.GetLength();
|
||||
VerifyOrExit(tlvTotalLength <= sizeof(networkData));
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &networkData) == tlvTotalLength);
|
||||
VerifyOrExit(networkData.IsValid());
|
||||
VerifyOrExit(sizeof(aNetworkDiagTlv.mNetworkData) >= networkData.GetLength());
|
||||
|
||||
memcpy(aNetworkDiagTlv.mNetworkData, networkData.GetNetworkData(), networkData.GetLength());
|
||||
aNetworkDiagTlv.mNetworkDataCount = networkData.GetLength();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kIp6AddressList:
|
||||
{
|
||||
Ip6AddressListTlv &ip6AddrList = static_cast<Ip6AddressListTlv &>(tlv);
|
||||
|
||||
VerifyOrExit(ip6AddrList.IsValid());
|
||||
VerifyOrExit(sizeof(aNetworkDiagTlv.mIp6AddrList) >= ip6AddrList.GetLength());
|
||||
VerifyOrExit(message.Read(offset + sizeof(ip6AddrList), ip6AddrList.GetLength(),
|
||||
aNetworkDiagTlv.mIp6AddrList) == ip6AddrList.GetLength());
|
||||
|
||||
aNetworkDiagTlv.mIp6AddrCount = ip6AddrList.GetLength() / OT_IP6_ADDRESS_SIZE;
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kMacCounters:
|
||||
{
|
||||
MacCountersTlv macCounters;
|
||||
|
||||
tlvTotalLength = sizeof(MacCountersTlv);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &macCounters) == tlvTotalLength);
|
||||
VerifyOrExit(macCounters.IsValid());
|
||||
|
||||
ParseMacCounters(macCounters, aNetworkDiagTlv.mMacCounters);
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kBatteryLevel:
|
||||
{
|
||||
BatteryLevelTlv batteryLevel;
|
||||
|
||||
tlvTotalLength = sizeof(BatteryLevelTlv);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &batteryLevel) == tlvTotalLength);
|
||||
VerifyOrExit(batteryLevel.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mBatteryLevel = batteryLevel.GetBatteryLevel();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kSupplyVoltage:
|
||||
{
|
||||
SupplyVoltageTlv supplyVoltage;
|
||||
|
||||
tlvTotalLength = sizeof(SupplyVoltageTlv);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &supplyVoltage) == tlvTotalLength);
|
||||
VerifyOrExit(supplyVoltage.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mSupplyVoltage = supplyVoltage.GetSupplyVoltage();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kChildTable:
|
||||
{
|
||||
ChildTableTlv &childTable = static_cast<ChildTableTlv &>(tlv);
|
||||
|
||||
VerifyOrExit(childTable.IsValid());
|
||||
VerifyOrExit(childTable.GetNumEntries() <= OT_ARRAY_LENGTH(aNetworkDiagTlv.mChildTable));
|
||||
|
||||
for (uint8_t i = 0; i < childTable.GetNumEntries(); ++i)
|
||||
{
|
||||
ChildTableEntry childEntry;
|
||||
VerifyOrExit(childTable.ReadEntry(childEntry, message, offset, i) == OT_ERROR_NONE);
|
||||
ParseChildEntry(childEntry, aNetworkDiagTlv.mChildTable[i]);
|
||||
}
|
||||
aNetworkDiagTlv.mChildCount = childTable.GetNumEntries();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kChannelPages:
|
||||
{
|
||||
VerifyOrExit(sizeof(aNetworkDiagTlv.mChannelPages) >= tlv.GetLength());
|
||||
VerifyOrExit(message.Read(offset + sizeof(tlv), tlv.GetLength(), aNetworkDiagTlv.mChannelPages) ==
|
||||
tlv.GetLength());
|
||||
|
||||
aNetworkDiagTlv.mChannelPageCount = tlv.GetLength();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case NetworkDiagnosticTlv::kMaxChildTimeout:
|
||||
{
|
||||
MaxChildTimeoutTlv maxChildTimeout;
|
||||
|
||||
tlvTotalLength = sizeof(maxChildTimeout);
|
||||
VerifyOrExit(message.Read(offset, tlvTotalLength, &maxChildTimeout) == tlvTotalLength);
|
||||
VerifyOrExit(maxChildTimeout.IsValid());
|
||||
|
||||
aNetworkDiagTlv.mMaxChildTimeout = maxChildTimeout.GetTimeout();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Ignore unrecognized Network Diagnostic TLV silently.
|
||||
break;
|
||||
}
|
||||
|
||||
// The actual TLV size may exceeds tlvTotalLength.
|
||||
offset += tlv.GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
aNetworkDiagTlv.mType = tlv.GetType();
|
||||
aIterator = offset - message.GetOffset();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace NetworkDiagnostic
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/netdiag.h>
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
@@ -98,6 +100,10 @@ public:
|
||||
*/
|
||||
otError SendDiagnosticReset(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount);
|
||||
|
||||
static otError GetNextDiagTlv(const otMessage & aMessage,
|
||||
otNetworkDiagIterator &aIterator,
|
||||
otNetworkDiagTlv & aNetworkDiagTlv);
|
||||
|
||||
private:
|
||||
otError AppendIp6AddressList(Message &aMessage);
|
||||
otError AppendChildTable(Message &aMessage);
|
||||
|
||||
@@ -82,23 +82,22 @@ public:
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
kExtMacAddress = 0, ///< Source Address TLV
|
||||
kAddress16 = 1, ///< Address16 TLV
|
||||
kMode = 2, ///< Mode TLV
|
||||
kTimeout = 3, ///< Timeout TLV
|
||||
kConnectivity = 4, ///< Connectivity TLV
|
||||
kRoute = 5, ///< Routing-Table TLV
|
||||
kLeaderData = 6, ///< Leader Data TLV
|
||||
kNetworkData = 7, ///< Network Data TLV
|
||||
kIp6AddressList = 8, ///< Ip6 Address List TLV
|
||||
kMacCounters = 9, ///< Mac Counters TLV
|
||||
kBatteryLevel = 14, ///< Battery Level TLV
|
||||
kSupplyVoltage = 15, ///< Supply Voltage TLV
|
||||
kChildTable = 16, ///< Child Table TLV
|
||||
kChannelPages = 17, ///< Channel Pages TLV
|
||||
kTypeList = 18, ///< Type List TLV
|
||||
kMaxChildTimeout = 19, ///< Max Child Timeout TLV
|
||||
kInvalid = 255,
|
||||
kExtMacAddress = OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS,
|
||||
kAddress16 = OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS,
|
||||
kMode = OT_NETWORK_DIAGNOSTIC_TLV_MODE,
|
||||
kTimeout = OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT,
|
||||
kConnectivity = OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY,
|
||||
kRoute = OT_NETWORK_DIAGNOSTIC_TLV_ROUTE,
|
||||
kLeaderData = OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA,
|
||||
kNetworkData = OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA,
|
||||
kIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST,
|
||||
kMacCounters = OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS,
|
||||
kBatteryLevel = OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL,
|
||||
kSupplyVoltage = OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE,
|
||||
kChildTable = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE,
|
||||
kChannelPages = OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES,
|
||||
kTypeList = OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST,
|
||||
kMaxChildTimeout = OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -919,6 +918,15 @@ public:
|
||||
SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return !IsExtended() && (GetLength() % OT_IP6_ADDRESS_SIZE == 0); }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the IPv6 address entry.
|
||||
*
|
||||
@@ -1388,7 +1396,7 @@ public:
|
||||
* @retval OT_ERROR_NOT_FOUND No such entry is found.
|
||||
* @retval OT_ERROR_NONE Successfully read the entry.
|
||||
*/
|
||||
otError ReadEntry(ChildTableEntry &aEntry, Message &aMessage, uint16_t aOffset, uint8_t aIndex) const
|
||||
otError ReadEntry(ChildTableEntry &aEntry, const Message &aMessage, uint16_t aOffset, uint8_t aIndex) const
|
||||
{
|
||||
return (aIndex < GetNumEntries() &&
|
||||
aMessage.Read(aOffset + sizeof(ChildTableTlv) + (aIndex * sizeof(ChildTableEntry)),
|
||||
@@ -1417,6 +1425,19 @@ public:
|
||||
SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const
|
||||
{
|
||||
// At least one channel page must be included.
|
||||
return GetLength() >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the list of Channel Pages.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user