Path: blob/main/tests/sys/netpfil/common/dummynet.sh
39507 views
#1# SPDX-License-Identifier: BSD-2-Clause2#3# Copyright (c) 2021 Rubicon Communications, LLC (Netgate)4#5# Redistribution and use in source and binary forms, with or without6# modification, are permitted provided that the following conditions7# are met:8# 1. Redistributions of source code must retain the above copyright9# notice, this list of conditions and the following disclaimer.10# 2. Redistributions in binary form must reproduce the above copyright11# notice, this list of conditions and the following disclaimer in the12# documentation and/or other materials provided with the distribution.13#14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24# SUCH DAMAGE.2526. $(atf_get_srcdir)/utils.subr27. $(atf_get_srcdir)/runner.subr2829interface_removal_head()30{31atf_set descr 'Test removing interfaces with dummynet delayed traffic'32atf_set require.user root33}3435interface_removal_body()36{37fw=$138firewall_init $fw39dummynet_init $fw4041epair=$(vnet_mkepair)42vnet_mkjail alcatraz ${epair}b4344ifconfig ${epair}a 192.0.2.1/24 up45jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up4647# Sanity check48atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.24950jexec alcatraz dnctl pipe 1 config delay 15005152firewall_config alcatraz ${fw} \53"ipfw" \54"ipfw add 1000 pipe 1 ip from any to any" \55"pf" \56"pass on ${epair}b dnpipe 1"5758# single ping succeeds just fine59atf_check -s exit:0 -o ignore ping -c 1 192.0.2.26061# Send traffic that'll still be pending when we remove the interface62ping -c 5 -s 1200 192.0.2.2 &63sleep 1 # Give ping the chance to start.6465# Remove the interface, but keep the jail around for a bit66ifconfig ${epair}a destroy6768sleep 369}7071interface_removal_cleanup()72{73firewall_cleanup $174}7576pipe_head()77{78atf_set descr 'Basic pipe test'79atf_set require.user root80}8182pipe_body()83{84fw=$185firewall_init $fw86dummynet_init $fw8788epair=$(vnet_mkepair)89vnet_mkjail alcatraz ${epair}b9091ifconfig ${epair}a 192.0.2.1/24 up92jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up9394# Sanity check95atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.29697jexec alcatraz dnctl pipe 1 config bw 30Byte/s9899firewall_config alcatraz ${fw} \100"ipfw" \101"ipfw add 1000 pipe 1 ip from any to any" \102"pf" \103"pass on ${epair}b dnpipe 1"104105# single ping succeeds just fine106atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2107108# Saturate the link109ping -i .1 -c 5 -s 1200 192.0.2.2110111# We should now be hitting the limits and get this packet dropped.112atf_check -s exit:2 -o ignore ping -c 1 -s 1200 192.0.2.2113}114115pipe_cleanup()116{117firewall_cleanup $1118}119120pipe_v6_head()121{122atf_set descr 'Basic IPv6 pipe test'123atf_set require.user root124}125126pipe_v6_body()127{128fw=$1129firewall_init $fw130dummynet_init $fw131132epair=$(vnet_mkepair)133vnet_mkjail alcatraz ${epair}b134135ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad136jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad137138# Sanity check139atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2140141jexec alcatraz dnctl pipe 1 config bw 100Byte/s142143firewall_config alcatraz ${fw} \144"ipfw" \145"ipfw add 1000 pipe 1 ip6 from any to any" \146"pf" \147"pass on ${epair}b dnpipe 1"148149# Single ping succeeds150atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2151152# Saturate the link153ping6 -i .1 -c 5 -s 1200 2001:db8:42::2154155# We should now be hitting the limit and get this packet dropped.156atf_check -s exit:2 -o ignore ping6 -c 1 -s 1200 2001:db8:42::2157}158159pipe_v6_cleanup()160{161firewall_cleanup $1162}163164codel_head()165{166atf_set descr 'FQ_CODEL basic test'167atf_set require.user root168}169170codel_body()171{172fw=$1173firewall_init $fw174dummynet_init $fw175176epair=$(vnet_mkepair)177vnet_mkjail alcatraz ${epair}b178179ifconfig ${epair}a 192.0.2.1/24 up180jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up181182# Sanity check183atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2184185jexec alcatraz dnctl pipe 1 config bw 10Mb queue 100 droptail186jexec alcatraz dnctl sched 1 config pipe 1 type fq_codel target 0ms interval 0ms quantum 1514 limit 10240 flows 1024 ecn187jexec alcatraz dnctl queue 1 config pipe 1 droptail188189firewall_config alcatraz ${fw} \190"ipfw" \191"ipfw add 1000 queue 1 ip from any to any" \192"pf" \193"pass dnqueue 1"194195# single ping succeeds just fine196atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2197}198199codel_cleanup()200{201firewall_cleanup $1202}203204wf2q_heap_head()205{206atf_set descr 'Test WF2Q+, attempting to provoke use-after-free'207atf_set require.user root208}209210wf2q_heap_body()211{212fw=$1213firewall_init $fw214dummynet_init $fw215216j=dummynet_wf2q_heap_${fw}_217218epair=$(vnet_mkepair)219epair_other=$(vnet_mkepair)220vnet_mkjail ${j}a ${epair}a221vnet_mkjail ${j}b ${epair}b ${epair_other}b222223jexec ${j}a ifconfig ${epair}a up mtu 9000224va=$(jexec ${j}a ifconfig vlan create vlan 42 vlandev ${epair}a)225jexec ${j}a ifconfig ${va} 192.0.2.1/24 up #mtu 8000226227jexec ${j}b ifconfig ${epair}b up mtu 9000228vb=$(jexec ${j}b ifconfig vlan create vlan 42 vlandev ${epair}b)229jexec ${j}b ifconfig ${vb} 192.0.2.2/24 up #mtu 8000230jexec ${j}b ifconfig ${epair_other}b up231232# Sanity check233atf_check -s exit:0 -o ignore \234jexec ${j}b ping -c 1 192.0.2.1235236jexec ${j}b dnctl pipe 1 config bw 10Mb queue 100 delay 500 droptail237jexec ${j}b dnctl sched 1 config pipe 1 type wf2q+238jexec ${j}b dnctl queue 1 config pipe 1 droptail239240firewall_config ${j}b ${fw} \241"pf" \242"pass dnqueue 1"243244jexec ${j}a ping -f 192.0.2.2 &245sleep 1246247jexec ${j}b ifconfig ${vb} destroy248249sleep 2250}251252wf2q_heap_cleanup()253{254firewall_cleanup $1255}256257queue_head()258{259atf_set descr 'Basic queue test'260atf_set require.user root261}262263queue_body()264{265fw=$1266267firewall_init $fw268dummynet_init $fw269270epair=$(vnet_mkepair)271vnet_mkjail alcatraz ${epair}b272273ifconfig ${epair}a 192.0.2.1/24 up274jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up275jexec alcatraz /usr/sbin/inetd -p ${PWD}/inetd-alcatraz.pid \276$(atf_get_srcdir)/../pf/echo_inetd.conf277278# Sanity check279atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2280reply=$(echo "foo" | nc -N 192.0.2.2 7)281if [ "$reply" != "foo" ];282then283atf_fail "Echo sanity check failed"284fi285286jexec alcatraz dnctl pipe 1 config bw 1MByte/s287jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+288jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all289jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all290291firewall_config alcatraz ${fw} \292"ipfw" \293"ipfw add 1000 queue 100 tcp from 192.0.2.2 to any out" \294"ipfw add 1001 queue 200 icmp from 192.0.2.2 to any out" \295"ipfw add 1002 allow ip from any to any" \296"pf" \297"pass in proto tcp dnqueue (0, 100)" \298"pass in proto icmp dnqueue (0, 200)"299300# Single ping succeeds301atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2302303# Unsaturated TCP succeeds304reply=$(echo "foo" | nc -w 5 -N 192.0.2.2 7)305if [ "$reply" != "foo" ];306then307atf_fail "Unsaturated echo failed"308fi309310# Saturate the link311ping -f -s 1300 192.0.2.2 &312313# Allow this to fill the queue314sleep 1315316# TCP should still just pass317fails=0318for i in `seq 1 5`319do320result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c)321if [ $result -ne 2048000 ];322then323echo "Failed to prioritise TCP traffic. Got only $result bytes"324fails=$(( ${fails} + 1 ))325fi326done327if [ ${fails} -gt 2 ];328then329atf_fail "We failed prioritisation ${fails} times"330fi331332# This will fail if we reverse the pola^W priority333firewall_config alcatraz ${fw} \334"ipfw" \335"ipfw add 1000 queue 200 tcp from 192.0.2.2 to any out" \336"ipfw add 1001 queue 100 icmp from 192.0.2.2 to any out" \337"ipfw add 1002 allow ip from any to any" \338"pf" \339"pass in proto tcp dnqueue (0, 200)" \340"pass in proto icmp dnqueue (0, 100)"341342jexec alcatraz ping -f -s 1300 192.0.2.1 &343sleep 1344345fails=0346for i in `seq 1 5`347do348result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c)349if [ $result -ne 2048000 ];350then351echo "Failed to prioritise TCP traffic. Got only $result bytes"352fails=$(( ${fails} + 1 ))353fi354done355if [ ${fails} -lt 3 ];356then357atf_fail "We failed reversed prioritisation only ${fails} times."358fi359}360361queue_cleanup()362{363firewall_cleanup $1364}365366queue_v6_head()367{368atf_set descr 'Basic queue test'369atf_set require.user root370}371372queue_v6_body()373{374fw=$1375firewall_init $fw376dummynet_init $fw377378epair=$(vnet_mkepair)379vnet_mkjail alcatraz ${epair}b380381ifconfig ${epair}a inet6 2001:db8:42::1/64 no_dad up382jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2 no_dad up383jexec alcatraz /usr/sbin/inetd -p ${PWD}/inetd-alcatraz.pid \384$(atf_get_srcdir)/../pf/echo_inetd.conf385jexec alcatraz sysctl net.inet6.icmp6.errppslimit=0386387# Sanity check388atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2389reply=$(echo "foo" | nc -N 2001:db8:42::2 7)390if [ "$reply" != "foo" ];391then392atf_fail "Echo sanity check failed"393fi394395jexec alcatraz dnctl pipe 1 config bw 1MByte/s396jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+397jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all398jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all399400firewall_config alcatraz ${fw} \401"ipfw" \402"ipfw add 1001 queue 100 tcp from 2001:db8:42::2 to any out" \403"ipfw add 1000 queue 200 ipv6-icmp from 2001:db8:42::2 to any out" \404"ipfw add 1002 allow ip6 from any to any" \405"pf" \406"pass in proto tcp dnqueue (0, 100)" \407"pass in proto icmp6 dnqueue (0, 200)"408409# Single ping succeeds410atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2411412# Unsaturated TCP succeeds413reply=$(echo "foo" | nc -w 5 -N 2001:db8:42::2 7)414if [ "$reply" != "foo" ];415then416atf_fail "Unsaturated echo failed"417fi418419# Saturate the link420ping6 -f -s 1200 2001:db8:42::2 &421422# Allow this to fill the queue423sleep 1424425# TCP should still just pass426fails=0427for i in `seq 1 5`428do429result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c)430if [ $result -ne 1024000 ];431then432echo "Failed to prioritise TCP traffic. Got only $result bytes"433fails=$(( ${fails} + 1 ))434fi435done436if [ ${fails} -gt 2 ];437then438atf_fail "We failed prioritisation ${fails} times"439fi440441# What happens if we prioritise ICMP over TCP?442firewall_config alcatraz ${fw} \443"ipfw" \444"ipfw add 1001 queue 200 tcp from 2001:db8:42::2 to any out" \445"ipfw add 1000 queue 100 ipv6-icmp from 2001:db8:42::2 to any out" \446"ipfw add 1002 allow ip6 from any to any" \447"pf" \448"pass in proto tcp dnqueue (0, 200)" \449"pass in proto icmp6 dnqueue (0, 100)"450451fails=0452for i in `seq 1 5`453do454result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c)455if [ $result -ne 1024000 ];456then457echo "Failed to prioritise TCP traffic. Got only $result bytes"458fails=$(( ${fails} + 1 ))459fi460done461if [ ${fails} -lt 3 ];462then463atf_fail "We failed reversed prioritisation only ${fails} times."464fi465}466467queue_v6_cleanup()468{469firewall_cleanup $1470}471472nat_head()473{474atf_set descr 'Basic dummynet + NAT test'475atf_set require.user root476}477478nat_body()479{480fw=$1481firewall_init $fw482dummynet_init $fw483nat_init $fw484485epair=$(vnet_mkepair)486epair_two=$(vnet_mkepair)487488ifconfig ${epair}a 192.0.2.2/24 up489route add -net 198.51.100.0/24 192.0.2.1490491vnet_mkjail gw ${epair}b ${epair_two}a492jexec gw ifconfig ${epair}b 192.0.2.1/24 up493jexec gw ifconfig ${epair_two}a 198.51.100.1/24 up494jexec gw sysctl net.inet.ip.forwarding=1495496vnet_mkjail srv ${epair_two}b497jexec srv ifconfig ${epair_two}b 198.51.100.2/24 up498499jexec gw dnctl pipe 1 config bw 300Byte/s500501firewall_config gw $fw \502"pf" \503"nat on ${epair_two}a inet from 192.0.2.0/24 to any -> (${epair_two}a)" \504"pass dnpipe 1"505506# We've deliberately not set a route to 192.0.2.0/24 on srv, so the507# only way it can respond to this is if NAT is applied correctly.508atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2509}510511nat_cleanup()512{513firewall_cleanup $1514}515516pls_basic_head()517{518atf_set descr 'Basic dummynet packet loss rate test'519atf_set require.user root520}521522pls_basic_body()523{524fw=$1525firewall_init $fw526dummynet_init $fw527528epair=$(vnet_mkepair)529vnet_mkjail alcatraz ${epair}b530531ifconfig ${epair}a 192.0.2.1/24 up532jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up533534firewall_config alcatraz ${fw} \535"ipfw" \536"ipfw add 65432 ip from any to any" \537"pf" \538"pass on ${epair}b"539540# Sanity check541atf_check -s exit:0 -o match:'100 packets transmitted, 100 packets received' ping -i .1 -c 100 192.0.2.2542543jexec alcatraz dnctl pipe 1 config plr 0.1544545firewall_config alcatraz ${fw} \546"ipfw" \547"ipfw add 1000 pipe 1 ip from 192.0.2.1 to 192.0.2.2" \548"pf" \549"pass on ${epair}b dnpipe 1"550551# check if the expected number of pings552# are dropped (84 - 96 responses).553# repeat up to 6 times if the initial554# checks fail555atf_check -s exit:0 -o match:'100 packets transmitted, (8[4-9]|9[0-6]) packets received' -r 20:10 ping -i 0.010 -c 100 192.0.2.2556}557558pls_basic_cleanup()559{560firewall_cleanup $1561}562563pls_gilbert_head()564{565atf_set descr 'dummynet Gilbert-Elliott packet loss model test'566atf_set require.user root567}568569pls_gilbert_body()570{571fw=$1572firewall_init $fw573dummynet_init $fw574575epair=$(vnet_mkepair)576vnet_mkjail alcatraz ${epair}b577578ifconfig ${epair}a 192.0.2.1/24 up579jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up580581firewall_config alcatraz ${fw} \582"ipfw" \583"ipfw add 65432 ip from any to any" \584"pf" \585"pass on ${epair}b"586587# Sanity check588atf_check -s exit:0 -o match:'100 packets transmitted, 100 packets received' ping -i .1 -c 100 192.0.2.2589590jexec alcatraz dnctl pipe 1 config plr 0.01,0.1,0.8,0.2591592firewall_config alcatraz ${fw} \593"ipfw" \594"ipfw add 1000 pipe 1 ip from 192.0.2.1 to 192.0.2.2" \595"pf" \596"pass on ${epair}b dnpipe 1"597598# check if the expected number of pings599# are dropped (70 - 85 responses).600# repeat up to 6 times if the initial601# checks fail602atf_check -s exit:0 -o match:'100 packets transmitted, (7[0-9]|8[0-5]) packets received' -r 20:10 ping -i 0.010 -c 100 192.0.2.2603}604605pls_gilbert_cleanup()606{607firewall_cleanup $1608}609610611612setup_tests \613interface_removal \614ipfw \615pf \616pipe \617ipfw \618pf \619pipe_v6 \620ipfw \621pf \622codel \623ipfw \624pf \625wf2q_heap \626pf \627queue \628ipfw \629pf \630queue_v6 \631ipfw \632pf \633nat \634pf \635pls_basic \636ipfw \637pf \638pls_gilbert \639ipfw \640pf641642643