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