Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'icmp-fix-icmp-error-source-address-over-xfrm-tunnel'

Antony Antony says:

====================
icmp: Fix icmp error source address over xfrm tunnel

icmp: Fix icmp error source address over xfrm tunnel

This fix, originally sent to XFRM/IPsec, has been recommended by
Steffen Klassert to submit to the net tree, since it changes ICMP
behavior.

The patch addresses a minor issue related to the IPv4 source address
of ICMP error messages. The bug only occurs when xfrm policies are
configured. It originated from an old 2011 commit:

commit 415b3334a21a ("icmp: Fix regression in nexthop resolution during
replies.")
====================

Link: https://patch.msgid.link/cover.1772101380.git.antony.antony@secunet.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+614 -1
-1
net/ipv4/icmp.c
··· 591 591 rt2 = dst_rtable(dst2); 592 592 if (!IS_ERR(dst2)) { 593 593 dst_release(&rt->dst); 594 - memcpy(fl4, &fl4_dec, sizeof(*fl4)); 595 594 rt = rt2; 596 595 } else if (PTR_ERR(dst2) == -EPERM) { 597 596 if (rt)
+1
tools/testing/selftests/net/Makefile
··· 120 120 vrf_route_leaking.sh \ 121 121 vrf_strict_mode_test.sh \ 122 122 xfrm_policy.sh \ 123 + xfrm_state.sh \ 123 124 # end of TEST_PROGS 124 125 125 126 TEST_PROGS_EXTENDED := \
+613
tools/testing/selftests/net/xfrm_state.sh
··· 1 + #!/bin/bash -e 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # xfrm/IPsec tests. 5 + # Currently implemented: 6 + # - ICMP error source address verification (IETF RFC 4301 section 6) 7 + # - ICMP MTU exceeded handling over IPsec tunnels. 8 + # 9 + # Addresses and topology: 10 + # IPv4 prefix 10.1.c.d IPv6 prefix fc00:c::d/64 where c is the segment number 11 + # and d is the interface identifier. 12 + # IPv6 uses the same c:d as IPv4, and start with IPv6 prefix instead ipv4 prefix 13 + # 14 + # Network topology default: ns_set_v4 or ns_set_v6 15 + # 1.1 1.2 2.1 2.2 3.1 3.2 4.1 4.2 5.1 5.2 6.1 6.2 16 + # eth0 eth1 eth0 eth1 eth0 eth1 eth0 eth1 eth0 eth1 eth0 eth1 17 + # a -------- r1 -------- s1 -------- r2 -------- s2 -------- r3 -------- b 18 + # a, b = Alice and Bob hosts without IPsec. 19 + # r1, r2, r3 routers, without IPsec 20 + # s1, s2, IPsec gateways/routers that setup tunnel(s). 21 + 22 + # Network topology x: IPsec gateway that generates ICMP response - ns_set_v4x or ns_set_v6x 23 + # 1.1 1.2 2.1 2.2 3.1 3.2 4.1 4.2 5.1 5.2 24 + # eth0 eth1 eth0 eth1 eth0 eth1 eth0 eth1 eth0 eth1 25 + # a -------- r1 -------- s1 -------- r2 -------- s2 -------- b 26 + 27 + . lib.sh 28 + 29 + EXIT_ON_TEST_FAIL=no 30 + PAUSE=no 31 + VERBOSE=${VERBOSE:-0} 32 + DEBUG=0 33 + 34 + # Name Description 35 + tests=" 36 + unreachable_ipv4 IPv4 unreachable from router r3 37 + unreachable_ipv6 IPv6 unreachable from router r3 38 + unreachable_gw_ipv4 IPv4 unreachable from IPsec gateway s2 39 + unreachable_gw_ipv6 IPv6 unreachable from IPsec gateway s2 40 + mtu_ipv4_s2 IPv4 MTU exceeded from IPsec gateway s2 41 + mtu_ipv6_s2 IPv6 MTU exceeded from IPsec gateway s2 42 + mtu_ipv4_r2 IPv4 MTU exceeded from ESP router r2 43 + mtu_ipv6_r2 IPv6 MTU exceeded from ESP router r2 44 + mtu_ipv4_r3 IPv4 MTU exceeded from router r3 45 + mtu_ipv6_r3 IPv6 MTU exceeded from router r3" 46 + 47 + prefix4="10.1" 48 + prefix6="fc00" 49 + 50 + run_cmd_err() { 51 + cmd="$*" 52 + 53 + if [ "$VERBOSE" -gt 0 ]; then 54 + printf " COMMAND: %s\n" "$cmd" 55 + fi 56 + 57 + out="$($cmd 2>&1)" && rc=0 || rc=$? 58 + if [ "$VERBOSE" -gt 1 ] && [ -n "$out" ]; then 59 + echo " $out" 60 + echo 61 + fi 62 + return 0 63 + } 64 + 65 + run_cmd() { 66 + run_cmd_err "$@" || exit 1 67 + } 68 + 69 + run_test() { 70 + # If errexit is set, unset it for sub-shell and restore after test 71 + errexit=0 72 + if [[ $- =~ "e" ]]; then 73 + errexit=1 74 + set +e 75 + fi 76 + 77 + ( 78 + unset IFS 79 + 80 + # shellcheck disable=SC2030 # fail is read by trap/cleanup within this subshell 81 + fail="yes" 82 + 83 + # Since cleanup() relies on variables modified by this sub shell, 84 + # it has to run in this context. 85 + trap 'log_test_error $?; cleanup' EXIT INT TERM 86 + 87 + if [ "$VERBOSE" -gt 0 ]; then 88 + printf "\n#############################################################\n\n" 89 + fi 90 + 91 + ret=0 92 + case "${name}" in 93 + # can't use eval and test names shell check will complain about unused code 94 + unreachable_ipv4) test_unreachable_ipv4 ;; 95 + unreachable_ipv6) test_unreachable_ipv6 ;; 96 + unreachable_gw_ipv4) test_unreachable_gw_ipv4 ;; 97 + unreachable_gw_ipv6) test_unreachable_gw_ipv6 ;; 98 + mtu_ipv4_s2) test_mtu_ipv4_s2 ;; 99 + mtu_ipv6_s2) test_mtu_ipv6_s2 ;; 100 + mtu_ipv4_r2) test_mtu_ipv4_r2 ;; 101 + mtu_ipv6_r2) test_mtu_ipv6_r2 ;; 102 + mtu_ipv4_r3) test_mtu_ipv4_r3 ;; 103 + mtu_ipv6_r3) test_mtu_ipv6_r3 ;; 104 + esac 105 + ret=$? 106 + 107 + if [ $ret -eq 0 ]; then 108 + fail="no" 109 + 110 + if [ "$VERBOSE" -gt 1 ]; then 111 + show_icmp_filter 112 + fi 113 + 114 + printf "TEST: %-60s [ PASS ]\n" "${desc}" 115 + elif [ $ret -eq "$ksft_skip" ]; then 116 + fail="no" 117 + printf "TEST: %-60s [SKIP]\n" "${desc}" 118 + fi 119 + 120 + return $ret 121 + ) 122 + ret=$? 123 + 124 + [ $errexit -eq 1 ] && set -e 125 + 126 + case $ret in 127 + 0) 128 + all_skipped=false 129 + [ "$exitcode" -eq "$ksft_skip" ] && exitcode=0 130 + ;; 131 + "$ksft_skip") 132 + [ $all_skipped = true ] && exitcode=$ksft_skip 133 + ;; 134 + *) 135 + all_skipped=false 136 + exitcode=1 137 + ;; 138 + esac 139 + 140 + return 0 # don't trigger errexit (-e); actual status in exitcode 141 + } 142 + 143 + setup_namespaces() { 144 + local namespaces="" 145 + 146 + NS_A="" 147 + NS_B="" 148 + NS_R1="" 149 + NS_R2="" 150 + NS_R3="" 151 + NS_S1="" 152 + NS_S2="" 153 + 154 + for ns in ${ns_set}; do 155 + namespaces="$namespaces NS_${ns^^}" 156 + done 157 + 158 + # shellcheck disable=SC2086 # setup_ns expects unquoted list 159 + setup_ns $namespaces 160 + 161 + ns_active= #ordered list of namespaces for this test. 162 + 163 + [ -n "${NS_A}" ] && ns_a=(ip netns exec "${NS_A}") && ns_active="${ns_active} $NS_A" 164 + [ -n "${NS_R1}" ] && ns_active="${ns_active} $NS_R1" 165 + [ -n "${NS_S1}" ] && ns_s1=(ip netns exec "${NS_S1}") && ns_active="${ns_active} $NS_S1" 166 + [ -n "${NS_R2}" ] && ns_r2=(ip netns exec "${NS_R2}") && ns_active="${ns_active} $NS_R2" 167 + [ -n "${NS_S2}" ] && ns_s2=(ip netns exec "${NS_S2}") && ns_active="${ns_active} $NS_S2" 168 + [ -n "${NS_R3}" ] && ns_r3=(ip netns exec "${NS_R3}") && ns_active="${ns_active} $NS_R3" 169 + [ -n "${NS_B}" ] && ns_active="${ns_active} $NS_B" 170 + } 171 + 172 + addr_add() { 173 + local -a ns_cmd=(ip netns exec "$1") 174 + local addr="$2" 175 + local dev="$3" 176 + 177 + run_cmd "${ns_cmd[@]}" ip addr add "${addr}" dev "${dev}" 178 + run_cmd "${ns_cmd[@]}" ip link set up "${dev}" 179 + } 180 + 181 + veth_add() { 182 + local ns=$2 183 + local pns=$1 184 + local -a ns_cmd=(ip netns exec "${pns}") 185 + local ln="eth0" 186 + local rn="eth1" 187 + 188 + run_cmd "${ns_cmd[@]}" ip link add "${ln}" type veth peer name "${rn}" netns "${ns}" 189 + } 190 + 191 + show_icmp_filter() { 192 + run_cmd "${ns_r2[@]}" nft list ruleset 193 + echo "$out" 194 + } 195 + 196 + setup_icmp_filter() { 197 + run_cmd "${ns_r2[@]}" nft add table inet filter 198 + run_cmd "${ns_r2[@]}" nft add chain inet filter FORWARD \ 199 + '{ type filter hook forward priority filter; policy drop ; }' 200 + run_cmd "${ns_r2[@]}" nft add rule inet filter FORWARD counter ip protocol esp \ 201 + counter log accept 202 + run_cmd "${ns_r2[@]}" nft add rule inet filter FORWARD counter ip protocol \ 203 + icmp counter log drop 204 + 205 + if [ "$VERBOSE" -gt 0 ]; then 206 + run_cmd "${ns_r2[@]}" nft list ruleset 207 + echo "$out" 208 + fi 209 + } 210 + 211 + setup_icmpv6_filter() { 212 + run_cmd "${ns_r2[@]}" nft add table inet filter 213 + run_cmd "${ns_r2[@]}" nft add chain inet filter FORWARD \ 214 + '{ type filter hook forward priority filter; policy drop ; }' 215 + run_cmd "${ns_r2[@]}" nft add rule inet filter FORWARD ip6 nexthdr \ 216 + ipv6-icmp icmpv6 type echo-request counter log drop 217 + run_cmd "${ns_r2[@]}" nft add rule inet filter FORWARD ip6 nexthdr esp \ 218 + counter log accept 219 + run_cmd "${ns_r2[@]}" nft add rule inet filter FORWARD ip6 nexthdr \ 220 + ipv6-icmp icmpv6 type \ 221 + '{nd-neighbor-solicit,nd-neighbor-advert,nd-router-solicit,nd-router-advert}' \ 222 + counter log drop 223 + if [ "$VERBOSE" -gt 0 ]; then 224 + run_cmd "${ns_r2[@]}" nft list ruleset 225 + echo "$out" 226 + fi 227 + } 228 + 229 + set_xfrm_params() { 230 + s1_src=${src} 231 + s1_dst=${dst} 232 + s1_src_net=${src_net} 233 + s1_dst_net=${dst_net} 234 + } 235 + 236 + setup_ns_set_v4() { 237 + ns_set="a r1 s1 r2 s2 r3 b" # Network topology default 238 + imax=$(echo "$ns_set" | wc -w) # number of namespaces in this topology 239 + 240 + src="10.1.3.1" 241 + dst="10.1.4.2" 242 + src_net="10.1.1.0/24" 243 + dst_net="10.1.6.0/24" 244 + 245 + prefix=${prefix4} 246 + prefix_len=24 247 + s="." 248 + S="." 249 + 250 + set_xfrm_params 251 + } 252 + 253 + setup_ns_set_v4x() { 254 + ns_set="a r1 s1 r2 s2 b" # Network topology: x 255 + imax=$(echo "$ns_set" | wc -w) # number of namespaces in this topology 256 + prefix=${prefix4} 257 + s="." 258 + S="." 259 + src="10.1.3.1" 260 + dst="10.1.4.2" 261 + src_net="10.1.1.0/24" 262 + dst_net="10.1.5.0/24" 263 + prefix_len=24 264 + 265 + set_xfrm_params 266 + } 267 + 268 + setup_ns_set_v6() { 269 + ns_set="a r1 s1 r2 s2 r3 b" # Network topology default 270 + imax=$(echo "$ns_set" | wc -w) # number of namespaces in this topology 271 + prefix=${prefix6} 272 + s=":" 273 + S="::" 274 + src="fc00:3::1" 275 + dst="fc00:4::2" 276 + src_net="fc00:1::0/64" 277 + dst_net="fc00:6::0/64" 278 + prefix_len=64 279 + 280 + set_xfrm_params 281 + } 282 + 283 + setup_ns_set_v6x() { 284 + ns_set="a r1 s1 r2 s2 b" # Network topology: x 285 + imax=$(echo "$ns_set" | wc -w) 286 + prefix=${prefix6} 287 + s=":" 288 + S="::" 289 + src="fc00:3::1" 290 + dst="fc00:4::2" 291 + src_net="fc00:1::0/64" 292 + dst_net="fc00:5::0/64" 293 + prefix_len=64 294 + 295 + set_xfrm_params 296 + } 297 + 298 + setup_network() { 299 + # Create veths and add addresses 300 + local -a ns_cmd 301 + i=1 302 + p="" 303 + for ns in ${ns_active}; do 304 + ns_cmd=(ip netns exec "${ns}") 305 + 306 + if [ "${i}" -ne 1 ]; then 307 + # Create veth between previous and current namespace 308 + veth_add "${p}" "${ns}" 309 + # Add addresses: previous gets .1 on eth0, current gets .2 on eth1 310 + addr_add "${p}" "${prefix}${s}$((i-1))${S}1/${prefix_len}" eth0 311 + addr_add "${ns}" "${prefix}${s}$((i-1))${S}2/${prefix_len}" eth1 312 + fi 313 + 314 + # Enable forwarding 315 + run_cmd "${ns_cmd[@]}" sysctl -q net/ipv4/ip_forward=1 316 + run_cmd "${ns_cmd[@]}" sysctl -q net/ipv6/conf/all/forwarding=1 317 + run_cmd "${ns_cmd[@]}" sysctl -q net/ipv6/conf/default/accept_dad=0 318 + 319 + p=${ns} 320 + i=$((i + 1)) 321 + done 322 + 323 + # Add routes (needs all addresses to exist first) 324 + i=1 325 + for ns in ${ns_active}; do 326 + ns_cmd=(ip netns exec "${ns}") 327 + 328 + # Forward routes to networks beyond this node 329 + if [ "${i}" -ne "${imax}" ]; then 330 + nhf="${prefix}${s}${i}${S}2" # nexthop forward 331 + for j in $(seq $((i + 1)) "${imax}"); do 332 + run_cmd "${ns_cmd[@]}" ip route replace \ 333 + "${prefix}${s}${j}${S}0/${prefix_len}" via "${nhf}" 334 + done 335 + fi 336 + 337 + # Reverse routes to networks before this node 338 + if [ "${i}" -gt 1 ]; then 339 + nhr="${prefix}${s}$((i-1))${S}1" # nexthop reverse 340 + for j in $(seq 1 $((i - 2))); do 341 + run_cmd "${ns_cmd[@]}" ip route replace \ 342 + "${prefix}${s}${j}${S}0/${prefix_len}" via "${nhr}" 343 + done 344 + fi 345 + 346 + i=$((i + 1)) 347 + done 348 + } 349 + 350 + setup_xfrm_mode() { 351 + local MODE=${1:-tunnel} 352 + if [ "${MODE}" != "tunnel" ] && [ "${MODE}" != "beet" ]; then 353 + echo "xfrm mode ${MODE} not supported" 354 + log_test_error 355 + return 1 356 + fi 357 + 358 + run_cmd "${ns_s1[@]}" ip xfrm policy add src "${s1_src_net}" dst "${s1_dst_net}" dir out \ 359 + tmpl src "${s1_src}" dst "${s1_dst}" proto esp reqid 1 mode "${MODE}" 360 + 361 + # no "input" policies. we are only doing forwarding so far 362 + 363 + run_cmd "${ns_s1[@]}" ip xfrm policy add src "${s1_dst_net}" dst "${s1_src_net}" dir fwd \ 364 + flag icmp tmpl src "${s1_dst}" dst "${s1_src}" proto esp reqid 2 mode "${MODE}" 365 + 366 + run_cmd "${ns_s1[@]}" ip xfrm state add src "${s1_src}" dst "${s1_dst}" proto esp spi 1 \ 367 + reqid 1 mode "${MODE}" aead 'rfc4106(gcm(aes))' \ 368 + 0x1111111111111111111111111111111111111111 96 \ 369 + sel src "${s1_src_net}" dst "${s1_dst_net}" dir out 370 + 371 + run_cmd "${ns_s1[@]}" ip xfrm state add src "${s1_dst}" dst "${s1_src}" proto esp spi 2 \ 372 + reqid 2 flag icmp replay-window 8 mode "${MODE}" aead 'rfc4106(gcm(aes))' \ 373 + 0x2222222222222222222222222222222222222222 96 \ 374 + sel src "${s1_dst_net}" dst "${s1_src_net}" dir in 375 + 376 + run_cmd "${ns_s2[@]}" ip xfrm policy add src "${s1_dst_net}" dst "${s1_src_net}" dir out \ 377 + flag icmp tmpl src "${s1_dst}" dst "${s1_src}" proto esp reqid 2 mode "${MODE}" 378 + 379 + run_cmd "${ns_s2[@]}" ip xfrm policy add src "${s1_src_net}" dst "${s1_dst_net}" dir fwd \ 380 + tmpl src "${s1_src}" dst "${s1_dst}" proto esp reqid 1 mode "${MODE}" 381 + 382 + run_cmd "${ns_s2[@]}" ip xfrm state add src "${s1_dst}" dst "${s1_src}" proto esp spi 2 \ 383 + reqid 2 mode "${MODE}" aead 'rfc4106(gcm(aes))' \ 384 + 0x2222222222222222222222222222222222222222 96 \ 385 + sel src "${s1_dst_net}" dst "${s1_src_net}" dir out 386 + 387 + run_cmd "${ns_s2[@]}" ip xfrm state add src "${s1_src}" dst "${s1_dst}" proto esp spi 1 \ 388 + reqid 1 flag icmp replay-window 8 mode "${MODE}" aead 'rfc4106(gcm(aes))' \ 389 + 0x1111111111111111111111111111111111111111 96 \ 390 + sel src "${s1_src_net}" dst "${s1_dst_net}" dir in 391 + } 392 + 393 + setup_xfrm() { 394 + setup_xfrm_mode tunnel 395 + } 396 + 397 + setup() { 398 + [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return "$ksft_skip" 399 + 400 + for arg; do 401 + case "${arg}" in 402 + ns_set_v4) setup_ns_set_v4 ;; 403 + ns_set_v4x) setup_ns_set_v4x ;; 404 + ns_set_v6) setup_ns_set_v6 ;; 405 + ns_set_v6x) setup_ns_set_v6x ;; 406 + namespaces) setup_namespaces ;; 407 + network) setup_network ;; 408 + xfrm) setup_xfrm ;; 409 + icmp_filter) setup_icmp_filter ;; 410 + icmpv6_filter) setup_icmpv6_filter ;; 411 + *) echo " ${arg} not supported"; return 1 ;; 412 + esac || return 1 413 + done 414 + } 415 + 416 + # shellcheck disable=SC2317 # called via trap 417 + pause() { 418 + echo 419 + echo "Pausing. Hit enter to continue" 420 + read -r _ 421 + } 422 + 423 + # shellcheck disable=SC2317 # called via trap 424 + log_test_error() { 425 + # shellcheck disable=SC2031 # fail is set in subshell, read via trap 426 + if [ "${fail}" = "yes" ] && [ -n "${desc}" ]; then 427 + if [ "$VERBOSE" -gt 0 ]; then 428 + show_icmp_filter 429 + fi 430 + printf "TEST: %-60s [ FAIL ] %s\n" "${desc}" "${name}" 431 + [ -n "${cmd}" ] && printf '%s\n\n' "${cmd}" 432 + [ -n "${out}" ] && printf '%s\n\n' "${out}" 433 + fi 434 + } 435 + 436 + # shellcheck disable=SC2317 # called via trap 437 + cleanup() { 438 + # shellcheck disable=SC2031 # fail is set in subshell, read via trap 439 + [[ "$PAUSE" = "always" || ( "$PAUSE" = "fail" && "$fail" = "yes" ) ]] && pause 440 + cleanup_all_ns 441 + # shellcheck disable=SC2031 # fail is set in subshell, read via trap 442 + [ "${EXIT_ON_TEST_FAIL}" = "yes" ] && [ "${fail}" = "yes" ] && exit 1 443 + } 444 + 445 + test_unreachable_ipv6() { 446 + setup ns_set_v6 namespaces network xfrm icmpv6_filter || return "$ksft_skip" 447 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:6::2 448 + run_cmd_err "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:6::3 449 + rc=0 450 + echo -e "$out" | grep -q -E 'From fc00:5::2 icmp_seq.* Destination' || rc=1 451 + return "${rc}" 452 + } 453 + 454 + test_unreachable_gw_ipv6() { 455 + setup ns_set_v6x namespaces network xfrm icmpv6_filter || return "$ksft_skip" 456 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:5::2 457 + run_cmd_err "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:5::3 458 + rc=0 459 + echo -e "$out" | grep -q -E 'From fc00:4::2 icmp_seq.* Destination' || rc=1 460 + return "${rc}" 461 + } 462 + 463 + test_unreachable_ipv4() { 464 + setup ns_set_v4 namespaces network icmp_filter xfrm || return "$ksft_skip" 465 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.6.2 466 + run_cmd_err "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.6.3 467 + rc=0 468 + echo -e "$out" | grep -q -E 'From 10.1.5.2 icmp_seq.* Destination' || rc=1 469 + return "${rc}" 470 + } 471 + 472 + test_unreachable_gw_ipv4() { 473 + setup ns_set_v4x namespaces network icmp_filter xfrm || return "$ksft_skip" 474 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.5.2 475 + run_cmd_err "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.5.3 476 + rc=0 477 + echo -e "$out" | grep -q -E 'From 10.1.4.2 icmp_seq.* Destination' || rc=1 478 + return "${rc}" 479 + } 480 + 481 + test_mtu_ipv4_r2() { 482 + setup ns_set_v4 namespaces network icmp_filter xfrm || return "$ksft_skip" 483 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.6.2 484 + run_cmd "${ns_r2[@]}" ip route replace 10.1.3.0/24 dev eth1 src 10.1.3.2 mtu 1300 485 + run_cmd "${ns_r2[@]}" ip route replace 10.1.4.0/24 dev eth0 src 10.1.4.1 mtu 1300 486 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 487 + run_cmd "${ns_a[@]}" ping -M do -s 1300 -W 5 -w 4 -c 1 10.1.6.2 || true 488 + rc=0 489 + echo -e "$out" | grep -q -E "From 10.1.2.2 icmp_seq=.* Frag needed and DF set" || rc=1 490 + return "${rc}" 491 + } 492 + 493 + test_mtu_ipv6_r2() { 494 + setup ns_set_v6 namespaces network xfrm icmpv6_filter || return "$ksft_skip" 495 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:6::2 496 + run_cmd "${ns_r2[@]}" ip -6 route replace fc00:3::/64 \ 497 + dev eth1 metric 256 src fc00:3::2 mtu 1300 498 + run_cmd "${ns_r2[@]}" ip -6 route replace fc00:4::/64 \ 499 + dev eth0 metric 256 src fc00:4::1 mtu 1300 500 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 501 + run_cmd "${ns_a[@]}" ping -M do -s 1300 -W 5 -w 4 -c 1 fc00:6::2 || true 502 + rc=0 503 + echo -e "$out" | grep -q -E "From fc00:2::2 icmp_seq=.* Packet too big: mtu=1230" || rc=1 504 + return "${rc}" 505 + } 506 + 507 + test_mtu_ipv4_r3() { 508 + setup ns_set_v4 namespaces network icmp_filter xfrm || return "$ksft_skip" 509 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.6.2 510 + run_cmd "${ns_r3[@]}" ip route replace 10.1.6.0/24 dev eth0 mtu 1300 511 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 512 + run_cmd "${ns_a[@]}" ping -M do -s 1350 -W 5 -w 4 -c 1 10.1.6.2 || true 513 + rc=0 514 + echo -e "$out" | grep -q -E "From 10.1.5.2 .* Frag needed and DF set \(mtu = 1300\)" || rc=1 515 + return "${rc}" 516 + } 517 + 518 + test_mtu_ipv4_s2() { 519 + setup ns_set_v4x namespaces network icmp_filter xfrm || return "$ksft_skip" 520 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 10.1.5.2 521 + run_cmd "${ns_s2[@]}" ip route replace 10.1.5.0/24 dev eth0 src 10.1.5.1 mtu 1300 522 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 523 + run_cmd "${ns_a[@]}" ping -M do -s 1350 -W 5 -w 4 -c 1 10.1.5.2 || true 524 + rc=0 525 + echo -e "$out" | grep -q -E "From 10.1.4.2.*Frag needed and DF set \(mtu = 1300\)" || rc=1 526 + return "${rc}" 527 + } 528 + 529 + test_mtu_ipv6_s2() { 530 + setup ns_set_v6x namespaces network xfrm icmpv6_filter || return "$ksft_skip" 531 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:5::2 532 + run_cmd "${ns_s2[@]}" ip -6 route replace fc00:5::/64 dev eth0 metric 256 mtu 1300 533 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 534 + run_cmd "${ns_a[@]}" ping -M do -s 1350 -W 5 -w 4 -c 1 fc00:5::2 || true 535 + rc=0 536 + echo -e "$out" | grep -q -E "From fc00:4::2.*Packet too big: mtu=1300" || rc=1 537 + return "${rc}" 538 + } 539 + 540 + test_mtu_ipv6_r3() { 541 + setup ns_set_v6 namespaces network xfrm icmpv6_filter || return "$ksft_skip" 542 + run_cmd "${ns_a[@]}" ping -W 5 -w 4 -c 1 fc00:6::2 543 + run_cmd "${ns_r3[@]}" ip -6 route replace fc00:6::/64 dev eth1 metric 256 mtu 1300 544 + # shellcheck disable=SC1010 # -M do: do = dont-fragment, not shell keyword 545 + run_cmd "${ns_a[@]}" ping -M do -s 1300 -W 5 -w 4 -c 1 fc00:6::2 || true 546 + rc=0 547 + echo -e "$out" | grep -q -E "From fc00:5::2 icmp_seq=.* Packet too big: mtu=1300" || rc=1 548 + return "${rc}" 549 + } 550 + 551 + ################################################################################ 552 + # 553 + usage() { 554 + echo 555 + echo "$0 [OPTIONS] [TEST]..." 556 + echo "If no TEST argument is given, all tests will be run." 557 + echo 558 + echo -e "\t-p Pause on fail. Namespaces are kept for diagnostics" 559 + echo -e "\t-P Pause after the test. Namespaces are kept for diagnostics" 560 + echo -e "\t-v Verbose output. Show commands; -vv Show output and nft rules also" 561 + echo "Available tests${tests}" 562 + exit 1 563 + } 564 + 565 + ################################################################################ 566 + # 567 + exitcode=0 568 + all_skipped=true 569 + out= 570 + cmd= 571 + 572 + while getopts :epPv o; do 573 + case $o in 574 + e) EXIT_ON_TEST_FAIL=yes ;; 575 + P) PAUSE=always ;; 576 + p) PAUSE=fail ;; 577 + v) VERBOSE=$((VERBOSE + 1)) ;; 578 + *) usage ;; 579 + esac 580 + done 581 + shift $((OPTIND - 1)) 582 + 583 + IFS=$'\t\n' 584 + 585 + for arg; do 586 + # Check first that all requested tests are available before running any 587 + command -v "test_${arg}" >/dev/null || { 588 + echo "=== Test ${arg} not found" 589 + usage 590 + } 591 + done 592 + 593 + name="" 594 + desc="" 595 + fail="no" 596 + 597 + for t in ${tests}; do 598 + [ "${name}" = "" ] && name="${t}" && continue 599 + [ "${desc}" = "" ] && desc="${t}" 600 + 601 + run_this=1 602 + for arg; do 603 + [ "${arg}" = "${name}" ] && run_this=1 && break 604 + run_this=0 605 + done 606 + if [ $run_this -eq 1 ]; then 607 + run_test 608 + fi 609 + name="" 610 + desc="" 611 + done 612 + 613 + exit ${exitcode}