Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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}"