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