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 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 jexec carp_basic_v4_three ifconfig ${epair_two}b 192.0.2.203/29 up 94 jexec carp_basic_v4_three ifconfig ${epair_two}b add vhid 1 \ 95 192.0.2.1/29 96 97 wait_for_carp carp_basic_v4_two ${epair_one}b \ 98 carp_basic_v4_three ${epair_two}b 99 100 atf_check -s exit:0 -o ignore jexec carp_basic_v4_one \ 101 ping -c 3 192.0.2.1 102} 103 104basic_v4_cleanup() 105{ 106 vnet_cleanup 107} 108 109atf_test_case "vrrp_v4" "cleanup" 110vrrp_v4_head() 111{ 112 atf_set descr 'Basic VRRP test (IPv4)' 113 atf_set require.user root 114} 115 116vrrp_v4_body() 117{ 118 carp_init 119 vnet_init_bridge 120 121 j=vrrp_basic_v4 122 123 bridge=$(vnet_mkbridge) 124 epair_one=$(vnet_mkepair) 125 epair_two=$(vnet_mkepair) 126 127 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 128 vnet_mkjail ${j}_two ${epair_one}b 129 vnet_mkjail ${j}_three ${epair_two}b 130 131 jexec ${j}_one ifconfig ${bridge} 192.0.2.4/29 up 132 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 133 addm ${epair_two}a 134 jexec ${j}_one ifconfig ${epair_one}a up 135 jexec ${j}_one ifconfig ${epair_two}a up 136 137 jexec ${j}_two ifconfig ${epair_one}b 192.0.2.202/29 up 138 jexec ${j}_two ifconfig ${epair_one}b add vhid 1 carpver 3 192.0.2.1/29 139 140 jexec ${j}_three ifconfig ${epair_two}b 192.0.2.203/29 up 141 jexec ${j}_three ifconfig ${epair_two}b add vhid 1 carpver 3 \ 142 192.0.2.1/29 143 144 wait_for_carp ${j}_two ${epair_one}b \ 145 ${j}_three ${epair_two}b 146 147 atf_check -s exit:0 -o ignore jexec ${j}_one \ 148 ping -c 3 192.0.2.1 149} 150 151vrrp_v4_cleanup() 152{ 153 vnet_cleanup 154} 155 156atf_test_case "unicast_v4" "cleanup" 157unicast_v4_head() 158{ 159 atf_set descr 'Unicast CARP test (IPv4)' 160 atf_set require.user root 161} 162 163unicast_v4_body() 164{ 165 carp_init 166 167 epair_one=$(vnet_mkepair) 168 epair_two=$(vnet_mkepair) 169 170 vnet_mkjail carp_uni_v4_one ${epair_one}a ${epair_two}a 171 vnet_mkjail carp_uni_v4_two ${epair_one}b 172 vnet_mkjail carp_uni_v4_three ${epair_two}b 173 174 jexec carp_uni_v4_one sysctl net.inet.ip.forwarding=1 175 jexec carp_uni_v4_one ifconfig ${epair_one}a inet 198.51.100.1/25 176 jexec carp_uni_v4_one ifconfig ${epair_two}a inet 198.51.100.129/25 177 178 jexec carp_uni_v4_two sysctl net.inet.ip.forwarding=1 179 jexec carp_uni_v4_two ifconfig ${epair_one}b 198.51.100.2/25 up 180 jexec carp_uni_v4_two route add 198.51.100.224 198.51.100.1 181 # A peer address x.x.x.224 to catch PR 284872 182 jexec carp_uni_v4_two ifconfig ${epair_one}b add vhid 1 \ 183 peer 198.51.100.224 192.0.2.1/32 184 185 jexec carp_uni_v4_three sysctl net.inet.ip.forwarding=1 186 jexec carp_uni_v4_three ifconfig ${epair_two}b 198.51.100.224/25 up 187 jexec carp_uni_v4_three route add 198.51.100.2 198.51.100.129 188 jexec carp_uni_v4_three ifconfig ${epair_two}b add vhid 1 \ 189 peer 198.51.100.2 192.0.2.1/32 190 191 # Sanity check 192 atf_check -s exit:0 -o ignore jexec carp_uni_v4_two \ 193 ping -c 1 198.51.100.224 194 195 wait_for_carp carp_uni_v4_two ${epair_one}b \ 196 carp_uni_v4_three ${epair_two}b 197 198 # Setup RIPv2 route daemon 199 jexec carp_uni_v4_two routed -s -Pripv2 200 jexec carp_uni_v4_three routed -s -Pripv2 201 jexec carp_uni_v4_one routed -Pripv2 202 203 # XXX Wait for route propagation 204 sleep 3 205 206 atf_check -s exit:0 -o ignore jexec carp_uni_v4_one \ 207 ping -c 3 192.0.2.1 208 209 # Check that we remain in unicast when tweaking settings 210 atf_check -s exit:0 -o ignore \ 211 jexec carp_uni_v4_two ifconfig ${epair_one}b vhid 1 advskew 2 212 atf_check -s exit:0 -o match:"peer 198.51.100.224" \ 213 jexec carp_uni_v4_two ifconfig ${epair_one}b 214} 215 216unicast_v4_cleanup() 217{ 218 jexec carp_uni_v4_one killall routed 219 jexec carp_uni_v4_two killall routed 220 jexec carp_uni_v4_three killall routed 221 vnet_cleanup 222} 223 224atf_test_case "basic_v6" "cleanup" 225basic_v6_head() 226{ 227 atf_set descr 'Basic CARP test (IPv6)' 228 atf_set require.user root 229} 230 231basic_v6_body() 232{ 233 carp_init 234 vnet_init_bridge 235 236 bridge=$(vnet_mkbridge) 237 epair_one=$(vnet_mkepair) 238 epair_two=$(vnet_mkepair) 239 240 vnet_mkjail carp_basic_v6_one ${bridge} ${epair_one}a ${epair_two}a 241 vnet_mkjail carp_basic_v6_two ${epair_one}b 242 vnet_mkjail carp_basic_v6_three ${epair_two}b 243 244 jexec carp_basic_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 245 no_dad 246 jexec carp_basic_v6_one ifconfig ${bridge} addm ${epair_one}a \ 247 addm ${epair_two}a 248 jexec carp_basic_v6_one ifconfig ${epair_one}a up 249 jexec carp_basic_v6_one ifconfig ${epair_two}a up 250 251 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 \ 252 2001:db8::1:2/64 up no_dad 253 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \ 254 2001:db8::0:1/64 255 256 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad 257 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \ 258 2001:db8::0:1/64 259 260 wait_for_carp carp_basic_v6_two ${epair_one}b \ 261 carp_basic_v6_three ${epair_two}b 262 263 atf_check -s exit:0 -o ignore jexec carp_basic_v6_one \ 264 ping -6 -c 3 2001:db8::0:1 265} 266 267basic_v6_cleanup() 268{ 269 vnet_cleanup 270} 271 272atf_test_case "vrrp_v6" "cleanup" 273vrrp_v6_head() 274{ 275 atf_set descr 'Basic VRRP test (IPv6)' 276 atf_set require.user root 277} 278 279vrrp_v6_body() 280{ 281 carp_init 282 vnet_init_bridge 283 284 j=carp_basic_v6 285 286 bridge=$(vnet_mkbridge) 287 epair_one=$(vnet_mkepair) 288 epair_two=$(vnet_mkepair) 289 290 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 291 vnet_mkjail ${j}_two ${epair_one}b 292 vnet_mkjail ${j}_three ${epair_two}b 293 294 jexec ${j}_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 295 no_dad 296 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 297 addm ${epair_two}a 298 jexec ${j}_one ifconfig ${epair_one}a up 299 jexec ${j}_one ifconfig ${epair_two}a up 300 301 jexec ${j}_two ifconfig ${epair_one}b inet6 \ 302 2001:db8::1:2/64 up no_dad 303 jexec ${j}_two ifconfig ${epair_one}b inet6 add vhid 1 carpver 3 \ 304 2001:db8::0:1/64 305 306 jexec ${j}_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad 307 jexec ${j}_three ifconfig ${epair_two}b inet6 add vhid 1 carpver 3 \ 308 2001:db8::0:1/64 309 310 wait_for_carp ${j}_two ${epair_one}b \ 311 ${j}_three ${epair_two}b 312 313 atf_check -s exit:0 -o ignore jexec ${j}_one \ 314 ping -6 -c 3 2001:db8::0:1 315} 316 317vrrp_v6_cleanup() 318{ 319 vnet_cleanup 320} 321 322atf_test_case "unicast_v6" "cleanup" 323unicast_v6_head() 324{ 325 atf_set descr 'Unicast CARP test (IPv6)' 326 atf_set require.user root 327} 328 329unicast_v6_body() 330{ 331 carp_init 332 vnet_init_bridge 333 334 bridge=$(vnet_mkbridge) 335 epair_one=$(vnet_mkepair) 336 epair_two=$(vnet_mkepair) 337 338 vnet_mkjail carp_uni_v6_one ${bridge} ${epair_one}a ${epair_two}a 339 vnet_mkjail carp_uni_v6_two ${epair_one}b 340 vnet_mkjail carp_uni_v6_three ${epair_two}b 341 342 jexec carp_uni_v6_one sysctl net.inet6.ip6.forwarding=1 343 jexec carp_uni_v6_one ifconfig ${bridge} addm ${epair_one}a \ 344 addm ${epair_two}a 345 jexec carp_uni_v6_one ifconfig ${epair_one}a up 346 jexec carp_uni_v6_one ifconfig ${epair_two}a up 347 jexec carp_uni_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 348 no_dad 349 jexec carp_uni_v6_one ifconfig ${bridge} inet6 alias 2001:db8:1::1/64 \ 350 no_dad up 351 jexec carp_uni_v6_one ifconfig ${bridge} inet6 alias 2001:db8:2::1/64 \ 352 no_dad up 353 354 jexec carp_uni_v6_two ifconfig ${epair_one}b inet6 2001:db8:1::2/64 \ 355 no_dad up 356 jexec carp_uni_v6_two route -6 add default 2001:db8:1::1 357 jexec carp_uni_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \ 358 peer6 2001:db8:2::2 \ 359 2001:db8::0:1/64 360 361 jexec carp_uni_v6_three ifconfig ${epair_two}b inet6 2001:db8:2::2/64 \ 362 no_dad up 363 jexec carp_uni_v6_three route -6 add default 2001:db8:2::1 364 jexec carp_uni_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \ 365 peer6 2001:db8:1::2 \ 366 2001:db8::0:1/64 367 368 # Sanity check 369 atf_check -s exit:0 -o ignore jexec carp_uni_v6_two \ 370 ping -6 -c 1 2001:db8:2::2 371 372 wait_for_carp carp_uni_v6_two ${epair_one}b \ 373 carp_uni_v6_three ${epair_two}b 374 375 atf_check -s exit:0 -o ignore jexec carp_uni_v6_one \ 376 ping -6 -c 3 2001:db8::0:1 377} 378 379unicast_v6_cleanup() 380{ 381 vnet_cleanup 382} 383 384atf_test_case "unicast_ll_v6" "cleanup" 385unicast_ll_v6_head() 386{ 387 atf_set descr 'Unicast CARP test (IPv6, link-local)' 388 atf_set require.user root 389} 390 391unicast_ll_v6_body() 392{ 393 carp_init 394 vnet_init_bridge 395 396 j=carp_uni_ll_v6 397 398 bridge=$(vnet_mkbridge) 399 epair_one=$(vnet_mkepair) 400 epair_two=$(vnet_mkepair) 401 402 vnet_mkjail ${j}_one ${bridge} ${epair_one}a ${epair_two}a 403 vnet_mkjail ${j}_two ${epair_one}b 404 vnet_mkjail ${j}_three ${epair_two}b 405 406 jexec ${j}_one ifconfig ${bridge} addm ${epair_one}a \ 407 addm ${epair_two}a 408 jexec ${j}_one ifconfig ${epair_one}a up 409 jexec ${j}_one ifconfig ${epair_two}a up 410 jexec ${j}_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 411 no_dad 412 jexec ${j}_one ifconfig ${bridge} inet6 alias 2001:db8:1::1/64 \ 413 no_dad up 414 415 jexec ${j}_two ifconfig ${epair_one}b inet6 2001:db8:1::2/64 \ 416 no_dad up 417 jexec ${j}_three ifconfig ${epair_two}b inet6 2001:db8:1::3/64 \ 418 no_dad up 419 420 ll_one=$(jexec ${j}_two ifconfig ${epair_one}b | awk "/ .*%${epair_one}b.* / { print \$2 }" | cut -d % -f 1) 421 ll_two=$(jexec ${j}_three ifconfig ${epair_two}b | awk "/ .*%${epair_two}b.* / { print \$2 }" | cut -d % -f 1) 422 423 jexec ${j}_two ifconfig ${epair_one}b inet6 add vhid 1 \ 424 peer6 ${ll_two} \ 425 2001:db8::0:1/64 426 jexec ${j}_three ifconfig ${epair_two}b inet6 add vhid 1 \ 427 peer6 ${ll_one} \ 428 2001:db8::0:1/64 429 430 # Sanity check 431 atf_check -s exit:0 -o ignore jexec ${j}_two \ 432 ping -6 -c 1 2001:db8:1::3 433 434 wait_for_carp ${j}_two ${epair_one}b \ 435 ${j}_three ${epair_two}b 436 437 atf_check -s exit:0 -o ignore jexec ${j}_one \ 438 ping -6 -c 3 2001:db8::0:1 439} 440 441unicast_ll_v6_cleanup() 442{ 443 vnet_cleanup 444} 445 446atf_test_case "negative_demotion" "cleanup" 447negative_demotion_head() 448{ 449 atf_set descr 'Test PR #259528' 450 atf_set require.user root 451} 452 453negative_demotion_body() 454{ 455 carp_init 456 457 epair=$(vnet_mkepair) 458 459 vnet_mkjail one ${epair}a 460 jexec one sysctl net.inet.carp.preempt=1 461 jexec one ifconfig ${epair}a 192.0.2.1/24 up 462 jexec one ifconfig ${epair}a add vhid 1 192.0.2.254/24 \ 463 advskew 0 pass foobar 464 465 vnet_mkjail two ${epair}b 466 jexec two sysctl net.inet.carp.preempt=1 467 jexec two ifconfig ${epair}b 192.0.2.2/24 up 468 jexec two ifconfig ${epair}b add vhid 1 192.0.2.254/24 \ 469 advskew 100 pass foobar 470 471 # Allow things to settle 472 wait_for_carp one ${epair}a two ${epair}b 473 474 if is_master one ${epair}a && is_master two ${epair}b 475 then 476 atf_fail "Two masters!" 477 fi 478 479 jexec one sysctl net.inet.carp.demotion=-1 480 sleep 3 481 482 if is_master one ${epair}a && is_master two ${epair}b 483 then 484 atf_fail "Two masters!" 485 fi 486} 487 488negative_demotion_cleanup() 489{ 490 vnet_cleanup 491} 492 493 494 495atf_test_case "nd6_ns_source_mac" "cleanup" 496nd6_ns_source_mac_head() 497{ 498 atf_set descr 'CARP ndp neighbor solicitation MAC source test (IPv6)' 499 atf_set require.user root 500} 501 502nd6_ns_source_mac_body() 503{ 504 carp_init 505 vnet_init_bridge 506 507 bridge=$(vnet_mkbridge) 508 epair_one=$(vnet_mkepair) 509 epair_two=$(vnet_mkepair) 510 511 vnet_mkjail carp_ndp_v6_bridge ${bridge} ${epair_one}a ${epair_two}a 512 vnet_mkjail carp_ndp_v6_master ${epair_one}b 513 vnet_mkjail carp_ndp_v6_slave ${epair_two}b 514 515 jexec carp_ndp_v6_bridge ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 516 no_dad 517 jexec carp_ndp_v6_bridge ifconfig ${bridge} addm ${epair_one}a \ 518 addm ${epair_two}a 519 jexec carp_ndp_v6_bridge ifconfig ${epair_one}a up 520 jexec carp_ndp_v6_bridge ifconfig ${epair_two}a up 521 522 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 \ 523 2001:db8::1:2/64 up no_dad 524 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 add vhid 1 \ 525 advskew 0 2001:db8::0:1/64 526 527 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 \ 528 2001:db8::1:3/64 up no_dad 529 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 add vhid 1 \ 530 advskew 100 2001:db8::0:1/64 531 532 wait_for_carp carp_ndp_v6_master ${epair_one}b \ 533 carp_ndp_v6_slave ${epair_two}b 534 535 # carp_ndp_v6_master is MASTER 536 537 # trigger a NS from the virtual IP from the BACKUP 538 atf_check -s exit:2 -o ignore jexec carp_ndp_v6_slave \ 539 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 540 541 # trigger a NS from the virtual IP from the MASTER, 542 # this ping should work 543 atf_check -s exit:0 -o ignore jexec carp_ndp_v6_master \ 544 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 545 546 # ndp entry should be for the virtual mac 547 atf_check -o match:'2001:db8::1 +00:00:5e:00:01:01' \ 548 jexec carp_ndp_v6_bridge ndp -an 549} 550 551nd6_ns_source_mac_cleanup() 552{ 553 vnet_cleanup 554} 555 556 557atf_test_case "switch" "cleanup" 558switch_head() 559{ 560 atf_set descr 'Switch between master and backup' 561 atf_set require.user root 562} 563 564switch_body() 565{ 566 carp_init 567 568 epair=$(vnet_mkepair) 569 570 ifconfig ${epair}a up 571 ifconfig ${epair}a vhid 1 advskew 100 192.0.2.1/24 572 ifconfig ${epair}a vhid 1 state backup 573 ifconfig ${epair}a vhid 1 state master 574} 575 576switch_cleanup() 577{ 578 vnet_cleanup 579} 580 581atf_init_test_cases() 582{ 583 atf_add_test_case "basic_v4" 584 atf_add_test_case "vrrp_v4" 585 atf_add_test_case "unicast_v4" 586 atf_add_test_case "basic_v6" 587 atf_add_test_case "vrrp_v6" 588 atf_add_test_case "unicast_v6" 589 atf_add_test_case "unicast_ll_v6" 590 atf_add_test_case "negative_demotion" 591 atf_add_test_case "nd6_ns_source_mac" 592 atf_add_test_case "switch" 593} 594