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