xref: /freebsd/tools/test/netfibs/forwarding.sh (revision 783d3ff6d7fae619db8a7990b8a6387de0c677b5)
1#!/bin/sh
2#-
3# Copyright (c) 2012 Cisco Systems, Inc.
4# All rights reserved.
5#
6# This software was developed by Bjoern Zeeb under contract to
7# Cisco Systems, Inc..
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28# SUCH DAMAGE.
29#
30#
31
32# Test setup:
33#
34#  left ------------------------- middle ------------------------- right
35#    IFACE                     IFACE  IFACEFAR                  IFACE
36#    LEFTADDR         MIDDLELEFTADDR  MIDDLERIGHTADDR       RIGHTADDR
37#                               forwarding=1
38#    initiator                   FIB tests                  reflector
39
40# We will use the RFC5180 (and Errata) benchmarking working group prefix
41# 2001:0002::/48 for testing.
42PREFIX="2001:2:"
43
44# Set IFACE to the real interface you want to run the test on.
45# IFACEFAR is only relevant on the middle (forwarding) node and will be the
46# 'right' side (far end) one.
47: ${IFACE:=lo0}
48: ${IFACEFAR:=lo0}
49
50# Number of seconds to wait for peer node to synchronize for test.
51: ${WAITS:=120}
52
53# Control port we use to exchange messages between nodes to sync. tests, etc.
54: ${CTRLPORT:=6666}
55
56# Get the number of FIBs from the kernel.
57RT_NUMFIBS=`sysctl -n net.fibs`
58
59# This is the initiator and connected middle node.
60LEFTADDR="2001:2:fe00::1"
61MIDDLELEFTADDR="2001:2:fe00::2"
62# This is the far end middle node and receiver side.
63MIDDLERIGHTADDR="2001:2:ff00::1"
64RIGHTADDR="2001:2:ff00::2"
65
66# By default all commands must succeed.  Individual tests may disable this
67# temporary.
68set -e
69
70# Debug magic.
71case "${DEBUG}" in
7242)	set -x ;;
73esac
74
75
76################################################################################
77#
78# Input validation.
79#
80
81node=$1
82case ${node} in
83left)	;;
84middle)	;;
85right)	;;
86*)	echo "ERROR: invalid node name '${node}'. Must be left, middle or" \
87	    " right" >&1
88	exit 1
89	;;
90esac
91
92################################################################################
93#
94# Helper functions.
95#
96check_rc()
97{
98	local _rc _exp _testno _testname _msg _r
99	_rc=$1
100	_exp=$2
101	_testno=$3
102	_testname="$4"
103	_msg="$5"
104
105	_r="not ok"
106	if test ${_rc} -eq ${_exp}; then
107		_r="ok"
108	fi
109	echo "${_r} ${_testno} ${_testname} # ${_msg} ${_rc} ${_exp}"
110}
111
112print_debug()
113{
114	local _msg
115	_msg="$*"
116
117	case ${DEBUG} in
118	''|0)	;;
119	*)	echo "DEBUG: ${_msg}" >&2 ;;
120	esac
121}
122
123die()
124{
125	local _msg
126	_msg="$*"
127
128	echo "ERROR: ${_msg}" >&2
129	exit 1
130}
131
132
133################################################################################
134#
135# Functions to configure networking and do a basic reachability check.
136#
137
138setup_networking()
139{
140
141	print_debug "Setting up networking"
142	case ${node} in
143	left)	ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias \
144		    > /dev/null 2>&1 || true
145		ifconfig ${IFACE} inet6 ${LEFTADDR}/64 alias up
146		ifconfig ${IFACE} fib 0
147		sysctl net.inet6.ip6.forwarding=0 > /dev/null
148		route delete -net -inet6 default > /dev/null 2>&1 || true
149		route delete -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \
150		    > /dev/null 2>&1 || true
151		route add -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \
152		    > /dev/null
153		route delete -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \
154		    > /dev/null 2>&1 || true
155		route add -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \
156		    > /dev/null 2>&1 || true
157		;;
158	middle)	ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias \
159		    > /dev/null 2>&1 || true
160		ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 alias up
161		ifconfig ${IFACE} fib 0
162		ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias \
163		    > /dev/null 2>&1 || true
164		ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 alias up
165		ifconfig ${IFACEFAR} fib 0
166		sysctl net.inet6.ip6.forwarding=1 > /dev/null
167		;;
168	right)	ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias \
169		    > /dev/null 2>&1 || true
170		ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 alias up
171		ifconfig ${IFACE} fib 0
172		sysctl net.inet6.ip6.forwarding=0 > /dev/null
173		route delete -net -inet6 default > /dev/null 2>&1 || true
174		route delete -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \
175		    > /dev/null 2>&1 || true
176		route add -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \
177		    > /dev/null
178		route delete -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \
179		    > /dev/null 2>&1 || true
180		route add -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \
181		    > /dev/null
182		;;
183	esac
184
185	# Let things settle.
186	print_debug "Waiting 4 seconds for things to settle"
187	sleep 4
188}
189
190cleanup_networking()
191{
192
193	case ${node} in
194	left)	ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias
195		;;
196	middle)	ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias
197		ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias
198		sysctl net.inet6.ip6.forwarding=0 > /dev/null
199		;;
200	right)	ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias
201		;;
202	esac
203	print_debug "Cleaned up networking"
204}
205
206_reachability_check()
207{
208	local _addr _rc
209	_addr="$1"
210
211	ping6 -n -c1 ${_addr} > /dev/null 2>&1
212	_rc=$?
213	case ${_rc} in
214	0)	;;
215	*)	print_debug "cannot ping6 ${_addr}, rc=${_rc}"
216		return 1
217		;;
218	esac
219	return 0
220}
221
222reachability_check()
223{
224	local _i rc
225
226	# Try to reach all control addresses on other nodes.
227	# We need to loop for a while as we cannot expect all to be up
228	# the very same moment.
229	i=1
230	rc=42
231	while test ${rc} -ne 0 -a ${i} -le ${WAITS}; do
232		print_debug "${i}/${WAITS} trying to ping6 control addresses."
233		rc=0
234		set +e
235		case ${node} in
236		left)	_reachability_check ${MIDDLELEFTADDR}
237			rc=$((rc + $?))
238			_reachability_check ${MIDDLERIGHTADDR}
239			rc=$((rc + $?))
240			_reachability_check ${RIGHTADDR}
241			rc=$((rc + $?))
242			;;
243		middle)	_reachability_check ${LEFTADDR}
244			rc=$((rc + $?))
245			_reachability_check ${RIGHTADDR}
246			rc=$((rc + $?))
247			;;
248		right)	_reachability_check ${MIDDLERIGHTADDR}
249			rc=$((rc + $?))
250			_reachability_check ${MIDDLELEFTADDR}
251			rc=$((rc + $?))
252			_reachability_check ${LEFTADDR}
253			rc=$((rc + $?))
254			;;
255		esac
256		set -e
257		sleep 1
258		i=$((i + 1))
259	done
260}
261
262################################################################################
263#
264# "Greeting" handling to sync notes to the agreed upon next test case.
265#
266send_control_msg()
267{
268        local _case _addr i rc _msg _keyword _fibs
269	_case="$1"
270	_addr="$2"
271
272	set +e
273	i=0
274	rc=-1
275	while test ${i} -lt ${WAITS} -a ${rc} -ne 0; do
276		print_debug "Sending control msg #${i} to peer ${_addr}"
277		_msg=`echo "${_case} ${RT_NUMFIBS}" | \
278		    nc -6 -w 1 ${_addr} ${CTRLPORT}`
279		rc=$?
280		i=$((i + 1))
281		# Might sleep longer in total but better than to DoS
282		# and not get anywhere.
283		sleep 1
284	done
285	set -e
286
287	read _keyword _fibs <<EOI
288${_msg}
289EOI
290	print_debug "_keyword=${_keyword}"
291	print_debug "_fibs=${_fibs}"
292	case ${_keyword} in
293	${_case});;
294	*)	die "Got invalid keyword from ${_addr} in control message:" \
295		    "${_msg}"
296	;;
297	esac
298	if test ${_fibs} -ne ${RT_NUMFIBS}; then
299		die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
300		    "control message from ${_addr}: ${_msg}"
301	fi
302
303	print_debug "Successfully exchanged control message with ${_addr}."
304}
305
306send_control_msgs()
307{
308	local _case _addr
309	_case="$1"
310
311	# Always start with the far end.  Otherwise we will cut that off when
312	# cleanly taering down things again.
313	for _addr in ${RIGHTADDR} ${MIDDLELEFTADDR}; do
314		send_control_msg "${_case}" ${_addr}
315	done
316
317	# Allow us to flush ipfw counters etc before new packets will arrive.
318	sleep 1
319}
320
321# We are setup.  Wait for the initiator to tell us that it is ready.
322wait_remote_ready()
323{
324        local _case _msg _keyword _fibs
325	_case="$1"
326
327	# Wait for the remote to connect and start things.
328	# We tell it the magic keyword, and our number of FIBs.
329	_msg=`echo "${_case} ${RT_NUMFIBS}" | nc -6 -l ${CTRLPORT}`
330
331	read _keyword _fibs <<EOI
332${_msg}
333EOI
334	print_debug "_keyword=${_keyword}"
335	print_debug "_fibs=${_fibs}"
336	case ${_keyword} in
337	${_case});;
338	*)	die "Got invalid keyword in control message: ${_msg}"
339		;;
340	esac
341	if test ${_fibs} -ne ${RT_NUMFIBS}; then
342		die "Number of FIBs not matching ours (${RT_NUMFIBS}) in" \
343		    "control message: ${_msg}"
344	fi
345
346	print_debug "Successfully received control message."
347}
348
349################################################################################
350#
351# Test case helper functions.
352#
353# Please note that neither on the intiator nor the reflector are FIBs despite
354# a variable name might indicate.  If such a variable is used it mirrors FIB
355# numbers from the middle node to match for test cases.
356#
357test_icmp6()
358{
359	local _maxfibs _addr _n _testno i _rc _ec
360	_maxfibs=$1
361	_addr="$2"
362	_n="$3"
363
364	printf "1..%d\n" ${_maxfibs}
365	_testno=1
366	set +e
367	i=0
368	while test ${i} -lt ${_maxfibs}; do
369		_txt="${_n}_${i}"
370		print_debug "Testing ${_txt}"
371
372		# Generate HEX for ping6 payload.
373		_fibtxt=`echo "${_txt}" | hd -v | cut -b11-60 | tr -d ' \r\n'`
374
375		eval _rc="\${rc_${i}}"
376		ping6 -n -c1 -p ${_fibtxt} ${_addr} > /dev/null 2>&1
377		_ec=$?
378		# We need to normalize the exit code of ping6.
379		case ${_ec} in
380		0)	;;
381		*)	_ec=1 ;;
382		esac
383		check_rc ${_ec} ${_rc} ${_testno} "${_txt}" "FIB ${i} ${_addr}"
384		testno=$((testno + 1))
385		i=$((i + 1))
386	done
387	set -e
388}
389
390test_ulp_reflect_one()
391{
392	local _txt _opts port fib
393	_txt="$1"
394	_opts="$2"
395	port=$3
396	fib=$4
397
398	print_debug "./reflect -p $((port + 1 + fib)) -t ${_txt}" "${_opts}"
399	./reflect -p $((port + 1 + fib)) -t ${_txt} ${_opts}
400	print_debug "reflect '${_txt}' terminated without error."
401}
402
403test_ulp_reflect_multiple()
404{
405	local _maxfibs _txt _opts i _jobs _p
406	_maxfibs=$1
407	_txt="$2"
408	_opts="$3"
409
410	i=0
411	_jobs=""
412	while test ${i} -lt ${_maxfibs}; do
413		print_debug "./reflect -p $((CTRLPORT + 1000 + i))" \
414		    "-t ${_txt} ${_opts} -N -f ${i} &"
415		./reflect -p $((CTRLPORT + 1000 + i)) \
416		    -t ${_txt} ${_opts} -N -f ${i} &
417		_p=$!
418		_jobs="${_jobs}${_p} "
419		i=$((i + 1))
420	done
421
422	# Start OOB control connection for START/DONE.
423	testrx_run_one "${_txt}" "${_opts}"
424	print_debug "KILL ${_jobs}"
425	for i in ${_jobs}; do
426		kill ${i} || true
427	done
428	#killall reflect || true
429	print_debug "reflects for '${_txt}' terminated without error."
430}
431
432nc_send_recv()
433{
434	local _loops _msg _expreply _addr _port _opts i
435	_loops=$1
436	_msg="$2"
437	_expreply="$3"
438	_addr=$4
439	_port=$5
440	_opts="$6"
441
442	i=0
443	while test ${i} -lt ${_loops}; do
444		i=$((i + 1))
445		print_debug "e ${_msg} | nc -6 -w1 ${_opts} ${_addr} ${_port}"
446		_reply=`echo "${_msg}" | nc -6 -w1 ${_opts} ${_addr} ${_port}`
447		if test "${_reply}" != "${_expreply}"; then
448			if test ${i} -lt ${_loops}; then
449				sleep 1
450			else
451			# Must let caller decide how to handle the error.
452			#	die "Got invalid reply from peer." \
453			#	    "Expected '${_expreply}', got '${_reply}'"
454				return 1
455			fi
456		else
457			break
458		fi
459	done
460	return 0
461}
462
463test_ulp()
464{
465	local maxfibs _msg _addr port fib i _txt testno _rc _reply
466	maxfibs=$1
467	_msg="$2"
468	_addr=$3
469	port=$4
470	fib=$5
471
472	printf "1..%d\n" $((${maxfibs} * 2))
473	testno=1
474	i=0
475	while test ${i} -lt ${maxfibs}; do
476
477		if test ${i} -eq $((${maxfibs} - 1)); then
478			# Last one; signal DONE.
479			_txt="DONE ${_msg}_${i}"
480		else
481			_txt="DONE ${_msg}_${i}"
482		fi
483
484		eval _rc="\${rc_${i}}"
485
486		# Test TCP.
487		nc_send_recv ${maxfibs} "${_txt}" "${_txt}" ${_addr} \
488		    $((${port} + 1 + fib)) ""
489		check_rc $? ${_rc} ${testno} "${_msg}_${i}_tcp" \
490		    "[${_addr}]:$((${port} + 1 + fib)) ${_reply}"
491		testno=$((testno + 1))
492		sleep 1
493
494		# Test UDP.
495		nc_send_recv ${maxfibs} "${_txt}" "${_txt}" ${_addr} \
496		    $((${port} + 1 + fib)) "-u"
497		check_rc $? ${_rc} ${testno} "${_msg}_${i}_udp" \
498		    "[${_addr}]:$((${port} + 1 + fib)) ${_reply}"
499		sleep 1
500
501		i=$((i + 1))
502		testno=$((testno + 1))
503	done
504}
505
506setup_ipfw_count()
507{
508	local i port maxfib _p _fib _ofib
509	port=$1
510	maxfib=$2
511	_fib=$3
512	_ofib=$4
513
514	i=0
515	while test ${i} -lt ${maxfib}; do
516
517		case ${_ofib} in
518		-1)	_p=$((port + 1 + i)) ;;
519		*)	_p=$((port + 1 + maxfib - 1 - i)) ;;
520		esac
521
522		# Only count ICMP6 echo replies.
523		ipfw add $((10000 + i)) count ipv6-icmp from any to any \
524		    icmp6types 129 fib ${i} via ${IFACE} out > /dev/null
525		ipfw add $((10000 + i)) count tcp from any to any \
526		    src-port ${_p} fib ${i}  via ${IFACE} out > /dev/null
527		ipfw add $((10000 + i)) count udp from any to any \
528		    src-port ${_p} fib ${i} via ${IFACE} out > /dev/null
529
530		# Only count ICMP6 echo requests.
531		ipfw add $((20000 + i)) count ipv6-icmp from any to any \
532		    icmp6types 128 fib ${i} via ${IFACEFAR} out > /dev/null
533		ipfw add $((20000 + i)) count tcp from any to any \
534		    dst-port $((${port} + 1 + i)) fib ${i} \
535		    via ${IFACEFAR} out > /dev/null
536		ipfw add $((20000 + i)) count udp from any to any \
537		    dst-port $((${port} + 1 + i)) fib ${i} \
538		    via ${IFACEFAR} out > /dev/null
539
540		i=$((i + 1))
541	done
542}
543
544report_ipfw_count()
545{
546	local _fib _o i _rstr _c _req _p _opts base
547	_o="$2"
548
549	case ${DEBUG} in
550	''|0)	;;
551	*)	ipfw show ;;
552	esac
553
554	_rstr="RESULTS "
555	for base in 10000 20000; do
556		for _o in i t u; do
557			case ${base} in
558			10000)	_rstr="${_rstr}\nLEFT " ;;
559			20000)	_rstr="${_rstr}\nRIGHT " ;;
560			esac
561			case ${_o} in
562			i)	_rstr="${_rstr}ICMP6 " ;;
563			t)	_rstr="${_rstr}TCP " ;;
564			u)	_rstr="${_rstr}UDP " ;;
565			esac
566			i=0
567			while test ${i} -lt ${RT_NUMFIBS}; do
568
569				case "${_o}" in
570				i)	_c=`ipfw show $((${base} + i)) | \
571					    awk '/ ipv6-icmp / { print $2 }'` ;;
572				t)	_c=`ipfw show $((${base} + i)) | \
573					    awk '/ tcp / { print $2 }'` ;;
574				u)	_c=`ipfw show $((${base} + i)) | \
575					    awk '/ udp / { print $2 }'` ;;
576				esac
577				_rstr="${_rstr}${i} ${_c},"
578
579				i=$((i + 1))
580			done
581		done
582		i=0
583		while test ${i} -lt ${RT_NUMFIBS}; do
584			ipfw delete $((${base} + i)) > /dev/null 2>&1 || true
585			i=$((i + 1))
586		done
587	done
588
589	# We do not care about the request.
590	_req=`printf "${_rstr}" | nc -6 -l $((${CTRLPORT} - 1))`
591	print_debug "$? -- ${_req} -- ${_rstr}"
592}
593
594fetch_ipfw_count()
595{
596	local _n _reply _line _edge _type _fib _count _rc _ec _status
597	_n="$1"
598
599	# Leave node some time to build result set.
600	sleep 3
601
602	print_debug "Asking for ipfw count results..."
603	set +e
604	nc_send_recv 1 "RESULT REQUEST" "" ${MIDDLELEFTADDR} \
605	    $((${CTRLPORT} - 1)) ""
606	set -e
607	case "${_reply}" in
608	RESULTS\ *)	;;
609	*)		die "Got invalid reply from peer." \
610			    "Expected 'RESULTS ...', got '${_reply}'" ;;
611	esac
612
613	# Trim "RESULTS "
614	_reply=${_reply#* }
615
616	# FIBs * {left, right} * {icmp6, tcp, udp}
617	printf "1..%d\n" $((RT_NUMFIBS * 2 * 3))
618	testno=1
619	while read _line; do
620		print_debug "_line == ${_line}"
621		_edge=${_line%% *}
622		_line=${_line#* }
623		_type=${_line%% *}
624		_line=${_line#* }
625
626		while read _fib _count; do
627			eval _em="\${rc_${_n}_${_edge}_${_type}_${_fib}}"
628			: ${_em:=-42}
629			if test ${_count} -gt 0; then
630				_rc=1
631			else
632				_rc=0
633			fi
634			if test ${_rc} -eq ${_em}; then
635				_status="ok"
636			else
637				_status="not ok"
638			fi
639			printf "%s %d %s # count=%s _rc=%d _em=%d\n" \
640			    "${_status}" ${testno} "${_n}_${_edge}_${_type}_${_fib}" \
641			    ${_count} ${_rc} ${_em}
642			testno=$((testno + 1))
643		done <<EOi
644`printf "${_line}" | tr ',' '\n'`
645EOi
646
647	done <<EOo
648`printf "${_reply}" | grep -v "^$"`
649EOo
650
651	print_debug "ipfw count results processed"
652}
653
654################################################################################
655#
656# Test cases.
657#
658# In general we set the FIB on in, but count on out.
659#
660
661_fwd_default_fib_symmetric_results()
662{
663	local _n i _edge _type _rc
664	_n="$1"
665
666	i=0
667	while test ${i} -lt ${RT_NUMFIBS}; do
668		for _edge in "LEFT" "RIGHT"; do
669			for _type in "ICMP6" "TCP" "UDP"; do
670
671				case ${i} in
672				0)	eval rc_${_n}_${_edge}_${_type}_${i}=1
673					#print_debug \
674					#   "rc_${_n}_${_edge}_${_type}_${i}=1"
675					;;
676				*)	eval rc_${_n}_${_edge}_${_type}_${i}=0
677					#print_debug \
678					#   "rc_${_n}_${_edge}_${_type}_${i}=0"
679					;;
680				esac
681
682			done
683		done
684		i=$((i + 1))
685	done
686}
687
688_fwd_default_fib_symmetric_left()
689{
690	local _n
691	_n="$1"
692
693	send_control_msgs "START_${_n}"
694
695	# Setup expected return code
696	rc_0=0
697
698	# Initiate probes for ICMP6, TCP and UDP.
699	test_icmp6 1 ${RIGHTADDR} "${_n}_icmp6"
700	test_ulp 1 "${_n}" ${RIGHTADDR} ${CTRLPORT} 0
701
702	send_control_msgs "STOP_${_n}"
703	_fwd_default_fib_symmetric_results "${_n}"
704	fetch_ipfw_count "${_n}"
705}
706
707_fwd_default_fib_symmetric_middle()
708{
709	local _n
710	_n="$1"
711
712	setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
713	wait_remote_ready "START_${_n}"
714	ipfw -q zero > /dev/null
715	# Nothing to do for the middle node testing the default.
716	sleep 1
717	wait_remote_ready "STOP_${_n}"
718	report_ipfw_count
719}
720
721_fwd_default_fib_symmetric_right()
722{
723	local _n
724	_n="$1"
725
726	wait_remote_ready "START_${_n}"
727
728	# No need to do anything for ICMPv6.
729	# Start reflect for TCP and UDP.
730	test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" 0 ${CTRLPORT}
731	test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" 0 ${CTRLPORT}
732
733	wait_remote_ready "STOP_${_n}"
734}
735
736fwd_default_fib_symmetric()
737{
738	local _n
739
740	_n="fwd_default_fib_symmetric"
741
742	print_debug "${_n}"
743	case ${node} in
744	left)	_fwd_default_fib_symmetric_left ${_n} ;;
745	middle)	_fwd_default_fib_symmetric_middle ${_n} ;;
746	right)	_fwd_default_fib_symmetric_right ${_n} ;;
747	esac
748}
749
750_fwd_default_fib_symmetric_middle_ifconfig()
751{
752	local _n
753	_n="$1"
754
755	ifconfig ${IFACE} fib 0
756	ifconfig ${IFACEFAR} fib 0
757	setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
758	wait_remote_ready "START_${_n}"
759	ipfw -q zero > /dev/null
760	# Nothing to do for the middle node testing the default.
761	sleep 1
762	wait_remote_ready "STOP_${_n}"
763	report_ipfw_count
764}
765
766fwd_default_fib_symmetric_ifconfig()
767{
768	local _n
769
770	_n="fwd_default_fib_symmetric_ifconfig"
771
772	print_debug "${_n}"
773	case ${node} in
774	left)	_fwd_default_fib_symmetric_left ${_n} ;;
775	middle)	_fwd_default_fib_symmetric_middle_ifconfig ${_n} ;;
776	right)	_fwd_default_fib_symmetric_right ${_n} ;;
777	esac
778}
779
780_fwd_default_fib_symmetric_middle_ipfw()
781{
782	local _n
783	_n="$1"
784
785	ipfw add 100 setfib 0 ipv6-icmp from any to any \
786	    icmp6types 128 via ${IFACE} in > /dev/null
787	ipfw add 100 setfib 0 ip6 from any to any \
788	    proto tcp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null
789	ipfw add 100 setfib 0 ip6 from any to any \
790	    proto udp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null
791
792	ipfw add 100 setfib 0 ipv6-icmp from any to any \
793	    icmp6types 128 via ${IFACEFAR} in > /dev/null
794	ipfw add 100 setfib 0 tcp from any to any \
795	    dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null
796	ipfw add 100 setfib 0 udp from any to any \
797	    dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null
798
799	setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1
800	wait_remote_ready "START_${_n}"
801	ipfw -q zero > /dev/null
802	# Nothing to do for the middle node testing the default.
803	sleep 1
804	wait_remote_ready "STOP_${_n}"
805	report_ipfw_count
806
807	ipfw delete 100 > /dev/null
808}
809
810fwd_default_fib_symmetric_ipfw()
811{
812	local _n
813
814	_n="fwd_default_fib_symmetric_ipfw"
815
816	print_debug "${_n}"
817	case ${node} in
818	left)	_fwd_default_fib_symmetric_left ${_n} ;;
819	middle)	_fwd_default_fib_symmetric_middle_ipfw ${_n} ;;
820	right)	_fwd_default_fib_symmetric_right ${_n} ;;
821	esac
822}
823
824################################################################################
825
826_fwd_fib_symmetric_results()
827{
828	local _n _fib i _edge _type _rc
829	_n="$1"
830	_fib=$2
831
832	i=0
833	while test ${i} -lt ${RT_NUMFIBS}; do
834		for _edge in "LEFT" "RIGHT"; do
835			for _type in "ICMP6" "TCP" "UDP"; do
836
837				case ${i} in
838				${_fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
839					#print_debug \
840					#   "rc_${_n}_${_edge}_${_type}_${i}=1"
841					;;
842				*)	eval rc_${_n}_${_edge}_${_type}_${i}=0
843					#print_debug \
844					#   "rc_${_n}_${_edge}_${_type}_${i}=0"
845					;;
846				esac
847
848			done
849		done
850		i=$((i + 1))
851	done
852}
853
854_fwd_fib_symmetric_left()
855{
856	local _n _maxfib i
857	_n="$1"
858	_maxfib=$2
859
860	# Setup expected return code
861	i=0
862	while test ${i} -lt ${_maxfib}; do
863		eval rc_${i}=0
864		i=$((i + 1))
865	done
866
867	# Initiate probes for ICMP6, TCP and UDP.
868	i=0
869	while test ${i} -lt ${_maxfib}; do
870
871		sleep 1
872
873		send_control_msgs "START_${_n}_${i}"
874
875		test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6"
876		test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i}
877
878		send_control_msgs "STOP_${_n}_${i}"
879		_fwd_fib_symmetric_results "${_n}_${i}" ${i}
880		fetch_ipfw_count "${_n}_${i}"
881		i=$((i + 1))
882	done
883}
884
885_fwd_fib_symmetric_right()
886{
887	local _n _maxfib i
888	_n="$1"
889	_maxfib=$2
890
891	i=0
892	while test ${i} -lt ${_maxfib}; do
893		wait_remote_ready "START_${_n}_${i}"
894
895		# No need to do anything for ICMPv6.
896		# Start reflect for TCP and UDP.
897		test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" ${i} ${CTRLPORT}
898		test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" ${i} ${CTRLPORT}
899
900		wait_remote_ready "STOP_${_n}_${i}"
901		i=$((i + 1))
902	done
903}
904
905_fwd_fib_symmetric_middle_ifconfig()
906{
907	local _n _maxfib i
908	_n="$1"
909	_maxfib=$2
910
911	i=0
912	while test ${i} -lt ${_maxfib}; do
913		ifconfig ${IFACE} fib ${i}
914		ifconfig ${IFACEFAR} fib ${i}
915		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
916		wait_remote_ready "START_${_n}_${i}"
917		ipfw -q zero > /dev/null
918		# Nothing to do for the middle node testing the default.
919		sleep 1
920		wait_remote_ready "STOP_${_n}_${i}"
921		report_ipfw_count
922		i=$((i + 1))
923	done
924}
925
926_fwd_fib_symmetric_middle_ipfw()
927{
928	local _n _maxfib i _port
929	_n="$1"
930	_maxfib=$2
931
932	i=0
933	while test ${i} -lt ${_maxfib}; do
934		_port=$((CTRLPORT + 1 + i))
935		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
936		    icmp6types 128 via ${IFACE} in > /dev/null
937		ipfw add 100 setfib ${i} tcp from any to any \
938		    dst-port ${_port} via ${IFACE} in > /dev/null
939		ipfw add 100 setfib ${i} udp from any to any \
940		    dst-port ${_port} via ${IFACE} in > /dev/null
941
942		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
943		    icmp6types 129 via ${IFACEFAR} in > /dev/null
944		ipfw add 100 setfib ${i} tcp from any to any \
945		    src-port ${_port} via ${IFACEFAR} in > /dev/null
946		ipfw add 100 setfib ${i} udp from any to any \
947		    src-port ${_port} via ${IFACEFAR} in > /dev/null
948
949		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
950		wait_remote_ready "START_${_n}_${i}"
951		ipfw -q zero > /dev/null
952		# Nothing to do for the middle node testing the default.
953		sleep 1
954		wait_remote_ready "STOP_${_n}_${i}"
955		report_ipfw_count
956
957		ipfw delete 100 > /dev/null
958		i=$((i + 1))
959	done
960}
961
962fwd_fib_symmetric_ifconfig()
963{
964	local _maxfib _n
965	_maxfib=$1
966
967	_n="fwd_fib_symmetric_ifconfig"
968
969	print_debug "${_n} ${_maxfib}"
970	case ${node} in
971	left)	_fwd_fib_symmetric_left ${_n} ${_maxfib} ;;
972	middle)	_fwd_fib_symmetric_middle_ifconfig ${_n} ${_maxfib} ;;
973	right)	_fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
974	esac
975}
976
977fwd_fib_symmetric_ipfw()
978{
979	local _maxfib _n
980	_maxfib=$1
981
982	_n="fwd_fib_symmetric_ipfw"
983
984	print_debug "${_n} ${_maxfib}"
985	case ${node} in
986	left)	_fwd_fib_symmetric_left ${_n} ${_maxfib} ;;
987	middle)	_fwd_fib_symmetric_middle_ipfw ${_n} ${_maxfib} ;;
988	right)	_fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
989	esac
990}
991
992################################################################################
993
994_fwd_fib_asymmetric_results()
995{
996	local _n fib maxfib i _edge _type _rc
997	_n="$1"
998	fib=$2
999	maxfib=$3
1000
1001	i=0
1002	while test ${i} -lt ${maxfib}; do
1003		_edge="RIGHT"
1004			for _type in "ICMP6" "TCP" "UDP"; do
1005
1006				case ${i} in
1007				${fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
1008					#print_debug \
1009					#   "rc_${_n}_${_edge}_${_type}_${i}=1"
1010					;;
1011				*)	eval rc_${_n}_${_edge}_${_type}_${i}=0
1012					#print_debug \
1013					#   "rc_${_n}_${_edge}_${_type}_${i}=0"
1014					;;
1015				esac
1016
1017			done
1018		i=$((i + 1))
1019	done
1020	fib=$((maxfib - 1 - fib))
1021	i=0
1022	while test ${i} -lt ${maxfib}; do
1023		_edge="LEFT"
1024			for _type in "ICMP6" "TCP" "UDP"; do
1025
1026				case ${i} in
1027				${fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1
1028					#print_debug \
1029					#   "rc_${_n}_${_edge}_${_type}_${i}=1"
1030					;;
1031				*)	eval rc_${_n}_${_edge}_${_type}_${i}=0
1032					#print_debug \
1033					#   "rc_${_n}_${_edge}_${_type}_${i}=0"
1034					;;
1035				esac
1036
1037			done
1038		i=$((i + 1))
1039	done
1040}
1041
1042_fwd_fib_asymmetric_left()
1043{
1044	local _n _maxfib i
1045	_n="$1"
1046	_maxfib=$2
1047
1048	# Setup expected return code
1049	i=0
1050	while test ${i} -lt ${_maxfib}; do
1051		eval rc_${i}=0
1052		i=$((i + 1))
1053	done
1054
1055	# Initiate probes for ICMP6, TCP and UDP.
1056	i=0
1057	while test ${i} -lt ${_maxfib}; do
1058
1059		sleep 1
1060
1061		send_control_msgs "START_${_n}_${i}"
1062
1063		test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6"
1064		test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i}
1065
1066		send_control_msgs "STOP_${_n}_${i}"
1067		_fwd_fib_asymmetric_results "${_n}_${i}" ${i} ${_maxfib}
1068		fetch_ipfw_count "${_n}_${i}"
1069		i=$((i + 1))
1070	done
1071}
1072
1073_fwd_fib_asymmetric_middle_ifconfig()
1074{
1075	local _n maxfib i
1076	_n="$1"
1077	maxfib=$2
1078
1079	i=0
1080	while test ${i} -lt ${maxfib}; do
1081		ifconfig ${IFACE} fib ${i}
1082		ifconfig ${IFACEFAR} fib $((${maxfib} - 1 - ${i}))
1083		setup_ipfw_count ${CTRLPORT} ${maxfib} ${i} \
1084		    $((${maxfib} - 1 - ${i}))
1085		wait_remote_ready "START_${_n}_${i}"
1086		ipfw -q zero > /dev/null
1087		# Nothing to do for the middle node testing the default.
1088		sleep 1
1089		wait_remote_ready "STOP_${_n}_${i}"
1090		report_ipfw_count
1091		i=$((i + 1))
1092	done
1093}
1094
1095_fwd_fib_asymmetric_middle_ipfw()
1096{
1097	local _n maxfib i j _port
1098	_n="$1"
1099	maxfib=$2
1100
1101	i=0
1102	while test ${i} -lt ${maxfib}; do
1103
1104		_port=$((CTRLPORT + 1 + i))
1105		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
1106		    icmp6types 128 via ${IFACE} in > /dev/null
1107		ipfw add 100 setfib ${i} tcp from any to any \
1108		    dst-port ${_port} via ${IFACE} in > /dev/null
1109		ipfw add 100 setfib ${i} udp from any to any \
1110		    dst-port ${_port} via ${IFACE} in > /dev/null
1111
1112		j=$((${maxfib} - 1 - ${i}))
1113		ipfw add 100 setfib ${j} ipv6-icmp from any to any \
1114		    icmp6types 129 via ${IFACEFAR} in > /dev/null
1115		ipfw add 100 setfib ${j} tcp from any to any \
1116		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1117		ipfw add 100 setfib ${j} udp from any to any \
1118		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1119
1120		setup_ipfw_count ${CTRLPORT} ${maxfib} ${i} ${j}
1121		wait_remote_ready "START_${_n}_${i}"
1122		ipfw -q zero > /dev/null
1123		# Nothing to do for the middle node testing the default.
1124		sleep 1
1125		wait_remote_ready "STOP_${_n}_${i}"
1126		report_ipfw_count
1127
1128		ipfw delete 100 > /dev/null
1129		i=$((i + 1))
1130	done
1131}
1132
1133fwd_fib_asymmetric_ifconfig()
1134{
1135	local _maxfib _n
1136	_maxfib=$1
1137
1138	_n="fwd_fib_asymmetric_ifconfig"
1139
1140	print_debug "${_n} ${_maxfib}"
1141	case ${node} in
1142	left)	_fwd_fib_asymmetric_left ${_n} ${_maxfib} ;;
1143	middle)	_fwd_fib_asymmetric_middle_ifconfig ${_n} ${_maxfib} ;;
1144	right)	_fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
1145	esac
1146}
1147
1148fwd_fib_asymmetric_ipfw()
1149{
1150	local _maxfib _n
1151	_maxfib=$1
1152
1153	_n="fwd_fib_asymmetric_ipfw"
1154
1155	print_debug "${_n} ${_maxfib}"
1156	case ${node} in
1157	left)	_fwd_fib_asymmetric_left ${_n} ${_maxfib} ;;
1158	middle)	_fwd_fib_asymmetric_middle_ipfw ${_n} ${_maxfib} ;;
1159	right)	_fwd_fib_symmetric_right ${_n} ${_maxfib} ;;
1160	esac
1161}
1162
1163################################################################################
1164
1165_fwd_fib_symmetric_destructive_left()
1166{
1167	local _n _maxfib i _addr
1168	_n="$1"
1169	_maxfib=$2
1170
1171	# Setup expected return code
1172	i=0
1173	while test ${i} -lt ${_maxfib}; do
1174		eval rc_${i}=0
1175		i=$((i + 1))
1176	done
1177
1178	# Add default route.
1179	route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null
1180
1181	# Initiate probes for ICMP6, TCP and UDP.
1182	i=0
1183	while test ${i} -lt ${_maxfib}; do
1184
1185		sleep 1
1186
1187		send_control_msgs "START_${_n}_${i}"
1188
1189		_addr="2001:2:${i}::2"
1190		test_icmp6 1 ${_addr} "${_n}_${i}_icmp6"
1191		test_ulp 1 "${_n}_${i}" ${_addr} ${CTRLPORT} ${i}
1192
1193		send_control_msgs "STOP_${_n}_${i}"
1194		_fwd_fib_symmetric_results "${_n}_${i}" ${i}
1195		fetch_ipfw_count "${_n}_${i}"
1196		i=$((i + 1))
1197	done
1198
1199	# Cleanup networking.
1200	route delete -net -inet6 default > /dev/null
1201}
1202
1203_fwd_fib_symmetric_destructive_right()
1204{
1205	local _n _maxfib i _addr
1206	_n="$1"
1207	_maxfib=$2
1208
1209	# Setup networking (ideally we'd use the link-local).
1210	route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1
1211	i=0
1212	while test ${i} -lt ${_maxfib}; do
1213		ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias
1214		i=$((i + 1))
1215	done
1216
1217	i=0
1218	while test ${i} -lt ${_maxfib}; do
1219		wait_remote_ready "START_${_n}_${i}"
1220
1221		# No need to do anything for ICMPv6.
1222		# Start reflect for TCP and UDP.
1223		_addr="2001:2:${i}::2"
1224		test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \
1225		    ${i} ${CTRLPORT}
1226		test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \
1227		    ${i} ${CTRLPORT}
1228
1229		wait_remote_ready "STOP_${_n}_${i}"
1230		i=$((i + 1))
1231	done
1232
1233	# Cleanup networking again.
1234	route delete -net -inet6 default > /dev/null 2>&1
1235	i=0
1236	while test ${i} -lt ${_maxfib}; do
1237		ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias
1238		i=$((i + 1))
1239	done
1240
1241}
1242
1243
1244_fwd_fib_symmetric_destructive_middle_setup_networking()
1245{
1246	local _maxfib i j
1247	_maxfib=$1
1248
1249	# Setup networking.
1250	i=0
1251	while test ${i} -lt ${_maxfib}; do
1252		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \
1253		    > /dev/null 2>&1 || true
1254		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias
1255		j=0
1256		while test ${j} -lt ${_maxfib}; do
1257			# Only work on all other FIBs.
1258			if test ${j} -ne ${i}; then
1259				setfib -F ${j} route delete -net -inet6 \
1260				     2001:2:${i}::/64 > /dev/null
1261			fi
1262			j=$((j + 1))
1263		done
1264		i=$((i + 1))
1265	done
1266}
1267
1268_fwd_fib_symmetric_destructive_middle_cleanup_networking()
1269{
1270	local _maxfib i
1271	_maxfib=$1
1272
1273	# Cleanup networking again.
1274	i=0
1275	while test ${i} -lt ${_maxfib}; do
1276		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias
1277		i=$((i + 1))
1278	done
1279}
1280
1281_fwd_fib_symmetric_destructive_middle_ifconfig()
1282{
1283	local _n _maxfib i
1284	_n="$1"
1285	_maxfib=$2
1286
1287	_fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib}
1288
1289	i=0
1290	while test ${i} -lt ${_maxfib}; do
1291		ifconfig ${IFACE} fib ${i}
1292		ifconfig ${IFACEFAR} fib ${i}
1293		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
1294		wait_remote_ready "START_${_n}_${i}"
1295		ipfw -q zero > /dev/null
1296		# Nothing to do for the middle node testing the default.
1297		sleep 1
1298		wait_remote_ready "STOP_${_n}_${i}"
1299		report_ipfw_count
1300		i=$((i + 1))
1301	done
1302
1303	_fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib}
1304}
1305
1306_fwd_fib_symmetric_destructive_middle_ipfw()
1307{
1308	local _n _maxfib i _port
1309	_n="$1"
1310	_maxfib=$2
1311
1312	_fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib}
1313
1314	i=0
1315	while test ${i} -lt ${_maxfib}; do
1316		_port=$((CTRLPORT + 1 + i))
1317		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
1318		    icmp6types 128 via ${IFACE} in > /dev/null
1319		ipfw add 100 setfib ${i} tcp from any to any \
1320		    dst-port ${_port} via ${IFACE} in > /dev/null
1321		ipfw add 100 setfib ${i} udp from any to any \
1322		    dst-port ${_port} via ${IFACE} in > /dev/null
1323
1324		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
1325		    icmp6types 129 via ${IFACEFAR} in > /dev/null
1326		ipfw add 100 setfib ${i} tcp from any to any \
1327		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1328		ipfw add 100 setfib ${i} udp from any to any \
1329		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1330
1331		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
1332		wait_remote_ready "START_${_n}_${i}"
1333		ipfw -q zero > /dev/null
1334		# Nothing to do for the middle node testing the default.
1335		sleep 1
1336		wait_remote_ready "STOP_${_n}_${i}"
1337		report_ipfw_count
1338
1339		ipfw delete 100 > /dev/null
1340		i=$((i + 1))
1341	done
1342
1343	_fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib}
1344}
1345
1346fwd_fib_symmetric_destructive_ifconfig()
1347{
1348	local _maxfib _n
1349	_maxfib=$1
1350
1351	_n="fwd_fib_symmetric_destructive_ifconfig"
1352
1353	print_debug "${_n} ${_maxfib}"
1354	case ${node} in
1355	left)	_fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;;
1356	middle)	_fwd_fib_symmetric_destructive_middle_ifconfig \
1357		    ${_n} ${_maxfib} ;;
1358	right)	_fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;;
1359	esac
1360}
1361
1362fwd_fib_symmetric_destructive_ipfw()
1363{
1364	local _maxfib _n
1365	_maxfib=$1
1366
1367	_n="fwd_fib_symmetric_destructive_ipfw"
1368
1369	print_debug "${_n} ${_maxfib}"
1370	case ${node} in
1371	left)	_fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;;
1372	middle)	_fwd_fib_symmetric_destructive_middle_ipfw \
1373		    ${_n} ${_maxfib} ;;
1374	right)	_fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;;
1375	esac
1376}
1377
1378################################################################################
1379
1380_fwd_fib_symmetric_destructive_defroute_left()
1381{
1382	local _n _maxfib i _addr
1383	_n="$1"
1384	_maxfib=$2
1385
1386	# Setup expected return code
1387	i=0
1388	while test ${i} -lt ${_maxfib}; do
1389		eval rc_${i}=0
1390		i=$((i + 1))
1391	done
1392
1393	# Add default route.
1394	route delete -net -inet6 default > /dev/null 2>&1 || true
1395	route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null
1396
1397	# Initiate probes for ICMP6, TCP and UDP.
1398	_addr="2001:2:1234::2"
1399	i=0
1400	while test ${i} -lt ${_maxfib}; do
1401
1402		sleep 1
1403
1404		send_control_msgs "START_${_n}_${i}"
1405
1406		test_icmp6 1 "${_addr}" "${_n}_${i}_icmp6"
1407		test_ulp 1 "${_n}_${i}" "${_addr}" ${CTRLPORT} ${i}
1408
1409		send_control_msgs "STOP_${_n}_${i}"
1410		_fwd_fib_symmetric_results "${_n}_${i}" ${i}
1411		fetch_ipfw_count "${_n}_${i}"
1412		i=$((i + 1))
1413	done
1414
1415	# Cleanup networking.
1416	route delete -net -inet6 default > /dev/null 2>&1
1417}
1418
1419_fwd_fib_symmetric_destructive_defroute_right()
1420{
1421	local _n _maxfib i _addr
1422	_n="$1"
1423	_maxfib=$2
1424
1425	# Setup networking (ideally we'd use the link-local).
1426	route delete -net -inet6 default > /dev/null 2>&1 ||  true
1427	route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1
1428	i=0
1429	while test ${i} -lt ${_maxfib}; do
1430		ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \
1431		    > /dev/null 2>&1 || true
1432		ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias
1433		i=$((i + 1))
1434	done
1435	_addr="2001:2:1234::2"
1436	ifconfig lo0 inet6 ${_addr}/128 alias
1437
1438	i=0
1439	while test ${i} -lt ${_maxfib}; do
1440		wait_remote_ready "START_${_n}_${i}"
1441
1442		# No need to do anything for ICMPv6.
1443		# Start reflect for TCP and UDP.
1444		test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \
1445		    ${i} ${CTRLPORT}
1446		test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \
1447		    ${i} ${CTRLPORT}
1448
1449		wait_remote_ready "STOP_${_n}_${i}"
1450		i=$((i + 1))
1451	done
1452
1453	# Cleanup networking again.
1454	route delete -net -inet6 default > /dev/null 2>&1
1455	i=0
1456	while test ${i} -lt ${_maxfib}; do
1457		ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias
1458		i=$((i + 1))
1459	done
1460	ifconfig lo0 inet6 ${_addr}/128 -alias
1461
1462}
1463
1464_fwd_fib_symmetric_destructive_defroute_middle_setup_networking()
1465{
1466	local _maxfib i j
1467	_maxfib=$1
1468
1469	# Setup networking.
1470	i=0
1471	while test ${i} -lt ${_maxfib}; do
1472		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \
1473		    > /dev/null 2>&1 || true
1474		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias
1475		j=0
1476		while test ${j} -lt ${_maxfib}; do
1477			# Only work on all other FIBs.
1478			if test ${j} -ne ${i}; then
1479				setfib -F ${j} route delete -net -inet6 \
1480				     2001:2:${i}::/64 > /dev/null
1481			fi
1482			j=$((j + 1))
1483		done
1484		setfib -F ${i} route delete -net -inet6 \
1485		     2001:2:1234::2 2001:2:${i}::2 > /dev/null 2>&1 || true
1486		setfib -F ${i} route add -net -inet6 \
1487		     2001:2:1234::2 2001:2:${i}::2 > /dev/null
1488		i=$((i + 1))
1489	done
1490}
1491
1492_fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking()
1493{
1494	local _maxfib i
1495	_maxfib=$1
1496
1497	# Cleanup networking again.
1498	i=0
1499	while test ${i} -lt ${_maxfib}; do
1500		ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias
1501		setfib -F ${i} route delete -net -inet6 \
1502		     2001:2:1234::2 2001:2:${i}::2 > /dev/null
1503		i=$((i + 1))
1504	done
1505}
1506
1507_fwd_fib_symmetric_destructive_defroute_middle_ifconfig()
1508{
1509	local _n _maxfib i
1510	_n="$1"
1511	_maxfib=$2
1512
1513	_fwd_fib_symmetric_destructive_defroute_middle_setup_networking \
1514	     ${_maxfib}
1515
1516	i=0
1517	while test ${i} -lt ${_maxfib}; do
1518		ifconfig ${IFACE} fib ${i}
1519		ifconfig ${IFACEFAR} fib ${i}
1520		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
1521		wait_remote_ready "START_${_n}_${i}"
1522		ipfw -q zero > /dev/null
1523		# Nothing to do for the middle node testing the default.
1524		sleep 1
1525		wait_remote_ready "STOP_${_n}_${i}"
1526		report_ipfw_count
1527		i=$((i + 1))
1528	done
1529
1530	_fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \
1531	    ${_maxfib}
1532}
1533
1534_fwd_fib_symmetric_destructive_defroute_middle_ipfw()
1535{
1536	local _n _maxfib i _port
1537	_n="$1"
1538	_maxfib=$2
1539
1540	_fwd_fib_symmetric_destructive_defroute_middle_setup_networking \
1541	    ${_maxfib}
1542
1543	i=0
1544	while test ${i} -lt ${_maxfib}; do
1545		_port=$((CTRLPORT + 1 + i))
1546		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
1547		    icmp6types 128 via ${IFACE} in > /dev/null
1548		ipfw add 100 setfib ${i} tcp from any to any \
1549		    dst-port ${_port} via ${IFACE} in > /dev/null
1550		ipfw add 100 setfib ${i} udp from any to any \
1551		    dst-port ${_port} via ${IFACE} in > /dev/null
1552
1553		ipfw add 100 setfib ${i} ipv6-icmp from any to any \
1554		    icmp6types 129 via ${IFACEFAR} in > /dev/null
1555		ipfw add 100 setfib ${i} tcp from any to any \
1556		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1557		ipfw add 100 setfib ${i} udp from any to any \
1558		    src-port ${_port} via ${IFACEFAR} in > /dev/null
1559
1560		setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1
1561		wait_remote_ready "START_${_n}_${i}"
1562		ipfw -q zero > /dev/null
1563		# Nothing to do for the middle node testing the default.
1564		sleep 1
1565		wait_remote_ready "STOP_${_n}_${i}"
1566		report_ipfw_count
1567
1568		ipfw delete 100 > /dev/null
1569		i=$((i + 1))
1570	done
1571
1572	_fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \
1573	    ${_maxfib}
1574}
1575
1576fwd_fib_symmetric_destructive_defroute_ifconfig()
1577{
1578	local _maxfib _n
1579	_maxfib=$1
1580
1581	_n="fwd_fib_symmetric_destructive_defroute_ifconfig"
1582
1583	print_debug "${_n} ${_maxfib}"
1584	case ${node} in
1585	left)	_fwd_fib_symmetric_destructive_defroute_left \
1586		    ${_n} ${_maxfib} ;;
1587	middle)	_fwd_fib_symmetric_destructive_defroute_middle_ifconfig \
1588		    ${_n} ${_maxfib} ;;
1589	right)	_fwd_fib_symmetric_destructive_defroute_right \
1590		    ${_n} ${_maxfib} ;;
1591	esac
1592}
1593
1594fwd_fib_symmetric_destructive_defroute_ipfw()
1595{
1596	local _maxfib _n
1597	_maxfib=$1
1598
1599	_n="fwd_fib_symmetric_destructive_defroute_ipfw"
1600
1601	print_debug "${_n} ${_maxfib}"
1602	case ${node} in
1603	left)	_fwd_fib_symmetric_destructive_defroute_left \
1604		    ${_n} ${_maxfib} ;;
1605	middle)	_fwd_fib_symmetric_destructive_defroute_middle_ipfw \
1606		    ${_n} ${_maxfib} ;;
1607	right)	_fwd_fib_symmetric_destructive_defroute_right \
1608		    ${_n} ${_maxfib} ;;
1609	esac
1610}
1611
1612################################################################################
1613#
1614# MAIN
1615#
1616
1617# Same for all hosts.
1618if test `sysctl -n security.jail.jailed` -eq 0; then
1619	kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw
1620fi
1621ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system"
1622ipfw add 65000 permit ip from any to any > /dev/null 2>&1
1623
1624# Per host setup.
1625setup_networking
1626reachability_check
1627
1628#
1629# Tests
1630#
1631
1632fwd_default_fib_symmetric
1633fwd_default_fib_symmetric_ifconfig
1634fwd_default_fib_symmetric_ipfw
1635
1636fwd_fib_symmetric_ifconfig ${RT_NUMFIBS}
1637fwd_fib_symmetric_ipfw ${RT_NUMFIBS}
1638
1639fwd_fib_asymmetric_ifconfig ${RT_NUMFIBS}
1640fwd_fib_asymmetric_ipfw ${RT_NUMFIBS}
1641
1642fwd_fib_symmetric_destructive_ifconfig ${RT_NUMFIBS}
1643fwd_fib_symmetric_destructive_ipfw ${RT_NUMFIBS}
1644
1645fwd_fib_symmetric_destructive_defroute_ifconfig ${RT_NUMFIBS}
1646fwd_fib_symmetric_destructive_defroute_ipfw ${RT_NUMFIBS}
1647
1648# Per host cleanup.
1649cleanup_networking
1650
1651# end
1652