1#
2#  Copyright (c) 2014 Spectra Logic Corporation
3#  All rights reserved.
4#
5#  Redistribution and use in source and binary forms, with or without
6#  modification, are permitted provided that the following conditions
7#  are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions, and the following disclaimer,
10#     without modification.
11#  2. Redistributions in binary form must reproduce at minimum a disclaimer
12#     substantially similar to the "NO WARRANTY" disclaimer below
13#     ("Disclaimer") and any redistribution must be conditioned upon
14#     including a substantially similar Disclaimer requirement for further
15#     binary redistribution.
16#
17#  NO WARRANTY
18#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22#  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26#  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27#  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28#  POSSIBILITY OF SUCH DAMAGES.
29#
30#  Authors: Alan Somers         (Spectra Logic Corporation)
31#
32# $FreeBSD: stable/11/tests/sys/net/if_clone_test.sh 350124 2019-07-19 14:22:24Z asomers $
33
34# Outline:
35# For each cloned interface type, do three tests
36# 1) Create and destroy it
37# 2) Create, up, and destroy it
38# 3) Create, disable IPv6 auto address assignment, up, and destroy it
39
40TESTLEN=10	# seconds
41
42atf_test_case epair_stress cleanup
43epair_stress_head()
44{
45	atf_set "descr" "Simultaneously create and destroy an epair(4)"
46	atf_set "require.user" "root"
47}
48epair_stress_body()
49{
50	do_stress "epair"
51}
52epair_stress_cleanup()
53{
54	cleanup_ifaces
55}
56
57atf_test_case epair_up_stress cleanup
58epair_up_stress_head()
59{
60	atf_set "descr" "Simultaneously up and detroy an epair(4)"
61	atf_set "require.user" "root"
62}
63epair_up_stress_body()
64{
65	do_up_stress "epair" "" ""
66}
67epair_up_stress_cleanup()
68{
69	cleanup_ifaces
70}
71
72atf_test_case epair_ipv6_up_stress cleanup
73epair_ipv6_up_stress_head()
74{
75	atf_set "descr" "Simultaneously up and destroy an epair(4) with IPv6"
76	atf_set "require.user" "root"
77}
78epair_ipv6_up_stress_body()
79{
80	atf_skip "Quickly panics: page fault in in6_unlink_ifa (PR 225438)"
81	do_up_stress "epair" "6" ""
82}
83epair_ipv6_up_stress_cleanup()
84{
85	cleanup_ifaces
86}
87
88atf_test_case faith_stress cleanup
89faith_stress_head()
90{
91	atf_set "descr" "Simultaneously create and destroy a faith(4)"
92	atf_set "require.user" "root"
93}
94faith_stress_body()
95{
96	do_stress "faith"
97}
98faith_stress_cleanup()
99{
100	cleanup_ifaces
101}
102
103atf_test_case faith_up_stress cleanup
104faith_up_stress_head()
105{
106	atf_set "descr" "Simultaneously up and destroy a faith(4)"
107	atf_set "require.user" "root"
108}
109faith_up_stress_body()
110{
111	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
112	do_up_stress "faith" "" ""
113}
114faith_up_stress_cleanup()
115{
116	cleanup_ifaces
117}
118
119atf_test_case faith_ipv6_up_stress cleanup
120faith_ipv6_up_stress_head()
121{
122	atf_set "descr" "Simultaneously up and destroy a faith(4) with IPv6"
123	atf_set "require.user" "root"
124}
125faith_ipv6_up_stress_body()
126{
127	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
128	do_up_stress "faith" "6" ""
129}
130faith_ipv6_up_stress_cleanup()
131{
132	cleanup_ifaces
133}
134
135atf_test_case gif_stress cleanup
136gif_stress_head()
137{
138	atf_set "descr" "Simultaneously create and destroy a gif(4)"
139	atf_set "require.user" "root"
140}
141gif_stress_body()
142{
143	do_stress "gif"
144}
145gif_stress_cleanup()
146{
147	cleanup_ifaces
148}
149
150atf_test_case gif_up_stress cleanup
151gif_up_stress_head()
152{
153	atf_set "descr" "Simultaneously up and destroy a gif(4)"
154	atf_set "require.user" "root"
155}
156gif_up_stress_body()
157{
158	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
159	do_up_stress "gif" "" "p2p"
160}
161gif_up_stress_cleanup()
162{
163	cleanup_ifaces
164}
165
166atf_test_case gif_ipv6_up_stress cleanup
167gif_ipv6_up_stress_head()
168{
169	atf_set "descr" "Simultaneously up and destroy a gif(4) with IPv6"
170	atf_set "require.user" "root"
171}
172gif_ipv6_up_stress_body()
173{
174	atf_skip "Quickly panics: rt_tables_get_rnh_ptr: fam out of bounds."
175	do_up_stress "gif" "6" "p2p"
176}
177gif_ipv6_up_stress_cleanup()
178{
179	cleanup_ifaces
180}
181
182atf_test_case lo_stress cleanup
183lo_stress_head()
184{
185	atf_set "descr" "Simultaneously create and destroy an lo(4)"
186	atf_set "require.user" "root"
187}
188lo_stress_body()
189{
190	do_stress "lo"
191}
192lo_stress_cleanup()
193{
194	cleanup_ifaces
195}
196
197atf_test_case lo_up_stress cleanup
198lo_up_stress_head()
199{
200	atf_set "descr" "Simultaneously up and destroy an lo(4)"
201	atf_set "require.user" "root"
202}
203lo_up_stress_body()
204{
205	atf_skip "Quickly panics: GPF in rtsock_routemsg"
206	do_up_stress "lo" "" ""
207}
208lo_up_stress_cleanup()
209{
210	cleanup_ifaces
211}
212
213atf_test_case lo_ipv6_up_stress cleanup
214lo_ipv6_up_stress_head()
215{
216	atf_set "descr" "Simultaneously up and destroy an lo(4) with IPv6"
217	atf_set "require.user" "root"
218}
219lo_ipv6_up_stress_body()
220{
221	atf_skip "Quickly panics: page fault in rtsock_addrmsg"
222	do_up_stress "lo" "6" ""
223}
224lo_ipv6_up_stress_cleanup()
225{
226	cleanup_ifaces
227}
228
229atf_test_case tap_stress cleanup
230tap_stress_head()
231{
232	atf_set "descr" "Simultaneously create and destroy a tap(4)"
233	atf_set "require.user" "root"
234}
235tap_stress_body()
236{
237	do_stress "tap"
238}
239tap_stress_cleanup()
240{
241	cleanup_ifaces
242}
243
244atf_test_case tap_up_stress cleanup
245tap_up_stress_head()
246{
247	atf_set "descr" "Simultaneously up and destroy a tap(4)"
248	atf_set "require.user" "root"
249}
250tap_up_stress_body()
251{
252	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
253	do_up_stress "tap" "" ""
254}
255tap_up_stress_cleanup()
256{
257	cleanup_ifaces
258}
259
260atf_test_case tap_ipv6_up_stress cleanup
261tap_ipv6_up_stress_head()
262{
263	atf_set "descr" "Simultaneously up and destroy a tap(4) with IPv6"
264	atf_set "require.user" "root"
265}
266tap_ipv6_up_stress_body()
267{
268	atf_skip "Quickly panics: if_delmulti_locked: inconsistent ifp 0xfffff80150e44000"
269	do_up_stress "tap" "6" ""
270}
271tap_ipv6_up_stress_cleanup()
272{
273	cleanup_ifaces
274}
275
276atf_test_case tun_stress cleanup
277tun_stress_head()
278{
279	atf_set "descr" "Simultaneously create and destroy a tun(4)"
280	atf_set "require.user" "root"
281}
282tun_stress_body()
283{
284	do_stress "tun"
285}
286tun_stress_cleanup()
287{
288	cleanup_ifaces
289}
290
291atf_test_case tun_up_stress cleanup
292tun_up_stress_head()
293{
294	atf_set "descr" "Simultaneously up and destroy a tun(4)"
295	atf_set "require.user" "root"
296}
297tun_up_stress_body()
298{
299	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
300	do_up_stress "tun" "" "p2p"
301}
302tun_up_stress_cleanup()
303{
304	cleanup_ifaces
305}
306
307atf_test_case tun_ipv6_up_stress cleanup
308tun_ipv6_up_stress_head()
309{
310	atf_set "descr" "Simultaneously up and destroy a tun(4) with IPv6"
311	atf_set "require.user" "root"
312}
313tun_ipv6_up_stress_body()
314{
315	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
316	do_up_stress "tun" "6" "p2p"
317}
318tun_ipv6_up_stress_cleanup()
319{
320	cleanup_ifaces
321}
322
323atf_test_case vlan_stress cleanup
324vlan_stress_head()
325{
326	atf_set "descr" "Simultaneously create and destroy a vlan(4)"
327	atf_set "require.user" "root"
328}
329vlan_stress_body()
330{
331	do_stress "vlan"
332}
333vlan_stress_cleanup()
334{
335	cleanup_ifaces
336}
337
338atf_test_case vlan_up_stress cleanup
339vlan_up_stress_head()
340{
341	atf_set "descr" "Simultaneously up and destroy a vlan(4)"
342	atf_set "require.user" "root"
343}
344vlan_up_stress_body()
345{
346	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
347	do_up_stress "vlan" "" ""
348}
349vlan_up_stress_cleanup()
350{
351	cleanup_ifaces
352}
353
354atf_test_case vlan_ipv6_up_stress cleanup
355vlan_ipv6_up_stress_head()
356{
357	atf_set "descr" "Simultaneously up and destroy a vlan(4) with IPv6"
358	atf_set "require.user" "root"
359}
360vlan_ipv6_up_stress_body()
361{
362	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
363	do_up_stress "vlan" "6" ""
364}
365vlan_ipv6_up_stress_cleanup()
366{
367	cleanup_ifaces
368}
369
370atf_test_case vmnet_stress cleanup
371vmnet_stress_head()
372{
373	atf_set "descr" "Simultaneously create and destroy a vmnet(4)"
374	atf_set "require.user" "root"
375}
376vmnet_stress_body()
377{
378	do_stress "vmnet"
379}
380vmnet_stress_cleanup()
381{
382	cleanup_ifaces
383}
384
385atf_test_case vmnet_up_stress cleanup
386vmnet_up_stress_head()
387{
388	atf_set "descr" "Simultaneously up and destroy a vmnet(4)"
389	atf_set "require.user" "root"
390}
391vmnet_up_stress_body()
392{
393	do_up_stress "vmnet" "" ""
394}
395vmnet_up_stress_cleanup()
396{
397	cleanup_ifaces
398}
399
400atf_test_case vmnet_ipv6_up_stress cleanup
401vmnet_ipv6_up_stress_head()
402{
403	atf_set "descr" "Simultaneously up and destroy a vmnet(4) with IPv6"
404	atf_set "require.user" "root"
405}
406vmnet_ipv6_up_stress_body()
407{
408	atf_skip "Quickly panics: if_freemulti: protospec not NULL"
409	do_up_stress "vmnet" "6" ""
410}
411vmnet_ipv6_up_stress_cleanup()
412{
413	cleanup_ifaces
414}
415
416atf_init_test_cases()
417{
418	atf_add_test_case epair_ipv6_up_stress
419	atf_add_test_case epair_stress
420	atf_add_test_case epair_up_stress
421	atf_add_test_case faith_ipv6_up_stress
422	atf_add_test_case faith_stress
423	atf_add_test_case faith_up_stress
424	atf_add_test_case gif_ipv6_up_stress
425	atf_add_test_case gif_stress
426	atf_add_test_case gif_up_stress
427	# Don't test lagg; it has its own test program
428	atf_add_test_case lo_ipv6_up_stress
429	atf_add_test_case lo_stress
430	atf_add_test_case lo_up_stress
431	atf_add_test_case tap_ipv6_up_stress
432	atf_add_test_case tap_stress
433	atf_add_test_case tap_up_stress
434	atf_add_test_case tun_ipv6_up_stress
435	atf_add_test_case tun_stress
436	atf_add_test_case tun_up_stress
437	atf_add_test_case vlan_ipv6_up_stress
438	atf_add_test_case vlan_stress
439	atf_add_test_case vlan_up_stress
440	atf_add_test_case vmnet_ipv6_up_stress
441	atf_add_test_case vmnet_stress
442	atf_add_test_case vmnet_up_stress
443}
444
445do_stress()
446{
447	local IFACE CREATOR_PID DESTROYER_PID
448
449	IFACE=`get_iface $1`
450
451	# First thread: create the interface
452	while true; do
453		ifconfig ${IFACE%a} create 2>/dev/null && \
454			echo -n . >> creator_count.txt
455	done &
456	CREATOR_PID=$!
457
458	# Second thread: destroy the lagg
459	while true; do 
460		ifconfig $IFACE destroy 2>/dev/null && \
461			echo -n . >> destroyer_count.txt
462	done &
463	DESTROYER_PID=$!
464
465	sleep ${TESTLEN}
466	kill $CREATOR_PID
467	kill $DESTROYER_PID
468	echo "Created ${IFACE%a} `stat -f %z creator_count.txt` times."
469	echo "Destroyed it `stat -f %z destroyer_count.txt` times."
470}
471
472# Implement the up stress tests
473# Parameters
474# $1	Interface class, etc "lo" or "tap"
475# $2	"6" to enable IPv6 auto address assignment, anything else otherwise
476# $3	p2p for point to point interfaces, anything else for normal interfaces
477do_up_stress()
478{
479	local ADDR DSTADDR MASK MEAN_SLEEP_SECONDS MAX_SLEEP_USECS \
480	    IFACE IPV6 P2P SRCDIR LOOP_PID ipv6_cmd up_cmd
481
482	# Configure the interface to use an RFC5737 nonrouteable addresses
483	ADDR="192.0.2.2"
484	DSTADDR="192.0.2.3"
485	MASK="24"
486	# ifconfig takes about 10ms to run.  To increase race coverage,
487	# randomly delay the two commands relative to each other by 5ms either
488	# way.
489	MEAN_SLEEP_SECONDS=.005
490	MAX_SLEEP_USECS=10000
491
492	IFACE=`get_iface $1`
493	IPV6=$2
494	P2P=$3
495
496	SRCDIR=$( atf_get_srcdir )
497	if [ "$IPV6" = 6 ]; then
498		ipv6_cmd="true"
499	else
500		ipv6_cmd="ifconfig $IFACE inet6 ifdisabled"
501	fi
502	if [ "$P2P" = "p2p" ]; then
503		up_cmd="ifconfig $IFACE up ${ADDR}/${MASK} ${DSTADDR}"
504	else
505		up_cmd="ifconfig $IFACE up ${ADDR}/${MASK}"
506	fi
507	while true; do
508		eval "$ipv6_cmd"
509		{ sleep ${MEAN_SLEEP_SECONDS} && \
510			eval "$up_cmd" 2> /dev/null &&
511			echo -n . >> up_count.txt ; } &
512		{ ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \
513			ifconfig $IFACE destroy &&
514			echo -n . >> destroy_count.txt ; } &
515		wait
516		ifconfig ${IFACE%a} create
517	done &
518	LOOP_PID=$!
519
520	sleep ${TESTLEN}
521	kill $LOOP_PID
522	echo "Upped ${IFACE} `stat -f %z up_count.txt` times."
523	echo "Destroyed it `stat -f %z destroy_count.txt` times."
524}
525
526# Creates a new cloned interface, registers it for cleanup, and echoes it
527# params: $1	Interface class name (tap, gif, etc)
528get_iface()
529{
530	local CLASS DEV N
531
532	CLASS=$1
533	N=0
534	while ! ifconfig ${CLASS}${N} create > /dev/null 2>&1; do
535		if [ "$N" -ge 8 ]; then
536			atf_skip "Could not create a ${CLASS} interface"
537		else
538			N=$(($N + 1))
539		fi
540	done
541	if [ ${CLASS} = "epair" ]; then
542		DEV=${CLASS}${N}a
543	else
544		DEV=${CLASS}${N}
545	fi
546	# Record the device so we can clean it up later
547	echo ${DEV} >> "devices_to_cleanup"
548	echo ${DEV}
549}
550
551
552cleanup_ifaces()
553{
554	local DEV
555
556	for DEV in `cat "devices_to_cleanup"`; do
557		ifconfig ${DEV} destroy
558	done
559	true
560}
561