xref: /freebsd/tests/sys/netpfil/pf/pfsync.sh (revision bdcbfde31e8e9b343f113a1956384bdf30d1ed62)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2018 Orange Business Services
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)/utils.subr
28
29common_dir=$(atf_get_srcdir)/../common
30
31atf_test_case "basic" "cleanup"
32basic_head()
33{
34	atf_set descr 'Basic pfsync test'
35	atf_set require.user root
36}
37
38basic_body()
39{
40	common_body
41}
42
43common_body()
44{
45	defer=$1
46	pfsynct_init
47
48	epair_sync=$(vnet_mkepair)
49	epair_one=$(vnet_mkepair)
50	epair_two=$(vnet_mkepair)
51
52	vnet_mkjail one ${epair_one}a ${epair_sync}a
53	vnet_mkjail two ${epair_two}a ${epair_sync}b
54
55	# pfsync interface
56	jexec one ifconfig ${epair_sync}a 192.0.2.1/24 up
57	jexec one ifconfig ${epair_one}a 198.51.100.1/24 up
58	jexec one ifconfig pfsync0 \
59		syncdev ${epair_sync}a \
60		maxupd 1 \
61		$defer \
62		up
63	jexec two ifconfig ${epair_two}a 198.51.100.2/24 up
64	jexec two ifconfig ${epair_sync}b 192.0.2.2/24 up
65	jexec two ifconfig pfsync0 \
66		syncdev ${epair_sync}b \
67		maxupd 1 \
68		$defer \
69		up
70
71	# Enable pf!
72	jexec one pfctl -e
73	pft_set_rules one \
74		"set skip on ${epair_sync}a" \
75		"pass out keep state"
76	jexec two pfctl -e
77	pft_set_rules two \
78		"set skip on ${epair_sync}b" \
79		"pass out keep state"
80
81	hostid_one=$(jexec one pfctl -si -v | awk '/Hostid:/ { gsub(/0x/, "", $2); printf($2); }')
82
83	ifconfig ${epair_one}b 198.51.100.254/24 up
84
85	ping -c 1 -S 198.51.100.254 198.51.100.1
86
87	# Give pfsync time to do its thing
88	sleep 2
89
90	if ! jexec two pfctl -s states | grep icmp | grep 198.51.100.1 | \
91	    grep 198.51.100.254 ; then
92		atf_fail "state not found on synced host"
93	fi
94
95	if ! jexec two pfctl -sc | grep ""${hostid_one}"";
96	then
97		jexec two pfctl -sc
98		atf_fail "HostID for host one not found on two"
99	fi
100}
101
102basic_cleanup()
103{
104	pfsynct_cleanup
105}
106
107atf_test_case "basic_defer" "cleanup"
108basic_defer_head()
109{
110	atf_set descr 'Basic defer mode pfsync test'
111	atf_set require.user root
112}
113
114basic_defer_body()
115{
116	common_body defer
117}
118
119basic_defer_cleanup()
120{
121	pfsynct_cleanup
122}
123
124atf_test_case "defer" "cleanup"
125defer_head()
126{
127	atf_set descr 'Defer mode pfsync test'
128	atf_set require.user root
129	atf_set require.progs scapy
130}
131
132defer_body()
133{
134	pfsynct_init
135
136	epair_sync=$(vnet_mkepair)
137	epair_in=$(vnet_mkepair)
138	epair_out=$(vnet_mkepair)
139
140	vnet_mkjail alcatraz ${epair_sync}a ${epair_in}a ${epair_out}a
141
142	jexec alcatraz ifconfig ${epair_sync}a 192.0.2.1/24 up
143	jexec alcatraz ifconfig ${epair_out}a 198.51.100.1/24 up
144	jexec alcatraz ifconfig ${epair_in}a 203.0.113.1/24 up
145	jexec alcatraz arp -s 203.0.113.2 00:01:02:03:04:05
146	jexec alcatraz sysctl net.inet.ip.forwarding=1
147
148	# Set a long defer delay
149	jexec alcatraz sysctl net.pfsync.defer_delay=2500
150
151	jexec alcatraz ifconfig pfsync0 \
152		syncdev ${epair_sync}a \
153		maxupd 1 \
154		defer \
155		up
156
157	ifconfig ${epair_sync}b 192.0.2.2/24 up
158	ifconfig ${epair_out}b 198.51.100.2/24 up
159	ifconfig ${epair_in}b up
160	route add -net 203.0.113.0/24 198.51.100.1
161
162	# Enable pf
163	jexec alcatraz sysctl net.pf.filter_local=0
164	jexec alcatraz pfctl -e
165	pft_set_rules alcatraz \
166		"set skip on ${epair_sync}a" \
167		"pass keep state"
168
169	atf_check -s exit:0 env PYTHONPATH=${common_dir} \
170		$(atf_get_srcdir)/pfsync_defer.py \
171		--syncdev ${epair_sync}b \
172		--indev ${epair_in}b \
173		--outdev ${epair_out}b
174
175	# Now disable defer mode and expect failure.
176	jexec alcatraz ifconfig pfsync0 -defer
177
178	# Flush state
179	pft_set_rules alcatraz \
180		"set skip on ${epair_sync}a" \
181		"pass keep state"
182
183	atf_check -s exit:3 env PYTHONPATH=${common_dir} \
184		$(atf_get_srcdir)/pfsync_defer.py \
185		--syncdev ${epair_sync}b \
186		--indev ${epair_in}b \
187		--outdev ${epair_out}b
188}
189
190defer_cleanup()
191{
192	pfsynct_cleanup
193}
194
195atf_test_case "bulk" "cleanup"
196bulk_head()
197{
198	atf_set descr 'Test bulk updates'
199	atf_set require.user root
200}
201
202bulk_body()
203{
204	pfsynct_init
205
206	epair_sync=$(vnet_mkepair)
207	epair_one=$(vnet_mkepair)
208	epair_two=$(vnet_mkepair)
209
210	vnet_mkjail one ${epair_one}a ${epair_sync}a
211	vnet_mkjail two ${epair_two}a ${epair_sync}b
212
213	# pfsync interface
214	jexec one ifconfig ${epair_sync}a 192.0.2.1/24 up
215	jexec one ifconfig ${epair_one}a 198.51.100.1/24 up
216	jexec one ifconfig pfsync0 \
217		syncdev ${epair_sync}a \
218		maxupd 1\
219		up
220	jexec two ifconfig ${epair_two}a 198.51.100.2/24 up
221	jexec two ifconfig ${epair_sync}b 192.0.2.2/24 up
222
223	# Enable pf
224	jexec one pfctl -e
225	pft_set_rules one \
226		"set skip on ${epair_sync}a" \
227		"pass keep state"
228	jexec two pfctl -e
229	pft_set_rules two \
230		"set skip on ${epair_sync}b" \
231		"pass keep state"
232
233	ifconfig ${epair_one}b 198.51.100.254/24 up
234
235	# Create state prior to setting up pfsync
236	ping -c 1 -S 198.51.100.254 198.51.100.1
237
238	# Wait before setting up pfsync on two, so we don't accidentally catch
239	# the update anyway.
240	sleep 1
241
242	# Now set up pfsync in jail two
243	jexec two ifconfig pfsync0 \
244		syncdev ${epair_sync}b \
245		up
246
247	# Give pfsync time to do its thing
248	sleep 2
249
250	jexec two pfctl -s states
251	if ! jexec two pfctl -s states | grep icmp | grep 198.51.100.1 | \
252	    grep 198.51.100.2 ; then
253		atf_fail "state not found on synced host"
254	fi
255}
256
257bulk_cleanup()
258{
259	pfsynct_cleanup
260}
261
262atf_test_case "pbr" "cleanup"
263pbr_head()
264{
265	atf_set descr 'route_to and reply_to directives test'
266	atf_set require.user root
267	atf_set timeout '600'
268}
269
270pbr_body()
271{
272	pbr_common_body
273}
274
275pbr_cleanup()
276{
277	pbr_common_cleanup
278}
279
280atf_test_case "pfsync_pbr" "cleanup"
281pfsync_pbr_head()
282{
283	atf_set descr 'route_to and reply_to directives pfsync test'
284	atf_set require.user root
285	atf_set timeout '600'
286}
287
288pfsync_pbr_body()
289{
290	pbr_common_body backup_promotion
291}
292
293pfsync_pbr_cleanup()
294{
295	pbr_common_cleanup
296}
297
298pbr_common_body()
299{
300	# + builds bellow topology and initiate a single ping session
301	#   from client to server.
302	# + gw* forward traffic through pbr not fib lookups.
303	# + if backup_promotion arg is given, a carp failover event occurs
304	#   during the ping session on both gateways.
305	#                   ┌──────┐
306	#                   │client│
307	#                   └───┬──┘
308	#                       │
309	#                   ┌───┴───┐
310	#                   │bridge0│
311	#                   └┬─────┬┘
312	#                    │     │
313	#   ┌────────────────┴─┐ ┌─┴────────────────┐
314	#   │gw_route_to_master├─┤gw_route_to_backup│
315	#   └────────────────┬─┘ └─┬────────────────┘
316	#                    │     │
317	#                   ┌┴─────┴┐
318	#                   │bridge1│
319	#                   └┬─────┬┘
320	#                    │     │
321	#   ┌────────────────┴─┐ ┌─┴────────────────┐
322	#   │gw_reply_to_master├─┤gw_reply_to_backup│
323	#   └────────────────┬─┘ └─┬────────────────┘
324	#                    │     │
325	#                   ┌┴─────┴┐
326	#                   │bridge2│
327	#                   └───┬───┘
328	#                       │
329	#                   ┌───┴──┐
330	#                   │server│
331	#                   └──────┘
332
333	if ! kldstat -q -m carp
334	then
335		atf_skip "This test requires carp"
336	fi
337	pfsynct_init
338
339	bridge0=$(vnet_mkbridge)
340	bridge1=$(vnet_mkbridge)
341	bridge2=$(vnet_mkbridge)
342
343	epair_sync_gw_route_to=$(vnet_mkepair)
344	epair_sync_gw_reply_to=$(vnet_mkepair)
345	epair_client_bridge0=$(vnet_mkepair)
346
347	epair_gw_route_to_master_bridge0=$(vnet_mkepair)
348	epair_gw_route_to_backup_bridge0=$(vnet_mkepair)
349	epair_gw_route_to_master_bridge1=$(vnet_mkepair)
350	epair_gw_route_to_backup_bridge1=$(vnet_mkepair)
351
352	epair_gw_reply_to_master_bridge1=$(vnet_mkepair)
353	epair_gw_reply_to_backup_bridge1=$(vnet_mkepair)
354	epair_gw_reply_to_master_bridge2=$(vnet_mkepair)
355	epair_gw_reply_to_backup_bridge2=$(vnet_mkepair)
356
357	epair_server_bridge2=$(vnet_mkepair)
358
359	ifconfig ${bridge0} up
360	ifconfig ${epair_client_bridge0}b up
361	ifconfig ${epair_gw_route_to_master_bridge0}b up
362	ifconfig ${epair_gw_route_to_backup_bridge0}b up
363	ifconfig ${bridge0} \
364		addm ${epair_client_bridge0}b \
365		addm ${epair_gw_route_to_master_bridge0}b \
366		addm ${epair_gw_route_to_backup_bridge0}b
367
368	ifconfig ${bridge1} up
369	ifconfig ${epair_gw_route_to_master_bridge1}b up
370	ifconfig ${epair_gw_route_to_backup_bridge1}b up
371	ifconfig ${epair_gw_reply_to_master_bridge1}b up
372	ifconfig ${epair_gw_reply_to_backup_bridge1}b up
373	ifconfig ${bridge1} \
374		addm ${epair_gw_route_to_master_bridge1}b \
375		addm ${epair_gw_route_to_backup_bridge1}b \
376		addm ${epair_gw_reply_to_master_bridge1}b \
377		addm ${epair_gw_reply_to_backup_bridge1}b
378
379	ifconfig ${bridge2} up
380	ifconfig ${epair_gw_reply_to_master_bridge2}b up
381	ifconfig ${epair_gw_reply_to_backup_bridge2}b up
382	ifconfig ${epair_server_bridge2}b up
383	ifconfig ${bridge2} \
384		addm ${epair_gw_reply_to_master_bridge2}b \
385		addm ${epair_gw_reply_to_backup_bridge2}b \
386		addm ${epair_server_bridge2}b
387
388	vnet_mkjail client ${epair_client_bridge0}a
389	jexec client hostname client
390	vnet_mkjail gw_route_to_master \
391		${epair_gw_route_to_master_bridge0}a \
392		${epair_gw_route_to_master_bridge1}a \
393		${epair_sync_gw_route_to}a
394	jexec gw_route_to_master hostname gw_route_to_master
395	vnet_mkjail gw_route_to_backup \
396		${epair_gw_route_to_backup_bridge0}a \
397		${epair_gw_route_to_backup_bridge1}a \
398		${epair_sync_gw_route_to}b
399	jexec gw_route_to_backup hostname gw_route_to_backup
400	vnet_mkjail gw_reply_to_master \
401		${epair_gw_reply_to_master_bridge1}a \
402		${epair_gw_reply_to_master_bridge2}a \
403		${epair_sync_gw_reply_to}a
404	jexec gw_reply_to_master hostname gw_reply_to_master
405	vnet_mkjail gw_reply_to_backup \
406		${epair_gw_reply_to_backup_bridge1}a \
407		${epair_gw_reply_to_backup_bridge2}a \
408		${epair_sync_gw_reply_to}b
409	jexec gw_reply_to_backup hostname gw_reply_to_backup
410	vnet_mkjail server ${epair_server_bridge2}a
411	jexec server hostname server
412
413	jexec client ifconfig ${epair_client_bridge0}a inet 198.18.0.1/24 up
414	jexec client route add 198.18.2.0/24 198.18.0.10
415
416	jexec gw_route_to_master ifconfig ${epair_sync_gw_route_to}a \
417		inet 198.19.10.1/24 up
418	jexec gw_route_to_master ifconfig ${epair_gw_route_to_master_bridge0}a \
419		inet 198.18.0.8/24 up
420	jexec gw_route_to_master ifconfig ${epair_gw_route_to_master_bridge0}a \
421		alias 198.18.0.10/32 vhid 10 pass 3WjvVVw7 advskew 50
422	jexec gw_route_to_master ifconfig ${epair_gw_route_to_master_bridge1}a \
423		inet 198.18.1.8/24 up
424	jexec gw_route_to_master ifconfig ${epair_gw_route_to_master_bridge1}a \
425		alias 198.18.1.10/32 vhid 11 pass 3WjvVVw7 advskew 50
426	jexec gw_route_to_master sysctl net.inet.ip.forwarding=1
427	jexec gw_route_to_master sysctl net.inet.carp.preempt=1
428
429	vnet_ifrename_jail gw_route_to_master ${epair_sync_gw_route_to}a if_pfsync
430	vnet_ifrename_jail gw_route_to_master ${epair_gw_route_to_master_bridge0}a if_br0
431	vnet_ifrename_jail gw_route_to_master ${epair_gw_route_to_master_bridge1}a if_br1
432
433	jexec gw_route_to_master ifconfig pfsync0 \
434		syncpeer 198.19.10.2 \
435		syncdev if_pfsync \
436		maxupd 1 \
437		up
438	pft_set_rules gw_route_to_master \
439		"keep_state = 'tag auth_packet keep state'" \
440		"set timeout { icmp.first 120, icmp.error 60 }" \
441		"block log all" \
442		"pass quick on if_pfsync proto pfsync keep state (no-sync)" \
443		"pass quick on { if_br0 if_br1 } proto carp keep state (no-sync)" \
444		"block drop in quick to 224.0.0.18/32" \
445		"pass out quick tagged auth_packet keep state" \
446		"pass in quick log on if_br0 route-to (if_br1 198.18.1.20) proto { icmp udp tcp } from 198.18.0.0/24 to 198.18.2.0/24 \$keep_state"
447	jexec gw_route_to_master pfctl -e
448
449	jexec gw_route_to_backup ifconfig ${epair_sync_gw_route_to}b \
450		inet 198.19.10.2/24 up
451	jexec gw_route_to_backup ifconfig ${epair_gw_route_to_backup_bridge0}a \
452		inet 198.18.0.9/24 up
453	jexec gw_route_to_backup ifconfig ${epair_gw_route_to_backup_bridge0}a \
454		alias 198.18.0.10/32 vhid 10 pass 3WjvVVw7 advskew 100
455	jexec gw_route_to_backup ifconfig ${epair_gw_route_to_backup_bridge1}a \
456		inet 198.18.1.9/24 up
457	jexec gw_route_to_backup ifconfig ${epair_gw_route_to_backup_bridge1}a \
458		alias 198.18.1.10/32 vhid 11 pass 3WjvVVw7 advskew 100
459	jexec gw_route_to_backup sysctl net.inet.ip.forwarding=1
460	jexec gw_route_to_backup sysctl net.inet.carp.preempt=1
461
462	vnet_ifrename_jail gw_route_to_backup ${epair_sync_gw_route_to}b if_pfsync
463	vnet_ifrename_jail gw_route_to_backup ${epair_gw_route_to_backup_bridge0}a if_br0
464	vnet_ifrename_jail gw_route_to_backup ${epair_gw_route_to_backup_bridge1}a if_br1
465
466	jexec gw_route_to_backup ifconfig pfsync0 \
467		syncpeer 198.19.10.1 \
468		syncdev if_pfsync \
469		up
470	pft_set_rules gw_route_to_backup \
471		"keep_state = 'tag auth_packet keep state'" \
472		"set timeout { icmp.first 120, icmp.error 60 }" \
473		"block log all" \
474		"pass quick on if_pfsync proto pfsync keep state (no-sync)" \
475		"pass quick on { if_br0 if_br1 } proto carp keep state (no-sync)" \
476		"block drop in quick to 224.0.0.18/32" \
477		"pass out quick tagged auth_packet keep state" \
478		"pass in quick log on if_br0 route-to (if_br1 198.18.1.20) proto { icmp udp tcp } from 198.18.0.0/24 to 198.18.2.0/24 \$keep_state"
479	jexec gw_route_to_backup pfctl -e
480
481	jexec gw_reply_to_master ifconfig ${epair_sync_gw_reply_to}a \
482		inet 198.19.20.1/24 up
483	jexec gw_reply_to_master ifconfig ${epair_gw_reply_to_master_bridge1}a \
484		inet 198.18.1.18/24 up
485	jexec gw_reply_to_master ifconfig ${epair_gw_reply_to_master_bridge1}a \
486		alias 198.18.1.20/32 vhid 21 pass 3WjvVVw7 advskew 50
487	jexec gw_reply_to_master ifconfig ${epair_gw_reply_to_master_bridge2}a \
488		inet 198.18.2.18/24 up
489	jexec gw_reply_to_master ifconfig ${epair_gw_reply_to_master_bridge2}a \
490		alias 198.18.2.20/32 vhid 22 pass 3WjvVVw7 advskew 50
491	jexec gw_reply_to_master sysctl net.inet.ip.forwarding=1
492	jexec gw_reply_to_master sysctl net.inet.carp.preempt=1
493
494	vnet_ifrename_jail gw_reply_to_master ${epair_sync_gw_reply_to}a if_pfsync
495	vnet_ifrename_jail gw_reply_to_master ${epair_gw_reply_to_master_bridge1}a if_br1
496	vnet_ifrename_jail gw_reply_to_master ${epair_gw_reply_to_master_bridge2}a if_br2
497
498	jexec gw_reply_to_master ifconfig pfsync0 \
499		syncpeer 198.19.20.2 \
500		syncdev if_pfsync \
501		maxupd 1 \
502		up
503	pft_set_rules gw_reply_to_master \
504		"set timeout { icmp.first 120, icmp.error 60 }" \
505		"block log all" \
506		"pass quick on if_pfsync proto pfsync keep state (no-sync)" \
507		"pass quick on { if_br1 if_br2 } proto carp keep state (no-sync)" \
508		"block drop in quick to 224.0.0.18/32" \
509		"pass out quick on if_br2 reply-to (if_br1 198.18.1.10) tagged auth_packet_reply_to keep state" \
510		"pass in quick log on if_br1 proto { icmp udp tcp } from 198.18.0.0/24 to 198.18.2.0/24 tag auth_packet_reply_to keep state"
511	jexec gw_reply_to_master pfctl -e
512
513	jexec gw_reply_to_backup ifconfig ${epair_sync_gw_reply_to}b \
514		inet 198.19.20.2/24 up
515	jexec gw_reply_to_backup ifconfig ${epair_gw_reply_to_backup_bridge1}a \
516		inet 198.18.1.19/24 up
517	jexec gw_reply_to_backup ifconfig ${epair_gw_reply_to_backup_bridge1}a \
518		alias 198.18.1.20/32 vhid 21 pass 3WjvVVw7 advskew 100
519	jexec gw_reply_to_backup ifconfig ${epair_gw_reply_to_backup_bridge2}a \
520		inet 198.18.2.19/24 up
521	jexec gw_reply_to_backup ifconfig ${epair_gw_reply_to_backup_bridge2}a \
522		alias 198.18.2.20/32 vhid 22 pass 3WjvVVw7 advskew 100
523	jexec gw_reply_to_backup sysctl net.inet.ip.forwarding=1
524	jexec gw_reply_to_backup sysctl net.inet.carp.preempt=1
525
526	vnet_ifrename_jail gw_reply_to_backup ${epair_sync_gw_reply_to}b if_pfsync
527	vnet_ifrename_jail gw_reply_to_backup ${epair_gw_reply_to_backup_bridge1}a if_br1
528	vnet_ifrename_jail gw_reply_to_backup ${epair_gw_reply_to_backup_bridge2}a if_br2
529
530	jexec gw_reply_to_backup ifconfig pfsync0 \
531		syncpeer 198.19.20.1 \
532		syncdev if_pfsync \
533		up
534	pft_set_rules gw_reply_to_backup \
535		"set timeout { icmp.first 120, icmp.error 60 }" \
536		"block log all" \
537		"pass quick on if_pfsync proto pfsync keep state (no-sync)" \
538		"pass quick on { if_br1 if_br2 } proto carp keep state (no-sync)" \
539		"block drop in quick to 224.0.0.18/32" \
540		"pass out quick on if_br2 reply-to (if_br1 198.18.1.10) tagged auth_packet_reply_to keep state" \
541		"pass in quick log on if_br1 proto { icmp udp tcp } from 198.18.0.0/24 to 198.18.2.0/24 tag auth_packet_reply_to keep state"
542	jexec gw_reply_to_backup pfctl -e
543
544	jexec server ifconfig ${epair_server_bridge2}a inet 198.18.2.1/24 up
545	jexec server route add 198.18.0.0/24 198.18.2.20
546
547	# Waiting for platform to settle
548	while ! jexec gw_route_to_backup ifconfig | grep 'carp: BACKUP'
549	do
550		sleep 1
551	done
552	while ! jexec gw_reply_to_backup ifconfig | grep 'carp: BACKUP'
553	do
554		sleep 1
555	done
556	while ! jexec client ping -c 10 198.18.2.1 | grep ', 0.0% packet loss'
557	do
558		sleep 1
559	done
560
561	# Checking cluster members pf.conf checksums match
562	gw_route_to_master_checksum=$(jexec gw_route_to_master pfctl -si -v | grep 'Checksum:' | cut -d ' ' -f 2)
563	gw_route_to_backup_checksum=$(jexec gw_route_to_backup pfctl -si -v | grep 'Checksum:' | cut -d ' ' -f 2)
564	gw_reply_to_master_checksum=$(jexec gw_reply_to_master pfctl -si -v | grep 'Checksum:' | cut -d ' ' -f 2)
565	gw_reply_to_backup_checksum=$(jexec gw_reply_to_backup pfctl -si -v | grep 'Checksum:' | cut -d ' ' -f 2)
566	if [ "$gw_route_to_master_checksum" != "$gw_route_to_backup_checksum" ]
567	then
568		atf_fail "gw_route_to cluster members pf.conf do not match each others"
569	fi
570	if [ "$gw_reply_to_master_checksum" != "$gw_reply_to_backup_checksum" ]
571	then
572		atf_fail "gw_reply_to cluster members pf.conf do not match each others"
573	fi
574
575	# Creating state entries
576	(jexec client ping -c 10 198.18.2.1 >ping.stdout) &
577
578	if [ "$1" = "backup_promotion" ]
579	then
580		sleep 1
581		jexec gw_route_to_backup ifconfig if_br0 vhid 10 advskew 0
582		jexec gw_route_to_backup ifconfig if_br1 vhid 11 advskew 0
583		jexec gw_reply_to_backup ifconfig if_br1 vhid 21 advskew 0
584		jexec gw_reply_to_backup ifconfig if_br2 vhid 22 advskew 0
585	fi
586	while ! grep -q -e 'packet loss' ping.stdout
587	do
588		sleep 1
589	done
590
591	atf_check -s exit:0 -e ignore -o ignore grep ', 0.0% packet loss' ping.stdout
592}
593
594pbr_common_cleanup()
595{
596	pft_cleanup
597}
598
599atf_test_case "ipsec" "cleanup"
600ipsec_head()
601{
602	atf_set descr 'Transport pfsync over IPSec'
603	atf_set require.user root
604}
605
606ipsec_body()
607{
608	if ! sysctl -q kern.features.ipsec >/dev/null ; then
609		atf_skip "This test requires ipsec"
610	fi
611
612	# Run the common test, to set up pfsync
613	common_body
614
615	# But we want unicast pfsync
616	jexec one ifconfig pfsync0 syncpeer 192.0.2.2
617	jexec two ifconfig pfsync0 syncpeer 192.0.2.1
618
619	# Flush existing states
620	jexec one pfctl -Fs
621	jexec two pfctl -Fs
622
623	# Now define an ipsec policy to run over the epair_sync interfaces
624	echo "flush;
625	spdflush;
626	spdadd 192.0.2.1/32 192.0.2.2/32 any -P out ipsec esp/transport//require;
627	spdadd 192.0.2.2/32 192.0.2.1/32 any -P in ipsec esp/transport//require;
628	add 192.0.2.1 192.0.2.2 esp 0x1000 -E aes-gcm-16 \"12345678901234567890\";
629	add 192.0.2.2 192.0.2.1 esp 0x1001 -E aes-gcm-16 \"12345678901234567890\";" \
630	    | jexec one setkey -c
631
632	echo "flush;
633	spdflush;
634	spdadd 192.0.2.2/32 192.0.2.1/32 any -P out ipsec esp/transport//require;
635	spdadd 192.0.2.1/32 192.0.2.2/32 any -P in ipsec esp/transport//require;
636	add 192.0.2.1 192.0.2.2 esp 0x1000 -E aes-gcm-16 \"12345678901234567891\";
637	add 192.0.2.2 192.0.2.1 esp 0x1001 -E aes-gcm-16 \"12345678901234567891\";" \
638	    | jexec two setkey -c
639
640	# We've set incompatible keys, so pfsync will be broken.
641	ping -c 1 -S 198.51.100.254 198.51.100.1
642
643	# Give pfsync time to do its thing
644	sleep 2
645
646	if jexec two pfctl -s states | grep icmp | grep 198.51.100.1 | \
647	    grep 198.51.100.2 ; then
648		atf_fail "state synced although IPSec should have prevented it"
649	fi
650
651	# Flush existing states
652	jexec one pfctl -Fs
653	jexec two pfctl -Fs
654
655	# Fix the IPSec key to match
656	echo "flush;
657	spdflush;
658	spdadd 192.0.2.2/32 192.0.2.1/32 any -P out ipsec esp/transport//require;
659	spdadd 192.0.2.1/32 192.0.2.2/32 any -P in ipsec esp/transport//require;
660	add 192.0.2.1 192.0.2.2 esp 0x1000 -E aes-gcm-16 \"12345678901234567890\";
661	add 192.0.2.2 192.0.2.1 esp 0x1001 -E aes-gcm-16 \"12345678901234567890\";" \
662	    | jexec two setkey -c
663
664	ping -c 1 -S 198.51.100.254 198.51.100.1
665
666	# Give pfsync time to do its thing
667	sleep 2
668
669	if ! jexec two pfctl -s states | grep icmp | grep 198.51.100.1 | \
670	    grep 198.51.100.2 ; then
671		atf_fail "state not found on synced host"
672	fi
673}
674
675ipsec_cleanup()
676{
677	pft_cleanup
678}
679
680atf_test_case "timeout" "cleanup"
681timeout_head()
682{
683	atf_set descr 'Trigger pfsync_timeout()'
684	atf_set require.user root
685}
686
687timeout_body()
688{
689	pft_init
690
691	vnet_mkjail one
692
693	jexec one ifconfig lo0 127.0.0.1/8 up
694	jexec one ifconfig lo0 inet6 ::1/128 up
695
696	pft_set_rules one \
697		"pass all"
698	jexec one pfctl -e
699	jexec one ifconfig pfsync0 defer up
700
701	jexec one ping -c 1 ::1
702	jexec one ping -c 1 127.0.0.1
703
704	# Give pfsync_timeout() time to fire (a callout on a 1 second delay)
705	sleep 2
706}
707
708timeout_cleanup()
709{
710	pft_cleanup
711}
712
713atf_test_case "basic_ipv6_unicast" "cleanup"
714basic_ipv6_unicast_head()
715{
716	atf_set descr 'Basic pfsync test (IPv6)'
717	atf_set require.user root
718}
719
720basic_ipv6_unicast_body()
721{
722	pfsynct_init
723
724	epair_sync=$(vnet_mkepair)
725	epair_one=$(vnet_mkepair)
726	epair_two=$(vnet_mkepair)
727
728	vnet_mkjail one ${epair_one}a ${epair_sync}a
729	vnet_mkjail two ${epair_two}a ${epair_sync}b
730
731	# pfsync interface
732	jexec one ifconfig ${epair_sync}a inet6 fd2c::1/64 no_dad up
733	jexec one ifconfig ${epair_one}a inet6 fd2b::1/64 no_dad up
734	jexec one ifconfig pfsync0 \
735		syncdev ${epair_sync}a \
736		syncpeer fd2c::2 \
737		maxupd 1 \
738		up
739	jexec two ifconfig ${epair_two}a inet6 fd2b::2/64 no_dad up
740	jexec two ifconfig ${epair_sync}b inet6 fd2c::2/64 no_dad up
741	jexec two ifconfig pfsync0 \
742		syncdev ${epair_sync}b \
743		syncpeer fd2c::1 \
744		maxupd 1 \
745		up
746
747	# Enable pf!
748	jexec one pfctl -e
749	pft_set_rules one \
750		"block on ${epair_sync}a inet" \
751		"pass out keep state"
752	jexec two pfctl -e
753	pft_set_rules two \
754		"block on ${epair_sync}b inet" \
755		"pass out keep state"
756
757	ifconfig ${epair_one}b inet6 fd2b::f0/64 no_dad up
758
759	ping6 -c 1 -S fd2b::f0 fd2b::1
760
761	# Give pfsync time to do its thing
762	sleep 2
763
764	if ! jexec two pfctl -s states | grep icmp | grep fd2b::1 | \
765	    grep fd2b::f0 ; then
766		atf_fail "state not found on synced host"
767	fi
768}
769
770basic_ipv6_unicast_cleanup()
771{
772	pfsynct_cleanup
773}
774
775atf_test_case "basic_ipv6" "cleanup"
776basic_ipv6_head()
777{
778	atf_set descr 'Basic pfsync test (IPv6)'
779	atf_set require.user root
780}
781
782basic_ipv6_body()
783{
784	pfsynct_init
785
786	epair_sync=$(vnet_mkepair)
787	epair_one=$(vnet_mkepair)
788	epair_two=$(vnet_mkepair)
789
790	vnet_mkjail one ${epair_one}a ${epair_sync}a
791	vnet_mkjail two ${epair_two}a ${epair_sync}b
792
793	# pfsync interface
794	jexec one ifconfig ${epair_sync}a inet6 fd2c::1/64 no_dad up
795	jexec one ifconfig ${epair_one}a inet6 fd2b::1/64 no_dad up
796	jexec one ifconfig pfsync0 \
797		syncdev ${epair_sync}a \
798		syncpeer ff12::f0 \
799		maxupd 1 \
800		up
801	jexec two ifconfig ${epair_two}a inet6 fd2b::2/64 no_dad up
802	jexec two ifconfig ${epair_sync}b inet6 fd2c::2/64 no_dad up
803	jexec two ifconfig pfsync0 \
804		syncdev ${epair_sync}b \
805		syncpeer ff12::f0 \
806		maxupd 1 \
807		up
808
809	# Enable pf!
810	jexec one pfctl -e
811	pft_set_rules one \
812		"block on ${epair_sync}a inet" \
813		"pass out keep state"
814	jexec two pfctl -e
815	pft_set_rules two \
816		"block on ${epair_sync}b inet" \
817		"pass out keep state"
818
819	ifconfig ${epair_one}b inet6 fd2b::f0/64 no_dad up
820
821	ping6 -c 1 -S fd2b::f0 fd2b::1
822
823	# Give pfsync time to do its thing
824	sleep 2
825
826	if ! jexec two pfctl -s states | grep icmp | grep fd2b::1 | \
827	    grep fd2b::f0 ; then
828		atf_fail "state not found on synced host"
829	fi
830}
831
832basic_ipv6_cleanup()
833{
834	pfsynct_cleanup
835}
836
837atf_test_case "route_to" "cleanup"
838route_to_head()
839{
840	atf_set descr 'Test route-to with default rule'
841	atf_set require.user root
842	atf_set require.progs scapy
843}
844
845route_to_body()
846{
847	pfsynct_init
848
849	epair_sync=$(vnet_mkepair)
850	epair_one=$(vnet_mkepair)
851	epair_two=$(vnet_mkepair)
852	epair_out_one=$(vnet_mkepair)
853	epair_out_two=$(vnet_mkepair)
854
855	vnet_mkjail one ${epair_one}a ${epair_sync}a ${epair_out_one}a
856	vnet_mkjail two ${epair_two}a ${epair_sync}b ${epair_out_two}a
857
858	# pfsync interface
859	jexec one ifconfig ${epair_sync}a 192.0.2.1/24 up
860	jexec one ifconfig ${epair_one}a 198.51.100.1/24 up
861	jexec one ifconfig ${epair_out_one}a 203.0.113.1/24 up
862	jexec one ifconfig ${epair_out_one}a name outif
863	jexec one sysctl net.inet.ip.forwarding=1
864	jexec one arp -s 203.0.113.254 00:01:02:03:04:05
865	jexec one ifconfig pfsync0 \
866		syncdev ${epair_sync}a \
867		maxupd 1 \
868		up
869
870	jexec two ifconfig ${epair_sync}b 192.0.2.2/24 up
871	jexec two ifconfig ${epair_two}a 198.51.100.2/24 up
872	jexec two ifconfig ${epair_out_two}a 203.0.113.2/24 up
873	#jexec two ifconfig ${epair_out_two}a name outif
874	jexec two sysctl net.inet.ip.forwarding=1
875	jexec two arp -s 203.0.113.254 00:01:02:03:04:05
876	jexec two ifconfig pfsync0 \
877		syncdev ${epair_sync}b \
878		maxupd 1 \
879		up
880
881	# Enable pf!
882	jexec one pfctl -e
883	pft_set_rules one \
884		"set skip on ${epair_sync}a" \
885		"pass out route-to (outif 203.0.113.254)"
886	jexec two pfctl -e
887
888	# Make sure we have different rulesets so the synced state is associated with
889	# V_pf_default_rule
890	pft_set_rules two \
891		"set skip on ${epair_sync}b" \
892		"pass out route-to (outif 203.0.113.254)" \
893		"pass out proto tcp"
894
895	ifconfig ${epair_one}b 198.51.100.254/24 up
896	ifconfig ${epair_two}b 198.51.100.253/24 up
897	route add -net 203.0.113.0/24 198.51.100.1
898	ifconfig ${epair_two}b up
899	ifconfig ${epair_out_one}b up
900	ifconfig ${epair_out_two}b up
901
902	atf_check -s exit:0 env PYTHONPATH=${common_dir} \
903		${common_dir}/pft_ping.py \
904		--sendif ${epair_one}b \
905		--fromaddr 198.51.100.254 \
906		--to 203.0.113.254 \
907		--recvif ${epair_out_one}b
908
909	# Allow time for sync
910	ifconfig ${epair_one}b inet 198.51.100.254 -alias
911	route del -net 203.0.113.0/24 198.51.100.1
912	route add -net 203.0.113.0/24 198.51.100.2
913
914	sleep 2
915
916	# Now try to trigger the state on the other pfsync member
917	env PYTHONPATH=${common_dir} \
918		${common_dir}/pft_ping.py \
919		--sendif ${epair_two}b \
920		--fromaddr 198.51.100.254 \
921		--to 203.0.113.254 \
922		--recvif ${epair_out_two}b
923
924	true
925}
926
927route_to_cleanup()
928{
929	pfsynct_cleanup
930}
931
932atf_init_test_cases()
933{
934	atf_add_test_case "basic"
935	atf_add_test_case "basic_defer"
936	atf_add_test_case "defer"
937	atf_add_test_case "bulk"
938	atf_add_test_case "pbr"
939	atf_add_test_case "pfsync_pbr"
940	atf_add_test_case "ipsec"
941	atf_add_test_case "timeout"
942	atf_add_test_case "basic_ipv6_unicast"
943	atf_add_test_case "basic_ipv6"
944	atf_add_test_case "route_to"
945}
946