diff options
Diffstat (limited to 'tools/testing/selftests/net/pmtu.sh')
-rwxr-xr-x | tools/testing/selftests/net/pmtu.sh | 270 |
1 files changed, 221 insertions, 49 deletions
diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh index cfc84958025a..88e914c4eef9 100755 --- a/tools/testing/selftests/net/pmtu.sh +++ b/tools/testing/selftests/net/pmtu.sh @@ -197,9 +197,14 @@ # # - pmtu_ipv6_route_change # Same as above but with IPv6 +# +# - pmtu_ipv4_mp_exceptions +# Use the same topology as in pmtu_ipv4, but add routeable addresses +# on host A and B on lo reachable via both routers. Host A and B +# addresses have multipath routes to each other, b_r1 mtu = 1500. +# Check that PMTU exceptions are created for both paths. source lib.sh -source net_helper.sh PAUSE_ON_FAIL=no VERBOSE=0 @@ -266,7 +271,8 @@ tests=" list_flush_ipv4_exception ipv4: list and flush cached exceptions 1 list_flush_ipv6_exception ipv6: list and flush cached exceptions 1 pmtu_ipv4_route_change ipv4: PMTU exception w/route replace 1 - pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1" + pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1 + pmtu_ipv4_mp_exceptions ipv4: PMTU multipath nh exceptions 1" # Addressing and routing for tests with routers: four network segments, with # index SEGMENT between 1 and 4, a common prefix (PREFIX4 or PREFIX6) and an @@ -343,6 +349,9 @@ tunnel6_a_addr="fd00:2::a" tunnel6_b_addr="fd00:2::b" tunnel6_mask="64" +host4_a_addr="192.168.99.99" +host4_b_addr="192.168.88.88" + dummy6_0_prefix="fc00:1000::" dummy6_1_prefix="fc00:1001::" dummy6_mask="64" @@ -681,13 +690,7 @@ setup_xfrm() { } setup_nettest_xfrm() { - if ! which nettest >/dev/null; then - PATH=$PWD:$PATH - if ! which nettest >/dev/null; then - echo "'nettest' command not found; skipping tests" - return 1 - fi - fi + check_gen_prog "nettest" [ ${1} -eq 6 ] && proto="-6" || proto="" port=${2} @@ -842,25 +845,97 @@ setup_bridge() { run_cmd ${ns_a} ip link set veth_A-C master br0 } +setup_ovs_via_internal_utility() { + type="${1}" + a_addr="${2}" + b_addr="${3}" + dport="${4}" + + run_cmd python3 ./openvswitch/ovs-dpctl.py add-if ovs_br0 ${type}_a -t ${type} || return 1 + + ports=$(python3 ./openvswitch/ovs-dpctl.py show) + br0_port=$(echo "$ports" | grep -E "\sovs_br0" | sed -e 's@port @@' | cut -d: -f1 | xargs) + type_a_port=$(echo "$ports" | grep ${type}_a | sed -e 's@port @@' | cut -d: -f1 | xargs) + veth_a_port=$(echo "$ports" | grep veth_A | sed -e 's@port @@' | cut -d: -f1 | xargs) + + v4_a_tun="${prefix4}.${a_r1}.1" + v4_b_tun="${prefix4}.${b_r1}.1" + + v6_a_tun="${prefix6}:${a_r1}::1" + v6_b_tun="${prefix6}:${b_r1}::1" + + if [ "${v4_a_tun}" = "${a_addr}" ]; then + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0800),ipv4()" \ + "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x86dd),ipv6()" \ + "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0800),ipv4()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x86dd),ipv6()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0806),arp()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0806),arp(sip=${veth4_c_addr},tip=${tunnel4_b_addr})" \ + "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + else + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0800),ipv4()" \ + "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x86dd),ipv6()" \ + "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0800),ipv4()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x86dd),ipv6()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0806),arp()" \ + "${veth_a_port}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \ + "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0806),arp(sip=${veth4_c_addr},tip=${tunnel4_b_addr})" \ + "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}" + fi +} + +setup_ovs_via_vswitchd() { + type="${1}" + b_addr="${2}" + + run_cmd ovs-vsctl add-port ovs_br0 ${type}_a -- \ + set interface ${type}_a type=${type} \ + options:remote_ip=${b_addr} options:key=1 options:csum=true || return 1 +} + setup_ovs_vxlan_or_geneve() { type="${1}" a_addr="${2}" b_addr="${3}" + dport="6081" if [ "${type}" = "vxlan" ]; then + dport="4789" opts="${opts} ttl 64 dstport 4789" opts_b="local ${b_addr}" fi - run_cmd ovs-vsctl add-port ovs_br0 ${type}_a -- \ - set interface ${type}_a type=${type} \ - options:remote_ip=${b_addr} options:key=1 options:csum=true || return 1 + setup_ovs_via_internal_utility "${type}" "${a_addr}" "${b_addr}" \ + "${dport}" || \ + setup_ovs_via_vswitchd "${type}" "${b_addr}" || return 1 run_cmd ${ns_b} ip link add ${type}_b type ${type} id 1 ${opts_b} remote ${a_addr} ${opts} || return 1 run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${type}_b run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${type}_b + run_cmd ip link set ${type}_a up run_cmd ${ns_b} ip link set ${type}_b up } @@ -880,8 +955,24 @@ setup_ovs_vxlan6() { setup_ovs_vxlan_or_geneve vxlan ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 } +setup_ovs_br_internal() { + run_cmd python3 ./openvswitch/ovs-dpctl.py add-dp ovs_br0 || \ + return 1 +} + +setup_ovs_br_vswitchd() { + run_cmd ovs-vsctl add-br ovs_br0 || return 1 +} + +setup_ovs_add_if() { + ifname="${1}" + run_cmd python3 ./openvswitch/ovs-dpctl.py add-if ovs_br0 \ + "${ifname}" || \ + run_cmd ovs-vsctl add-port ovs_br0 "${ifname}" +} + setup_ovs_bridge() { - run_cmd ovs-vsctl add-br ovs_br0 || return $ksft_skip + setup_ovs_br_internal || setup_ovs_br_vswitchd || return $ksft_skip run_cmd ip link set ovs_br0 up run_cmd ${ns_c} ip link add veth_C-A type veth peer name veth_A-C @@ -891,7 +982,7 @@ setup_ovs_bridge() { run_cmd ${ns_c} ip link set veth_C-A up run_cmd ${ns_c} ip addr add ${veth4_c_addr}/${veth4_mask} dev veth_C-A run_cmd ${ns_c} ip addr add ${veth6_c_addr}/${veth6_mask} dev veth_C-A - run_cmd ovs-vsctl add-port ovs_br0 veth_A-C + setup_ovs_add_if veth_A-C # Move veth_A-R1 to init run_cmd ${ns_a} ip link set veth_A-R1 netns 1 @@ -902,6 +993,52 @@ setup_ovs_bridge() { run_cmd ip route add ${prefix6}:${b_r1}::1 via ${prefix6}:${a_r1}::2 } +setup_multipath_new() { + # Set up host A with multipath routes to host B host4_b_addr + run_cmd ${ns_a} ip addr add ${host4_a_addr} dev lo + run_cmd ${ns_a} ip nexthop add id 401 via ${prefix4}.${a_r1}.2 dev veth_A-R1 + run_cmd ${ns_a} ip nexthop add id 402 via ${prefix4}.${a_r2}.2 dev veth_A-R2 + run_cmd ${ns_a} ip nexthop add id 403 group 401/402 + run_cmd ${ns_a} ip route add ${host4_b_addr} src ${host4_a_addr} nhid 403 + + # Set up host B with multipath routes to host A host4_a_addr + run_cmd ${ns_b} ip addr add ${host4_b_addr} dev lo + run_cmd ${ns_b} ip nexthop add id 401 via ${prefix4}.${b_r1}.2 dev veth_B-R1 + run_cmd ${ns_b} ip nexthop add id 402 via ${prefix4}.${b_r2}.2 dev veth_B-R2 + run_cmd ${ns_b} ip nexthop add id 403 group 401/402 + run_cmd ${ns_b} ip route add ${host4_a_addr} src ${host4_b_addr} nhid 403 +} + +setup_multipath_old() { + # Set up host A with multipath routes to host B host4_b_addr + run_cmd ${ns_a} ip addr add ${host4_a_addr} dev lo + run_cmd ${ns_a} ip route add ${host4_b_addr} \ + src ${host4_a_addr} \ + nexthop via ${prefix4}.${a_r1}.2 weight 1 \ + nexthop via ${prefix4}.${a_r2}.2 weight 1 + + # Set up host B with multipath routes to host A host4_a_addr + run_cmd ${ns_b} ip addr add ${host4_b_addr} dev lo + run_cmd ${ns_b} ip route add ${host4_a_addr} \ + src ${host4_b_addr} \ + nexthop via ${prefix4}.${b_r1}.2 weight 1 \ + nexthop via ${prefix4}.${b_r2}.2 weight 1 +} + +setup_multipath() { + if [ "$USE_NH" = "yes" ]; then + setup_multipath_new + else + setup_multipath_old + fi + + # Set up routers with routes to dummies + run_cmd ${ns_r1} ip route add ${host4_a_addr} via ${prefix4}.${a_r1}.1 + run_cmd ${ns_r2} ip route add ${host4_a_addr} via ${prefix4}.${a_r2}.1 + run_cmd ${ns_r1} ip route add ${host4_b_addr} via ${prefix4}.${b_r1}.1 + run_cmd ${ns_r2} ip route add ${host4_b_addr} via ${prefix4}.${b_r2}.1 +} + setup() { [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip @@ -922,6 +1059,18 @@ trace() { sleep 1 } +cleanup_del_ovs_internal() { + # squelch the output of the del-if commands since it can be wordy + python3 ./openvswitch/ovs-dpctl.py del-if ovs_br0 -d true vxlan_a >/dev/null 2>&1 + python3 ./openvswitch/ovs-dpctl.py del-if ovs_br0 -d true geneve_a >/dev/null 2>&1 + python3 ./openvswitch/ovs-dpctl.py del-dp ovs_br0 >/dev/null 2>&1 +} + +cleanup_del_ovs_vswitchd() { + ovs-vsctl --if-exists del-port vxlan_a 2>/dev/null + ovs-vsctl --if-exists del-br ovs_br0 2>/dev/null +} + cleanup() { for pid in ${tcpdump_pids}; do kill ${pid} @@ -940,10 +1089,10 @@ cleanup() { cleanup_all_ns - ip link del veth_A-C 2>/dev/null - ip link del veth_A-R1 2>/dev/null - ovs-vsctl --if-exists del-port vxlan_a 2>/dev/null - ovs-vsctl --if-exists del-br ovs_br0 2>/dev/null + ip link del veth_A-C 2>/dev/null + ip link del veth_A-R1 2>/dev/null + cleanup_del_ovs_internal + cleanup_del_ovs_vswitchd rm -f "$tmpoutfile" } @@ -982,23 +1131,15 @@ link_get_mtu() { } route_get_dst_exception() { - ns_cmd="${1}" - dst="${2}" - dsfield="${3}" - - if [ -z "${dsfield}" ]; then - dsfield=0 - fi + ns_cmd="${1}"; shift - ${ns_cmd} ip route get "${dst}" dsfield "${dsfield}" + ${ns_cmd} ip route get "$@" } route_get_dst_pmtu_from_exception() { - ns_cmd="${1}" - dst="${2}" - dsfield="${3}" + ns_cmd="${1}"; shift - mtu_parse "$(route_get_dst_exception "${ns_cmd}" "${dst}" "${dsfield}")" + mtu_parse "$(route_get_dst_exception "${ns_cmd}" "$@")" } check_pmtu_value() { @@ -1141,10 +1282,10 @@ test_pmtu_ipv4_dscp_icmp_exception() { run_cmd "${ns_a}" ping -q -M want -Q "${dsfield}" -c 1 -w 1 -s "${len}" "${dst2}" # Check that exceptions have been created with the correct PMTU - pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" "${policy_mark}")" + pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" dsfield "${policy_mark}")" check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1 - pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" "${policy_mark}")" + pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" dsfield "${policy_mark}")" check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1 } @@ -1191,9 +1332,9 @@ test_pmtu_ipv4_dscp_udp_exception() { UDP:"${dst2}":50000,tos="${dsfield}" # Check that exceptions have been created with the correct PMTU - pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" "${policy_mark}")" + pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" dsfield "${policy_mark}")" check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1 - pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" "${policy_mark}")" + pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" dsfield "${policy_mark}")" check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1 } @@ -1347,7 +1488,7 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() { size=$(du -sb $tmpoutfile) size=${size%%/tmp/*} - [ $size -ne 1048576 ] && err "File size $size mismatches exepcted value in locally bridged vxlan test" && return 1 + [ $size -ne 1048576 ] && err "File size $size mismatches expected value in locally bridged vxlan test" && return 1 done rm -f "$tmpoutfile" @@ -1397,6 +1538,12 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() { outer_family=${3} ll_mtu=4000 + if [ "${type}" = "vxlan" ]; then + tun_a="vxlan_sys_4789" + elif [ "${type}" = "geneve" ]; then + tun_a="genev_sys_6081" + fi + if [ ${outer_family} -eq 4 ]; then setup namespaces routing ovs_bridge ovs_${type}4 || return $ksft_skip # IPv4 header UDP header VXLAN/GENEVE header Ethernet header @@ -1407,17 +1554,11 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() { exp_mtu=$((${ll_mtu} - 40 - 8 - 8 - 14)) fi - if [ "${type}" = "vxlan" ]; then - tun_a="vxlan_sys_4789" - elif [ "${type}" = "geneve" ]; then - tun_a="genev_sys_6081" - fi - - trace "" "${tun_a}" "${ns_b}" ${type}_b \ - "" veth_A-R1 "${ns_r1}" veth_R1-A \ - "${ns_b}" veth_B-R1 "${ns_r1}" veth_R1-B \ - "" ovs_br0 "" veth-A-C \ - "${ns_c}" veth_C-A + trace "" ${type}_a "${ns_b}" ${type}_b \ + "" veth_A-R1 "${ns_r1}" veth_R1-A \ + "${ns_b}" veth_B-R1 "${ns_r1}" veth_R1-B \ + "" ovs_br0 "" veth-A_C \ + "${ns_c}" veth_C-A "" "${tun_a}" if [ ${family} -eq 4 ]; then ping=ping @@ -1436,8 +1577,9 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() { mtu "${ns_b}" veth_B-R1 ${ll_mtu} mtu "${ns_r1}" veth_R1-B ${ll_mtu} - mtu "" ${tun_a} $((${ll_mtu} + 1000)) - mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000)) + mtu "" ${tun_a} $((${ll_mtu} + 1000)) 2>/dev/null || \ + mtu "" ${type}_a $((${ll_mtu} + 1000)) 2>/dev/null + mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000)) run_cmd ${ns_c} ${ping} -q -M want -i 0.1 -c 20 -s $((${ll_mtu} + 500)) ${dst} || return 1 @@ -1961,7 +2103,7 @@ check_running() { pid=${1} cmd=${2} - [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ] + [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "${cmd}" ] } test_cleanup_vxlanX_exception() { @@ -2234,6 +2376,36 @@ test_pmtu_ipv6_route_change() { test_pmtu_ipvX_route_change 6 } +test_pmtu_ipv4_mp_exceptions() { + setup namespaces routing multipath || return $ksft_skip + + trace "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \ + "${ns_r1}" veth_R1-B "${ns_b}" veth_B-R1 \ + "${ns_a}" veth_A-R2 "${ns_r2}" veth_R2-A \ + "${ns_r2}" veth_R2-B "${ns_b}" veth_B-R2 + + # Set up initial MTU values + mtu "${ns_a}" veth_A-R1 2000 + mtu "${ns_r1}" veth_R1-A 2000 + mtu "${ns_r1}" veth_R1-B 1500 + mtu "${ns_b}" veth_B-R1 1500 + + mtu "${ns_a}" veth_A-R2 2000 + mtu "${ns_r2}" veth_R2-A 2000 + mtu "${ns_r2}" veth_R2-B 1500 + mtu "${ns_b}" veth_B-R2 1500 + + # Ping and expect two nexthop exceptions for two routes + run_cmd ${ns_a} ping -q -M want -i 0.1 -c 1 -s 1800 "${host4_b_addr}" + + # Check that exceptions have been created with the correct PMTU + pmtu_a_R1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${host4_b_addr}" oif veth_A-R1)" + pmtu_a_R2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${host4_b_addr}" oif veth_A-R2)" + + check_pmtu_value "1500" "${pmtu_a_R1}" "exceeding MTU (veth_A-R1)" || return 1 + check_pmtu_value "1500" "${pmtu_a_R2}" "exceeding MTU (veth_A-R2)" || return 1 +} + usage() { echo echo "$0 [OPTIONS] [TEST]..." |