1#!/usr/bin/env atf-sh 2#- 3# SPDX-License-Identifier: BSD-2-Clause 4# 5# Copyright (c) 2020 Alexander V. Chernikov 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# $FreeBSD$ 29# 30 31. $(atf_get_srcdir)/../common/vnet.subr 32 33atf_test_case "output_tcp_setup_success" "cleanup" 34output_tcp_setup_success_head() 35{ 36 37 atf_set descr 'Test valid IPv4 TCP output' 38 atf_set require.user root 39} 40 41output_tcp_setup_success_body() 42{ 43 44 vnet_init 45 46 net_src="192.0.2." 47 net_dst="192.0.2." 48 ip_src="${net_src}1" 49 ip_dst="${net_dst}2" 50 plen=24 51 text="testtesttst" 52 port=4242 53 54 script_name=`dirname $0`/../common/net_receiver.py 55 script_name=`realpath ${script_name}` 56 jname="v4t-output_tcp_setup_success" 57 58 epair=$(vnet_mkepair) 59 60 vnet_mkjail ${jname}a ${epair}a 61 jexec ${jname}a ifconfig ${epair}a up 62 jexec ${jname}a ifconfig ${epair}a inet ${ip_src}/${plen} 63 64 vnet_mkjail ${jname}b ${epair}b 65 jexec ${jname}b ifconfig ${epair}b up 66 67 jexec ${jname}b ifconfig ${epair}b inet ${ip_dst}/${plen} 68 69 # run listener 70 args="--family inet --ports ${port} --match_str ${text}" 71 echo jexec ${jname}b ${script_name} ${args} 72 jexec ${jname}b ${script_name} --test_name "test_listen_tcp" ${args} & 73 cmd_pid=$! 74 75 # wait for the script init 76 counter=0 77 while [ `jexec ${jname}b sockstat -4qlp ${port} | wc -l` != "1" ]; do 78 sleep 0.01 79 counter=$((counter+1)) 80 if [ ${counter} -ge 50 ]; then break; fi 81 done 82 if [ `jexec ${jname}b sockstat -4qlp ${port} | wc -l` != "1" ]; then 83 echo "App setup failed" 84 exit 1 85 fi 86 87 # run sender 88 echo -n "${text}" | jexec ${jname}a nc -N ${ip_dst} ${port} 89 exit_code=$? 90 if [ $exit_code -ne 0 ]; then atf_fail "sender exit code $exit_code" ; fi 91 92 wait ${cmd_pid} 93 exit_code=$? 94 if [ $exit_code -ne 0 ]; then atf_fail "receiver exit code $exit_code" ; fi 95} 96 97output_tcp_setup_success_cleanup() 98{ 99 vnet_cleanup 100} 101 102 103atf_test_case "output_udp_setup_success" "cleanup" 104output_udp_setup_success_head() 105{ 106 107 atf_set descr 'Test valid IPv4 UDP output' 108 atf_set require.user root 109} 110 111output_udp_setup_success_body() 112{ 113 114 vnet_init 115 116 net_src="192.0.2." 117 net_dst="192.0.2." 118 ip_src="${net_src}1" 119 ip_dst="${net_dst}2" 120 plen=24 121 text="testtesttst" 122 port=4242 123 124 script_name=`dirname $0`/../common/net_receiver.py 125 script_name=`realpath ${script_name}` 126 jname="v4t-output_udp_setup_success" 127 128 epair=$(vnet_mkepair) 129 130 vnet_mkjail ${jname}a ${epair}a 131 jexec ${jname}a ifconfig ${epair}a up 132 jexec ${jname}a ifconfig ${epair}a inet ${ip_src}/${plen} 133 134 vnet_mkjail ${jname}b ${epair}b 135 jexec ${jname}b ifconfig ${epair}b up 136 jexec ${jname}b ifconfig ${epair}b inet ${ip_dst}/${plen} 137 138 # run listener 139 args="--family inet --ports ${port} --match_str ${text}" 140 echo jexec ${jname}b ${script_name} ${args} 141 jexec ${jname}b ${script_name} --test_name "test_listen_udp" ${args} & 142 cmd_pid=$! 143 144 # wait for the script init 145 counter=0 146 while [ `jexec ${jname}b sockstat -4qlp ${port} | wc -l` != "1" ]; do 147 sleep 0.1 148 counterc=$((counter+1)) 149 if [ ${counter} -ge 50 ]; then break; fi 150 done 151 if [ `jexec ${jname}b sockstat -4qlp ${port} | wc -l` != "1" ]; then 152 echo "App setup failed" 153 exit 1 154 fi 155 156 # run sender 157 # TODO: switch from nc to some alternative to avoid 1-second delay 158 echo -n "${text}" | jexec ${jname}a nc -uNw1 ${ip_dst} ${port} 159 exit_code=$? 160 if [ $exit_code -ne 0 ]; then atf_fail "sender exit code $exit_code" ; fi 161 162 wait ${cmd_pid} 163 exit_code=$? 164 if [ $exit_code -ne 0 ]; then atf_fail "receiver exit code $exit_code" ; fi 165} 166 167output_udp_setup_success_cleanup() 168{ 169 vnet_cleanup 170} 171 172atf_test_case "output_raw_success" "cleanup" 173output_raw_success_head() 174{ 175 176 atf_set descr 'Test valid IPv4 raw output' 177 atf_set require.user root 178} 179 180output_raw_success_body() 181{ 182 183 vnet_init 184 185 net_src="192.0.2." 186 net_dst="192.0.2." 187 ip_src="${net_src}1" 188 ip_dst="${net_dst}2" 189 plen=24 190 191 script_name=`dirname $0`/../common/net_receiver.py 192 script_name=`realpath ${script_name}` 193 jname="v4t-output_raw_success" 194 195 epair=$(vnet_mkepair) 196 197 vnet_mkjail ${jname}a ${epair}a 198 jexec ${jname}a ifconfig ${epair}a up 199 jexec ${jname}a ifconfig ${epair}a inet ${ip_src}/${plen} 200 201 vnet_mkjail ${jname}b ${epair}b 202 jexec ${jname}b ifconfig ${epair}b up 203 204 jexec ${jname}b ifconfig ${epair}b inet ${ip_dst}/${plen} 205 206 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 207} 208 209output_raw_success_cleanup() 210{ 211 vnet_cleanup 212} 213 214# Multipath tests are done the following way: 215# epair0 216# jailA lo < > lo jailB 217# epair1 218# jailA has 2 routes towards /24 prefix on jailB loopback, via 2 epairs 219# jailB has 1 route towards /24 prefix on jailA loopback, via epair0 220# 221# jailA initiates connections/sends packets towards IPs on jailB loopback. 222# Script then compares amount of packets sent via epair0 and epair1 223 224mpath_check() 225{ 226 if [ "`sysctl -i -n net.route.multipath`" != 1 ]; then 227 atf_skip "This test requires ROUTE_MPATH enabled" 228 fi 229} 230 231atf_test_case "output_tcp_flowid_mpath_success" "cleanup" 232output_tcp_flowid_mpath_success_head() 233{ 234 235 atf_set descr 'Test valid IPv4 TCP output flowid generation' 236 atf_set require.user root 237} 238 239output_tcp_flowid_mpath_success_body() 240{ 241 vnet_init 242 mpath_check 243 244 net_src="192.0.2." 245 net_dst="198.51.100." 246 ip_src="${net_src}1" 247 ip_dst="${net_dst}1" 248 plen=24 249 text="testtesttst" 250 251 script_name=`dirname $0`/../common/net_receiver.py 252 script_name=`realpath ${script_name}` 253 jname="v4t-output_tcp_flowid_mpath_success" 254 255 epair0=$(vnet_mkepair) 256 epair1=$(vnet_mkepair) 257 lo_src=$(vnet_mkloopback) 258 lo_dst=$(vnet_mkloopback) 259 260 vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src} 261 # Setup transit IPv4 networks 262 jexec ${jname}a ifconfig ${epair0}a up 263 jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30 264 jexec ${jname}a ifconfig ${epair1}a up 265 jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30 266 jexec ${jname}a ifconfig ${lo_src} up 267 268 vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst} 269 jexec ${jname}b ifconfig ${epair0}b up 270 jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30 271 jexec ${jname}b ifconfig ${epair1}b up 272 jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30 273 jexec ${jname}b ifconfig ${lo_dst} up 274 275 # DST ips/ports to test 276 ips="4 29 48 53 55 61 71 80 84 87 90 91 119 131 137 153 154 158 162 169 169 171 176 187 197 228 233 235 236 237 245 251" 277 ports="53540 49743 43067 9131 16734 5150 14379 40292 20634 51302 3387 24387 9282 14275 42103 26881 42461 29520 45714 11096" 278 279 jexec ${jname}a ifconfig ${lo_src} inet ${ip_src}/32 280 281 jexec ${jname}b ifconfig ${lo_dst} inet ${ip_dst}/32 282 for i in ${ips}; do 283 jexec ${jname}b ifconfig ${lo_dst} alias ${net_dst}${i}/32 284 done 285 286 # Add routes 287 # A -> towards B via epair0a 288 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.2 289 # A -> towards B via epair1a 290 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.6 291 292 # B towards A via epair0b 293 jexec ${jname}b route add -4 -net ${net_src}0/${plen} 203.0.113.1 294 295 # Base setup verification 296 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 297 298 # run listener 299 num_ports=`echo ${ports} | wc -w` 300 num_ips=`echo ${ips} | wc -w` 301 count_examples=$((num_ports*num_ips)) 302 listener_ports=`echo ${ports} | tr ' ' '\n' | sort -n | tr '\n' ',' | sed -e 's?,$??'` 303 args="--family inet --ports ${listener_ports} --count ${count_examples} --match_str ${text}" 304 echo jexec ${jname}b ${script_name} ${args} 305 jexec ${jname}b ${script_name} --test_name "test_listen_tcp" ${args} & 306 cmd_pid=$! 307 308 # wait for the app init 309 counter=0 310 init=0 311 while [ ${counter} -le 50 ]; do 312 _ports=`jexec ${jname}b sockstat -4ql | awk "\\\$3 == ${cmd_pid} {print \\\$6}"|awk -F: "{print \\\$2}" | sort -n | tr '\n' ','` 313 if [ "${_ports}" = "${listener_ports}," ]; then 314 init=1 315 break; 316 fi 317 done 318 if [ ${init} -eq 0 ]; then 319 jexec ${jname}b sockstat -6ql | awk "\$3 == ${cmd_pid}" 320 echo "App setup failed" 321 exit 1 322 fi 323 echo "App setup done" 324 325 # run sender 326 for _ip in ${ips}; do 327 ip="${net_dst}${_ip}" 328 for port in ${ports}; do 329 echo -n "${text}" | jexec ${jname}a nc -nN ${ip} ${port} 330 exit_code=$? 331 if [ $exit_code -ne 0 ]; then atf_fail "sender exit code $exit_code" ; fi 332 done 333 done 334 335 wait ${cmd_pid} 336 exit_code=$? 337 if [ $exit_code -ne 0 ]; then atf_fail "receiver exit code $exit_code" ; fi 338 339 pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'` 340 pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'` 341 if [ ${pkt_0} -le 10 ]; then 342 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 343 fi 344 if [ ${pkt_1} -le 10 ]; then 345 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 346 exit 1 347 fi 348 echo "TCP Balancing: 1: ${pkt_0} 2: ${pkt_1}" 349} 350 351output_tcp_flowid_mpath_success_cleanup() 352{ 353 vnet_cleanup 354} 355 356atf_test_case "output_udp_flowid_mpath_success" "cleanup" 357output_udp_flowid_mpath_success_head() 358{ 359 360 atf_set descr 'Test valid IPv4 UDP output flowid generation' 361 atf_set require.user root 362} 363 364output_udp_flowid_mpath_success_body() 365{ 366 367 vnet_init 368 mpath_check 369 370 # Note this test will spawn around ~100 nc processes 371 372 net_src="192.0.2." 373 net_dst="198.51.100." 374 ip_src="${net_src}1" 375 ip_dst="${net_dst}1" 376 plen=24 377 text="testtesttst" 378 379 script_name=`dirname $0`/../common/net_receiver.py 380 script_name=`realpath ${script_name}` 381 jname="v4t-output_tcp_flowid_mpath_success" 382 383 epair0=$(vnet_mkepair) 384 epair1=$(vnet_mkepair) 385 lo_src=$(vnet_mkloopback) 386 lo_dst=$(vnet_mkloopback) 387 388 vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src} 389 # Setup transit IPv4 networks 390 jexec ${jname}a ifconfig ${epair0}a up 391 jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30 392 jexec ${jname}a ifconfig ${epair1}a up 393 jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30 394 jexec ${jname}a ifconfig ${lo_src} up 395 396 vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst} 397 jexec ${jname}b ifconfig ${epair0}b up 398 jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30 399 jexec ${jname}b ifconfig ${epair1}b up 400 jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30 401 jexec ${jname}b ifconfig ${lo_dst} up 402 403 # DST ips/ports to test 404 ips="4 29 48 53 55 61 71 80 84 87 90 91 119 131 137 153 154 158 162 169 169 171 176 187 197 228 233 235 236 237 245 251" 405 ports="53540 49743 43067 9131 16734 5150 14379 40292 20634 51302 3387 24387 9282 14275 42103 26881 42461 29520 45714 11096" 406 407 jexec ${jname}a ifconfig ${lo_src} inet ${ip_src}/32 408 409 jexec ${jname}b ifconfig ${lo_dst} inet ${ip_dst}/32 410 for i in ${ips}; do 411 jexec ${jname}b ifconfig ${lo_dst} alias ${net_dst}${i}/32 412 done 413 414 # Add routes 415 # A -> towards B via epair0a 416 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.2 417 # A -> towards B via epair1a 418 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.6 419 420 # B towards A via epair0b 421 jexec ${jname}b route add -4 -net ${net_src}0/${plen} 203.0.113.1 422 423 # Base setup verification 424 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 425 426 # run listener 427 num_ports=`echo ${ports} | wc -w` 428 num_ips=`echo ${ips} | wc -w` 429 count_examples=$((num_ports*num_ips)) 430 listener_ports=`echo ${ports} | tr ' ' '\n' | sort -n | tr '\n' ',' | sed -e 's?,$??'` 431 args="--family inet --ports ${listener_ports} --count ${count_examples} --match_str ${text}" 432 echo jexec ${jname}b ${script_name} ${args} 433 jexec ${jname}b ${script_name} --test_name "test_listen_udp" ${args} & 434 cmd_pid=$! 435 436 # wait for the app init 437 counter=0 438 init=0 439 while [ ${counter} -le 50 ]; do 440 _ports=`jexec ${jname}b sockstat -4ql | awk "\\\$3 == ${cmd_pid} {print \\\$6}"|awk -F: "{print \\\$2}" | sort -n | tr '\n' ','` 441 if [ "${_ports}" = "${listener_ports}," ]; then 442 init=1 443 break; 444 fi 445 done 446 if [ ${init} -eq 0 ]; then 447 jexec ${jname}b sockstat -4ql | awk "\$3 == ${cmd_pid}" 448 echo "App setup failed" 449 exit 1 450 fi 451 echo "App setup done" 452 453 # run sender 454 for _ip in ${ips}; do 455 ip="${net_dst}${_ip}" 456 for port in ${ports}; do 457 # XXX: switch to something that allows immediate exit 458 echo -n "${text}" | jexec ${jname}a nc -nuNw1 ${ip} ${port} & 459 sleep 0.01 460 done 461 done 462 463 wait ${cmd_pid} 464 exit_code=$? 465 if [ $exit_code -ne 0 ]; then atf_fail "receiver exit code $exit_code" ; fi 466 467 pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'` 468 pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'` 469 if [ ${pkt_0} -le 10 ]; then 470 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 471 fi 472 if [ ${pkt_1} -le 10 ]; then 473 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 474 fi 475 echo "UDP BALANCING: 1: ${pkt_0} 2: ${pkt_1}" 476} 477 478output_udp_flowid_mpath_success_cleanup() 479{ 480 vnet_cleanup 481} 482 483atf_test_case "output_raw_flowid_mpath_success" "cleanup" 484output_raw_flowid_mpath_success_head() 485{ 486 487 atf_set descr 'Test valid IPv4 raw output flowid generation' 488 atf_set require.user root 489} 490 491output_raw_flowid_mpath_success_body() 492{ 493 494 vnet_init 495 mpath_check 496 497 net_src="192.0.2." 498 net_dst="198.51.100." 499 ip_src="${net_src}1" 500 ip_dst="${net_dst}1" 501 plen=24 502 text="testtesttst" 503 504 jname="v4t-output_tcp_flowid_mpath_success" 505 506 epair0=$(vnet_mkepair) 507 epair1=$(vnet_mkepair) 508 lo_src=$(vnet_mkloopback) 509 lo_dst=$(vnet_mkloopback) 510 511 vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src} 512 # Setup transit IPv4 networks 513 jexec ${jname}a ifconfig ${epair0}a up 514 jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30 515 jexec ${jname}a ifconfig ${epair1}a up 516 jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30 517 jexec ${jname}a ifconfig ${lo_src} up 518 519 vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst} 520 jexec ${jname}b ifconfig ${epair0}b up 521 jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30 522 jexec ${jname}b ifconfig ${epair1}b up 523 jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30 524 jexec ${jname}b ifconfig ${lo_dst} up 525 526 # DST ips/ports to test 527 ips="4 29 48 53 55 61 71 80 84 87 90 91 119 131 137 153 154 158 162 169 169 171 176 187 197 228 233 235 236 237 245 251" 528 529 jexec ${jname}a ifconfig ${lo_src} inet ${ip_src}/32 530 531 jexec ${jname}b ifconfig ${lo_dst} inet ${ip_dst}/32 532 for i in ${ips}; do 533 jexec ${jname}b ifconfig ${lo_dst} alias ${net_dst}${i}/32 534 done 535 536 # Add routes 537 # A -> towards B via epair0a 538 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.2 539 # A -> towards B via epair1a 540 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.6 541 542 # B towards A via epair0b 543 jexec ${jname}b route add -4 -net ${net_src}0/${plen} 203.0.113.1 544 545 # Base setup verification 546 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 547 548 # run sender 549 valid_message='1 packets transmitted, 1 packets received' 550 for _ip in ${ips}; do 551 ip="${net_dst}${_ip}" 552 atf_check -o match:"${valid_message}" jexec ${jname}a ping -nc1 ${ip} 553 done 554 555 pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'` 556 pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'` 557 558 jexec ${jname}a netstat -bWf link -I ${epair0}a 559 jexec ${jname}a netstat -bWf link -I ${epair1}a 560 if [ ${pkt_0} -le 10 ]; then 561 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 562 fi 563 if [ ${pkt_1} -le 10 ]; then 564 atf_fail "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 565 fi 566 echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}" 567} 568 569output_raw_flowid_mpath_success_cleanup() 570{ 571 vnet_cleanup 572} 573 574atf_init_test_cases() 575{ 576 atf_add_test_case "output_tcp_setup_success" 577 atf_add_test_case "output_udp_setup_success" 578 atf_add_test_case "output_raw_success" 579 atf_add_test_case "output_tcp_flowid_mpath_success" 580 atf_add_test_case "output_udp_flowid_mpath_success" 581 atf_add_test_case "output_raw_flowid_mpath_success" 582} 583 584