selftests: net: Introduce first PMTU test
[linux-2.6-microblaze.git] / tools / testing / selftests / net / pmtu.sh
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # Check that route PMTU values match expectations
5 #
6 # Tests currently implemented:
7 #
8 # - test_pmtu_vti6_exception
9 #       Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
10 #       namespaces with matching endpoints. Check that route exception is
11 #       created by exceeding link layer MTU with ping to other endpoint. Then
12 #       decrease and increase MTU of tunnel, checking that route exception PMTU
13 #       changes accordingly
14
15 NS_A="ns-$(mktemp -u XXXXXX)"
16 NS_B="ns-$(mktemp -u XXXXXX)"
17 ns_a="ip netns exec ${NS_A}"
18 ns_b="ip netns exec ${NS_B}"
19
20 veth6_a_addr="fd00:1::a"
21 veth6_b_addr="fd00:1::b"
22 veth6_mask="64"
23
24 vti6_a_addr="fd00:2::a"
25 vti6_b_addr="fd00:2::b"
26 vti6_mask="64"
27
28 setup_namespaces() {
29         ip netns add ${NS_A} || return 0
30         ip netns add ${NS_B}
31
32         return 1
33 }
34
35 setup_veth() {
36         ${ns_a} ip link add veth_a type veth peer name veth_b || return 0
37         ${ns_a} ip link set veth_b netns ${NS_B}
38
39         ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
40         ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
41
42         ${ns_a} ip link set veth_a up
43         ${ns_b} ip link set veth_b up
44
45         return 1
46 }
47
48 setup_vti6() {
49         ${ns_a} ip link add vti_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 || return 0
50         ${ns_b} ip link add vti_b type vti6 local ${veth6_b_addr} remote ${veth6_a_addr} key 10
51
52         ${ns_a} ip addr add ${vti6_a_addr}/${vti6_mask} dev vti_a
53         ${ns_b} ip addr add ${vti6_b_addr}/${vti6_mask} dev vti_b
54
55         ${ns_a} ip link set vti_a up
56         ${ns_b} ip link set vti_b up
57
58         sleep 1
59
60         return 1
61 }
62
63 setup_xfrm() {
64         ${ns_a} ip -6 xfrm state add src ${veth6_a_addr} dst ${veth6_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel || return 0
65         ${ns_a} ip -6 xfrm state add src ${veth6_b_addr} dst ${veth6_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
66         ${ns_a} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
67         ${ns_a} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
68
69         ${ns_b} ip -6 xfrm state add src ${veth6_a_addr} dst ${veth6_b_addr} spi 0x1000 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
70         ${ns_b} ip -6 xfrm state add src ${veth6_b_addr} dst ${veth6_a_addr} spi 0x1001 proto esp aead "rfc4106(gcm(aes))" 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode tunnel
71         ${ns_b} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
72         ${ns_b} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
73
74         return 1
75 }
76
77 setup() {
78         tunnel_type="$1"
79
80         [ "$(id -u)" -ne 0 ] && echo "SKIP: need to run as root" && exit 0
81
82         setup_namespaces && echo "SKIP: namespaces not supported" && exit 0
83         setup_veth && echo "SKIP: veth not supported" && exit 0
84
85         case ${tunnel_type} in
86         "vti6")
87                 setup_vti6 && echo "SKIP: vti6 not supported" && exit 0
88                 setup_xfrm && echo "SKIP: xfrm not supported" && exit 0
89                 ;;
90         *)
91                 ;;
92         esac
93 }
94
95 cleanup() {
96         ip netns del ${NS_A} 2 > /dev/null
97         ip netns del ${NS_B} 2 > /dev/null
98 }
99
100 mtu() {
101         ns_cmd="${1}"
102         dev="${2}"
103         mtu="${3}"
104
105         ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
106 }
107
108 route_get_dst_exception() {
109         dst="${1}"
110
111         ${ns_a} ip route get "${dst}"
112 }
113
114 route_get_dst_pmtu_from_exception() {
115         dst="${1}"
116
117         exception="$(route_get_dst_exception ${dst})"
118         next=0
119         for i in ${exception}; do
120                 [ ${next} -eq 1 ] && echo "${i}" && return
121                 [ "${i}" = "mtu" ] && next=1
122         done
123 }
124
125 test_pmtu_vti6_exception() {
126         setup vti6
127
128         # Create route exception by exceeding link layer MTU
129         mtu "${ns_a}" veth_a 4000
130         mtu "${ns_b}" veth_b 4000
131         mtu "${ns_a}" vti_a 5000
132         mtu "${ns_b}" vti_b 5000
133         ${ns_a} ping6 -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null
134
135         # Check that exception was created
136         if [ "$(route_get_dst_pmtu_from_exception ${vti6_b_addr})" = "" ]; then
137                 echo "FAIL: Tunnel exceeding link layer MTU didn't create route exception"
138                 exit 1
139         fi
140
141         # Decrease tunnel MTU, check for PMTU decrease in route exception
142         mtu "${ns_a}" vti_a 3000
143
144         if [ "$(route_get_dst_pmtu_from_exception ${vti6_b_addr})" -ne 3000 ]; then
145                 echo "FAIL: Decreasing tunnel MTU didn't decrease route exception PMTU"
146                 exit 1
147         fi
148
149         # Increase tunnel MTU, check for PMTU increase in route exception
150         mtu "${ns_a}" vti_a 9000
151         if [ "$(route_get_dst_pmtu_from_exception ${vti6_b_addr})" -ne 9000 ]; then
152                 echo "FAIL: Increasing tunnel MTU didn't increase route exception PMTU"
153                 exit 1
154         fi
155
156         echo "PASS"
157 }
158
159 trap cleanup EXIT
160
161 test_pmtu_vti6_exception
162
163 exit 0