mirror of
https://github.com/espressif/openthread.git
synced 2026-09-05 16:50:05 +00:00
[test] add multi-radio and TREL test cases (#4440)
This commit adds new builds under "simulation-build-autotools"
to cover multi-radio configurations: TREL only, 15.4+TREL,
15.4+TREL+ToBLE.
It also adds new GitHub action tests covering all `toranj`
test-cases with different configurations:
1) NCP model with TREL radio only,
2) POSIX App and RCP model with TREL radio only (emulated over
a virtual Ethernet netif).
This commit is contained in:
committed by
Jonathan Hui
parent
451ae39be4
commit
3d21a846d9
@@ -44,6 +44,7 @@ jobs:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
COVERAGE: 1
|
||||
TORANJ_RADIO : 15.4
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
@@ -81,6 +82,7 @@ jobs:
|
||||
env:
|
||||
COVERAGE: 1
|
||||
TORANJ_POSIX_RCP_MODEL: 1
|
||||
TORANJ_RADIO : 15.4
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
@@ -113,10 +115,111 @@ jobs:
|
||||
name: cov-toranj-rcp
|
||||
path: tmp/coverage.info
|
||||
|
||||
toranj-ncp-trel:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
COVERAGE: 1
|
||||
TORANJ_RADIO : trel
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
|
||||
sudo apt-get --no-install-recommends install -y dbus libdbus-1-dev
|
||||
sudo apt-get --no-install-recommends install -y autoconf-archive
|
||||
sudo apt-get --no-install-recommends install -y bsdtar
|
||||
sudo apt-get --no-install-recommends install -y libtool
|
||||
sudo apt-get --no-install-recommends install -y libglib2.0-dev
|
||||
sudo apt-get --no-install-recommends install -y libboost-dev libboost-signals-dev
|
||||
sudo apt-get --no-install-recommends install -y lcov
|
||||
|
||||
git clone --depth=1 --branch=master https://github.com/openthread/wpantund.git
|
||||
cd wpantund
|
||||
./bootstrap.sh
|
||||
./configure
|
||||
sudo make -j2
|
||||
sudo make install
|
||||
- name: Build & Run
|
||||
run: |
|
||||
top_builddir=$(pwd)/build/toranj ./tests/toranj/start.sh
|
||||
- name: Generate Coverage
|
||||
run: |
|
||||
./script/test generate_coverage gcc
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cov-toranj-ncp-trel
|
||||
path: tmp/coverage.info
|
||||
|
||||
toranj-rcp-trel:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
COVERAGE: 1
|
||||
TORANJ_POSIX_RCP_MODEL: 1
|
||||
TORANJ_RADIO : trel
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
|
||||
sudo apt-get --no-install-recommends install -y dbus libdbus-1-dev
|
||||
sudo apt-get --no-install-recommends install -y autoconf-archive
|
||||
sudo apt-get --no-install-recommends install -y bsdtar
|
||||
sudo apt-get --no-install-recommends install -y libtool
|
||||
sudo apt-get --no-install-recommends install -y libglib2.0-dev
|
||||
sudo apt-get --no-install-recommends install -y libboost-dev libboost-signals-dev
|
||||
sudo apt-get --no-install-recommends install -y lcov
|
||||
|
||||
git clone --depth=1 --branch=master https://github.com/openthread/wpantund.git
|
||||
cd wpantund
|
||||
./bootstrap.sh
|
||||
./configure
|
||||
sudo make -j2
|
||||
sudo make install
|
||||
- name: Build & Run
|
||||
run: |
|
||||
top_builddir=$(pwd)/build/toranj ./tests/toranj/start.sh
|
||||
- name: Generate Coverage
|
||||
run: |
|
||||
./script/test generate_coverage gcc
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cov-toranj-rcp-trel
|
||||
path: tmp/coverage.info
|
||||
|
||||
toranj-ncp-multi:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
COVERAGE: 1
|
||||
TORANJ_RADIO : multi
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
|
||||
sudo apt-get --no-install-recommends install -y dbus libdbus-1-dev
|
||||
sudo apt-get --no-install-recommends install -y autoconf-archive
|
||||
sudo apt-get --no-install-recommends install -y bsdtar
|
||||
sudo apt-get --no-install-recommends install -y libtool
|
||||
sudo apt-get --no-install-recommends install -y libglib2.0-dev
|
||||
sudo apt-get --no-install-recommends install -y libboost-dev libboost-signals-dev
|
||||
sudo apt-get --no-install-recommends install -y lcov
|
||||
|
||||
git clone --depth=1 --branch=master https://github.com/openthread/wpantund.git
|
||||
cd wpantund
|
||||
./bootstrap.sh
|
||||
./configure
|
||||
sudo make -j2
|
||||
sudo make install
|
||||
- name: Build & Run
|
||||
run: |
|
||||
top_builddir=$(pwd)/build/toranj ./tests/toranj/start.sh
|
||||
|
||||
upload-coverage:
|
||||
needs:
|
||||
- toranj-ncp
|
||||
- toranj-rcp
|
||||
- toranj-ncp-trel
|
||||
- toranj-rcp-trel
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -192,12 +192,68 @@ build_nest_common()
|
||||
cd ..
|
||||
}
|
||||
|
||||
build_multi_radio_links()
|
||||
{
|
||||
# TREL radio link only.
|
||||
local options=(
|
||||
"-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG"
|
||||
"-DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=0"
|
||||
"-DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1"
|
||||
)
|
||||
export CPPFLAGS="${options[*]}"
|
||||
|
||||
reset_source
|
||||
mkdir build && cd build
|
||||
../configure \
|
||||
--enable-cli \
|
||||
--enable-ftd \
|
||||
--enable-mtd \
|
||||
--enable-ncp \
|
||||
--enable-radio-only \
|
||||
--with-examples=simulation \
|
||||
--disable-docs \
|
||||
--disable-tests
|
||||
make -j"${OT_BUILD_JOBS}"
|
||||
cd ..
|
||||
|
||||
# Multi radio link - 15.4 and TREL.
|
||||
options=(
|
||||
"-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_DIAG_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_LINK_RAW_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG"
|
||||
"-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1"
|
||||
)
|
||||
export CPPFLAGS="${options[*]}"
|
||||
|
||||
reset_source
|
||||
mkdir build && cd build
|
||||
../configure \
|
||||
--enable-cli \
|
||||
--enable-ftd \
|
||||
--enable-mtd \
|
||||
--enable-ncp \
|
||||
--enable-radio-only \
|
||||
--with-examples=simulation \
|
||||
--disable-docs \
|
||||
--disable-tests
|
||||
make -j"${OT_BUILD_JOBS}"
|
||||
cd ..
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
./bootstrap
|
||||
|
||||
build_all_features
|
||||
build_nest_common
|
||||
build_multi_radio_links
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -134,6 +134,7 @@ case ${build_config} in
|
||||
--with-examples=simulation \
|
||||
"${configure_options[@]}" || die
|
||||
make -j 8 || die
|
||||
cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-15.4
|
||||
;;
|
||||
|
||||
ncp-trel)
|
||||
@@ -150,6 +151,7 @@ case ${build_config} in
|
||||
--with-examples=simulation \
|
||||
"${configure_options[@]}" || die
|
||||
make -j 8 || die
|
||||
cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-trel
|
||||
;;
|
||||
|
||||
ncp-15.4+trel | ncp-trel+15.4)
|
||||
@@ -166,6 +168,7 @@ case ${build_config} in
|
||||
--with-examples=simulation \
|
||||
"${configure_options[@]}" || die
|
||||
make -j 8 || die
|
||||
cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-15.4-trel
|
||||
;;
|
||||
|
||||
rcp)
|
||||
|
||||
+28
-4
@@ -75,8 +75,8 @@ run()
|
||||
return
|
||||
fi
|
||||
|
||||
# We allow a failed test to be retried up to 3 attempts.
|
||||
if [ "$counter" -lt 2 ]; then
|
||||
# We allow a failed test to be retried up to 7 attempts.
|
||||
if [ "$counter" -lt 7 ]; then
|
||||
counter=$((counter + 1))
|
||||
echo Attempt $counter running "$1" failed. Trying again.
|
||||
cleanup
|
||||
@@ -92,6 +92,10 @@ run()
|
||||
|
||||
cd "$(dirname "$0")" || die "cd failed"
|
||||
|
||||
if [ -z "${top_builddir}" ]; then
|
||||
top_builddir=.
|
||||
fi
|
||||
|
||||
if [ "$COVERAGE" = 1 ]; then
|
||||
coverage_option="--enable-coverage"
|
||||
else
|
||||
@@ -108,8 +112,17 @@ case $TORANJ_POSIX_RCP_MODEL in
|
||||
esac
|
||||
|
||||
if [ "$use_posix_with_rcp" = "no" ]; then
|
||||
./build.sh ${coverage_option} ncp-"${TORANJ_RADIO}" || die "ncp build failed"
|
||||
|
||||
if [ "$TORANJ_RADIO" = "multi" ]; then
|
||||
# Build all combinations
|
||||
./build.sh ${coverage_option} ncp-15.4 || die "ncp-15.4 build failed"
|
||||
(cd ${top_builddir} && make clean) || die "cd and clean failed"
|
||||
./build.sh ${coverage_option} ncp-trel || die "ncp-trel build failed"
|
||||
(cd ${top_builddir} && make clean) || die "cd and clean failed"
|
||||
./build.sh ${coverage_option} ncp-15.4+trel || die "ncp-15.4+trel build failed"
|
||||
(cd ${top_builddir} && make clean) || die "cd and clean failed"
|
||||
else
|
||||
./build.sh ${coverage_option} ncp-"${TORANJ_RADIO}" || die "ncp build failed"
|
||||
fi
|
||||
else
|
||||
./build.sh ${coverage_option} rcp || die "rcp build failed"
|
||||
./build.sh ${coverage_option} posix-"${TORANJ_RADIO}" || die "posix build failed"
|
||||
@@ -121,6 +134,17 @@ fi
|
||||
|
||||
cleanup
|
||||
|
||||
if [ "$TORANJ_RADIO" = "multi" ]; then
|
||||
run test-700-multi-radio-join.py
|
||||
run test-701-multi-radio-probe.py
|
||||
run test-702-multi-radio-discovery-by-rx.py
|
||||
run test-703-multi-radio-mesh-header-msg.py
|
||||
run test-704-multi-radio-scan.py
|
||||
run test-705-multi-radio-discover-scan.py
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
run test-001-get-set.py
|
||||
run test-002-form.py
|
||||
run test-003-join.py
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import time
|
||||
import wpan
|
||||
from wpan import verify
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: This test covers joining of nodes with different radio links
|
||||
#
|
||||
# Parent node with trel and 15.4 with 3 children.
|
||||
#
|
||||
# parent
|
||||
# (trel + 15.4)
|
||||
# / | \
|
||||
# / | \
|
||||
# / | \
|
||||
# c1 c2 c3
|
||||
# (15.4) (trel) (trel+15.4)
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 4
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
parent = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
c1 = wpan.Node(wpan.NODE_15_4)
|
||||
c2 = wpan.Node(wpan.NODE_TREL)
|
||||
c3 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
WAIT_TIME = 5
|
||||
|
||||
# Verify that each node supports the correct radio links:
|
||||
|
||||
parent_radios = wpan.parse_list(parent.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(parent_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in parent_radios) and
|
||||
(wpan.RADIO_LINK_TREL_UDP6 in parent_radios))
|
||||
|
||||
c1_radios = wpan.parse_list(c1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(len(c1_radios) == 1 and wpan.RADIO_LINK_IEEE_802_15_4 in c1_radios)
|
||||
|
||||
c2_radios = wpan.parse_list(c2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(len(c2_radios) == 1 and wpan.RADIO_LINK_TREL_UDP6 in c2_radios)
|
||||
|
||||
c3_radios = wpan.parse_list(c3.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(c3_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in c3_radios) and (wpan.RADIO_LINK_TREL_UDP6 in c3_radios))
|
||||
|
||||
parent.form("multi-radio")
|
||||
|
||||
c1.join_node(parent, wpan.JOIN_TYPE_END_DEVICE)
|
||||
c2.join_node(parent, wpan.JOIN_TYPE_END_DEVICE)
|
||||
c3.join_node(parent, wpan.JOIN_TYPE_END_DEVICE)
|
||||
|
||||
# Verify that parent correctly knows about all the children and their supported radio links
|
||||
|
||||
radio_info_entries = wpan.parse_multi_radio_result(parent.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(radio_info_entries) == 3)
|
||||
|
||||
for node in [c1, c2, c3]:
|
||||
# Find the entry matching node ext address
|
||||
address = node.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
|
||||
filtred_list = [entry for entry in radio_info_entries if entry.ext_address == address]
|
||||
verify(len(filtred_list) == 1)
|
||||
entry = filtred_list[0]
|
||||
|
||||
# Verify that the multi radio info matches the radio links supported by the node
|
||||
node_radios = wpan.parse_list(node.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(len(node_radios) == len(entry.radios))
|
||||
for radio in node_radios:
|
||||
verify(entry.supports(radio))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Reset the parent and check that all children are attached back successfully
|
||||
|
||||
parent.reset()
|
||||
|
||||
|
||||
def check_all_children_are_attached():
|
||||
neighbor_table = wpan.parse_neighbor_table_result(parent.get(wpan.WPAN_THREAD_NEIGHBOR_TABLE))
|
||||
verify(len(neighbor_table) == 3)
|
||||
|
||||
|
||||
wpan.verify_within(check_all_children_are_attached, WAIT_TIME)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import time
|
||||
import wpan
|
||||
from wpan import verify
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: This test covers behavior of device after trel network is temporarily disabled
|
||||
# and rediscovery of trel radio using probe mechanism.
|
||||
#
|
||||
# r1 ---------- r2
|
||||
# (15.4+trel) (15.4+trel)
|
||||
#
|
||||
# On r2 we disable trel temporarily.
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 4
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
r1 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
r2 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
c2 = wpan.Node(wpan.NODE_15_4)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
#
|
||||
|
||||
r1.allowlist_node(r2)
|
||||
r2.allowlist_node(r1)
|
||||
|
||||
r2.allowlist_node(c2)
|
||||
c2.allowlist_node(r2)
|
||||
|
||||
r1.form("discover-by-rx")
|
||||
|
||||
r2.join_node(r1, wpan.JOIN_TYPE_ROUTER)
|
||||
c2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
WAIT_TIME = 5
|
||||
HIGH_PREFERENCE_THRESHOLD = 220
|
||||
MIN_PREFERENCE_THRESHOLD = 0
|
||||
|
||||
r1_ext_address = r1.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
|
||||
r1_rloc = int(r1.get(wpan.WPAN_THREAD_RLOC16), 16)
|
||||
r1_ml_address = r1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
r2_ext_address = r2.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
|
||||
r2_rloc = int(r2.get(wpan.WPAN_THREAD_RLOC16), 16)
|
||||
r2_ml_address = r2.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
|
||||
# Wait for r2 to become router and r1 establishes a link with it
|
||||
|
||||
|
||||
def check_r1_router_table():
|
||||
router_table = wpan.parse_router_table_result(r1.get(wpan.WPAN_THREAD_ROUTER_TABLE))
|
||||
verify(len(router_table) == 2)
|
||||
for entry in router_table:
|
||||
verify(entry.rloc16 == r1_rloc or entry.is_link_established())
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_router_table, WAIT_TIME)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Check that r1 detected both trel and 15.4 as supported radio by r2
|
||||
|
||||
r1_radios = wpan.parse_list(r1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(r1_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r1_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r1_radios))
|
||||
|
||||
r2_radios = wpan.parse_list(r2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(r2_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r2_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r2_radios))
|
||||
|
||||
|
||||
def check_r1_sees_r2_has_two_radio_links():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
verify(len(r1_neighbor_radios[0].radios) == 2)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_sees_r2_has_two_radio_links, WAIT_TIME)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Send from r1 to r2 and verify that r1 prefers trel radio link for sending to r2.
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi r2 from r1", 5)
|
||||
recver = r2.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Now disable trel link on r2 and send again. We expect that r1 would quickly learn that trel is
|
||||
# no longer supported by r2 and prefer 15.4 for tx to r2.
|
||||
|
||||
r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'false')
|
||||
verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'false')
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi again r2 from r1", 5)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
|
||||
|
||||
def check_r1_does_not_prefer_trel_for_r2():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_does_not_prefer_trel_for_r2, WAIT_TIME)
|
||||
|
||||
# Check that we can send between r1 and r2 (now all tx should use 15.4)
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi on 15.4 r2 from r1", 5)
|
||||
recver = r2.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD)
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_IEEE_802_15_4))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_IEEE_802_15_4) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Enable trel back on r2, start sending traffic from r1 to r2
|
||||
# The probe mechanism should kick and detect that r2 has trel again.
|
||||
|
||||
r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'true')
|
||||
verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'true')
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Probing r2 from r1", 80)
|
||||
recver = r2.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
|
||||
def check_r1_again_prefers_trel_for_r2():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_again_prefers_trel_for_r2, WAIT_TIME)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import time
|
||||
import wpan
|
||||
from wpan import verify
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: This test covers behavior of device after TREL network is temporarily disabled
|
||||
# and rediscovery of TREL by receiving message over that radio from the neighbor.
|
||||
#
|
||||
# r1 ---------- r2
|
||||
# (15.4+trel) (15.4+trel)
|
||||
#
|
||||
# On r2 we disable trel temporarily.
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 4
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
r1 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
r2 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
c2 = wpan.Node(wpan.NODE_15_4)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
#
|
||||
|
||||
r1.allowlist_node(r2)
|
||||
r2.allowlist_node(r1)
|
||||
|
||||
r2.allowlist_node(c2)
|
||||
c2.allowlist_node(r2)
|
||||
|
||||
r1.form("discover-by-rx")
|
||||
|
||||
r2.join_node(r1, wpan.JOIN_TYPE_ROUTER)
|
||||
c2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
WAIT_TIME = 5
|
||||
HIGH_PREFERENCE_THRESHOLD = 220
|
||||
MIN_PREFERENCE_THRESHOLD = 0
|
||||
|
||||
r1_ext_address = r1.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
|
||||
r1_rloc = int(r1.get(wpan.WPAN_THREAD_RLOC16), 16)
|
||||
r1_ml_address = r1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
r2_ext_address = r2.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
|
||||
r2_rloc = int(r2.get(wpan.WPAN_THREAD_RLOC16), 16)
|
||||
r2_ml_address = r2.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
|
||||
# Wait for r2 to become router and r1 establishes a link with it
|
||||
|
||||
|
||||
def check_r1_router_table():
|
||||
router_table = wpan.parse_router_table_result(r1.get(wpan.WPAN_THREAD_ROUTER_TABLE))
|
||||
verify(len(router_table) == 2)
|
||||
for entry in router_table:
|
||||
verify(entry.rloc16 == r1_rloc or entry.is_link_established())
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_router_table, WAIT_TIME)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Check that r1 detected both TREL and 15.4 as supported radio by r2
|
||||
|
||||
r1_radios = wpan.parse_list(r1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(r1_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r1_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r1_radios))
|
||||
|
||||
r2_radios = wpan.parse_list(r2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(r2_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r2_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r2_radios))
|
||||
|
||||
|
||||
def check_r1_sees_r2_has_two_radio_links():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
verify(len(r1_neighbor_radios[0].radios) == 2)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_sees_r2_has_two_radio_links, WAIT_TIME)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Send from r1 to r2 and verify that r1 prefers TREL radio link for sending to r2.
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi r2 from r1", 5)
|
||||
recver = r2.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Now disable TREL link on r2 and send again. We expect that r1 would quickly learn that trel is
|
||||
# no longer supported by r2 and prefer 15.4 for tx to r2.
|
||||
|
||||
r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'false')
|
||||
verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'false')
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi again r2 from r1", 5)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
|
||||
|
||||
def check_r1_does_not_prefer_trel_for_r2():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_does_not_prefer_trel_for_r2, WAIT_TIME)
|
||||
|
||||
# Check that we can send between r1 and r2 (now all tx should use 15.4)
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi on 15.4 r2 from r1", 5)
|
||||
recver = r2.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD)
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_IEEE_802_15_4))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_IEEE_802_15_4) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Enable trel back on r2, start sending traffic from r2 to r1.
|
||||
# r2 would use probe mehcnasim to discover that trel is enabled again
|
||||
# r1 should notice new rx on trel and update trel preference for r1
|
||||
|
||||
r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'true')
|
||||
verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'true')
|
||||
|
||||
sender = r2.prepare_tx(r2_ml_address, r1_ml_address, "Probing r1 from r2", 80)
|
||||
recver = r1.prepare_rx(sender)
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
|
||||
def check_r1_again_prefers_trel_for_r2():
|
||||
r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO))
|
||||
verify(len(r1_neighbor_radios) == 1)
|
||||
r2_radio_info = r1_neighbor_radios[0]
|
||||
verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6))
|
||||
verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_again_prefers_trel_for_r2, WAIT_TIME)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import time
|
||||
import wpan
|
||||
from wpan import verify
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: This test covers behavior of MeshHeader messages (message sent over multi-hop) when the
|
||||
# underlying devices (in the path) support different radio types with different frame MTU length.
|
||||
#
|
||||
# r1 --------- r2 ---------- r3
|
||||
# (trel) (15.4+trel) (15.4)
|
||||
# |
|
||||
# |
|
||||
# c3 (15.4)
|
||||
#
|
||||
# c3 is used for quick router promotion of r3.
|
||||
#
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 4
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
r1 = wpan.Node(wpan.NODE_TREL)
|
||||
r2 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
r3 = wpan.Node(wpan.NODE_15_4)
|
||||
c3 = wpan.Node(wpan.NODE_15_4)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
#
|
||||
|
||||
r1.allowlist_node(r2)
|
||||
r2.allowlist_node(r1)
|
||||
|
||||
r2.allowlist_node(r3)
|
||||
r3.allowlist_node(r2)
|
||||
|
||||
r3.allowlist_node(c3)
|
||||
c3.allowlist_node(r3)
|
||||
|
||||
r1.form("mesh-header")
|
||||
|
||||
r2.join_node(r1, wpan.JOIN_TYPE_ROUTER)
|
||||
r3.join_node(r2, wpan.JOIN_TYPE_ROUTER)
|
||||
c3.join_node(r3, wpan.JOIN_TYPE_END_DEVICE)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
WAIT_TIME = 5
|
||||
INVALID_ROUTER_ID = 63
|
||||
MSG_LEN = 1000
|
||||
MSG_COUNT = 7
|
||||
|
||||
# Verify that each node supports the correct radio links.
|
||||
|
||||
r1_radios = wpan.parse_list(r1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(len(r1_radios) == 1 and (wpan.RADIO_LINK_TREL_UDP6 in r1_radios))
|
||||
|
||||
r2_radios = wpan.parse_list(r2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(
|
||||
len(r2_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r2_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r2_radios))
|
||||
|
||||
r3_radios = wpan.parse_list(r3.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS))
|
||||
verify(len(r3_radios) == 1 and (wpan.RADIO_LINK_IEEE_802_15_4 in r3_radios))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Wait for all router entries are updated
|
||||
|
||||
r1_rloc = int(r1.get(wpan.WPAN_THREAD_RLOC16), 16)
|
||||
|
||||
|
||||
def check_r1_router_table():
|
||||
router_table = wpan.parse_router_table_result(r1.get(wpan.WPAN_THREAD_ROUTER_TABLE))
|
||||
verify(len(router_table) == 3)
|
||||
for entry in router_table:
|
||||
verify(entry.rloc16 == r1_rloc or entry.is_link_established() or entry.next_hop != INVALID_ROUTER_ID)
|
||||
|
||||
|
||||
wpan.verify_within(check_r1_router_table, WAIT_TIME)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Send large message from r1 to r3. Such a messag would be sent as a
|
||||
# Mesh Header message. Note that the origin r1 is a trel-only device
|
||||
# whereas the final destination r3 is a 15.4-only device. The originator
|
||||
# should use smaller MTU size (which then fragment the message into
|
||||
# multiple frames) otherwise the 15.4 link won't be able to handle it.
|
||||
|
||||
r1_ml_address = r1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
r3_ml_address = r3.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
|
||||
|
||||
sender = r1.prepare_tx(r1_ml_address, r3_ml_address, MSG_LEN, MSG_COUNT)
|
||||
recver = r3.prepare_rx(sender)
|
||||
|
||||
wpan.Node.perform_async_tx_rx()
|
||||
|
||||
verify(sender.was_successful)
|
||||
verify(recver.was_successful)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from wpan import verify
|
||||
import wpan
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: Test active scan with nodes supporting different radios
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 1
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
n1 = wpan.Node(wpan.NODE_15_4)
|
||||
n2 = wpan.Node(wpan.NODE_TREL)
|
||||
n3 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
s1 = wpan.Node(wpan.NODE_15_4)
|
||||
s2 = wpan.Node(wpan.NODE_TREL)
|
||||
s3 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
|
||||
n1.form("n1", channel='20')
|
||||
n2.form("n2", channel='21')
|
||||
n3.form("n3", channel='22')
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Scan by scanner nodes (no network)
|
||||
|
||||
# Scan by s1 (15.4 only), expect to see n1(15.4) and n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(s1.active_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by s2 (trel only), expect to see n2(trel) and n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(s2.active_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by s3 (trel+15.4), expect to see all nodes
|
||||
result = wpan.parse_scan_result(s3.active_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Scan by the nodes
|
||||
|
||||
# Scan by n1 (15.4 only), expect to see only n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(n1.active_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by n2 (trel only), expect to see only n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(n2.active_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by n3 (15.4+trel), expect to see n1(15.4) and n2(trel)
|
||||
result = wpan.parse_scan_result(n3.active_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(not n3.is_in_scan_result(result))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from wpan import verify
|
||||
import wpan
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: Test MLE discover scan with nodes supporting different radios
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `wpan.Nodes` instances
|
||||
|
||||
speedup = 1
|
||||
wpan.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
n1 = wpan.Node(wpan.NODE_15_4)
|
||||
n2 = wpan.Node(wpan.NODE_TREL)
|
||||
n3 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
s1 = wpan.Node(wpan.NODE_15_4)
|
||||
s2 = wpan.Node(wpan.NODE_TREL)
|
||||
s3 = wpan.Node(wpan.NODE_15_4_TREL)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Init all nodes
|
||||
|
||||
wpan.Node.init_all_nodes()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
|
||||
n1.form("n1", channel='20')
|
||||
n2.form("n2", channel='21')
|
||||
n3.form("n3", channel='22')
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Scan by scanner nodes (no network)
|
||||
|
||||
# Scan by s1 (15.4 only), expect to see n1(15.4) and n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(s1.discover_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by s2 (trel only), expect to see n2(trel) and n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(s2.discover_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by s3 (trel+15.4), expect to see all nodes
|
||||
result = wpan.parse_scan_result(s3.discover_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Scan by the nodes
|
||||
|
||||
# Scan by n1 (15.4 only), expect to see only n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(n1.discover_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by n2 (trel only), expect to see only n3(15.4+trel)
|
||||
result = wpan.parse_scan_result(n2.discover_scan())
|
||||
verify(not n1.is_in_scan_result(result))
|
||||
verify(not n2.is_in_scan_result(result))
|
||||
verify(n3.is_in_scan_result(result))
|
||||
|
||||
# Scan by n3 (15.4+trel), expect to see n1(15.4) and n2(trel)
|
||||
result = wpan.parse_scan_result(n3.discover_scan())
|
||||
verify(n1.is_in_scan_result(result))
|
||||
verify(n2.is_in_scan_result(result))
|
||||
verify(not n3.is_in_scan_result(result))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
wpan.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
+82
-5
@@ -122,6 +122,9 @@ WPAN_OT_MSG_BUFFER_COUNTERS = "OpenThread:MsgBufferCounters"
|
||||
WPAN_OT_MSG_BUFFER_COUNTERS_AS_STRING = "OpenThread:MsgBufferCounters:AsString"
|
||||
WPAN_OT_DEBUG_TEST_ASSERT = "OpenThread:Debug:TestAssert"
|
||||
WPAN_OT_DEBUG_TEST_WATCHDOG = "OpenThread:Debug:TestWatchdog"
|
||||
WPAN_OT_SUPPORTED_RADIO_LINKS = "OpenThread:SupportedRadioLinks"
|
||||
WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO = "OpenThread:NeighborTable::MultiRadioInfo"
|
||||
WPAN_OT_TREL_TEST_MODE_ENABLE = "OpenThread:Trel:TestMode:Enable"
|
||||
|
||||
WPAN_MAC_ALLOWLIST_ENABLED = "MAC:Allowlist:Enabled"
|
||||
WPAN_MAC_ALLOWLIST_ENTRIES = "MAC:Allowlist:Entries"
|
||||
@@ -228,6 +231,13 @@ MCU_POWER_STATE_ON = '"on"'
|
||||
MCU_POWER_STATE_LOW_POWER = '"low-power"'
|
||||
MCU_POWER_STATE_OFF = '"off"'
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Node Radio Link Types (Use as input to `Node()` initializer)
|
||||
|
||||
NODE_15_4 = "-15.4"
|
||||
NODE_TREL = "-trel"
|
||||
NODE_15_4_TREL = "-15.4-trel"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Node types (from `WPAN_NODE_TYPE` property)
|
||||
|
||||
@@ -261,6 +271,13 @@ THREAD_MODE_FLAG_FULL_NETWORK_DATA = (1 << 0)
|
||||
THREAD_MODE_FLAG_FULL_THREAD_DEV = (1 << 1)
|
||||
THREAD_MODE_FLAG_RX_ON_WHEN_IDLE = (1 << 3)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Radio Link type
|
||||
|
||||
RADIO_LINK_IEEE_802_15_4 = "IEEE_802_15_4"
|
||||
RADIO_LINK_TREL_UDP6 = "TREL_UDP6"
|
||||
RADIO_LINK_TOBLE = "TOBLE"
|
||||
|
||||
_OT_BUILDDIR = os.getenv('top_builddir', '../..')
|
||||
_WPANTUND_PREFIX = os.getenv('WPANTUND_PREFIX', '/usr/local')
|
||||
|
||||
@@ -281,7 +298,6 @@ def _log(text, new_line=True, flush=True):
|
||||
|
||||
class Node(object):
|
||||
""" A wpantund OT NCP instance """
|
||||
|
||||
# defines the default verbosity setting (can be changed per `Node`)
|
||||
_VERBOSE = os.getenv('TORANJ_VERBOSE', 'no').lower() in ['true', '1', 't', 'y', 'yes', 'on']
|
||||
_SPEED_UP_FACTOR = 1 # defines the default time speed up factor
|
||||
@@ -312,7 +328,7 @@ class Node(object):
|
||||
_cur_index = _START_INDEX
|
||||
_all_nodes = weakref.WeakSet()
|
||||
|
||||
def __init__(self, verbose=_VERBOSE):
|
||||
def __init__(self, radios=None, verbose=_VERBOSE):
|
||||
"""Creates a new `Node` instance"""
|
||||
|
||||
index = Node._cur_index
|
||||
@@ -330,10 +346,11 @@ class Node(object):
|
||||
self._use_posix_with_rcp = False
|
||||
|
||||
if self._use_posix_with_rcp:
|
||||
ncp_socket_path = 'system:{} -s {} spinel+hdlc+uart://{}?forkpty-arg={}'.format(
|
||||
self._OT_NCP_FTD_POSIX, self._SPEED_UP_FACTOR, self._OT_RCP, index)
|
||||
ncp_socket_path = 'system:{}{} -s {} spinel+hdlc+uart://{}?forkpty-arg={}'.format(
|
||||
self._OT_NCP_FTD_POSIX, '' if radios is None else radios, self._SPEED_UP_FACTOR, self._OT_RCP, index)
|
||||
else:
|
||||
ncp_socket_path = 'system:{} {} {}'.format(self._OT_NCP_FTD, index, self._SPEED_UP_FACTOR)
|
||||
ncp_socket_path = 'system:{}{} {} {}'.format(self._OT_NCP_FTD, '' if radios is None else radios, index,
|
||||
self._SPEED_UP_FACTOR)
|
||||
|
||||
cmd = self._WPANTUND + \
|
||||
' -o Config:NCP:SocketPath \"{}\"'.format(ncp_socket_path) + \
|
||||
@@ -1536,3 +1553,63 @@ class InterfaceRoute(object):
|
||||
def parse_interface_routes_result(interface_routes_list):
|
||||
""" Parses interface routes list string and returns an array of `InterfaceRoute` objects"""
|
||||
return [InterfaceRoute(item) for item in interface_routes_list.split('\n')[1:-1]]
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
class MultiRadioEntry(object):
|
||||
""" This object encapsulates a multi radio info entry"""
|
||||
|
||||
def __init__(self, text):
|
||||
|
||||
# Example of expected text:
|
||||
#
|
||||
# `\t"0EB758375B4976E7, RLOC16:f403, Radios:[IEEE_802_15_4(200), TREL_UDP6(255)]"`
|
||||
#
|
||||
|
||||
# We get rid of the first two chars `\t"' and last char '"', split the rest using whitespace as separator.
|
||||
# Then remove any ',' at end of items in the list.
|
||||
items = [item[:-1] if item[-1] == ',' else item for item in text[2:-1].split()]
|
||||
|
||||
# First item is the extended address
|
||||
self._ext_address = items[0]
|
||||
|
||||
# Second items is 'RLCO16:{rloc}'
|
||||
self._rloc16 = items[1].split(':')[1]
|
||||
|
||||
# Join back rest of items, split using ":" to get list of radios of form "[IEEE_802_15_4(200) TREL_UDP6(255)]"
|
||||
radios = " ".join(items[2:]).split(":")[1]
|
||||
|
||||
if radios != "[]":
|
||||
# Get rid of `[ and `]`, then split using " ", then convert to dictionary mapping radio type
|
||||
# to its preference value.
|
||||
self._radios = {radio.split("(")[0]: radio.split("(")[1][:-1] for radio in radios[1:-1].split(' ')}
|
||||
else:
|
||||
self._radios = {}
|
||||
|
||||
@property
|
||||
def ext_address(self):
|
||||
return self._ext_address
|
||||
|
||||
@property
|
||||
def rloc16(self):
|
||||
return self._rloc16
|
||||
|
||||
@property
|
||||
def radios(self):
|
||||
return self._radios
|
||||
|
||||
def supports(self, radio_type):
|
||||
return radio_type in self._radios
|
||||
|
||||
def preference(self, radio_type):
|
||||
return int(self._radios[radio_type], 0) if self.supports(radio_type) else None
|
||||
|
||||
def __repr__(self):
|
||||
return 'MultiRadioEntry({})'.format(self.__dict__)
|
||||
|
||||
|
||||
def parse_multi_radio_result(multi_radio_list):
|
||||
""" Parses multi radio neighbor list string and returns an array of `MultiRadioEntry` objects"""
|
||||
return [MultiRadioEntry(item) for item in multi_radio_list.split('\n')[1:-1]]
|
||||
|
||||
Reference in New Issue
Block a user