diff --git a/tools/cp-caps/README.md b/tools/cp-caps/README.md index 48ec8883b..b84387172 100644 --- a/tools/cp-caps/README.md +++ b/tools/cp-caps/README.md @@ -41,7 +41,7 @@ $ git clone git@github.com:openthread/ot-nrf528xx.git $ cd ot-nrf528xx/ $ git submodule update --init $ ./script/bootstrap -$ ./script/build nrf52840 UART_trans -DOT_DIAGNOSTIC=ON -DOT_CSL_RECEIVER=ON +$ ./script/build nrf52840 UART_trans -DOT_DIAGNOSTIC=ON -DOT_CSL_RECEIVER=ON -DOT_LINK_METRICS_INITIATOR=ON -DOT_LINK_METRICS_SUBJECT=ON $ arm-none-eabi-objcopy -O ihex build/bin/ot-cli-ftd ot-cli-ftd.hex $ nrfjprog -f nrf52 --chiperase --program ot-cli-ftd.hex --reset ``` @@ -62,6 +62,7 @@ options: -h, --help show this help message and exit -c, --csl test whether the RCP supports CSL transmitter -d, --diag-commands test whether the RCP supports all diag commands + -l, --link-metrics test whether the RCP supports link metrics -p, --data-poll test whether the RCP supports data poll -t, --throughput test the Thread network 1-hop throughput -v, --verbose output verbose information @@ -146,6 +147,16 @@ Data Poll Parent ----------------------------------------- OK Data Poll Child ------------------------------------------ OK ``` +### Test Link Metrics + +The parameter `-l` or `--link-metrics` starts to test whether the RCP supports link metrics. + +```bash +$ DUT_ADB_USB=1269UCKFZTAM95OR REF_CLI_SERIAL=/dev/ttyACM0 python3 ./tools/cp-caps/rcp_caps_test.py -l +Link Metrics Initiator ----------------------------------- OK +Link Metrics Subject ------------------------------------- OK +``` + ### Test Throughput The parameter `-t` or `--throughput` starts to test the Thread network 1-hop throughput of the DUT. diff --git a/tools/cp-caps/rcp_caps_test.py b/tools/cp-caps/rcp_caps_test.py index 432777859..96e46cecd 100644 --- a/tools/cp-caps/rcp_caps_test.py +++ b/tools/cp-caps/rcp_caps_test.py @@ -38,6 +38,7 @@ from typing import List import otci from otci import OTCI +from otci.types import Ip6Addr logging.basicConfig(level=logging.WARNING) @@ -136,9 +137,62 @@ class RcpCaps(object): self.__output_format_string('Throughput', self.__bitrate_to_string(results['receiver']['bitrate'])) + def test_link_metrics(self): + """Test whether the DUT supports Link Metrics Initiator and Subject.""" + self.__dataset = self.__get_default_dataset() + + self.__dut.factory_reset() + self.__ref.factory_reset() + + self.__dut.join(self.__dataset) + self.__dut.wait_for('state', 'leader') + + self.__ref.join(self.__dataset) + self.__ref.wait_for('state', ['child', 'router']) + + test_case = 'Link Metrics Initiator' + ref_linklocal_address = self.__ref.get_ipaddr_linklocal() + ret = self.__run_link_metrics_test_commands(initiator=self.__dut, subject_address=ref_linklocal_address) + self.__output_format_bool(test_case, ret) + + test_case = 'Link Metrics Subject' + dut_linklocal_address = self.__dut.get_ipaddr_linklocal() + ret = self.__run_link_metrics_test_commands(initiator=self.__ref, subject_address=dut_linklocal_address) + self.__output_format_bool(test_case, ret) + + self.__ref.leave() + self.__dut.leave() + # # Private methods # + def __run_link_metrics_test_commands(self, initiator: OTCI, subject_address: Ip6Addr) -> bool: + seriesid = 1 + series_flags = 'ldra' + link_metrics_flags = 'qr' + probe_length = 10 + + if not initiator.linkmetrics_config_enhanced_ack_register(subject_address, link_metrics_flags): + return False + + if not initiator.linkmetrics_config_forward(subject_address, seriesid, series_flags, link_metrics_flags): + return False + + initiator.linkmetrics_probe(subject_address, seriesid, probe_length) + + results = initiator.linkmetrics_request_single(subject_address, link_metrics_flags) + if not ('lqi' in results.keys() and 'rssi' in results.keys()): + return False + + results = initiator.linkmetrics_request_forward(subject_address, seriesid) + if not ('lqi' in results.keys() and 'rssi' in results.keys()): + return False + + if not initiator.linkmetrics_config_enhanced_ack_clear(subject_address): + return False + + return True + def __ref_iperf3_server_task(self, bind_address: str, timeout: int): self.__ref.iperf3_server(bind_address, timeout=timeout) @@ -535,6 +589,14 @@ def parse_arguments(): help='test whether the RCP supports CSL transmitter', ) + parser.add_argument( + '-l', + '--link-metrics', + action='store_true', + default=False, + help='test whether the RCP supports link metrics', + ) + parser.add_argument( '-d', '--diag-commands', @@ -588,6 +650,9 @@ def main(): if arguments.data_poll is True: rcp_caps.test_data_poll() + if arguments.link_metrics is True: + rcp_caps.test_link_metrics() + if arguments.throughput: rcp_caps.test_throughput()