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