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