1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Run traceroute/traceroute6 tests 5# 6 7source lib.sh 8VERBOSE=0 9PAUSE_ON_FAIL=no 10 11################################################################################ 12# 13run_cmd() 14{ 15 local ns 16 local cmd 17 local out 18 local rc 19 20 ns="$1" 21 shift 22 cmd="$*" 23 24 if [ "$VERBOSE" = "1" ]; then 25 printf " COMMAND: $cmd\n" 26 fi 27 28 out=$(eval ip netns exec ${ns} ${cmd} 2>&1) 29 rc=$? 30 if [ "$VERBOSE" = "1" -a -n "$out" ]; then 31 echo " $out" 32 fi 33 34 [ "$VERBOSE" = "1" ] && echo 35 36 return $rc 37} 38 39__check_traceroute_version() 40{ 41 local cmd=$1; shift 42 local req_ver=$1; shift 43 local ver 44 45 req_ver=$(echo "$req_ver" | sed 's/\.//g') 46 ver=$($cmd -V 2>&1 | grep -Eo '[0-9]+.[0-9]+.[0-9]+' | sed 's/\.//g') 47 if [[ $ver -lt $req_ver ]]; then 48 return 1 49 else 50 return 0 51 fi 52} 53 54check_traceroute6_version() 55{ 56 local req_ver=$1; shift 57 58 __check_traceroute_version traceroute6 "$req_ver" 59} 60 61check_traceroute_version() 62{ 63 local req_ver=$1; shift 64 65 __check_traceroute_version traceroute "$req_ver" 66} 67 68################################################################################ 69# create namespaces and interconnects 70 71create_ns() 72{ 73 local ns=$1 74 local addr=$2 75 local addr6=$3 76 77 [ -z "${addr}" ] && addr="-" 78 [ -z "${addr6}" ] && addr6="-" 79 80 if [ "${addr}" != "-" ]; then 81 ip netns exec ${ns} ip addr add dev lo ${addr} 82 fi 83 if [ "${addr6}" != "-" ]; then 84 ip netns exec ${ns} ip -6 addr add dev lo ${addr6} 85 fi 86 87 ip netns exec ${ns} ip ro add unreachable default metric 8192 88 ip netns exec ${ns} ip -6 ro add unreachable default metric 8192 89 90 ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1 91 ip netns exec ${ns} sysctl -qw net.ipv4.icmp_ratelimit=0 92 ip netns exec ${ns} sysctl -qw net.ipv6.icmp.ratelimit=0 93 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1 94 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1 95 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1 96 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0 97} 98 99# create veth pair to connect namespaces and apply addresses. 100connect_ns() 101{ 102 local ns1=$1 103 local ns1_dev=$2 104 local ns1_addr=$3 105 local ns1_addr6=$4 106 local ns2=$5 107 local ns2_dev=$6 108 local ns2_addr=$7 109 local ns2_addr6=$8 110 111 ip netns exec ${ns1} ip li add ${ns1_dev} type veth peer name tmp 112 ip netns exec ${ns1} ip li set ${ns1_dev} up 113 ip netns exec ${ns1} ip li set tmp netns ${ns2} name ${ns2_dev} 114 ip netns exec ${ns2} ip li set ${ns2_dev} up 115 116 if [ "${ns1_addr}" != "-" ]; then 117 ip netns exec ${ns1} ip addr add dev ${ns1_dev} ${ns1_addr} 118 fi 119 120 if [ "${ns2_addr}" != "-" ]; then 121 ip netns exec ${ns2} ip addr add dev ${ns2_dev} ${ns2_addr} 122 fi 123 124 if [ "${ns1_addr6}" != "-" ]; then 125 ip netns exec ${ns1} ip addr add dev ${ns1_dev} ${ns1_addr6} 126 fi 127 128 if [ "${ns2_addr6}" != "-" ]; then 129 ip netns exec ${ns2} ip addr add dev ${ns2_dev} ${ns2_addr6} 130 fi 131} 132 133################################################################################ 134# traceroute6 test 135# 136# Verify that in this scenario 137# 138# ------------------------ N2 139# | | 140# ------ ------ N3 ---- 141# | R1 | | R2 |------|H2| 142# ------ ------ ---- 143# | | 144# ------------------------ N1 145# | 146# ---- 147# |H1| 148# ---- 149# 150# where H1's default route goes through R1 and R1's default route goes 151# through R2 over N2, traceroute6 from H1 to H2 reports R2's address 152# on N2 and not N1. 153# 154# Addresses are assigned as follows: 155# 156# N1: 2000:101::/64 157# N2: 2000:102::/64 158# N3: 2000:103::/64 159# 160# R1's host part of address: 1 161# R2's host part of address: 2 162# H1's host part of address: 3 163# H2's host part of address: 4 164# 165# For example: 166# the IPv6 address of R1's interface on N2 is 2000:102::1/64 167 168cleanup_traceroute6() 169{ 170 cleanup_ns $h1 $h2 $r1 $r2 171} 172 173setup_traceroute6() 174{ 175 brdev=br0 176 177 # start clean 178 cleanup_traceroute6 179 180 set -e 181 setup_ns h1 h2 r1 r2 182 create_ns $h1 183 create_ns $h2 184 create_ns $r1 185 create_ns $r2 186 187 # Setup N3 188 connect_ns $r2 eth3 - 2000:103::2/64 $h2 eth3 - 2000:103::4/64 189 ip netns exec $h2 ip route add default via 2000:103::2 190 191 # Setup N2 192 connect_ns $r1 eth2 - 2000:102::1/64 $r2 eth2 - 2000:102::2/64 193 ip netns exec $r1 ip route add default via 2000:102::2 194 195 # Setup N1. host-1 and router-2 connect to a bridge in router-1. 196 ip netns exec $r1 ip link add name ${brdev} type bridge 197 ip netns exec $r1 ip link set ${brdev} up 198 ip netns exec $r1 ip addr add 2000:101::1/64 dev ${brdev} 199 200 connect_ns $h1 eth0 - 2000:101::3/64 $r1 eth0 - - 201 ip netns exec $r1 ip link set dev eth0 master ${brdev} 202 ip netns exec $h1 ip route add default via 2000:101::1 203 204 connect_ns $r2 eth1 - 2000:101::2/64 $r1 eth1 - - 205 ip netns exec $r1 ip link set dev eth1 master ${brdev} 206 207 # Prime the network 208 ip netns exec $h1 ping6 -c5 2000:103::4 >/dev/null 2>&1 209 210 set +e 211} 212 213run_traceroute6() 214{ 215 setup_traceroute6 216 217 RET=0 218 219 # traceroute6 host-2 from host-1 (expects 2000:102::2) 220 run_cmd $h1 "traceroute6 2000:103::4 | grep -q 2000:102::2" 221 check_err $? "traceroute6 did not return 2000:102::2" 222 log_test "IPv6 traceroute" 223 224 cleanup_traceroute6 225} 226 227################################################################################ 228# traceroute6 with VRF test 229# 230# Verify that in this scenario 231# 232# ------------------------ N2 233# | | 234# ------ ------ N3 ---- 235# | R1 | | R2 |------|H2| 236# ------ ------ ---- 237# | | 238# ------------------------ N1 239# | 240# ---- 241# |H1| 242# ---- 243# 244# Where H1's default route goes through R1 and R1's default route goes through 245# R2 over N2, traceroute6 from H1 to H2 reports R2's address on N2 and not N1. 246# The interfaces connecting R2 to the different subnets are membmer in a VRF 247# and the intention is to check that traceroute6 does not report the VRF's 248# address. 249# 250# Addresses are assigned as follows: 251# 252# N1: 2000:101::/64 253# N2: 2000:102::/64 254# N3: 2000:103::/64 255# 256# R1's host part of address: 1 257# R2's host part of address: 2 258# H1's host part of address: 3 259# H2's host part of address: 4 260# 261# For example: 262# the IPv6 address of R1's interface on N2 is 2000:102::1/64 263 264cleanup_traceroute6_vrf() 265{ 266 cleanup_all_ns 267} 268 269setup_traceroute6_vrf() 270{ 271 # Start clean 272 cleanup_traceroute6_vrf 273 274 setup_ns h1 h2 r1 r2 275 create_ns "$h1" 276 create_ns "$h2" 277 create_ns "$r1" 278 create_ns "$r2" 279 280 ip -n "$r2" link add name vrf100 up type vrf table 100 281 ip -n "$r2" addr add 2001:db8:100::1/64 dev vrf100 282 283 # Setup N3 284 connect_ns "$r2" eth3 - 2000:103::2/64 "$h2" eth3 - 2000:103::4/64 285 286 ip -n "$r2" link set dev eth3 master vrf100 287 288 ip -n "$h2" route add default via 2000:103::2 289 290 # Setup N2 291 connect_ns "$r1" eth2 - 2000:102::1/64 "$r2" eth2 - 2000:102::2/64 292 293 ip -n "$r1" route add default via 2000:102::2 294 295 ip -n "$r2" link set dev eth2 master vrf100 296 297 # Setup N1. host-1 and router-2 connect to a bridge in router-1. 298 ip -n "$r1" link add name br100 up type bridge 299 ip -n "$r1" addr add 2000:101::1/64 dev br100 300 301 connect_ns "$h1" eth0 - 2000:101::3/64 "$r1" eth0 - - 302 303 ip -n "$h1" route add default via 2000:101::1 304 305 ip -n "$r1" link set dev eth0 master br100 306 307 connect_ns "$r2" eth1 - 2000:101::2/64 "$r1" eth1 - - 308 309 ip -n "$r2" link set dev eth1 master vrf100 310 311 ip -n "$r1" link set dev eth1 master br100 312 313 # Prime the network 314 ip netns exec "$h1" ping6 -c5 2000:103::4 >/dev/null 2>&1 315} 316 317run_traceroute6_vrf() 318{ 319 setup_traceroute6_vrf 320 321 RET=0 322 323 # traceroute6 host-2 from host-1 (expects 2000:102::2) 324 run_cmd "$h1" "traceroute6 2000:103::4 | grep 2000:102::2" 325 check_err $? "traceroute6 did not return 2000:102::2" 326 log_test "IPv6 traceroute with VRF" 327 328 cleanup_traceroute6_vrf 329} 330 331################################################################################ 332# traceroute6 with ICMP extensions test 333# 334# Verify that in this scenario 335# 336# ---- ---- ---- 337# |H1|--------------------------|R1|--------------------------|H2| 338# ---- N1 ---- N2 ---- 339# 340# ICMP extensions are correctly reported. The loopback interfaces on all the 341# nodes are assigned global addresses and the interfaces connecting the nodes 342# are assigned IPv6 link-local addresses. 343 344cleanup_traceroute6_ext() 345{ 346 cleanup_all_ns 347} 348 349setup_traceroute6_ext() 350{ 351 # Start clean 352 cleanup_traceroute6_ext 353 354 setup_ns h1 r1 h2 355 create_ns "$h1" 356 create_ns "$r1" 357 create_ns "$h2" 358 359 # Setup N1 360 connect_ns "$h1" eth1 - fe80::1/64 "$r1" eth1 - fe80::2/64 361 # Setup N2 362 connect_ns "$r1" eth2 - fe80::3/64 "$h2" eth2 - fe80::4/64 363 364 # Setup H1 365 ip -n "$h1" address add 2001:db8:1::1/128 dev lo 366 ip -n "$h1" route add ::/0 nexthop via fe80::2 dev eth1 367 368 # Setup R1 369 ip -n "$r1" address add 2001:db8:1::2/128 dev lo 370 ip -n "$r1" route add 2001:db8:1::1/128 nexthop via fe80::1 dev eth1 371 ip -n "$r1" route add 2001:db8:1::3/128 nexthop via fe80::4 dev eth2 372 373 # Setup H2 374 ip -n "$h2" address add 2001:db8:1::3/128 dev lo 375 ip -n "$h2" route add ::/0 nexthop via fe80::3 dev eth2 376 377 # Prime the network 378 ip netns exec "$h1" ping6 -c5 2001:db8:1::3 >/dev/null 2>&1 379} 380 381traceroute6_ext_iio_iif_test() 382{ 383 local r1_ifindex h2_ifindex 384 local pkt_len=$1; shift 385 386 # Test that incoming interface info is not appended by default. 387 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep INC" 388 check_fail $? "Incoming interface info appended by default when should not" 389 390 # Test that the extension is appended when enabled. 391 run_cmd "$r1" "bash -c \"echo 0x01 > /proc/sys/net/ipv6/icmp/errors_extension_mask\"" 392 check_err $? "Failed to enable incoming interface info extension on R1" 393 394 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep INC" 395 check_err $? "Incoming interface info not appended after enable" 396 397 # Test that the extension is not appended when disabled. 398 run_cmd "$r1" "bash -c \"echo 0x00 > /proc/sys/net/ipv6/icmp/errors_extension_mask\"" 399 check_err $? "Failed to disable incoming interface info extension on R1" 400 401 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep INC" 402 check_fail $? "Incoming interface info appended after disable" 403 404 # Test that the extension is sent correctly from both R1 and H2. 405 run_cmd "$r1" "sysctl -w net.ipv6.icmp.errors_extension_mask=0x01" 406 r1_ifindex=$(ip -n "$r1" -j link show dev eth1 | jq '.[]["ifindex"]') 407 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep '<INC:$r1_ifindex,\"eth1\",mtu=1500>'" 408 check_err $? "Wrong incoming interface info reported from R1" 409 410 run_cmd "$h2" "sysctl -w net.ipv6.icmp.errors_extension_mask=0x01" 411 h2_ifindex=$(ip -n "$h2" -j link show dev eth2 | jq '.[]["ifindex"]') 412 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep '<INC:$h2_ifindex,\"eth2\",mtu=1500>'" 413 check_err $? "Wrong incoming interface info reported from H2" 414 415 # Add a global address on the incoming interface of R1 and check that 416 # it is reported. 417 run_cmd "$r1" "ip address add 2001:db8:100::1/64 dev eth1 nodad" 418 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep '<INC:$r1_ifindex,2001:db8:100::1,\"eth1\",mtu=1500>'" 419 check_err $? "Wrong incoming interface info reported from R1 after address addition" 420 run_cmd "$r1" "ip address del 2001:db8:100::1/64 dev eth1" 421 422 # Change name and MTU and make sure the result is still correct. 423 run_cmd "$r1" "ip link set dev eth1 name eth1tag mtu 1501" 424 run_cmd "$h1" "traceroute6 -e 2001:db8:1::3 $pkt_len | grep '<INC:$r1_ifindex,\"eth1tag\",mtu=1501>'" 425 check_err $? "Wrong incoming interface info reported from R1 after name and MTU change" 426 run_cmd "$r1" "ip link set dev eth1tag name eth1 mtu 1500" 427 428 run_cmd "$r1" "sysctl -w net.ipv6.icmp.errors_extension_mask=0x00" 429 run_cmd "$h2" "sysctl -w net.ipv6.icmp.errors_extension_mask=0x00" 430} 431 432run_traceroute6_ext() 433{ 434 # Need at least version 2.1.5 for RFC 5837 support. 435 if ! check_traceroute6_version 2.1.5; then 436 log_test_skip "traceroute6 too old, missing ICMP extensions support" 437 return 438 fi 439 440 setup_traceroute6_ext 441 442 RET=0 443 444 ## General ICMP extensions tests 445 446 # Test that ICMP extensions are disabled by default. 447 run_cmd "$h1" "sysctl net.ipv6.icmp.errors_extension_mask | grep \"= 0$\"" 448 check_err $? "ICMP extensions are not disabled by default" 449 450 # Test that unsupported values are rejected. Do not use "sysctl" as 451 # older versions do not return an error code upon failure. 452 run_cmd "$h1" "bash -c \"echo 0x80 > /proc/sys/net/ipv6/icmp/errors_extension_mask\"" 453 check_fail $? "Unsupported sysctl value was not rejected" 454 455 ## Extension-specific tests 456 457 # Incoming interface info test. Test with various packet sizes, 458 # including the default one. 459 traceroute6_ext_iio_iif_test 460 traceroute6_ext_iio_iif_test 127 461 traceroute6_ext_iio_iif_test 128 462 traceroute6_ext_iio_iif_test 129 463 464 log_test "IPv6 traceroute with ICMP extensions" 465 466 cleanup_traceroute6_ext 467} 468 469################################################################################ 470# traceroute test 471# 472# Verify that traceroute from H1 to H2 shows 1.0.3.1 and 1.0.1.1 when 473# traceroute uses 1.0.3.3 and 1.0.1.3 as the source IP, respectively. 474# 475# 1.0.3.3/24 1.0.3.1/24 476# ---- 1.0.1.3/24 1.0.1.1/24 ---- 1.0.2.1/24 1.0.2.4/24 ---- 477# |H1|--------------------------|R1|--------------------------|H2| 478# ---- N1 ---- N2 ---- 479# 480# where net.ipv4.icmp_errors_use_inbound_ifaddr is set on R1 and 1.0.3.1/24 and 481# 1.0.1.1/24 are R1's primary addresses on N1. The kernel is expected to prefer 482# a source address that is on the same subnet as the destination IP of the ICMP 483# error message. 484 485cleanup_traceroute() 486{ 487 cleanup_ns $h1 $h2 $router 488} 489 490setup_traceroute() 491{ 492 # start clean 493 cleanup_traceroute 494 495 set -e 496 setup_ns h1 h2 router 497 create_ns $h1 498 create_ns $h2 499 create_ns $router 500 501 connect_ns $h1 eth0 1.0.1.3/24 - \ 502 $router eth1 1.0.3.1/24 - 503 ip -n "$h1" addr add 1.0.3.3/24 dev eth0 504 ip netns exec $h1 ip route add default via 1.0.1.1 505 506 ip netns exec $router ip addr add 1.0.1.1/24 dev eth1 507 ip netns exec $router sysctl -qw \ 508 net.ipv4.icmp_errors_use_inbound_ifaddr=1 509 510 connect_ns $h2 eth0 1.0.2.4/24 - \ 511 $router eth2 1.0.2.1/24 - 512 ip netns exec $h2 ip route add default via 1.0.2.1 513 514 # Prime the network 515 ip netns exec $h1 ping -c5 1.0.2.4 >/dev/null 2>&1 516 517 set +e 518} 519 520run_traceroute() 521{ 522 setup_traceroute 523 524 RET=0 525 526 # traceroute host-2 from host-1. Expect a source IP that is on the same 527 # subnet as destination IP of the ICMP error message. 528 run_cmd "$h1" "traceroute -s 1.0.1.3 1.0.2.4 | grep -q 1.0.1.1" 529 check_err $? "traceroute did not return 1.0.1.1" 530 run_cmd "$h1" "traceroute -s 1.0.3.3 1.0.2.4 | grep -q 1.0.3.1" 531 check_err $? "traceroute did not return 1.0.3.1" 532 log_test "IPv4 traceroute" 533 534 cleanup_traceroute 535} 536 537################################################################################ 538# traceroute with VRF test 539# 540# Verify that traceroute from H1 to H2 shows 1.0.3.1 and 1.0.1.1 when 541# traceroute uses 1.0.3.3 and 1.0.1.3 as the source IP, respectively. The 542# intention is to check that the kernel does not choose an IP assigned to the 543# VRF device, but rather an address from the VRF port (eth1) that received the 544# packet that generates the ICMP error message. 545# 546# 1.0.4.1/24 (vrf100) 547# 1.0.3.3/24 1.0.3.1/24 548# ---- 1.0.1.3/24 1.0.1.1/24 ---- 1.0.2.1/24 1.0.2.4/24 ---- 549# |H1|--------------------------|R1|--------------------------|H2| 550# ---- N1 ---- N2 ---- 551 552cleanup_traceroute_vrf() 553{ 554 cleanup_all_ns 555} 556 557setup_traceroute_vrf() 558{ 559 # Start clean 560 cleanup_traceroute_vrf 561 562 setup_ns h1 h2 router 563 create_ns "$h1" 564 create_ns "$h2" 565 create_ns "$router" 566 567 ip -n "$router" link add name vrf100 up type vrf table 100 568 ip -n "$router" addr add 1.0.4.1/24 dev vrf100 569 570 connect_ns "$h1" eth0 1.0.1.3/24 - \ 571 "$router" eth1 1.0.1.1/24 - 572 573 ip -n "$h1" addr add 1.0.3.3/24 dev eth0 574 ip -n "$h1" route add default via 1.0.1.1 575 576 ip -n "$router" link set dev eth1 master vrf100 577 ip -n "$router" addr add 1.0.3.1/24 dev eth1 578 ip netns exec "$router" sysctl -qw \ 579 net.ipv4.icmp_errors_use_inbound_ifaddr=1 580 581 connect_ns "$h2" eth0 1.0.2.4/24 - \ 582 "$router" eth2 1.0.2.1/24 - 583 584 ip -n "$h2" route add default via 1.0.2.1 585 586 ip -n "$router" link set dev eth2 master vrf100 587 588 # Prime the network 589 ip netns exec "$h1" ping -c5 1.0.2.4 >/dev/null 2>&1 590} 591 592run_traceroute_vrf() 593{ 594 setup_traceroute_vrf 595 596 RET=0 597 598 # traceroute host-2 from host-1. Expect a source IP that is on the same 599 # subnet as destination IP of the ICMP error message. 600 run_cmd "$h1" "traceroute -s 1.0.1.3 1.0.2.4 | grep 1.0.1.1" 601 check_err $? "traceroute did not return 1.0.1.1" 602 run_cmd "$h1" "traceroute -s 1.0.3.3 1.0.2.4 | grep 1.0.3.1" 603 check_err $? "traceroute did not return 1.0.3.1" 604 log_test "IPv4 traceroute with VRF" 605 606 cleanup_traceroute_vrf 607} 608 609################################################################################ 610# traceroute with ICMP extensions test 611# 612# Verify that in this scenario 613# 614# ---- ---- ---- 615# |H1|--------------------------|R1|--------------------------|H2| 616# ---- N1 ---- N2 ---- 617# 618# ICMP extensions are correctly reported. The loopback interfaces on all the 619# nodes are assigned global addresses and the interfaces connecting the nodes 620# are assigned IPv6 link-local addresses. 621 622cleanup_traceroute_ext() 623{ 624 cleanup_all_ns 625} 626 627setup_traceroute_ext() 628{ 629 # Start clean 630 cleanup_traceroute_ext 631 632 setup_ns h1 r1 h2 633 create_ns "$h1" 634 create_ns "$r1" 635 create_ns "$h2" 636 637 # Setup N1 638 connect_ns "$h1" eth1 - fe80::1/64 "$r1" eth1 - fe80::2/64 639 # Setup N2 640 connect_ns "$r1" eth2 - fe80::3/64 "$h2" eth2 - fe80::4/64 641 642 # Setup H1 643 ip -n "$h1" address add 192.0.2.1/32 dev lo 644 ip -n "$h1" route add 0.0.0.0/0 nexthop via inet6 fe80::2 dev eth1 645 646 # Setup R1 647 ip -n "$r1" address add 192.0.2.2/32 dev lo 648 ip -n "$r1" route add 192.0.2.1/32 nexthop via inet6 fe80::1 dev eth1 649 ip -n "$r1" route add 192.0.2.3/32 nexthop via inet6 fe80::4 dev eth2 650 651 # Setup H2 652 ip -n "$h2" address add 192.0.2.3/32 dev lo 653 ip -n "$h2" route add 0.0.0.0/0 nexthop via inet6 fe80::3 dev eth2 654 655 # Prime the network 656 ip netns exec "$h1" ping -c5 192.0.2.3 >/dev/null 2>&1 657} 658 659traceroute_ext_iio_iif_test() 660{ 661 local r1_ifindex h2_ifindex 662 local pkt_len=$1; shift 663 664 # Test that incoming interface info is not appended by default. 665 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep INC" 666 check_fail $? "Incoming interface info appended by default when should not" 667 668 # Test that the extension is appended when enabled. 669 run_cmd "$r1" "bash -c \"echo 0x01 > /proc/sys/net/ipv4/icmp_errors_extension_mask\"" 670 check_err $? "Failed to enable incoming interface info extension on R1" 671 672 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep INC" 673 check_err $? "Incoming interface info not appended after enable" 674 675 # Test that the extension is not appended when disabled. 676 run_cmd "$r1" "bash -c \"echo 0x00 > /proc/sys/net/ipv4/icmp_errors_extension_mask\"" 677 check_err $? "Failed to disable incoming interface info extension on R1" 678 679 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep INC" 680 check_fail $? "Incoming interface info appended after disable" 681 682 # Test that the extension is sent correctly from both R1 and H2. 683 run_cmd "$r1" "sysctl -w net.ipv4.icmp_errors_extension_mask=0x01" 684 r1_ifindex=$(ip -n "$r1" -j link show dev eth1 | jq '.[]["ifindex"]') 685 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep '<INC:$r1_ifindex,\"eth1\",mtu=1500>'" 686 check_err $? "Wrong incoming interface info reported from R1" 687 688 run_cmd "$h2" "sysctl -w net.ipv4.icmp_errors_extension_mask=0x01" 689 h2_ifindex=$(ip -n "$h2" -j link show dev eth2 | jq '.[]["ifindex"]') 690 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep '<INC:$h2_ifindex,\"eth2\",mtu=1500>'" 691 check_err $? "Wrong incoming interface info reported from H2" 692 693 # Add a global address on the incoming interface of R1 and check that 694 # it is reported. 695 run_cmd "$r1" "ip address add 198.51.100.1/24 dev eth1" 696 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep '<INC:$r1_ifindex,198.51.100.1,\"eth1\",mtu=1500>'" 697 check_err $? "Wrong incoming interface info reported from R1 after address addition" 698 run_cmd "$r1" "ip address del 198.51.100.1/24 dev eth1" 699 700 # Change name and MTU and make sure the result is still correct. 701 # Re-add the route towards H1 since it was deleted when we removed the 702 # last IPv4 address from eth1 on R1. 703 run_cmd "$r1" "ip route add 192.0.2.1/32 nexthop via inet6 fe80::1 dev eth1" 704 run_cmd "$r1" "ip link set dev eth1 name eth1tag mtu 1501" 705 run_cmd "$h1" "traceroute -e 192.0.2.3 $pkt_len | grep '<INC:$r1_ifindex,\"eth1tag\",mtu=1501>'" 706 check_err $? "Wrong incoming interface info reported from R1 after name and MTU change" 707 run_cmd "$r1" "ip link set dev eth1tag name eth1 mtu 1500" 708 709 run_cmd "$r1" "sysctl -w net.ipv4.icmp_errors_extension_mask=0x00" 710 run_cmd "$h2" "sysctl -w net.ipv4.icmp_errors_extension_mask=0x00" 711} 712 713run_traceroute_ext() 714{ 715 # Need at least version 2.1.5 for RFC 5837 support. 716 if ! check_traceroute_version 2.1.5; then 717 log_test_skip "traceroute too old, missing ICMP extensions support" 718 return 719 fi 720 721 setup_traceroute_ext 722 723 RET=0 724 725 ## General ICMP extensions tests 726 727 # Test that ICMP extensions are disabled by default. 728 run_cmd "$h1" "sysctl net.ipv4.icmp_errors_extension_mask | grep \"= 0$\"" 729 check_err $? "ICMP extensions are not disabled by default" 730 731 # Test that unsupported values are rejected. Do not use "sysctl" as 732 # older versions do not return an error code upon failure. 733 run_cmd "$h1" "bash -c \"echo 0x80 > /proc/sys/net/ipv4/icmp_errors_extension_mask\"" 734 check_fail $? "Unsupported sysctl value was not rejected" 735 736 ## Extension-specific tests 737 738 # Incoming interface info test. Test with various packet sizes, 739 # including the default one. 740 traceroute_ext_iio_iif_test 741 traceroute_ext_iio_iif_test 127 742 traceroute_ext_iio_iif_test 128 743 traceroute_ext_iio_iif_test 129 744 745 log_test "IPv4 traceroute with ICMP extensions" 746 747 cleanup_traceroute_ext 748} 749 750################################################################################ 751# Run tests 752 753run_tests() 754{ 755 run_traceroute6 756 run_traceroute6_vrf 757 run_traceroute6_ext 758 run_traceroute 759 run_traceroute_vrf 760 run_traceroute_ext 761} 762 763################################################################################ 764# main 765 766while getopts :pv o 767do 768 case $o in 769 p) PAUSE_ON_FAIL=yes;; 770 v) VERBOSE=$(($VERBOSE + 1));; 771 *) exit 1;; 772 esac 773done 774 775require_command traceroute6 776require_command traceroute 777require_command jq 778 779run_tests 780 781exit "${EXIT_STATUS}" 782