1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0 3# 4# Check that route PMTU values match expectations, and that initial device MTU 5# values are assigned correctly 6# 7# Tests currently implemented: 8# 9# - pmtu_ipv4 10# Set up two namespaces, A and B, with two paths between them over routers 11# R1 and R2 (also implemented with namespaces), with different MTUs: 12# 13# segment a_r1 segment b_r1 a_r1: 2000 14# .--------------R1--------------. a_r2: 1500 15# A B a_r3: 2000 16# '--------------R2--------------' a_r4: 1400 17# segment a_r2 segment b_r2 18# 19# Check that PMTU exceptions with the correct PMTU are created. Then 20# decrease and increase the MTU of the local link for one of the paths, 21# A to R1, checking that route exception PMTU changes accordingly over 22# this path. Also check that locked exceptions are created when an ICMP 23# message advertising a PMTU smaller than net.ipv4.route.min_pmtu is 24# received 25# 26# - pmtu_ipv6 27# Same as pmtu_ipv4, except for locked PMTU tests, using IPv6 28# 29# - pmtu_ipv4_vxlan4_exception 30# Set up the same network topology as pmtu_ipv4, create a VXLAN tunnel 31# over IPv4 between A and B, routed via R1. On the link between R1 and B, 32# set a MTU lower than the VXLAN MTU and the MTU on the link between A and 33# R1. Send IPv4 packets, exceeding the MTU between R1 and B, over VXLAN 34# from A to B and check that the PMTU exception is created with the right 35# value on A 36# 37# - pmtu_ipv6_vxlan4_exception 38# Same as pmtu_ipv4_vxlan4_exception, but send IPv6 packets from A to B 39# 40# - pmtu_ipv4_vxlan6_exception 41# Same as pmtu_ipv4_vxlan4_exception, but use IPv6 transport from A to B 42# 43# - pmtu_ipv6_vxlan6_exception 44# Same as pmtu_ipv4_vxlan6_exception, but send IPv6 packets from A to B 45# 46# - pmtu_ipv4_geneve4_exception 47# Same as pmtu_ipv4_vxlan4_exception, but using a GENEVE tunnel instead of 48# VXLAN 49# 50# - pmtu_ipv6_geneve4_exception 51# Same as pmtu_ipv6_vxlan4_exception, but using a GENEVE tunnel instead of 52# VXLAN 53# 54# - pmtu_ipv4_geneve6_exception 55# Same as pmtu_ipv4_vxlan6_exception, but using a GENEVE tunnel instead of 56# VXLAN 57# 58# - pmtu_ipv6_geneve6_exception 59# Same as pmtu_ipv6_vxlan6_exception, but using a GENEVE tunnel instead of 60# VXLAN 61# 62# - pmtu_ipv{4,6}_fou{4,6}_exception 63# Same as pmtu_ipv4_vxlan4, but using a direct IPv4/IPv6 encapsulation 64# (FoU) over IPv4/IPv6, instead of VXLAN 65# 66# - pmtu_ipv{4,6}_fou{4,6}_exception 67# Same as pmtu_ipv4_vxlan4, but using a generic UDP IPv4/IPv6 68# encapsulation (GUE) over IPv4/IPv6, instead of VXLAN 69# 70# - pmtu_vti4_exception 71# Set up vti tunnel on top of veth, with xfrm states and policies, in two 72# namespaces with matching endpoints. Check that route exception is not 73# created if link layer MTU is not exceeded, then exceed it and check that 74# exception is created with the expected PMTU. The approach described 75# below for IPv6 doesn't apply here, because, on IPv4, administrative MTU 76# changes alone won't affect PMTU 77# 78# - pmtu_vti6_exception 79# Set up vti6 tunnel on top of veth, with xfrm states and policies, in two 80# namespaces with matching endpoints. Check that route exception is 81# created by exceeding link layer MTU with ping to other endpoint. Then 82# decrease and increase MTU of tunnel, checking that route exception PMTU 83# changes accordingly 84# 85# - pmtu_vti4_default_mtu 86# Set up vti4 tunnel on top of veth, in two namespaces with matching 87# endpoints. Check that MTU assigned to vti interface is the MTU of the 88# lower layer (veth) minus additional lower layer headers (zero, for veth) 89# minus IPv4 header length 90# 91# - pmtu_vti6_default_mtu 92# Same as above, for IPv6 93# 94# - pmtu_vti4_link_add_mtu 95# Set up vti4 interface passing MTU value at link creation, check MTU is 96# configured, and that link is not created with invalid MTU values 97# 98# - pmtu_vti6_link_add_mtu 99# Same as above, for IPv6 100# 101# - pmtu_vti6_link_change_mtu 102# Set up two dummy interfaces with different MTUs, create a vti6 tunnel 103# and check that configured MTU is used on link creation and changes, and 104# that MTU is properly calculated instead when MTU is not configured from 105# userspace 106# 107# - cleanup_ipv4_exception 108# Similar to pmtu_ipv4_vxlan4_exception, but explicitly generate PMTU 109# exceptions on multiple CPUs and check that the veth device tear-down 110# happens in a timely manner 111# 112# - cleanup_ipv6_exception 113# Same as above, but use IPv6 transport from A to B 114 115 116# Kselftest framework requirement - SKIP code is 4. 117ksft_skip=4 118 119# Some systems don't have a ping6 binary anymore 120which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping) 121 122tests=" 123 pmtu_ipv4_exception ipv4: PMTU exceptions 124 pmtu_ipv6_exception ipv6: PMTU exceptions 125 pmtu_ipv4_vxlan4_exception IPv4 over vxlan4: PMTU exceptions 126 pmtu_ipv6_vxlan4_exception IPv6 over vxlan4: PMTU exceptions 127 pmtu_ipv4_vxlan6_exception IPv4 over vxlan6: PMTU exceptions 128 pmtu_ipv6_vxlan6_exception IPv6 over vxlan6: PMTU exceptions 129 pmtu_ipv4_geneve4_exception IPv4 over geneve4: PMTU exceptions 130 pmtu_ipv6_geneve4_exception IPv6 over geneve4: PMTU exceptions 131 pmtu_ipv4_geneve6_exception IPv4 over geneve6: PMTU exceptions 132 pmtu_ipv6_geneve6_exception IPv6 over geneve6: PMTU exceptions 133 pmtu_ipv4_fou4_exception IPv4 over fou4: PMTU exceptions 134 pmtu_ipv6_fou4_exception IPv6 over fou4: PMTU exceptions 135 pmtu_ipv4_fou6_exception IPv4 over fou6: PMTU exceptions 136 pmtu_ipv6_fou6_exception IPv6 over fou6: PMTU exceptions 137 pmtu_ipv4_gue4_exception IPv4 over gue4: PMTU exceptions 138 pmtu_ipv6_gue4_exception IPv6 over gue4: PMTU exceptions 139 pmtu_ipv4_gue6_exception IPv4 over gue6: PMTU exceptions 140 pmtu_ipv6_gue6_exception IPv6 over gue6: PMTU exceptions 141 pmtu_vti6_exception vti6: PMTU exceptions 142 pmtu_vti4_exception vti4: PMTU exceptions 143 pmtu_vti4_default_mtu vti4: default MTU assignment 144 pmtu_vti6_default_mtu vti6: default MTU assignment 145 pmtu_vti4_link_add_mtu vti4: MTU setting on link creation 146 pmtu_vti6_link_add_mtu vti6: MTU setting on link creation 147 pmtu_vti6_link_change_mtu vti6: MTU changes on link changes 148 cleanup_ipv4_exception ipv4: cleanup of cached exceptions 149 cleanup_ipv6_exception ipv6: cleanup of cached exceptions" 150 151NS_A="ns-$(mktemp -u XXXXXX)" 152NS_B="ns-$(mktemp -u XXXXXX)" 153NS_R1="ns-$(mktemp -u XXXXXX)" 154NS_R2="ns-$(mktemp -u XXXXXX)" 155ns_a="ip netns exec ${NS_A}" 156ns_b="ip netns exec ${NS_B}" 157ns_r1="ip netns exec ${NS_R1}" 158ns_r2="ip netns exec ${NS_R2}" 159 160# Addressing and routing for tests with routers: four network segments, with 161# index SEGMENT between 1 and 4, a common prefix (PREFIX4 or PREFIX6) and an 162# identifier ID, which is 1 for hosts (A and B), 2 for routers (R1 and R2). 163# Addresses are: 164# - IPv4: PREFIX4.SEGMENT.ID (/24) 165# - IPv6: PREFIX6:SEGMENT::ID (/64) 166prefix4="10.0" 167prefix6="fc00" 168a_r1=1 169a_r2=2 170b_r1=3 171b_r2=4 172# ns peer segment 173routing_addrs=" 174 A R1 ${a_r1} 175 A R2 ${a_r2} 176 B R1 ${b_r1} 177 B R2 ${b_r2} 178" 179# Traffic from A to B goes through R1 by default, and through R2, if destined to 180# B's address on the b_r2 segment. 181# Traffic from B to A goes through R1. 182# ns destination gateway 183routes=" 184 A default ${prefix4}.${a_r1}.2 185 A ${prefix4}.${b_r2}.1 ${prefix4}.${a_r2}.2 186 B default ${prefix4}.${b_r1}.2 187 188 A default ${prefix6}:${a_r1}::2 189 A ${prefix6}:${b_r2}::1 ${prefix6}:${a_r2}::2 190 B default ${prefix6}:${b_r1}::2 191" 192 193veth4_a_addr="192.168.1.1" 194veth4_b_addr="192.168.1.2" 195veth4_mask="24" 196veth6_a_addr="fd00:1::a" 197veth6_b_addr="fd00:1::b" 198veth6_mask="64" 199 200tunnel4_a_addr="192.168.2.1" 201tunnel4_b_addr="192.168.2.2" 202tunnel4_mask="24" 203tunnel6_a_addr="fd00:2::a" 204tunnel6_b_addr="fd00:2::b" 205tunnel6_mask="64" 206 207dummy6_0_addr="fc00:1000::0" 208dummy6_1_addr="fc00:1001::0" 209dummy6_mask="64" 210 211cleanup_done=1 212err_buf= 213tcpdump_pids= 214 215err() { 216 err_buf="${err_buf}${1} 217" 218} 219 220err_flush() { 221 echo -n "${err_buf}" 222 err_buf= 223} 224 225# Find the auto-generated name for this namespace 226nsname() { 227 eval echo \$NS_$1 228} 229 230setup_fou_or_gue() { 231 outer="${1}" 232 inner="${2}" 233 encap="${3}" 234 235 if [ "${outer}" = "4" ]; then 236 modprobe fou || return 2 237 a_addr="${prefix4}.${a_r1}.1" 238 b_addr="${prefix4}.${b_r1}.1" 239 if [ "${inner}" = "4" ]; then 240 type="ipip" 241 ipproto="4" 242 else 243 type="sit" 244 ipproto="41" 245 fi 246 else 247 modprobe fou6 || return 2 248 a_addr="${prefix6}:${a_r1}::1" 249 b_addr="${prefix6}:${b_r1}::1" 250 if [ "${inner}" = "4" ]; then 251 type="ip6tnl" 252 mode="mode ipip6" 253 ipproto="4 -6" 254 else 255 type="ip6tnl" 256 mode="mode ip6ip6" 257 ipproto="41 -6" 258 fi 259 fi 260 261 ${ns_a} ip fou add port 5555 ipproto ${ipproto} || return 2 262 ${ns_a} ip link add ${encap}_a type ${type} ${mode} local ${a_addr} remote ${b_addr} encap ${encap} encap-sport auto encap-dport 5556 || return 2 263 264 ${ns_b} ip fou add port 5556 ipproto ${ipproto} 265 ${ns_b} ip link add ${encap}_b type ${type} ${mode} local ${b_addr} remote ${a_addr} encap ${encap} encap-sport auto encap-dport 5555 266 267 if [ "${inner}" = "4" ]; then 268 ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ${encap}_a 269 ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${encap}_b 270 else 271 ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ${encap}_a 272 ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${encap}_b 273 fi 274 275 ${ns_a} ip link set ${encap}_a up 276 ${ns_b} ip link set ${encap}_b up 277} 278 279setup_fou44() { 280 setup_fou_or_gue 4 4 fou 281} 282 283setup_fou46() { 284 setup_fou_or_gue 4 6 fou 285} 286 287setup_fou64() { 288 setup_fou_or_gue 6 4 fou 289} 290 291setup_fou66() { 292 setup_fou_or_gue 6 6 fou 293} 294 295setup_gue44() { 296 setup_fou_or_gue 4 4 gue 297} 298 299setup_gue46() { 300 setup_fou_or_gue 4 6 gue 301} 302 303setup_gue64() { 304 setup_fou_or_gue 6 4 gue 305} 306 307setup_gue66() { 308 setup_fou_or_gue 6 6 gue 309} 310 311setup_namespaces() { 312 for n in ${NS_A} ${NS_B} ${NS_R1} ${NS_R2}; do 313 ip netns add ${n} || return 1 314 315 # Disable DAD, so that we don't have to wait to use the 316 # configured IPv6 addresses 317 ip netns exec ${n} sysctl -q net/ipv6/conf/default/accept_dad=0 318 done 319} 320 321setup_veth() { 322 ${ns_a} ip link add veth_a type veth peer name veth_b || return 1 323 ${ns_a} ip link set veth_b netns ${NS_B} 324 325 ${ns_a} ip addr add ${veth4_a_addr}/${veth4_mask} dev veth_a 326 ${ns_b} ip addr add ${veth4_b_addr}/${veth4_mask} dev veth_b 327 328 ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a 329 ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b 330 331 ${ns_a} ip link set veth_a up 332 ${ns_b} ip link set veth_b up 333} 334 335setup_vti() { 336 proto=${1} 337 veth_a_addr="${2}" 338 veth_b_addr="${3}" 339 vti_a_addr="${4}" 340 vti_b_addr="${5}" 341 vti_mask=${6} 342 343 [ ${proto} -eq 6 ] && vti_type="vti6" || vti_type="vti" 344 345 ${ns_a} ip link add vti${proto}_a type ${vti_type} local ${veth_a_addr} remote ${veth_b_addr} key 10 || return 1 346 ${ns_b} ip link add vti${proto}_b type ${vti_type} local ${veth_b_addr} remote ${veth_a_addr} key 10 347 348 ${ns_a} ip addr add ${vti_a_addr}/${vti_mask} dev vti${proto}_a 349 ${ns_b} ip addr add ${vti_b_addr}/${vti_mask} dev vti${proto}_b 350 351 ${ns_a} ip link set vti${proto}_a up 352 ${ns_b} ip link set vti${proto}_b up 353} 354 355setup_vti4() { 356 setup_vti 4 ${veth4_a_addr} ${veth4_b_addr} ${tunnel4_a_addr} ${tunnel4_b_addr} ${tunnel4_mask} 357} 358 359setup_vti6() { 360 setup_vti 6 ${veth6_a_addr} ${veth6_b_addr} ${tunnel6_a_addr} ${tunnel6_b_addr} ${tunnel6_mask} 361} 362 363setup_vxlan_or_geneve() { 364 type="${1}" 365 a_addr="${2}" 366 b_addr="${3}" 367 opts="${4}" 368 369 if [ "${type}" = "vxlan" ]; then 370 opts="${opts} ttl 64 dstport 4789" 371 opts_a="local ${a_addr}" 372 opts_b="local ${b_addr}" 373 else 374 opts_a="" 375 opts_b="" 376 fi 377 378 ${ns_a} ip link add ${type}_a type ${type} id 1 ${opts_a} remote ${b_addr} ${opts} || return 1 379 ${ns_b} ip link add ${type}_b type ${type} id 1 ${opts_b} remote ${a_addr} ${opts} 380 381 ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ${type}_a 382 ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${type}_b 383 384 ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ${type}_a 385 ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${type}_b 386 387 ${ns_a} ip link set ${type}_a up 388 ${ns_b} ip link set ${type}_b up 389} 390 391setup_geneve4() { 392 setup_vxlan_or_geneve geneve ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "df set" 393} 394 395setup_vxlan4() { 396 setup_vxlan_or_geneve vxlan ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "df set" 397} 398 399setup_geneve6() { 400 setup_vxlan_or_geneve geneve ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 401} 402 403setup_vxlan6() { 404 setup_vxlan_or_geneve vxlan ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 405} 406 407setup_xfrm() { 408 proto=${1} 409 veth_a_addr="${2}" 410 veth_b_addr="${3}" 411 412 ${ns_a} ip -${proto} xfrm state add src ${veth_a_addr} dst ${veth_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel || return 1 413 ${ns_a} ip -${proto} xfrm state add src ${veth_b_addr} dst ${veth_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel 414 ${ns_a} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel 415 ${ns_a} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel 416 417 ${ns_b} ip -${proto} xfrm state add src ${veth_a_addr} dst ${veth_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel 418 ${ns_b} ip -${proto} xfrm state add src ${veth_b_addr} dst ${veth_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel 419 ${ns_b} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel 420 ${ns_b} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel 421} 422 423setup_xfrm4() { 424 setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} 425} 426 427setup_xfrm6() { 428 setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} 429} 430 431setup_routing() { 432 for i in ${NS_R1} ${NS_R2}; do 433 ip netns exec ${i} sysctl -q net/ipv4/ip_forward=1 434 ip netns exec ${i} sysctl -q net/ipv6/conf/all/forwarding=1 435 done 436 437 for i in ${routing_addrs}; do 438 [ "${ns}" = "" ] && ns="${i}" && continue 439 [ "${peer}" = "" ] && peer="${i}" && continue 440 [ "${segment}" = "" ] && segment="${i}" 441 442 ns_name="$(nsname ${ns})" 443 peer_name="$(nsname ${peer})" 444 if="veth_${ns}-${peer}" 445 ifpeer="veth_${peer}-${ns}" 446 447 # Create veth links 448 ip link add ${if} up netns ${ns_name} type veth peer name ${ifpeer} netns ${peer_name} || return 1 449 ip -n ${peer_name} link set dev ${ifpeer} up 450 451 # Add addresses 452 ip -n ${ns_name} addr add ${prefix4}.${segment}.1/24 dev ${if} 453 ip -n ${ns_name} addr add ${prefix6}:${segment}::1/64 dev ${if} 454 455 ip -n ${peer_name} addr add ${prefix4}.${segment}.2/24 dev ${ifpeer} 456 ip -n ${peer_name} addr add ${prefix6}:${segment}::2/64 dev ${ifpeer} 457 458 ns=""; peer=""; segment="" 459 done 460 461 for i in ${routes}; do 462 [ "${ns}" = "" ] && ns="${i}" && continue 463 [ "${addr}" = "" ] && addr="${i}" && continue 464 [ "${gw}" = "" ] && gw="${i}" 465 466 ns_name="$(nsname ${ns})" 467 468 ip -n ${ns_name} route add ${addr} via ${gw} 469 470 ns=""; addr=""; gw="" 471 done 472} 473 474setup() { 475 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip 476 477 cleanup_done=0 478 for arg do 479 eval setup_${arg} || { echo " ${arg} not supported"; return 1; } 480 done 481} 482 483trace() { 484 [ $tracing -eq 0 ] && return 485 486 for arg do 487 [ "${ns_cmd}" = "" ] && ns_cmd="${arg}" && continue 488 ${ns_cmd} tcpdump -s 0 -i "${arg}" -w "${name}_${arg}.pcap" 2> /dev/null & 489 tcpdump_pids="${tcpdump_pids} $!" 490 ns_cmd= 491 done 492 sleep 1 493} 494 495cleanup() { 496 for pid in ${tcpdump_pids}; do 497 kill ${pid} 498 done 499 tcpdump_pids= 500 501 [ ${cleanup_done} -eq 1 ] && return 502 for n in ${NS_A} ${NS_B} ${NS_R1} ${NS_R2}; do 503 ip netns del ${n} 2> /dev/null 504 done 505 cleanup_done=1 506} 507 508mtu() { 509 ns_cmd="${1}" 510 dev="${2}" 511 mtu="${3}" 512 513 ${ns_cmd} ip link set dev ${dev} mtu ${mtu} 514} 515 516mtu_parse() { 517 input="${1}" 518 519 next=0 520 for i in ${input}; do 521 [ ${next} -eq 1 -a "${i}" = "lock" ] && next=2 && continue 522 [ ${next} -eq 1 ] && echo "${i}" && return 523 [ ${next} -eq 2 ] && echo "lock ${i}" && return 524 [ "${i}" = "mtu" ] && next=1 525 done 526} 527 528link_get() { 529 ns_cmd="${1}" 530 name="${2}" 531 532 ${ns_cmd} ip link show dev "${name}" 533} 534 535link_get_mtu() { 536 ns_cmd="${1}" 537 name="${2}" 538 539 mtu_parse "$(link_get "${ns_cmd}" ${name})" 540} 541 542route_get_dst_exception() { 543 ns_cmd="${1}" 544 dst="${2}" 545 546 ${ns_cmd} ip route get "${dst}" 547} 548 549route_get_dst_pmtu_from_exception() { 550 ns_cmd="${1}" 551 dst="${2}" 552 553 mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})" 554} 555 556check_pmtu_value() { 557 expected="${1}" 558 value="${2}" 559 event="${3}" 560 561 [ "${expected}" = "any" ] && [ -n "${value}" ] && return 0 562 [ "${value}" = "${expected}" ] && return 0 563 [ -z "${value}" ] && err " PMTU exception wasn't created after ${event}" && return 1 564 [ -z "${expected}" ] && err " PMTU exception shouldn't exist after ${event}" && return 1 565 err " found PMTU exception with incorrect MTU ${value}, expected ${expected}, after ${event}" 566 return 1 567} 568 569test_pmtu_ipvX() { 570 family=${1} 571 572 setup namespaces routing || return 2 573 trace "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \ 574 "${ns_r1}" veth_R1-B "${ns_b}" veth_B-R1 \ 575 "${ns_a}" veth_A-R2 "${ns_r2}" veth_R2-A \ 576 "${ns_r2}" veth_R2-B "${ns_b}" veth_B-R2 577 578 if [ ${family} -eq 4 ]; then 579 ping=ping 580 dst1="${prefix4}.${b_r1}.1" 581 dst2="${prefix4}.${b_r2}.1" 582 else 583 ping=${ping6} 584 dst1="${prefix6}:${b_r1}::1" 585 dst2="${prefix6}:${b_r2}::1" 586 fi 587 588 # Set up initial MTU values 589 mtu "${ns_a}" veth_A-R1 2000 590 mtu "${ns_r1}" veth_R1-A 2000 591 mtu "${ns_r1}" veth_R1-B 1400 592 mtu "${ns_b}" veth_B-R1 1400 593 594 mtu "${ns_a}" veth_A-R2 2000 595 mtu "${ns_r2}" veth_R2-A 2000 596 mtu "${ns_r2}" veth_R2-B 1500 597 mtu "${ns_b}" veth_B-R2 1500 598 599 # Create route exceptions 600 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst1} > /dev/null 601 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst2} > /dev/null 602 603 # Check that exceptions have been created with the correct PMTU 604 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})" 605 check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1 606 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 607 check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1 608 609 # Decrease local MTU below PMTU, check for PMTU decrease in route exception 610 mtu "${ns_a}" veth_A-R1 1300 611 mtu "${ns_r1}" veth_R1-A 1300 612 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})" 613 check_pmtu_value "1300" "${pmtu_1}" "decreasing local MTU" || return 1 614 # Second exception shouldn't be modified 615 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 616 check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1 617 618 # Increase MTU, check for PMTU increase in route exception 619 mtu "${ns_a}" veth_A-R1 1700 620 mtu "${ns_r1}" veth_R1-A 1700 621 pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})" 622 check_pmtu_value "1700" "${pmtu_1}" "increasing local MTU" || return 1 623 # Second exception shouldn't be modified 624 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 625 check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1 626 627 # Skip PMTU locking tests for IPv6 628 [ $family -eq 6 ] && return 0 629 630 # Decrease remote MTU on path via R2, get new exception 631 mtu "${ns_r2}" veth_R2-B 400 632 mtu "${ns_b}" veth_B-R2 400 633 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1400 ${dst2} > /dev/null 634 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 635 check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1 636 637 # Decrease local MTU below PMTU 638 mtu "${ns_a}" veth_A-R2 500 639 mtu "${ns_r2}" veth_R2-A 500 640 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 641 check_pmtu_value "500" "${pmtu_2}" "decreasing local MTU" || return 1 642 643 # Increase local MTU 644 mtu "${ns_a}" veth_A-R2 1500 645 mtu "${ns_r2}" veth_R2-A 1500 646 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 647 check_pmtu_value "1500" "${pmtu_2}" "increasing local MTU" || return 1 648 649 # Get new exception 650 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1400 ${dst2} > /dev/null 651 pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})" 652 check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1 653} 654 655test_pmtu_ipv4_exception() { 656 test_pmtu_ipvX 4 657} 658 659test_pmtu_ipv6_exception() { 660 test_pmtu_ipvX 6 661} 662 663test_pmtu_ipvX_over_vxlanY_or_geneveY_exception() { 664 type=${1} 665 family=${2} 666 outer_family=${3} 667 ll_mtu=4000 668 669 if [ ${outer_family} -eq 4 ]; then 670 setup namespaces routing ${type}4 || return 2 671 # IPv4 header UDP header VXLAN/GENEVE header Ethernet header 672 exp_mtu=$((${ll_mtu} - 20 - 8 - 8 - 14)) 673 else 674 setup namespaces routing ${type}6 || return 2 675 # IPv6 header UDP header VXLAN/GENEVE header Ethernet header 676 exp_mtu=$((${ll_mtu} - 40 - 8 - 8 - 14)) 677 fi 678 679 trace "${ns_a}" ${type}_a "${ns_b}" ${type}_b \ 680 "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \ 681 "${ns_b}" veth_B-R1 "${ns_r1}" veth_R1-B 682 683 if [ ${family} -eq 4 ]; then 684 ping=ping 685 dst=${tunnel4_b_addr} 686 else 687 ping=${ping6} 688 dst=${tunnel6_b_addr} 689 fi 690 691 # Create route exception by exceeding link layer MTU 692 mtu "${ns_a}" veth_A-R1 $((${ll_mtu} + 1000)) 693 mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000)) 694 mtu "${ns_b}" veth_B-R1 ${ll_mtu} 695 mtu "${ns_r1}" veth_R1-B ${ll_mtu} 696 697 mtu "${ns_a}" ${type}_a $((${ll_mtu} + 1000)) 698 mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000)) 699 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${dst} > /dev/null 700 701 # Check that exception was created 702 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})" 703 check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on ${type} interface" 704} 705 706test_pmtu_ipv4_vxlan4_exception() { 707 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan 4 4 708} 709 710test_pmtu_ipv6_vxlan4_exception() { 711 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan 6 4 712} 713 714test_pmtu_ipv4_geneve4_exception() { 715 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 4 4 716} 717 718test_pmtu_ipv6_geneve4_exception() { 719 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 6 4 720} 721 722test_pmtu_ipv4_vxlan6_exception() { 723 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan 4 6 724} 725 726test_pmtu_ipv6_vxlan6_exception() { 727 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan 6 6 728} 729 730test_pmtu_ipv4_geneve6_exception() { 731 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 4 6 732} 733 734test_pmtu_ipv6_geneve6_exception() { 735 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 6 6 736} 737 738test_pmtu_ipvX_over_fouY_or_gueY() { 739 inner_family=${1} 740 outer_family=${2} 741 encap=${3} 742 ll_mtu=4000 743 744 setup namespaces routing ${encap}${outer_family}${inner_family} || return 2 745 trace "${ns_a}" ${encap}_a "${ns_b}" ${encap}_b \ 746 "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \ 747 "${ns_b}" veth_B-R1 "${ns_r1}" veth_R1-B 748 749 if [ ${inner_family} -eq 4 ]; then 750 ping=ping 751 dst=${tunnel4_b_addr} 752 else 753 ping=${ping6} 754 dst=${tunnel6_b_addr} 755 fi 756 757 if [ "${encap}" = "gue" ]; then 758 encap_overhead=4 759 else 760 encap_overhead=0 761 fi 762 763 if [ ${outer_family} -eq 4 ]; then 764 # IPv4 header UDP header 765 exp_mtu=$((${ll_mtu} - 20 - 8 - ${encap_overhead})) 766 else 767 # IPv6 header Option 4 UDP header 768 exp_mtu=$((${ll_mtu} - 40 - 8 - 8 - ${encap_overhead})) 769 fi 770 771 # Create route exception by exceeding link layer MTU 772 mtu "${ns_a}" veth_A-R1 $((${ll_mtu} + 1000)) 773 mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000)) 774 mtu "${ns_b}" veth_B-R1 ${ll_mtu} 775 mtu "${ns_r1}" veth_R1-B ${ll_mtu} 776 777 mtu "${ns_a}" ${encap}_a $((${ll_mtu} + 1000)) 778 mtu "${ns_b}" ${encap}_b $((${ll_mtu} + 1000)) 779 ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${dst} > /dev/null 780 781 # Check that exception was created 782 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})" 783 check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on ${encap} interface" 784} 785 786test_pmtu_ipv4_fou4_exception() { 787 test_pmtu_ipvX_over_fouY_or_gueY 4 4 fou 788} 789 790test_pmtu_ipv6_fou4_exception() { 791 test_pmtu_ipvX_over_fouY_or_gueY 6 4 fou 792} 793 794test_pmtu_ipv4_fou6_exception() { 795 test_pmtu_ipvX_over_fouY_or_gueY 4 6 fou 796} 797 798test_pmtu_ipv6_fou6_exception() { 799 test_pmtu_ipvX_over_fouY_or_gueY 6 6 fou 800} 801 802test_pmtu_ipv4_gue4_exception() { 803 test_pmtu_ipvX_over_fouY_or_gueY 4 4 gue 804} 805 806test_pmtu_ipv6_gue4_exception() { 807 test_pmtu_ipvX_over_fouY_or_gueY 6 4 gue 808} 809 810test_pmtu_ipv4_gue6_exception() { 811 test_pmtu_ipvX_over_fouY_or_gueY 4 6 gue 812} 813 814test_pmtu_ipv6_gue6_exception() { 815 test_pmtu_ipvX_over_fouY_or_gueY 6 6 gue 816} 817 818test_pmtu_vti4_exception() { 819 setup namespaces veth vti4 xfrm4 || return 2 820 trace "${ns_a}" veth_a "${ns_b}" veth_b \ 821 "${ns_a}" vti4_a "${ns_b}" vti4_b 822 823 veth_mtu=1500 824 vti_mtu=$((veth_mtu - 20)) 825 826 # SPI SN IV ICV pad length next header 827 esp_payload_rfc4106=$((vti_mtu - 4 - 4 - 8 - 16 - 1 - 1)) 828 ping_payload=$((esp_payload_rfc4106 - 28)) 829 830 mtu "${ns_a}" veth_a ${veth_mtu} 831 mtu "${ns_b}" veth_b ${veth_mtu} 832 mtu "${ns_a}" vti4_a ${vti_mtu} 833 mtu "${ns_b}" vti4_b ${vti_mtu} 834 835 # Send DF packet without exceeding link layer MTU, check that no 836 # exception is created 837 ${ns_a} ping -q -M want -i 0.1 -w 1 -s ${ping_payload} ${tunnel4_b_addr} > /dev/null 838 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})" 839 check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1 840 841 # Now exceed link layer MTU by one byte, check that exception is created 842 # with the right PMTU value 843 ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((ping_payload + 1)) ${tunnel4_b_addr} > /dev/null 844 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})" 845 check_pmtu_value "${esp_payload_rfc4106}" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106 + 1)))" 846} 847 848test_pmtu_vti6_exception() { 849 setup namespaces veth vti6 xfrm6 || return 2 850 trace "${ns_a}" veth_a "${ns_b}" veth_b \ 851 "${ns_a}" vti6_a "${ns_b}" vti6_b 852 fail=0 853 854 # Create route exception by exceeding link layer MTU 855 mtu "${ns_a}" veth_a 4000 856 mtu "${ns_b}" veth_b 4000 857 mtu "${ns_a}" vti6_a 5000 858 mtu "${ns_b}" vti6_b 5000 859 ${ns_a} ${ping6} -q -i 0.1 -w 1 -s 60000 ${tunnel6_b_addr} > /dev/null 860 861 # Check that exception was created 862 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})" 863 check_pmtu_value any "${pmtu}" "creating tunnel exceeding link layer MTU" || return 1 864 865 # Decrease tunnel MTU, check for PMTU decrease in route exception 866 mtu "${ns_a}" vti6_a 3000 867 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})" 868 check_pmtu_value "3000" "${pmtu}" "decreasing tunnel MTU" || fail=1 869 870 # Increase tunnel MTU, check for PMTU increase in route exception 871 mtu "${ns_a}" vti6_a 9000 872 pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})" 873 check_pmtu_value "9000" "${pmtu}" "increasing tunnel MTU" || fail=1 874 875 return ${fail} 876} 877 878test_pmtu_vti4_default_mtu() { 879 setup namespaces veth vti4 || return 2 880 881 # Check that MTU of vti device is MTU of veth minus IPv4 header length 882 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)" 883 vti4_mtu="$(link_get_mtu "${ns_a}" vti4_a)" 884 if [ $((veth_mtu - vti4_mtu)) -ne 20 ]; then 885 err " vti MTU ${vti4_mtu} is not veth MTU ${veth_mtu} minus IPv4 header length" 886 return 1 887 fi 888} 889 890test_pmtu_vti6_default_mtu() { 891 setup namespaces veth vti6 || return 2 892 893 # Check that MTU of vti device is MTU of veth minus IPv6 header length 894 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)" 895 vti6_mtu="$(link_get_mtu "${ns_a}" vti6_a)" 896 if [ $((veth_mtu - vti6_mtu)) -ne 40 ]; then 897 err " vti MTU ${vti6_mtu} is not veth MTU ${veth_mtu} minus IPv6 header length" 898 return 1 899 fi 900} 901 902test_pmtu_vti4_link_add_mtu() { 903 setup namespaces || return 2 904 905 ${ns_a} ip link add vti4_a type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10 906 [ $? -ne 0 ] && err " vti not supported" && return 2 907 ${ns_a} ip link del vti4_a 908 909 fail=0 910 911 min=68 912 max=$((65535 - 20)) 913 # Check invalid values first 914 for v in $((min - 1)) $((max + 1)); do 915 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10 2>/dev/null 916 # This can fail, or MTU can be adjusted to a proper value 917 [ $? -ne 0 ] && continue 918 mtu="$(link_get_mtu "${ns_a}" vti4_a)" 919 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then 920 err " vti tunnel created with invalid MTU ${mtu}" 921 fail=1 922 fi 923 ${ns_a} ip link del vti4_a 924 done 925 926 # Now check valid values 927 for v in ${min} 1300 ${max}; do 928 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10 929 mtu="$(link_get_mtu "${ns_a}" vti4_a)" 930 ${ns_a} ip link del vti4_a 931 if [ "${mtu}" != "${v}" ]; then 932 err " vti MTU ${mtu} doesn't match configured value ${v}" 933 fail=1 934 fi 935 done 936 937 return ${fail} 938} 939 940test_pmtu_vti6_link_add_mtu() { 941 setup namespaces || return 2 942 943 ${ns_a} ip link add vti6_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 944 [ $? -ne 0 ] && err " vti6 not supported" && return 2 945 ${ns_a} ip link del vti6_a 946 947 fail=0 948 949 min=68 # vti6 can carry IPv4 packets too 950 max=$((65535 - 40)) 951 # Check invalid values first 952 for v in $((min - 1)) $((max + 1)); do 953 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 2>/dev/null 954 # This can fail, or MTU can be adjusted to a proper value 955 [ $? -ne 0 ] && continue 956 mtu="$(link_get_mtu "${ns_a}" vti6_a)" 957 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then 958 err " vti6 tunnel created with invalid MTU ${v}" 959 fail=1 960 fi 961 ${ns_a} ip link del vti6_a 962 done 963 964 # Now check valid values 965 for v in 68 1280 1300 $((65535 - 40)); do 966 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 967 mtu="$(link_get_mtu "${ns_a}" vti6_a)" 968 ${ns_a} ip link del vti6_a 969 if [ "${mtu}" != "${v}" ]; then 970 err " vti6 MTU ${mtu} doesn't match configured value ${v}" 971 fail=1 972 fi 973 done 974 975 return ${fail} 976} 977 978test_pmtu_vti6_link_change_mtu() { 979 setup namespaces || return 2 980 981 ${ns_a} ip link add dummy0 mtu 1500 type dummy 982 [ $? -ne 0 ] && err " dummy not supported" && return 2 983 ${ns_a} ip link add dummy1 mtu 3000 type dummy 984 ${ns_a} ip link set dummy0 up 985 ${ns_a} ip link set dummy1 up 986 987 ${ns_a} ip addr add ${dummy6_0_addr}/${dummy6_mask} dev dummy0 988 ${ns_a} ip addr add ${dummy6_1_addr}/${dummy6_mask} dev dummy1 989 990 fail=0 991 992 # Create vti6 interface bound to device, passing MTU, check it 993 ${ns_a} ip link add vti6_a mtu 1300 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr} 994 mtu="$(link_get_mtu "${ns_a}" vti6_a)" 995 if [ ${mtu} -ne 1300 ]; then 996 err " vti6 MTU ${mtu} doesn't match configured value 1300" 997 fail=1 998 fi 999 1000 # Move to another device with different MTU, without passing MTU, check 1001 # MTU is adjusted 1002 ${ns_a} ip link set vti6_a type vti6 remote ${dummy6_1_addr} local ${dummy6_1_addr} 1003 mtu="$(link_get_mtu "${ns_a}" vti6_a)" 1004 if [ ${mtu} -ne $((3000 - 40)) ]; then 1005 err " vti MTU ${mtu} is not dummy MTU 3000 minus IPv6 header length" 1006 fail=1 1007 fi 1008 1009 # Move it back, passing MTU, check MTU is not overridden 1010 ${ns_a} ip link set vti6_a mtu 1280 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr} 1011 mtu="$(link_get_mtu "${ns_a}" vti6_a)" 1012 if [ ${mtu} -ne 1280 ]; then 1013 err " vti6 MTU ${mtu} doesn't match configured value 1280" 1014 fail=1 1015 fi 1016 1017 return ${fail} 1018} 1019 1020check_command() { 1021 cmd=${1} 1022 1023 if ! which ${cmd} > /dev/null 2>&1; then 1024 err " missing required command: '${cmd}'" 1025 return 1 1026 fi 1027 return 0 1028} 1029 1030test_cleanup_vxlanX_exception() { 1031 outer="${1}" 1032 encap="vxlan" 1033 ll_mtu=4000 1034 1035 check_command taskset || return 2 1036 cpu_list=$(grep -m 2 processor /proc/cpuinfo | cut -d ' ' -f 2) 1037 1038 setup namespaces routing ${encap}${outer} || return 2 1039 trace "${ns_a}" ${encap}_a "${ns_b}" ${encap}_b \ 1040 "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \ 1041 "${ns_b}" veth_B-R1 "${ns_r1}" veth_R1-B 1042 1043 # Create route exception by exceeding link layer MTU 1044 mtu "${ns_a}" veth_A-R1 $((${ll_mtu} + 1000)) 1045 mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000)) 1046 mtu "${ns_b}" veth_B-R1 ${ll_mtu} 1047 mtu "${ns_r1}" veth_R1-B ${ll_mtu} 1048 1049 mtu "${ns_a}" ${encap}_a $((${ll_mtu} + 1000)) 1050 mtu "${ns_b}" ${encap}_b $((${ll_mtu} + 1000)) 1051 1052 # Fill exception cache for multiple CPUs (2) 1053 # we can always use inner IPv4 for that 1054 for cpu in ${cpu_list}; do 1055 taskset --cpu-list ${cpu} ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${tunnel4_b_addr} > /dev/null 1056 done 1057 1058 ${ns_a} ip link del dev veth_A-R1 & 1059 iplink_pid=$! 1060 sleep 1 1061 if [ "$(cat /proc/${iplink_pid}/cmdline 2>/dev/null | tr -d '\0')" = "iplinkdeldevveth_A-R1" ]; then 1062 err " can't delete veth device in a timely manner, PMTU dst likely leaked" 1063 return 1 1064 fi 1065} 1066 1067test_cleanup_ipv6_exception() { 1068 test_cleanup_vxlanX_exception 6 1069} 1070 1071test_cleanup_ipv4_exception() { 1072 test_cleanup_vxlanX_exception 4 1073} 1074 1075usage() { 1076 echo 1077 echo "$0 [OPTIONS] [TEST]..." 1078 echo "If no TEST argument is given, all tests will be run." 1079 echo 1080 echo "Options" 1081 echo " --trace: capture traffic to TEST_INTERFACE.pcap" 1082 echo 1083 echo "Available tests${tests}" 1084 exit 1 1085} 1086 1087exitcode=0 1088desc=0 1089IFS=" 1090" 1091 1092tracing=0 1093for arg do 1094 if [ "${arg}" != "${arg#--*}" ]; then 1095 opt="${arg#--}" 1096 if [ "${opt}" = "trace" ]; then 1097 if which tcpdump > /dev/null 2>&1; then 1098 tracing=1 1099 else 1100 echo "=== tcpdump not available, tracing disabled" 1101 fi 1102 else 1103 usage 1104 fi 1105 else 1106 # Check first that all requested tests are available before 1107 # running any 1108 command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; } 1109 fi 1110done 1111 1112trap cleanup EXIT 1113 1114for t in ${tests}; do 1115 [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0 1116 1117 run_this=1 1118 for arg do 1119 [ "${arg}" != "${arg#--*}" ] && continue 1120 [ "${arg}" = "${name}" ] && run_this=1 && break 1121 run_this=0 1122 done 1123 [ $run_this -eq 0 ] && continue 1124 1125 ( 1126 unset IFS 1127 eval test_${name} 1128 ret=$? 1129 cleanup 1130 1131 if [ $ret -eq 0 ]; then 1132 printf "TEST: %-60s [ OK ]\n" "${t}" 1133 elif [ $ret -eq 1 ]; then 1134 printf "TEST: %-60s [FAIL]\n" "${t}" 1135 err_flush 1136 exit 1 1137 elif [ $ret -eq 2 ]; then 1138 printf "TEST: %-60s [SKIP]\n" "${t}" 1139 err_flush 1140 fi 1141 ) 1142 [ $? -ne 0 ] && exitcode=1 1143done 1144 1145exit ${exitcode} 1146