xref: /freebsd/tests/sys/netinet/carp.sh (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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