selftests: net: add ESP-in-UDP PMTU test
[linux-2.6-microblaze.git] / tools / testing / selftests / net / pmtu.sh
index 64cd2e2..543ad75 100755 (executable)
 #      below for IPv6 doesn't apply here, because, on IPv4, administrative MTU
 #      changes alone won't affect PMTU
 #
+# - pmtu_vti4_udp_exception
+#       Same as pmtu_vti4_exception, but using ESP-in-UDP
+#
+# - pmtu_vti4_udp_routed_exception
+#       Set up vti tunnel on top of veth connected through routing namespace and
+#      add xfrm states and policies with ESP-in-UDP encapsulation. Check that
+#      route exception is not created if link layer MTU is not exceeded, then
+#      lower MTU on second part of routed environment and check that exception
+#      is created with the expected PMTU.
+#
 # - pmtu_vti6_exception
 #      Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
 #      namespaces with matching endpoints. Check that route exception is
 #      decrease and increase MTU of tunnel, checking that route exception PMTU
 #      changes accordingly
 #
+# - pmtu_vti6_udp_exception
+#       Same as pmtu_vti6_exception, but using ESP-in-UDP
+#
+# - pmtu_vti6_udp_routed_exception
+#      Same as pmtu_vti6_udp_routed_exception but with routing between vti
+#      endpoints
+#
 # - pmtu_vti4_default_mtu
 #      Set up vti4 tunnel on top of veth, in two namespaces with matching
 #      endpoints. Check that MTU assigned to vti interface is the MTU of the
@@ -224,6 +241,10 @@ tests="
        pmtu_ipv6_ipv6_exception        IPv6 over IPv6: PMTU exceptions         1
        pmtu_vti6_exception             vti6: PMTU exceptions                   0
        pmtu_vti4_exception             vti4: PMTU exceptions                   0
+       pmtu_vti6_udp_exception         vti6: PMTU exceptions (ESP-in-UDP)      0
+       pmtu_vti4_udp_exception         vti4: PMTU exceptions (ESP-in-UDP)      0
+       pmtu_vti6_udp_routed_exception  vti6: PMTU exceptions, routed (ESP-in-UDP)      0
+       pmtu_vti4_udp_routed_exception  vti4: PMTU exceptions, routed (ESP-in-UDP)      0
        pmtu_vti4_default_mtu           vti4: default MTU assignment            0
        pmtu_vti6_default_mtu           vti6: default MTU assignment            0
        pmtu_vti4_link_add_mtu          vti4: MTU setting on link creation      0
@@ -246,7 +267,6 @@ ns_b="ip netns exec ${NS_B}"
 ns_c="ip netns exec ${NS_C}"
 ns_r1="ip netns exec ${NS_R1}"
 ns_r2="ip netns exec ${NS_R2}"
-
 # 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
 # identifier ID, which is 1 for hosts (A and B), 2 for routers (R1 and R2).
@@ -279,7 +299,6 @@ routes="
        A       ${prefix6}:${b_r2}::1   ${prefix6}:${a_r2}::2
        B       default                 ${prefix6}:${b_r1}::2
 "
-
 USE_NH="no"
 #      ns      family  nh id      destination          gateway
 nexthops="
@@ -326,6 +345,7 @@ dummy6_mask="64"
 
 err_buf=
 tcpdump_pids=
+nettest_pids=
 
 err() {
        err_buf="${err_buf}${1}
@@ -548,6 +568,14 @@ setup_vti6() {
        setup_vti 6 ${veth6_a_addr} ${veth6_b_addr} ${tunnel6_a_addr} ${tunnel6_b_addr} ${tunnel6_mask}
 }
 
+setup_vti4routed() {
+       setup_vti 4 ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 ${tunnel4_a_addr} ${tunnel4_b_addr} ${tunnel4_mask}
+}
+
+setup_vti6routed() {
+       setup_vti 6 ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 ${tunnel6_a_addr} ${tunnel6_b_addr} ${tunnel6_mask}
+}
+
 setup_vxlan_or_geneve() {
        type="${1}"
        a_addr="${2}"
@@ -619,18 +647,36 @@ setup_xfrm() {
        proto=${1}
        veth_a_addr="${2}"
        veth_b_addr="${3}"
+       encap=${4}
 
-       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
-       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
+       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 ${encap} || return 1
+       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 ${encap}
        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
        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
 
-       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
-       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
+       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 ${encap}
+       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 ${encap}
        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
        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
 }
 
+setup_nettest_xfrm() {
+       which nettest >/dev/null
+       if [ $? -ne 0 ]; then
+               echo "'nettest' command not found; skipping tests"
+               return 1
+       fi
+
+       [ ${1} -eq 6 ] && proto="-6" || proto=""
+       port=${2}
+
+       run_cmd ${ns_a} nettest ${proto} -q -D -s -x -p ${port} -t 5 &
+       nettest_pids="${nettest_pids} $!"
+
+       run_cmd ${ns_b} nettest ${proto} -q -D -s -x -p ${port} -t 5 &
+       nettest_pids="${nettest_pids} $!"
+}
+
 setup_xfrm4() {
        setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr}
 }
@@ -639,6 +685,26 @@ setup_xfrm6() {
        setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr}
 }
 
+setup_xfrm4udp() {
+       setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} "encap espinudp 4500 4500 0.0.0.0"
+       setup_nettest_xfrm 4 4500
+}
+
+setup_xfrm6udp() {
+       setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} "encap espinudp 4500 4500 0.0.0.0"
+       setup_nettest_xfrm 6 4500
+}
+
+setup_xfrm4udprouted() {
+       setup_xfrm 4 ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "encap espinudp 4500 4500 0.0.0.0"
+       setup_nettest_xfrm 4 4500
+}
+
+setup_xfrm6udprouted() {
+       setup_xfrm 6 ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "encap espinudp 4500 4500 0.0.0.0"
+       setup_nettest_xfrm 6 4500
+}
+
 setup_routing_old() {
        for i in ${routes}; do
                [ "${ns}" = "" ]        && ns="${i}"            && continue
@@ -823,6 +889,11 @@ cleanup() {
        done
        tcpdump_pids=
 
+       for pid in ${nettest_pids}; do
+               kill ${pid}
+       done
+       nettest_pids=
+
        for n in ${NS_A} ${NS_B} ${NS_C} ${NS_R1} ${NS_R2}; do
                ip netns del ${n} 2> /dev/null
        done
@@ -1432,6 +1503,135 @@ test_pmtu_vti6_exception() {
        return ${fail}
 }
 
+test_pmtu_vti4_udp_exception() {
+       setup namespaces veth vti4 xfrm4udp || return $ksft_skip
+       trace "${ns_a}" veth_a    "${ns_b}" veth_b \
+             "${ns_a}" vti4_a    "${ns_b}" vti4_b
+
+       veth_mtu=1500
+       vti_mtu=$((veth_mtu - 20))
+
+       #                                UDP   SPI   SN   IV  ICV   pad length   next header
+       esp_payload_rfc4106=$((vti_mtu - 8   - 4   - 4  - 8 - 16  - 1          - 1))
+       ping_payload=$((esp_payload_rfc4106 - 28))
+
+       mtu "${ns_a}" veth_a ${veth_mtu}
+       mtu "${ns_b}" veth_b ${veth_mtu}
+       mtu "${ns_a}" vti4_a ${vti_mtu}
+       mtu "${ns_b}" vti4_b ${vti_mtu}
+
+       # Send DF packet without exceeding link layer MTU, check that no
+       # exception is created
+       run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s ${ping_payload} ${tunnel4_b_addr}
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
+       check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1
+
+       # Now exceed link layer MTU by one byte, check that exception is created
+       # with the right PMTU value
+       run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((ping_payload + 1)) ${tunnel4_b_addr}
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
+       check_pmtu_value "${esp_payload_rfc4106}" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106 + 1)))"
+}
+
+test_pmtu_vti6_udp_exception() {
+       setup namespaces veth vti6 xfrm6udp || return $ksft_skip
+       trace "${ns_a}" veth_a    "${ns_b}" veth_b \
+             "${ns_a}" vti6_a    "${ns_b}" vti6_b
+       fail=0
+
+       # Create route exception by exceeding link layer MTU
+       mtu "${ns_a}" veth_a 4000
+       mtu "${ns_b}" veth_b 4000
+       mtu "${ns_a}" vti6_a 5000
+       mtu "${ns_b}" vti6_b 5000
+       run_cmd ${ns_a} ${ping6} -q -i 0.1 -w 1 -s 60000 ${tunnel6_b_addr}
+
+       # Check that exception was created
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
+       check_pmtu_value any "${pmtu}" "creating tunnel exceeding link layer MTU" || return 1
+
+       # Decrease tunnel MTU, check for PMTU decrease in route exception
+       mtu "${ns_a}" vti6_a 3000
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
+       check_pmtu_value "3000" "${pmtu}" "decreasing tunnel MTU" || fail=1
+
+       # Increase tunnel MTU, check for PMTU increase in route exception
+       mtu "${ns_a}" vti6_a 9000
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
+       check_pmtu_value "9000" "${pmtu}" "increasing tunnel MTU" || fail=1
+
+       return ${fail}
+}
+
+test_pmtu_vti4_udp_routed_exception() {
+       setup namespaces routing vti4routed xfrm4udprouted || return $ksft_skip
+       trace "${ns_a}" veth_A-R1    "${ns_b}" veth_B-R1 \
+             "${ns_a}" vti4_a       "${ns_b}" vti4_b
+
+       veth_mtu=1500
+       vti_mtu=$((veth_mtu - 20))
+
+       #                                UDP   SPI   SN   IV  ICV   pad length   next header
+       esp_payload_rfc4106=$((vti_mtu - 8   - 4   - 4  - 8 - 16  - 1          - 1))
+       ping_payload=$((esp_payload_rfc4106 - 28))
+
+        mtu "${ns_a}"  veth_A-R1 ${veth_mtu}
+        mtu "${ns_r1}" veth_R1-A ${veth_mtu}
+        mtu "${ns_b}"  veth_B-R1 ${veth_mtu}
+        mtu "${ns_r1}" veth_R1-B ${veth_mtu}
+
+       mtu "${ns_a}" vti4_a ${vti_mtu}
+       mtu "${ns_b}" vti4_b ${vti_mtu}
+
+       # Send DF packet without exceeding link layer MTU, check that no
+       # exception is created
+       run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s ${ping_payload} ${tunnel4_b_addr}
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
+       check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1
+
+       # Now decrease link layer MTU by 8 bytes on R1, check that exception is created
+       # with the right PMTU value
+        mtu "${ns_r1}" veth_R1-B $((veth_mtu - 8))
+       run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((ping_payload)) ${tunnel4_b_addr}
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
+       check_pmtu_value "$((esp_payload_rfc4106 - 8))" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106)))"
+}
+
+test_pmtu_vti6_udp_routed_exception() {
+       setup namespaces routing vti6routed xfrm6udprouted || return $ksft_skip
+       trace "${ns_a}" veth_A-R1    "${ns_b}" veth_B-R1 \
+             "${ns_a}" vti6_a       "${ns_b}" vti6_b
+
+       veth_mtu=1500
+       vti_mtu=$((veth_mtu - 40))
+
+       #                                UDP   SPI   SN   IV  ICV   pad length   next header
+       esp_payload_rfc4106=$((vti_mtu - 8   - 4   - 4  - 8 - 16  - 1          - 1))
+       ping_payload=$((esp_payload_rfc4106 - 48))
+
+        mtu "${ns_a}"  veth_A-R1 ${veth_mtu}
+        mtu "${ns_r1}" veth_R1-A ${veth_mtu}
+        mtu "${ns_b}"  veth_B-R1 ${veth_mtu}
+        mtu "${ns_r1}" veth_R1-B ${veth_mtu}
+
+       # mtu "${ns_a}" vti6_a ${vti_mtu}
+       # mtu "${ns_b}" vti6_b ${vti_mtu}
+
+       run_cmd ${ns_a} ${ping6} -q -M want -i 0.1 -w 1 -s ${ping_payload} ${tunnel6_b_addr}
+
+       # Check that exception was not created
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
+       check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1
+
+       # Now decrease link layer MTU by 8 bytes on R1, check that exception is created
+       # with the right PMTU value
+        mtu "${ns_r1}" veth_R1-B $((veth_mtu - 8))
+       run_cmd ${ns_a} ${ping6} -q -M want -i 0.1 -w 1 -s $((ping_payload)) ${tunnel6_b_addr}
+       pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
+       check_pmtu_value "$((esp_payload_rfc4106 - 8))" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106)))"
+
+}
+
 test_pmtu_vti4_default_mtu() {
        setup namespaces veth vti4 || return $ksft_skip