xref: /netbsd-src/tests/net/if_bridge/t_bridge.sh (revision fe76e013a16002b6276da331dfc7e18c89a4199f)
1#	$NetBSD: t_bridge.sh,v 1.21 2024/09/03 08:01:38 ozaki-r Exp $
2#
3# Copyright (c) 2014 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27
28SOCK1=unix://commsock1
29SOCK2=unix://commsock2
30SOCK3=unix://commsock3
31IP1=10.0.0.1
32IP2=10.0.0.2
33IP61=fc00::1
34IP62=fc00::2
35IPBR1=10.0.0.11
36IPBR2=10.0.0.12
37IP6BR1=fc00::11
38IP6BR2=fc00::12
39
40DEBUG=${DEBUG:-false}
41TIMEOUT=5
42
43setup_endpoint()
44{
45	sock=${1}
46	addr=${2}
47	bus=${3}
48	mode=${4}
49
50	rump_server_add_iface $sock shmif0 $bus
51	export RUMP_SERVER=${sock}
52	if [ $mode = "ipv6" ]; then
53		atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${addr}
54	else
55		atf_check -s exit:0 rump.ifconfig shmif0 inet ${addr} netmask 0xffffff00
56	fi
57
58	atf_check -s exit:0 rump.ifconfig shmif0 up
59	$DEBUG && rump.ifconfig shmif0
60}
61
62test_endpoint()
63{
64	sock=${1}
65	addr=${2}
66	bus=${3}
67	mode=${4}
68
69	export RUMP_SERVER=${sock}
70	atf_check -s exit:0 -o match:shmif0 rump.ifconfig
71	if [ $mode = "ipv6" ]; then
72		atf_check -s exit:0 -o ignore rump.ping6 -n -c 1 -X $TIMEOUT ${addr}
73	else
74		atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 ${addr}
75	fi
76}
77
78test_setup()
79{
80	test_endpoint $SOCK1 $IP1 bus1 ipv4
81	test_endpoint $SOCK3 $IP2 bus2 ipv4
82
83	export RUMP_SERVER=$SOCK2
84	atf_check -s exit:0 -o match:shmif0 rump.ifconfig
85	atf_check -s exit:0 -o match:shmif1 rump.ifconfig
86}
87
88test_setup6()
89{
90	test_endpoint $SOCK1 $IP61 bus1 ipv6
91	test_endpoint $SOCK3 $IP62 bus2 ipv6
92
93	export RUMP_SERVER=$SOCK2
94	atf_check -s exit:0 -o match:shmif0 rump.ifconfig
95	atf_check -s exit:0 -o match:shmif1 rump.ifconfig
96}
97
98setup_bridge_server()
99{
100
101	rump_server_add_iface $SOCK2 shmif0 bus1
102	rump_server_add_iface $SOCK2 shmif1 bus2
103	export RUMP_SERVER=$SOCK2
104	atf_check -s exit:0 rump.ifconfig shmif0 up
105	atf_check -s exit:0 rump.ifconfig shmif1 up
106}
107
108setup()
109{
110
111	rump_server_start $SOCK1 bridge
112	rump_server_start $SOCK2 bridge
113	rump_server_start $SOCK3 bridge
114
115	setup_endpoint $SOCK1 $IP1 bus1 ipv4
116	setup_endpoint $SOCK3 $IP2 bus2 ipv4
117	setup_bridge_server
118}
119
120setup6()
121{
122
123	rump_server_start $SOCK1 netinet6 bridge
124	rump_server_start $SOCK2 netinet6 bridge
125	rump_server_start $SOCK3 netinet6 bridge
126
127	setup_endpoint $SOCK1 $IP61 bus1 ipv6
128	setup_endpoint $SOCK3 $IP62 bus2 ipv6
129	setup_bridge_server
130}
131
132setup_bridge()
133{
134	export RUMP_SERVER=$SOCK2
135	rump_server_add_iface $SOCK2 bridge0
136	atf_check -s exit:0 rump.ifconfig bridge0 up
137
138	export LD_PRELOAD=/usr/lib/librumphijack.so
139	atf_check -s exit:0 /sbin/brconfig bridge0 add shmif0
140	atf_check -s exit:0 /sbin/brconfig bridge0 add shmif1
141	/sbin/brconfig bridge0
142	unset LD_PRELOAD
143	rump.ifconfig shmif0
144	rump.ifconfig shmif1
145}
146
147setup_member_ip()
148{
149	export RUMP_SERVER=$SOCK2
150	export LD_PRELOAD=/usr/lib/librumphijack.so
151	atf_check -s exit:0 rump.ifconfig shmif0 $IPBR1/24
152	atf_check -s exit:0 rump.ifconfig shmif1 $IPBR2/24
153	atf_check -s exit:0 rump.ifconfig -w 10
154	/sbin/brconfig bridge0
155	unset LD_PRELOAD
156	rump.ifconfig shmif0
157	rump.ifconfig shmif1
158}
159
160setup_member_ip6()
161{
162	export RUMP_SERVER=$SOCK2
163	export LD_PRELOAD=/usr/lib/librumphijack.so
164	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6BR1
165	atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6BR2
166	atf_check -s exit:0 rump.ifconfig -w 10
167	/sbin/brconfig bridge0
168	unset LD_PRELOAD
169	rump.ifconfig shmif0
170	rump.ifconfig shmif1
171}
172
173teardown_bridge()
174{
175	export RUMP_SERVER=$SOCK2
176	export LD_PRELOAD=/usr/lib/librumphijack.so
177	/sbin/brconfig bridge0
178	atf_check -s exit:0 /sbin/brconfig bridge0 delete shmif0
179	atf_check -s exit:0 /sbin/brconfig bridge0 delete shmif1
180	/sbin/brconfig bridge0
181	unset LD_PRELOAD
182	rump.ifconfig shmif0
183	rump.ifconfig shmif1
184}
185
186test_setup_bridge()
187{
188	export RUMP_SERVER=$SOCK2
189	export LD_PRELOAD=/usr/lib/librumphijack.so
190	atf_check -s exit:0 -o match:shmif0 /sbin/brconfig bridge0
191	atf_check -s exit:0 -o match:shmif1 /sbin/brconfig bridge0
192	/sbin/brconfig bridge0
193	unset LD_PRELOAD
194}
195
196down_up_interfaces()
197{
198	export RUMP_SERVER=$SOCK1
199	rump.ifconfig shmif0 down
200	rump.ifconfig shmif0 up
201	export RUMP_SERVER=$SOCK3
202	rump.ifconfig shmif0 down
203	rump.ifconfig shmif0 up
204}
205
206test_ping_failure()
207{
208	export RUMP_SERVER=$SOCK1
209	atf_check -s not-exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IP2
210	export RUMP_SERVER=$SOCK3
211	atf_check -s not-exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IP1
212}
213
214test_ping_success()
215{
216	export RUMP_SERVER=$SOCK1
217	rump.ifconfig -v shmif0
218	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IP2
219	rump.ifconfig -v shmif0
220
221	export RUMP_SERVER=$SOCK3
222	rump.ifconfig -v shmif0
223	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IP1
224	rump.ifconfig -v shmif0
225}
226
227test_ping6_failure()
228{
229	export RUMP_SERVER=$SOCK1
230	atf_check -s not-exit:0 -o ignore rump.ping6 -q -n -c 1 -X $TIMEOUT $IP62
231	export RUMP_SERVER=$SOCK3
232	atf_check -s not-exit:0 -o ignore rump.ping6 -q -n -c 1 -X $TIMEOUT $IP61
233}
234
235test_ping6_success()
236{
237	export RUMP_SERVER=$SOCK1
238	rump.ifconfig -v shmif0
239	atf_check -s exit:0 -o ignore rump.ping6 -q -n -c 1 -X $TIMEOUT $IP62
240	rump.ifconfig -v shmif0
241
242	export RUMP_SERVER=$SOCK3
243	rump.ifconfig -v shmif0
244	atf_check -s exit:0 -o ignore rump.ping6 -q -n -c 1 -X $TIMEOUT $IP61
245	rump.ifconfig -v shmif0
246}
247
248test_ping_member()
249{
250	export RUMP_SERVER=$SOCK1
251	rump.ifconfig -v shmif0
252	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IPBR1
253	rump.ifconfig -v shmif0
254	# Test for PR#48104
255	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IPBR2
256	rump.ifconfig -v shmif0
257
258	export RUMP_SERVER=$SOCK3
259	rump.ifconfig -v shmif0
260	# Test for PR#48104
261	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IPBR1
262	rump.ifconfig -v shmif0
263	atf_check -s exit:0 -o ignore rump.ping -q -n -w $TIMEOUT -c 1 $IPBR2
264	rump.ifconfig -v shmif0
265}
266
267test_ping6_member()
268{
269	export RUMP_SERVER=$SOCK1
270	rump.ifconfig -v shmif0
271	atf_check -s exit:0 -o ignore rump.ping6 -q -n -X $TIMEOUT -c 1 $IP6BR1
272	rump.ifconfig -v shmif0
273	# Test for PR#48104
274	atf_check -s exit:0 -o ignore rump.ping6 -q -n -X $TIMEOUT -c 1 $IP6BR2
275	rump.ifconfig -v shmif0
276
277	export RUMP_SERVER=$SOCK3
278	rump.ifconfig -v shmif0
279	# Test for PR#48104
280	atf_check -s exit:0 -o ignore rump.ping6 -q -n -X $TIMEOUT -c 1 $IP6BR1
281	rump.ifconfig -v shmif0
282	atf_check -s exit:0 -o ignore rump.ping6 -q -n -X $TIMEOUT -c 1 $IP6BR2
283	rump.ifconfig -v shmif0
284}
285
286test_create_destroy()
287{
288
289	rump_server_start $SOCK1 bridge
290
291	test_create_destroy_common $SOCK1 bridge0
292}
293
294test_ipv4()
295{
296	setup
297	test_setup
298
299	# Enable once PR kern/49219 is fixed
300	#test_ping_failure
301
302	setup_bridge
303	sleep 1
304	test_setup_bridge
305	test_ping_success
306
307	teardown_bridge
308	test_ping_failure
309
310	rump_server_destroy_ifaces
311}
312
313test_ipv6()
314{
315	setup6
316	test_setup6
317
318	test_ping6_failure
319
320	setup_bridge
321	sleep 1
322	test_setup_bridge
323	test_ping6_success
324
325	teardown_bridge
326	test_ping6_failure
327
328	rump_server_destroy_ifaces
329}
330
331test_member_ipv4()
332{
333	setup
334	test_setup
335
336	# Enable once PR kern/49219 is fixed
337	#test_ping_failure
338
339	setup_bridge
340	sleep 1
341	test_setup_bridge
342	test_ping_success
343
344	setup_member_ip
345	test_ping_member
346
347	teardown_bridge
348	test_ping_failure
349
350	rump_server_destroy_ifaces
351}
352
353test_member_ipv6()
354{
355	setup6
356	test_setup6
357
358	test_ping6_failure
359
360	setup_bridge
361	sleep 1
362	test_setup_bridge
363	test_ping6_success
364
365	setup_member_ip6
366	test_ping6_member
367
368	teardown_bridge
369	test_ping6_failure
370
371	rump_server_destroy_ifaces
372}
373
374BUS_SHMIF0=./bus0
375BUS_SHMIF1=./bus1
376BUS_SHMIF2=./bus2
377
378unpack_file()
379{
380
381	atf_check -s exit:0 uudecode $(atf_get_srcdir)/${1}.uue
382}
383
384reset_if_stats()
385{
386
387	for ifname in shmif0 shmif1 shmif2
388	do
389		atf_check -s exit:0 -o ignore rump.ifconfig -z $ifname
390	done
391}
392
393test_protection()
394{
395
396	unpack_file unicast.pcap
397	unpack_file broadcast.pcap
398
399	rump_server_start $SOCK1 bridge
400	rump_server_add_iface $SOCK1 shmif0 $BUS_SHMIF0
401	rump_server_add_iface $SOCK1 shmif1 $BUS_SHMIF1
402	rump_server_add_iface $SOCK1 shmif2 $BUS_SHMIF2
403
404	export RUMP_SERVER=$SOCK1
405	atf_check -s exit:0 rump.ifconfig shmif0 up
406	atf_check -s exit:0 rump.ifconfig shmif1 up
407	atf_check -s exit:0 rump.ifconfig shmif2 up
408
409	atf_check -s exit:0 rump.ifconfig bridge0 create
410	atf_check -s exit:0 rump.ifconfig bridge0 up
411
412	atf_check -s exit:0 $HIJACKING brconfig bridge0 add shmif0 add shmif1 add shmif2
413	$DEBUG && rump.ifconfig
414
415	# Protected interfaces: -
416	# Learning: -
417	# Input: unicast through shmif0
418	# Output: shmif1, shmif2
419	reset_if_stats
420	atf_check -s exit:0 -o ignore shmif_pcapin unicast.pcap ${BUS_SHMIF0}
421	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
422	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif1
423	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif2
424	$DEBUG && rump.ifconfig -v bridge0
425
426	# Protected interfaces: -
427	# Learning: -
428	# Input: broadcast through shmif0
429	# Output: shmif1, shmif2
430	reset_if_stats
431	atf_check -s exit:0 -o ignore shmif_pcapin broadcast.pcap ${BUS_SHMIF0}
432	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
433	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif1
434	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif2
435	$DEBUG && rump.ifconfig -v bridge0
436
437	# Protect shmif0 and shmif2
438	atf_check -s exit:0 $HIJACKING brconfig bridge0 protect shmif0
439	atf_check -s exit:0 $HIJACKING brconfig bridge0 protect shmif2
440	atf_check -s exit:0 \
441	    -o match:"shmif0.+PROTECTED" \
442	    -o match:"shmif2.+PROTECTED" \
443	    -o not-match:"shmif1.+PROTECTED" \
444	    $HIJACKING brconfig bridge0
445
446	# Protected interfaces: shmif0 shmif2
447	# Learning: -
448	# Input: unicast through shmif0
449	# Output: shmif1
450	reset_if_stats
451	atf_check -s exit:0 -o ignore shmif_pcapin unicast.pcap ${BUS_SHMIF0}
452	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
453	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif1
454	atf_check -s exit:0 -o match:"output: 0 packet" rump.ifconfig -v shmif2
455	$DEBUG && rump.ifconfig -v bridge0
456
457	# Protected interfaces: shmif0 shmif2
458	# Learning: -
459	# Input: broadcast through shmif0
460	# Output: shmif1
461	reset_if_stats
462	atf_check -s exit:0 -o ignore shmif_pcapin broadcast.pcap ${BUS_SHMIF0}
463	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
464	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif1
465	atf_check -s exit:0 -o match:"output: 0 packet" rump.ifconfig -v shmif2
466	$DEBUG && rump.ifconfig -v bridge0
467
468	# Insert a route 00:aa:aa:aa:aa:aa shmif2 to test forwarding path of known-unicast-frame
469	atf_check -s exit:0 $HIJACKING brconfig bridge0 static shmif2 00:aa:aa:aa:aa:aa
470	atf_check -s exit:0 -o match:'00:aa:aa:aa:aa:aa shmif2 0 flags=1<STATIC>' \
471	    $HIJACKING brconfig bridge0
472	$DEBUG && $HIJACKING brconfig bridge0
473
474	# Protected interfaces: shmif0 shmif2
475	# Learning: 00:aa:aa:aa:aa:aa shmif2
476	# Input: broadcast through shmif0
477	# Output: -
478	reset_if_stats
479	atf_check -s exit:0 -o ignore shmif_pcapin unicast.pcap ${BUS_SHMIF0}
480	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
481	atf_check -s exit:0 -o match:"output: 0 packet" rump.ifconfig -v shmif1
482	atf_check -s exit:0 -o match:"output: 0 packet" rump.ifconfig -v shmif2
483	$DEBUG && rump.ifconfig -v bridge0
484
485	# Unprotect shmif2
486	atf_check -s exit:0 $HIJACKING brconfig bridge0 -protect shmif2
487	atf_check -s exit:0 \
488	    -o match:"shmif0.+PROTECTED" \
489	    -o not-match:"shmif2.+PROTECTED" \
490	    -o not-match:"shmif1.+PROTECTED" \
491	    $HIJACKING brconfig bridge0
492
493	# Protected interfaces: shmif0
494	# Learning: 00:aa:aa:aa:aa:aa shmif2
495	# Input: broadcast through shmif0
496	# Output: shmif2
497	reset_if_stats
498	atf_check -s exit:0 -o ignore shmif_pcapin unicast.pcap ${BUS_SHMIF0}
499	atf_check -s exit:0 -o match:"input: 1 packet" rump.ifconfig -v shmif0
500	atf_check -s exit:0 -o match:"output: 0 packet" rump.ifconfig -v shmif1
501	atf_check -s exit:0 -o match:"output: 1 packet" rump.ifconfig -v shmif2
502	$DEBUG && rump.ifconfig -v bridge0
503
504	rump_server_destroy_ifaces
505}
506
507add_test()
508{
509	local name=$1
510	local desc="$2"
511
512	atf_test_case "bridge_${name}" cleanup
513	eval "bridge_${name}_head() {
514			atf_set descr \"${desc}\"
515			atf_set require.progs rump_server
516		}
517	    bridge_${name}_body() {
518			test_${name}
519		}
520	    bridge_${name}_cleanup() {
521			\$DEBUG && dump
522			cleanup
523		}"
524	atf_add_test_case "bridge_${name}"
525}
526
527atf_init_test_cases()
528{
529
530	add_test create_destroy "Tests creating/destroying bridge interfaces"
531	add_test ipv4           "Does basic if_bridge tests (IPv4)"
532	add_test ipv6           "Does basic if_bridge tests (IPv6)"
533	add_test member_ipv4    "Tests if_bridge with members with an IP address (IPv4)"
534	add_test member_ipv6    "Tests if_bridge with members with an IP address (IPv6)"
535	add_test protection     "Tests interface protection"
536}
537