Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 284 additions & 0 deletions tests/scripts/expect/dind_srp_tc_6.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2026, 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.
#

source "tests/scripts/expect/_common.exp"


set pty1 [create_socat_tcp 1 9000]
set container "otbr-test-container"
set dataset "0e080000000000010000000300001435060004001fffe002087d61eb42cdc48d6a0708fd0d07fca1b9f0500510ba088fc2bd6c3b3897f7a10f58263ff3030f4f70656e5468726561642d353234660102524f04109dc023ccd447b12b50997ef68020f19e0c0402a0f7f8"

# Step 1: BR_1 (DUT) Enable: switch on.
send_user "Starting OTBR Docker container (BR_1 / DUT)...\n"
start_otbr_docker_dind $container $::env(EXP_OT_RCP_PATH) 2 $pty1

# Wait for otbr-agent to create the domain socket
set socket_ready false
for {set i 0} {$i < 10} {incr i} {
if {![catch {exec docker exec -i $container ot-ctl state}]} {
set socket_ready true
break
}
sleep 2
}
if {!$socket_ready} {
fail "ot-ctl failed to communicate with otbr-agent"
}

# Step 2: Eth_1, ED_1 Enable
# Setup active dataset on OTBR and start Thread
exec docker exec -i $container ot-ctl thread stop
exec docker exec -i $container ot-ctl ifconfig down
exec docker exec -i $container ot-ctl dataset set active ${dataset}
exec docker exec -i $container ot-ctl ifconfig up
exec docker exec -i $container ot-ctl thread start

# Wait for OTBR to become leader
set leader false
for {set i 0} {$i < 20} {incr i} {
if {![catch {exec docker exec -i $container ot-ctl state} state] && [string match "*leader*" $state]} {
set leader true
break
}
sleep 2
}
if {!$leader} {
fail "OTBR did not become leader"
}

# Enable SRP server explicitly
exec docker exec -i $container ot-ctl srp server auto disable
exec docker exec -i $container ot-ctl srp server enable
sleep 2

# Wait 15 seconds for the dynamic OMR prefix to fully stabilize
send_user "Waiting 15 seconds for the dynamic OMR prefix to stabilize...\n"
sleep 15

# Step 3: BR_1 (DUT) Automatically adds SRP Server info and configures OMR prefix
send_user "Step 3: Verifying SRP Server information and ULA OMR prefix in Network Data...\n"
set netdata [exec docker exec -i $container ot-ctl netdata show]
check_string_contains $netdata "44970 5d"
check_string_contains $netdata "fd"

# Get the running Border Router's active dataset dynamically to configure clients
set active_dataset [exec docker exec -i $container ot-ctl dataset active -x]
set active_dataset [string trim $active_dataset]

# Enable ED_1 (Node 4)
spawn_node 4 cli $::env(EXP_OT_CLI_PATH)
send "dataset set active $active_dataset\r\n"
expect_line "Done"
send "mode rdn\r\n"
expect_line "Done"
send "routereligible disable\r\n"
expect_line "Done"
send "ifconfig up\r\n"
expect_line "Done"
send "thread start\r\n"
expect_line "Done"
wait_for "state" "child"
expect_line "Done"

set omr_addr_1 [get_omr_addr]
Comment thread
jwhui marked this conversation as resolved.
expect_line "Done"
set mleid_1 [get_ipaddr mleid]
send_user "ED_1 ML-EID Address: $mleid_1\n"
send_user "ED_1 OMR Address: $omr_addr_1\n"
sleep 1

# Set up test-client container to verify from adjacent infrastructure link (Eth_1)
set test_client "test-client"
track_container $test_client
exec docker run -d \
--name $test_client \
--network infrastructure-link \
--cap-add=NET_ADMIN \
--privileged \
--sysctl net.ipv6.conf.all.disable_ipv6=0 \
--entrypoint /bin/bash \
$::env(EXP_TEST_CLIENT_IMAGE) \
-c "echo 0 > /proc/sys/net/ipv6/conf/all/autoconf && echo 0 > /proc/sys/net/ipv6/conf/eth0/autoconf && echo 2 > /proc/sys/net/ipv6/conf/all/accept_ra && echo 2 > /proc/sys/net/ipv6/conf/eth0/accept_ra && sleep infinity"

# Configure routes on test client
set has_rio [expr {[catch {exec docker exec -i $test_client test -e /proc/sys/net/ipv6/conf/all/accept_ra_rt_info_max_plen}] == 0}]
if {$has_rio} {
exec docker exec -i $test_client sysctl -w net.ipv6.conf.all.accept_ra_rt_info_max_plen=64
exec docker exec -i $test_client sysctl -w net.ipv6.conf.eth0.accept_ra_rt_info_max_plen=64
exec docker exec -i $test_client rdisc6 eth0
} else {
set format {{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}}
set otbr_ip [string trim [exec docker inspect $container -f $format]]
exec docker exec -i $test_client ip -6 route add fc00::/7 via $otbr_ip dev eth0
}
sleep 2

# Retrieve Border Router's RLOC or ML-EID address to use as DNS server on ED_1
set otbr_addrs [exec docker exec -i $container ot-ctl ipaddr]
set otbr_dns_addr ""
foreach addr [split $otbr_addrs "\n"] {
set addr [string trim $addr]
if {[string match -nocase "*:ff:fe00:fc00" $addr]} {
set otbr_dns_addr $addr
break
}
}
if {$otbr_dns_addr eq ""} {
set otbr_dns_addr [string trim [lindex [split $otbr_addrs "\n"] 0]]
}
send_user "OTBR DNS Server Address: $otbr_dns_addr\n"

# Step 4: ED_1 sends SRP Update without name compression
send_user "Step 4: ED_1 sending SRP Update without name compression...\n"
switch_node 4
send "dns compression disable\r\n"
expect_line "Done"
send "srp client leaseinterval 1200\r\n"
expect_line "Done"
send "srp client keyleaseinterval 1200\r\n"
expect_line "Done"
send "srp client host name host-test-1\r\n"
expect_line "Done"
send "srp client host address $omr_addr_1\r\n"
expect_line "Done"
send "srp client service add service-test-1 _thread-test._udp 55555\r\n"
expect_line "Done"
send "srp client autostart enable\r\n"
expect_line "Done"

# Step 5: BR_1 (DUT) sends success SRP Update Response
send_user "Step 5: Verifying SRP registration success (RCODE=0)...\n"
wait_for "srp client host state" "Registered"
expect_line "Done"
send_user "SRP registration without name compression successful.\n"

# Step 6-7: ED_1 unicast DNS QType=PTR query to DUT
send_user "Step 6-7: Verifying unicast DNS query from ED_1...\n"
send "dns config $otbr_dns_addr\r\n"
expect_line "Done"
send "dns browse _thread-test._udp.default.service.arpa.\r\n"
set timeout 30
set found_ptr 0
expect {
-re "service-test-1" {
set found_ptr 1
exp_continue
}
-re "Done" {
# Succeeded
}
timeout {
fail "Unicast DNS PTR query timed out"
}
}
if {!$found_ptr} {
fail "Unicast DNS PTR query response missing 'service-test-1'"
}
send_user "Unicast DNS PTR query successful.\n"

# Step 8-9 & 9b: Eth_1 sends mDNS QType=PTR and SRV queries
send_user "Step 8-9 & 9b: Verifying mDNS resolution from Eth_1 (test-client) on AIL...\n"
set py_mdns_check {import time
from zeroconf import Zeroconf, IPVersion

zc = Zeroconf(ip_version=IPVersion.V6Only)
for _ in range(10):
info = zc.get_service_info('_thread-test._udp.local.', 'service-test-1._thread-test._udp.local.', 2000)
if info and info.port is not None and info.server is not None:
print(f'SRV:{info.port},{info.server}')
break
time.sleep(1)
else:
print('SRV:None')
zc.close()
}

set mdns_res [exec docker exec -i $test_client python3 -c $py_mdns_check]
set mdns_res [string trim $mdns_res]
send_user "mDNS Check Result:\n$mdns_res\n"

if {![string match "*SRV:55555,host-test-1.local.*" $mdns_res]} {
fail "mDNS SRV resolution incorrect or missing"
}
send_user "mDNS PTR and SRV resolution verified successfully.\n"

# Step 10: Repeat Steps 4 through 9b with name compression enabled
send_user "Step 10: Repeating Steps 4 through 9b with name compression enabled...\n"
switch_node 4
send "srp client service remove service-test-1 _thread-test._udp\r\n"
expect_line "Done"
sleep 2

send "dns compression enable\r\n"
expect_line "Done"
send "srp client service add service-test-1 _thread-test._udp 55555\r\n"
expect_line "Done"

# Verify SRP Update Response (Step 5 equivalent)
send_user "Verifying SRP registration success with name compression (RCODE=0)...\n"
wait_for "srp client host state" "Registered"
expect_line "Done"
send_user "SRP registration with name compression successful.\n"

# Repeat Step 6-7 (Unicast DNS query)
send_user "Repeating unicast DNS PTR query...\n"
send "dns browse _thread-test._udp.default.service.arpa.\r\n"
set timeout 30
set found_ptr 0
expect {
-re "service-test-1" {
set found_ptr 1
exp_continue
}
-re "Done" {
# Succeeded
}
timeout {
fail "Unicast DNS PTR query timed out"
}
}
if {!$found_ptr} {
fail "Unicast DNS PTR query response missing 'service-test-1'"
}

# Repeat Step 8-9 & 9b (mDNS query)
send_user "Repeating mDNS check...\n"
set mdns_res2 [exec docker exec -i $test_client python3 -c $py_mdns_check]
set mdns_res2 [string trim $mdns_res2]
send_user "mDNS Check 2 Result:\n$mdns_res2\n"

if {![string match "*SRV:55555,host-test-1.local.*" $mdns_res2]} {
fail "mDNS SRV resolution 2 incorrect or missing"
}
send_user "mDNS PTR and SRV resolution 2 verified successfully.\n"

# Cleanup
dispose_all
send_user "# Name Compression (1_3_SRP_TC_6) integration test completed successfully!\n"
exit 0
3 changes: 3 additions & 0 deletions tests/scripts/test_dind_dns_sd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ test_run()
echo "--- Running SRP KEY Record Inclusion/Omission (1_3_SRP_TC_5) integration test ---"
expect -df "${SCRIPT_DIR}/expect/dind_srp_tc_5.exp"

echo "--- Running SRP Name Compression (1_3_SRP_TC_6) integration test ---"
expect -df "${SCRIPT_DIR}/expect/dind_srp_tc_6.exp"

echo "--- Running TREL integration test ---"
expect -df "${SCRIPT_DIR}/expect/dind_trel.exp"

Expand Down
Loading