OSDN Git Service

selftests: pmtu: Introduce support for multiple tests
[tomoyo/tomoyo-test1.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 # - 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 tests="
16         pmtu_vti6_exception     vti6: PMTU exceptions"
17
18 NS_A="ns-$(mktemp -u XXXXXX)"
19 NS_B="ns-$(mktemp -u XXXXXX)"
20 ns_a="ip netns exec ${NS_A}"
21 ns_b="ip netns exec ${NS_B}"
22
23 veth6_a_addr="fd00:1::a"
24 veth6_b_addr="fd00:1::b"
25 veth6_mask="64"
26
27 vti6_a_addr="fd00:2::a"
28 vti6_b_addr="fd00:2::b"
29 vti6_mask="64"
30
31 cleanup_done=1
32 err_buf=
33
34 err() {
35         err_buf="${err_buf}${1}
36 "
37 }
38
39 err_flush() {
40         echo -n "${err_buf}"
41         err_buf=
42 }
43
44 setup_namespaces() {
45         ip netns add ${NS_A} || return 1
46         ip netns add ${NS_B}
47 }
48
49 setup_veth() {
50         ${ns_a} ip link add veth_a type veth peer name veth_b || return 1
51         ${ns_a} ip link set veth_b netns ${NS_B}
52
53         ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
54         ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
55
56         ${ns_a} ip link set veth_a up
57         ${ns_b} ip link set veth_b up
58 }
59
60 setup_vti6() {
61         ${ns_a} ip link add vti_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10 || return 1
62         ${ns_b} ip link add vti_b type vti6 local ${veth6_b_addr} remote ${veth6_a_addr} key 10
63
64         ${ns_a} ip addr add ${vti6_a_addr}/${vti6_mask} dev vti_a
65         ${ns_b} ip addr add ${vti6_b_addr}/${vti6_mask} dev vti_b
66
67         ${ns_a} ip link set vti_a up
68         ${ns_b} ip link set vti_b up
69
70         sleep 1
71 }
72
73 setup_xfrm() {
74         ${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 1
75         ${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
76         ${ns_a} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
77         ${ns_a} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
78
79         ${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
80         ${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
81         ${ns_b} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
82         ${ns_b} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
83 }
84
85 setup() {
86         [ "$(id -u)" -ne 0 ] && echo "  need to run as root" && return 1
87
88         cleanup_done=0
89         for arg do
90                 eval setup_${arg} || { echo "  ${arg} not supported"; return 1; }
91         done
92 }
93
94 cleanup() {
95         [ ${cleanup_done} -eq 1 ] && return
96         ip netns del ${NS_A} 2 > /dev/null
97         ip netns del ${NS_B} 2 > /dev/null
98         cleanup_done=1
99 }
100
101 mtu() {
102         ns_cmd="${1}"
103         dev="${2}"
104         mtu="${3}"
105
106         ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
107 }
108
109 mtu_parse() {
110         input="${1}"
111
112         next=0
113         for i in ${input}; do
114                 [ ${next} -eq 1 ] && echo "${i}" && return
115                 [ "${i}" = "mtu" ] && next=1
116         done
117 }
118
119 route_get_dst_exception() {
120         ns_cmd="${1}"
121         dst="${2}"
122
123         ${ns_cmd} ip route get "${dst}"
124 }
125
126 route_get_dst_pmtu_from_exception() {
127         ns_cmd="${1}"
128         dst="${2}"
129
130         mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})"
131 }
132
133 test_pmtu_vti6_exception() {
134         setup namespaces veth vti6 xfrm || return 2
135         fail=0
136
137         # Create route exception by exceeding link layer MTU
138         mtu "${ns_a}" veth_a 4000
139         mtu "${ns_b}" veth_b 4000
140         mtu "${ns_a}" vti_a 5000
141         mtu "${ns_b}" vti_b 5000
142         ${ns_a} ping6 -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null
143
144         # Check that exception was created
145         if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" = "" ]; then
146                 err "  tunnel exceeding link layer MTU didn't create route exception"
147                 return 1
148         fi
149
150         # Decrease tunnel MTU, check for PMTU decrease in route exception
151         mtu "${ns_a}" vti_a 3000
152
153         if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 3000 ]; then
154                 err "  decreasing tunnel MTU didn't decrease route exception PMTU"
155                 fail=1
156         fi
157
158         # Increase tunnel MTU, check for PMTU increase in route exception
159         mtu "${ns_a}" vti_a 9000
160         if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 9000 ]; then
161                 err "  increasing tunnel MTU didn't increase route exception PMTU"
162                 fail=1
163         fi
164
165         return ${fail}
166 }
167
168 trap cleanup EXIT
169
170 exitcode=0
171 desc=0
172 IFS="   
173 "
174 for t in ${tests}; do
175         [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0
176
177         (
178                 unset IFS
179                 eval test_${name}
180                 ret=$?
181                 cleanup
182
183                 if [ $ret -eq 0 ]; then
184                         printf "TEST: %-60s  [ OK ]\n" "${t}"
185                 elif [ $ret -eq 1 ]; then
186                         printf "TEST: %-60s  [FAIL]\n" "${t}"
187                         err_flush
188                         exit 1
189                 elif [ $ret -eq 2 ]; then
190                         printf "TEST: %-60s  [SKIP]\n" "${t}"
191                         err_flush
192                 fi
193         )
194         [ $? -ne 0 ] && exitcode=1
195 done
196
197 exit ${exitcode}