CI:add openthread ipv6 ra check in openthread CI

This commit is contained in:
Xu Si Yu 2022-10-13 11:55:36 +08:00
parent e0580d2669
commit 0a7e204d2e
3 changed files with 206 additions and 87 deletions

View File

@ -88,6 +88,7 @@
- "components/esp_phy/**/*" - "components/esp_phy/**/*"
- "components/ieee802154/**/*" - "components/ieee802154/**/*"
- "components/lwip/**/*" - "components/lwip/**/*"
- "components/openthread/**/*"
- "examples/common_components/iperf/**/*" - "examples/common_components/iperf/**/*"
- "examples/openthread/**/*" - "examples/openthread/**/*"

View File

@ -4,6 +4,8 @@
# this file defines some functions for testing cli and br under pytest framework # this file defines some functions for testing cli and br under pytest framework
import re import re
import socket
import struct
import subprocess import subprocess
import time import time
from typing import Tuple, Union from typing import Tuple, Union
@ -14,10 +16,12 @@ from pytest_embedded_idf.dut import IdfDut
def reset_thread(dut:IdfDut) -> None: def reset_thread(dut:IdfDut) -> None:
time.sleep(1) dut.write(' ')
dut.write('state')
clean_buffer(dut)
wait(dut, 1)
dut.write('factoryreset') dut.write('factoryreset')
time.sleep(3) dut.expect('OpenThread attached to netif', timeout=20)
dut.expect('OpenThread attached to netif', timeout=10)
dut.write(' ') dut.write(' ')
dut.write('state') dut.write('state')
@ -92,18 +96,30 @@ def start_thread(dut:IdfDut) -> str:
return role return role
def wait_key_str(leader:IdfDut, child:IdfDut) -> None:
wait(leader, 1)
leader.expect('OpenThread attached to netif', timeout=20)
leader.write(' ')
leader.write('state')
child.expect('OpenThread attached to netif', timeout=20)
child.write(' ')
child.write('state')
def config_network(leader:IdfDut, child:IdfDut, leader_name:str, thread_dataset_model:str,
thread_dataset:str, wifi:IdfDut, wifi_ssid:str, wifi_psk:str) -> str:
wait_key_str(leader, child)
return form_network_using_manual_configuration(leader, child, leader_name, thread_dataset_model,
thread_dataset, wifi, wifi_ssid, wifi_psk)
# config br and cli manually # config br and cli manually
def form_network_using_manual_configuration(leader:IdfDut, child:IdfDut, leader_name:str, thread_dataset_model:str, def form_network_using_manual_configuration(leader:IdfDut, child:IdfDut, leader_name:str, thread_dataset_model:str,
thread_dataset:str, wifi:IdfDut, wifi_ssid:str, wifi_psk:str) -> str: thread_dataset:str, wifi:IdfDut, wifi_ssid:str, wifi_psk:str) -> str:
time.sleep(3)
leader.expect('OpenThread attached to netif', timeout=10)
leader.write(' ')
leader.write('state')
child.expect('OpenThread attached to netif', timeout=10)
child.write(' ')
child.write('state')
reset_thread(leader) reset_thread(leader)
clean_buffer(leader)
reset_thread(child) reset_thread(child)
clean_buffer(child)
leader.write('channel 12') leader.write('channel 12')
leader.expect('Done', timeout=2) leader.expect('Done', timeout=2)
child.write('channel 12') child.write('channel 12')
@ -130,6 +146,7 @@ def form_network_using_manual_configuration(leader:IdfDut, child:IdfDut, leader_
child.expect('Done', timeout=2) child.expect('Done', timeout=2)
role = start_thread(child) role = start_thread(child)
assert role == 'child' assert role == 'child'
wait(leader, 10)
return res return res
@ -152,6 +169,7 @@ def connect_wifi(dut:IdfDut, ssid:str, psk:str, nums:int) -> Tuple[str, int]:
for order in range(1, nums): for order in range(1, nums):
dut.write('wifi connect -s ' + str(ssid) + ' -p ' + str(psk)) dut.write('wifi connect -s ' + str(ssid) + ' -p ' + str(psk))
tmp = dut.expect(pexpect.TIMEOUT, timeout=5) tmp = dut.expect(pexpect.TIMEOUT, timeout=5)
if 'sta ip' in str(tmp):
ip_address = re.findall(r'sta ip: (\w+.\w+.\w+.\w+),', str(tmp))[0] ip_address = re.findall(r'sta ip: (\w+.\w+.\w+.\w+),', str(tmp))[0]
information = dut.expect(r'wifi sta (\w+ \w+ \w+)\W', timeout=5)[1].decode() information = dut.expect(r'wifi sta (\w+ \w+ \w+)\W', timeout=5)[1].decode()
if information == 'is connected successfully': if information == 'is connected successfully':
@ -166,13 +184,13 @@ def reset_host_interface() -> None:
try: try:
command = 'ifconfig ' + interface_name + ' down' command = 'ifconfig ' + interface_name + ' down'
subprocess.call(command, shell=True, timeout=5) subprocess.call(command, shell=True, timeout=5)
time.sleep(10) time.sleep(1)
command = 'ifconfig ' + interface_name + ' up' command = 'ifconfig ' + interface_name + ' up'
subprocess.call(command, shell=True, timeout=10) subprocess.call(command, shell=True, timeout=10)
time.sleep(20) time.sleep(1)
flag = True flag = True
finally: finally:
time.sleep(10) time.sleep(1)
assert flag assert flag
@ -185,10 +203,10 @@ def set_interface_sysctl_options() -> None:
time.sleep(1) time.sleep(1)
command = 'sysctl -w net/ipv6/conf/' + interface_name + '/accept_ra_rt_info_max_plen=128' command = 'sysctl -w net/ipv6/conf/' + interface_name + '/accept_ra_rt_info_max_plen=128'
subprocess.call(command, shell=True, timeout=5) subprocess.call(command, shell=True, timeout=5)
time.sleep(5) time.sleep(1)
flag = True flag = True
finally: finally:
time.sleep(5) time.sleep(2)
assert flag assert flag
@ -207,7 +225,7 @@ def init_interface_ipv6_address() -> None:
time.sleep(1) time.sleep(1)
flag = True flag = True
finally: finally:
time.sleep(5) time.sleep(1)
assert flag assert flag
@ -220,3 +238,98 @@ def get_host_interface_name() -> str:
def clean_buffer(dut:IdfDut) -> None: def clean_buffer(dut:IdfDut) -> None:
str_length = str(len(dut.expect(pexpect.TIMEOUT, timeout=0.1))) str_length = str(len(dut.expect(pexpect.TIMEOUT, timeout=0.1)))
dut.expect(r'[\s\S]{%s}' % str(str_length), timeout=10) dut.expect(r'[\s\S]{%s}' % str(str_length), timeout=10)
def check_if_host_receive_ra(br:IdfDut) -> bool:
interface_name = get_host_interface_name()
clean_buffer(br)
br.write('br omrprefix')
omrprefix = br.expect(r'\n((?:\w+:){4}):/\d+\r', timeout=5)[1].decode()
command = 'ip -6 route | grep ' + str(interface_name)
out_str = subprocess.getoutput(command)
print('br omrprefix: ', str(omrprefix))
print('host route table:\n', str(out_str))
return str(omrprefix) in str(out_str)
def host_connect_wifi() -> None:
command = '. /home/test/wlan_connection_OTTE.sh'
subprocess.call(command, shell=True, timeout=30)
time.sleep(5)
def is_joined_wifi_network(br:IdfDut) -> bool:
return check_if_host_receive_ra(br)
thread_ipv6_group = 'ff04:0:0:0:0:0:0:125'
def check_ipmaddr(dut:IdfDut) -> bool:
clean_buffer(dut)
dut.write('ipmaddr')
info = dut.expect(pexpect.TIMEOUT, timeout=2)
if thread_ipv6_group in str(info):
return True
return False
def thread_is_joined_group(dut:IdfDut) -> bool:
command = 'mcast join ' + thread_ipv6_group
dut.write(command)
dut.expect('Done', timeout=2)
order = 0
while order < 3:
if check_ipmaddr(dut):
return True
dut.write(command)
wait(dut, 2)
order = order + 1
return False
host_ipv6_group = 'ff04::125'
def host_joined_group() -> bool:
interface_name = get_host_interface_name()
command = 'netstat -g | grep ' + str(interface_name)
out_str = subprocess.getoutput(command)
print('groups:\n', str(out_str))
return host_ipv6_group in str(out_str)
class udp_parameter:
def __init__(self, group:str='', try_join_udp_group:bool=False, timeout:float=15.0, udp_bytes:bytes=b''):
self.group = group
self.try_join_udp_group = try_join_udp_group
self.timeout = timeout
self.udp_bytes = udp_bytes
def create_host_udp_server(myudp:udp_parameter) -> None:
interface_name = get_host_interface_name()
try:
print('The host start to create udp server!')
if_index = socket.if_nametoindex(interface_name)
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.bind(('::', 5090))
sock.setsockopt(
socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP,
struct.pack('16si', socket.inet_pton(socket.AF_INET6, myudp.group),
if_index))
myudp.try_join_udp_group = True
sock.settimeout(myudp.timeout)
print('The host start to receive message!')
myudp.udp_bytes = (sock.recvfrom(1024))[0]
print('The host has received message: ', myudp.udp_bytes)
except socket.error:
print('The host did not receive message!')
finally:
print('Close the socket.')
sock.close()
def wait(dut:IdfDut, wait_time:float) -> None:
dut.expect(pexpect.TIMEOUT, timeout=wait_time)

View File

@ -5,9 +5,8 @@
import os.path import os.path
import re import re
import socket
import struct
import subprocess import subprocess
import threading
import time import time
from typing import Tuple from typing import Tuple
@ -34,32 +33,37 @@ from pytest_embedded_idf.dut import IdfDut
def fixture_Init_interface() -> bool: def fixture_Init_interface() -> bool:
ocf.init_interface_ipv6_address() ocf.init_interface_ipv6_address()
ocf.reset_host_interface() ocf.reset_host_interface()
time.sleep(30)
ocf.set_interface_sysctl_options() ocf.set_interface_sysctl_options()
return True return True
wifi_ssid = 'OTCITE'
wifi_psk = 'otcitest888'
# Case 1: Thread network formation and attaching # Case 1: Thread network formation and attaching
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.timeout(40 * 60)
@pytest.mark.i154_multi_dut @pytest.mark.i154_multi_dut
@pytest.mark.flaky(reruns=2, reruns_delay=10)
@pytest.mark.parametrize( @pytest.mark.parametrize(
'port, config, count, app_path, beta_target, target', [ 'port, config, count, app_path, beta_target, target', [
('/dev/USB_BR|/dev/USB_CLI|/dev/USB_RCP', 'br|cli|rcp', 3, ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
f'{os.path.join(os.path.dirname(__file__), "ot_br")}' f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_rcp")}', f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32s3|esp32h2beta2|esp32h2beta2', 'esp32s3|esp32h2|esp32h2'), 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h2|esp32h2|esp32s3'),
], ],
indirect=True, indirect=True,
) )
def test_thread_connect(dut:Tuple[IdfDut, IdfDut]) -> None: def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None:
br = dut[0] br = dut[2]
cli = dut[1] cli = dut[1]
dut[0].close()
dataset = '-1' dataset = '-1'
ocf.form_network_using_manual_configuration(br, cli, 'br', 'random', dataset, br, 'OTCITE', '0000') ocf.config_network(br, cli, 'br', 'random', dataset, br, wifi_ssid, '0000')
time.sleep(1)
flag = False flag = False
try: try:
cli_mleid_addr = ocf.get_mleid_addr(cli) cli_mleid_addr = ocf.get_mleid_addr(cli)
@ -79,32 +83,34 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut]) -> None:
# Case 2: Bidirectional IPv6 connectivity # Case 2: Bidirectional IPv6 connectivity
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.timeout(40 * 60)
@pytest.mark.i154_multi_dut @pytest.mark.i154_multi_dut
@pytest.mark.flaky(reruns=5, reruns_delay=10)
@pytest.mark.parametrize( @pytest.mark.parametrize(
'port, config, count, app_path, beta_target, target', [ 'port, config, count, app_path, beta_target, target', [
('/dev/USB_BR|/dev/USB_CLI|/dev/USB_RCP', 'br|cli|rcp', 3, ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
f'{os.path.join(os.path.dirname(__file__), "ot_br")}' f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_rcp")}', f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32s3|esp32h2beta2|esp32h2beta2', 'esp32s3|esp32h2|esp32h2'), 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h2|esp32h2|esp32s3'),
], ],
indirect=True, indirect=True,
) )
def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut, IdfDut]) -> None: def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
br = dut[0] br = dut[2]
cli = dut[1] cli = dut[1]
assert Init_interface assert Init_interface
dut[0].close()
dataset = '-1' dataset = '-1'
ocf.form_network_using_manual_configuration(br, cli, 'br', 'random', dataset, br, 'OTCITE', 'otcitest888') ocf.config_network(br, cli, 'br', 'random', dataset, br, wifi_ssid, wifi_psk)
time.sleep(5)
cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
flag = False flag = False
try: try:
assert ocf.is_joined_wifi_network(br)
cli_global_unicast_addr = ocf.get_global_unicast_addr(cli, br)
print('cli_global_unicast_addr', cli_global_unicast_addr)
command = 'ping ' + str(cli_global_unicast_addr) + ' -c 10' command = 'ping ' + str(cli_global_unicast_addr) + ' -c 10'
out_bytes = subprocess.check_output(command, shell=True, timeout=60) out_str = subprocess.getoutput(command)
out_str = out_bytes.decode('utf-8') print('ping result:\n', str(out_str))
role = re.findall(r' (\d+)%', str(out_str))[0] role = re.findall(r' (\d+)%', str(out_str))[0]
assert role != '100' assert role != '100'
interface_name = ocf.get_host_interface_name() interface_name = ocf.get_host_interface_name()
@ -128,37 +134,36 @@ def test_Bidirectional_IPv6_connectivity(Init_interface:bool, dut: Tuple[IdfDut,
# Case 3: Multicast forwarding from Wi-Fi to Thread network # Case 3: Multicast forwarding from Wi-Fi to Thread network
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.timeout(40 * 60)
@pytest.mark.i154_multi_dut @pytest.mark.i154_multi_dut
@pytest.mark.flaky(reruns=5, reruns_delay=10)
@pytest.mark.parametrize( @pytest.mark.parametrize(
'port, config, count, app_path, beta_target, target', [ 'port, config, count, app_path, beta_target, target', [
('/dev/USB_BR|/dev/USB_CLI|/dev/USB_RCP', 'br|cli|rcp', 3, ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
f'{os.path.join(os.path.dirname(__file__), "ot_br")}' f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_rcp")}', f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32s3|esp32h2beta2|esp32h2beta2', 'esp32s3|esp32h2|esp32h2'), 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h2|esp32h2|esp32s3'),
], ],
indirect=True, indirect=True,
) )
def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut]) -> None: def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
br = dut[0] br = dut[2]
cli = dut[1] cli = dut[1]
assert Init_interface assert Init_interface
dut[0].close()
dataset = '-1' dataset = '-1'
ocf.form_network_using_manual_configuration(br, cli, 'br', 'random', dataset, br, 'OTCITE', 'otcitest888') ocf.config_network(br, cli, 'br', 'random', dataset, br, wifi_ssid, wifi_psk)
time.sleep(5)
flag = False flag = False
try: try:
assert ocf.is_joined_wifi_network(br)
br.write('bbr') br.write('bbr')
br.expect('server16', timeout=2) br.expect('server16', timeout=2)
cli.write('mcast join ff04::125') assert ocf.thread_is_joined_group(cli)
cli.expect('Done', timeout=2)
time.sleep(1)
interface_name = ocf.get_host_interface_name() interface_name = ocf.get_host_interface_name()
command = 'ping -I ' + str(interface_name) + ' -t 64 ff04::125 -c 10' command = 'ping -I ' + str(interface_name) + ' -t 64 ff04::125 -c 10'
out_bytes = subprocess.check_output(command, shell=True, timeout=60) out_str = subprocess.getoutput(command)
out_str = out_bytes.decode('utf-8') print('ping result:\n', str(out_str))
role = re.findall(r' (\d+)%', str(out_str))[0] role = re.findall(r' (\d+)%', str(out_str))[0]
assert role != '100' assert role != '100'
flag = True flag = True
@ -172,52 +177,52 @@ def test_multicast_forwarding_A(Init_interface:bool, dut: Tuple[IdfDut, IdfDut])
# Case 4: Multicast forwarding from Thread to Wi-Fi network # Case 4: Multicast forwarding from Thread to Wi-Fi network
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.timeout(40 * 60)
@pytest.mark.i154_multi_dut @pytest.mark.i154_multi_dut
@pytest.mark.flaky(reruns=5, reruns_delay=5)
@pytest.mark.parametrize( @pytest.mark.parametrize(
'port, config, count, app_path, beta_target, target', [ 'port, config, count, app_path, beta_target, target', [
('/dev/USB_BR|/dev/USB_CLI|/dev/USB_RCP', 'br|cli|rcp', 3, ('/dev/USB_RCP|/dev/USB_CLI|/dev/USB_BR', 'rcp|cli|br', 3,
f'{os.path.join(os.path.dirname(__file__), "ot_br")}' f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}' f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_rcp")}', f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32s3|esp32h2beta2|esp32h2beta2', 'esp32s3|esp32h2|esp32h2'), 'esp32h2beta2|esp32h2beta2|esp32s3', 'esp32h2|esp32h2|esp32s3'),
], ],
indirect=True, indirect=True,
) )
def test_multicast_forwarding_B(Init_interface:bool, dut: Tuple[IdfDut, IdfDut]) -> None: def test_multicast_forwarding_B(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> None:
br = dut[0] br = dut[2]
cli = dut[1] cli = dut[1]
assert Init_interface assert Init_interface
dut[0].close()
dataset = '-1' dataset = '-1'
ocf.form_network_using_manual_configuration(br, cli, 'br', 'random', dataset, br, 'OTCITE', 'otcitest888') ocf.config_network(br, cli, 'br', 'random', dataset, br, wifi_ssid, wifi_psk)
time.sleep(5) try:
assert ocf.is_joined_wifi_network(br)
br.write('bbr') br.write('bbr')
br.expect('server16', timeout=2) br.expect('server16', timeout=2)
interface_name = ocf.get_host_interface_name()
if_index = socket.if_nametoindex(interface_name)
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.bind(('::', 5090))
sock.setsockopt(
socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP,
struct.pack('16si', socket.inet_pton(socket.AF_INET6, 'ff04::125'),
if_index))
time.sleep(1)
cli.write('udp open') cli.write('udp open')
cli.expect('Done', timeout=2) cli.expect('Done', timeout=2)
cli.write('udp send ff04::125 5090 hello') ocf.wait(cli, 1)
cli.write('udp open')
cli.expect('Already', timeout=2)
myudp = ocf.udp_parameter('ff04::125', False, 15.0, b'')
udp_mission = threading.Thread(target=ocf.create_host_udp_server, args=(myudp, ))
udp_mission.start()
start_time = time.time()
while not myudp.try_join_udp_group:
if (time.time() - start_time) > 10:
assert False
assert ocf.host_joined_group()
for num in range(0, 3):
command = 'udp send ff04::125 5090 hello' + str(num)
cli.write(command)
cli.expect('Done', timeout=2) cli.expect('Done', timeout=2)
data = b'' ocf.wait(cli, 0.5)
try: while udp_mission.is_alive():
print('The host start to receive message!') time.sleep(1)
sock.settimeout(5)
data = (sock.recvfrom(1024))[0]
print('The host has received message!')
except socket.error:
print('The host did not received message!')
finally: finally:
sock.close()
br.write('factoryreset') br.write('factoryreset')
cli.write('factoryreset') cli.write('factoryreset')
time.sleep(3) time.sleep(3)
assert data == b'hello' assert b'hello' in myudp.udp_bytes