[test] test whether the RCP supports tx/rx 154 frames of all formats (#10912)

This commit add a command `--frame-format` to the `cp-caps` to test
whether the RCP supports sending and receiving 802.15.4 frames of all
formats.
This commit is contained in:
Zhanglong Xia
2024-11-14 02:46:53 +08:00
committed by GitHub
parent 659b4272b7
commit cc8f078586
2 changed files with 218 additions and 33 deletions
+62 -10
View File
@@ -54,26 +54,28 @@ Show help info.
```bash
$ python3 ./tools/cp-caps/rcp_caps_test.py -h
usage: rcp_caps_test.py [-h] [-c] [-d] [-p] [-t] [-v] [-D]
usage: rcp_caps_test.py [-h] [-c] [-l] [-d] [-f] [-p] [-t] [-v] [-D]
This script is used for testing RCP capabilities.
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
-d, --diag-commands test whether the RCP supports all diag commands
-f, --frame-format test whether the RCP supports 802.15.4 frames of all formats
-p, --data-poll test whether the RCP supports data poll
-t, --throughput test the Thread network 1-hop throughput
-t, --throughput test Thread network 1-hop throughput
-v, --version output version
-D, --debug output debug information
Device Interfaces:
DUT_SSH=<device_ip> Connect to the DUT via ssh
DUT_ADB_TCP=<device_ip> Connect to the DUT via adb tcp
DUT_ADB_USB=<serial_number> Connect to the DUT via adb usb
REF_CLI_SERIAL=<serial_device> Connect to the reference device via cli serial port
DUT_CLI_SERIAL=<serial_device> Connect to the DUT via cli serial port
DUT_SSH=<device_ip> Connect to the DUT via ssh
REF_ADB_USB=<serial_number> Connect to the reference device via adb usb
REF_CLI_SERIAL=<serial_device> Connect to the reference device via cli serial port
REF_SSH=<device_ip> Connect to the reference device via ssh
Example:
@@ -82,7 +84,7 @@ Example:
### Test Diag Commands
The parameter `-d` or `--diag-commands` starts to test all diag commands.
The option `-d` or `--diag-commands` tests all diag commands.
Following environment variables are used to configure diag command parameters:
@@ -131,7 +133,7 @@ diag gpio set 2 1 ---------------------------------------- NotSupported
### Test CSL Transmitter
The parameter `-c` or `--csl` starts to test whether the RCP supports the CSL transmitter.
The option `-c` or `--csl` tests whether the RCP supports the CSL transmitter.
```bash
$ DUT_ADB_USB=TW69UCKFZTGM95OR REF_CLI_SERIAL=/dev/ttyACM0 python3 ./tools/cp-caps/rcp_caps_test.py -c
@@ -140,7 +142,7 @@ CSL Transmitter ------------------------------------------ OK
### Test Data Poll
The parameter `-p` or `--data-poll` starts to test whether the RCP supports data poll.
The option `-p` or `--data-poll` tests whether the RCP supports data poll.
```bash
$ DUT_ADB_USB=1269UCKFZTAM95OR REF_CLI_SERIAL=/dev/ttyACM0 python3 ./tools/cp-caps/rcp_caps_test.py -p
@@ -150,7 +152,7 @@ Data Poll Child ------------------------------------------ OK
### Test Link Metrics
The parameter `-l` or `--link-metrics` starts to test whether the RCP supports link metrics.
The option `-l` or `--link-metrics` tests 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
@@ -160,9 +162,59 @@ Link Metrics Subject ------------------------------------- OK
### Test Throughput
The parameter `-t` or `--throughput` starts to test the Thread network 1-hop throughput of the DUT.
The option `-t` or `--throughput` tests the Thread network 1-hop throughput of the DUT.
```bash
$ DUT_ADB_USB=1269UCKFZTAM95OR REF_ADB_USB=44061HFAG01AQK python3 ./tools/cp-caps/rcp_caps_test.py -t
Throughput ----------------------------------------------- 75.6 Kbits/sec
```
### Test Frame Format
The option `-f` or `--frame-format` tests whether the RCP supports sending and receiving 802.15.4 frames of all formats.
```bash
$ DUT_ADB_USB=1269UCKFZTAM95OR REF_CLI_SERIAL=/dev/ttyACM0 python3 ./tools/cp-caps/rcp_caps_test.py -f
TX ver:2003,Cmd,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2003,Cmd,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2003,Bcon,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:30 ---------------- OK
RX ver:2003,Bcon,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:30 ---------------- OK
TX ver:2006,Cmd,seq,dst[addr:short,pan:id],src[addr:short,pan:no],sec:l5,ie:no,plen:0 -------------- OK
RX ver:2006,Cmd,seq,dst[addr:short,pan:id],src[addr:short,pan:no],sec:l5,ie:no,plen:0 -------------- OK
TX ver:2006,Cmd,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:l5,ie:no,plen:0 ---------------- OK
RX ver:2006,Cmd,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:l5,ie:no,plen:0 ---------------- OK
TX ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0 --------------- OK
RX ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0 --------------- OK
TX ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ------------- OK
RX ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ------------- OK
TX ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ---------------- OK
RX ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ---------------- OK
TX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0 ------------------- OK
RX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0 ------------------- OK
TX ver:2015,Data,seq,dst[addr:no,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ------------------- OK
RX ver:2015,Data,seq,dst[addr:no,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ------------------- OK
TX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0 ----------------- OK
RX ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0 ----------------- OK
TX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:no,ie:no,plen:0 --------------- OK
RX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:no,ie:no,plen:0 --------------- OK
TX ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0 --------------- OK
RX ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0 --------------- OK
TX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ------------- OK
RX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ------------- OK
TX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0 -------------- OK
RX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0 -------------- OK
TX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 -------------- OK
RX ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 -------------- OK
TX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie[csl],plen:0 ----------- OK
RX ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie[csl],plen:0 ----------- OK
TX ver:2015,Data,noseq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ----------- OK
RX ver:2015,Data,noseq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0 ----------- OK
```
+156 -23
View File
@@ -40,7 +40,7 @@ import otci
from otci import OTCI
from otci.types import Ip6Addr
CP_CAPABILITY_VERSION = "0.1.0"
CP_CAPABILITY_VERSION = "0.1.1-dev"
logging.basicConfig(level=logging.WARNING)
@@ -50,6 +50,8 @@ class RcpCaps(object):
This class represents an OpenThread RCP capability test instance.
"""
DEFAULT_FORMAT_ALIGN_LENGTH = 58 # The default formatted string alignment length
def __init__(self):
self.__dut = self.__connect_dut()
self.__ref = self.__connect_reference_device()
@@ -83,6 +85,113 @@ class RcpCaps(object):
self.__ref.diag_stop()
self.__dut.diag_stop()
def test_frame_format(self):
"""Test whether the DUT supports sending and receiving 802.15.4 frames of all formats."""
frames = [
{
'name': 'ver:2003,Cmd,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '030800ffffffff070000'
},
{
'name': 'ver:2003,Bcon,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:30',
'psdu': '00c000eeee0102030405060708ff0f000003514f70656e54687265616400000000000001020304050607080000'
},
{
'name': 'ver:2006,Cmd,seq,dst[addr:short,pan:id],src[addr:short,pan:no],sec:l5,ie:no,plen:0',
'psdu': '4b98ddddddaaaabbbb0d708001020304050607081565'
},
{
'name': 'ver:2006,Cmd,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:l5,ie:no,plen:0',
'psdu': '4bdcdddddd102030405060708001020304050607080d6e54687265046400820ee803'
},
{
'name': 'ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0',
'psdu': '01dcdddddd1020304050607080000001020304050607085468'
},
{
'name': 'ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0',
'psdu': '0198ddddddaaaaeeeebbbb7080'
},
{
'name': 'ver:2006,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '011cdddddd10203040506070800000'
},
{
'name': 'ver:2006,Data,seq,dst[addr:short,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '0118ddddddaaaa3040'
},
{
'name': 'ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '0120dddddd'
},
{
'name': 'ver:2015,Data,seq,dst[addr:no,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '4120ddddddaaaa'
},
{
'name': 'ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '012cdddddd10203040506070800000'
},
{
'name': 'ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:no,pan:no],sec:no,ie:no,plen:0',
'psdu': '412cdd10203040506070807080'
},
{
'name': 'ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:id],sec:no,ie:no,plen:0',
'psdu': '01e0ddeeee01020304050607080000'
},
{
'name': 'ver:2015,Data,seq,dst[addr:no,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0',
'psdu': '41e0dd01020304050607080708'
},
{
'name': 'ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:extd,pan:no],sec:no,ie:no,plen:0',
'psdu': '01ecdddddd102030405060708001020304050607080708'
},
{
'name': 'ver:2015,Data,seq,dst[addr:extd,pan:no],src[addr:extd,pan:no],sec:no,ie:no,plen:0',
'psdu': '41ecdd102030405060708001020304050607080708'
},
{
'name': 'ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0',
'psdu': '01a8ddddddaaaaeeeebbbb0102'
},
{
'name': 'ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:extd,pan:id],sec:no,ie:no,plen:0',
'psdu': '01e8ddddddaaaaeeee01020304050607080708'
},
{
'name': 'ver:2015,Data,seq,dst[addr:extd,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0',
'psdu': '01acdddddd1020304050607080eeeebbbb0708'
},
{
'name': 'ver:2015,Data,seq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie[csl],plen:0',
'psdu': '01aaddddddaaaaeeeebbbb040dc800e8030708'
},
{
'name': 'ver:2015,Data,noseq,dst[addr:short,pan:id],src[addr:short,pan:id],sec:no,ie:no,plen:0',
'psdu': '01a9ddddaaaaeeeebbbbbb04'
},
]
self.__dut.factory_reset()
self.__ref.factory_reset()
ret = self.__dut.is_command_supported('diag start')
if ret is False:
print('Diag commands are not supported')
return
self.__dut.diag_start()
self.__ref.diag_start()
for frame in frames:
self.__test_send_formated_frame(self.__dut, self.__ref, 'TX ' + frame['name'], frame['psdu'], 100)
self.__test_send_formated_frame(self.__ref, self.__dut, 'RX ' + frame['name'], frame['psdu'], 100)
self.__ref.diag_stop()
self.__dut.diag_stop()
def test_csl(self):
"""Test whether the DUT supports CSL transmitter."""
self.__dataset = self.__get_default_dataset()
@@ -476,34 +585,44 @@ class RcpCaps(object):
self.__output_format_bool(cmd_diag_repeat, ret)
self.__output_format_bool(cmd_diag_repeat_stop, ret)
def __test_diag_frame(self):
def __test_send_formated_frame(self,
sender: OTCI,
receiver: OTCI,
format_name: str,
frame: str,
align_length: int = DEFAULT_FORMAT_ALIGN_LENGTH):
packets = 100
threshold = 80
channel = 20
frame = '00010203040506070809'
cmd_diag_frame = f'diag frame {frame}'
commands = [cmd_diag_frame, f'diag send {packets}', f'diag stats', f'diag stats clear']
if self.__support_commands(commands):
self.__dut.wait(1)
self.__dut.diag_set_channel(channel)
self.__ref.diag_set_channel(channel)
self.__ref.diag_radio_receive()
sender.wait(1)
sender.diag_set_channel(channel)
receiver.diag_set_channel(channel)
receiver.diag_radio_receive()
self.__dut.diag_stats_clear()
self.__ref.diag_stats_clear()
sender.diag_stats_clear()
sender.diag_stats_clear()
self.__ref.diag_frame(frame)
self.__dut.diag_send(packets, None)
self.__dut.wait(1)
dut_stats = self.__dut.diag_get_stats()
ref_stats = self.__ref.diag_get_stats()
sender.diag_frame(frame)
sender.diag_send(packets, None)
sender.wait(1)
sender_stats = sender.diag_get_stats()
receiver_stats = receiver.diag_get_stats()
ret = dut_stats['sent_packets'] == packets and ref_stats['received_packets'] > threshold
ret = sender_stats['sent_packets'] == packets and receiver_stats['received_packets'] > threshold
else:
ret = False
self.__output_format_bool(cmd_diag_frame, ret)
self.__output_format_bool(format_name, ret, align_length)
def __test_diag_frame(self):
frame = '00010203040506070809'
cmd_diag_frame = f'diag frame {frame}'
self.__test_send_formated_frame(self.__dut, self.__ref, cmd_diag_frame, frame)
def __support_commands(self, commands: List[str]) -> bool:
ret = True
@@ -533,10 +652,12 @@ class RcpCaps(object):
node = otci.connect_otbr_adb_tcp(os.getenv('DUT_ADB_TCP'))
elif os.getenv('DUT_ADB_USB'):
node = otci.connect_otbr_adb_usb(os.getenv('DUT_ADB_USB'))
elif os.getenv('DUT_CLI_SERIAL'):
node = otci.connect_cli_serial(os.getenv('DUT_CLI_SERIAL'))
elif os.getenv('DUT_SSH'):
node = otci.connect_otbr_ssh(os.getenv('DUT_SSH'))
else:
self.__fail("Please set DUT_ADB_TCP, DUT_ADB_USB or DUT_SSH to connect to the DUT device.")
self.__fail("Please set DUT_ADB_TCP, DUT_ADB_USB, DUT_CLI_SERIAL or DUT_SSH to connect to the DUT device.")
return node
@@ -552,12 +673,12 @@ class RcpCaps(object):
return node
def __output_format_string(self, name: str, value: str):
prefix = '{0:-<58}'.format('{} '.format(name))
def __output_format_string(self, name: str, value: str, align_length: int = DEFAULT_FORMAT_ALIGN_LENGTH):
prefix = (name + ' ').ljust(align_length, '-')
print(f'{prefix} {value}')
def __output_format_bool(self, name: str, value: bool):
self.__output_format_string(name, 'OK' if value else 'NotSupported')
def __output_format_bool(self, name: str, value: bool, align_length: int = DEFAULT_FORMAT_ALIGN_LENGTH):
self.__output_format_string(name, 'OK' if value else 'NotSupported', align_length)
def __fail(self, value: str):
print(f'{value}')
@@ -569,11 +690,12 @@ def parse_arguments():
description_msg = 'This script is used for testing RCP capabilities.'
epilog_msg = textwrap.dedent(
'Device Interfaces:\r\n'
' DUT_SSH=<device_ip> Connect to the DUT via ssh\r\n'
' DUT_ADB_TCP=<device_ip> Connect to the DUT via adb tcp\r\n'
' DUT_ADB_USB=<serial_number> Connect to the DUT via adb usb\r\n'
' REF_CLI_SERIAL=<serial_device> Connect to the reference device via cli serial port\r\n'
' DUT_CLI_SERIAL=<serial_device> Connect to the DUT via cli serial port\r\n'
' DUT_SSH=<device_ip> Connect to the DUT via ssh\r\n'
' REF_ADB_USB=<serial_number> Connect to the reference device via adb usb\r\n'
' REF_CLI_SERIAL=<serial_device> Connect to the reference device via cli serial port\r\n'
' REF_SSH=<device_ip> Connect to the reference device via ssh\r\n'
'\r\n'
'Example:\r\n'
@@ -607,6 +729,14 @@ def parse_arguments():
help='test whether the RCP supports all diag commands',
)
parser.add_argument(
'-f',
'--frame-format',
action='store_true',
default=False,
help='test whether the RCP supports 802.15.4 frames of all formats',
)
parser.add_argument(
'-p',
'--data-poll',
@@ -670,6 +800,9 @@ def main():
if arguments.throughput:
rcp_caps.test_throughput()
if arguments.frame_format:
rcp_caps.test_frame_format()
if __name__ == '__main__':
main()