1#!/usr/bin/ksh 2# 3# This file and its contents are supplied under the terms of the 4# Common Development and Distribution License ("CDDL"), version 1.0. 5# You may only use this file in accordance with the terms of version 6# 1.0 of the CDDL. 7# 8# A full copy of the text of the CDDL should have accompanied this 9# source. A copy of the CDDL is also available via the Internet at 10# http://www.illumos.org/license/CDDL. 11 12# 13# Copyright 2019 Joyent, Inc. 14# 15 16# 17# Usage: 18# 19# ip_forwarding.ksh -bcflnpuv <client> <router> <server> 20# 21# Where client, router, and server are the names of three native 22# zones. The user must create and start these zones; but other 23# than that there is no special configuration required for them. 24# 25# -b Place server and router on same underlying simnet, causing 26# them to talk via MAC-loopback. 27# 28# -c Run cleanup only. 29# 30# -f Enable Tx ULP hardware checksum. 31# 32# -l Enable TCP LSO. 33# 34# -n No cleanup: the various artifacts created by this script will 35# remain after execution. 36# 37# -p Enabled partial Tx ULP hardware checksum. 38# 39# -r Enable Rx IPv4 header checksum offload. 40# 41# -u Run UDP tests. 42# 43# -v Vebose mode. 44# 45 46if [[ -z $NET_TESTS ]]; then 47 echo "NET_TESTS not set" >&2 48 exit 1 49fi 50 51. $NET_TESTS/tests/net_common 52 53function cleanup 54{ 55 if ((nt_cleanup == 0)); then 56 dbg "skipping cleanup" 57 return 0 58 fi 59 60 rm -rf ${nt_tdirprefix}* 61 zlogin $nt_client rm -rf ${nt_tdirprefix}* 62 zlogin $nt_server rm -rf ${nt_tdirprefix}* 63 64 rm_route $nt_client $nt_server_ip $nt_server_subnet $nt_client_router_ip 65 rm_route $nt_server $nt_client_ip $nt_client_subnet $nt_server_router_ip 66 rm_route6 $nt_client $nt_server_ip6 $nt_server_subnet6 \ 67 $nt_client_router_ip6 68 rm_route6 $nt_server $nt_client_ip6 $nt_client_subnet6 \ 69 $nt_server_router_ip6 70 71 ip_fwd_disable $nt_router 72 73 delete_addr $nt_client ipft_client0 v4 74 delete_addr $nt_router ipft_client_r0 v4 75 delete_addr $nt_router ipft_server_r0 v4 76 delete_addr $nt_server ipft_server0 v4 77 78 delete_addr $nt_client ipft_client0 v6 79 delete_addr $nt_router ipft_client_r0 v6 80 delete_addr $nt_router ipft_server_r0 v6 81 delete_addr $nt_server ipft_server0 v6 82 83 delete_if $nt_client ipft_client0 84 delete_if $nt_router ipft_client_r0 85 delete_if $nt_router ipft_server_r0 86 delete_if $nt_server ipft_server0 87 88 delete_vnic ipft_client0 0 $nt_client 89 delete_vnic ipft_client_r0 0 $nt_router 90 delete_vnic ipft_server_r0 5 $nt_router 91 delete_vnic ipft_server0 5 $nt_server 92 93 for nt_name in ${nt_nics[@]}; do 94 delete_simnet $nt_name 95 done 96} 97 98function usage 99{ 100 echo "$nt_tname -bcflnpruv <client> <router> <server>" >&2 101} 102 103# 104# Set test defaults. 105# 106nt_tname=${NT_TNAME:-$(basename $0)} 107nt_loopback=0 108nt_ulp_full=0 109nt_ulp_partial=0 110nt_tcp_lso=0 111nt_udp=0 112nt_rx_ip_cksum=0 113nt_cleanup=1 114nt_cleanup_only=0 115 116nt_tdirprefix=/var/tmp/${nt_tname} 117nt_tdir=${nt_tdirprefix}.$$ 118nt_dfile=${nt_tdir}/${nt_tname}.data 119nt_efile=${nt_tdir}/${nt_tname}-expected-sha1 120nt_rfile=${nt_tdir}/${nt_tname}-received-sha1 121nt_ofile=${nt_tdir}/${nt_tname}-received 122nt_client_subnet=192.168.77.0/24 123nt_client_ip=192.168.77.2 124nt_client_router_ip=192.168.77.1 125nt_server_subnet=192.168.88.0/24 126nt_server_ip=192.168.88.2 127nt_server_router_ip=192.168.88.1 128nt_port=7774 129nt_client_subnet6=fd00:0:1:4d::2/64 130nt_client_ip6=fd00:0:1:4d::2 131nt_client_router_ip6=fd00:0:1:4d::1 132nt_server_subnet6=fd00:0:1:58::/64 133nt_server_router_ip6=fd00:0:1:58::1 134nt_server_ip6=fd00:0:1:58::2 135nt_port6=7776 136nt_bridge=ipft_switch 137typeset -A nt_nics 138 139while getopts "bcflnpruv" opt; do 140 case $opt in 141 b) 142 nt_loopback=1 143 ;; 144 c) 145 nt_cleanup_only=1 146 ;; 147 f) 148 nt_ulp_full=1 149 ;; 150 l) 151 nt_tcp_lso=1 152 ;; 153 n) 154 nt_cleanup=0 155 ;; 156 p) 157 nt_ulp_partial=1 158 ;; 159 r) 160 nt_rx_ip_cksum=1 161 ;; 162 u) 163 nt_udp=1 164 ;; 165 v) 166 DEBUG=1 167 ;; 168 esac 169done 170 171shift $((OPTIND - 1)) 172 173if ((nt_ulp_partial == 1)) && ((nt_ulp_full == 1)); then 174 fail "both partial and full checksum enabled" 175fi 176 177if (( $# != 3 )); then 178 usage 179 fail "wrong number of arguments" 180fi 181 182nt_client=$1 183nt_router=$2 184nt_server=$3 185 186if [[ "$nt_client" == "$nt_router" || "$nt_router" == "$nt_server" || 187 "$nt_client" == "$nt_server" ]]; then 188 fail "all zones must be unique" 189fi 190 191dbg "client zone: $nt_client" 192dbg "router zone: $nt_router" 193dbg "server zone: $nt_server" 194 195BAIL=1 196zone_exists $nt_client || fail "zone $nt_client not found" 197zone_exists $nt_router || fail "zone $nt_router not found" 198zone_exists $nt_server || fail "zone $nt_server not found" 199 200zone_running $nt_client 201zone_running $nt_router 202zone_running $nt_server 203 204if ! zlogin $nt_client ls /usr/bin/socat > /dev/null; then 205 fail "zone $nt_client missing socat" 206fi 207 208if ! zlogin $nt_server ls /usr/bin/socat > /dev/null; then 209 fail "zone $nt_client missing socat" 210fi 211 212if ((nt_loopback == 0)); then 213 nt_nics[0]=ipft_client_nic0 214 nt_nics[1]=ipft_router_nic0 215 nt_nics[2]=ipft_router_nic1 216 nt_nics[3]=ipft_server_nic0 217else 218 nt_nics[0]=ipft_nic0 219 nt_nics[1]=ipft_nic1 220fi 221 222# 223# Make a best effort to cleanup artifacts from a previous run. 224# 225if ((nt_cleanup_only == 1)); then 226 dbg "performing cleanup only" 227 BAIL=0 228 cleanup 229 BAIL=1 230 exit 0 231fi 232 233if ! mkdir $nt_tdir; then 234 fail "failed to mkdir $nt_tdir in GZ" 235fi 236dbg "created dir $nt_tdir in GZ" 237if ! zlogin $nt_client mkdir $nt_tdir; then 238 fail "failed to mkdir $nt_tdir in $nt_client" 239fi 240dbg "created dir $nt_tdir in $nt_client" 241if ! zlogin $nt_server mkdir $nt_tdir; then 242 fail "failed to mkdir $nt_tdir in $nt_server" 243fi 244dbg "created dir $nt_tdir in $nt_server" 245 246trap cleanup ERR 247 248for nt_name in ${nt_nics[@]}; do 249 create_simnet $nt_name 250done 251 252if ((nt_loopback == 0)); then 253 link_simnets ${nt_nics[0]} ${nt_nics[1]} 254 link_simnets ${nt_nics[2]} ${nt_nics[3]} 255else 256 link_simnets ${nt_nics[0]} ${nt_nics[1]} 257fi 258 259for nt_name in ${nt_nics[@]}; do 260 if ((nt_ulp_partial == 1)); then 261 set_linkprop $nt_name _tx_ulp_cksum partial 262 fi 263 264 if ((nt_ulp_full == 1)); then 265 set_linkprop $nt_name _tx_ulp_cksum fullv4 266 fi 267 268 if ((nt_ulp_full == 1)) || ((nt_ulp_partial == 1)); then 269 set_linkprop $nt_name _tx_ipv4_cksum on 270 fi 271 272 if ((nt_tcp_lso == 1)); then 273 set_linkprop $nt_name _lso on 274 fi 275 276 if ((nt_rx_ip_cksum == 1)); then 277 set_linkprop $nt_name _rx_ipv4_cksum on 278 fi 279done 280 281if ((nt_loopback == 0)); then 282 create_vnic ipft_client0 ipft_client_nic0 0 $nt_client 283 create_vnic ipft_client_r0 ipft_router_nic0 0 $nt_router 284 create_vnic ipft_server_r0 ipft_router_nic1 5 $nt_router 285 create_vnic ipft_server0 ipft_server_nic0 5 $nt_server 286else 287 create_vnic ipft_client0 ipft_nic0 0 $nt_client 288 create_vnic ipft_client_r0 ipft_nic1 0 $nt_router 289 create_vnic ipft_server_r0 ipft_nic1 5 $nt_router 290 create_vnic ipft_server0 ipft_nic1 5 $nt_server 291fi 292 293ip_fwd_enable $nt_router 294 295create_addr $nt_client ipft_client0 $nt_client_ip/24 296create_addr $nt_router ipft_client_r0 $nt_client_router_ip/24 297create_addr $nt_router ipft_server_r0 $nt_server_router_ip/24 298create_addr $nt_server ipft_server0 $nt_server_ip/24 299 300add_route $nt_client $nt_server_ip $nt_server_subnet $nt_client_router_ip 301add_route $nt_server $nt_client_ip $nt_client_subnet $nt_server_router_ip 302 303create_addr6 $nt_client ipft_client0 $nt_client_ip6 304create_addr6 $nt_router ipft_client_r0 $nt_client_router_ip6 305create_addr6 $nt_router ipft_server_r0 $nt_server_router_ip6 306create_addr6 $nt_server ipft_server0 $nt_server_ip6 307 308add_route6 $nt_client $nt_server_ip6 $nt_server_subnet6 $nt_client_router_ip6 309add_route6 $nt_server $nt_client_ip6 $nt_client_subnet6 $nt_server_router_ip6 310 311dd if=/dev/urandom of=$nt_dfile bs=1024 count=1024 > /dev/null 2>&1 312if (($? != 0)); then 313 fail "failed to create data file: $nt_dfile" 314else 315 dbg "created data file: $nt_dfile" 316fi 317 318digest -a sha1 $nt_dfile > $nt_efile 319 320# ================================================================ 321# client -> server 322# ================================================================ 323ping $nt_client $nt_client_ip $nt_server_ip 324ping $nt_client $nt_client_ip6 $nt_server_ip6 325 326start_server $nt_server TCP4 $nt_server_ip $nt_port $nt_ofile 327nt_listener_ppid=$! 328 329# Give the server time to start. 330sleep 1 331 332dbg "sending 1M $nt_client ($nt_client_ip) -> $nt_server ($nt_server_ip)" 333zlogin $nt_client /usr/bin/socat -b 8192 STDIN \ 334 TCP4:$nt_server_ip:$nt_port,connect-timeout=5 < $nt_dfile 335 336if (($? != 0)); then 337 pkill -TERM -P $nt_listener_ppid 338 fail "failed to run socat client" 339else 340 dbg "sent 1M $nt_client ($nt_client_ip) -> $nt_server ($nt_server_ip)" 341fi 342 343# 344# The client may have exited but make sure to give the server time to 345# exit and finish computing the SHA1. 346# 347dbg "waiting for listener $nt_listener_ppid" 348wait_for_pid $nt_listener_ppid 5 349dbg "listener $nt_listener_ppid exited" 350 351digest -a sha1 /zones/$nt_server/root/$nt_ofile > $nt_rfile 352 353if ! diff $nt_efile $nt_rfile; then 354 fail "SHA1 comparison failed" 355else 356 dbg "SHA1 comparison passed" 357fi 358 359start_server $nt_server TCP6 $nt_server_ip6 $nt_port6 $nt_rfile 360listener_ppid=$! 361 362# Give the server time to start. 363sleep 1 364 365zlogin $nt_client /usr/bin/socat -b 8192 STDIN \ 366 TCP6:[${nt_server_ip6}]:$nt_port6,connect-timeout=5 < $nt_dfile 367 368if (($? != 0)); then 369 pkill -TERM -P $nt_listener_ppid 370 fail "failed to run socat client IPv6" 371else 372 dbg "sent 1M $nt_client ($nt_client_ip6)" \ 373 "-> $nt_server ($nt_server_ip6) IPv6" 374fi 375 376# 377# The client may have exited but make sure to give the server time to 378# exit and finish computing the SHA1. 379# 380dbg "waiting for listener $nt_listener_ppid" 381wait_for_pid $nt_listener_ppid 5 382dbg "listener $nt_listener_ppid exited" 383 384digest -a sha1 /zones/$nt_server/root/$nt_ofile > $nt_rfile 385 386if ! diff $nt_efile $nt_rfile; then 387 fail "SHA1 comparison failed" 388else 389 dbg "SHA1 comparison passed" 390fi 391 392if ((nt_udp == 1)); then 393 ping_udp $nt_client $nt_client_ip $nt_server_ip 256 3 394 ping_udp $nt_client $nt_client_ip6 $nt_server_ip6 256 3 395 396 # 397 # Test IP fragmentation by sending a larger-than-MTU datagram. 398 # You can verify fragmentation is happening by dtracing the 399 # various "Frag" and "Reasm" mibs. 400 # 401 dbg "test IP fragmentation $nt_client_ip -> $nt_server_ip" 402 ping_udp $nt_client $nt_client_ip $nt_server_ip $((1024 * 16)) 3 403 404 dbg "test IPv6 fragmentation $nt_client_ip6 -> $nt_server_ip6" 405 ping_udp $nt_client $nt_client_ip6 $nt_server_ip6 $((1024 * 16)) 3 406fi 407 408# ================================================================ 409# server -> client 410# ================================================================ 411ping $nt_server $nt_server_ip $nt_client_ip 412ping $nt_server $nt_server_ip6 $nt_client_ip6 413 414start_server $nt_client TCP4 $nt_client_ip $nt_port $nt_ofile 415nt_listener_ppid=$! 416 417# Give the listener time to start. 418sleep 1 419 420zlogin $nt_server /usr/bin/socat -b 8192 STDIN \ 421 TCP4:$nt_client_ip:$nt_port,bind=$nt_server_ip,connect-timeout=5 \ 422 < $nt_dfile 423 424if (($? != 0)); then 425 pkill -TERM -P $nt_listener_ppid 426 fail "failed to run socat client" 427else 428 dbg "sent 1M $nt_server ($nt_server_ip) -> $nt_client ($nt_client_ip)" 429fi 430 431# 432# The client may have exited but make sure to give the server time to 433# exit and finish computing the SHA1. 434# 435dbg "waiting for listener $nt_listener_ppid" 436wait_for_pid $nt_listener_ppid 5 437dbg "listener $nt_listener_ppid exited" 438 439digest -a sha1 /zones/$nt_client/root/$nt_ofile > $nt_rfile 440 441if ! diff $nt_efile $nt_rfile; then 442 fail "SHA1 comparison failed" 443else 444 dbg "SHA1 comparison passed" 445fi 446 447start_server $nt_client TCP6 $nt_client_ip6 $nt_port6 $nt_ofile 448nt_listener_ppid=$! 449 450# Give the listener time to start. 451sleep 1 452 453zlogin $nt_server /usr/bin/socat -b 8192 STDIN \ 454 TCP6:[$nt_client_ip6]:$nt_port6,connect-timeout=5 < $nt_dfile 455 456if (($? != 0)); then 457 pkill -TERM -P $nt_listener_ppid 458 fail "failed to run socat client IPv6" 459else 460 dbg "sent 1M $nt_server ($nt_server_ip6) -> $nt_client ($nt_client_ip6)" 461fi 462 463# 464# The client may have exited but make sure to give the server time to 465# exit and finish computing the SHA1. 466# 467dbg "waiting for listener $nt_listener_ppid" 468wait_for_pid $nt_listener_ppid 5 469dbg "server $nt_listener_ppid exited" 470 471digest -a sha1 /zones/$nt_client/root/$nt_ofile > $nt_rfile 472 473if ! diff $nt_efile $nt_rfile; then 474 fail "SHA1 comparison failed" 475else 476 dbg "SHA1 comparison passed" 477fi 478 479if ((nt_udp == 1)); then 480 ping_udp $nt_server $nt_server_ip $nt_client_ip 256 3 481 ping_udp $nt_server $nt_server_ip6 $nt_client_ip6 256 3 482 483 # 484 # Test IP fragmentation by sending a larger-than-MTU datagram. 485 # You can verify fragmentation is happening by dtracing the 486 # various "Frag" and "Reasm" mibs. 487 # 488 dbg "test IP fragmentation $nt_server_ip -> $nt_client_ip" 489 ping_udp $nt_server $nt_server_ip $nt_client_ip $((1024 * 16)) 3 490 491 dbg "test IPv6 fragmentation $nt_server_ip6 -> $nt_client_ip6" 492 ping_udp $nt_server $nt_server_ip6 $nt_client_ip6 $((1024 * 16)) 3 493fi 494 495cleanup 496echo "PASS [$nt_tname]" 497