2929
3030source "tests/scripts/expect/_common.exp"
3131
32+ proc start_radvd {server} {
33+ exec docker exec -d $server bash -c "radvd -C /etc/radvd.conf -u root -n -m stderr >/var/log/radvd.log 2>&1"
34+ sleep 1
35+ if {[catch {exec docker exec -i $server pgrep radvd} radvd_pid]} {
36+ if {![catch {exec docker exec -i $server cat /var/log/radvd.log} radvd_log]} {
37+ send_user "\n=== radvd.log ===\n$radvd_log\n=== end of radvd.log ===\n"
38+ }
39+ fail "Failed to start radvd on $server: $radvd_pid"
40+ }
41+ send_user "radvd started on $server with PID: [string trim $radvd_pid]\n"
42+ }
43+
44+
3245set pty1 [create_socat_tcp 1 9000]
3346set container "otbr-test-container"
3447set eth2_server "eth2-server"
@@ -52,11 +65,12 @@ exec docker run -d \
5265# Wait for eth2-server eth0 to be ready
5366sleep 2
5467
55- # Add 2002:1234::1234 IP to loopback of eth2-server
68+ # Add 2002:1234::1234 IP to loopback and 2001:db8:1::1 to eth0 of eth2-server
5669exec docker exec -i $eth2_server ip -6 addr add 2002:1234::1234/128 dev lo
70+ exec docker exec -i $eth2_server ip -6 addr add 2001:db8:1::1/64 dev eth0
5771
5872# Configure and start Kea DHCPv6 PD server on eth2-server (delegating 2005:1234:abcd:0::/56)
59- set kea_conf {{"Dhcp6": {"interfaces-config": {"interfaces": ["eth0"]}, "lease-database": {"type": "memfile", "persist": true, "name": "/var/lib/kea/kea-leases6.csv"}, "preferred-lifetime": 54000, "valid-lifetime": 86400, "subnet6": [{"subnet": "fd00 :db8:1::/64", "interface": "eth0", "pd-pools": [{"prefix": "2005:1234:abcd:0::", "prefix-len": 56, "delegated-len": 64}], "rapid-commit": true}], "loggers": [{"name": "kea-dhcp6", "output_options": [{"output": "stdout"}], "severity": "DEBUG", "debuglevel": 99}]}}}
73+ set kea_conf {{"Dhcp6": {"interfaces-config": {"interfaces": ["eth0"]}, "lease-database": {"type": "memfile", "persist": true, "name": "/var/lib/kea/kea-leases6.csv"}, "preferred-lifetime": 54000, "valid-lifetime": 86400, "subnet6": [{"subnet": "2001 :db8:1::/64", "interface": "eth0", "pd-pools": [{"prefix": "2005:1234:abcd:0::", "prefix-len": 56, "delegated-len": 64}], "rapid-commit": true}], "loggers": [{"name": "kea-dhcp6", "output_options": [{"output": "stdout"}], "severity": "DEBUG", "debuglevel": 99}]}}}
6074exec docker exec -i $eth2_server bash -c "echo '$kea_conf' > /etc/kea/kea-dhcp6.conf"
6175exec docker exec -i $eth2_server mkdir -p /var/lib/kea /var/run/kea
6276exec docker exec -d $eth2_server /usr/sbin/kea-dhcp6 -c /etc/kea/kea-dhcp6.conf
@@ -70,16 +84,7 @@ exec docker exec -i $eth2_server sysctl -w net.ipv6.conf.eth0.forwarding=1
7084set radvd_conf "interface eth0\n{\n AdvSendAdvert on;\n MinRtrAdvInterval 3;\n MaxRtrAdvInterval 10;\n prefix 2001:db8:1::/64\n {\n AdvOnLink on;\n AdvAutonomous on;\n AdvRouterAddr on;\n };\n};"
7185exec docker exec -i $eth2_server bash -c "echo '$radvd_conf' > /etc/radvd.conf"
7286exec docker exec -i $eth2_server chmod 600 /etc/radvd.conf
73- exec docker exec -d $eth2_server bash -c "radvd -C /etc/radvd.conf -u root -n -m stderr >/var/log/radvd.log 2>&1"
74- sleep 1
75-
76- if {[catch {exec docker exec -i $eth2_server pgrep radvd} radvd_pid]} {
77- if {![catch {exec docker exec -i $eth2_server cat /var/log/radvd.log} radvd_log]} {
78- send_user "\n=== radvd.log ===\n$radvd_log\n=== end of radvd.log ===\n"
79- }
80- fail "Failed to start radvd on eth2-server: $radvd_pid"
81- }
82- send_user "radvd started on eth2-server with PID: [string trim $radvd_pid]\n"
87+ start_radvd $eth2_server
8388
8489# 2. Start Eth_1 container (Local Infrastructure Host)
8590send_user "Starting Eth_1 container (Local Host)...\n"
@@ -122,15 +127,14 @@ start_otbr_docker_dind $container $::env(EXP_OT_RCP_PATH) 2 $pty1
122127# Wait for otbr-agent to create the domain socket
123128wait_for_otbr_agent [list $container]
124129
130+ # Delete Docker's static default route so the DUT only relies on RAs
131+ # We can run it via docker exec now that iproute2 package is added to the container
132+ catch { exec docker exec -i $container ip -6 route del default dev eth0 }
133+
125134# Enable accept_ra=2 on DUT so it configures default route and GUA via SLAAC
126135exec docker exec -i $container sysctl -w net.ipv6.conf.all.accept_ra=2
127136exec docker exec -i $container sysctl -w net.ipv6.conf.eth0.accept_ra=2
128137
129- # Delete Docker's static default route so the DUT only relies on RAs
130- set dut_pid [exec docker inspect -f {{{.State.Pid}}} $container]
131- set dut_pid [string trim $dut_pid]
132- exec nsenter -t $dut_pid -n ip -6 route del default dev eth0
133-
134138# Setup active dataset on OTBR via ot-ctl
135139exec docker exec -i $container ot-ctl thread stop
136140exec docker exec -i $container ot-ctl ifconfig down
@@ -170,12 +174,11 @@ if {!$prefix_acquired} {
170174}
171175send_user "Successfully Discovered Delegated Prefix: $delegated_prefix\n"
172176
173-
174177# Verify OMR prefix properties in netdata (subprefix of 2005:1234:abcd:0::/56, /64, default route, med preference)
175178# AND verify default route ::/0 with Route sub-TLV (NP=0)
176179proc verify_netdata {container} {
177180 set omr_regex {2005:1234:abcd:(?:[0-9a-fA-F]{1,2})?::/64\s+([a-z]*r[a-z]*)\s+med}
178- set route_regex {::/0\s+([a-z]*) \s+med}
181+ set route_regex {::/0(?: \s+([a-z]+))? \s+med}
179182 set netdata_verified false
180183 for {set i 0} {$i < 10} {incr i} {
181184 if {![catch {exec docker exec -i $container ot-ctl netdata show} netdata]} {
@@ -331,10 +334,17 @@ send_user "Ping to Internet Server verified successfully.\n"
331334# Step 7: Reconfigure radvd on eth2-server to stop advertising default route
332335send_user "Step 7: Reconfiguring radvd to stop advertising default route...\n"
333336catch {exec docker exec -i $eth2_server pkill radvd}
337+ # Wait for radvd to fully terminate to avoid port/socket binding conflicts
338+ for {set j 0} {$j < 50} {incr j} {
339+ if {[catch {exec docker exec -i $eth2_server pgrep radvd}]} {
340+ break
341+ }
342+ after 100
343+ }
334344set radvd_conf_no_default "interface eth0\n{\n AdvSendAdvert on;\n MinRtrAdvInterval 3;\n MaxRtrAdvInterval 10;\n AdvDefaultLifetime 0;\n prefix 2001:db8:1::/64\n {\n AdvOnLink on;\n AdvAutonomous on;\n AdvRouterAddr on;\n };\n};"
335345exec docker exec -i $eth2_server bash -c "echo '$radvd_conf_no_default' > /etc/radvd.conf"
336- exec docker exec -d $eth2_server bash -c "radvd -C /etc/radvd.conf -u root -n -m stderr >/var/log/radvd.log 2>&1"
337- sleep 5
346+ start_radvd $eth2_server
347+ sleep 4
338348
339349# Step 8: Verify DUT *still* advertises default route in Thread Network Data
340350send_user "Step 8: Verifying default route is still advertised in Thread Network Data...\n"
@@ -392,9 +402,9 @@ send_user "Ping to Local Host verified successfully.\n"
392402# Step 10: Ping 2002:1234::1234 from ED_1. Ping response MUST NOT be received. Ping request MUST NOT be sent on AIL.
393403send_user "Step 10: Verifying Ping to Internet Server does NOT work and is NOT forwarded...\n"
394404
395- # Start tcpdump on eth2-server to detect any ICMPv6 echo requests
405+ # Start tcpdump on eth2-server to detect any ICMPv6 echo requests (line-buffered with -l)
396406# Run in background via exec docker exec -d. Timeout in 8 seconds to allow ping tool to finish.
397- exec docker exec -d $eth2_server bash -c "timeout 8 tcpdump -c 1 -i eth0 'icmp6 and ip6\[40 \] == 128' > /var/log/tcpdump.log 2>&1"
407+ exec docker exec -d $eth2_server bash -c "timeout 8 tcpdump -l - c 1 -i eth0 'icmp6 and icmp6\[0 \] == 128' > /var/log/tcpdump.log 2>&1"
398408sleep 1
399409
400410# Send ping from ED_1
@@ -415,11 +425,15 @@ expect {
415425 }
416426}
417427if {$ping_received} {
428+ catch {
429+ set radvd_log [exec docker exec -i $eth2_server cat /var/log/radvd.log]
430+ send_user "\n=== radvd.log ===\n$radvd_log\n=== end of radvd.log ===\n"
431+ }
418432 fail "Ping from ED_1 to Internet Server succeeded, but it was expected to fail"
419433}
420434
421435# Check if tcpdump captured any packet
422- sleep 5
436+ sleep 9
423437set tcpdump_log [exec docker exec -i $eth2_server cat /var/log/tcpdump.log]
424438send_user "tcpdump log on eth2-server:\n$tcpdump_log\n"
425439if {![string match "*listening on*" $tcpdump_log]} {
@@ -433,10 +447,17 @@ send_user "Verified: Ping request was not forwarded to AIL and no response was r
433447# Step 11: Reconfigure radvd on eth2-server to start advertising default route again
434448send_user "Step 11: Reconfiguring radvd to start advertising default route again...\n"
435449catch {exec docker exec -i $eth2_server pkill radvd}
450+ # Wait for radvd to fully terminate to avoid port/socket binding conflicts
451+ for {set j 0} {$j < 50} {incr j} {
452+ if {[catch {exec docker exec -i $eth2_server pgrep radvd}]} {
453+ break
454+ }
455+ after 100
456+ }
436457set radvd_conf_with_default "interface eth0\n{\n AdvSendAdvert on;\n MinRtrAdvInterval 3;\n MaxRtrAdvInterval 10;\n AdvDefaultLifetime 875;\n prefix 2001:db8:1::/64\n {\n AdvOnLink on;\n AdvAutonomous on;\n AdvRouterAddr on;\n };\n};"
437458exec docker exec -i $eth2_server bash -c "echo '$radvd_conf_with_default' > /etc/radvd.conf"
438- exec docker exec -d $eth2_server bash -c "radvd -C /etc/radvd.conf -u root -n -m stderr >/var/log/radvd.log 2>&1"
439- sleep 5
459+ start_radvd $eth2_server
460+ sleep 4
440461
441462# Step 12: Verify default route is advertised in Thread Network Data
442463send_user "Step 12: Verifying default route is advertised in Thread Network Data again...\n"
0 commit comments