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