#!/bin/sh #- # Copyright (c) 2012 Cisco Systems, Inc. # All rights reserved. # # This software was developed by Bjoern Zeeb under contract to # Cisco Systems, Inc.. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # # Test setup: # # left ------------------------- middle ------------------------- right # IFACE IFACE IFACEFAR IFACE # LEFTADDR MIDDLELEFTADDR MIDDLERIGHTADDR RIGHTADDR # forwarding=1 # initiator FIB tests reflector # We will use the RFC5180 (and Errata) benchmarking working group prefix # 2001:0002::/48 for testing. PREFIX="2001:2:" # Set IFACE to the real interface you want to run the test on. # IFACEFAR is only relevant on the middle (forwarding) node and will be the # 'right' side (far end) one. : ${IFACE:=lo0} : ${IFACEFAR:=lo0} # Number of seconds to wait for peer node to synchronize for test. : ${WAITS:=120} # Control port we use to exchange messages between nodes to sync. tests, etc. : ${CTRLPORT:=6666} # Get the number of FIBs from the kernel. RT_NUMFIBS=`sysctl -n net.fibs` # This is the initiator and connected middle node. LEFTADDR="2001:2:fe00::1" MIDDLELEFTADDR="2001:2:fe00::2" # This is the far end middle node and receiver side. MIDDLERIGHTADDR="2001:2:ff00::1" RIGHTADDR="2001:2:ff00::2" # By default all commands must succeed. Individual tests may disable this # temporary. set -e # Debug magic. case "${DEBUG}" in 42) set -x ;; esac ################################################################################ # # Input validation. # node=$1 case ${node} in left) ;; middle) ;; right) ;; *) echo "ERROR: invalid node name '${node}'. Must be left, middle or" \ " right" >&1 exit 1 ;; esac ################################################################################ # # Helper functions. # check_rc() { local _rc _exp _testno _testname _msg _r _rc=$1 _exp=$2 _testno=$3 _testname="$4" _msg="$5" _r="not ok" if test ${_rc} -eq ${_exp}; then _r="ok" fi echo "${_r} ${_testno} ${_testname} # ${_msg} ${_rc} ${_exp}" } print_debug() { local _msg _msg="$*" case ${DEBUG} in ''|0) ;; *) echo "DEBUG: ${_msg}" >&2 ;; esac } die() { local _msg _msg="$*" echo "ERROR: ${_msg}" >&2 exit 1 } ################################################################################ # # Functions to configure networking and do a basic reachability check. # setup_networking() { print_debug "Setting up networking" case ${node} in left) ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACE} inet6 ${LEFTADDR}/64 alias up ifconfig ${IFACE} fib 0 sysctl net.inet6.ip6.forwarding=0 > /dev/null route delete -net -inet6 default > /dev/null 2>&1 || true route delete -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \ > /dev/null 2>&1 || true route add -host -inet6 ${RIGHTADDR} ${MIDDLELEFTADDR} \ > /dev/null route delete -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \ > /dev/null 2>&1 || true route add -host -inet6 ${MIDDLERIGHTADDR} ${MIDDLELEFTADDR} \ > /dev/null 2>&1 || true ;; middle) ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 alias up ifconfig ${IFACE} fib 0 ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 alias up ifconfig ${IFACEFAR} fib 0 sysctl net.inet6.ip6.forwarding=1 > /dev/null ;; right) ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 alias up ifconfig ${IFACE} fib 0 sysctl net.inet6.ip6.forwarding=0 > /dev/null route delete -net -inet6 default > /dev/null 2>&1 || true route delete -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \ > /dev/null 2>&1 || true route add -host -inet6 ${LEFTADDR} ${MIDDLERIGHTADDR} \ > /dev/null route delete -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \ > /dev/null 2>&1 || true route add -host -inet6 ${MIDDLELEFTADDR} ${MIDDLERIGHTADDR} \ > /dev/null ;; esac # Let things settle. print_debug "Waiting 4 seconds for things to settle" sleep 4 } cleanup_networking() { case ${node} in left) ifconfig ${IFACE} inet6 ${LEFTADDR}/64 -alias ;; middle) ifconfig ${IFACE} inet6 ${MIDDLELEFTADDR}/64 -alias ifconfig ${IFACEFAR} inet6 ${MIDDLERIGHTADDR}/64 -alias sysctl net.inet6.ip6.forwarding=0 > /dev/null ;; right) ifconfig ${IFACE} inet6 ${RIGHTADDR}/64 -alias ;; esac print_debug "Cleaned up networking" } _reachability_check() { local _addr _rc _addr="$1" ping6 -n -c1 ${_addr} > /dev/null 2>&1 _rc=$? case ${_rc} in 0) ;; *) print_debug "cannot ping6 ${_addr}, rc=${_rc}" return 1 ;; esac return 0 } reachability_check() { local _i _rc # Try to reach all control addresses on other nodes. # We need to loop for a while as we cannot expect all to be up # the very same moment. i=1 _rc=42 while test ${_rc} -ne 0 -a ${i} -le ${WAITS}; do print_debug "${i}/${WAITS} trying to ping6 control addresses." _rc=0 set +e case ${node} in left) _reachability_check ${MIDDLELEFTADDR} _rc=$((_rc + $?)) _reachability_check ${MIDDLERIGHTADDR} _rc=$((_rc + $?)) _reachability_check ${RIGHTADDR} _rc=$((_rc + $?)) ;; middle) _reachability_check ${LEFTADDR} _rc=$((_rc + $?)) _reachability_check ${RIGHTADDR} _rc=$((_rc + $?)) ;; right) _reachability_check ${MIDDLERIGHTADDR} _rc=$((_rc + $?)) _reachability_check ${MIDDLELEFTADDR} _rc=$((_rc + $?)) _reachability_check ${LEFTADDR} _rc=$((_rc + $?)) ;; esac set -e sleep 1 i=$((i + 1)) done } ################################################################################ # # "Greeting" handling to sync notes to the agreed upon next test case. # send_control_msg() { local _case _addr i rc _msg _keyword _fibs _case="$1" _addr="$2" set +e i=0 rc=-1 while test ${i} -lt ${WAITS} -a ${rc} -ne 0; do print_debug "Sending control msg #${i} to peer ${_addr}" _msg=`echo "${_case} ${RT_NUMFIBS}" | \ nc -6 -w 1 ${_addr} ${CTRLPORT}` rc=$? i=$((i + 1)) # Might sleep longer in total but better than to DoS # and not get anywhere. sleep 1 done set -e read _keyword _fibs < /dev/null 2>&1 _ec=$? # We need to normalize the exit code of ping6. case ${_ec} in 0) ;; *) _ec=1 ;; esac check_rc ${_ec} ${_rc} ${_testno} "${_txt}" "FIB ${i} ${_addr}" testno=$((testno + 1)) i=$((i + 1)) done set -e } test_ulp_reflect_one() { local _txt _opts _port _fib _txt="$1" _opts="$2" _port=$3 _fib=$4 print_debug "./reflect -p $((_port + 1 + _fib)) -t ${_txt}" "${_opts}" ./reflect -p $((_port + 1 + _fib)) -t ${_txt} ${_opts} print_debug "reflect '${_txt}' terminated without error." } test_ulp_reflect_multiple() { local _maxfibs _txt _opts i _jobs _p _maxfibs=$1 _txt="$2" _opts="$3" i=0 _jobs="" while test ${i} -lt ${_maxfibs}; do print_debug "./reflect -p $((CTRLPORT + 1000 + i))" \ "-t ${_txt} ${_opts} -N -f ${i} &" ./reflect -p $((CTRLPORT + 1000 + i)) \ -t ${_txt} ${_opts} -N -f ${i} & _p=$! _jobs="${_jobs}${_p} " i=$((i + 1)) done # Start OOB control connection for START/DONE. testrx_run_one "${_txt}" "${_opts}" print_debug "KILL ${_jobs}" for i in ${_jobs}; do kill ${i} || true done #killall reflect || true print_debug "reflects for '${_txt}' terminated without error." } nc_send_recv() { local _loops _msg _expreply _addr _port _opts i _loops=$1 _msg="$2" _expreply="$3" _addr=$4 _port=$5 _opts="$6" i=0 while test ${i} -lt ${_loops}; do i=$((i + 1)) print_debug "e ${_msg} | nc -6 -w1 ${_opts} ${_addr} ${_port}" _reply=`echo "${_msg}" | nc -6 -w1 ${_opts} ${_addr} ${_port}` if test "${_reply}" != "${_expreply}"; then if test ${i} -lt ${_loops}; then sleep 1 else # Must let caller decide how to handle the error. # die "Got invalid reply from peer." \ # "Expected '${_expreply}', got '${_reply}'" return 1 fi else break fi done return 0 } test_ulp() { local _maxfibs _msg _addr _port _fib i _txt testno _rc _reply _maxfibs=$1 _msg="$2" _addr=$3 _port=$4 _fib=$5 printf "1..%d\n" $((${_maxfibs} * 2)) testno=1 i=0 while test ${i} -lt ${_maxfibs}; do if test ${i} -eq $((${_maxfibs} - 1)); then # Last one; signal DONE. _txt="DONE ${_msg}_${i}" else _txt="DONE ${_msg}_${i}" fi eval _rc="\${rc_${i}}" # Test TCP. nc_send_recv ${_maxfibs} "${_txt}" "${_txt}" ${_addr} \ $((${_port} + 1 + _fib)) "" check_rc $? ${_rc} ${testno} "${_msg}_${i}_tcp" \ "[${_addr}]:$((${_port} + 1 + _fib)) ${_reply}" testno=$((testno + 1)) sleep 1 # Test UDP. nc_send_recv ${_maxfibs} "${_txt}" "${_txt}" ${_addr} \ $((${_port} + 1 + _fib)) "-u" check_rc $? ${_rc} ${testno} "${_msg}_${i}_udp" \ "[${_addr}]:$((${_port} + 1 + _fib)) ${_reply}" sleep 1 i=$((i + 1)) testno=$((testno + 1)) done } setup_ipfw_count() { local i _port _maxfib _p _fib _ofib _port=$1 _maxfib=$2 _fib=$3 _ofib=$4 i=0 while test ${i} -lt ${_maxfib}; do case ${_ofib} in -1) _p=$((_port + 1 + i)) ;; *) _p=$((_port + 1 + _maxfib - 1 - i)) ;; esac # Only count ICMP6 echo replies. ipfw add $((10000 + i)) count ipv6-icmp from any to any \ icmp6types 129 fib ${i} via ${IFACE} out > /dev/null ipfw add $((10000 + i)) count tcp from any to any \ src-port ${_p} fib ${i} via ${IFACE} out > /dev/null ipfw add $((10000 + i)) count udp from any to any \ src-port ${_p} fib ${i} via ${IFACE} out > /dev/null # Only count ICMP6 echo requests. ipfw add $((20000 + i)) count ipv6-icmp from any to any \ icmp6types 128 fib ${i} via ${IFACEFAR} out > /dev/null ipfw add $((20000 + i)) count tcp from any to any \ dst-port $((${_port} + 1 + i)) fib ${i} \ via ${IFACEFAR} out > /dev/null ipfw add $((20000 + i)) count udp from any to any \ dst-port $((${_port} + 1 + i)) fib ${i} \ via ${IFACEFAR} out > /dev/null i=$((i + 1)) done } report_ipfw_count() { local _fib _o i _rstr _c _req _p _opts _o="$2" case ${DEBUG} in ''|0) ;; *) ipfw show ;; esac _rstr="RESULTS " for _base in 10000 20000; do for _o in i t u; do case ${_base} in 10000) _rstr="${_rstr}\nLEFT " ;; 20000) _rstr="${_rstr}\nRIGHT " ;; esac case ${_o} in i) _rstr="${_rstr}ICMP6 " ;; t) _rstr="${_rstr}TCP " ;; u) _rstr="${_rstr}UDP " ;; esac i=0 while test ${i} -lt ${RT_NUMFIBS}; do case "${_o}" in i) _c=`ipfw show $((${_base} + i)) | \ awk '/ ipv6-icmp / { print $2 }'` ;; t) _c=`ipfw show $((${_base} + i)) | \ awk '/ tcp / { print $2 }'` ;; u) _c=`ipfw show $((${_base} + i)) | \ awk '/ udp / { print $2 }'` ;; esac _rstr="${_rstr}${i} ${_c}," i=$((i + 1)) done done i=0 while test ${i} -lt ${RT_NUMFIBS}; do ipfw delete $((${_base} + i)) > /dev/null 2>&1 || true i=$((i + 1)) done done # We do not care about the request. _req=`printf "${_rstr}" | nc -6 -l $((${CTRLPORT} - 1))` print_debug "$? -- ${_req} -- ${_rstr}" } fetch_ipfw_count() { local _n _reply _line _edge _type _fib _count _rc _ec _status _n="$1" # Leave node some time to build result set. sleep 3 print_debug "Asking for ipfw count results..." set +e nc_send_recv 1 "RESULT REQUEST" "" ${MIDDLELEFTADDR} \ $((${CTRLPORT} - 1)) "" set -e case "${_reply}" in RESULTS\ *) ;; *) die "Got invalid reply from peer." \ "Expected 'RESULTS ...', got '${_reply}'" ;; esac # Trim "RESULTS " _reply=${_reply#* } # FIBs * {left, right} * {icmp6, tcp, udp} printf "1..%d\n" $((RT_NUMFIBS * 2 * 3)) testno=1 while read _line; do print_debug "_line == ${_line}" _edge=${_line%% *} _line=${_line#* } _type=${_line%% *} _line=${_line#* } while read _fib _count; do eval _em="\${rc_${_n}_${_edge}_${_type}_${_fib}}" : ${_em:=-42} if test ${_count} -gt 0; then _rc=1 else _rc=0 fi if test ${_rc} -eq ${_em}; then _status="ok" else _status="not ok" fi printf "%s %d %s # count=%s _rc=%d _em=%d\n" \ "${_status}" ${testno} "${_n}_${_edge}_${_type}_${_fib}" \ ${_count} ${_rc} ${_em} testno=$((testno + 1)) done < /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}" report_ipfw_count } _fwd_default_fib_symmetric_right() { local _n _n="$1" wait_remote_ready "START_${_n}" # No need to do anything for ICMPv6. # Start reflect for TCP and UDP. test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" 0 ${CTRLPORT} test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" 0 ${CTRLPORT} wait_remote_ready "STOP_${_n}" } fwd_default_fib_symmetric() { local _n _n="fwd_default_fib_symmetric" print_debug "${_n}" case ${node} in left) _fwd_default_fib_symmetric_left ${_n} ;; middle) _fwd_default_fib_symmetric_middle ${_n} ;; right) _fwd_default_fib_symmetric_right ${_n} ;; esac } _fwd_default_fib_symmetric_middle_ifconfig() { local _n _n="$1" ifconfig ${IFACE} fib 0 ifconfig ${IFACEFAR} fib 0 setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1 wait_remote_ready "START_${_n}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}" report_ipfw_count } fwd_default_fib_symmetric_ifconfig() { local _n _n="fwd_default_fib_symmetric_ifconfig" print_debug "${_n}" case ${node} in left) _fwd_default_fib_symmetric_left ${_n} ;; middle) _fwd_default_fib_symmetric_middle_ifconfig ${_n} ;; right) _fwd_default_fib_symmetric_right ${_n} ;; esac } _fwd_default_fib_symmetric_middle_ipfw() { local _n _n="$1" ipfw add 100 setfib 0 ipv6-icmp from any to any \ icmp6types 128 via ${IFACE} in > /dev/null ipfw add 100 setfib 0 ip6 from any to any \ proto tcp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null ipfw add 100 setfib 0 ip6 from any to any \ proto udp dst-port ${CTRLPORT} via ${IFACE} in > /dev/null ipfw add 100 setfib 0 ipv6-icmp from any to any \ icmp6types 128 via ${IFACEFAR} in > /dev/null ipfw add 100 setfib 0 tcp from any to any \ dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null ipfw add 100 setfib 0 udp from any to any \ dst-port ${CTRLPORT} via ${IFACEFAR} in > /dev/null setup_ipfw_count ${CTRLPORT} ${RT_NUMFIBS} 0 -1 wait_remote_ready "START_${_n}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}" report_ipfw_count ipfw delete 100 > /dev/null } fwd_default_fib_symmetric_ipfw() { local _n _n="fwd_default_fib_symmetric_ipfw" print_debug "${_n}" case ${node} in left) _fwd_default_fib_symmetric_left ${_n} ;; middle) _fwd_default_fib_symmetric_middle_ipfw ${_n} ;; right) _fwd_default_fib_symmetric_right ${_n} ;; esac } ################################################################################ _fwd_fib_symmetric_results() { local _n _fib i _edge _type _rc _n="$1" _fib=$2 i=0 while test ${i} -lt ${RT_NUMFIBS}; do for _edge in "LEFT" "RIGHT"; do for _type in "ICMP6" "TCP" "UDP"; do case ${i} in ${_fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=1" ;; *) eval rc_${_n}_${_edge}_${_type}_${i}=0 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=0" ;; esac done done i=$((i + 1)) done } _fwd_fib_symmetric_left() { local _n _maxfib i _n="$1" _maxfib=$2 # Setup expected return code i=0 while test ${i} -lt ${_maxfib}; do eval rc_${i}=0 i=$((i + 1)) done # Initiate probes for ICMP6, TCP and UDP. i=0 while test ${i} -lt ${_maxfib}; do sleep 1 send_control_msgs "START_${_n}_${i}" test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6" test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i} send_control_msgs "STOP_${_n}_${i}" _fwd_fib_symmetric_results "${_n}_${i}" ${i} fetch_ipfw_count "${_n}_${i}" i=$((i + 1)) done } _fwd_fib_symmetric_right() { local _n _maxfib i _n="$1" _maxfib=$2 i=0 while test ${i} -lt ${_maxfib}; do wait_remote_ready "START_${_n}_${i}" # No need to do anything for ICMPv6. # Start reflect for TCP and UDP. test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6" ${i} ${CTRLPORT} test_ulp_reflect_one "${_n}_udp" "-N -T UDP6" ${i} ${CTRLPORT} wait_remote_ready "STOP_${_n}_${i}" i=$((i + 1)) done } _fwd_fib_symmetric_middle_ifconfig() { local _n _maxfib i _n="$1" _maxfib=$2 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} fib ${i} ifconfig ${IFACEFAR} fib ${i} setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count i=$((i + 1)) done } _fwd_fib_symmetric_middle_ipfw() { local _n _maxfib i _port _n="$1" _maxfib=$2 i=0 while test ${i} -lt ${_maxfib}; do _port=$((CTRLPORT + 1 + i)) ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 128 via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 129 via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count ipfw delete 100 > /dev/null i=$((i + 1)) done } fwd_fib_symmetric_ifconfig() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_ifconfig" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_left ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_middle_ifconfig ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;; esac } fwd_fib_symmetric_ipfw() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_ipfw" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_left ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_middle_ipfw ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;; esac } ################################################################################ _fwd_fib_asymmetric_results() { local _n _fib _maxfib i _edge _type _rc _n="$1" _fib=$2 _maxfib=$3 i=0 while test ${i} -lt ${_maxfib}; do _edge="RIGHT" for _type in "ICMP6" "TCP" "UDP"; do case ${i} in ${_fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=1" ;; *) eval rc_${_n}_${_edge}_${_type}_${i}=0 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=0" ;; esac done i=$((i + 1)) done _fib=$((_maxfib - 1 - _fib)) i=0 while test ${i} -lt ${_maxfib}; do _edge="LEFT" for _type in "ICMP6" "TCP" "UDP"; do case ${i} in ${_fib}) eval rc_${_n}_${_edge}_${_type}_${i}=1 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=1" ;; *) eval rc_${_n}_${_edge}_${_type}_${i}=0 #print_debug \ # "rc_${_n}_${_edge}_${_type}_${i}=0" ;; esac done i=$((i + 1)) done } _fwd_fib_asymmetric_left() { local _n _maxfib i _n="$1" _maxfib=$2 # Setup expected return code i=0 while test ${i} -lt ${_maxfib}; do eval rc_${i}=0 i=$((i + 1)) done # Initiate probes for ICMP6, TCP and UDP. i=0 while test ${i} -lt ${_maxfib}; do sleep 1 send_control_msgs "START_${_n}_${i}" test_icmp6 1 ${RIGHTADDR} "${_n}_${i}_icmp6" test_ulp 1 "${_n}_${i}" ${RIGHTADDR} ${CTRLPORT} ${i} send_control_msgs "STOP_${_n}_${i}" _fwd_fib_asymmetric_results "${_n}_${i}" ${i} ${_maxfib} fetch_ipfw_count "${_n}_${i}" i=$((i + 1)) done } _fwd_fib_asymmetric_middle_ifconfig() { local _n _maxfib i _n="$1" _maxfib=$2 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} fib ${i} ifconfig ${IFACEFAR} fib $((${_maxfib} - 1 - ${i})) setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} \ $((${_maxfib} - 1 - ${i})) wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count i=$((i + 1)) done } _fwd_fib_asymmetric_middle_ipfw() { local _n _maxfib i j _port _n="$1" _maxfib=$2 i=0 while test ${i} -lt ${_maxfib}; do _port=$((CTRLPORT + 1 + i)) ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 128 via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null j=$((${_maxfib} - 1 - ${i})) ipfw add 100 setfib ${j} ipv6-icmp from any to any \ icmp6types 129 via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${j} tcp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${j} udp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} ${j} wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count ipfw delete 100 > /dev/null i=$((i + 1)) done } fwd_fib_asymmetric_ifconfig() { local _maxfib _n _maxfib=$1 _n="fwd_fib_asymmetric_ifconfig" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_asymmetric_left ${_n} ${_maxfib} ;; middle) _fwd_fib_asymmetric_middle_ifconfig ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;; esac } fwd_fib_asymmetric_ipfw() { local _maxfib _n _maxfib=$1 _n="fwd_fib_asymmetric_ipfw" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_asymmetric_left ${_n} ${_maxfib} ;; middle) _fwd_fib_asymmetric_middle_ipfw ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_right ${_n} ${_maxfib} ;; esac } ################################################################################ _fwd_fib_symmetric_destructive_left() { local _n _maxfib i _addr _n="$1" _maxfib=$2 # Setup expected return code i=0 while test ${i} -lt ${_maxfib}; do eval rc_${i}=0 i=$((i + 1)) done # Add default route. route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null # Initiate probes for ICMP6, TCP and UDP. i=0 while test ${i} -lt ${_maxfib}; do sleep 1 send_control_msgs "START_${_n}_${i}" _addr="2001:2:${i}::2" test_icmp6 1 ${_addr} "${_n}_${i}_icmp6" test_ulp 1 "${_n}_${i}" ${_addr} ${CTRLPORT} ${i} send_control_msgs "STOP_${_n}_${i}" _fwd_fib_symmetric_results "${_n}_${i}" ${i} fetch_ipfw_count "${_n}_${i}" i=$((i + 1)) done # Cleanup networking. route delete -net -inet6 default > /dev/null } _fwd_fib_symmetric_destructive_right() { local _n _maxfib i _addr _n="$1" _maxfib=$2 # Setup networking (ideally we'd use the link-local). route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias i=$((i + 1)) done i=0 while test ${i} -lt ${_maxfib}; do wait_remote_ready "START_${_n}_${i}" # No need to do anything for ICMPv6. # Start reflect for TCP and UDP. _addr="2001:2:${i}::2" test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \ ${i} ${CTRLPORT} test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \ ${i} ${CTRLPORT} wait_remote_ready "STOP_${_n}_${i}" i=$((i + 1)) done # Cleanup networking again. route delete -net -inet6 default > /dev/null 2>&1 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias i=$((i + 1)) done } _fwd_fib_symmetric_destructive_middle_setup_networking() { local _maxfib i j _maxfib=$1 # Setup networking. i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias j=0 while test ${j} -lt ${_maxfib}; do # Only work on all other FIBs. if test ${j} -ne ${i}; then setfib -F ${j} route delete -net -inet6 \ 2001:2:${i}::/64 > /dev/null fi j=$((j + 1)) done i=$((i + 1)) done } _fwd_fib_symmetric_destructive_middle_cleanup_networking() { local _maxfib i _maxfib=$1 # Cleanup networking again. i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias i=$((i + 1)) done } _fwd_fib_symmetric_destructive_middle_ifconfig() { local _n _maxfib i _n="$1" _maxfib=$2 _fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib} i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} fib ${i} ifconfig ${IFACEFAR} fib ${i} setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count i=$((i + 1)) done _fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib} } _fwd_fib_symmetric_destructive_middle_ipfw() { local _n _maxfib i _port _n="$1" _maxfib=$2 _fwd_fib_symmetric_destructive_middle_setup_networking ${_maxfib} i=0 while test ${i} -lt ${_maxfib}; do _port=$((CTRLPORT + 1 + i)) ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 128 via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 129 via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count ipfw delete 100 > /dev/null i=$((i + 1)) done _fwd_fib_symmetric_destructive_middle_cleanup_networking ${_maxfib} } fwd_fib_symmetric_destructive_ifconfig() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_destructive_ifconfig" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_destructive_middle_ifconfig \ ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;; esac } fwd_fib_symmetric_destructive_ipfw() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_destructive_ipfw" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_destructive_left ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_destructive_middle_ipfw \ ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_destructive_right ${_n} ${_maxfib} ;; esac } ################################################################################ _fwd_fib_symmetric_destructive_defroute_left() { local _n _maxfib i _addr _n="$1" _maxfib=$2 # Setup expected return code i=0 while test ${i} -lt ${_maxfib}; do eval rc_${i}=0 i=$((i + 1)) done # Add default route. route delete -net -inet6 default > /dev/null 2>&1 || true route add -net -inet6 default ${MIDDLELEFTADDR} > /dev/null # Initiate probes for ICMP6, TCP and UDP. _addr="2001:2:1234::2" i=0 while test ${i} -lt ${_maxfib}; do sleep 1 send_control_msgs "START_${_n}_${i}" test_icmp6 1 "${_addr}" "${_n}_${i}_icmp6" test_ulp 1 "${_n}_${i}" "${_addr}" ${CTRLPORT} ${i} send_control_msgs "STOP_${_n}_${i}" _fwd_fib_symmetric_results "${_n}_${i}" ${i} fetch_ipfw_count "${_n}_${i}" i=$((i + 1)) done # Cleanup networking. route delete -net -inet6 default > /dev/null 2>&1 } _fwd_fib_symmetric_destructive_defroute_right() { local _n _maxfib i _addr _n="$1" _maxfib=$2 # Setup networking (ideally we'd use the link-local). route delete -net -inet6 default > /dev/null 2>&1 || true route add -net -inet6 default ${MIDDLERIGHTADDR} > /dev/null 2>&1 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACE} inet6 2001:2:${i}::2/64 alias i=$((i + 1)) done _addr="2001:2:1234::2" ifconfig lo0 inet6 ${_addr}/128 alias i=0 while test ${i} -lt ${_maxfib}; do wait_remote_ready "START_${_n}_${i}" # No need to do anything for ICMPv6. # Start reflect for TCP and UDP. test_ulp_reflect_one "${_n}_tcp" "-N -T TCP6 -A ${_addr}" \ ${i} ${CTRLPORT} test_ulp_reflect_one "${_n}_udp" "-N -T UDP6 -A ${_addr}" \ ${i} ${CTRLPORT} wait_remote_ready "STOP_${_n}_${i}" i=$((i + 1)) done # Cleanup networking again. route delete -net -inet6 default > /dev/null 2>&1 i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} inet6 2001:2:${i}::2/64 -alias i=$((i + 1)) done ifconfig lo0 inet6 ${_addr}/128 -alias } _fwd_fib_symmetric_destructive_defroute_middle_setup_networking() { local _maxfib i j _maxfib=$1 # Setup networking. i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias \ > /dev/null 2>&1 || true ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 alias j=0 while test ${j} -lt ${_maxfib}; do # Only work on all other FIBs. if test ${j} -ne ${i}; then setfib -F ${j} route delete -net -inet6 \ 2001:2:${i}::/64 > /dev/null fi j=$((j + 1)) done setfib -F ${i} route delete -net -inet6 \ 2001:2:1234::2 2001:2:${i}::2 > /dev/null 2>&1 || true setfib -F ${i} route add -net -inet6 \ 2001:2:1234::2 2001:2:${i}::2 > /dev/null i=$((i + 1)) done } _fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking() { local _maxfib i _maxfib=$1 # Cleanup networking again. i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACEFAR} inet6 2001:2:${i}::1/64 -alias setfib -F ${i} route delete -net -inet6 \ 2001:2:1234::2 2001:2:${i}::2 > /dev/null i=$((i + 1)) done } _fwd_fib_symmetric_destructive_defroute_middle_ifconfig() { local _n _maxfib i _n="$1" _maxfib=$2 _fwd_fib_symmetric_destructive_defroute_middle_setup_networking \ ${_maxfib} i=0 while test ${i} -lt ${_maxfib}; do ifconfig ${IFACE} fib ${i} ifconfig ${IFACEFAR} fib ${i} setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count i=$((i + 1)) done _fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \ ${_maxfib} } _fwd_fib_symmetric_destructive_defroute_middle_ipfw() { local _n _maxfib i _port _n="$1" _maxfib=$2 _fwd_fib_symmetric_destructive_defroute_middle_setup_networking \ ${_maxfib} i=0 while test ${i} -lt ${_maxfib}; do _port=$((CTRLPORT + 1 + i)) ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 128 via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ dst-port ${_port} via ${IFACE} in > /dev/null ipfw add 100 setfib ${i} ipv6-icmp from any to any \ icmp6types 129 via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} tcp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null ipfw add 100 setfib ${i} udp from any to any \ src-port ${_port} via ${IFACEFAR} in > /dev/null setup_ipfw_count ${CTRLPORT} ${_maxfib} ${i} -1 wait_remote_ready "START_${_n}_${i}" ipfw -q zero > /dev/null # Nothing to do for the middle node testing the default. sleep 1 wait_remote_ready "STOP_${_n}_${i}" report_ipfw_count ipfw delete 100 > /dev/null i=$((i + 1)) done _fwd_fib_symmetric_destructive_defroute_middle_cleanup_networking \ ${_maxfib} } fwd_fib_symmetric_destructive_defroute_ifconfig() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_destructive_defroute_ifconfig" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_destructive_defroute_left \ ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_destructive_defroute_middle_ifconfig \ ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_destructive_defroute_right \ ${_n} ${_maxfib} ;; esac } fwd_fib_symmetric_destructive_defroute_ipfw() { local _maxfib _n _maxfib=$1 _n="fwd_fib_symmetric_destructive_defroute_ipfw" print_debug "${_n} ${_maxfib}" case ${node} in left) _fwd_fib_symmetric_destructive_defroute_left \ ${_n} ${_maxfib} ;; middle) _fwd_fib_symmetric_destructive_defroute_middle_ipfw \ ${_n} ${_maxfib} ;; right) _fwd_fib_symmetric_destructive_defroute_right \ ${_n} ${_maxfib} ;; esac } ################################################################################ # # MAIN # # Same for all hosts. if test `sysctl -n security.jail.jailed` -eq 0; then kldload ipfw > /dev/null 2>&1 || kldstat -v | grep -q ipfw fi ipfw -f flush > /dev/null 2>&1 || die "please load ipfw in base system" ipfw add 65000 permit ip from any to any > /dev/null 2>&1 # Per host setup. setup_networking reachability_check # # Tests # fwd_default_fib_symmetric fwd_default_fib_symmetric_ifconfig fwd_default_fib_symmetric_ipfw fwd_fib_symmetric_ifconfig ${RT_NUMFIBS} fwd_fib_symmetric_ipfw ${RT_NUMFIBS} fwd_fib_asymmetric_ifconfig ${RT_NUMFIBS} fwd_fib_asymmetric_ipfw ${RT_NUMFIBS} fwd_fib_symmetric_destructive_ifconfig ${RT_NUMFIBS} fwd_fib_symmetric_destructive_ipfw ${RT_NUMFIBS} fwd_fib_symmetric_destructive_defroute_ifconfig ${RT_NUMFIBS} fwd_fib_symmetric_destructive_defroute_ipfw ${RT_NUMFIBS} # Per host cleanup. cleanup_networking # end