[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
+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)