[mesh-diag] new module and new API to discover network topology (#8682)

This commit is contained in:
Abtin Keshavarzian
2023-03-02 00:43:46 -08:00
committed by GitHub
parent d93521de06
commit 0a79c30a20
23 changed files with 1255 additions and 1 deletions
+1
View File
@@ -139,6 +139,7 @@
* @defgroup api-history-tracker History Tracker
* @defgroup api-jam-detection Jam Detection
* @defgroup api-logging Logging - Thread Stack
* @defgroup api-mesh-diag Mesh Diagnostics
* @defgroup api-ncp Network Co-Processor
* @defgroup api-network-time Network Time Synchronization
* @defgroup api-random-group Random Number Generator
+1
View File
@@ -117,6 +117,7 @@ ot_option(OT_LINK_METRICS_SUBJECT OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENA
ot_option(OT_LINK_RAW OPENTHREAD_CONFIG_LINK_RAW_ENABLE "link raw service")
ot_option(OT_LOG_LEVEL_DYNAMIC OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE "dynamic log level control")
ot_option(OT_MAC_FILTER OPENTHREAD_CONFIG_MAC_FILTER_ENABLE "mac filter")
ot_option(OT_MESH_DIAG OPENTHREAD_CONFIG_MESH_DIAG_ENABLE "mesh diag")
ot_option(OT_MESSAGE_USE_HEAP OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE "heap allocator for message buffers")
ot_option(OT_MLE_LONG_ROUTES OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE "MLE long routes extension (experimental)")
ot_option(OT_MLR OPENTHREAD_CONFIG_MLR_ENABLE "Multicast Listener Registration (MLR)")
+5
View File
@@ -66,6 +66,7 @@ LOG_OUTPUT ?= APP
endif
LINK_RAW ?= 0
MAC_FILTER ?= 0
MESH_DIAG ?= 0
MESSAGE_USE_HEAP ?= 0
MLE_LONG_ROUTES ?= 0
MLR ?= 0
@@ -268,6 +269,10 @@ ifeq ($(MAC_FILTER),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1
endif
ifeq ($(MESH_DIAG),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MESH_DIAG_ENABLE=1
endif
ifeq ($(MESSAGE_USE_HEAP),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1
endif
+1
View File
@@ -68,6 +68,7 @@ openthread_headers = \
openthread/link_metrics.h \
openthread/link_raw.h \
openthread/logging.h \
openthread/mesh_diag.h \
openthread/message.h \
openthread/multi_radio.h \
openthread/nat64.h \
+1
View File
@@ -72,6 +72,7 @@ source_set("openthread") {
"link_metrics.h",
"link_raw.h",
"logging.h",
"mesh_diag.h",
"message.h",
"multi_radio.h",
"nat64.h",
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (293)
#define OPENTHREAD_API_VERSION (294)
/**
* @addtogroup api-instance
+223
View File
@@ -0,0 +1,223 @@
/*
* Copyright (c) 2023, 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 Mesh Diagnostic APIs.
*/
#ifndef OPENTHREAD_MESH_DIAG_H_
#define OPENTHREAD_MESH_DIAG_H_
#include <openthread/instance.h>
#include <openthread/thread.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup api-mesh-diag
*
* @brief
* This module includes definitions and functions for Mesh Diagnostics.
*
* The Mesh Diagnostics APIs require `OPENTHREAD_CONFIG_MESH_DIAG_ENABLE` and `OPENTHREAD_FTD`.
*
* @{
*
*/
/**
* This structure represents the set of configurations used when discovering mesh topology indicating which items to
* discover.
*
*/
typedef struct otMeshDiagDiscoverConfig
{
bool mDiscoverIp6Addresses : 1; ///< Whether or not to discover IPv6 addresses of every router.
bool mDiscoverChildTable : 1; ///< Whether or not to discover children of every router.
} otMeshDiagDiscoverConfig;
/**
* This type is an opaque iterator to iterate over list of IPv6 addresses of a router.
*
* Pointers to instance of this type are provided in `otMeshDiagRouterInfo`.
*
*/
typedef struct otMeshDiagIp6AddrIterator otMeshDiagIp6AddrIterator;
/**
* This type is an opaque iterator to iterate over list of children of a router.
*
* Pointers to instance of this type are provided in `otMeshDiagRouterInfo`.
*
*/
typedef struct otMeshDiagChildIterator otMeshDiagChildIterator;
/**
* This type represents information about a router in Thread mesh.
*
*/
typedef struct otMeshDiagRouterInfo
{
otExtAddress mExtAddress; ///< Extended MAC address.
uint16_t mRloc16; ///< RLOC16.
uint8_t mRouterId; ///< Router ID.
bool mIsThisDevice : 1; ///< Whether router is this device itself.
bool mIsThisDeviceParent : 1; ///< Whether router is parent of this device (when device is a child).
bool mIsLeader : 1; ///< Whether router is leader.
bool mIsBorderRouter : 1; ///< Whether router acts as a border router providing ext connectivity.
/**
* This array provides the link quality from this router to other routers, also indicating whether a link is
* established between the routers.
*
* The array is indexed based on Router ID. `mLinkQualities[routerId]` indicates the incoming link quality, the
* router sees to the router with `routerId`. Link quality is a value in [0, 3]. Value zero indicates no link.
* Larger value indicate better link quality (as defined by Thread specification).
*
*/
uint8_t mLinkQualities[OT_NETWORK_MAX_ROUTER_ID + 1];
/**
* A pointer to an iterator to go through the list of IPv6 addresses of the router.
*
* The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextIp6Address`
* to iterate through the IPv6 addresses.
*
* The pointer can be NULL when there was no request to discover IPv6 addresses (in `otMeshDiagDiscoverConfig`) or
* if the router did not provide the list.
*
*/
otMeshDiagIp6AddrIterator *mIp6AddrIterator;
/**
* A pointer to an iterator to go through the list of children of the router.
*
* The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextChildInfo`
* to iterate through the children of the router.
*
* The pointer can be NULL when there was no request to discover children (in `otMeshDiagDiscoverConfig`) or
* if the router did not provide the list.
*
*/
otMeshDiagChildIterator *mChildIterator;
} otMeshDiagRouterInfo;
/**
* This type represents information about a discovered child in Thread mesh.
*
*/
typedef struct otMeshDiagChildInfo
{
uint16_t mRloc16; ///< RLOC16.
otLinkModeConfig mMode; ///< Device mode.
uint8_t mLinkQuality; ///< Incoming link quality to child from parent.
bool mIsThisDevice : 1; ///< Whether child is this device itself.
bool mIsBorderRouter : 1; ///< Whether child acts as a border router providing ext connectivity.
} otMeshDiagChildInfo;
/**
* This function pointer type represents the callback used by `otMeshDiagDiscoverTopology()` to provide information
* about a discovered router.
*
* When @p aError is `OT_ERROR_PENDING`, it indicates that the discovery is not yet finished and there will be more
* routers to discover and the callback will be invoked again.
*
* @param[in] aError OT_ERROR_PENDING Indicates there are more routers to be discovered.
* OT_ERROR_NONE Indicates this is the last router and mesh discovery is done.
* OT_ERROR_RESPONSE_TIMEOUT Timed out waiting for response from one or more routers.
* @param[in] aRouterInfo The discovered router info (can be null if `aError` is OT_ERROR_RESPONSE_TIMEOUT).
* @param[in] aContext Application-specific context.
*
*/
typedef void (*otMeshDiagDiscoverCallback)(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext);
/**
* This function starts network topology discovery.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aConfig The configuration to use for discovery (e.g., which items to discover).
* @param[in] aCallback The callback to report the discovered routers.
* @param[in] aContext A context to pass in @p aCallback.
*
* @retval OT_ERROR_NONE The network topology discovery started successfully.
* @retval OT_ERROR_BUSY A previous discovery request is still ongoing.
* @retval OT_ERROR_INVALID_STATE Device is not attached.
* @retval OT_ERROR_NO_BUFS Could not allocate buffer to send discovery messages.
*
*/
otError otMeshDiagDiscoverTopology(otInstance *aInstance,
const otMeshDiagDiscoverConfig *aConfig,
otMeshDiagDiscoverCallback aCallback,
void *aContext);
/**
* This function cancels an ongoing topology discovery if there is one, otherwise no action.
*
* When ongoing discovery is cancelled, the callback from `otMeshDiagDiscoverTopology()` will not be called anymore.
*
*/
void otMeshDiagCancel(otInstance *aInstance);
/**
* This function iterates through the discovered IPv6 address of a router.
*
* @param[in,out] aIterator The address iterator to use.
* @param[out] aIp6Address A pointer to return the next IPv6 address (if any).
*
* @retval OT_ERROR_NONE Successfully retrieved the next address. @p aIp6Address and @p aIterator are updated.
* @retval OT_ERROR_NOT_FOUND No more address. Reached the end of the list.
*
*/
otError otMeshDiagGetNextIp6Address(otMeshDiagIp6AddrIterator *aIterator, otIp6Address *aIp6Address);
/**
* This function iterates through the discovered children of a router.
*
* @param[in,out] aIterator The address iterator to use.
* @param[out] aChildInfo A pointer to return the child info (if any).
*
* @retval OT_ERROR_NONE Successfully retrieved the next child. @p aChildInfo and @p aIterator are updated.
* @retval OT_ERROR_NOT_FOUND No more child. Reached the end of the list.
*
*/
otError otMeshDiagGetNextChildInfo(otMeshDiagChildIterator *aIterator, otMeshDiagChildInfo *aChildInfo);
/**
* @}
*
*/
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_MESH_DIAG_H_
+1
View File
@@ -61,6 +61,7 @@ OT_BUILD_OPTIONS=(
"-DOT_JOINER=ON"
"-DOT_LOG_LEVEL_DYNAMIC=ON"
"-DOT_MAC_FILTER=ON"
"-DOT_MESH_DIAG=ON"
"-DOT_MTD_NETDIAG=ON"
"-DOT_NAT64_BORDER_ROUTING=ON"
"-DOT_NAT64_TRANSLATOR=ON"
+1
View File
@@ -120,6 +120,7 @@ OT_CLANG_TIDY_BUILD_OPTS=(
'-DOT_LINK_METRICS_INITIATOR=ON'
'-DOT_LINK_METRICS_SUBJECT=ON'
'-DOT_MAC_FILTER=ON'
'-DOT_MESH_DIAG=ON'
'-DOT_MTD_NETDIAG=ON'
'-DOT_NAT64_BORDER_ROUTING=ON'
'-DOT_NAT64_TRANSLATOR=ON'
+135
View File
@@ -67,6 +67,7 @@ Done
- [log](#log-filename-filename)
- [mac](#mac-retries-direct)
- [macfilter](#macfilter)
- [meshdiag](#meshdiag-topology)
- [mliid](#mliid-iid)
- [mlr](#mlr-reg-ipaddr--timeout)
- [mode](#mode)
@@ -1821,6 +1822,140 @@ Set the log level.
Done
```
### meshdiag topology [ip6-addrs][children]
Discover network topology (list of routers and their connections).
This command requires `OPENTHREAD_CONFIG_MESH_DIAG_ENABLE` and `OPENTHREAD_FTD`.
Parameters are optional and indicate additional items to discover. Can be added in any order.
- `ip6-addrs` to discover the list of IPv6 addresses of every router.
- `children` to discover the child table of every router.
Output lists all discovered routers. Information per router:
- Router ID
- RLOC16
- Extended MAC address
- Whether the router is this device is itself (`me`)
- Whether the router is the parent of this device when device is a child (`parent`)
- Whether the router is `leader`
- Whether the router acts as a border router providing external connectivity (`br`)
- List of routers to which this router has a link:
- `3-links`: Router IDs to which this router has a incoming link with link quality 3
- `2-links`: Router IDs to which this router has a incoming link with link quality 2
- `1-links`: Router IDs to which this router has a incoming link with link quality 1
- If a list if empty, it is omitted in the out.
- If `ip6-addrs`, list of IPv6 addresses of the router
- If `children`, list of all children of the router. Information per child:
- RLOC16
- Incoming Link Quality from perspective of parent to child (zero indicates unknown)
- Child Device mode (`r` rx-on-when-idle, `d` Full Thread Device, `n` Full Network Data, `-` no flags set)
- Whether the child is this device itself (`me`)
- Whether the child acts as a border router providing external connectivity (`br`)
Discover network topology:
```bash
> meshdiag topology
id:02 rloc16:0x0800 ext-addr:8aa57d2c603fe16c - me - leader
3-links:{ 46 }
id:46 rloc16:0xb800 ext-addr:fe109d277e0175cc
3-links:{ 02 51 57 }
id:33 rloc16:0x8400 ext-addr:d2e511a146b9e54d
3-links:{ 51 57 }
id:51 rloc16:0xcc00 ext-addr:9aab43ababf05352
3-links:{ 33 57 }
2-links:{ 46 }
id:57 rloc16:0xe400 ext-addr:dae9c4c0e9da55ff
3-links:{ 46 51 }
1-links:{ 33 }
Done
```
Discover network topology with router's IPv6 addresses and children:
```bash
> meshdiag topology children ip6-addrs
id:62 rloc16:0xf800 ext-addr:ce349873897233a5 - me - br
3-links:{ 46 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:f800
fdde:ad00:beef:0:211d:39e9:6b2e:4ad1
fe80:0:0:0:cc34:9873:8972:33a5
children: none
id:02 rloc16:0x0800 ext-addr:8aa57d2c603fe16c - leader - br
3-links:{ 46 51 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:fc00
fdde:ad00:beef:0:0:ff:fe00:800
fdde:ad00:beef:0:8a36:a3eb:47ae:a9b0
fe80:0:0:0:88a5:7d2c:603f:e16c
children:
rloc16:0x0803 lq:3, mode:rn
rloc16:0x0804 lq:3, mode:rdn
id:33 rloc16:0x8400 ext-addr:d2e511a146b9e54d
3-links:{ 57 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:8400
fdde:ad00:beef:0:824:a126:cf19:a9f4
fe80:0:0:0:d0e5:11a1:46b9:e54d
children: none
id:51 rloc16:0xcc00 ext-addr:9aab43ababf05352
3-links:{ 02 46 57 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:cc00
fdde:ad00:beef:0:2986:bba3:12d0:1dd2
fe80:0:0:0:98ab:43ab:abf0:5352
children: none
id:57 rloc16:0xe400 ext-addr:dae9c4c0e9da55ff
3-links:{ 33 51 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:e400
fdde:ad00:beef:0:87d0:550:bc18:9920
fe80:0:0:0:d8e9:c4c0:e9da:55ff
children:
rloc16:0xe402 lq:3, mode:rn - br
rloc16:0xe403 lq:3, mode:rn
id:46 rloc16:0xb800 ext-addr:fe109d277e0175cc
3-links:{ 02 51 62 }
ip6-addrs:
fdde:ad00:beef:0:0:ff:fe00:b800
fdde:ad00:beef:0:df4d:2994:d85c:c337
fe80:0:0:0:fc10:9d27:7e01:75cc
children: none
Done
```
Discover network topology with children:
```bash
> meshdiag topology children
id:02 rloc16:0x0800 ext-addr:8aa57d2c603fe16c - parent - leader - br
3-links:{ 46 51 }
children:
rloc16:0x0803 lq:0, mode:rn
rloc16:0x0804 lq:0, mode:rdn - me
id:46 rloc16:0xb800 ext-addr:fe109d277e0175cc
3-links:{ 02 51 62 }
children: none
id:33 rloc16:0x8400 ext-addr:d2e511a146b9e54d
3-links:{ 57 }
children: none
id:51 rloc16:0xcc00 ext-addr:9aab43ababf05352
3-links:{ 02 46 57 }
children: none
id:57 rloc16:0xe400 ext-addr:dae9c4c0e9da55ff
3-links:{ 33 51 }
children:
rloc16:0xe402 lq:3, mode:rn - br
rloc16:0xe403 lq:3, mode:rn
id:62 rloc16:0xf800 ext-addr:ce349873897233a5 - br
3-links:{ 46 }
children: none
```
### mliid \<iid\>
Set the Mesh Local IID.
+212
View File
@@ -5434,6 +5434,215 @@ template <> otError Interpreter::Process<Cmd("nexthop")>(Arg aArgs[])
exit:
return error;
}
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE
template <> otError Interpreter::Process<Cmd("meshdiag")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
/**
* @cli meshdiag topology
* @code
* meshdiag topology
* id:02 rloc16:0x0800 ext-addr:8aa57d2c603fe16c - me - leader
* 3-links:{ 46 }
* id:46 rloc16:0xb800 ext-addr:fe109d277e0175cc
* 3-links:{ 02 51 57 }
* id:33 rloc16:0x8400 ext-addr:d2e511a146b9e54d
* 3-links:{ 51 57 }
* id:51 rloc16:0xcc00 ext-addr:9aab43ababf05352
* 3-links:{ 33 57 }
* 2-links:{ 46 }
* id:57 rloc16:0xe400 ext-addr:dae9c4c0e9da55ff
* 3-links:{ 46 51 }
* 1-links:{ 33 }
* Done
* @endcode
* @par
* Discover network topology (list of routers and their connections).
* Parameters are optional and indicate additional items to discover. Can be added in any order.
* * `ip6-addrs` to discover the list of IPv6 addresses of every router.
* * `children` to discover the child table of every router.
* @par
* Information per router:
* * Router ID
* * RLOC16
* * Extended MAC address
* * Whether the router is this device is itself (`me`)
* * Whether the router is the parent of this device when device is a child (`parent`)
* * Whether the router is `leader`
* * Whether the router acts as a border router providing external connectivity (`br`)
* * List of routers to which this router has a link:
* * `3-links`: Router IDs to which this router has a incoming link with link quality 3
* * `2-links`: Router IDs to which this router has a incoming link with link quality 2
* * `1-links`: Router IDs to which this router has a incoming link with link quality 1
* * If a list if empty, it is omitted in the out.
* * If `ip6-addrs`, list of IPv6 addresses of the router
* * If `children`, list of all children of the router. Information per child:
* * RLOC16
* * Incoming Link Quality from perspective of parent to child (zero indicates unknown)
* * Child Device mode (`r` rx-on-when-idle, `d` Full Thread Device, `n` Full Network Data, `-` no flags set)
* * Whether the child is this device itself (`me`)
* * Whether the child acts as a border router providing external connectivity (`br`)
* @cparam meshdiag topology [@ca{ip6-addrs}] [@ca{children}]
* @sa otMeshDiagDiscoverTopology
*/
if (aArgs[0] == "topology")
{
otMeshDiagDiscoverConfig config;
config.mDiscoverIp6Addresses = false;
config.mDiscoverChildTable = false;
aArgs++;
for (; !aArgs->IsEmpty(); aArgs++)
{
if (*aArgs == "ip6-addrs")
{
config.mDiscoverIp6Addresses = true;
}
else if (*aArgs == "children")
{
config.mDiscoverChildTable = true;
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
SuccessOrExit(error = otMeshDiagDiscoverTopology(GetInstancePtr(), &config, HandleMeshDiagDiscoverDone, this));
error = OT_ERROR_PENDING;
}
else
{
error = OT_ERROR_INVALID_COMMAND;
}
exit:
return error;
}
void Interpreter::HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext)
{
reinterpret_cast<Interpreter *>(aContext)->HandleMeshDiagDiscoverDone(aError, aRouterInfo);
}
void Interpreter::HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo)
{
VerifyOrExit(aRouterInfo != nullptr);
OutputFormat("id:%02u rloc16:0x%04x ext-addr:", aRouterInfo->mRouterId, aRouterInfo->mRloc16);
OutputExtAddress(aRouterInfo->mExtAddress);
if (aRouterInfo->mIsThisDevice)
{
OutputFormat(" - me");
}
if (aRouterInfo->mIsThisDeviceParent)
{
OutputFormat(" - parent");
}
if (aRouterInfo->mIsLeader)
{
OutputFormat(" - leader");
}
if (aRouterInfo->mIsBorderRouter)
{
OutputFormat(" - br");
}
OutputNewLine();
for (uint8_t linkQuality = 3; linkQuality > 0; linkQuality--)
{
bool hasLinkQuality = false;
for (uint8_t entryQuality : aRouterInfo->mLinkQualities)
{
if (entryQuality == linkQuality)
{
hasLinkQuality = true;
break;
}
}
if (hasLinkQuality)
{
OutputFormat(kIndentSize, "%u-links:{ ", linkQuality);
for (uint8_t id = 0; id < OT_ARRAY_LENGTH(aRouterInfo->mLinkQualities); id++)
{
if (aRouterInfo->mLinkQualities[id] == linkQuality)
{
OutputFormat("%02u ", id);
}
}
OutputLine("}");
}
}
if (aRouterInfo->mIp6AddrIterator != nullptr)
{
otIp6Address ip6Address;
OutputLine(kIndentSize, "ip6-addrs:");
while (otMeshDiagGetNextIp6Address(aRouterInfo->mIp6AddrIterator, &ip6Address) == OT_ERROR_NONE)
{
OutputSpaces(kIndentSize * 2);
OutputIp6AddressLine(ip6Address);
}
}
if (aRouterInfo->mChildIterator != nullptr)
{
otMeshDiagChildInfo childInfo;
char linkModeString[kLinkModeStringSize];
bool isFirst = true;
while (otMeshDiagGetNextChildInfo(aRouterInfo->mChildIterator, &childInfo) == OT_ERROR_NONE)
{
if (isFirst)
{
OutputLine(kIndentSize, "children:");
isFirst = false;
}
OutputFormat(kIndentSize * 2, "rloc16:0x%04x lq:%u, mode:%s", childInfo.mRloc16, childInfo.mLinkQuality,
LinkModeToString(childInfo.mMode, linkModeString));
if (childInfo.mIsThisDevice)
{
OutputFormat(" - me");
}
if (childInfo.mIsBorderRouter)
{
OutputFormat(" - br");
}
OutputNewLine();
}
if (isFirst)
{
OutputLine(kIndentSize, "children: none");
}
}
exit:
OutputResult(aError);
}
#endif // OPENTHREAD_CONFIG_MESH_DIAG_ENABLE
#endif // OPENTHREAD_FTD
template <> otError Interpreter::Process<Cmd("panid")>(Arg aArgs[])
@@ -7740,6 +7949,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
CmdEntry("macfilter"),
#endif
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
CmdEntry("meshdiag"),
#endif
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
CmdEntry("mliid"),
#endif
+5
View File
@@ -47,6 +47,7 @@
#include <openthread/ip6.h>
#include <openthread/link.h>
#include <openthread/logging.h>
#include <openthread/mesh_diag.h>
#include <openthread/netdata.h>
#include <openthread/ping_sender.h>
#include <openthread/sntp.h>
@@ -403,6 +404,10 @@ private:
uint16_t aRloc16);
void HandleLocateResult(otError aError, const otIp6Address *aMeshLocalAddress, uint16_t aRloc16);
#endif
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
static void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext);
void HandleMeshDiagDiscoverDone(otError aError, otMeshDiagRouterInfo *aRouterInfo);
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
static void HandleMlrRegResult(void *aContext,
otError aError,
+4
View File
@@ -326,6 +326,7 @@ openthread_core_files = [
"api/link_metrics_api.cpp",
"api/link_raw_api.cpp",
"api/logging_api.cpp",
"api/mesh_diag_api.cpp",
"api/message_api.cpp",
"api/multi_radio_api.cpp",
"api/nat64_api.cpp",
@@ -694,6 +695,8 @@ openthread_core_files = [
"utils/history_tracker.hpp",
"utils/jam_detector.cpp",
"utils/jam_detector.hpp",
"utils/mesh_diag.cpp",
"utils/mesh_diag.hpp",
"utils/otns.cpp",
"utils/otns.hpp",
"utils/parse_cmdline.cpp",
@@ -782,6 +785,7 @@ source_set("libopenthread_core_config") {
"config/link_raw.h",
"config/logging.h",
"config/mac.h",
"config/mesh_diag.h",
"config/misc.h",
"config/mle.h",
"config/nat64.h",
+2
View File
@@ -61,6 +61,7 @@ set(COMMON_SOURCES
api/link_metrics_api.cpp
api/link_raw_api.cpp
api/logging_api.cpp
api/mesh_diag_api.cpp
api/message_api.cpp
api/multi_radio_api.cpp
api/nat64_api.cpp
@@ -238,6 +239,7 @@ set(COMMON_SOURCES
utils/heap.cpp
utils/history_tracker.cpp
utils/jam_detector.cpp
utils/mesh_diag.cpp
utils/otns.cpp
utils/parse_cmdline.cpp
utils/ping_sender.cpp
+4
View File
@@ -151,6 +151,7 @@ SOURCES_COMMON = \
api/link_metrics_api.cpp \
api/link_raw_api.cpp \
api/logging_api.cpp \
api/mesh_diag_api.cpp \
api/message_api.cpp \
api/multi_radio_api.cpp \
api/nat64_api.cpp \
@@ -328,6 +329,7 @@ SOURCES_COMMON = \
utils/heap.cpp \
utils/history_tracker.cpp \
utils/jam_detector.cpp \
utils/mesh_diag.cpp \
utils/otns.cpp \
utils/parse_cmdline.cpp \
utils/ping_sender.cpp \
@@ -511,6 +513,7 @@ HEADERS_COMMON = \
config/link_raw.h \
config/logging.h \
config/mac.h \
config/mesh_diag.h \
config/misc.h \
config/mle.h \
config/nat64.h \
@@ -652,6 +655,7 @@ HEADERS_COMMON = \
utils/heap.hpp \
utils/history_tracker.hpp \
utils/jam_detector.hpp \
utils/mesh_diag.hpp \
utils/otns.hpp \
utils/parse_cmdline.hpp \
utils/ping_sender.hpp \
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023, 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 Mesh Diagnostics public APIs.
*/
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
#include <openthread/mesh_diag.h>
#include "common/as_core_type.hpp"
#include "common/locator_getters.hpp"
#include "utils/mesh_diag.hpp"
using namespace ot;
otError otMeshDiagDiscoverTopology(otInstance *aInstance,
const otMeshDiagDiscoverConfig *aConfig,
otMeshDiagDiscoverCallback aCallback,
void *aContext)
{
AssertPointerIsNotNull(aConfig);
return AsCoreType(aInstance).Get<Utils::MeshDiag>().DiscoverTopology(*aConfig, aCallback, aContext);
}
void otMeshDiagCancel(otInstance *aInstance) { AsCoreType(aInstance).Get<Utils::MeshDiag>().Cancel(); }
otError otMeshDiagGetNextIp6Address(otMeshDiagIp6AddrIterator *aIterator, otIp6Address *aIp6Address)
{
return AsCoreType(aIterator).GetNextAddress(AsCoreType(aIp6Address));
}
otError otMeshDiagGetNextChildInfo(otMeshDiagChildIterator *aIterator, otMeshDiagChildInfo *aChildInfo)
{
return AsCoreType(aIterator).GetNextChildInfo(AsCoreType(aChildInfo));
}
#endif // OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
+3
View File
@@ -206,6 +206,9 @@ Instance::Instance(void)
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
, mChannelManager(*this)
#endif
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
, mMeshDiag(*this)
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
, mHistoryTracker(*this)
#endif
+9
View File
@@ -127,6 +127,7 @@
#include "utils/heap.hpp"
#include "utils/history_tracker.hpp"
#include "utils/jam_detector.hpp"
#include "utils/mesh_diag.hpp"
#include "utils/ping_sender.hpp"
#include "utils/slaac_address.hpp"
#include "utils/srp_client_buffers.hpp"
@@ -585,6 +586,10 @@ private:
Utils::ChannelManager mChannelManager;
#endif
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
Utils::MeshDiag mMeshDiag;
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Utils::HistoryTracker mHistoryTracker;
#endif
@@ -864,6 +869,10 @@ template <> inline Utils::ChannelMonitor &Instance::Get(void) { return mChannelM
template <> inline Utils::ChannelManager &Instance::Get(void) { return mChannelManager; }
#endif
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
template <> inline Utils::MeshDiag &Instance::Get(void) { return mMeshDiag; }
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
template <> inline Utils::HistoryTracker &Instance::Get(void) { return mHistoryTracker; }
#endif
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2023, 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 compile-time configurations for Mesh Diagnostic module.
*
*/
#ifndef CONFIG_MESH_DIAG_H_
#define CONFIG_MESH_DIAG_H_
#include "config/border_routing.h"
/**
* @def OPENTHREAD_CONFIG_MESH_DIAG_ENABLE
*
* Define to 1 to enable Mesh Diagnostic module.
*
* By default this feature is enabled if device is configured to act as Border Router.
*
*/
#ifndef OPENTHREAD_CONFIG_MESH_DIAG_ENABLE
#define OPENTHREAD_CONFIG_MESH_DIAG_ENABLE OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif
/**
* @def OPENTHREAD_CONFIG_MESH_DIAG_RESPONSE_TIMEOUT
*
* Specifies the timeout interval in milliseconds waiting for response from router during discover.
*
*/
#ifndef OPENTHREAD_CONFIG_MESH_DIAG_RESPONSE_TIMEOUT
#define OPENTHREAD_CONFIG_MESH_DIAG_RESPONSE_TIMEOUT 5000
#endif
#endif // CONFIG_MESH_DIAG_H_
+1
View File
@@ -82,6 +82,7 @@
#include "config/link_raw.h"
#include "config/logging.h"
#include "config/mac.h"
#include "config/mesh_diag.h"
#include "config/misc.h"
#include "config/mle.h"
#include "config/nat64.h"
+295
View File
@@ -0,0 +1,295 @@
/*
* Copyright (c) 2023, 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 Mesh Diag module.
*/
#include "mesh_diag.hpp"
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
namespace ot {
namespace Utils {
using namespace ot::NetworkDiagnostic;
RegisterLogModule("MeshDiag");
//---------------------------------------------------------------------------------------------------------------------
// MeshDiag
MeshDiag::MeshDiag(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimer(aInstance)
{
}
Error MeshDiag::DiscoverTopology(const DiscoverConfig &aConfig, DiscoverCallback aCallback, void *aContext)
{
Error error = kErrorNone;
VerifyOrExit(Get<Mle::Mle>().IsAttached(), error = kErrorInvalidState);
VerifyOrExit(!mTimer.IsRunning(), error = kErrorBusy);
Get<RouterTable>().GetRouterIdSet(mExpectedRouterIdSet);
for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
{
if (mExpectedRouterIdSet.Contains(routerId))
{
SuccessOrExit(error = SendDiagGetTo(Mle::Rloc16FromRouterId(routerId), aConfig));
}
}
mDiscoverCallback.Set(aCallback, aContext);
mTimer.Start(kResponseTimeout);
exit:
return error;
}
void MeshDiag::Cancel(void)
{
mTimer.Stop();
IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleDiagGetResponse, this));
}
Error MeshDiag::SendDiagGetTo(uint16_t aRloc16, const DiscoverConfig &aConfig)
{
Error error = kErrorNone;
Coap::Message *message = nullptr;
Tmf::MessageInfo messageInfo(GetInstance());
uint8_t tlvs[kMaxTlvsToRequest];
uint8_t tlvsLength;
message = Get<Tmf::Agent>().NewConfirmablePostMessage(kUriDiagnosticGetRequest);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
IgnoreError(message->SetPriority(Message::kPriorityLow));
tlvs[0] = Address16Tlv::kType;
tlvs[1] = ExtMacAddressTlv::kType;
tlvs[2] = RouteTlv::kType;
tlvsLength = 3;
if (aConfig.mDiscoverIp6Addresses)
{
tlvs[tlvsLength++] = Ip6AddressListTlv::kType;
}
if (aConfig.mDiscoverChildTable)
{
tlvs[tlvsLength++] = ChildTableTlv::kType;
}
SuccessOrExit(error = Tlv::Append<TypeListTlv>(*message, tlvs, tlvsLength));
messageInfo.SetSockAddrToRlocPeerAddrTo(aRloc16);
error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleDiagGetResponse, this);
exit:
FreeMessageOnError(message, error);
return error;
}
void MeshDiag::HandleDiagGetResponse(void *aContext,
otMessage *aMessage,
const otMessageInfo *aMessageInfo,
Error aResult)
{
static_cast<MeshDiag *>(aContext)->HandleDiagGetResponse(AsCoapMessagePtr(aMessage), AsCoreTypePtr(aMessageInfo),
aResult);
}
void MeshDiag::HandleDiagGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
Error error;
RouterInfo routerInfo;
Ip6AddrIterator ip6AddrIterator;
ChildIterator childIterator;
SuccessOrExit(aResult);
VerifyOrExit((aMessage != nullptr) && mTimer.IsRunning());
SuccessOrExit(routerInfo.ParseFrom(*aMessage));
if (ip6AddrIterator.InitFrom(*aMessage) == kErrorNone)
{
routerInfo.mIp6AddrIterator = &ip6AddrIterator;
}
if (childIterator.InitFrom(*aMessage, routerInfo.mRloc16) == kErrorNone)
{
routerInfo.mChildIterator = &childIterator;
}
mExpectedRouterIdSet.Remove(routerInfo.mRouterId);
if (mExpectedRouterIdSet.GetNumberOfAllocatedIds() == 0)
{
error = kErrorNone;
mTimer.Stop();
}
else
{
error = kErrorPending;
}
mDiscoverCallback.InvokeIfSet(error, &routerInfo);
exit:
return;
}
void MeshDiag::HandleTimer(void)
{
// Timed out waiting for response from one or more routers.
IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleDiagGetResponse, this));
mDiscoverCallback.InvokeIfSet(kErrorResponseTimeout, nullptr);
}
//---------------------------------------------------------------------------------------------------------------------
// MeshDiag::RouterInfo
Error MeshDiag::RouterInfo::ParseFrom(const Message &aMessage)
{
Error error = kErrorNone;
Mle::Mle &mle = aMessage.Get<Mle::Mle>();
RouteTlv routeTlv;
Clear();
SuccessOrExit(error = Tlv::Find<Address16Tlv>(aMessage, mRloc16));
SuccessOrExit(error = Tlv::Find<ExtMacAddressTlv>(aMessage, AsCoreType(&mExtAddress)));
SuccessOrExit(error = Tlv::FindTlv(aMessage, routeTlv));
mRouterId = Mle::RouterIdFromRloc16(mRloc16);
mIsThisDevice = (mRloc16 == mle.GetRloc16());
mIsThisDeviceParent = mle.IsChild() && (mRloc16 == mle.GetParent().GetRloc16());
mIsLeader = (mRouterId == mle.GetLeaderId());
mIsBorderRouter = aMessage.Get<NetworkData::Leader>().ContainsBorderRouterWithRloc(mRloc16);
for (uint8_t id = 0, index = 0; id <= Mle::kMaxRouterId; id++)
{
if (routeTlv.IsRouterIdSet(id))
{
mLinkQualities[id] = routeTlv.GetLinkQualityIn(index);
index++;
}
}
exit:
return error;
}
//---------------------------------------------------------------------------------------------------------------------
// MeshDiag::Ip6AddrIterator
Error MeshDiag::Ip6AddrIterator::InitFrom(const Message &aMessage)
{
Error error;
uint16_t tlvLength;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Ip6AddressListTlv::kType, mCurOffset, tlvLength));
mEndOffset = mCurOffset + tlvLength;
mMessage = &aMessage;
exit:
return error;
}
Error MeshDiag::Ip6AddrIterator::GetNextAddress(Ip6::Address &aAddress)
{
Error error = kErrorNone;
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
VerifyOrExit(mCurOffset + sizeof(Ip6::Address) <= mEndOffset, error = kErrorNotFound);
IgnoreError(mMessage->Read(mCurOffset, aAddress));
mCurOffset += sizeof(Ip6::Address);
exit:
return error;
}
//---------------------------------------------------------------------------------------------------------------------
// MeshDiag::ChildIterator
Error MeshDiag::ChildIterator::InitFrom(const Message &aMessage, uint16_t aParentRloc16)
{
Error error;
uint16_t tlvLength;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, ChildTableTlv::kType, mCurOffset, tlvLength));
mEndOffset = mCurOffset + tlvLength;
mMessage = &aMessage;
mParentRloc16 = aParentRloc16;
exit:
return error;
}
Error MeshDiag::ChildIterator::GetNextChildInfo(ChildInfo &aChildInfo)
{
Error error = kErrorNone;
ChildTableEntry entry;
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
VerifyOrExit(mCurOffset + sizeof(ChildTableEntry) <= mEndOffset, error = kErrorNotFound);
IgnoreError(mMessage->Read(mCurOffset, entry));
mCurOffset += sizeof(ChildTableEntry);
aChildInfo.mRloc16 = mParentRloc16 + entry.GetChildId();
entry.GetMode().Get(aChildInfo.mMode);
aChildInfo.mLinkQuality = entry.GetLinkQuality();
aChildInfo.mIsThisDevice = (aChildInfo.mRloc16 == mMessage->Get<Mle::Mle>().GetRloc16());
aChildInfo.mIsBorderRouter = mMessage->Get<NetworkData::Leader>().ContainsBorderRouterWithRloc(aChildInfo.mRloc16);
exit:
return error;
}
} // namespace Utils
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
+213
View File
@@ -0,0 +1,213 @@
/*
* Copyright (c) 2023, 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 Mesh Diagnostic module.
*/
#ifndef MESH_DIAG_HPP_
#define MESH_DIAG_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
#include <openthread/mesh_diag.h>
#include "coap/coap.hpp"
#include "common/callback.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/timer.hpp"
#include "net/ip6_address.hpp"
#include "thread/network_diagnostic_tlvs.hpp"
struct otMeshDiagIp6AddrIterator
{
};
struct otMeshDiagChildIterator
{
};
namespace ot {
namespace Utils {
/**
* This class implements the Mesh Diagnostics.
*
*/
class MeshDiag : public InstanceLocator
{
public:
typedef otMeshDiagDiscoverConfig DiscoverConfig; ///< The discovery configuration.
typedef otMeshDiagDiscoverCallback DiscoverCallback; ///< The discovery callback function pointer type.
/**
* This type represents an iterator to go over list of IPv6 addresses of a router.
*
*/
class Ip6AddrIterator : public otMeshDiagIp6AddrIterator
{
friend class MeshDiag;
public:
/**
* This method iterates through the discovered IPv6 address of a router.
*
* @param[out] aIp6Address A reference to return the next IPv6 address (if any).
*
* @retval kErrorNone Successfully retrieved the next address. @p aIp6Address is updated.
* @retval kErrorNotFound No more address. Reached the end of the list.
*
*/
Error GetNextAddress(Ip6::Address &aAddress);
private:
Error InitFrom(const Message &aMessage);
const Message *mMessage;
uint16_t mCurOffset;
uint16_t mEndOffset;
};
/**
* This type represents information about a router in Thread mesh.
*
*/
class RouterInfo : public otMeshDiagRouterInfo, public Clearable<RouterInfo>
{
friend class MeshDiag;
private:
Error ParseFrom(const Message &aMessage);
};
/**
* This type represents information about a child in Thread mesh.
*
*/
class ChildInfo : public otMeshDiagChildInfo, public Clearable<ChildInfo>
{
};
/**
* This type represents an iterator to go over list of IPv6 addresses of a router.
*
*/
class ChildIterator : public otMeshDiagChildIterator
{
friend class MeshDiag;
public:
/**
* This method iterates through the discovered children of a router.
*
* @param[out] aChildInfo A reference to return the info for the next child (if any).
*
* @retval kErrorNone Successfully retrieved the next child info. @p aChildInfo is updated.
* @retval kErrorNotFound No more child entry. Reached the end of the list.
*
*/
Error GetNextChildInfo(ChildInfo &aChildInfo);
private:
Error InitFrom(const Message &aMessage, uint16_t aParentRloc16);
const Message *mMessage;
uint16_t mCurOffset;
uint16_t mEndOffset;
uint16_t mParentRloc16;
};
/**
* This constructor initializes the `MeshDiag` instance.
*
* @param[in] aInstance The OpenThread instance.
*
*/
explicit MeshDiag(Instance &aInstance);
/**
* This method starts network topology discovery.
*
* @param[in] aConfig The configuration to use for discovery (e.g., which items to discover).
* @param[in] aCallback The callback to report the discovered routers.
* @param[in] aContext A context to pass in @p aCallback.
*
* @retval kErrorNone The network topology discovery started successfully.
* @retval kErrorBusy A previous discovery request is still ongoing.
* @retval kErrorInvalidState Device is not attached.
* @retval kErrorNoBufs Could not allocate buffer to send discovery messages.
*
*/
Error DiscoverTopology(const DiscoverConfig &aConfig, DiscoverCallback aCallback, void *aContext);
/**
* This method cancels an ongoing topology discovery if there one, otherwise no action.
*
* When ongoing discovery is cancelled, the callback from `DiscoverTopology()` will not be called anymore.
*
*/
void Cancel(void);
private:
typedef ot::NetworkDiagnostic::Tlv Tlv;
static constexpr uint32_t kResponseTimeout = OPENTHREAD_CONFIG_MESH_DIAG_RESPONSE_TIMEOUT;
static constexpr uint8_t kMaxTlvsToRequest = 5;
Error SendDiagGetTo(uint16_t aRloc16, const DiscoverConfig &aConfig);
void HandleTimer(void);
void HandleDiagGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleDiagGetResponse(void *aContext,
otMessage *aMessage,
const otMessageInfo *aMessageInfo,
Error aResult);
using TimeoutTimer = TimerMilliIn<MeshDiag, &MeshDiag::HandleTimer>;
Callback<DiscoverCallback> mDiscoverCallback;
Mle::RouterIdSet mExpectedRouterIdSet;
TimeoutTimer mTimer;
};
} // namespace Utils
DefineCoreType(otMeshDiagIp6AddrIterator, Utils::MeshDiag::Ip6AddrIterator);
DefineCoreType(otMeshDiagRouterInfo, Utils::MeshDiag::RouterInfo);
DefineCoreType(otMeshDiagChildInfo, Utils::MeshDiag::ChildInfo);
DefineCoreType(otMeshDiagChildIterator, Utils::MeshDiag::ChildIterator);
} // namespace ot
#endif // OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
#endif // MESH_DIAG_HPP_
@@ -83,6 +83,14 @@
*/
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_MESH_DIAG_ENABLE
*
* Define as 1 to enable Mesh Diagnostics module.
*
*/
#define OPENTHREAD_CONFIG_MESH_DIAG_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
*