1329874Sasomers#
2329874Sasomers#  Copyright (c) 2014 Spectra Logic Corporation
3329874Sasomers#  All rights reserved.
4329874Sasomers#
5329874Sasomers#  Redistribution and use in source and binary forms, with or without
6329874Sasomers#  modification, are permitted provided that the following conditions
7329874Sasomers#  are met:
8329874Sasomers#  1. Redistributions of source code must retain the above copyright
9329874Sasomers#     notice, this list of conditions, and the following disclaimer,
10329874Sasomers#     without modification.
11329874Sasomers#  2. Redistributions in binary form must reproduce at minimum a disclaimer
12329874Sasomers#     substantially similar to the "NO WARRANTY" disclaimer below
13329874Sasomers#     ("Disclaimer") and any redistribution must be conditioned upon
14329874Sasomers#     including a substantially similar Disclaimer requirement for further
15329874Sasomers#     binary redistribution.
16329874Sasomers#
17329874Sasomers#  NO WARRANTY
18329874Sasomers#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19329874Sasomers#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20329874Sasomers#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21329874Sasomers#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22329874Sasomers#  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23329874Sasomers#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24329874Sasomers#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25329874Sasomers#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26329874Sasomers#  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27329874Sasomers#  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28329874Sasomers#  POSSIBILITY OF SUCH DAMAGES.
29329874Sasomers#
30329874Sasomers#  Authors: Alan Somers         (Spectra Logic Corporation)
31329874Sasomers#
32329874Sasomers# $FreeBSD: stable/11/tests/sys/net/if_lagg_test.sh 329874 2018-02-23 18:18:42Z asomers $
33329874Sasomers
34329874Sasomersatf_test_case create cleanup
35329874Sasomerscreate_head()
36329874Sasomers{
37329874Sasomers	atf_set "descr" "Create a lagg and assign an address"
38329874Sasomers	atf_set "require.user" "root"
39329874Sasomers}
40329874Sasomerscreate_body()
41329874Sasomers{
42329874Sasomers	local TAP0 TAP1 LAGG MAC
43329874Sasomers
44329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
45329874Sasomers	ADDR="192.0.2.2"
46329874Sasomers	MASK="24"
47329874Sasomers
48329874Sasomers	TAP0=`get_tap`
49329874Sasomers	TAP1=`get_tap`
50329874Sasomers	LAGG=`get_lagg`
51329874Sasomers
52329874Sasomers	# Create the lagg
53329874Sasomers	ifconfig $TAP0 up
54329874Sasomers	ifconfig $TAP1 up
55329874Sasomers	atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
56329874Sasomers		${ADDR}/${MASK}
57329874Sasomers	atf_check -o match:"inet ${ADDR}" ifconfig $LAGG
58329874Sasomers	atf_check -o match:"laggport: ${TAP0}" ifconfig $LAGG
59329874Sasomers	atf_check -o match:"laggport: ${TAP1}" ifconfig $LAGG
60329874Sasomers
61329874Sasomers	# Check that all members have the same MAC
62329874Sasomers	MAC=`ifconfig $LAGG | awk '/ether/ {print $2}'`
63329874Sasomers	atf_check -o match:"ether ${MAC}" ifconfig $TAP0
64329874Sasomers	atf_check -o match:"ether ${MAC}" ifconfig $TAP1
65329874Sasomers
66329874Sasomers	# Check that no members have an IPv6 link-local address. IPv6
67329874Sasomers	# link-local addresses should never be merged in any way to prevent
68329874Sasomers	# scope violation.
69329874Sasomers	atf_check -o not-match:"inet6 fe80:" ifconfig $TAP0
70329874Sasomers	atf_check -o not-match:"inet6 fe80:" ifconfig $TAP1
71329874Sasomers}
72329874Sasomerscreate_cleanup()
73329874Sasomers{
74329874Sasomers	cleanup_tap_and_lagg
75329874Sasomers}
76329874Sasomers
77329874Sasomersatf_test_case status_stress cleanup
78329874Sasomersstatus_stress_head()
79329874Sasomers{
80329874Sasomers	atf_set "descr" "Simultaneously query a lagg while also creating or destroying it."
81329874Sasomers	atf_set "require.user" "root"
82329874Sasomers}
83329874Sasomersstatus_stress_body()
84329874Sasomers{
85329874Sasomers	local TAP0 TAP1 LAGG MAC
86329874Sasomers
87329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
88329874Sasomers	ADDR="192.0.2.2"
89329874Sasomers	MASK="24"
90329874Sasomers
91329874Sasomers	TAP0=`get_tap`
92329874Sasomers	TAP1=`get_tap`
93329874Sasomers	TAP2=`get_tap`
94329874Sasomers	TAP3=`get_tap`
95329874Sasomers	LAGG=`get_lagg`
96329874Sasomers
97329874Sasomers	# Up the lagg's children
98329874Sasomers	ifconfig $TAP0 inet6 ifdisabled up
99329874Sasomers	ifconfig $TAP1 inet6 ifdisabled up
100329874Sasomers	ifconfig $TAP2 inet6 ifdisabled up
101329874Sasomers	ifconfig $TAP3 inet6 ifdisabled up
102329874Sasomers
103329874Sasomers	# First thread: create and destroy the lagg
104329874Sasomers	while true; do
105329874Sasomers		ifconfig $LAGG destroy 2>&1
106329874Sasomers		ifconfig $LAGG create 2>/dev/null
107329874Sasomers		ifconfig $LAGG inet6 ifdisabled
108329874Sasomers		ifconfig $LAGG up laggport $TAP0 laggport $TAP1 laggport $TAP2\
109329874Sasomers			laggport $TAP3 ${ADDR}/${MASK} 2>/dev/null
110329874Sasomers		echo -n . >> creator_count.txt
111329874Sasomers	done &
112329874Sasomers	CREATOR_PID=$!
113329874Sasomers
114329874Sasomers	# Second thread: Query the lagg's status
115329874Sasomers	while true; do
116329874Sasomers		ifconfig -am 2> /dev/null > /dev/null
117329874Sasomers		echo -n . >> querier_count.txt
118329874Sasomers	done &
119329874Sasomers	QUERIER_PID=$!
120329874Sasomers
121329874Sasomers	sleep 60
122329874Sasomers	kill $CREATOR_PID
123329874Sasomers	kill $QUERIER_PID
124329874Sasomers	echo "Created the lagg `stat -f %z creator_count.txt` times."
125329874Sasomers	echo "Queried its status `stat -f %z querier_count.txt` times"
126329874Sasomers}
127329874Sasomersstatus_stress_cleanup()
128329874Sasomers{
129329874Sasomers	cleanup_tap_and_lagg
130329874Sasomers}
131329874Sasomers
132329874Sasomersatf_test_case create_destroy_stress cleanup
133329874Sasomerscreate_destroy_stress_head()
134329874Sasomers{
135329874Sasomers	atf_set "descr" "Simultaneously create and destroy a lagg"
136329874Sasomers	atf_set "require.user" "root"
137329874Sasomers}
138329874Sasomerscreate_destroy_stress_body()
139329874Sasomers{
140329874Sasomers	local TAP0 TAP1 LAGG MAC
141329874Sasomers	
142329874Sasomers	atf_skip "Skipping this test because it easily panics the machine"
143329874Sasomers
144329874Sasomers	TAP0=`get_tap`
145329874Sasomers	TAP1=`get_tap`
146329874Sasomers	TAP2=`get_tap`
147329874Sasomers	TAP3=`get_tap`
148329874Sasomers	LAGG=`get_lagg`
149329874Sasomers
150329874Sasomers	# Up the lagg's children
151329874Sasomers	ifconfig $TAP0 inet6 ifdisabled up
152329874Sasomers	ifconfig $TAP1 inet6 ifdisabled up
153329874Sasomers	ifconfig $TAP2 inet6 ifdisabled up
154329874Sasomers	ifconfig $TAP3 inet6 ifdisabled up
155329874Sasomers
156329874Sasomers	# First thread: create the lagg
157329874Sasomers	while true; do
158329874Sasomers		ifconfig $LAGG create 2>/dev/null && \
159329874Sasomers			echo -n . >> creator_count.txt
160329874Sasomers	done &
161329874Sasomers	CREATOR_PID=$!
162329874Sasomers
163329874Sasomers	# Second thread: destroy the lagg
164329874Sasomers	while true; do 
165329874Sasomers		ifconfig $LAGG destroy 2>/dev/null && \
166329874Sasomers			echo -n . >> destroyer_count.txt
167329874Sasomers	done &
168329874Sasomers	DESTROYER_PID=$!
169329874Sasomers
170329874Sasomers	sleep 60
171329874Sasomers	kill $CREATOR_PID
172329874Sasomers	kill $DESTROYER_PID
173329874Sasomers	echo "Created the lagg `stat -f %z creator_count.txt` times."
174329874Sasomers	echo "Destroyed it `stat -f %z destroyer_count.txt` times."
175329874Sasomers}
176329874Sasomerscreate_destroy_stress_cleanup()
177329874Sasomers{
178329874Sasomers	cleanup_tap_and_lagg
179329874Sasomers}
180329874Sasomers
181329874Sasomers# This test regresses a panic that is particular to LACP.  If the child's link
182329874Sasomers# state changes while the lagg is being destroyed, lacp_linkstate can
183329874Sasomers# use-after-free.  The problem is compounded by two factors:
184329874Sasomers# 1) In SpectraBSD, downing the parent will also down the child
185329874Sasomers# 2) The cxgbe driver will show the link state as "no carrier" as soon as you
186329874Sasomers#    down the interface.
187329874Sasomers# TeamTrack: P2_30328
188329874Sasomersatf_test_case lacp_linkstate_destroy_stress cleanup
189329874Sasomerslacp_linkstate_destroy_stress_head()
190329874Sasomers{
191329874Sasomers	atf_set "descr" "Simultaneously destroy an LACP lagg and change its childrens link states"
192329874Sasomers	atf_set "require.user" "root"
193329874Sasomers}
194329874Sasomerslacp_linkstate_destroy_stress_body()
195329874Sasomers{
196329874Sasomers	local TAP0 TAP1 LAGG MAC SRCDIR
197329874Sasomers	
198329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
199329874Sasomers	ADDR="192.0.2.2"
200329874Sasomers	MASK="24"
201329874Sasomers	# ifconfig takes about 10ms to run.  To increase race coverage,
202329874Sasomers	# randomly delay the two commands relative to each other by 5ms either
203329874Sasomers	# way.
204329874Sasomers	MEAN_SLEEP_SECONDS=.005
205329874Sasomers	MAX_SLEEP_USECS=10000
206329874Sasomers
207329874Sasomers	TAP0=`get_tap`
208329874Sasomers	TAP1=`get_tap`
209329874Sasomers	LAGG=`get_lagg`
210329874Sasomers
211329874Sasomers	# Up the lagg's children
212329874Sasomers	ifconfig $TAP0 inet6 ifdisabled up
213329874Sasomers	ifconfig $TAP1 inet6 ifdisabled up
214329874Sasomers
215329874Sasomers	SRCDIR=$( atf_get_srcdir )
216329874Sasomers	while true; do
217329874Sasomers		ifconfig $LAGG inet6 ifdisabled
218329874Sasomers		# We must open the tap devices to change their link states
219329874Sasomers		cat /dev/$TAP0 > /dev/null &
220329874Sasomers		CAT0_PID=$!
221329874Sasomers		cat /dev/$TAP1 > /dev/null &
222329874Sasomers		CAT1_PID=$!
223329874Sasomers		ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
224329874Sasomers			${ADDR}/${MASK} 2> /dev/null &&
225329874Sasomers		{ sleep ${MEAN_SLEEP_SECONDS} && \
226329874Sasomers			kill $CAT0_PID &&
227329874Sasomers			kill $CAT1_PID &&
228329874Sasomers			echo -n . >> linkstate_count.txt ; } &
229329874Sasomers		{ ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \
230329874Sasomers			ifconfig $LAGG destroy &&
231329874Sasomers			echo -n . >> destroy_count.txt ; } &
232329874Sasomers		wait
233329874Sasomers		ifconfig $LAGG create
234329874Sasomers	done &
235329874Sasomers	LOOP_PID=$!
236329874Sasomers
237329874Sasomers	sleep 60
238329874Sasomers	kill $LOOP_PID
239329874Sasomers	echo "Disconnected the children `stat -f %z linkstate_count.txt` times."
240329874Sasomers	echo "Destroyed the lagg `stat -f %z destroy_count.txt` times."
241329874Sasomers}
242329874Sasomerslacp_linkstate_destroy_stress_cleanup()
243329874Sasomers{
244329874Sasomers	cleanup_tap_and_lagg
245329874Sasomers}
246329874Sasomers
247329874Sasomersatf_test_case up_destroy_stress cleanup
248329874Sasomersup_destroy_stress_head()
249329874Sasomers{
250329874Sasomers	atf_set "descr" "Simultaneously up and destroy a lagg"
251329874Sasomers	atf_set "require.user" "root"
252329874Sasomers}
253329874Sasomersup_destroy_stress_body()
254329874Sasomers{
255329874Sasomers	local TAP0 TAP1 LAGG MAC SRCDIR
256329874Sasomers
257329874Sasomers	atf_skip "Skipping this test because it panics the machine fairly often"
258329874Sasomers	
259329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
260329874Sasomers	ADDR="192.0.2.2"
261329874Sasomers	MASK="24"
262329874Sasomers	# ifconfig takes about 10ms to run.  To increase race coverage,
263329874Sasomers	# randomly delay the two commands relative to each other by 5ms either
264329874Sasomers	# way.
265329874Sasomers	MEAN_SLEEP_SECONDS=.005
266329874Sasomers	MAX_SLEEP_USECS=10000
267329874Sasomers
268329874Sasomers	TAP0=`get_tap`
269329874Sasomers	TAP1=`get_tap`
270329874Sasomers	TAP2=`get_tap`
271329874Sasomers	TAP3=`get_tap`
272329874Sasomers	LAGG=`get_lagg`
273329874Sasomers
274329874Sasomers	# Up the lagg's children
275329874Sasomers	ifconfig $TAP0 inet6 ifdisabled up
276329874Sasomers	ifconfig $TAP1 inet6 ifdisabled up
277329874Sasomers	ifconfig $TAP2 inet6 ifdisabled up
278329874Sasomers	ifconfig $TAP3 inet6 ifdisabled up
279329874Sasomers
280329874Sasomers	SRCDIR=$( atf_get_srcdir )
281329874Sasomers	while true; do
282329874Sasomers		ifconfig $LAGG inet6 ifdisabled
283329874Sasomers		{ sleep ${MEAN_SLEEP_SECONDS} && \
284329874Sasomers			ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
285329874Sasomers				laggport $TAP2 laggport $TAP3 \
286329874Sasomers				${ADDR}/${MASK} 2> /dev/null &&
287329874Sasomers			echo -n . >> up_count.txt ; } &
288329874Sasomers		{ ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \
289329874Sasomers			ifconfig $LAGG destroy &&
290329874Sasomers			echo -n . >> destroy_count.txt ; } &
291329874Sasomers		wait
292329874Sasomers		ifconfig $LAGG create
293329874Sasomers	done &
294329874Sasomers	LOOP_PID=$!
295329874Sasomers
296329874Sasomers	sleep 60
297329874Sasomers	kill $LOOP_PID
298329874Sasomers	echo "Upped the lagg `stat -f %z up_count.txt` times."
299329874Sasomers	echo "Destroyed it `stat -f %z destroy_count.txt` times."
300329874Sasomers}
301329874Sasomersup_destroy_stress_cleanup()
302329874Sasomers{
303329874Sasomers	cleanup_tap_and_lagg
304329874Sasomers}
305329874Sasomers
306329874Sasomersatf_test_case set_ether cleanup
307329874Sasomersset_ether_head()
308329874Sasomers{
309329874Sasomers	atf_set "descr" "Set a lagg's ethernet address"
310329874Sasomers	atf_set "require.user" "root"
311329874Sasomers}
312329874Sasomersset_ether_body()
313329874Sasomers{
314329874Sasomers	local TAP0 TAP1 LAGG MAC
315329874Sasomers
316329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
317329874Sasomers	ADDR="192.0.2.2"
318329874Sasomers	MASK="24"
319329874Sasomers	MAC="00:11:22:33:44:55"
320329874Sasomers
321329874Sasomers	TAP0=`get_tap`
322329874Sasomers	TAP1=`get_tap`
323329874Sasomers	LAGG=`get_lagg`
324329874Sasomers
325329874Sasomers	# Create the lagg
326329874Sasomers	ifconfig $TAP0 up
327329874Sasomers	ifconfig $TAP1 up
328329874Sasomers	atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
329329874Sasomers		${ADDR}/${MASK}
330329874Sasomers
331329874Sasomers	# Change the lagg's ethernet address
332329874Sasomers	atf_check ifconfig $LAGG ether ${MAC}
333329874Sasomers
334329874Sasomers	# Check that all members have the same MAC
335329874Sasomers	atf_check -o match:"ether ${MAC}" ifconfig $LAGG
336329874Sasomers	atf_check -o match:"ether ${MAC}" ifconfig $TAP0
337329874Sasomers	atf_check -o match:"ether ${MAC}" ifconfig $TAP1
338329874Sasomers}
339329874Sasomersset_ether_cleanup()
340329874Sasomers{
341329874Sasomers	cleanup_tap_and_lagg
342329874Sasomers}
343329874Sasomers
344329874Sasomersatf_test_case updown cleanup
345329874Sasomersupdown_head()
346329874Sasomers{
347329874Sasomers	atf_set "descr" "upping or downing a lagg ups or downs its children"
348329874Sasomers	atf_set "require.user" "root"
349329874Sasomers}
350329874Sasomersupdown_body()
351329874Sasomers{
352329874Sasomers	local TAP0 TAP1 LAGG MAC
353329874Sasomers
354329874Sasomers	atf_expect_fail "PR 226144 Upping a lagg interrface should automatically up its children"
355329874Sasomers	# Configure the lagg interface to use an RFC5737 nonrouteable addresses
356329874Sasomers	ADDR="192.0.2.2"
357329874Sasomers	MASK="24"
358329874Sasomers	MAC="00:11:22:33:44:55"
359329874Sasomers
360329874Sasomers	TAP0=`get_tap`
361329874Sasomers	TAP1=`get_tap`
362329874Sasomers	LAGG=`get_lagg`
363329874Sasomers
364329874Sasomers	# Create the lagg
365329874Sasomers	ifconfig $TAP0 up
366329874Sasomers	ifconfig $TAP1 up
367329874Sasomers	atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
368329874Sasomers		${ADDR}/${MASK}
369329874Sasomers
370329874Sasomers	# Down the lagg
371329874Sasomers	ifconfig $LAGG down
372329874Sasomers	atf_check -o not-match:"flags=.*\<UP\>" ifconfig $LAGG
373329874Sasomers	atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP0
374329874Sasomers	atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP1
375329874Sasomers	# Up the lagg again
376329874Sasomers	ifconfig $LAGG up
377329874Sasomers	atf_check -o match:"flags=.*\<UP\>" ifconfig $LAGG
378329874Sasomers	atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP0
379329874Sasomers	atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP1
380329874Sasomers
381329874Sasomers	# Check that no members have acquired an IPv6 link-local address by
382329874Sasomers	# virtue of being upped. IPv6 link-local addresses should never be
383329874Sasomers	# merged in any way to prevent scope violation.
384329874Sasomers	atf_check -o not-match:"inet6 fe80:" ifconfig $TAP0
385329874Sasomers	atf_check -o not-match:"inet6 fe80:" ifconfig $TAP1
386329874Sasomers}
387329874Sasomersupdown_cleanup()
388329874Sasomers{
389329874Sasomers	cleanup_tap_and_lagg
390329874Sasomers}
391329874Sasomers
392329874Sasomers# Check for lock-order reversals.  For best results, this test should be run
393329874Sasomers# last.
394329874Sasomersatf_test_case witness
395329874Sasomerswitness_head()
396329874Sasomers{
397329874Sasomers	atf_set "descr" "Check witness(4) for lock-order reversals in if_lagg"
398329874Sasomers}
399329874Sasomerswitness_body()
400329874Sasomers{
401329874Sasomers	if [ `sysctl -n debug.witness.watch` -ne 1 ]; then
402329874Sasomers		atf_skip "witness(4) is not enabled"
403329874Sasomers	fi
404329874Sasomers	if `sysctl -n debug.witness.badstacks | grep -q 'at lagg_'`; then
405329874Sasomers		sysctl debug.witness.badstacks
406329874Sasomers		atf_fail "Lock-order reversals involving if_lagg.c detected"
407329874Sasomers	fi
408329874Sasomers}
409329874Sasomers
410329874Sasomersatf_init_test_cases()
411329874Sasomers{
412329874Sasomers	atf_add_test_case create
413329874Sasomers	atf_add_test_case create_destroy_stress
414329874Sasomers	atf_add_test_case lacp_linkstate_destroy_stress
415329874Sasomers	atf_add_test_case set_ether
416329874Sasomers	atf_add_test_case status_stress
417329874Sasomers	atf_add_test_case up_destroy_stress
418329874Sasomers	atf_add_test_case updown
419329874Sasomers	# For best results, keep the witness test last
420329874Sasomers	atf_add_test_case witness
421329874Sasomers}
422329874Sasomers
423329874Sasomers
424329874Sasomers# Creates a new tap(4) interface, registers it for cleanup, and echoes it
425329874Sasomersget_tap()
426329874Sasomers{
427329874Sasomers	local TAPN=0
428329874Sasomers	while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
429329874Sasomers		if [ "$TAPN" -ge 8 ]; then
430329874Sasomers			atf_skip "Could not create a tap(4) interface"
431329874Sasomers		else
432329874Sasomers			TAPN=$(($TAPN + 1))
433329874Sasomers		fi
434329874Sasomers	done
435329874Sasomers	local TAPD=tap${TAPN}
436329874Sasomers	# Record the TAP device so we can clean it up later
437329874Sasomers	echo ${TAPD} >> "devices_to_cleanup"
438329874Sasomers	echo ${TAPD}
439329874Sasomers}
440329874Sasomers
441329874Sasomers# Creates a new lagg(4) interface, registers it for cleanup, and echoes it
442329874Sasomersget_lagg()
443329874Sasomers{
444329874Sasomers	local LAGGN=0
445329874Sasomers	while ! ifconfig lagg${LAGGN} create > /dev/null 2>&1; do
446329874Sasomers		if [ "$LAGGN" -ge 8 ]; then
447329874Sasomers			atf_skip "Could not create a lagg(4) interface"
448329874Sasomers		else
449329874Sasomers			LAGGN=$(($LAGGN + 1))
450329874Sasomers		fi
451329874Sasomers	done
452329874Sasomers	local LAGGD=lagg${LAGGN}
453329874Sasomers	# Record the lagg device so we can clean it up later
454329874Sasomers	echo ${LAGGD} >> "devices_to_cleanup"
455329874Sasomers	echo ${LAGGD}
456329874Sasomers}
457329874Sasomers
458329874Sasomerscleanup_tap_and_lagg()
459329874Sasomers{
460329874Sasomers	local DEV
461329874Sasomers
462329874Sasomers	for DEV in `cat "devices_to_cleanup"`; do
463329874Sasomers		ifconfig ${DEV} destroy
464329874Sasomers	done
465329874Sasomers	true
466329874Sasomers}
467