1# $FreeBSD$ 2# 3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4# 5# Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27 28. $(atf_get_srcdir)/utils.subr 29. $(atf_get_srcdir)/runner.subr 30 31pipe_head() 32{ 33 atf_set descr 'Basic pipe test' 34 atf_set require.user root 35} 36 37pipe_body() 38{ 39 fw=$1 40 firewall_init $fw 41 dummynet_init $fw 42 43 epair=$(vnet_mkepair) 44 vnet_mkjail alcatraz ${epair}b 45 46 ifconfig ${epair}a 192.0.2.1/24 up 47 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 48 49 # Sanity check 50 atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2 51 52 jexec alcatraz dnctl pipe 1 config bw 30Byte/s 53 54 firewall_config alcatraz ${fw} \ 55 "ipfw" \ 56 "ipfw add 1000 pipe 1 ip from any to any" 57 58 # single ping succeeds just fine 59 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 60 61 # Saturate the link 62 ping -i .1 -c 5 -s 1200 192.0.2.2 63 64 # We should now be hitting the limits and get this packet dropped. 65 atf_check -s exit:2 -o ignore ping -c 1 -s 1200 192.0.2.2 66} 67 68pipe_cleanup() 69{ 70 firewall_cleanup $1 71} 72 73pipe_v6_head() 74{ 75 atf_set descr 'Basic IPv6 pipe test' 76 atf_set require.user root 77} 78 79pipe_v6_body() 80{ 81 fw=$1 82 firewall_init $fw 83 dummynet_init $fw 84 85 epair=$(vnet_mkepair) 86 vnet_mkjail alcatraz ${epair}b 87 88 ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad 89 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad 90 91 # Sanity check 92 atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2 93 94 jexec alcatraz dnctl pipe 1 config bw 100Byte/s 95 96 firewall_config alcatraz ${fw} \ 97 "ipfw" \ 98 "ipfw add 1000 pipe 1 ip6 from any to any" 99 100 # Single ping succeeds 101 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2 102 103 # Saturate the link 104 ping6 -i .1 -c 5 -s 1200 2001:db8:42::2 105 106 # We should now be hitting the limit and get this packet dropped. 107 atf_check -s exit:2 -o ignore ping6 -c 1 -s 1200 2001:db8:42::2 108} 109 110pipe_v6_cleanup() 111{ 112 firewall_cleanup $1 113} 114 115queue_head() 116{ 117 atf_set descr 'Basic queue test' 118 atf_set require.user root 119} 120 121queue_body() 122{ 123 fw=$1 124 firewall_init $fw 125 dummynet_init $fw 126 127 epair=$(vnet_mkepair) 128 vnet_mkjail alcatraz ${epair}b 129 130 ifconfig ${epair}a 192.0.2.1/24 up 131 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 132 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \ 133 $(atf_get_srcdir)/../pf/echo_inetd.conf 134 135 # Sanity check 136 atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2 137 reply=$(echo "foo" | nc -N 192.0.2.2 7) 138 if [ "$reply" != "foo" ]; 139 then 140 atf_fail "Echo sanity check failed" 141 fi 142 143 jexec alcatraz dnctl pipe 1 config bw 1MByte/s 144 jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+ 145 jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all 146 jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all 147 148 firewall_config alcatraz ${fw} \ 149 "ipfw" \ 150 "ipfw add 1000 queue 100 tcp from 192.0.2.2 to any out" \ 151 "ipfw add 1001 queue 200 icmp from 192.0.2.2 to any out" \ 152 "ipfw add 1002 allow ip from any to any" 153 154 # Single ping succeeds 155 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 156 157 # Unsaturated TCP succeeds 158 reply=$(echo "foo" | nc -w 5 -N 192.0.2.2 7) 159 if [ "$reply" != "foo" ]; 160 then 161 atf_fail "Unsaturated echo failed" 162 fi 163 164 # Saturate the link 165 ping -f -s 1300 192.0.2.2 & 166 167 # Allow this to fill the queue 168 sleep 1 169 170 # TCP should still just pass 171 fails=0 172 for i in `seq 1 3` 173 do 174 result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c) 175 if [ $result -ne 2048000 ]; 176 then 177 echo "Failed to prioritise TCP traffic. Got only $result bytes" 178 fails=$(( ${fails} + 1 )) 179 fi 180 done 181 if [ ${fails} -gt 0 ]; 182 then 183 atf_fail "We failed prioritisation ${fails} times" 184 fi 185 186 # This will fail if we reverse the pola^W priority 187 firewall_config alcatraz ${fw} \ 188 "ipfw" \ 189 "ipfw add 1000 queue 200 tcp from 192.0.2.2 to any out" \ 190 "ipfw add 1001 queue 100 icmp from 192.0.2.2 to any out" \ 191 "ipfw add 1002 allow ip from any to any" 192 193 jexec alcatraz ping -f -s 1300 192.0.2.1 & 194 sleep 1 195 196 fails=0 197 for i in `seq 1 3` 198 do 199 result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c) 200 if [ $result -ne 2048000 ]; 201 then 202 echo "Failed to prioritise TCP traffic. Got only $result bytes" 203 fails=$(( ${fails} + 1 )) 204 fi 205 done 206 if [ ${fails} -lt 3 ]; 207 then 208 atf_fail "We failed reversed prioritisation only ${fails} times." 209 fi 210} 211 212queue_cleanup() 213{ 214 firewall_cleanup $1 215} 216 217queue_v6_head() 218{ 219 atf_set descr 'Basic queue test' 220 atf_set require.user root 221} 222 223queue_v6_body() 224{ 225 fw=$1 226 firewall_init $fw 227 dummynet_init $fw 228 229 epair=$(vnet_mkepair) 230 vnet_mkjail alcatraz ${epair}b 231 232 ifconfig ${epair}a inet6 2001:db8:42::1/64 no_dad up 233 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2 no_dad up 234 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \ 235 $(atf_get_srcdir)/../pf/echo_inetd.conf 236 237 # Sanity check 238 atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2 239 reply=$(echo "foo" | nc -N 2001:db8:42::2 7) 240 if [ "$reply" != "foo" ]; 241 then 242 atf_fail "Echo sanity check failed" 243 fi 244 245 jexec alcatraz dnctl pipe 1 config bw 1MByte/s 246 jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+ 247 jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all 248 jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all 249 250 firewall_config alcatraz ${fw} \ 251 "ipfw" \ 252 "ipfw add 1001 queue 100 tcp from 2001:db8:42::2 to any out" \ 253 "ipfw add 1000 queue 200 ipv6-icmp from 2001:db8:42::2 to any out" \ 254 "ipfw add 1002 allow ip6 from any to any" \ 255 "pf" \ 256 "pass out proto tcp dnqueue 100" \ 257 "pass out proto icmp6 dnqueue 200" 258 259 # Single ping succeeds 260 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2 261 262 # Unsaturated TCP succeeds 263 reply=$(echo "foo" | nc -w 5 -N 2001:db8:42::2 7) 264 if [ "$reply" != "foo" ]; 265 then 266 atf_fail "Unsaturated echo failed" 267 fi 268 269 # Saturate the link 270 ping6 -f -s 1200 2001:db8:42::2 & 271 272 # Allow this to fill the queue 273 sleep 1 274 275 # TCP should still just pass 276 fails=0 277 for i in `seq 1 3` 278 do 279 result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c) 280 if [ $result -ne 1024000 ]; 281 then 282 echo "Failed to prioritise TCP traffic. Got only $result bytes" 283 fails=$(( ${fails} + 1 )) 284 fi 285 done 286 if [ ${fails} -gt 0 ]; 287 then 288 atf_fail "We failed prioritisation ${fails} times" 289 fi 290 291 # What happens if we prioritise ICMP over TCP? 292 firewall_config alcatraz ${fw} \ 293 "ipfw" \ 294 "ipfw add 1001 queue 200 tcp from 2001:db8:42::2 to any out" \ 295 "ipfw add 1000 queue 100 ipv6-icmp from 2001:db8:42::2 to any out" \ 296 "ipfw add 1002 allow ip6 from any to any" \ 297 "pf" \ 298 "pass out proto tcp dnqueue 200" \ 299 "pass out proto icmp6 dnqueue 100" 300 301 fails=0 302 for i in `seq 1 3` 303 do 304 result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c) 305 if [ $result -ne 1024000 ]; 306 then 307 echo "Failed to prioritise TCP traffic. Got only $result bytes" 308 fails=$(( ${fails} + 1 )) 309 fi 310 done 311 if [ ${fails} -lt 3 ]; 312 then 313 atf_fail "We failed reversed prioritisation only ${fails} times." 314 fi 315} 316 317queue_v6_cleanup() 318{ 319 firewall_cleanup $1 320} 321 322setup_tests \ 323 pipe \ 324 ipfw \ 325 pipe_v6 \ 326 ipfw \ 327 queue \ 328 ipfw \ 329 queue_v6 \ 330 ipfw 331