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