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 if [ "$(atf_config_get ci false)" = "true" ] && \ 197 [ "$(uname -p)" = "i386" ]; then 198 atf_skip "https://bugs.freebsd.org/244168" 199 fi 200 201 local TAP0 TAP1 LAGG MAC SRCDIR 202 203 # Configure the lagg interface to use an RFC5737 nonrouteable addresses 204 ADDR="192.0.2.2" 205 MASK="24" 206 # ifconfig takes about 10ms to run. To increase race coverage, 207 # randomly delay the two commands relative to each other by 5ms either 208 # way. 209 MEAN_SLEEP_SECONDS=.005 210 MAX_SLEEP_USECS=10000 211 212 TAP0=`get_tap` 213 TAP1=`get_tap` 214 LAGG=`get_lagg` 215 216 # Up the lagg's children 217 ifconfig $TAP0 inet6 ifdisabled up 218 ifconfig $TAP1 inet6 ifdisabled up 219 220 SRCDIR=$( atf_get_srcdir ) 221 while true; do 222 ifconfig $LAGG inet6 ifdisabled 223 # We must open the tap devices to change their link states 224 cat /dev/$TAP0 > /dev/null & 225 CAT0_PID=$! 226 cat /dev/$TAP1 > /dev/null & 227 CAT1_PID=$! 228 ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \ 229 ${ADDR}/${MASK} 2> /dev/null && 230 { sleep ${MEAN_SLEEP_SECONDS} && \ 231 kill $CAT0_PID && 232 kill $CAT1_PID && 233 echo -n . >> linkstate_count.txt ; } & 234 { ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \ 235 ifconfig $LAGG destroy && 236 echo -n . >> destroy_count.txt ; } & 237 wait 238 ifconfig $LAGG create 239 done & 240 LOOP_PID=$! 241 242 sleep 60 243 kill $LOOP_PID 244 echo "Disconnected the children `stat -f %z linkstate_count.txt` times." 245 echo "Destroyed the lagg `stat -f %z destroy_count.txt` times." 246} 247lacp_linkstate_destroy_stress_cleanup() 248{ 249 cleanup_tap_and_lagg 250} 251 252atf_test_case up_destroy_stress cleanup 253up_destroy_stress_head() 254{ 255 atf_set "descr" "Simultaneously up and destroy a lagg" 256 atf_set "require.user" "root" 257} 258up_destroy_stress_body() 259{ 260 local TAP0 TAP1 LAGG MAC SRCDIR 261 262 atf_skip "Skipping this test because it panics the machine fairly often" 263 264 # Configure the lagg interface to use an RFC5737 nonrouteable addresses 265 ADDR="192.0.2.2" 266 MASK="24" 267 # ifconfig takes about 10ms to run. To increase race coverage, 268 # randomly delay the two commands relative to each other by 5ms either 269 # way. 270 MEAN_SLEEP_SECONDS=.005 271 MAX_SLEEP_USECS=10000 272 273 TAP0=`get_tap` 274 TAP1=`get_tap` 275 TAP2=`get_tap` 276 TAP3=`get_tap` 277 LAGG=`get_lagg` 278 279 # Up the lagg's children 280 ifconfig $TAP0 inet6 ifdisabled up 281 ifconfig $TAP1 inet6 ifdisabled up 282 ifconfig $TAP2 inet6 ifdisabled up 283 ifconfig $TAP3 inet6 ifdisabled up 284 285 SRCDIR=$( atf_get_srcdir ) 286 while true; do 287 ifconfig $LAGG inet6 ifdisabled 288 { sleep ${MEAN_SLEEP_SECONDS} && \ 289 ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \ 290 laggport $TAP2 laggport $TAP3 \ 291 ${ADDR}/${MASK} 2> /dev/null && 292 echo -n . >> up_count.txt ; } & 293 { ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \ 294 ifconfig $LAGG destroy && 295 echo -n . >> destroy_count.txt ; } & 296 wait 297 ifconfig $LAGG create 298 done & 299 LOOP_PID=$! 300 301 sleep 60 302 kill $LOOP_PID 303 echo "Upped the lagg `stat -f %z up_count.txt` times." 304 echo "Destroyed it `stat -f %z destroy_count.txt` times." 305} 306up_destroy_stress_cleanup() 307{ 308 cleanup_tap_and_lagg 309} 310 311atf_test_case set_ether cleanup 312set_ether_head() 313{ 314 atf_set "descr" "Set a lagg's ethernet address" 315 atf_set "require.user" "root" 316} 317set_ether_body() 318{ 319 local TAP0 TAP1 LAGG MAC 320 321 # Configure the lagg interface to use an RFC5737 nonrouteable addresses 322 ADDR="192.0.2.2" 323 MASK="24" 324 MAC="00:11:22:33:44:55" 325 326 TAP0=`get_tap` 327 TAP1=`get_tap` 328 LAGG=`get_lagg` 329 330 # Create the lagg 331 ifconfig $TAP0 up 332 ifconfig $TAP1 up 333 atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \ 334 ${ADDR}/${MASK} 335 336 # Change the lagg's ethernet address 337 atf_check ifconfig $LAGG ether ${MAC} 338 339 # Check that all members have the same MAC 340 atf_check -o match:"ether ${MAC}" ifconfig $LAGG 341 atf_check -o match:"ether ${MAC}" ifconfig $TAP0 342 atf_check -o match:"ether ${MAC}" ifconfig $TAP1 343} 344set_ether_cleanup() 345{ 346 cleanup_tap_and_lagg 347} 348 349atf_test_case updown cleanup 350updown_head() 351{ 352 atf_set "descr" "upping or downing a lagg ups or downs its children" 353 atf_set "require.user" "root" 354} 355updown_body() 356{ 357 local TAP0 TAP1 LAGG MAC 358 359 atf_expect_fail "PR 226144 Upping a lagg interrface should automatically up its children" 360 # Configure the lagg interface to use an RFC5737 nonrouteable addresses 361 ADDR="192.0.2.2" 362 MASK="24" 363 MAC="00:11:22:33:44:55" 364 365 TAP0=`get_tap` 366 TAP1=`get_tap` 367 LAGG=`get_lagg` 368 369 # Create the lagg 370 ifconfig $TAP0 up 371 ifconfig $TAP1 up 372 atf_check ifconfig $LAGG up laggport $TAP0 laggport $TAP1 \ 373 ${ADDR}/${MASK} 374 375 # Down the lagg 376 ifconfig $LAGG down 377 atf_check -o not-match:"flags=.*\<UP\>" ifconfig $LAGG 378 atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP0 379 atf_check -o not-match:"flags=.*\<UP\>" ifconfig $TAP1 380 # Up the lagg again 381 ifconfig $LAGG up 382 atf_check -o match:"flags=.*\<UP\>" ifconfig $LAGG 383 atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP0 384 atf_check -o match:"flags=.*\<UP\>" ifconfig $TAP1 385 386 # Check that no members have acquired an IPv6 link-local address by 387 # virtue of being upped. IPv6 link-local addresses should never be 388 # merged in any way to prevent scope violation. 389 atf_check -o not-match:"inet6 fe80:" ifconfig $TAP0 390 atf_check -o not-match:"inet6 fe80:" ifconfig $TAP1 391} 392updown_cleanup() 393{ 394 cleanup_tap_and_lagg 395} 396 397# Check for lock-order reversals. For best results, this test should be run 398# last. 399atf_test_case witness 400witness_head() 401{ 402 atf_set "descr" "Check witness(4) for lock-order reversals in if_lagg" 403} 404witness_body() 405{ 406 if [ "$(atf_config_get ci false)" = "true" ] && \ 407 [ "$(uname -p)" = "i386" ]; then 408 atf_skip "https://bugs.freebsd.org/244163" 409 fi 410 if [ `sysctl -n debug.witness.watch` -ne 1 ]; then 411 atf_skip "witness(4) is not enabled" 412 fi 413 if `sysctl -n debug.witness.badstacks | grep -q 'at lagg_'`; then 414 sysctl debug.witness.badstacks 415 atf_fail "Lock-order reversals involving if_lagg.c detected" 416 fi 417} 418 419atf_init_test_cases() 420{ 421 atf_add_test_case create 422 atf_add_test_case create_destroy_stress 423 atf_add_test_case lacp_linkstate_destroy_stress 424 atf_add_test_case set_ether 425 atf_add_test_case status_stress 426 atf_add_test_case up_destroy_stress 427 atf_add_test_case updown 428 # For best results, keep the witness test last 429 atf_add_test_case witness 430} 431 432 433# Creates a new tap(4) interface, registers it for cleanup, and echoes it 434get_tap() 435{ 436 local TAPN=0 437 while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do 438 if [ "$TAPN" -ge 8 ]; then 439 atf_skip "Could not create a tap(4) interface" 440 else 441 TAPN=$(($TAPN + 1)) 442 fi 443 done 444 local TAPD=tap${TAPN} 445 # Record the TAP device so we can clean it up later 446 echo ${TAPD} >> "devices_to_cleanup" 447 echo ${TAPD} 448} 449 450# Creates a new lagg(4) interface, registers it for cleanup, and echoes it 451get_lagg() 452{ 453 local LAGGN=0 454 while ! ifconfig lagg${LAGGN} create > /dev/null 2>&1; do 455 if [ "$LAGGN" -ge 8 ]; then 456 atf_skip "Could not create a lagg(4) interface" 457 else 458 LAGGN=$(($LAGGN + 1)) 459 fi 460 done 461 local LAGGD=lagg${LAGGN} 462 # Record the lagg device so we can clean it up later 463 echo ${LAGGD} >> "devices_to_cleanup" 464 echo ${LAGGD} 465} 466 467cleanup_tap_and_lagg() 468{ 469 local DEV 470 471 for DEV in `cat "devices_to_cleanup"`; do 472 ifconfig ${DEV} destroy 473 done 474 true 475} 476