mirror of
https://github.com/espressif/openthread.git
synced 2025-05-17 07:16:08 +08:00
[net-diag] implement non-preferred channels mask TLV support (#11367)
This commit adds support for the "non-preferred channels" TLV in Network Diagnostics. New APIs and their related CLI commands are added to allow users to get/set this value, which is then used to respond to Diagnostic Get/Query messages requesting this TLV. This commit also introduces a mechanism to monitor and notify the caller when a Network Diagnostic Reset command is received for this TLV. The `test-020-net-diag` test is updated to validate the new TLV and its API.
This commit is contained in:

committed by
GitHub

parent
7cfae1e05e
commit
d2fcf539da
@ -152,7 +152,10 @@ typedef struct otSecurityPolicy
|
||||
} otSecurityPolicy;
|
||||
|
||||
/**
|
||||
* Represents Channel Mask.
|
||||
* Represents a Channel Mask.
|
||||
*
|
||||
* The least significant bit (LSB), also referred to as bit 0, corresponds to channel number 0, and so on.
|
||||
*
|
||||
*/
|
||||
typedef uint32_t otChannelMask;
|
||||
|
||||
|
@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (492)
|
||||
#define OPENTHREAD_API_VERSION (493)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
@ -35,6 +35,7 @@
|
||||
#ifndef OPENTHREAD_NETDIAG_H_
|
||||
#define OPENTHREAD_NETDIAG_H_
|
||||
|
||||
#include <openthread/dataset.h>
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/thread.h>
|
||||
|
||||
@ -48,36 +49,37 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS 0 ///< MAC Extended Address TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS 1 ///< Address16 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MODE 2 ///< Mode TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT 3 ///< Timeout TLV (max polling time period for SEDs)
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY 4 ///< Connectivity TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ROUTE 5 ///< Route64 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA 6 ///< Leader Data TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA 7 ///< Network Data TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST 8 ///< IPv6 Address List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS 9 ///< MAC Counters TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL 14 ///< Battery Level TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE 15 ///< Supply Voltage TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE 16 ///< Child Table TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES 17 ///< Channel Pages TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST 18 ///< Type List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT 19 ///< Max Child Timeout TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_EUI64 23 ///< EUI64 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VERSION 24 ///< Thread Version TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME 25 ///< Vendor Name TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL 26 ///< Vendor Model TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION 27 ///< Vendor SW Version TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION 28 ///< Thread Stack Version TLV (codebase/commit version)
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD 29 ///< Child TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST 30 ///< Child IPv6 Address List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR 31 ///< Router Neighbor TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ANSWER 32 ///< Answer TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID 33 ///< Query ID TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS 34 ///< MLE Counters TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL 35 ///< Vendor App URL TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ENHANCED_ROUTE 37 ///< Enhanced Route TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS 0 ///< MAC Extended Address TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS 1 ///< Address16 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MODE 2 ///< Mode TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT 3 ///< Timeout TLV (max polling time period for SEDs)
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY 4 ///< Connectivity TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ROUTE 5 ///< Route64 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA 6 ///< Leader Data TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA 7 ///< Network Data TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST 8 ///< IPv6 Address List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS 9 ///< MAC Counters TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL 14 ///< Battery Level TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE 15 ///< Supply Voltage TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE 16 ///< Child Table TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES 17 ///< Channel Pages TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST 18 ///< Type List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT 19 ///< Max Child Timeout TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_EUI64 23 ///< EUI64 TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VERSION 24 ///< Thread Version TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME 25 ///< Vendor Name TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL 26 ///< Vendor Model TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION 27 ///< Vendor SW Version TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION 28 ///< Thread Stack Version TLV (codebase/commit version)
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD 29 ///< Child TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST 30 ///< Child IPv6 Address List TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR 31 ///< Router Neighbor TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ANSWER 32 ///< Answer TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID 33 ///< Query ID TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS 34 ///< MLE Counters TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL 35 ///< Vendor App URL TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS 36 ///< Non-Preferred Channels Mask TLV
|
||||
#define OT_NETWORK_DIAGNOSTIC_TLV_ENHANCED_ROUTE 37 ///< Enhanced Route TLV
|
||||
|
||||
#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH 32 ///< Max length of Vendor Name TLV.
|
||||
#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH 32 ///< Max length of Vendor Model TLV.
|
||||
@ -254,6 +256,7 @@ typedef struct otNetworkDiagTlv
|
||||
char mVendorSwVersion[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH + 1];
|
||||
char mThreadStackVersion[OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH + 1];
|
||||
char mVendorAppUrl[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH + 1];
|
||||
otChannelMask mNonPreferredChannels;
|
||||
struct
|
||||
{
|
||||
uint8_t mCount;
|
||||
@ -453,6 +456,48 @@ otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwV
|
||||
*/
|
||||
otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl);
|
||||
|
||||
/**
|
||||
* Callback function pointer to notify when a Network Diagnostic Reset request message is received for the
|
||||
* `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.
|
||||
*
|
||||
* This is used to inform the device to reevaluate the channels that are presently included in the non-preferred
|
||||
* channels list and update it if needed based on the reevaluation.
|
||||
*
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*/
|
||||
typedef void (*otThreadNonPreferredChannelsResetCallback)(void *aContext);
|
||||
|
||||
/**
|
||||
* Sets the non-preferred channels value for `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.
|
||||
*
|
||||
* This value is used to respond to a Network Diagnostic Get request for this TLV.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aChannelMask A channel mask specifying the non-preferred channels.
|
||||
*/
|
||||
void otThreadSetNonPreferredChannels(otInstance *aInstance, otChannelMask aChannelMask);
|
||||
|
||||
/**
|
||||
* Gets the non-preferred channels for `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.
|
||||
*
|
||||
* @returns The non-preferred channels as a channel mask.
|
||||
*/
|
||||
otChannelMask otThreadGetNonPreferredChannels(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets the callback to notify when a Network Diagnostic Reset request message is received for the
|
||||
* `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.
|
||||
*
|
||||
* A subsequent call to this function will replace the previously set callback.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCallback The callback function pointer. Can be NULL.
|
||||
* @param[in] aContext A pointer to application-specific context used with @p aCallback.
|
||||
*/
|
||||
void otThreadSetNonPreferredChannelsResetCallback(otInstance *aInstance,
|
||||
otThreadNonPreferredChannelsResetCallback aCallback,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -2864,13 +2864,26 @@ Done
|
||||
|
||||
### networkdiagnostic reset \<addr\> \<type\> ..
|
||||
|
||||
Send network diagnostic request to reset \<addr\>'s tlv of \<type\>s. Currently only `MAC Counters`(9) is supported.
|
||||
Send network diagnostic request to reset \<addr\>'s tlv of \<type\>s. Currently `MAC Counters`(9) is supported.
|
||||
|
||||
```bash
|
||||
> diagnostic reset fd00:db8::ff:fe00:0 9
|
||||
Done
|
||||
```
|
||||
|
||||
### networkdiagnostic nonpreferredchannels
|
||||
|
||||
Get or set the non-preferred channels value as a channel mask. This is used to respond to a Network Diagnostics Get request for the corresponding TLV. The channel mask is a 32-bit unsigned integer value where the least significant bit (LSB), also referred to as bit 0, corresponds to channel number 0, and so on.
|
||||
|
||||
```bash
|
||||
> networkdiagnostic nonpreferredchannels 0x4000000
|
||||
Done
|
||||
|
||||
> networkdiagnostic nonpreferredchannels
|
||||
0x4000000
|
||||
Done
|
||||
```
|
||||
|
||||
### networkidtimeout
|
||||
|
||||
Get the NETWORK_ID_TIMEOUT parameter used in the Router role.
|
||||
|
@ -7468,6 +7468,46 @@ template <> otError Interpreter::Process<Cmd("networkdiagnostic")>(Arg aArgs[])
|
||||
uint8_t tlvTypes[kMaxTlvs];
|
||||
uint8_t count = 0;
|
||||
|
||||
if (aArgs[0] == "nonpreferredchannels")
|
||||
{
|
||||
/**
|
||||
* @cli networkdiagnostic nonpreferredchannels
|
||||
* @code
|
||||
* networkdiagnostic nonpreferredchannels
|
||||
* 0x4000000
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otThreadGetNonPreferredChannels
|
||||
*/
|
||||
if (aArgs[1].IsEmpty())
|
||||
{
|
||||
OutputLine("0x%lx", ToUlong(otThreadGetNonPreferredChannels(GetInstancePtr())));
|
||||
}
|
||||
/**
|
||||
* @cli networkdiagnostic nonpreferredchannels (set)
|
||||
* @code
|
||||
* networkdiagnostic nonpreferredchannels 0x4000000
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otThreadSetNonPreferredChannels
|
||||
* @cparam networkdiagnostic nonprfchannelmas @ca{mask}
|
||||
*/
|
||||
else
|
||||
{
|
||||
otChannelMask mask;
|
||||
|
||||
SuccessOrExit(error = aArgs[1].ParseAsUint32(mask));
|
||||
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
otThreadSetNonPreferredChannels(GetInstancePtr(), mask);
|
||||
}
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
// Process args for `get` and `reset` commands.
|
||||
|
||||
SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
|
||||
|
||||
for (Arg *arg = &aArgs[2]; !arg->IsEmpty(); arg++)
|
||||
@ -7709,6 +7749,9 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError,
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION:
|
||||
OutputLine("Thread Stack Version: %s", diagTlv.mData.mThreadStackVersion);
|
||||
break;
|
||||
case OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS:
|
||||
OutputLine("Non-preferred Channels Mask: 0x%lx", ToUlong(diagTlv.mData.mNonPreferredChannels));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -112,3 +112,20 @@ otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl
|
||||
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().SetVendorAppUrl(aVendorAppUrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
void otThreadSetNonPreferredChannels(otInstance *aInstance, otChannelMask aChannelMask)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().SetNonPreferredChannels(aChannelMask);
|
||||
}
|
||||
|
||||
otChannelMask otThreadGetNonPreferredChannels(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().GetNonPreferredChannels();
|
||||
}
|
||||
|
||||
void otThreadSetNonPreferredChannelsResetCallback(otInstance *aInstance,
|
||||
otThreadNonPreferredChannelsResetCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().SetNonPreferredChannelsResetCallback(aCallback, aContext);
|
||||
}
|
||||
|
@ -140,20 +140,26 @@ Error ChannelMaskTlv::ReadChannelMask(uint32_t &aChannelMask) const
|
||||
Error ChannelMaskTlv::FindIn(const Message &aMessage, uint32_t &aChannelMask)
|
||||
{
|
||||
Error error;
|
||||
EntriesData entriesData;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
entriesData.Clear();
|
||||
entriesData.mMessage = &aMessage;
|
||||
|
||||
SuccessOrExit(error = FindTlvValueOffsetRange(aMessage, Tlv::kChannelMask, offsetRange));
|
||||
entriesData.mOffsetRange = offsetRange;
|
||||
error = entriesData.Parse(aChannelMask);
|
||||
error = ParseValue(aMessage, offsetRange, aChannelMask);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error ChannelMaskTlv::ParseValue(const Message &aMessage, const OffsetRange &aOffsetRange, uint32_t &aChannelMask)
|
||||
{
|
||||
EntriesData entriesData;
|
||||
|
||||
entriesData.Clear();
|
||||
entriesData.mMessage = &aMessage;
|
||||
entriesData.mOffsetRange = aOffsetRange;
|
||||
|
||||
return entriesData.Parse(aChannelMask);
|
||||
}
|
||||
|
||||
Error ChannelMaskTlv::EntriesData::Parse(uint32_t &aChannelMask)
|
||||
{
|
||||
// Validates and parses the Channel Mask TLV entries for each
|
||||
@ -217,7 +223,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void ChannelMaskTlv::PrepareValue(Value &aValue, uint32_t aChannelMask)
|
||||
void ChannelMaskTlv::PrepareValue(Value &aValue, uint32_t aChannelMask, bool aIncludeZeroPageMasks)
|
||||
{
|
||||
Entry *entry = reinterpret_cast<Entry *>(aValue.mData);
|
||||
|
||||
@ -227,7 +233,7 @@ void ChannelMaskTlv::PrepareValue(Value &aValue, uint32_t aChannelMask)
|
||||
{
|
||||
uint32_t mask = (Radio::ChannelMaskForPage(page) & aChannelMask);
|
||||
|
||||
if (mask != 0)
|
||||
if ((mask != 0) || aIncludeZeroPageMasks)
|
||||
{
|
||||
entry->SetChannelPage(page);
|
||||
entry->SetMaskLength(kMaskLength);
|
||||
|
@ -640,13 +640,31 @@ public:
|
||||
*/
|
||||
static Error FindIn(const Message &aMessage, uint32_t &aChannelMask);
|
||||
|
||||
/**
|
||||
* Parses and validates the TLV value and returns the combined channel mask for all supported channel pages
|
||||
* included in the TLV.
|
||||
*
|
||||
* The Channel Mask TLV value entries for each channel page are parsed one by one and `aChannelMask` is updated
|
||||
* to return the combined mask for all channel pages that are supported by radio. Note that @p aOffsetRange
|
||||
* corresponds to offset range where the TLV value resides within @p aMessage (not the full TLV).
|
||||
*
|
||||
* @param[in] aMessage The message to read the TLV value from.
|
||||
* @param[in] aOffsetRange The offset range for the TLV value.
|
||||
* @param[out] aChannelMask A reference to return the channel mask.
|
||||
*
|
||||
* @retval kErrorNone Successfully parsed the TLV value, @p aChannelMask is updated.
|
||||
* @retval kErrorParse Failed to parse the TLV value.
|
||||
*/
|
||||
static Error ParseValue(const Message &aMessage, const OffsetRange &aOffsetRange, uint32_t &aChannelMask);
|
||||
|
||||
/**
|
||||
* Prepares Channel Mask TLV value for appending/writing.
|
||||
*
|
||||
* @param[out] aValue A reference to `Value` structure to populate.
|
||||
* @param[in] aChannelMask The combined channel mask for all supported channel pages.
|
||||
* @param[out] aValue A reference to `Value` structure to populate.
|
||||
* @param[in] aChannelMask The combined channel mask for all supported channel pages.
|
||||
* @param[in] aIncludeZeroPageMasks Determine whether to include or skip a zero mask for a supported channel page.
|
||||
*/
|
||||
static void PrepareValue(Value &aValue, uint32_t aChannelMask);
|
||||
static void PrepareValue(Value &aValue, uint32_t aChannelMask, bool aIncludeZeroPageMasks = false);
|
||||
|
||||
/**
|
||||
* Prepares a Channel Mask TLV value and appends the TLV to a given message.
|
||||
|
@ -51,6 +51,7 @@ const char Server::kVendorAppUrl[] = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_UR
|
||||
|
||||
Server::Server(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mNonPreferredChannels(0)
|
||||
{
|
||||
static_assert(sizeof(kVendorName) <= sizeof(VendorNameTlv::StringType), "VENDOR_NAME is too long");
|
||||
static_assert(sizeof(kVendorModel) <= sizeof(VendorModelTlv::StringType), "VENDOR_MODEL is too long");
|
||||
@ -387,6 +388,15 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kNonPreferredChannels:
|
||||
{
|
||||
MeshCoP::ChannelMaskTlv::Value value;
|
||||
|
||||
MeshCoP::ChannelMaskTlv::PrepareValue(value, mNonPreferredChannels, /* aIncludeZeroPageMasks */ true);
|
||||
error = Tlv::AppendTlv(aMessage, Tlv::kNonPreferredChannels, value.mData, value.mLength);
|
||||
break;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
case Tlv::kConnectivity:
|
||||
@ -884,6 +894,10 @@ template <> void Server::HandleTmf<kUriDiagnosticReset>(Coap::Message &aMessage,
|
||||
Get<Mle::Mle>().ResetCounters();
|
||||
break;
|
||||
|
||||
case Tlv::kNonPreferredChannels:
|
||||
mNonPreferredChannelsResetCallback.InvokeIfSet();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1110,9 +1124,8 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
|
||||
while (offset < aMessage.GetLength())
|
||||
{
|
||||
bool skipTlv = false;
|
||||
uint16_t valueOffset;
|
||||
uint16_t tlvLength;
|
||||
bool skipTlv = false;
|
||||
OffsetRange valueOffsetRange;
|
||||
union
|
||||
{
|
||||
Tlv tlv;
|
||||
@ -1124,13 +1137,11 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = aMessage.Read(offset, extTlv));
|
||||
valueOffset = offset + sizeof(ExtendedTlv);
|
||||
tlvLength = extTlv.GetLength();
|
||||
valueOffsetRange.Init(offset + sizeof(ExtendedTlv), extTlv.GetLength());
|
||||
}
|
||||
else
|
||||
{
|
||||
valueOffset = offset + sizeof(Tlv);
|
||||
tlvLength = tlv.GetLength();
|
||||
valueOffsetRange.Init(offset + sizeof(Tlv), tlv.GetLength());
|
||||
}
|
||||
|
||||
VerifyOrExit(offset + tlv.GetSize() <= aMessage.GetLength(), error = kErrorParse);
|
||||
@ -1201,9 +1212,9 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
static_assert(sizeof(aTlvInfo.mData.mNetworkData.m8) >= NetworkData::NetworkData::kMaxSize,
|
||||
"NetworkData array in `otNetworkDiagTlv` is too small");
|
||||
|
||||
VerifyOrExit(tlvLength <= NetworkData::NetworkData::kMaxSize, error = kErrorParse);
|
||||
aTlvInfo.mData.mNetworkData.mCount = static_cast<uint8_t>(tlvLength);
|
||||
aMessage.ReadBytes(valueOffset, aTlvInfo.mData.mNetworkData.m8, tlvLength);
|
||||
VerifyOrExit(valueOffsetRange.GetLength() <= NetworkData::NetworkData::kMaxSize, error = kErrorParse);
|
||||
aTlvInfo.mData.mNetworkData.mCount = static_cast<uint8_t>(valueOffsetRange.GetLength());
|
||||
aMessage.ReadBytes(valueOffsetRange, aTlvInfo.mData.mNetworkData.m8);
|
||||
break;
|
||||
|
||||
case Tlv::kIp6AddressList:
|
||||
@ -1212,7 +1223,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
Ip6::Address *addrEntry = AsCoreTypePtr(&aTlvInfo.mData.mIp6AddrList.mList[0]);
|
||||
uint8_t &addrCount = aTlvInfo.mData.mIp6AddrList.mCount;
|
||||
|
||||
VerifyOrExit((tlvLength % Ip6::Address::kSize) == 0, error = kErrorParse);
|
||||
VerifyOrExit((valueOffsetRange.GetLength() % Ip6::Address::kSize) == 0, error = kErrorParse);
|
||||
|
||||
// `TlvInfo` has a fixed array for IPv6 addresses. If there
|
||||
// are more addresses in the message, we read and return as
|
||||
@ -1220,13 +1231,12 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
|
||||
addrCount = 0;
|
||||
|
||||
while ((tlvLength > 0) && (addrCount < addrListLength))
|
||||
while (!valueOffsetRange.IsEmpty() && (addrCount < addrListLength))
|
||||
{
|
||||
SuccessOrExit(error = aMessage.Read(valueOffset, *addrEntry));
|
||||
SuccessOrExit(error = aMessage.Read(valueOffsetRange, *addrEntry));
|
||||
addrCount++;
|
||||
addrEntry++;
|
||||
valueOffset += Ip6::Address::kSize;
|
||||
tlvLength -= Ip6::Address::kSize;
|
||||
valueOffsetRange.AdvanceOffset(Ip6::Address::kSize);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1266,7 +1276,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
ChildInfo *childInfo = &aTlvInfo.mData.mChildTable.mTable[0];
|
||||
uint8_t &childCount = aTlvInfo.mData.mChildTable.mCount;
|
||||
|
||||
VerifyOrExit((tlvLength % sizeof(ChildTableEntry)) == 0, error = kErrorParse);
|
||||
VerifyOrExit((valueOffsetRange.GetLength() % sizeof(ChildTableEntry)) == 0, error = kErrorParse);
|
||||
|
||||
// `TlvInfo` has a fixed array Child Table entries. If there
|
||||
// are more entries in the message, we read and return as
|
||||
@ -1274,11 +1284,11 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
|
||||
childCount = 0;
|
||||
|
||||
while ((tlvLength > 0) && (childCount < childInfoLength))
|
||||
while (!valueOffsetRange.IsEmpty() && (childCount < childInfoLength))
|
||||
{
|
||||
ChildTableEntry entry;
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(valueOffset, entry));
|
||||
SuccessOrExit(error = aMessage.Read(valueOffsetRange, entry));
|
||||
|
||||
childInfo->mTimeout = entry.GetTimeout();
|
||||
childInfo->mLinkQuality = entry.GetLinkQuality();
|
||||
@ -1287,17 +1297,17 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
|
||||
childCount++;
|
||||
childInfo++;
|
||||
tlvLength -= sizeof(ChildTableEntry);
|
||||
valueOffset += sizeof(ChildTableEntry);
|
||||
valueOffsetRange.AdvanceOffset(sizeof(ChildTableEntry));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kChannelPages:
|
||||
aTlvInfo.mData.mChannelPages.mCount =
|
||||
static_cast<uint8_t>(Min(tlvLength, GetArrayLength(aTlvInfo.mData.mChannelPages.m8)));
|
||||
aMessage.ReadBytes(valueOffset, aTlvInfo.mData.mChannelPages.m8, aTlvInfo.mData.mChannelPages.mCount);
|
||||
aTlvInfo.mData.mChannelPages.mCount = static_cast<uint8_t>(
|
||||
Min(valueOffsetRange.GetLength(), GetArrayLength(aTlvInfo.mData.mChannelPages.m8)));
|
||||
aMessage.ReadBytes(valueOffsetRange.GetOffset(), aTlvInfo.mData.mChannelPages.m8,
|
||||
aTlvInfo.mData.mChannelPages.mCount);
|
||||
break;
|
||||
|
||||
case Tlv::kMaxChildTimeout:
|
||||
@ -1333,6 +1343,11 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
Tlv::Read<ThreadStackVersionTlv>(aMessage, offset, aTlvInfo.mData.mThreadStackVersion));
|
||||
break;
|
||||
|
||||
case Tlv::kNonPreferredChannels:
|
||||
SuccessOrExit(error = MeshCoP::ChannelMaskTlv::ParseValue(aMessage, valueOffsetRange,
|
||||
aTlvInfo.mData.mNonPreferredChannels));
|
||||
break;
|
||||
|
||||
default:
|
||||
// Skip unrecognized TLVs.
|
||||
skipTlv = true;
|
||||
|
@ -74,6 +74,11 @@ class Server : public InstanceLocator, private NonCopyable
|
||||
friend class Client;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Callback function pointer to notify a reset request for `kNonPreferredChannels` TLV value.
|
||||
*/
|
||||
typedef otThreadNonPreferredChannelsResetCallback NonPreferredChannelsResetCallback;
|
||||
|
||||
/**
|
||||
* Initializes the Server.
|
||||
*
|
||||
@ -81,6 +86,31 @@ public:
|
||||
*/
|
||||
explicit Server(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Sets the non-preferred channels value for `kNonPreferredChannels` TLV.
|
||||
*
|
||||
* @param[in] aChannelMask A channel mask for non-preferred channels.
|
||||
*/
|
||||
void SetNonPreferredChannels(uint32_t aChannelMask) { mNonPreferredChannels = aChannelMask; }
|
||||
|
||||
/**
|
||||
* Gets the non-preferred channel mask value for `kNonPreferredChannels` TLV.
|
||||
*
|
||||
* @returns The non-preferred channels as a channel mask.
|
||||
*/
|
||||
uint32_t GetNonPreferredChannels(void) const { return mNonPreferredChannels; }
|
||||
|
||||
/**
|
||||
* Sets the callback to notify when a Diagnostic Reset request is received for `kNonPreferredChannels` TLV value.
|
||||
*
|
||||
* @param[in] aCallback The callback function pointer.
|
||||
* @param[in] aContext An arbitrary context used with @p aCallback.
|
||||
*/
|
||||
void SetNonPreferredChannelsResetCallback(NonPreferredChannelsResetCallback aCallback, void *aContext)
|
||||
{
|
||||
mNonPreferredChannelsResetCallback.Set(aCallback, aContext);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
/**
|
||||
* Returns the vendor name string.
|
||||
@ -229,6 +259,8 @@ private:
|
||||
#if OPENTHREAD_FTD
|
||||
Coap::MessageQueue mAnswerQueue;
|
||||
#endif
|
||||
uint32_t mNonPreferredChannels;
|
||||
Callback<NonPreferredChannelsResetCallback> mNonPreferredChannelsResetCallback;
|
||||
};
|
||||
|
||||
DeclareTmfHandler(Server, kUriDiagnosticGetRequest);
|
||||
|
@ -66,36 +66,37 @@ public:
|
||||
*/
|
||||
enum Type : uint8_t
|
||||
{
|
||||
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,
|
||||
kEui64 = OT_NETWORK_DIAGNOSTIC_TLV_EUI64,
|
||||
kVersion = OT_NETWORK_DIAGNOSTIC_TLV_VERSION,
|
||||
kVendorName = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME,
|
||||
kVendorModel = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL,
|
||||
kVendorSwVersion = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION,
|
||||
kThreadStackVersion = OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION,
|
||||
kChild = OT_NETWORK_DIAGNOSTIC_TLV_CHILD,
|
||||
kChildIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST,
|
||||
kRouterNeighbor = OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR,
|
||||
kAnswer = OT_NETWORK_DIAGNOSTIC_TLV_ANSWER,
|
||||
kQueryId = OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID,
|
||||
kMleCounters = OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS,
|
||||
kVendorAppUrl = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL,
|
||||
kEnhancedRoute = OT_NETWORK_DIAGNOSTIC_TLV_ENHANCED_ROUTE,
|
||||
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,
|
||||
kEui64 = OT_NETWORK_DIAGNOSTIC_TLV_EUI64,
|
||||
kVersion = OT_NETWORK_DIAGNOSTIC_TLV_VERSION,
|
||||
kVendorName = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME,
|
||||
kVendorModel = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL,
|
||||
kVendorSwVersion = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION,
|
||||
kThreadStackVersion = OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION,
|
||||
kChild = OT_NETWORK_DIAGNOSTIC_TLV_CHILD,
|
||||
kChildIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST,
|
||||
kRouterNeighbor = OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR,
|
||||
kAnswer = OT_NETWORK_DIAGNOSTIC_TLV_ANSWER,
|
||||
kQueryId = OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID,
|
||||
kMleCounters = OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS,
|
||||
kVendorAppUrl = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL,
|
||||
kNonPreferredChannels = OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS,
|
||||
kEnhancedRoute = OT_NETWORK_DIAGNOSTIC_TLV_ENHANCED_ROUTE,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -70,6 +70,7 @@ VENDOR_SW_VERSION_TLV = 27
|
||||
THREAD_STACK_VERSION_TLV = 28
|
||||
MLE_COUNTERS_TLV = 34
|
||||
VENDOR_APP_URL = 35
|
||||
NON_PREFERRED_CHANNELS_TLV = 36
|
||||
|
||||
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Check setting vendor name, model, ans sw version
|
||||
@ -192,9 +193,42 @@ for line in result[1:]:
|
||||
verify(False)
|
||||
|
||||
result = r2.cli('networkdiagnostic get', r1_rloc, MLE_COUNTERS_TLV)
|
||||
print(len(result) >= 1)
|
||||
verify(result[1].startswith("MLE Counters:"))
|
||||
|
||||
# Test Non-preferred Channels TLV
|
||||
|
||||
|
||||
def verify_non_preferred_channels_query_result(mask):
|
||||
r1.cli('networkdiagnostic nonpreferredchannels', mask)
|
||||
result = r1.cli('networkdiagnostic nonpreferredchannels')
|
||||
verify(len(result) == 1)
|
||||
verify(int(result[0], 16) == mask)
|
||||
|
||||
|
||||
result = r1.cli('networkdiagnostic nonpreferredchannels')
|
||||
verify(len(result) == 1)
|
||||
verify(int(result[0], 16) == 0)
|
||||
|
||||
verify_non_preferred_channels_query_result(0)
|
||||
|
||||
mask = 1 << 26 # channel 26
|
||||
|
||||
r1.cli('networkdiagnostic nonpreferredchannels', mask)
|
||||
result = r1.cli('networkdiagnostic nonpreferredchannels')
|
||||
verify(len(result) == 1)
|
||||
verify(int(result[0], 16) == mask)
|
||||
|
||||
verify_non_preferred_channels_query_result(mask)
|
||||
|
||||
mask = 0
|
||||
|
||||
r1.cli('networkdiagnostic nonpreferredchannels', mask)
|
||||
result = r1.cli('networkdiagnostic nonpreferredchannels')
|
||||
verify(len(result) == 1)
|
||||
verify(int(result[0], 16) == mask)
|
||||
|
||||
verify_non_preferred_channels_query_result(mask)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
|
Reference in New Issue
Block a user