mirror of
https://github.com/espressif/openthread.git
synced 2026-11-06 22:43:09 +00:00
`SocketWithCloseExec()` has no SOCK_NONBLOCK on Apple platforms and passed O_NONBLOCK to fcntl(F_SETFD), which takes descriptor flags only and drops it. Every kSocketNonBlock socket that did not set the flag again by itself was therefore blocking on macOS: the utun control socket, the platform UDP and TCP sockets, the MLD monitor, the infra-if route socket, the BPF forwarder's membership socket and the daemon's listening socket. The Thread routing socket and TREL set it with F_SETFL on their own. Set the file status flag with F_SETFL in the helper, and drop the routing socket's and TREL's own fcntl, which this makes redundant; the routing socket's filter setup is written like infra_if.cpp's CreateRouteSocket(). BSD sockets inherit the listening socket's file status flags on accept(), Linux sockets do not. The daemon's session socket is therefore non-blocking today on FreeBSD and NetBSD, and would become so on macOS, while it is blocking on Linux; output of more than the socket buffer (8 KB on macOS) ahead of ot-ctl then fails with EAGAIN and closes the session. Clear the flag on the accepted socket, as accept(2) asks of portable programs. check-posix-pty verifies with lsof that the daemon's listening socket is non-blocking and its session socket is not.
499 lines
19 KiB
Bash
Executable File
499 lines
19 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2018, 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.
|
|
#
|
|
|
|
set -e
|
|
set -x
|
|
|
|
die()
|
|
{
|
|
echo " *** ERROR: " "$*"
|
|
exit 1
|
|
}
|
|
|
|
at_exit()
|
|
{
|
|
EXIT_CODE=$?
|
|
|
|
sudo killall expect || true
|
|
sudo killall ot-ctl || true
|
|
sudo killall ot-daemon || true
|
|
sudo killall ot-cli || true
|
|
sudo killall ot-rcp || true
|
|
sudo killall socat || true
|
|
|
|
# The daemon's output no longer streams through tee; show it when the check failed.
|
|
if [[ ${EXIT_CODE} != 0 && -f ${OT_DAEMON_OUTPUT:-} ]]; then
|
|
cat "${OT_DAEMON_OUTPUT}"
|
|
fi
|
|
|
|
exit $EXIT_CODE
|
|
}
|
|
|
|
wait_for_leader()
|
|
{
|
|
if grep -q leader "$OT_OUTPUT"; then
|
|
return 0
|
|
else
|
|
echo 'Still waiting for leader'
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
timeout_run()
|
|
{
|
|
local count="$1"
|
|
local exit_code
|
|
shift 1
|
|
|
|
while [[ $count != 0 && $exit_code != 0 ]]; do
|
|
count=$((count - 1))
|
|
"$@" && return 0 || exit_code=$?
|
|
sleep 1
|
|
done
|
|
|
|
return $exit_code
|
|
}
|
|
|
|
do_build()
|
|
{
|
|
./script/cmake-build simulation
|
|
# OMR prefixes are installed as kernel routes (which needs border routing for otNetDataContainsOmrPrefix), so that
|
|
# the daemon's route handling is exercised.
|
|
./script/cmake-build posix -DOT_PLATFORM_NETIF=1 -DOT_PLATFORM_UDP=1 -DOT_UDP_FORWARD=0 -DOT_POSIX_MAX_POWER_TABLE=1 -DOT_POSIX_INSTALL_OMR_ROUTES=ON -DOT_BORDER_ROUTING=ON -DOT_DAEMON="${OT_DAEMON}" -DOT_READLINE="${OT_READLINE}"
|
|
}
|
|
|
|
# The netif joins ff02::1 on the Thread interface when it comes up and leaves it when it
|
|
# goes down; both must reach the kernel. On macOS the join used to fail with EINVAL on a
|
|
# never-used utun (IPv6 is attached to a tun by its first address, which the stack adds
|
|
# after this join) and the failure was tolerated with a warning. The ot-daemon log is checked
|
|
# rather than a kernel-side group listing, which could not tell the daemon's own socket
|
|
# membership apart from one the kernel holds on its own.
|
|
check_daemon_multicast_group()
|
|
{
|
|
local action="$1"
|
|
|
|
[[ ${OT_DAEMON} == 'on' ]] || return 0
|
|
|
|
grep -q -E "${action} multicast address ff02::1([^0-9a-f:]|$)" "${OT_DAEMON_OUTPUT}" || die "ff02::1 not ${action}"
|
|
if grep -q -E 'IPV6_(JOIN|LEAVE)_GROUP failure' "${OT_DAEMON_OUTPUT}"; then
|
|
die 'multicast group failure in the ot-daemon log'
|
|
fi
|
|
}
|
|
|
|
# Taking the Thread interface down makes OpenThread leave its multicast groups, which
|
|
# ot-daemon treats as fatal when it fails. Verify that ot-daemon survives it.
|
|
check_daemon_netif_down()
|
|
{
|
|
local status
|
|
|
|
[[ ${OT_DAEMON} == 'on' ]] || return 0
|
|
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" ifconfig down || true
|
|
sleep 1
|
|
|
|
# OT_DAEMON_JOB is sudo (or the sudo function of script/_maybe_isolate), which
|
|
# lives as long as ot-daemon and exits with its status.
|
|
if ! ps -p "${OT_DAEMON_JOB}" >/dev/null; then
|
|
wait "${OT_DAEMON_JOB}" && status=0 || status=$?
|
|
die "ot-daemon exited with status ${status} on ifconfig down"
|
|
fi
|
|
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" ifconfig | grep 'down' || die 'ot-daemon does not respond after ifconfig down'
|
|
|
|
check_daemon_multicast_group Removed
|
|
}
|
|
|
|
# Lists a route to the prefix through the Thread interface. On Linux only the daemon's (proto boot) counts, since the
|
|
# kernel adds one of its own (proto kernel) for the interface's address once the address is deprecated.
|
|
kernel_route_known()
|
|
{
|
|
if [[ ${OSTYPE} == "linux-gnu"* ]]; then
|
|
ip -6 route show "$1" dev "${NETIF_NAME}" proto boot | grep .
|
|
else
|
|
netstat -rn -f inet6 | grep -F "$1" | grep -w "${NETIF_NAME}"
|
|
fi
|
|
}
|
|
|
|
# Runs an ot-ctl command on the daemon and succeeds when it answers Done. The output is collected first, so that a
|
|
# grep -q cannot end ot-ctl before it has read the daemon's whole reply.
|
|
ot_ctl_done()
|
|
{
|
|
local output
|
|
|
|
output=$("${OT_CTL[@]}" -I "${NETIF_NAME}" "$@") || return 1
|
|
grep -q Done <<<"${output}"
|
|
}
|
|
|
|
# Passes when the route listing fails too, so it must follow a kernel_route_known that passed.
|
|
kernel_route_gone()
|
|
{
|
|
! kernel_route_known "$1"
|
|
}
|
|
|
|
check_daemon_omr_route()
|
|
{
|
|
local omr_prefix=fd00:dead:beef::/64
|
|
# OpenThread prints every group within the prefix length, zero groups included.
|
|
local logged_prefix=fd00:dead:beef:0::/64
|
|
|
|
[[ ${OT_DAEMON} == 'on' ]] || return 0
|
|
|
|
# An OMR prefix in the network data becomes a kernel route through the Thread interface, and goes with the prefix.
|
|
# The kernel installs a prefix route of its own for the address the daemon configures from the prefix (XNU cannot
|
|
# be told not to), so the table alone does not prove the daemon's work: its log must show the route. The daemon
|
|
# logs critical lines only until told otherwise, and the route is reported at the info level.
|
|
ot_ctl_done log level 4 || die 'log level failed'
|
|
ot_ctl_done prefix add "${omr_prefix}" paos || die 'prefix add failed'
|
|
ot_ctl_done netdata register || die 'netdata register failed'
|
|
timeout_run 10 kernel_route_known "${omr_prefix}" || die 'the OMR prefix was not installed as a route through the Thread interface'
|
|
timeout_run 10 grep -qE "(Successfully added|Failed to add) an OMR route ${logged_prefix} in kernel" "${OT_DAEMON_OUTPUT}" \
|
|
|| die 'the daemon did not report the route of the OMR prefix'
|
|
grep -qF "Successfully added an OMR route ${logged_prefix} in kernel" "${OT_DAEMON_OUTPUT}" \
|
|
|| die 'the daemon failed to install the route of the OMR prefix'
|
|
|
|
ot_ctl_done prefix remove "${omr_prefix}" || die 'prefix remove failed'
|
|
ot_ctl_done netdata register || die 'netdata register failed'
|
|
timeout_run 10 kernel_route_gone "${omr_prefix}" || die 'the route of the removed OMR prefix is still installed'
|
|
timeout_run 10 grep -qE "(Successfully deleted|Failed to delete) an OMR route ${logged_prefix} in kernel" "${OT_DAEMON_OUTPUT}" \
|
|
|| die 'the daemon did not report the removal of the route of the OMR prefix'
|
|
grep -qF "Successfully deleted an OMR route ${logged_prefix} in kernel" "${OT_DAEMON_OUTPUT}" \
|
|
|| die 'the daemon failed to delete the route of the OMR prefix'
|
|
}
|
|
|
|
set_host_address()
|
|
{
|
|
if [[ ${OSTYPE} == darwin* ]]; then
|
|
sudo ifconfig "${NETIF_NAME}" inet6 "$2" prefixlen 64 "$([[ $1 == add ]] && echo alias || echo -alias)"
|
|
else
|
|
sudo ip -6 addr "$1" "$2/64" dev "${NETIF_NAME}"
|
|
fi
|
|
}
|
|
|
|
check_daemon_address_events()
|
|
{
|
|
local address='fd00:1234:5678::1'
|
|
# ot-ctl prints every address as eight groups, without "::"; `ipaddr -v` adds the origin, the prefix
|
|
# length taken from the trimmed netmask and the flags the address was added with.
|
|
local listed='fd00:1234:5678:0:0:0:0:1'
|
|
local listed_verbose="${listed} origin:manual plen:64 preferred:1 valid:1"
|
|
|
|
[[ ${OT_DAEMON} == 'on' ]] || return 0
|
|
|
|
# The routing socket (netlink on Linux) reports every address and multicast membership of the
|
|
# interface to the daemon, its own included, and the daemon logs each report at info level.
|
|
grep -q 'ADD \[U\] ' "${OT_DAEMON_OUTPUT}" || die "the reports of OpenThread's own addresses did not reach ot-daemon"
|
|
grep -q 'ADD \[M\] ' "${OT_DAEMON_OUTPUT}" || die "the reports of the interface's multicast memberships did not reach ot-daemon"
|
|
|
|
# An address the host adds becomes an address of OpenThread and goes with its removal.
|
|
set_host_address add "${address}"
|
|
timeout_run 10 host_address_known "${listed_verbose}" || die 'an address added on the host did not reach OpenThread'
|
|
|
|
set_host_address del "${address}"
|
|
timeout_run 10 host_address_gone "${listed}" || die 'an address removed on the host is still known to OpenThread'
|
|
}
|
|
|
|
# The CLI ends its lines with CR LF; the CR goes before the whole-line match.
|
|
host_address_known()
|
|
{
|
|
local addresses
|
|
|
|
addresses=$("${OT_CTL[@]}" -I "${NETIF_NAME}" ipaddr -v) || return 1
|
|
grep -Fx "$1" <<<"${addresses//$'\r'/}" >/dev/null
|
|
}
|
|
|
|
host_address_gone()
|
|
{
|
|
local addresses
|
|
|
|
addresses=$("${OT_CTL[@]}" -I "${NETIF_NAME}" ipaddr) || return 1
|
|
! grep -Fx "$1" <<<"${addresses//$'\r'/}" >/dev/null
|
|
}
|
|
|
|
check_daemon_socket_flags()
|
|
{
|
|
local fifo="$PWD/tmp/ot-ctl-input"
|
|
local sockets
|
|
|
|
# ot-ctl connects before it reads its input; the session stays open until it reads "exit".
|
|
mkfifo "${fifo}"
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" <"${fifo}" &
|
|
exec 3>"${fifo}"
|
|
|
|
# lsof prints the file status flags of each descriptor with +fg: NB for O_NONBLOCK, or ND
|
|
# where that is the same flag as O_NDELAY (Linux). Two descriptors of ot-daemon carry the
|
|
# socket path: the listening socket, which is non-blocking, and the session it accepted,
|
|
# which is served blocking on every platform (on BSD it inherits the flag from the listening
|
|
# socket until the daemon clears it).
|
|
for _ in $(seq 1 10); do
|
|
sockets=$(sudo lsof +fg -U -a -c ot-daemon | grep "openthread-${NETIF_NAME}.sock" || true)
|
|
[[ $(echo "${sockets}" | grep -c .) == 2 ]] && break
|
|
sleep 1
|
|
done
|
|
echo "${sockets}"
|
|
|
|
echo exit >&3 || true
|
|
exec 3>&-
|
|
wait $! || die 'ot-ctl did not exit cleanly'
|
|
rm -f "${fifo}"
|
|
|
|
# lsof lists the descriptors in order; the listening socket was opened first.
|
|
[[ $(echo "${sockets}" | grep -c .) == 2 ]] || die 'ot-daemon does not hold a listening and a session socket'
|
|
echo "${sockets}" | sed -n '1p' | grep -qwE 'NB|ND' || die 'the listening socket must be non-blocking'
|
|
! echo "${sockets}" | sed -n '2p' | grep -qwE 'NB|ND' || die 'the session socket must be blocking'
|
|
}
|
|
|
|
do_check()
|
|
{
|
|
trap at_exit INT TERM EXIT
|
|
|
|
sudo rm -rf tmp
|
|
mkdir tmp
|
|
|
|
SOCAT_PTY="$PWD/tmp/ot-rcp-pty"
|
|
OT_OUTPUT="$PWD/tmp/ot-output"
|
|
OT_DAEMON_OUTPUT="$PWD/tmp/ot-daemon-output"
|
|
RADIO_NCP_PATH="$PWD/build/simulation/examples/apps/ncp/ot-rcp"
|
|
|
|
socat pty,raw,echo=0,link="${SOCAT_PTY}" exec:"${RADIO_NCP_PATH} 1" &
|
|
timeout_run 10 test -c "${SOCAT_PTY}"
|
|
echo 'SOCAT_PTY' "${SOCAT_PTY}"
|
|
|
|
# Cover setting a valid network interface name. On macOS only a utun number can be chosen.
|
|
if [[ ${OSTYPE} == darwin* ]]; then
|
|
VALID_NETIF_NAME="utun$((200 + 10#$(date +%S)))"
|
|
else
|
|
VALID_NETIF_NAME="wan$(date +%H%M%S)"
|
|
fi
|
|
readonly VALID_NETIF_NAME
|
|
|
|
RADIO_URL="spinel+hdlc+uart://${SOCAT_PTY}?region=US&max-power-table-mbm=1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300,2400,2500,2600"
|
|
|
|
if [[ ${OT_DAEMON} == 'on' ]]; then
|
|
# The log file is in our own tmp directory, so the redirect does not need sudo.
|
|
# shellcheck disable=SC2024
|
|
sudo -E "$PWD/build/posix/src/posix/ot-daemon" -d5 -v -I "${VALID_NETIF_NAME}" "${RADIO_URL}" >"${OT_DAEMON_OUTPUT}" 2>&1 &
|
|
OT_DAEMON_JOB=$!
|
|
sleep 3
|
|
NETIF_NAME=$(grep -o 'Thread interface: .\+' "${OT_DAEMON_OUTPUT}" | cut -d: -f2 | tr -d ' \r\n')
|
|
[[ ${NETIF_NAME} == "${VALID_NETIF_NAME}" ]] || die "ot-daemon created ${NETIF_NAME}, not the requested ${VALID_NETIF_NAME}"
|
|
OT_CTL_PATH="$PWD/build/posix/src/posix/ot-ctl"
|
|
if [[ ${OT_DAEMON_ALLOW_ALL} == 1 ]] || [[ -n ${OT_ISOLATED_REEXEC:-} ]]; then
|
|
OT_CTL=("${OT_CTL_PATH}")
|
|
else
|
|
OT_CTL=(sudo "${OT_CTL_PATH}")
|
|
fi
|
|
# -d5 asks for debug logging; the daemon's output must carry OpenThread's own log lines, not only the
|
|
# syslog() lines of its startup.
|
|
timeout_run 10 grep -qE '\[(D|I)\] ' "${OT_DAEMON_OUTPUT}" || die 'the daemon does not log at the level -d asked for'
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl'
|
|
|
|
# verify supports options in OpenThread commands without separator --
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" pskc -p 123456 | grep 'Done' || die 'unable to set pskc'
|
|
|
|
# verify this reset and factoryreset end immediately
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" reset
|
|
# sleep a while for daemon ready
|
|
sleep 2
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" factoryreset
|
|
# sleep a while for daemon ready
|
|
sleep 2
|
|
|
|
OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH=640
|
|
readonly OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
|
|
local -r kMaxStringLength="$((OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH - 1))"
|
|
|
|
# verify success if command length doesn't exceed the limit
|
|
for len in $(seq 1 ${kMaxStringLength}); do
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" "$(printf '1%.0s' $(seq 1 "${len}"))"
|
|
done
|
|
|
|
# verify failure if command length exceeds the limit
|
|
len=${OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH}
|
|
if "${OT_CTL[@]}" -I "${NETIF_NAME}" "$(printf '1%.0s' $(seq 1 "${len}"))"; then
|
|
die
|
|
fi
|
|
|
|
# check_daemon_multicast_group reads INFO lines of the netif; -d5 above gives them along
|
|
# with everything at DEBG, so settle on INFO for the rest of the run.
|
|
"${OT_CTL[@]}" -I "${NETIF_NAME}" log level 4 | grep 'Done' || die 'failed to set log level'
|
|
check_daemon_socket_flags
|
|
OT_CLI_CMD="${OT_CTL[*]} -I ${NETIF_NAME}"
|
|
else
|
|
OT_CLI="$PWD/build/posix/src/posix/ot-cli"
|
|
sudo "${OT_CLI}" -I "${VALID_NETIF_NAME}" -n "${RADIO_URL}"
|
|
|
|
# Cover setting a too long(max is 15 characters) network interface name.
|
|
# Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS).
|
|
INVALID_NETIF_NAME="wan0123456789123"
|
|
readonly INVALID_NETIF_NAME
|
|
sudo "${OT_CLI}" -I "${INVALID_NETIF_NAME}" -n "${RADIO_URL}" || test $? = 2
|
|
|
|
if [[ ${OSTYPE} == darwin* ]]; then
|
|
# A utun name needs a number. The check runs when the interface is created, after a dry run ends,
|
|
# so no -n here; the CLI exits with 2 (OT_EXIT_INVALID_ARGUMENTS) before it would block.
|
|
sudo "${OT_CLI}" -I utunabc "${RADIO_URL}" || test $? = 2
|
|
fi
|
|
|
|
OT_CLI_CMD="$PWD/build/posix/src/posix/ot-cli ${RADIO_URL}"
|
|
fi
|
|
|
|
sudo expect <<EOF | tee "${OT_OUTPUT}" &
|
|
spawn ${OT_CLI_CMD}
|
|
expect_after {
|
|
timeout { error }
|
|
}
|
|
send "region\r\n"
|
|
expect "US"
|
|
expect "Done"
|
|
send "dataset init new\r\n"
|
|
expect "Done"
|
|
send "dataset commit active\r\n"
|
|
expect "Done"
|
|
send "routerselectionjitter 1\r\n"
|
|
expect "Done"
|
|
send "ifconfig up\r\n"
|
|
expect "Done"
|
|
send "thread start\r\n"
|
|
expect "Done"
|
|
sleep 10
|
|
send "state\r\n"
|
|
expect "leader"
|
|
expect "Done"
|
|
send "extaddr\r\n"
|
|
expect "Done"
|
|
send "dataset active\r\n"
|
|
expect "Done"
|
|
send "ipaddr\r\n"
|
|
expect "Done"
|
|
send "coex\r\n"
|
|
expect "Done"
|
|
send "coap start\r\n"
|
|
expect "Done"
|
|
send "coap resource TestResource\r\n"
|
|
expect "Done"
|
|
send "coap set TestContent\r\n"
|
|
expect "Done"
|
|
set timeout -1
|
|
expect eof
|
|
EOF
|
|
|
|
sleep 5
|
|
|
|
# wait until the node becomes leader
|
|
timeout_run 10 wait_for_leader
|
|
|
|
# wait coap service start
|
|
sleep 5
|
|
|
|
sudo lsof -iUDP:5683 -nP || die 'Application CoAP port is not available!'
|
|
|
|
extaddr=$(grep -ao -A +1 'extaddr' "$OT_OUTPUT" | tail -n1 | tr -d '\r\n\0')
|
|
echo "Extended address is: ${extaddr}"
|
|
|
|
prefix=$(grep -ao 'Mesh Local Prefix: [0-9a-f:]\+' "$OT_OUTPUT" | cut -d: -f2- | tr -d ' \r\n')
|
|
LEADER_ALOC="${prefix}ff:fe00:fc00"
|
|
|
|
if [[ ${OT_DAEMON} == 'on' ]]; then
|
|
# ot-daemon serves one session at a time and the interactive ot-ctl of the expect
|
|
# session reconnects whenever it is displaced, so end it before using ot-ctl below.
|
|
sudo killall -9 expect || true
|
|
sudo killall -9 ot-ctl || true
|
|
fi
|
|
|
|
check_daemon_multicast_group Added
|
|
check_daemon_address_events
|
|
|
|
# A group an application joins on the host becomes a membership of OpenThread and goes with the leave
|
|
# (netlink on Linux, RTM_NEWMADDR/RTM_DELMADDR on BSD).
|
|
if [[ ${OT_DAEMON} == 'on' ]]; then
|
|
NETIF_INDEX=$(python3 -c 'import socket, sys; print(socket.if_nametoindex(sys.argv[1]))' "${NETIF_NAME}")
|
|
sudo env PATH="$(dirname "${OT_CTL_PATH}"):${PATH}" \
|
|
python3 "$PWD/tests/scripts/misc/test_multicast_join.py" "${NETIF_INDEX}" "${NETIF_NAME}" \
|
|
|| die 'multicast group join failed'
|
|
fi
|
|
|
|
# skip testing CoAP for https://github.com/openthread/openthread/issues/6363
|
|
if [[ $OSTYPE != "linux-gnu"* ]]; then
|
|
check_daemon_omr_route
|
|
check_daemon_netif_down
|
|
return 0
|
|
fi
|
|
|
|
# Retrievie test resource through application CoAP
|
|
coap_response=$(coap-client -B 5 -m GET "coap://[${LEADER_ALOC}]:5683/TestResource")
|
|
echo "CoAP response is: ${coap_response}"
|
|
|
|
# Verify CoAP response contains the test content
|
|
if [[ ${coap_response} == *TestContent* ]]; then
|
|
echo 'Success'
|
|
else
|
|
die 'Failed to access application CoAP'
|
|
fi
|
|
|
|
# Retrievie extended address through network diagnostic get
|
|
coap_response=$(echo -n '120100' | xxd -r -p | coap-client -B 5 -m POST "coap://[${LEADER_ALOC}]:61631/d/dg" -f-)
|
|
|
|
# Verify Tmf CoAP is blocked
|
|
if [[ -z ${coap_response} ]]; then
|
|
die 'Tmf is not blocked'
|
|
fi
|
|
|
|
check_daemon_omr_route
|
|
check_daemon_netif_down
|
|
}
|
|
|
|
main()
|
|
{
|
|
if [[ $# == 0 ]]; then
|
|
do_build
|
|
do_check
|
|
return 0
|
|
fi
|
|
|
|
while [[ $# != 0 ]]; do
|
|
case $1 in
|
|
build)
|
|
do_build
|
|
;;
|
|
check)
|
|
# shellcheck source=script/_maybe_isolate
|
|
source script/_maybe_isolate
|
|
do_check
|
|
;;
|
|
*)
|
|
echo "Unknown action: $1"
|
|
return 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
main "$@"
|