1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2020 Kristof Provost <kp@FreeBSD.org> 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26 27. $(atf_get_srcdir)/../common/vnet.subr 28 29is_master() 30{ 31 jail=$1 32 itf=$2 33 34 jexec ${jail} ifconfig ${itf} | grep -E '(carp|vrrp)' | grep MASTER 35} 36 37wait_for_carp() 38{ 39 jail1=$1 40 itf1=$2 41 jail2=$3 42 itf2=$4 43 44 while [ -z "$(is_master ${jail1} ${itf1})" ] && 45 [ -z "$(is_master ${jail2} ${itf2})" ]; do 46 sleep 0.1 47 done 48 49 if [ -n "$(is_master ${jail1} ${itf1})" ] && 50 [ -n "$(is_master ${jail2} ${itf2})" ]; then 51 atf_fail "Both jails are master" 52 fi 53} 54 55carp_init() 56{ 57 if ! kldstat -q -m carp; then 58 atf_skip "This test requires carp" 59 fi 60 61 vnet_init 62} 63 64atf_test_case "basic_v4" "cleanup" 65basic_v4_head() 66{ 67 atf_set descr 'Basic CARP test (IPv4)' 68 atf_set require.user root 69} 70 71basic_v4_body() 72{ 73 carp_init 74 vnet_init_bridge 75 76 bridge=$(vnet_mkbridge) 77 epair_one=$(vnet_mkepair) 78 epair_two=$(vnet_mkepair) 79 80 vnet_mkjail carp_basic_v4_one ${bridge} ${epair_one}a ${epair_two}a 81 vnet_mkjail carp_basic_v4_two ${epair_one}b 82 vnet_mkjail carp_basic_v4_three ${epair_two}b 83 84 jexec carp_basic_v4_one ifconfig ${bridge} 192.0.2.4/29 up 85 jexec carp_basic_v4_one ifconfig ${bridge} addm ${epair_one}a \ 86 addm ${epair_two}a 87 jexec carp_basic_v4_one ifconfig ${epair_one}a up 88 jexec carp_basic_v4_one ifconfig ${epair_two}a up 89 90 jexec carp_basic_v4_two ifconfig ${epair_one}b 192.0.2.202/29 up 91 jexec carp_basic_v4_two ifconfig ${epair_one}b add vhid 1 192.0.2.1/29 92 93 sleep 0.2 94 jexec carp_basic_v4_three ifconfig ${epair_two}b 192.0.2.203/29 up 95 jexec carp_basic_v4_three ifconfig ${epair_two}b add vhid 1 \ 96 192.0.2.1/29 97 98 wait_for_carp carp_basic_v4_two ${epair_one}b \ 99 carp_basic_v4_three ${epair_two}b 100 101 atf_check -s exit:0 -o ignore jexec carp_basic_v4_one \ 102 ping -c 3 192.0.2.1 103} 104 105basic_v4_cleanup() 106{ 107 vnet_cleanup 108} 109 110atf_test_case "vrrp_v4" "cleanup" 111vrrp_v4_head() 112{ 113 atf_set descr 'Basic VRRP test (IPv4)' 114 atf_set require.user root 115} 116 117vrrp_v4_body() 118{ 119 carp_init 120 vnet_init_bridge 121 122 j=vrrp_basic_v4 123 124 bridge=$(vnet_mkbridge) 125 epair_one=$(vnet_mkepair) 126 epair_two=$(vnet_mkepair) 127 128 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 129 vnet_mkjail ${j}_two ${epair_one}b 130 vnet_mkjail ${j}_three ${epair_two}b 131 132 jexec ${j}_one ifconfig ${bridge} 192.0.2.4/29 up 133 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 134 addm ${epair_two}a 135 jexec ${j}_one ifconfig ${epair_one}a up 136 jexec ${j}_one ifconfig ${epair_two}a up 137 138 jexec ${j}_two ifconfig ${epair_one}b 192.0.2.202/29 up 139 jexec ${j}_two ifconfig ${epair_one}b add vhid 1 carpver 3 192.0.2.1/29 140 141 sleep 0.2 142 jexec ${j}_three ifconfig ${epair_two}b 192.0.2.203/29 up 143 jexec ${j}_three ifconfig ${epair_two}b add vhid 1 carpver 3 \ 144 192.0.2.1/29 145 146 wait_for_carp ${j}_two ${epair_one}b \ 147 ${j}_three ${epair_two}b 148 149 atf_check -s exit:0 -o ignore jexec ${j}_one \ 150 ping -c 3 192.0.2.1 151} 152 153vrrp_v4_cleanup() 154{ 155 vnet_cleanup 156} 157 158atf_test_case "unicast_v4" "cleanup" 159unicast_v4_head() 160{ 161 atf_set descr 'Unicast CARP test (IPv4)' 162 atf_set require.user root 163} 164 165unicast_v4_body() 166{ 167 carp_init 168 169 epair_one=$(vnet_mkepair) 170 epair_two=$(vnet_mkepair) 171 172 vnet_mkjail carp_uni_v4_one ${epair_one}a ${epair_two}a 173 vnet_mkjail carp_uni_v4_two ${epair_one}b 174 vnet_mkjail carp_uni_v4_three ${epair_two}b 175 176 jexec carp_uni_v4_one sysctl net.inet.ip.forwarding=1 177 jexec carp_uni_v4_one ifconfig ${epair_one}a inet 198.51.100.1/25 178 jexec carp_uni_v4_one ifconfig ${epair_two}a inet 198.51.100.129/25 179 180 jexec carp_uni_v4_two sysctl net.inet.ip.forwarding=1 181 jexec carp_uni_v4_two ifconfig ${epair_one}b 198.51.100.2/25 up 182 jexec carp_uni_v4_two route add 198.51.100.224 198.51.100.1 183 # A peer address x.x.x.224 to catch PR 284872 184 jexec carp_uni_v4_two ifconfig ${epair_one}b add vhid 1 \ 185 peer 198.51.100.224 192.0.2.1/32 186 187 sleep 0.2 188 jexec carp_uni_v4_three sysctl net.inet.ip.forwarding=1 189 jexec carp_uni_v4_three ifconfig ${epair_two}b 198.51.100.224/25 up 190 jexec carp_uni_v4_three route add 198.51.100.2 198.51.100.129 191 jexec carp_uni_v4_three ifconfig ${epair_two}b add vhid 1 \ 192 peer 198.51.100.2 192.0.2.1/32 193 194 # Sanity check 195 atf_check -s exit:0 -o ignore jexec carp_uni_v4_two \ 196 ping -c 1 198.51.100.224 197 198 wait_for_carp carp_uni_v4_two ${epair_one}b \ 199 carp_uni_v4_three ${epair_two}b 200 201 # Setup RIPv2 route daemon 202 jexec carp_uni_v4_two routed -s -Pripv2 203 jexec carp_uni_v4_three routed -s -Pripv2 204 jexec carp_uni_v4_one routed -Pripv2 205 206 # XXX Wait for route propagation 207 sleep 3 208 209 atf_check -s exit:0 -o ignore jexec carp_uni_v4_one \ 210 ping -c 3 192.0.2.1 211 212 # Check that we remain in unicast when tweaking settings 213 atf_check -s exit:0 -o ignore \ 214 jexec carp_uni_v4_two ifconfig ${epair_one}b vhid 1 advskew 2 215 atf_check -s exit:0 -o match:"peer 198.51.100.224" \ 216 jexec carp_uni_v4_two ifconfig ${epair_one}b 217} 218 219unicast_v4_cleanup() 220{ 221 jexec carp_uni_v4_one killall routed 222 jexec carp_uni_v4_two killall routed 223 jexec carp_uni_v4_three killall routed 224 vnet_cleanup 225} 226 227atf_test_case "basic_v6" "cleanup" 228basic_v6_head() 229{ 230 atf_set descr 'Basic CARP test (IPv6)' 231 atf_set require.user root 232} 233 234basic_v6_body() 235{ 236 carp_init 237 vnet_init_bridge 238 239 bridge=$(vnet_mkbridge) 240 epair_one=$(vnet_mkepair) 241 epair_two=$(vnet_mkepair) 242 243 vnet_mkjail carp_basic_v6_one ${bridge} ${epair_one}a ${epair_two}a 244 vnet_mkjail carp_basic_v6_two ${epair_one}b 245 vnet_mkjail carp_basic_v6_three ${epair_two}b 246 247 jexec carp_basic_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 248 no_dad 249 jexec carp_basic_v6_one ifconfig ${bridge} addm ${epair_one}a \ 250 addm ${epair_two}a 251 jexec carp_basic_v6_one ifconfig ${epair_one}a up 252 jexec carp_basic_v6_one ifconfig ${epair_two}a up 253 254 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 \ 255 2001:db8::1:2/64 up no_dad 256 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \ 257 2001:db8::0:1/64 258 259 sleep 0.2 260 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad 261 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \ 262 2001:db8::0:1/64 263 264 wait_for_carp carp_basic_v6_two ${epair_one}b \ 265 carp_basic_v6_three ${epair_two}b 266 267 atf_check -s exit:0 -o ignore jexec carp_basic_v6_one \ 268 ping -6 -c 3 2001:db8::0:1 269} 270 271basic_v6_cleanup() 272{ 273 vnet_cleanup 274} 275 276atf_test_case "vrrp_v6" "cleanup" 277vrrp_v6_head() 278{ 279 atf_set descr 'Basic VRRP test (IPv6)' 280 atf_set require.user root 281} 282 283vrrp_v6_body() 284{ 285 carp_init 286 vnet_init_bridge 287 288 j=carp_basic_v6 289 290 bridge=$(vnet_mkbridge) 291 epair_one=$(vnet_mkepair) 292 epair_two=$(vnet_mkepair) 293 294 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 295 vnet_mkjail ${j}_two ${epair_one}b 296 vnet_mkjail ${j}_three ${epair_two}b 297 298 jexec ${j}_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 299 no_dad 300 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 301 addm ${epair_two}a 302 jexec ${j}_one ifconfig ${epair_one}a up 303 jexec ${j}_one ifconfig ${epair_two}a up 304 305 jexec ${j}_two ifconfig ${epair_one}b inet6 \ 306 2001:db8::1:2/64 up no_dad 307 jexec ${j}_two ifconfig ${epair_one}b inet6 add vhid 1 carpver 3 \ 308 2001:db8::0:1/64 309 310 sleep 0.2 311 jexec ${j}_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad 312 jexec ${j}_three ifconfig ${epair_two}b inet6 add vhid 1 carpver 3 \ 313 2001:db8::0:1/64 314 315 wait_for_carp ${j}_two ${epair_one}b \ 316 ${j}_three ${epair_two}b 317 318 atf_check -s exit:0 -o ignore jexec ${j}_one \ 319 ping -6 -c 3 2001:db8::0:1 320} 321 322vrrp_v6_cleanup() 323{ 324 vnet_cleanup 325} 326 327atf_test_case "unicast_v6" "cleanup" 328unicast_v6_head() 329{ 330 atf_set descr 'Unicast CARP test (IPv6)' 331 atf_set require.user root 332} 333 334unicast_v6_body() 335{ 336 carp_init 337 vnet_init_bridge 338 339 bridge=$(vnet_mkbridge) 340 epair_one=$(vnet_mkepair) 341 epair_two=$(vnet_mkepair) 342 343 vnet_mkjail carp_uni_v6_one ${bridge} ${epair_one}a ${epair_two}a 344 vnet_mkjail carp_uni_v6_two ${epair_one}b 345 vnet_mkjail carp_uni_v6_three ${epair_two}b 346 347 jexec carp_uni_v6_one sysctl net.inet6.ip6.forwarding=1 348 jexec carp_uni_v6_one ifconfig ${bridge} addm ${epair_one}a \ 349 addm ${epair_two}a 350 jexec carp_uni_v6_one ifconfig ${epair_one}a up 351 jexec carp_uni_v6_one ifconfig ${epair_two}a up 352 jexec carp_uni_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 353 no_dad 354 jexec carp_uni_v6_one ifconfig ${bridge} inet6 alias 2001:db8:1::1/64 \ 355 no_dad up 356 jexec carp_uni_v6_one ifconfig ${bridge} inet6 alias 2001:db8:2::1/64 \ 357 no_dad up 358 359 jexec carp_uni_v6_two ifconfig ${epair_one}b inet6 2001:db8:1::2/64 \ 360 no_dad up 361 jexec carp_uni_v6_two route -6 add default 2001:db8:1::1 362 jexec carp_uni_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \ 363 peer6 2001:db8:2::2 \ 364 2001:db8::0:1/64 365 366 sleep 0.2 367 jexec carp_uni_v6_three ifconfig ${epair_two}b inet6 2001:db8:2::2/64 \ 368 no_dad up 369 jexec carp_uni_v6_three route -6 add default 2001:db8:2::1 370 jexec carp_uni_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \ 371 peer6 2001:db8:1::2 \ 372 2001:db8::0:1/64 373 374 # Sanity check 375 atf_check -s exit:0 -o ignore jexec carp_uni_v6_two \ 376 ping -6 -c 1 2001:db8:2::2 377 378 wait_for_carp carp_uni_v6_two ${epair_one}b \ 379 carp_uni_v6_three ${epair_two}b 380 381 atf_check -s exit:0 -o ignore jexec carp_uni_v6_one \ 382 ping -6 -c 3 2001:db8::0:1 383} 384 385unicast_v6_cleanup() 386{ 387 vnet_cleanup 388} 389 390atf_test_case "unicast_ll_v6" "cleanup" 391unicast_ll_v6_head() 392{ 393 atf_set descr 'Unicast CARP test (IPv6, link-local)' 394 atf_set require.user root 395} 396 397unicast_ll_v6_body() 398{ 399 carp_init 400 vnet_init_bridge 401 402 j=carp_uni_ll_v6 403 404 bridge=$(vnet_mkbridge) 405 epair_one=$(vnet_mkepair) 406 epair_two=$(vnet_mkepair) 407 408 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 409 vnet_mkjail ${j}_two ${epair_one}b 410 vnet_mkjail ${j}_three ${epair_two}b 411 412 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 413 addm ${epair_two}a 414 jexec ${j}_one ifconfig ${epair_one}a up 415 jexec ${j}_one ifconfig ${epair_two}a up 416 jexec ${j}_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 417 no_dad 418 jexec ${j}_one ifconfig ${bridge} inet6 alias 2001:db8:1::1/64 \ 419 no_dad up 420 421 jexec ${j}_two ifconfig ${epair_one}b inet6 2001:db8:1::2/64 \ 422 no_dad up 423 jexec ${j}_three ifconfig ${epair_two}b inet6 2001:db8:1::3/64 \ 424 no_dad up 425 426 ll_one=$(jexec ${j}_two ifconfig ${epair_one}b | awk "/ .*%${epair_one}b.* / { print \$2 }" | cut -d % -f 1) 427 ll_two=$(jexec ${j}_three ifconfig ${epair_two}b | awk "/ .*%${epair_two}b.* / { print \$2 }" | cut -d % -f 1) 428 429 jexec ${j}_two ifconfig ${epair_one}b inet6 add vhid 1 \ 430 peer6 ${ll_two} \ 431 2001:db8::0:1/64 432 sleep 0.2 433 jexec ${j}_three ifconfig ${epair_two}b inet6 add vhid 1 \ 434 peer6 ${ll_one} \ 435 2001:db8::0:1/64 436 437 # Sanity check 438 atf_check -s exit:0 -o ignore jexec ${j}_two \ 439 ping -6 -c 1 2001:db8:1::3 440 441 wait_for_carp ${j}_two ${epair_one}b \ 442 ${j}_three ${epair_two}b 443 444 atf_check -s exit:0 -o ignore jexec ${j}_one \ 445 ping -6 -c 3 2001:db8::0:1 446} 447 448unicast_ll_v6_cleanup() 449{ 450 vnet_cleanup 451} 452 453atf_test_case "negative_demotion" "cleanup" 454negative_demotion_head() 455{ 456 atf_set descr 'Test PR #259528' 457 atf_set require.user root 458} 459 460negative_demotion_body() 461{ 462 carp_init 463 464 epair=$(vnet_mkepair) 465 466 vnet_mkjail one ${epair}a 467 jexec one sysctl net.inet.carp.preempt=1 468 jexec one ifconfig ${epair}a 192.0.2.1/24 up 469 jexec one ifconfig ${epair}a add vhid 1 192.0.2.254/24 \ 470 advskew 0 pass foobar 471 472 vnet_mkjail two ${epair}b 473 jexec two sysctl net.inet.carp.preempt=1 474 jexec two ifconfig ${epair}b 192.0.2.2/24 up 475 jexec two ifconfig ${epair}b add vhid 1 192.0.2.254/24 \ 476 advskew 100 pass foobar 477 478 # Allow things to settle 479 wait_for_carp one ${epair}a two ${epair}b 480 481 if is_master one ${epair}a && is_master two ${epair}b 482 then 483 atf_fail "Two masters!" 484 fi 485 486 jexec one sysctl net.inet.carp.demotion=-1 487 sleep 3 488 489 if is_master one ${epair}a && is_master two ${epair}b 490 then 491 atf_fail "Two masters!" 492 fi 493} 494 495negative_demotion_cleanup() 496{ 497 vnet_cleanup 498} 499 500 501 502atf_test_case "nd6_ns_source_mac" "cleanup" 503nd6_ns_source_mac_head() 504{ 505 atf_set descr 'CARP ndp neighbor solicitation MAC source test (IPv6)' 506 atf_set require.user root 507} 508 509nd6_ns_source_mac_body() 510{ 511 carp_init 512 vnet_init_bridge 513 514 bridge=$(vnet_mkbridge) 515 epair_one=$(vnet_mkepair) 516 epair_two=$(vnet_mkepair) 517 518 vnet_mkjail carp_ndp_v6_bridge ${bridge} ${epair_one}a ${epair_two}a 519 vnet_mkjail carp_ndp_v6_master ${epair_one}b 520 vnet_mkjail carp_ndp_v6_slave ${epair_two}b 521 522 jexec carp_ndp_v6_bridge ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 523 no_dad 524 jexec carp_ndp_v6_bridge ifconfig ${bridge} addm ${epair_one}a \ 525 addm ${epair_two}a 526 jexec carp_ndp_v6_bridge ifconfig ${epair_one}a up 527 jexec carp_ndp_v6_bridge ifconfig ${epair_two}a up 528 529 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 \ 530 2001:db8::1:2/64 up no_dad 531 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 add vhid 1 \ 532 advskew 0 2001:db8::0:1/64 533 534 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 \ 535 2001:db8::1:3/64 up no_dad 536 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 add vhid 1 \ 537 advskew 100 2001:db8::0:1/64 538 539 wait_for_carp carp_ndp_v6_master ${epair_one}b \ 540 carp_ndp_v6_slave ${epair_two}b 541 542 # carp_ndp_v6_master is MASTER 543 544 # trigger a NS from the virtual IP from the BACKUP 545 atf_check -s exit:2 -o ignore jexec carp_ndp_v6_slave \ 546 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 547 548 # trigger a NS from the virtual IP from the MASTER, 549 # this ping should work 550 atf_check -s exit:0 -o ignore jexec carp_ndp_v6_master \ 551 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 552 553 # ndp entry should be for the virtual mac 554 atf_check -o match:'2001:db8::1 +00:00:5e:00:01:01' \ 555 jexec carp_ndp_v6_bridge ndp -an 556} 557 558nd6_ns_source_mac_cleanup() 559{ 560 vnet_cleanup 561} 562 563 564atf_test_case "switch" "cleanup" 565switch_head() 566{ 567 atf_set descr 'Switch between master and backup' 568 atf_set require.user root 569} 570 571switch_body() 572{ 573 carp_init 574 575 epair=$(vnet_mkepair) 576 577 ifconfig ${epair}a up 578 ifconfig ${epair}a vhid 1 advskew 100 192.0.2.1/24 579 ifconfig ${epair}a vhid 1 state backup 580 ifconfig ${epair}a vhid 1 state master 581} 582 583switch_cleanup() 584{ 585 vnet_cleanup 586} 587 588atf_init_test_cases() 589{ 590 atf_add_test_case "basic_v4" 591 atf_add_test_case "vrrp_v4" 592 atf_add_test_case "unicast_v4" 593 atf_add_test_case "basic_v6" 594 atf_add_test_case "vrrp_v6" 595 atf_add_test_case "unicast_v6" 596 atf_add_test_case "unicast_ll_v6" 597 atf_add_test_case "negative_demotion" 598 atf_add_test_case "nd6_ns_source_mac" 599 atf_add_test_case "switch" 600} 601