From c5ad131028e4d23e937d64206c3ffc333cc8aa22 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Sat, 3 Aug 2024 04:37:18 +0800 Subject: [PATCH] [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. --- src/cli/README.md | 69 +++++-- src/cli/cli_link_metrics.cpp | 189 ++++++++++++------ src/cli/cli_link_metrics.hpp | 17 +- tests/scripts/thread-cert/node.py | 31 +-- ..._SingleProbeLinkMetricsWithEnhancedAcks.py | 14 +- ...ingleProbeLinkMetricsWithoutEnhancedAck.py | 10 +- ...2_LowPower_7_2_01_ForwardTrackingSeries.py | 14 +- ...2_LowPower_test_forward_tracking_series.py | 17 +- .../thread-cert/v1_2_test_single_probe.py | 10 +- 9 files changed, 250 insertions(+), 121 deletions(-) diff --git a/src/cli/README.md b/src/cli/README.md index ee440b1345a..856d57f1ece 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -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 \ enhanced-ack clear +### linkmetrics config \[async\] \ 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 \ enhanced-ack register [qmr][r] +### linkmetrics config \[async\] \ enhanced-ack register \ \[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 \ forward \ [ldraX][pqmr] +### linkmetrics config \[async\] \ forward \ \ \ 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 \ single [pqmr] +### linkmetrics request \[async\] \ single \ 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 \ forward \ +### linkmetrics request \[async\] \ forward \ 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 diff --git a/src/cli/cli_link_metrics.cpp b/src/cli/cli_link_metrics.cpp index a12515d1bf7..69ad781c881 100644 --- a/src/cli/cli_link_metrics.cpp +++ b/src/cli/cli_link_metrics.cpp @@ -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(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(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(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(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(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(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(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(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(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(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(aContext)->HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(aAddress, aStatus); +} + +void LinkMetrics::HandleLinkMetricsConfigForwardTrackingSeriesMgmtResponse(const otIp6Address *aAddress, + otLinkMetricsStatus aStatus) { - static_cast(aContext)->HandleLinkMetricsMgmtResponse(aAddress, aStatus); + HandleLinkMetricsMgmtResponse(aAddress, aStatus); + + if (mConfigForwardTrackingSeriesSync) + { + mConfigForwardTrackingSeriesSync = false; + OutputResult(OT_ERROR_NONE); + } +} + +void LinkMetrics::HandleLinkMetricsConfigEnhAckProbingMgmtResponse(const otIp6Address *aAddress, + otLinkMetricsStatus aStatus, + void *aContext) +{ + static_cast(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) diff --git a/src/cli/cli_link_metrics.hpp b/src/cli/cli_link_metrics.hpp index 40b67c604ed..13b65a5591d 100644 --- a/src/cli/cli_link_metrics.hpp +++ b/src/cli/cli_link_metrics.hpp @@ -96,10 +96,15 @@ class LinkMetrics : private Utils 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 @@ class LinkMetrics : private Utils void OutputResult(otError aError); - bool mLinkMetricsQueryInProgress; + bool mQuerySync : 1; + bool mConfigForwardTrackingSeriesSync : 1; + bool mConfigEnhAckProbingSync : 1; }; } // namespace Cli diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index 118b692dadc..9f7bca09227 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -3255,14 +3255,14 @@ def router_table(self): 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 @@ def _parse_linkmetrics_query_result(self, lines): 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 @@ def link_metrics_mgmt_req_enhanced_ack_based_probing(self, 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() diff --git a/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py b/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py index dea41987574..7b67796e705 100755 --- a/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py +++ b/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py @@ -99,7 +99,7 @@ def test(self): # ---- 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 @@ def test(self): # ---- 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 @@ def test(self): # 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 @@ def test(self): # ---- 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 @@ def test(self): # ---- 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): diff --git a/tests/scripts/thread-cert/v1_2_LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck.py b/tests/scripts/thread-cert/v1_2_LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck.py index 92ab70cd1b7..9775470776a 100755 --- a/tests/scripts/thread-cert/v1_2_LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck.py +++ b/tests/scripts/thread-cert/v1_2_LowPower_7_1_02_SingleProbeLinkMetricsWithoutEnhancedAck.py @@ -108,7 +108,7 @@ def test(self): # 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 @@ def test(self): # # 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 @@ def test(self): # --- 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 @@ def test(self): # --- 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 @@ def test(self): # ---- 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): diff --git a/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py b/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py index 7cb02415665..6a278999997 100755 --- a/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py +++ b/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py @@ -103,7 +103,7 @@ def test(self): # -- 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 @@ def test(self): 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 @@ def test(self): # 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 @@ def test(self): # -- 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 @@ def test(self): 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') diff --git a/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py b/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py index c1287fe5c35..f8263de71af 100755 --- a/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py +++ b/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py @@ -76,38 +76,39 @@ def test(self): # 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 @@ def test(self): # 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): diff --git a/tests/scripts/thread-cert/v1_2_test_single_probe.py b/tests/scripts/thread-cert/v1_2_test_single_probe.py index 5b29aaac8d6..1e228b5ce94 100755 --- a/tests/scripts/thread-cert/v1_2_test_single_probe.py +++ b/tests/scripts/thread-cert/v1_2_test_single_probe.py @@ -70,7 +70,7 @@ def test(self): 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 @@ def test(self): 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 @@ def test(self): 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 @@ def test(self): 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 @@ def test(self): 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)