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 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 343 exit 1 344 fi 345 if [ ${pkt_1} -le 10 ]; then 346 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 347 exit 1 348 fi 349 echo "TCP Balancing: 1: ${pkt_0} 2: ${pkt_1}" 350} 351 352output_tcp_flowid_mpath_success_cleanup() 353{ 354 vnet_cleanup 355} 356 357atf_test_case "output_udp_flowid_mpath_success" "cleanup" 358output_udp_flowid_mpath_success_head() 359{ 360 361 atf_set descr 'Test valid IPv4 UDP output flowid generation' 362 atf_set require.user root 363} 364 365output_udp_flowid_mpath_success_body() 366{ 367 368 vnet_init 369 mpath_check 370 371 # Note this test will spawn around ~100 nc processes 372 373 net_src="192.0.2." 374 net_dst="198.51.100." 375 ip_src="${net_src}1" 376 ip_dst="${net_dst}1" 377 plen=24 378 text="testtesttst" 379 380 script_name=`dirname $0`/../common/net_receiver.py 381 script_name=`realpath ${script_name}` 382 jname="v4t-output_tcp_flowid_mpath_success" 383 384 epair0=$(vnet_mkepair) 385 epair1=$(vnet_mkepair) 386 lo_src=$(vnet_mkloopback) 387 lo_dst=$(vnet_mkloopback) 388 389 vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src} 390 # Setup transit IPv4 networks 391 jexec ${jname}a ifconfig ${epair0}a up 392 jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30 393 jexec ${jname}a ifconfig ${epair1}a up 394 jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30 395 jexec ${jname}a ifconfig ${lo_src} up 396 397 vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst} 398 jexec ${jname}b ifconfig ${epair0}b up 399 jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30 400 jexec ${jname}b ifconfig ${epair1}b up 401 jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30 402 jexec ${jname}b ifconfig ${lo_dst} up 403 404 # DST ips/ports to test 405 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" 406 ports="53540 49743 43067 9131 16734 5150 14379 40292 20634 51302 3387 24387 9282 14275 42103 26881 42461 29520 45714 11096" 407 408 jexec ${jname}a ifconfig ${lo_src} inet ${ip_src}/32 409 410 jexec ${jname}b ifconfig ${lo_dst} inet ${ip_dst}/32 411 for i in ${ips}; do 412 jexec ${jname}b ifconfig ${lo_dst} alias ${net_dst}${i}/32 413 done 414 415 # Add routes 416 # A -> towards B via epair0a 417 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.2 418 # A -> towards B via epair1a 419 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.6 420 421 # B towards A via epair0b 422 jexec ${jname}b route add -4 -net ${net_src}0/${plen} 203.0.113.1 423 424 # Base setup verification 425 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 426 427 # run listener 428 num_ports=`echo ${ports} | wc -w` 429 num_ips=`echo ${ips} | wc -w` 430 count_examples=$((num_ports*num_ips)) 431 listener_ports=`echo ${ports} | tr ' ' '\n' | sort -n | tr '\n' ',' | sed -e 's?,$??'` 432 args="--family inet --ports ${listener_ports} --count ${count_examples} --match_str ${text}" 433 echo jexec ${jname}b ${script_name} ${args} 434 jexec ${jname}b ${script_name} --test_name "test_listen_udp" ${args} & 435 cmd_pid=$! 436 437 # wait for the app init 438 counter=0 439 init=0 440 while [ ${counter} -le 50 ]; do 441 _ports=`jexec ${jname}b sockstat -4ql | awk "\\\$3 == ${cmd_pid} {print \\\$6}"|awk -F: "{print \\\$2}" | sort -n | tr '\n' ','` 442 if [ "${_ports}" = "${listener_ports}," ]; then 443 init=1 444 break; 445 fi 446 done 447 if [ ${init} -eq 0 ]; then 448 jexec ${jname}b sockstat -4ql | awk "\$3 == ${cmd_pid}" 449 echo "App setup failed" 450 exit 1 451 fi 452 echo "App setup done" 453 454 # run sender 455 for _ip in ${ips}; do 456 ip="${net_dst}${_ip}" 457 for port in ${ports}; do 458 # XXX: switch to something that allows immediate exit 459 echo -n "${text}" | jexec ${jname}a nc -nuNw1 ${ip} ${port} & 460 sleep 0.01 461 done 462 done 463 464 wait ${cmd_pid} 465 exit_code=$? 466 if [ $exit_code -ne 0 ]; then atf_fail "receiver exit code $exit_code" ; fi 467 468 pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'` 469 pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'` 470 if [ ${pkt_0} -le 10 ]; then 471 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 472 exit 1 473 fi 474 if [ ${pkt_1} -le 10 ]; then 475 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 476 exit 1 477 fi 478 echo "UDP BALANCING: 1: ${pkt_0} 2: ${pkt_1}" 479} 480 481output_udp_flowid_mpath_success_cleanup() 482{ 483 vnet_cleanup 484} 485 486atf_test_case "output_raw_flowid_mpath_success" "cleanup" 487output_raw_flowid_mpath_success_head() 488{ 489 490 atf_set descr 'Test valid IPv4 raw output flowid generation' 491 atf_set require.user root 492} 493 494output_raw_flowid_mpath_success_body() 495{ 496 497 vnet_init 498 mpath_check 499 500 net_src="192.0.2." 501 net_dst="198.51.100." 502 ip_src="${net_src}1" 503 ip_dst="${net_dst}1" 504 plen=24 505 text="testtesttst" 506 507 jname="v4t-output_tcp_flowid_mpath_success" 508 509 epair0=$(vnet_mkepair) 510 epair1=$(vnet_mkepair) 511 lo_src=$(vnet_mkloopback) 512 lo_dst=$(vnet_mkloopback) 513 514 vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src} 515 # Setup transit IPv4 networks 516 jexec ${jname}a ifconfig ${epair0}a up 517 jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30 518 jexec ${jname}a ifconfig ${epair1}a up 519 jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30 520 jexec ${jname}a ifconfig ${lo_src} up 521 522 vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst} 523 jexec ${jname}b ifconfig ${epair0}b up 524 jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30 525 jexec ${jname}b ifconfig ${epair1}b up 526 jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30 527 jexec ${jname}b ifconfig ${lo_dst} up 528 529 # DST ips/ports to test 530 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" 531 532 jexec ${jname}a ifconfig ${lo_src} inet ${ip_src}/32 533 534 jexec ${jname}b ifconfig ${lo_dst} inet ${ip_dst}/32 535 for i in ${ips}; do 536 jexec ${jname}b ifconfig ${lo_dst} alias ${net_dst}${i}/32 537 done 538 539 # Add routes 540 # A -> towards B via epair0a 541 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.2 542 # A -> towards B via epair1a 543 jexec ${jname}a route add -4 -net ${net_dst}0/${plen} 203.0.113.6 544 545 # B towards A via epair0b 546 jexec ${jname}b route add -4 -net ${net_src}0/${plen} 203.0.113.1 547 548 # Base setup verification 549 atf_check -o match:'1 packets transmitted, 1 packets received' jexec ${jname}a ping -nc1 ${ip_dst} 550 551 # run sender 552 valid_message='1 packets transmitted, 1 packets received' 553 for _ip in ${ips}; do 554 ip="${net_dst}${_ip}" 555 atf_check -o match:"${valid_message}" jexec ${jname}a ping -nc1 ${ip} 556 done 557 558 pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'` 559 pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'` 560 561 jexec ${jname}a netstat -bWf link -I ${epair0}a 562 jexec ${jname}a netstat -bWf link -I ${epair1}a 563 if [ ${pkt_0} -le 10 ]; then 564 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 565 exit 1 566 fi 567 if [ ${pkt_1} -le 10 ]; then 568 echo "Balancing failure: 1: ${pkt_0} 2: ${pkt_1}" 569 exit 1 570 fi 571 echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}" 572} 573 574output_raw_flowid_mpath_success_cleanup() 575{ 576 vnet_cleanup 577} 578 579atf_init_test_cases() 580{ 581 atf_add_test_case "output_tcp_setup_success" 582 atf_add_test_case "output_udp_setup_success" 583 atf_add_test_case "output_raw_success" 584 atf_add_test_case "output_tcp_flowid_mpath_success" 585 atf_add_test_case "output_udp_flowid_mpath_success" 586 atf_add_test_case "output_raw_flowid_mpath_success" 587} 588 589