Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/net/if_lagg_test.sh
39586 views
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
33
atf_test_case create cleanup
34
create_head()
35
{
36
atf_set "descr" "Create a lagg and assign an address"
37
atf_set "require.user" "root"
38
}
39
create_body()
40
{
41
local TAP0 TAP1 LAGG MAC
42
43
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
44
ADDR="192.0.2.2"
45
MASK="24"
46
47
TAP0=`get_tap`
48
TAP1=`get_tap`
49
LAGG=`get_lagg`
50
51
# Create the lagg
52
ifconfig $TAP0 up
53
ifconfig $TAP1 up
54
atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
55
${ADDR}/${MASK}
56
atf_check -o match:"inet ${ADDR}" ifconfig $LAGG
57
atf_check -o match:"laggport: ${TAP0}" ifconfig $LAGG
58
atf_check -o match:"laggport: ${TAP1}" ifconfig $LAGG
59
60
# Check that all members have the same MAC
61
MAC=`ifconfig $LAGG | awk '/ether/ {print $2}'`
62
atf_check -o match:"ether ${MAC}" ifconfig $TAP0
63
atf_check -o match:"ether ${MAC}" ifconfig $TAP1
64
65
# Check that no members have an IPv6 link-local address. IPv6
66
# link-local addresses should never be merged in any way to prevent
67
# scope violation.
68
atf_check -o not-match:"inet6 fe80:" ifconfig $TAP0
69
atf_check -o not-match:"inet6 fe80:" ifconfig $TAP1
70
}
71
create_cleanup()
72
{
73
cleanup_tap_and_lagg
74
}
75
76
atf_test_case status_stress cleanup
77
status_stress_head()
78
{
79
atf_set "descr" "Simultaneously query a lagg while also creating or destroying it."
80
atf_set "require.user" "root"
81
}
82
status_stress_body()
83
{
84
local TAP0 TAP1 LAGG MAC
85
86
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
87
ADDR="192.0.2.2"
88
MASK="24"
89
90
TAP0=`get_tap`
91
TAP1=`get_tap`
92
TAP2=`get_tap`
93
TAP3=`get_tap`
94
LAGG=`get_lagg`
95
96
# Up the lagg's children
97
ifconfig $TAP0 inet6 ifdisabled up
98
ifconfig $TAP1 inet6 ifdisabled up
99
ifconfig $TAP2 inet6 ifdisabled up
100
ifconfig $TAP3 inet6 ifdisabled up
101
102
# First thread: create and destroy the lagg
103
while true; do
104
ifconfig $LAGG destroy 2>&1
105
ifconfig $LAGG create 2>/dev/null
106
ifconfig $LAGG inet6 ifdisabled
107
ifconfig $LAGG up laggport $TAP0 laggport $TAP1 laggport $TAP2\
108
laggport $TAP3 ${ADDR}/${MASK} 2>/dev/null
109
echo -n . >> creator_count.txt
110
done &
111
CREATOR_PID=$!
112
113
# Second thread: Query the lagg's status
114
while true; do
115
ifconfig -am 2> /dev/null > /dev/null
116
echo -n . >> querier_count.txt
117
done &
118
QUERIER_PID=$!
119
120
sleep 60
121
kill $CREATOR_PID
122
kill $QUERIER_PID
123
echo "Created the lagg `stat -f %z creator_count.txt` times."
124
echo "Queried its status `stat -f %z querier_count.txt` times"
125
}
126
status_stress_cleanup()
127
{
128
cleanup_tap_and_lagg
129
}
130
131
atf_test_case create_destroy_stress cleanup
132
create_destroy_stress_head()
133
{
134
atf_set "descr" "Simultaneously create and destroy a lagg"
135
atf_set "require.user" "root"
136
}
137
create_destroy_stress_body()
138
{
139
local TAP0 TAP1 LAGG MAC
140
141
TAP0=`get_tap`
142
TAP1=`get_tap`
143
TAP2=`get_tap`
144
TAP3=`get_tap`
145
LAGG=`get_lagg`
146
147
# Up the lagg's children
148
ifconfig $TAP0 inet6 ifdisabled up
149
ifconfig $TAP1 inet6 ifdisabled up
150
ifconfig $TAP2 inet6 ifdisabled up
151
ifconfig $TAP3 inet6 ifdisabled up
152
153
# First thread: create the lagg
154
while true; do
155
ifconfig $LAGG create 2>/dev/null && \
156
echo -n . >> creator_count.txt
157
done &
158
CREATOR_PID=$!
159
160
# Second thread: destroy the lagg
161
while true; do
162
ifconfig $LAGG destroy 2>/dev/null && \
163
echo -n . >> destroyer_count.txt
164
done &
165
DESTROYER_PID=$!
166
167
sleep 60
168
kill $CREATOR_PID
169
kill $DESTROYER_PID
170
echo "Created the lagg `stat -f %z creator_count.txt` times."
171
echo "Destroyed it `stat -f %z destroyer_count.txt` times."
172
}
173
create_destroy_stress_cleanup()
174
{
175
cleanup_tap_and_lagg
176
}
177
178
# This test regresses a panic that is particular to LACP. If the child's link
179
# state changes while the lagg is being destroyed, lacp_linkstate can
180
# use-after-free. The problem is compounded by two factors:
181
# 1) In SpectraBSD, downing the parent will also down the child
182
# 2) The cxgbe driver will show the link state as "no carrier" as soon as you
183
# down the interface.
184
# TeamTrack: P2_30328
185
atf_test_case lacp_linkstate_destroy_stress cleanup
186
lacp_linkstate_destroy_stress_head()
187
{
188
atf_set "descr" "Simultaneously destroy an LACP lagg and change its childrens link states"
189
atf_set "require.user" "root"
190
}
191
lacp_linkstate_destroy_stress_body()
192
{
193
local TAP0 TAP1 LAGG MAC SRCDIR
194
195
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
196
ADDR="192.0.2.2"
197
MASK="24"
198
# ifconfig takes about 10ms to run. To increase race coverage,
199
# randomly delay the two commands relative to each other by 5ms either
200
# way.
201
MEAN_SLEEP_SECONDS=.005
202
MAX_SLEEP_USECS=10000
203
204
TAP0=`get_tap`
205
TAP1=`get_tap`
206
LAGG=`get_lagg`
207
208
# Up the lagg's children
209
ifconfig $TAP0 inet6 ifdisabled up
210
ifconfig $TAP1 inet6 ifdisabled up
211
212
SRCDIR=$( atf_get_srcdir )
213
while true; do
214
ifconfig $LAGG inet6 ifdisabled
215
# We must open the tap devices to change their link states
216
cat /dev/$TAP0 > /dev/null &
217
CAT0_PID=$!
218
cat /dev/$TAP1 > /dev/null &
219
CAT1_PID=$!
220
ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
221
${ADDR}/${MASK} 2> /dev/null &&
222
{ sleep ${MEAN_SLEEP_SECONDS} && \
223
kill $CAT0_PID &&
224
kill $CAT1_PID &&
225
echo -n . >> linkstate_count.txt ; } &
226
{ ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \
227
ifconfig $LAGG destroy &&
228
echo -n . >> destroy_count.txt ; } &
229
wait
230
ifconfig $LAGG create
231
done &
232
LOOP_PID=$!
233
234
sleep 60
235
kill $LOOP_PID
236
echo "Disconnected the children `stat -f %z linkstate_count.txt` times."
237
echo "Destroyed the lagg `stat -f %z destroy_count.txt` times."
238
}
239
lacp_linkstate_destroy_stress_cleanup()
240
{
241
cleanup_tap_and_lagg
242
}
243
244
atf_test_case up_destroy_stress cleanup
245
up_destroy_stress_head()
246
{
247
atf_set "descr" "Simultaneously up and destroy a lagg"
248
atf_set "require.user" "root"
249
}
250
up_destroy_stress_body()
251
{
252
local TAP0 TAP1 LAGG MAC SRCDIR
253
254
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
255
ADDR="192.0.2.2"
256
MASK="24"
257
# ifconfig takes about 10ms to run. To increase race coverage,
258
# randomly delay the two commands relative to each other by 5ms either
259
# way.
260
MEAN_SLEEP_SECONDS=.005
261
MAX_SLEEP_USECS=10000
262
263
TAP0=`get_tap`
264
TAP1=`get_tap`
265
TAP2=`get_tap`
266
TAP3=`get_tap`
267
LAGG=`get_lagg`
268
269
# Up the lagg's children
270
ifconfig $TAP0 inet6 ifdisabled up
271
ifconfig $TAP1 inet6 ifdisabled up
272
ifconfig $TAP2 inet6 ifdisabled up
273
ifconfig $TAP3 inet6 ifdisabled up
274
275
SRCDIR=$( atf_get_srcdir )
276
while true; do
277
ifconfig $LAGG inet6 ifdisabled
278
{ sleep ${MEAN_SLEEP_SECONDS} && \
279
ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
280
laggport $TAP2 laggport $TAP3 \
281
${ADDR}/${MASK} 2> /dev/null &&
282
echo -n . >> up_count.txt ; } &
283
{ ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \
284
ifconfig $LAGG destroy &&
285
echo -n . >> destroy_count.txt ; } &
286
wait
287
ifconfig $LAGG create
288
done &
289
LOOP_PID=$!
290
291
sleep 60
292
kill $LOOP_PID
293
echo "Upped the lagg `stat -f %z up_count.txt` times."
294
echo "Destroyed it `stat -f %z destroy_count.txt` times."
295
}
296
up_destroy_stress_cleanup()
297
{
298
cleanup_tap_and_lagg
299
}
300
301
atf_test_case set_ether cleanup
302
set_ether_head()
303
{
304
atf_set "descr" "Set a lagg's ethernet address"
305
atf_set "require.user" "root"
306
}
307
set_ether_body()
308
{
309
local TAP0 TAP1 LAGG MAC
310
311
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
312
ADDR="192.0.2.2"
313
MASK="24"
314
MAC="00:11:22:33:44:55"
315
316
TAP0=`get_tap`
317
TAP1=`get_tap`
318
LAGG=`get_lagg`
319
320
# Create the lagg
321
ifconfig $TAP0 up
322
ifconfig $TAP1 up
323
atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
324
${ADDR}/${MASK}
325
326
# Change the lagg's ethernet address
327
atf_check ifconfig $LAGG ether ${MAC}
328
329
# Check that all members have the same MAC
330
atf_check -o match:"ether ${MAC}" ifconfig $LAGG
331
atf_check -o match:"ether ${MAC}" ifconfig $TAP0
332
atf_check -o match:"ether ${MAC}" ifconfig $TAP1
333
}
334
set_ether_cleanup()
335
{
336
cleanup_tap_and_lagg
337
}
338
339
atf_test_case updown cleanup
340
updown_head()
341
{
342
atf_set "descr" "upping or downing a lagg ups or downs its children"
343
atf_set "require.user" "root"
344
}
345
updown_body()
346
{
347
local TAP0 TAP1 LAGG MAC
348
349
# Configure the lagg interface to use an RFC5737 nonrouteable addresses
350
ADDR="192.0.2.2"
351
MASK="24"
352
MAC="00:11:22:33:44:55"
353
354
TAP0=`get_tap`
355
TAP1=`get_tap`
356
LAGG=`get_lagg`
357
358
# Create the lagg
359
ifconfig $TAP0 up
360
ifconfig $TAP1 up
361
atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \
362
${ADDR}/${MASK}
363
364
# Down the lagg
365
ifconfig $LAGG down
366
atf_check -o not-match:"flags=.*\<UP\>" ifconfig $LAGG
367
atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP0
368
atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP1
369
# Up the lagg again
370
ifconfig $LAGG up
371
atf_check -o match:"flags=.*\<UP\>" ifconfig $LAGG
372
atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP0
373
atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP1
374
375
# Check that no members have acquired an IPv6 link-local address by
376
# virtue of being upped. IPv6 link-local addresses should never be
377
# merged in any way to prevent scope violation.
378
atf_check -o not-match:"inet6 fe80:" ifconfig $TAP0
379
atf_check -o not-match:"inet6 fe80:" ifconfig $TAP1
380
}
381
updown_cleanup()
382
{
383
cleanup_tap_and_lagg
384
}
385
386
# Check for lock-order reversals. For best results, this test should be run
387
# last.
388
atf_test_case witness
389
witness_head()
390
{
391
atf_set "descr" "Check witness(4) for lock-order reversals in if_lagg"
392
}
393
witness_body()
394
{
395
if [ "$(atf_config_get ci false)" = "true" ]; then
396
atf_skip "https://bugs.freebsd.org/244163 and https://bugs.freebsd.org/251726"
397
fi
398
if [ `sysctl -n debug.witness.watch` -ne 1 ]; then
399
atf_skip "witness(4) is not enabled"
400
fi
401
if `sysctl -n debug.witness.badstacks | grep -q 'at lagg_'`; then
402
sysctl debug.witness.badstacks
403
atf_fail "Lock-order reversals involving if_lagg.c detected"
404
fi
405
}
406
407
atf_init_test_cases()
408
{
409
atf_add_test_case create
410
atf_add_test_case create_destroy_stress
411
atf_add_test_case lacp_linkstate_destroy_stress
412
atf_add_test_case set_ether
413
atf_add_test_case status_stress
414
atf_add_test_case up_destroy_stress
415
atf_add_test_case updown
416
# For best results, keep the witness test last
417
atf_add_test_case witness
418
}
419
420
421
# Creates a new tap(4) interface, registers it for cleanup, and echoes it
422
get_tap()
423
{
424
local TAPN=0
425
while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
426
if [ "$TAPN" -ge 8 ]; then
427
atf_skip "Could not create a tap(4) interface"
428
else
429
TAPN=$(($TAPN + 1))
430
fi
431
done
432
local TAPD=tap${TAPN}
433
# Record the TAP device so we can clean it up later
434
echo ${TAPD} >> "devices_to_cleanup"
435
echo ${TAPD}
436
}
437
438
# Creates a new lagg(4) interface, registers it for cleanup, and echoes it
439
get_lagg()
440
{
441
local LAGGN=0
442
while ! ifconfig lagg${LAGGN} create > /dev/null 2>&1; do
443
if [ "$LAGGN" -ge 8 ]; then
444
atf_skip "Could not create a lagg(4) interface"
445
else
446
LAGGN=$(($LAGGN + 1))
447
fi
448
done
449
local LAGGD=lagg${LAGGN}
450
# Record the lagg device so we can clean it up later
451
echo ${LAGGD} >> "devices_to_cleanup"
452
echo ${LAGGD}
453
}
454
455
cleanup_tap_and_lagg()
456
{
457
local DEV
458
459
for DEV in `cat "devices_to_cleanup"`; do
460
ifconfig ${DEV} destroy
461
done
462
true
463
}
464
465