1# $FreeBSD$ 2# 3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4# 5# Copyright (c) 2020 Kristof Provost <kp@FreeBSD.org> 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27 28. $(atf_get_srcdir)/../common/vnet.subr 29 30is_master() 31{ 32 jail=$1 33 itf=$2 34 35 jexec ${jail} ifconfig ${itf} | grep carp | grep MASTER 36} 37 38wait_for_carp() 39{ 40 jail1=$1 41 itf1=$2 42 jail2=$3 43 itf2=$4 44 45 while [ -z "$(is_master ${jail1} ${itf1})" ] && 46 [ -z "$(is_master ${jail2} ${itf2})" ]; do 47 sleep 1 48 done 49} 50 51carp_init() 52{ 53 if ! kldstat -q -m carp; then 54 atf_skip "This test requires carp" 55 fi 56 57 vnet_init 58} 59 60atf_test_case "basic_v4" "cleanup" 61basic_v4_head() 62{ 63 atf_set descr 'Basic CARP test (IPv4)' 64 atf_set require.user root 65} 66 67basic_v4_body() 68{ 69 carp_init 70 71 bridge=$(vnet_mkbridge) 72 epair_one=$(vnet_mkepair) 73 epair_two=$(vnet_mkepair) 74 75 vnet_mkjail carp_basic_v4_one ${bridge} ${epair_one}a ${epair_two}a 76 vnet_mkjail carp_basic_v4_two ${epair_one}b 77 vnet_mkjail carp_basic_v4_three ${epair_two}b 78 79 jexec carp_basic_v4_one ifconfig ${bridge} 192.0.2.4/29 up 80 jexec carp_basic_v4_one ifconfig ${bridge} addm ${epair_one}a \ 81 addm ${epair_two}a 82 jexec carp_basic_v4_one ifconfig ${epair_one}a up 83 jexec carp_basic_v4_one ifconfig ${epair_two}a up 84 85 jexec carp_basic_v4_two ifconfig ${epair_one}b 192.0.2.202/29 up 86 jexec carp_basic_v4_two ifconfig ${epair_one}b add vhid 1 192.0.2.1/29 87 88 jexec carp_basic_v4_three ifconfig ${epair_two}b 192.0.2.203/29 up 89 jexec carp_basic_v4_three ifconfig ${epair_two}b add vhid 1 \ 90 192.0.2.1/29 91 92 wait_for_carp carp_basic_v4_two ${epair_one}b \ 93 carp_basic_v4_three ${epair_two}b 94 95 atf_check -s exit:0 -o ignore jexec carp_basic_v4_one \ 96 ping -c 3 192.0.2.1 97} 98 99basic_v4_cleanup() 100{ 101 vnet_cleanup 102} 103 104atf_test_case "basic_v6" "cleanup" 105basic_v6_head() 106{ 107 atf_set descr 'Basic CARP test (IPv6)' 108 atf_set require.user root 109} 110 111basic_v6_body() 112{ 113 carp_init 114 115 bridge=$(vnet_mkbridge) 116 epair_one=$(vnet_mkepair) 117 epair_two=$(vnet_mkepair) 118 119 vnet_mkjail carp_basic_v6_one ${bridge} ${epair_one}a ${epair_two}a 120 vnet_mkjail carp_basic_v6_two ${epair_one}b 121 vnet_mkjail carp_basic_v6_three ${epair_two}b 122 123 jexec carp_basic_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 124 no_dad 125 jexec carp_basic_v6_one ifconfig ${bridge} addm ${epair_one}a \ 126 addm ${epair_two}a 127 jexec carp_basic_v6_one ifconfig ${epair_one}a up 128 jexec carp_basic_v6_one ifconfig ${epair_two}a up 129 130 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 \ 131 2001:db8::1:2/64 up no_dad 132 jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \ 133 2001:db8::0:1/64 134 135 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad 136 jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \ 137 2001:db8::0:1/64 138 139 wait_for_carp carp_basic_v6_two ${epair_one}b \ 140 carp_basic_v6_three ${epair_two}b 141 142 atf_check -s exit:0 -o ignore jexec carp_basic_v6_one \ 143 ping -6 -c 3 2001:db8::0:1 144} 145 146basic_v6_cleanup() 147{ 148 vnet_cleanup 149} 150 151atf_test_case "negative_demotion" "cleanup" 152negative_demotion_head() 153{ 154 atf_set descr 'Test PR #259528' 155 atf_set require.user root 156} 157 158negative_demotion_body() 159{ 160 carp_init 161 162 epair=$(vnet_mkepair) 163 164 vnet_mkjail one ${epair}a 165 jexec one sysctl net.inet.carp.preempt=1 166 jexec one ifconfig ${epair}a 192.0.2.1/24 up 167 jexec one ifconfig ${epair}a add vhid 1 192.0.2.254/24 \ 168 advskew 0 pass foobar 169 170 vnet_mkjail two ${epair}b 171 jexec two sysctl net.inet.carp.preempt=1 172 jexec two ifconfig ${epair}b 192.0.2.2/24 up 173 jexec two ifconfig ${epair}b add vhid 1 192.0.2.254/24 \ 174 advskew 100 pass foobar 175 176 # Allow things to settle 177 wait_for_carp one ${epair}a two ${epair}b 178 179 if is_master one ${epair}a && is_master two ${epair}b 180 then 181 atf_fail "Two masters!" 182 fi 183 184 jexec one sysctl net.inet.carp.demotion=-1 185 sleep 3 186 187 if is_master one ${epair}a && is_master two ${epair}b 188 then 189 atf_fail "Two masters!" 190 fi 191} 192 193negative_demotion_cleanup() 194{ 195 vnet_cleanup 196} 197 198 199 200atf_test_case "nd6_ns_source_mac" "cleanup" 201nd6_ns_source_mac_head() 202{ 203 atf_set descr 'CARP ndp neighbor solicitation MAC source test (IPv6)' 204 atf_set require.user root 205} 206 207nd6_ns_source_mac_body() 208{ 209 carp_init 210 211 bridge=$(vnet_mkbridge) 212 epair_one=$(vnet_mkepair) 213 epair_two=$(vnet_mkepair) 214 215 vnet_mkjail carp_ndp_v6_bridge ${bridge} ${epair_one}a ${epair_two}a 216 vnet_mkjail carp_ndp_v6_master ${epair_one}b 217 vnet_mkjail carp_ndp_v6_slave ${epair_two}b 218 219 jexec carp_ndp_v6_bridge ifconfig ${bridge} inet6 2001:db8::0:4/64 up \ 220 no_dad 221 jexec carp_ndp_v6_bridge ifconfig ${bridge} addm ${epair_one}a \ 222 addm ${epair_two}a 223 jexec carp_ndp_v6_bridge ifconfig ${epair_one}a up 224 jexec carp_ndp_v6_bridge ifconfig ${epair_two}a up 225 226 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 \ 227 2001:db8::1:2/64 up no_dad 228 jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 add vhid 1 \ 229 advskew 0 2001:db8::0:1/64 230 231 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 \ 232 2001:db8::1:3/64 up no_dad 233 jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 add vhid 1 \ 234 advskew 100 2001:db8::0:1/64 235 236 wait_for_carp carp_ndp_v6_master ${epair_one}b \ 237 carp_ndp_v6_slave ${epair_two}b 238 239 # carp_ndp_v6_master is MASTER 240 241 # trigger a NS from the virtual IP from the BACKUP 242 atf_check -s exit:2 -o ignore jexec carp_ndp_v6_slave \ 243 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 244 245 # trigger a NS from the virtual IP from the MASTER, 246 # this ping should work 247 atf_check -s exit:0 -o ignore jexec carp_ndp_v6_master \ 248 ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4 249 250 # ndp entry should be for the virtual mac 251 atf_check -o match:'2001:db8::1 +00:00:5e:00:01:01' \ 252 jexec carp_ndp_v6_bridge ndp -an 253} 254 255nd6_ns_source_mac_cleanup() 256{ 257 vnet_cleanup 258} 259 260 261atf_init_test_cases() 262{ 263 atf_add_test_case "basic_v4" 264 atf_add_test_case "basic_v6" 265 atf_add_test_case "negative_demotion" 266 atf_add_test_case "nd6_ns_source_mac" 267} 268