xref: /freebsd/tests/sys/netinet/carp.sh (revision 927358dd98cb902160093e0dc0bac002d6b43858)
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	if [ -n "$(is_master ${jail1} ${itf1})" ] &&
51	    [ -n "$(is_master ${jail2} ${itf2})" ]; then
52		atf_fail "Both jails are master"
53	fi
54}
55
56carp_init()
57{
58	if ! kldstat -q -m carp; then
59		atf_skip "This test requires carp"
60	fi
61
62	vnet_init
63}
64
65atf_test_case "basic_v4" "cleanup"
66basic_v4_head()
67{
68	atf_set descr 'Basic CARP test (IPv4)'
69	atf_set require.user root
70}
71
72basic_v4_body()
73{
74	carp_init
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 "basic_v6" "cleanup"
110basic_v6_head()
111{
112	atf_set descr 'Basic CARP test (IPv6)'
113	atf_set require.user root
114}
115
116basic_v6_body()
117{
118	carp_init
119
120	bridge=$(vnet_mkbridge)
121	epair_one=$(vnet_mkepair)
122	epair_two=$(vnet_mkepair)
123
124	vnet_mkjail carp_basic_v6_one ${bridge} ${epair_one}a ${epair_two}a
125	vnet_mkjail carp_basic_v6_two ${epair_one}b
126	vnet_mkjail carp_basic_v6_three ${epair_two}b
127
128	jexec carp_basic_v6_one ifconfig ${bridge} inet6 2001:db8::0:4/64 up \
129	    no_dad
130	jexec carp_basic_v6_one ifconfig ${bridge} addm ${epair_one}a \
131	    addm ${epair_two}a
132	jexec carp_basic_v6_one ifconfig ${epair_one}a up
133	jexec carp_basic_v6_one ifconfig ${epair_two}a up
134
135	jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 \
136	    2001:db8::1:2/64 up no_dad
137	jexec carp_basic_v6_two ifconfig ${epair_one}b inet6 add vhid 1 \
138	    2001:db8::0:1/64
139
140	jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 2001:db8::1:3/64 up no_dad
141	jexec carp_basic_v6_three ifconfig ${epair_two}b inet6 add vhid 1 \
142	    2001:db8::0:1/64
143
144	wait_for_carp carp_basic_v6_two ${epair_one}b \
145	    carp_basic_v6_three ${epair_two}b
146
147	atf_check -s exit:0 -o ignore jexec carp_basic_v6_one \
148	    ping -6 -c 3 2001:db8::0:1
149}
150
151basic_v6_cleanup()
152{
153	vnet_cleanup
154}
155
156atf_test_case "negative_demotion" "cleanup"
157negative_demotion_head()
158{
159	atf_set descr 'Test PR #259528'
160	atf_set require.user root
161}
162
163negative_demotion_body()
164{
165	carp_init
166
167	epair=$(vnet_mkepair)
168
169	vnet_mkjail one ${epair}a
170	jexec one sysctl net.inet.carp.preempt=1
171	jexec one ifconfig ${epair}a 192.0.2.1/24 up
172	jexec one ifconfig ${epair}a add vhid 1 192.0.2.254/24 \
173	    advskew 0 pass foobar
174
175	vnet_mkjail two ${epair}b
176	jexec two sysctl net.inet.carp.preempt=1
177	jexec two ifconfig ${epair}b 192.0.2.2/24 up
178	jexec two ifconfig ${epair}b add vhid 1 192.0.2.254/24 \
179	    advskew 100 pass foobar
180
181	# Allow things to settle
182	wait_for_carp one ${epair}a two ${epair}b
183
184	if is_master one ${epair}a && is_master two ${epair}b
185	then
186		atf_fail "Two masters!"
187	fi
188
189	jexec one sysctl net.inet.carp.demotion=-1
190	sleep 3
191
192	if is_master one ${epair}a && is_master two ${epair}b
193	then
194		atf_fail "Two masters!"
195	fi
196}
197
198negative_demotion_cleanup()
199{
200	vnet_cleanup
201}
202
203
204
205atf_test_case "nd6_ns_source_mac" "cleanup"
206nd6_ns_source_mac_head()
207{
208        atf_set descr 'CARP ndp neighbor solicitation MAC source test (IPv6)'
209        atf_set require.user root
210}
211
212nd6_ns_source_mac_body()
213{
214        carp_init
215
216        bridge=$(vnet_mkbridge)
217        epair_one=$(vnet_mkepair)
218        epair_two=$(vnet_mkepair)
219
220        vnet_mkjail carp_ndp_v6_bridge ${bridge} ${epair_one}a ${epair_two}a
221        vnet_mkjail carp_ndp_v6_master ${epair_one}b
222        vnet_mkjail carp_ndp_v6_slave ${epair_two}b
223
224        jexec carp_ndp_v6_bridge ifconfig ${bridge} inet6 2001:db8::0:4/64 up \
225            no_dad
226        jexec carp_ndp_v6_bridge ifconfig ${bridge} addm ${epair_one}a \
227            addm ${epair_two}a
228        jexec carp_ndp_v6_bridge ifconfig ${epair_one}a up
229        jexec carp_ndp_v6_bridge ifconfig ${epair_two}a up
230
231        jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 \
232            2001:db8::1:2/64 up no_dad
233        jexec carp_ndp_v6_master ifconfig ${epair_one}b inet6 add vhid 1 \
234            advskew 0 2001:db8::0:1/64
235
236        jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 \
237	    2001:db8::1:3/64 up no_dad
238        jexec carp_ndp_v6_slave ifconfig ${epair_two}b inet6 add vhid 1 \
239            advskew 100 2001:db8::0:1/64
240
241        wait_for_carp carp_ndp_v6_master ${epair_one}b \
242            carp_ndp_v6_slave ${epair_two}b
243
244	# carp_ndp_v6_master is MASTER
245
246	# trigger a NS from the virtual IP from the BACKUP
247        atf_check -s exit:2 -o ignore jexec carp_ndp_v6_slave \
248            ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4
249
250	# trigger a NS from the virtual IP from the MASTER,
251	# this ping should work
252        atf_check -s exit:0 -o ignore jexec carp_ndp_v6_master \
253            ping -6 -c 3 -S 2001:db8::0:1 2001:db8::0:4
254
255        # ndp entry should be for the virtual mac
256        atf_check -o match:'2001:db8::1 +00:00:5e:00:01:01' \
257	    jexec carp_ndp_v6_bridge ndp -an
258}
259
260nd6_ns_source_mac_cleanup()
261{
262        vnet_cleanup
263}
264
265
266atf_init_test_cases()
267{
268	atf_add_test_case "basic_v4"
269	atf_add_test_case "basic_v6"
270	atf_add_test_case "negative_demotion"
271	atf_add_test_case "nd6_ns_source_mac"
272}
273