]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/test/netfibs/forwarding.sh
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / test / netfibs / forwarding.sh
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.
43 PREFIX="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.
58 RT_NUMFIBS=`sysctl -n net.fibs`
59
60 # This is the initiator and connected middle node.
61 LEFTADDR="2001:2:fe00::1"
62 MIDDLELEFTADDR="2001:2:fe00::2"
63 # This is the far end middle node and receiver side.
64 MIDDLERIGHTADDR="2001:2:ff00::1"
65 RIGHTADDR="2001:2:ff00::2"
66
67 # By default all commands must succeed.  Individual tests may disable this
68 # temporary.
69 set -e
70
71 # Debug magic.
72 case "${DEBUG}" in
73 42)     set -x ;;
74 esac
75
76
77 ################################################################################
78 #
79 # Input validation.
80 #
81
82 node=$1
83 case ${node} in
84 left)   ;;
85 middle) ;;
86 right)  ;;
87 *)      echo "ERROR: invalid node name '${node}'. Must be left, middle or" \
88             " right" >&1
89         exit 1
90         ;;
91 esac
92
93 ################################################################################
94 #
95 # Helper functions.
96 #
97 check_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
113 print_debug()
114 {
115         local _msg
116         _msg="$*"
117
118         case ${DEBUG} in
119         ''|0)   ;;
120         *)      echo "DEBUG: ${_msg}" >&2 ;;
121         esac
122 }
123
124 die()
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
139 setup_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
191 cleanup_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
223 reachability_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 #
267 send_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}
290 EOI
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
307 send_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.
323 wait_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}
334 EOI
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 #
358 test_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
391 test_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
404 test_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
433 nc_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
464 test_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
507 setup_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
545 report_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
595 fetch_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'`
646 EOi
647                 
648         done <<EOo
649 `printf "${_reply}" | grep -v "^$"`
650 EOo
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
737 fwd_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
767 fwd_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
811 fwd_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
963 fwd_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
978 fwd_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
1134 fwd_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
1149 fwd_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
1347 fwd_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
1363 fwd_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
1577 fwd_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
1595 fwd_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.
1619 if test `sysctl -n security.jail.jailed` -eq 0; then
1620         kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw 
1621 fi
1622 ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system"
1623 ipfw add 65000 permit ip from any to any > /dev/null 2>&1
1624
1625 # Per host setup.
1626 setup_networking
1627 reachability_check
1628
1629 #
1630 # Tests
1631 #
1632
1633 fwd_default_fib_symmetric
1634 fwd_default_fib_symmetric_ifconfig
1635 fwd_default_fib_symmetric_ipfw
1636
1637 fwd_fib_symmetric_ifconfig ${RT_NUMFIBS}
1638 fwd_fib_symmetric_ipfw ${RT_NUMFIBS}
1639
1640 fwd_fib_asymmetric_ifconfig ${RT_NUMFIBS}
1641 fwd_fib_asymmetric_ipfw ${RT_NUMFIBS}
1642
1643 fwd_fib_symmetric_destructive_ifconfig ${RT_NUMFIBS}
1644 fwd_fib_symmetric_destructive_ipfw ${RT_NUMFIBS}
1645
1646 fwd_fib_symmetric_destructive_defroute_ifconfig ${RT_NUMFIBS}
1647 fwd_fib_symmetric_destructive_defroute_ipfw ${RT_NUMFIBS}
1648
1649 # Per host cleanup.
1650 cleanup_networking
1651
1652 # end