[cli] add the sync option to the linkmetrics cli commands (#10518)

The cli command `linkmetrics` only provides an asynchronous output
method. It is difficult for scripts to call the `ot-ctl` to capture
the results of asynchronous output.

This commit replaces the command `linkmetrics mgmt` and `linkmetrics
query` with commands `linkmetrics config` and `linkmetrics
request`. Both the commands `linkmetrics config` and `linkmetrics
request` are set to the `sync` mode by default, and an option `async`
is added to these commands to support `async` mode.
This commit is contained in:
Zhanglong Xia
2024-08-02 13:37:18 -07:00
committed by GitHub
parent e219fe92f1
commit c5ad131028
9 changed files with 250 additions and 121 deletions
+53 -16
View File
@@ -66,7 +66,7 @@ Done
- [keysequence](#keysequence-counter)
- [leaderdata](#leaderdata)
- [leaderweight](#leaderweight)
- [linkmetrics](#linkmetrics-mgmt-ipaddr-enhanced-ack-clear)
- [linkmetrics](#linkmetrics-config-async-ipaddr-enhanced-ack-clear)
- [linkmetricsmgr](#linkmetricsmgr-disable)
- [locate](#locate)
- [log](#log-filename-filename)
@@ -1861,23 +1861,30 @@ Set the Thread Leader Weight.
Done
```
### linkmetrics mgmt \<ipaddr\> enhanced-ack clear
### linkmetrics config \[async\] \<ipaddr\> enhanced-ack clear
Send a Link Metrics Management Request to clear an Enhanced-ACK Based Probing.
- async: Use the non-blocking mode.
- ipaddr: Peer address (SHOULD be link local address of the neighboring device).
```bash
> linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
> linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: Success
Done
> linkmetrics config async fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
Done
> Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: Success
```
### linkmetrics mgmt \<ipaddr\> enhanced-ack register [qmr][r]
### linkmetrics config \[async\] \<ipaddr\> enhanced-ack register \<qmr\> \[r\]
Send a Link Metrics Management Request to register an Enhanced-ACK Based Probing.
- async: Use the non-blocking mode.
- ipaddr: Peer address.
- qmr: This specifies what metrics to query. At most two options are allowed to select (per spec 4.11.3.4.4.6).
- q: Layer 2 LQI.
@@ -1886,21 +1893,27 @@ Send a Link Metrics Management Request to register an Enhanced-ACK Based Probing
- r: This is optional and only used for reference devices. When this option is specified, Type/Average Enum of each Type Id Flags would be set to `reserved`. This is used to verify the Probing Subject correctly handles invalid Type Id Flags. This is only available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
```bash
> linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
> linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: Success
Done
> linkmetrics config async fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
Done
> Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: Success
> linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
> linkmetrics config async fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
Done
> Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: Cannot support new series
```
### linkmetrics mgmt \<ipaddr\> forward \<seriesid\> [ldraX][pqmr]
### linkmetrics config \[async\] \<ipaddr\> forward \<seriesid\> \<ldraX\> \<pqmr\>
Send a Link Metrics Management Request to configure a Forward Tracking Series.
- async: Use the non-blocking mode.
- ipaddr: Peer address.
- seriesid: The Series ID.
- ldraX: This specifies which frames are to be accounted.
@@ -1916,7 +1929,12 @@ Send a Link Metrics Management Request to configure a Forward Tracking Series.
- r: RSSI.
```bash
> linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
> linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: SUCCESS
Done
> linkmetrics config async fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
Done
> Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
Status: SUCCESS
@@ -1935,19 +1953,28 @@ Send a MLE Link Probe message to the peer.
Done
```
### linkmetrics query \<ipaddr\> single [pqmr]
### linkmetrics request \[async\] \<ipaddr\> single \<pqmr\>
Perform a Link Metrics query (Single Probe).
- async: Use the non-blocking mode.
- ipaddr: Peer address.
- pqmr: This specifies what metrics to query.
- p: Layer 2 Number of PDUs received.
- q: Layer 2 LQI.
- m: Link Margin.
- r: RSSI.
- p: Layer 2 Number of PDUs received.
- q: Layer 2 LQI.
- m: Link Margin.
- r: RSSI.
```bash
> linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 single qmr
> linkmetrics request fe80:0:0:0:3092:f334:1455:1ad2 single qmr
Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
- LQI: 76 (Exponential Moving Average)
- Margin: 82 (dB) (Exponential Moving Average)
- RSSI: -18 (dBm) (Exponential Moving Average)
Done
> linkmetrics request async fe80:0:0:0:3092:f334:1455:1ad2 single qmr
Done
> Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
@@ -1956,15 +1983,25 @@ Done
- RSSI: -18 (dBm) (Exponential Moving Average)
```
### linkmetrics query \<ipaddr\> forward \<seriesid\>
### linkmetrics request \[async\] \<ipaddr\> forward \<seriesid\>
Perform a Link Metrics query (Forward Tracking Series).
- sync: Use the blocking mode.
- ipaddr: Peer address.
- seriesid: The Series ID.
```bash
> linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 forward 1
> linkmetrics request fe80:0:0:0:3092:f334:1455:1ad2 forward 1
Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
- PDU Counter: 2 (Count/Summation)
- LQI: 76 (Exponential Moving Average)
- Margin: 82 (dB) (Exponential Moving Average)
- RSSI: -18 (dBm) (Exponential Moving Average)
Done
> linkmetrics request async fe80:0:0:0:3092:f334:1455:1ad2 forward 1
Done
> Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
+132 -57
View File
@@ -46,32 +46,48 @@ namespace Cli {
LinkMetrics::LinkMetrics(otInstance *aInstance, OutputImplementer &aOutputImplementer)
: Utils(aInstance, aOutputImplementer)
, mLinkMetricsQueryInProgress(false)
, mQuerySync(false)
, mConfigForwardTrackingSeriesSync(false)
, mConfigEnhAckProbingSync(false)
{
}
template <> otError LinkMetrics::Process<Cmd("query")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
OutputLine("The command \"linkmetrics query\" has been replaced by the command \"linkmetrics request\".");
return OT_ERROR_INVALID_COMMAND;
}
template <> otError LinkMetrics::Process<Cmd("request")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otIp6Address address;
bool sync = true;
bool isSingle;
bool blocking;
uint8_t seriesId;
otLinkMetrics linkMetrics;
if (aArgs[0] == "async")
{
sync = false;
aArgs++;
}
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
/**
* @cli linkmetrics query single
* @cli linkmetrics request single
* @code
* linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 single qmr
* Done
* > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
* linkmetrics request fe80:0:0:0:3092:f334:1455:1ad2 single qmr
* Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
* - LQI: 76 (Exponential Moving Average)
* - Margin: 82 (dB) (Exponential Moving Average)
* - RSSI: -18 (dBm) (Exponential Moving Average)
* Done
* @endcode
* @cparam linkmetrics query @ca{peer-ipaddr} single [@ca{pqmr}]
* @cparam linkmetrics request [@ca{async}] @ca{peer-ipaddr} single [@ca{pqmr}]
* - `async`: Use the non-blocking mode.
* - `peer-ipaddr`: Peer address.
* - [`p`, `q`, `m`, and `r`] map to #otLinkMetrics.
* - `p`: Layer 2 Number of PDUs received.
@@ -88,17 +104,18 @@ template <> otError LinkMetrics::Process<Cmd("query")>(Arg aArgs[])
SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[2]));
}
/**
* @cli linkmetrics query forward
* @cli linkmetrics request forward
* @code
* linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 forward 1
* Done
* > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
* linkmetrics request fe80:0:0:0:3092:f334:1455:1ad2 forward 1
* Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
* - PDU Counter: 2 (Count/Summation)
* - LQI: 76 (Exponential Moving Average)
* - Margin: 82 (dB) (Exponential Moving Average)
* - RSSI: -18 (dBm) (Exponential Moving Average)
* Done
* @endcode
* @cparam linkmetrics query @ca{peer-ipaddr} forward @ca{series-id}
* @cparam linkmetrics query [@ca{async}] @ca{peer-ipaddr} forward @ca{series-id}
* - `async`: Use the non-blocking mode.
* - `peer-ipaddr`: Peer address.
* - `series-id`: The Series ID.
* @par
@@ -115,40 +132,54 @@ template <> otError LinkMetrics::Process<Cmd("query")>(Arg aArgs[])
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
blocking = (aArgs[3] == "block");
SuccessOrExit(error = otLinkMetricsQuery(GetInstancePtr(), &address, isSingle ? 0 : seriesId,
isSingle ? &linkMetrics : nullptr, HandleLinkMetricsReport, this));
if (blocking)
if (sync)
{
mLinkMetricsQueryInProgress = true;
error = OT_ERROR_PENDING;
mQuerySync = true;
error = OT_ERROR_PENDING;
}
exit:
return error;
}
template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
OutputLine("The command \"linkmetrics mgmt\" has been replaced by the command \"linkmetrics config\".");
return OT_ERROR_INVALID_COMMAND;
}
template <> otError LinkMetrics::Process<Cmd("config")>(Arg aArgs[])
{
otError error;
otIp6Address address;
otLinkMetricsSeriesFlags seriesFlags;
bool sync = true;
bool clear = false;
if (aArgs[0] == "async")
{
sync = false;
aArgs++;
}
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
ClearAllBytes(seriesFlags);
/**
* @cli linkmetrics mgmt forward
* @cli linkmetrics config forward
* @code
* linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
* Done
* > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
* Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* Status: SUCCESS
* Done
* @endcode
* @cparam linkmetrics mgmt @ca{peer-ipaddr} forward @ca{series-id} [@ca{ldraX}][@ca{pqmr}]
* @cparam linkmetrics config [@ca{async}] @ca{peer-ipaddr} forward @ca{series-id} [@ca{ldraX}][@ca{pqmr}]
* - `async`: Use the non-blocking mode.
* - `peer-ipaddr`: Peer address.
* - `series-id`: The Series ID.
* - [`l`, `d`, `r`, and `a`] map to #otLinkMetricsSeriesFlags. `X` represents none of the
@@ -212,9 +243,15 @@ template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
VerifyOrExit(aArgs[5].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
}
error = otLinkMetricsConfigForwardTrackingSeries(GetInstancePtr(), &address, seriesId, seriesFlags,
clear ? nullptr : &linkMetrics,
&LinkMetrics::HandleLinkMetricsMgmtResponse, this);
SuccessOrExit(error = otLinkMetricsConfigForwardTrackingSeries(
GetInstancePtr(), &address, seriesId, seriesFlags, clear ? nullptr : &linkMetrics,
&LinkMetrics::HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse, this));
if (sync)
{
mConfigForwardTrackingSeriesSync = true;
error = OT_ERROR_PENDING;
}
}
else if (aArgs[1] == "enhanced-ack")
{
@@ -223,15 +260,16 @@ template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
otLinkMetrics *pLinkMetrics = &linkMetrics;
/**
* @cli linkmetrics mgmt enhanced-ack clear
* @cli linkmetrics config enhanced-ack clear
* @code
* linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
* Done
* > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
* Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* Status: Success
* Done
* @endcode
* @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack clear
* `peer-ipaddr` should be the Link Local address of the neighboring device.
* @cparam linkmetrics config [@ca{async}] @ca{peer-ipaddr} enhanced-ack clear
* - `async`: Use the non-blocking mode.
* - `peer-ipaddr` should be the Link Local address of the neighboring device.
* @par
* Sends a Link Metrics Management Request to clear an Enhanced-ACK Based Probing.
* @sa otLinkMetricsConfigEnhAckProbing
@@ -242,26 +280,27 @@ template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
pLinkMetrics = nullptr;
}
/**
* @cli linkmetrics mgmt enhanced-ack register
* @cli linkmetrics config enhanced-ack register
* @code
* linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
* Done
* > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
* Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* Status: Success
* Done
* @endcode
* @code
* > linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
* Done
* > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* > linkmetrics config fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
* Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
* Status: Cannot support new series
* Done
* @endcode
* @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack register [@ca{qmr}][@ca{r}]
* [`q`, `m`, and `r`] map to #otLinkMetricsValues. Per spec 4.11.3.4.4.6, you can
* only use a maximum of two options at once, for example `q`, or `qm`.
* - `q`: Layer 2 LQI.
* - `m`: Link Margin.
* - `r`: RSSI.
* .
* @cparam linkmetrics config [@ca{async}] @ca{peer-ipaddr} enhanced-ack register [@ca{qmr}][@ca{r}]
* - `async`: Use the non-blocking mode.
* - [`q`, `m`, and `r`] map to #otLinkMetricsValues. Per spec 4.11.3.4.4.6, you can
* only use a maximum of two options at once, for example `q`, or `qm`.
* - `q`: Layer 2 LQI.
* - `m`: Link Margin.
* - `r`: RSSI.
* @par
* The additional `r` is optional and only used for reference devices. When this option
* is specified, Type/Average Enum of each Type Id Flags is set to reserved. This is
* used to verify that the Probing Subject correctly handles invalid Type Id Flags, and
@@ -286,9 +325,16 @@ template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
error = otLinkMetricsConfigEnhAckProbing(GetInstancePtr(), &address, enhAckFlags, pLinkMetrics,
&LinkMetrics::HandleLinkMetricsMgmtResponse, this,
&LinkMetrics::HandleLinkMetricsEnhAckProbingIe, this);
SuccessOrExit(
error = otLinkMetricsConfigEnhAckProbing(GetInstancePtr(), &address, enhAckFlags, pLinkMetrics,
&LinkMetrics::HandleLinkMetricsConfigEnhAckProbingMgmtResponse,
this, &LinkMetrics::HandleLinkMetricsEnhAckProbingIe, this));
if (sync)
{
mConfigEnhAckProbingSync = true;
error = OT_ERROR_PENDING;
}
}
else
{
@@ -337,9 +383,7 @@ otError LinkMetrics::Process(Arg aArgs[])
}
static constexpr Command kCommands[] = {
CmdEntry("mgmt"),
CmdEntry("probe"),
CmdEntry("query"),
CmdEntry("config"), CmdEntry("mgmt"), CmdEntry("probe"), CmdEntry("query"), CmdEntry("request"),
};
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
@@ -448,18 +492,49 @@ void LinkMetrics::HandleLinkMetricsReport(const otIp6Address *aAddress,
OutputLine("Link Metrics Report, status: %s", LinkMetricsStatusToStr(aStatus));
}
if (mLinkMetricsQueryInProgress)
if (mQuerySync)
{
mLinkMetricsQueryInProgress = false;
mQuerySync = false;
OutputResult(OT_ERROR_NONE);
}
}
void LinkMetrics::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext)
void LinkMetrics::HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext)
{
static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsMgmtResponse(aAddress, aStatus);
static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(aAddress, aStatus);
}
void LinkMetrics::HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus)
{
HandleLinkMetricsMgmtResponse(aAddress, aStatus);
if (mConfigForwardTrackingSeriesSync)
{
mConfigForwardTrackingSeriesSync = false;
OutputResult(OT_ERROR_NONE);
}
}
void LinkMetrics::HandleLinkMetricsConfigEnhAckProbingMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext)
{
static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsConfigEnhAckProbingMgmtResponse(aAddress, aStatus);
}
void LinkMetrics::HandleLinkMetricsConfigEnhAckProbingMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus)
{
HandleLinkMetricsMgmtResponse(aAddress, aStatus);
if (mConfigEnhAckProbingSync)
{
mConfigEnhAckProbingSync = false;
OutputResult(OT_ERROR_NONE);
}
}
void LinkMetrics::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus)
+12 -5
View File
@@ -96,10 +96,15 @@ private:
const otLinkMetricsValues *aMetricsValues,
otLinkMetricsStatus aStatus);
static void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext);
static void HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext);
void HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus);
static void HandleLinkMetricsConfigEnhAckProbingMgmtResponse(const otIp6Address *aAddress,
otLinkMetricsStatus aStatus,
void *aContext);
void HandleLinkMetricsConfigEnhAckProbingMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus);
void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus);
static void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
@@ -115,7 +120,9 @@ private:
void OutputResult(otError aError);
bool mLinkMetricsQueryInProgress;
bool mQuerySync : 1;
bool mConfigForwardTrackingSeriesSync : 1;
bool mConfigEnhAckProbingSync : 1;
};
} // namespace Cli
+18 -13
View File
@@ -3255,14 +3255,14 @@ class NodeImpl:
return router_table
def link_metrics_query_single_probe(self, dst_addr: str, linkmetrics_flags: str, block: str = ""):
cmd = 'linkmetrics query %s single %s %s' % (dst_addr, linkmetrics_flags, block)
def link_metrics_request_single_probe(self, dst_addr: str, linkmetrics_flags: str, mode: str = ''):
cmd = 'linkmetrics request %s %s single %s' % (mode, dst_addr, linkmetrics_flags)
self.send_command(cmd)
self.simulator.go(5)
return self._parse_linkmetrics_query_result(self._expect_command_output())
def link_metrics_query_forward_tracking_series(self, dst_addr: str, series_id: int, block: str = ""):
cmd = 'linkmetrics query %s forward %d %s' % (dst_addr, series_id, block)
def link_metrics_request_forward_tracking_series(self, dst_addr: str, series_id: int, mode: str = ''):
cmd = 'linkmetrics request %s %s forward %d' % (mode, dst_addr, series_id)
self.send_command(cmd)
self.simulator.go(5)
return self._parse_linkmetrics_query_result(self._expect_command_output())
@@ -3288,12 +3288,13 @@ class NodeImpl:
result['Status'] = line[29:]
return result
def link_metrics_mgmt_req_enhanced_ack_based_probing(self,
dst_addr: str,
enable: bool,
metrics_flags: str,
ext_flags=''):
cmd = "linkmetrics mgmt %s enhanced-ack" % (dst_addr)
def link_metrics_config_req_enhanced_ack_based_probing(self,
dst_addr: str,
enable: bool,
metrics_flags: str,
ext_flags='',
mode: str = ''):
cmd = "linkmetrics config %s %s enhanced-ack" % (mode, dst_addr)
if enable:
cmd = cmd + (" register %s %s" % (metrics_flags, ext_flags))
else:
@@ -3301,9 +3302,13 @@ class NodeImpl:
self.send_command(cmd)
self._expect_done()
def link_metrics_mgmt_req_forward_tracking_series(self, dst_addr: str, series_id: int, series_flags: str,
metrics_flags: str):
cmd = "linkmetrics mgmt %s forward %d %s %s" % (dst_addr, series_id, series_flags, metrics_flags)
def link_metrics_config_req_forward_tracking_series(self,
dst_addr: str,
series_id: int,
series_flags: str,
metrics_flags: str,
mode: str = ''):
cmd = "linkmetrics config %s %s forward %d %s %s" % (mode, dst_addr, series_id, series_flags, metrics_flags)
self.send_command(cmd)
self._expect_done()
@@ -99,7 +99,7 @@ class LowPower_7_1_01(thread_cert.TestCase):
# ---- L = 0
# ---- Type/Average Enum = 1 (Exponential Moving Avg)
# ---- Metrics Enum = 2 (Link Margin)
self.nodes[SED_1].link_metrics_mgmt_req_enhanced_ack_based_probing(leader_addr, True, 'm')
self.nodes[SED_1].link_metrics_config_req_enhanced_ack_based_probing(leader_addr, True, 'm', mode='async')
self.simulator.go(5)
# Step 6 - SSED_1 enables IEEE 802.15.4-2015 Enhanced ACK based Probing by sending a Link Metrics Management
@@ -115,7 +115,7 @@ class LowPower_7_1_01(thread_cert.TestCase):
# ---- Type/Average Enum = 1 (Exponential Moving Avg)
# ---- Metrics Enum = 2 (Link Margin)
# ---- Metrics Enum = 3 (RSSI)
self.nodes[SSED_1].link_metrics_mgmt_req_enhanced_ack_based_probing(leader_addr, True, 'mr')
self.nodes[SSED_1].link_metrics_config_req_enhanced_ack_based_probing(leader_addr, True, 'mr', mode='async')
self.simulator.go(5)
# Step 8 - SSED_1 sends an MLE Data Message with setting Frame Version subfield within the MAC header of the
@@ -131,7 +131,7 @@ class LowPower_7_1_01(thread_cert.TestCase):
# Step 12 - SSED_1 clears its Enhanced ACK link metrics configuration by # sending a Link Metrics Management
# Request to the DUT
# Enh-ACK Flags = 0 (clear enhanced ACK link metric config)
self.nodes[SSED_1].link_metrics_mgmt_req_enhanced_ack_based_probing(leader_addr, False, '')
self.nodes[SSED_1].link_metrics_config_req_enhanced_ack_based_probing(leader_addr, False, '', mode='async')
self.simulator.go(5)
# Step 14 - SSED_1 Sends a MLE Data Message with setting Frame Version subfield within the MAC header of the
@@ -154,7 +154,7 @@ class LowPower_7_1_01(thread_cert.TestCase):
# ---- Metrics Enum = 1 (Layer 2 LQI)
# ---- Metrics Enum = 2 (Link Margin)
# ---- Metrics Enum = 3 (RSSI)
self.nodes[SSED_1].link_metrics_mgmt_req_enhanced_ack_based_probing(leader_addr, True, 'qmr')
self.nodes[SSED_1].link_metrics_config_req_enhanced_ack_based_probing(leader_addr, True, 'qmr', mode='async')
self.simulator.go(5)
# Step 18 - This step verifies that Enhanced ACKs cannot be enabled while requesting a reserved Type/Average
@@ -168,7 +168,11 @@ class LowPower_7_1_01(thread_cert.TestCase):
# ---- L = 0
# ---- Type/Average Enum = 2 (Reserved)
# ---- Metrics Enum = 2 (Link Margin)
self.nodes[SSED_1].link_metrics_mgmt_req_enhanced_ack_based_probing(leader_addr, True, 'm', 'r')
self.nodes[SSED_1].link_metrics_config_req_enhanced_ack_based_probing(leader_addr,
True,
'm',
'r',
mode='async')
self.simulator.go(5)
def verify(self, pv):
@@ -108,7 +108,7 @@ class LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck(thread_cert.TestC
# In this step, SED_1 should set its TxPower to 'High'. In simulation, this will be implemented by
# setting Macfilter on the Rx side (Leader).
self.nodes[LEADER].add_allowlist(sed_extaddr, -30)
res = self.nodes[SED_1].link_metrics_query_single_probe(leader_addr, 'r', 'block')
res = self.nodes[SED_1].link_metrics_request_single_probe(leader_addr, 'r')
rss_1 = int(res['RSSI'])
self.simulator.go(5)
@@ -125,7 +125,7 @@ class LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck(thread_cert.TestC
#
# In this step, SED_1 should set its TxPower to 'Low'.
self.nodes[LEADER].add_allowlist(sed_extaddr, -95)
res = self.nodes[SED_1].link_metrics_query_single_probe(leader_addr, 'r', 'block')
res = self.nodes[SED_1].link_metrics_request_single_probe(leader_addr, 'r')
rss_2 = int(res['RSSI'])
self.simulator.go(5)
@@ -142,7 +142,7 @@ class LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck(thread_cert.TestC
# --- Metric Type ID Flags
# ---- Type / Average Enum = 1 (Exponential Moving Avg)
# ---- Metric Enum = 1 (Layer 2 LQI)
self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'q', 'block')
self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'q')
self.simulator.go(5)
# Step 11 - SSED_1 sends a Single Probe Link Metric for Link Margin using MLE Data Request
@@ -155,7 +155,7 @@ class LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck(thread_cert.TestC
# --- Metric Type ID Flags
# ---- Type / Average Enum = 1 (Exponential Moving Avg)
# ---- Metric Enum = 2 (Link Margin)
self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'm', 'block')
self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'm')
self.simulator.go(5)
# Step 13 - SSED_1 sends a Single Probe Link Metric using MLE Data Request
@@ -170,7 +170,7 @@ class LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck(thread_cert.TestC
# ---- Metric Enum = 1 (Layer 2 LQI)
# ---- Metric Enum = 2 (Link Margin)
# ---- Metric Enum = 3 (RSSI)
self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'qmr', 'block')
self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'qmr')
self.simulator.go(5)
def verify(self, pv):
@@ -103,7 +103,7 @@ class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
# -- L = 1
# -- Type/Average Enum = 0 (count)
# -- Metrics Enum = 0 (count)
self.nodes[SED_1].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID, 'r', 'p')
self.nodes[SED_1].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID, 'r', 'p', 'async')
self.simulator.go(5)
@@ -111,7 +111,7 @@ class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
self.simulator.go(30)
# Step 7 - SED_1 sends an MLE Data Request to retrieve aggregated Forward Series Results
result = self.nodes[SED_1].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID, 'block')
result = self.nodes[SED_1].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID)
self.assertIn("PDU Counter", result)
#self.simulator.go(5)
@@ -120,7 +120,7 @@ class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
# Forward Series Flags = 0x00:
# - Bits 0-7 = 0
# Concatenation of Link Metric Type ID Flags = NULL:
self.nodes[SED_1].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID, 'X', '')
self.nodes[SED_1].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID, 'X', '', 'async')
self.simulator.go(5)
@@ -134,7 +134,7 @@ class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
# -- L = 0
# -- Type/Average Enum = 1 (Exponential Moving Average)
# -- Metrics Enum = 2 (Link Margin)
self.nodes[SSED_1].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'd', 'm')
self.nodes[SSED_1].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'd', 'm', 'async')
self.simulator.go(5)
@@ -145,19 +145,19 @@ class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
self.simulator.go(1)
# Step 19 - SSED_1 sends an MLE Data Request to retrieve aggregated Forward Series Results
result = self.nodes[SSED_1].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID_2, 'block')
result = self.nodes[SSED_1].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID_2)
self.assertIn("Margin", result)
# Step 21 - SSED_1 clears the Forward Series Link Metrics
# Forward Series Flags = 0x00:
# - Bits 0-7 = 0
# Concatenation of Link Metric Type ID Flags = NULL
self.nodes[SSED_1].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'X', '')
self.nodes[SSED_1].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'X', '', 'async')
self.simulator.go(5)
# Step 23 - SSED_1 sends an MLE Data Request to retrieve aggregated Forward Series Results
result = self.nodes[SSED_1].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID_2, 'block')
result = self.nodes[SSED_1].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID_2)
self.assertIn('Status', result)
self.assertEqual(result['Status'], 'Series ID not recognized')
@@ -76,38 +76,39 @@ class LowPower_test_ForwardTrackingSeries(thread_cert.TestCase):
# 1. Child configures a Forward Tracking Series successfully.
# The Series tracks the count of MAC Data Request.
# Child should get a response with status 0 (SUCCESS).
self.nodes[CHILD].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'r', 'p')
self.nodes[CHILD].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'r', 'p', 'async')
self.simulator.go(1)
# 2. Child configures the same Forward Tracking Series again.
# Child should get a response with status 2 (SERIES_ID_ALREADY_REGISTERED).
self.nodes[CHILD].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'r', 'p')
self.nodes[CHILD].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'r', 'p', 'async')
self.simulator.go(1)
# 3. Child queries a Series that doesn't exist (using a wrong Series ID).
# Child should get a report with status 3 (SERIES_ID_NOT_RECOGNIZED).
self.nodes[CHILD].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID_2)
self.nodes[CHILD].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID_2, 'async')
self.simulator.go(1)
# 4. Child queries a Series that don't have matched frames yet.
# Child should get a report with status 4 (NO_MATCHING_FRAMES_RECEIVED).
self.nodes[CHILD].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID_1)
self.nodes[CHILD].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID_1, 'async')
self.simulator.go(1)
# 5. Child clears a Forward Tracking Series that doesn't exist.
# Child should get a response with status 3 (SERIES_ID_NOT_RECOGNIZED).
self.nodes[CHILD].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'X', '')
self.nodes[CHILD].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'X', '', 'async')
self.simulator.go(1)
# 6. Child clears a Forward Tracking Series successfully.
# Child should get a response with status 0 (SUCCESS).
self.nodes[CHILD].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'X', '')
self.nodes[CHILD].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_1, 'X', '', 'async')
self.simulator.go(1)
# 7. Child configures a new Forward Tracking Series successfully.
# The Series tracks the count of all MAC Data frames.
# Child should get a response with status 0 (SUCCESS).
self.nodes[CHILD].link_metrics_mgmt_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'd', 'pqmr')
self.nodes[CHILD].link_metrics_config_req_forward_tracking_series(leader_addr, SERIES_ID_2, 'd', 'pqmr',
'async')
self.simulator.go(1)
# 8. Child sends an MLE Link Probe message to the Subject for the newly configured Series.
@@ -115,7 +116,7 @@ class LowPower_test_ForwardTrackingSeries(thread_cert.TestCase):
# 9. Child queries the newly configured Series successfully.
# Child should get a report with valid values.
self.nodes[CHILD].link_metrics_query_forward_tracking_series(leader_addr, SERIES_ID_2)
self.nodes[CHILD].link_metrics_request_forward_tracking_series(leader_addr, SERIES_ID_2, 'async')
self.simulator.go(1)
def verify(self, pv):
@@ -70,7 +70,7 @@ class SSED_SingleProbe(thread_cert.TestCase):
leader_messages = self.simulator.get_messages_sent_by(LEADER)
# SSED_1 sends a Single Probe Link Metrics for L2 PDU count using MLE Data Request
result = self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'p', 'block')
result = self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'p')
self.assertIn('PDU Counter', result)
self.assertEqual(len(result), 1)
@@ -79,7 +79,7 @@ class SSED_SingleProbe(thread_cert.TestCase):
msg.assertMleMessageContainsTlv(mle.LinkMetricsReport)
# SSED_1 sends a Single Probe Link Metrics for L2 LQI using MLE Data Request
result = self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'q', 'block')
result = self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'q')
self.assertIn('LQI', result)
self.assertEqual(len(result), 1)
@@ -88,7 +88,7 @@ class SSED_SingleProbe(thread_cert.TestCase):
msg.assertMleMessageContainsTlv(mle.LinkMetricsReport)
# SSED_1 sends a Single Probe Link Metrics for Link Margin using MLE Data Request
result = self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'm', 'block')
result = self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'm')
self.assertIn('Margin', result)
self.assertEqual(len(result), 1)
@@ -97,7 +97,7 @@ class SSED_SingleProbe(thread_cert.TestCase):
msg.assertMleMessageContainsTlv(mle.LinkMetricsReport)
# SSED_1 sends a Single Probe Link Metrics for Link Margin using MLE Data Request
result = self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'r', 'block')
result = self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'r')
self.assertIn('RSSI', result)
self.assertEqual(len(result), 1)
@@ -106,7 +106,7 @@ class SSED_SingleProbe(thread_cert.TestCase):
msg.assertMleMessageContainsTlv(mle.LinkMetricsReport)
# SSED_1 sends a Single Probe Link Metrics for all metrics using MLE Data Request
result = self.nodes[SSED_1].link_metrics_query_single_probe(leader_addr, 'pqmr', 'block')
result = self.nodes[SSED_1].link_metrics_request_single_probe(leader_addr, 'pqmr')
self.assertIn('PDU Counter', result)
self.assertIn('LQI', result)
self.assertIn('Margin', result)