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 34# Outline: 35# For each cloned interface type, do three tests 36# 1) Create and destroy it 37# 2) Create, up, and destroy it 38# 3) Create, disable IPv6 auto address assignment, up, and destroy it 39 40TESTLEN=10 # seconds 41 42atf_test_case faith_stress cleanup 43faith_stress_head() 44{ 45 atf_set "descr" "Simultaneously create and destroy a faith(4)" 46 atf_set "require.user" "root" 47} 48faith_stress_body() 49{ 50 do_stress "faith" 51} 52faith_stress_cleanup() 53{ 54 cleanup_ifaces 55} 56 57atf_test_case faith_up_stress cleanup 58faith_up_stress_head() 59{ 60 atf_set "descr" "Simultaneously up and destroy a faith(4)" 61 atf_set "require.user" "root" 62} 63faith_up_stress_body() 64{ 65 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 66 do_up_stress "faith" "" "" 67} 68faith_up_stress_cleanup() 69{ 70 cleanup_ifaces 71} 72 73atf_test_case faith_ipv6_up_stress cleanup 74faith_ipv6_up_stress_head() 75{ 76 atf_set "descr" "Simultaneously up and destroy a faith(4) with IPv6" 77 atf_set "require.user" "root" 78} 79faith_ipv6_up_stress_body() 80{ 81 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 82 do_up_stress "faith" "6" "" 83} 84faith_ipv6_up_stress_cleanup() 85{ 86 cleanup_ifaces 87} 88 89atf_test_case gif_stress cleanup 90gif_stress_head() 91{ 92 atf_set "descr" "Simultaneously create and destroy a gif(4)" 93 atf_set "require.user" "root" 94} 95gif_stress_body() 96{ 97 do_stress "gif" 98} 99gif_stress_cleanup() 100{ 101 cleanup_ifaces 102} 103 104atf_test_case gif_up_stress cleanup 105gif_up_stress_head() 106{ 107 atf_set "descr" "Simultaneously up and destroy a gif(4)" 108 atf_set "require.user" "root" 109} 110gif_up_stress_body() 111{ 112 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 113 do_up_stress "gif" "" "p2p" 114} 115gif_up_stress_cleanup() 116{ 117 cleanup_ifaces 118} 119 120atf_test_case gif_ipv6_up_stress cleanup 121gif_ipv6_up_stress_head() 122{ 123 atf_set "descr" "Simultaneously up and destroy a gif(4) with IPv6" 124 atf_set "require.user" "root" 125} 126gif_ipv6_up_stress_body() 127{ 128 atf_skip "Quickly panics: rt_tables_get_rnh_ptr: fam out of bounds." 129 do_up_stress "gif" "6" "p2p" 130} 131gif_ipv6_up_stress_cleanup() 132{ 133 cleanup_ifaces 134} 135 136atf_test_case lo_stress cleanup 137lo_stress_head() 138{ 139 atf_set "descr" "Simultaneously create and destroy an lo(4)" 140 atf_set "require.user" "root" 141} 142lo_stress_body() 143{ 144 do_stress "lo" 145} 146lo_stress_cleanup() 147{ 148 cleanup_ifaces 149} 150 151atf_test_case lo_up_stress cleanup 152lo_up_stress_head() 153{ 154 atf_set "descr" "Simultaneously up and destroy an lo(4)" 155 atf_set "require.user" "root" 156} 157lo_up_stress_body() 158{ 159 atf_skip "Quickly panics: GPF in rtsock_routemsg" 160 do_up_stress "lo" "" "" 161} 162lo_up_stress_cleanup() 163{ 164 cleanup_ifaces 165} 166 167atf_test_case lo_ipv6_up_stress cleanup 168lo_ipv6_up_stress_head() 169{ 170 atf_set "descr" "Simultaneously up and destroy an lo(4) with IPv6" 171 atf_set "require.user" "root" 172} 173lo_ipv6_up_stress_body() 174{ 175 atf_skip "Quickly panics: page fault in rtsock_addrmsg" 176 do_up_stress "lo" "6" "" 177} 178lo_ipv6_up_stress_cleanup() 179{ 180 cleanup_ifaces 181} 182 183atf_test_case tap_stress cleanup 184tap_stress_head() 185{ 186 atf_set "descr" "Simultaneously create and destroy a tap(4)" 187 atf_set "require.user" "root" 188} 189tap_stress_body() 190{ 191 do_stress "tap" 192} 193tap_stress_cleanup() 194{ 195 cleanup_ifaces 196} 197 198atf_test_case tap_up_stress cleanup 199tap_up_stress_head() 200{ 201 atf_set "descr" "Simultaneously up and destroy a tap(4)" 202 atf_set "require.user" "root" 203} 204tap_up_stress_body() 205{ 206 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 207 do_up_stress "tap" "" "" 208} 209tap_up_stress_cleanup() 210{ 211 cleanup_ifaces 212} 213 214atf_test_case tap_ipv6_up_stress cleanup 215tap_ipv6_up_stress_head() 216{ 217 atf_set "descr" "Simultaneously up and destroy a tap(4) with IPv6" 218 atf_set "require.user" "root" 219} 220tap_ipv6_up_stress_body() 221{ 222 atf_skip "Quickly panics: if_delmulti_locked: inconsistent ifp 0xfffff80150e44000" 223 do_up_stress "tap" "6" "" 224} 225tap_ipv6_up_stress_cleanup() 226{ 227 cleanup_ifaces 228} 229 230atf_test_case tun_stress cleanup 231tun_stress_head() 232{ 233 atf_set "descr" "Simultaneously create and destroy a tun(4)" 234 atf_set "require.user" "root" 235} 236tun_stress_body() 237{ 238 do_stress "tun" 239} 240tun_stress_cleanup() 241{ 242 cleanup_ifaces 243} 244 245atf_test_case tun_up_stress cleanup 246tun_up_stress_head() 247{ 248 atf_set "descr" "Simultaneously up and destroy a tun(4)" 249 atf_set "require.user" "root" 250} 251tun_up_stress_body() 252{ 253 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 254 do_up_stress "tun" "" "p2p" 255} 256tun_up_stress_cleanup() 257{ 258 cleanup_ifaces 259} 260 261atf_test_case tun_ipv6_up_stress cleanup 262tun_ipv6_up_stress_head() 263{ 264 atf_set "descr" "Simultaneously up and destroy a tun(4) with IPv6" 265 atf_set "require.user" "root" 266} 267tun_ipv6_up_stress_body() 268{ 269 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 270 do_up_stress "tun" "6" "p2p" 271} 272tun_ipv6_up_stress_cleanup() 273{ 274 cleanup_ifaces 275} 276 277atf_test_case vlan_stress cleanup 278vlan_stress_head() 279{ 280 atf_set "descr" "Simultaneously create and destroy a vlan(4)" 281 atf_set "require.user" "root" 282} 283vlan_stress_body() 284{ 285 do_stress "vlan" 286} 287vlan_stress_cleanup() 288{ 289 cleanup_ifaces 290} 291 292atf_test_case vlan_up_stress cleanup 293vlan_up_stress_head() 294{ 295 atf_set "descr" "Simultaneously up and destroy a vlan(4)" 296 atf_set "require.user" "root" 297} 298vlan_up_stress_body() 299{ 300 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 301 do_up_stress "vlan" "" "" 302} 303vlan_up_stress_cleanup() 304{ 305 cleanup_ifaces 306} 307 308atf_test_case vlan_ipv6_up_stress cleanup 309vlan_ipv6_up_stress_head() 310{ 311 atf_set "descr" "Simultaneously up and destroy a vlan(4) with IPv6" 312 atf_set "require.user" "root" 313} 314vlan_ipv6_up_stress_body() 315{ 316 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 317 do_up_stress "vlan" "6" "" 318} 319vlan_ipv6_up_stress_cleanup() 320{ 321 cleanup_ifaces 322} 323 324atf_test_case vmnet_stress cleanup 325vmnet_stress_head() 326{ 327 atf_set "descr" "Simultaneously create and destroy a vmnet(4)" 328 atf_set "require.user" "root" 329} 330vmnet_stress_body() 331{ 332 do_stress "vmnet" 333} 334vmnet_stress_cleanup() 335{ 336 cleanup_ifaces 337} 338 339atf_test_case vmnet_up_stress cleanup 340vmnet_up_stress_head() 341{ 342 atf_set "descr" "Simultaneously up and destroy a vmnet(4)" 343 atf_set "require.user" "root" 344} 345vmnet_up_stress_body() 346{ 347 do_up_stress "vmnet" "" "" 348} 349vmnet_up_stress_cleanup() 350{ 351 cleanup_ifaces 352} 353 354atf_test_case vmnet_ipv6_up_stress cleanup 355vmnet_ipv6_up_stress_head() 356{ 357 atf_set "descr" "Simultaneously up and destroy a vmnet(4) with IPv6" 358 atf_set "require.user" "root" 359} 360vmnet_ipv6_up_stress_body() 361{ 362 atf_skip "Quickly panics: if_freemulti: protospec not NULL" 363 do_up_stress "vmnet" "6" "" 364} 365vmnet_ipv6_up_stress_cleanup() 366{ 367 cleanup_ifaces 368} 369 370atf_init_test_cases() 371{ 372 # TODO: add epair(4) tests, which need a different syntax 373 atf_add_test_case faith_ipv6_up_stress 374 atf_add_test_case faith_stress 375 atf_add_test_case faith_up_stress 376 atf_add_test_case gif_ipv6_up_stress 377 atf_add_test_case gif_stress 378 atf_add_test_case gif_up_stress 379 # Don't test lagg; it has its own test program 380 atf_add_test_case lo_ipv6_up_stress 381 atf_add_test_case lo_stress 382 atf_add_test_case lo_up_stress 383 atf_add_test_case tap_ipv6_up_stress 384 atf_add_test_case tap_stress 385 atf_add_test_case tap_up_stress 386 atf_add_test_case tun_ipv6_up_stress 387 atf_add_test_case tun_stress 388 atf_add_test_case tun_up_stress 389 atf_add_test_case vlan_ipv6_up_stress 390 atf_add_test_case vlan_stress 391 atf_add_test_case vlan_up_stress 392 atf_add_test_case vmnet_ipv6_up_stress 393 atf_add_test_case vmnet_stress 394 atf_add_test_case vmnet_up_stress 395} 396 397do_stress() 398{ 399 local IFACE 400 401 IFACE=`get_iface $1` 402 403 # First thread: create the interface 404 while true; do 405 ifconfig $IFACE create 2>/dev/null && \ 406 echo -n . >> creator_count.txt 407 done & 408 CREATOR_PID=$! 409 410 # Second thread: destroy the lagg 411 while true; do 412 ifconfig $IFACE destroy 2>/dev/null && \ 413 echo -n . >> destroyer_count.txt 414 done & 415 DESTROYER_PID=$! 416 417 sleep ${TESTLEN} 418 kill $CREATOR_PID 419 kill $DESTROYER_PID 420 echo "Created $IFACE `stat -f %z creator_count.txt` times." 421 echo "Destroyed it `stat -f %z destroyer_count.txt` times." 422} 423 424# Implement the up stress tests 425# Parameters 426# $1 Interface class, etc "lo" or "tap" 427# $2 "6" to enable IPv6 auto address assignment, anything else otherwise 428# $3 p2p for point to point interfaces, anything else for normal interfaces 429do_up_stress() 430{ 431 local IFACE IPv6 MAC P2P SRCDIR 432 433 # Configure the interface to use an RFC5737 nonrouteable addresses 434 ADDR="192.0.2.2" 435 DSTADDR="192.0.2.3" 436 MASK="24" 437 # ifconfig takes about 10ms to run. To increase race coverage, 438 # randomly delay the two commands relative to each other by 5ms either 439 # way. 440 MEAN_SLEEP_SECONDS=.005 441 MAX_SLEEP_USECS=10000 442 443 IFACE=`get_iface $1` 444 IPV6=$2 445 P2P=$3 446 447 SRCDIR=$( atf_get_srcdir ) 448 if [ "$IPV6" = 6 ]; then 449 ipv6_cmd="true" 450 else 451 ipv6_cmd="ifconfig $IFACE inet6 ifdisabled" 452 fi 453 if [ "$P2P" = "p2p" ]; then 454 up_cmd="ifconfig $IFACE up ${ADDR}/${MASK} ${DSTADDR}" 455 else 456 up_cmd="ifconfig $IFACE up ${ADDR}/${MASK}" 457 fi 458 while true; do 459 eval "$ipv6_cmd" 460 { sleep ${MEAN_SLEEP_SECONDS} && \ 461 eval "$up_cmd" 2> /dev/null && 462 echo -n . >> up_count.txt ; } & 463 { ${SRCDIR}/randsleep ${MAX_SLEEP_USECS} && \ 464 ifconfig $IFACE destroy && 465 echo -n . >> destroy_count.txt ; } & 466 wait 467 ifconfig $IFACE create 468 done & 469 LOOP_PID=$! 470 471 sleep ${TESTLEN} 472 kill $LOOP_PID 473 echo "Upped ${IFACE} `stat -f %z up_count.txt` times." 474 echo "Destroyed it `stat -f %z destroy_count.txt` times." 475} 476 477# Creates a new cloned interface, registers it for cleanup, and echoes it 478# params: $1 Interface class name (tap, gif, etc) 479get_iface() 480{ 481 local CLASS DEV N 482 483 CLASS=$1 484 N=0 485 while ! ifconfig ${CLASS}${N} create > /dev/null 2>&1; do 486 if [ "$N" -ge 8 ]; then 487 atf_skip "Could not create a ${CLASS} interface" 488 else 489 N=$(($N + 1)) 490 fi 491 done 492 local DEV=${CLASS}${N} 493 # Record the device so we can clean it up later 494 echo ${DEV} >> "devices_to_cleanup" 495 echo ${DEV} 496} 497 498 499cleanup_ifaces() 500{ 501 local DEV 502 503 for DEV in `cat "devices_to_cleanup"`; do 504 if [ ${DEV%%[0-9]*a} = "epair" ]; then 505 ifconfig ${DEV}a destroy 506 else 507 ifconfig ${DEV} destroy 508 fi 509 done 510 true 511} 512