blob: 5d9af22b360a13b833fe47e4f8acc0afb55838a7 [file] [log] [blame]
Stefano Briviod1f1b9c2018-03-06 22:16:27 +01001#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
Stefano Brivioa41c7892018-03-17 02:31:42 +01004# Check that route PMTU values match expectations, and that initial device MTU
5# values are assigned correctly
Stefano Briviod1f1b9c2018-03-06 22:16:27 +01006#
7# Tests currently implemented:
8#
Stefano Brivio36455bd2018-03-17 02:31:41 +01009# - pmtu_vti6_exception
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010010# Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
11# namespaces with matching endpoints. Check that route exception is
12# created by exceeding link layer MTU with ping to other endpoint. Then
13# decrease and increase MTU of tunnel, checking that route exception PMTU
14# changes accordingly
Stefano Brivioa41c7892018-03-17 02:31:42 +010015#
16# - pmtu_vti4_default_mtu
17# Set up vti4 tunnel on top of veth, in two namespaces with matching
18# endpoints. Check that MTU assigned to vti interface is the MTU of the
19# lower layer (veth) minus additional lower layer headers (zero, for veth)
20# minus IPv4 header length
Stefano Brivio35b49422018-03-17 02:31:43 +010021#
22# - pmtu_vti6_default_mtu
23# Same as above, for IPv6
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010024
Stefano Brivio36455bd2018-03-17 02:31:41 +010025tests="
Stefano Brivioa41c7892018-03-17 02:31:42 +010026 pmtu_vti6_exception vti6: PMTU exceptions
Stefano Brivio35b49422018-03-17 02:31:43 +010027 pmtu_vti4_default_mtu vti4: default MTU assignment
28 pmtu_vti6_default_mtu vti6: default MTU assignment"
Stefano Brivio36455bd2018-03-17 02:31:41 +010029
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010030NS_A="ns-$(mktemp -u XXXXXX)"
31NS_B="ns-$(mktemp -u XXXXXX)"
32ns_a="ip netns exec ${NS_A}"
33ns_b="ip netns exec ${NS_B}"
34
Stefano Brivioa41c7892018-03-17 02:31:42 +010035veth4_a_addr="192.168.1.1"
36veth4_b_addr="192.168.1.2"
37veth4_mask="24"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010038veth6_a_addr="fd00:1::a"
39veth6_b_addr="fd00:1::b"
40veth6_mask="64"
41
Stefano Brivioa41c7892018-03-17 02:31:42 +010042vti4_a_addr="192.168.2.1"
43vti4_b_addr="192.168.2.2"
44vti4_mask="24"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010045vti6_a_addr="fd00:2::a"
46vti6_b_addr="fd00:2::b"
47vti6_mask="64"
48
Stefano Brivio36455bd2018-03-17 02:31:41 +010049cleanup_done=1
50err_buf=
51
52err() {
53 err_buf="${err_buf}${1}
54"
55}
56
57err_flush() {
58 echo -n "${err_buf}"
59 err_buf=
60}
61
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010062setup_namespaces() {
Stefano Brivio380e29a2018-03-17 02:31:38 +010063 ip netns add ${NS_A} || return 1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010064 ip netns add ${NS_B}
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010065}
66
67setup_veth() {
Stefano Brivio380e29a2018-03-17 02:31:38 +010068 ${ns_a} ip link add veth_a type veth peer name veth_b || return 1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010069 ${ns_a} ip link set veth_b netns ${NS_B}
70
Stefano Brivioa41c7892018-03-17 02:31:42 +010071 ${ns_a} ip addr add ${veth4_a_addr}/${veth4_mask} dev veth_a
72 ${ns_b} ip addr add ${veth4_b_addr}/${veth4_mask} dev veth_b
73
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010074 ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
75 ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
76
77 ${ns_a} ip link set veth_a up
78 ${ns_b} ip link set veth_b up
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010079}
80
Stefano Brivioa41c7892018-03-17 02:31:42 +010081setup_vti() {
82 proto=${1}
83 veth_a_addr="${2}"
84 veth_b_addr="${3}"
85 vti_a_addr="${4}"
86 vti_b_addr="${5}"
87 vti_mask=${6}
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010088
Stefano Brivioa41c7892018-03-17 02:31:42 +010089 [ ${proto} -eq 6 ] && vti_type="vti6" || vti_type="vti"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010090
Stefano Brivioa41c7892018-03-17 02:31:42 +010091 ${ns_a} ip link add vti${proto}_a type ${vti_type} local ${veth_a_addr} remote ${veth_b_addr} key 10 || return 1
92 ${ns_b} ip link add vti${proto}_b type ${vti_type} local ${veth_b_addr} remote ${veth_a_addr} key 10
93
94 ${ns_a} ip addr add ${vti_a_addr}/${vti_mask} dev vti${proto}_a
95 ${ns_b} ip addr add ${vti_b_addr}/${vti_mask} dev vti${proto}_b
96
97 ${ns_a} ip link set vti${proto}_a up
98 ${ns_b} ip link set vti${proto}_b up
Stefano Briviod1f1b9c2018-03-06 22:16:27 +010099
100 sleep 1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100101}
102
Stefano Brivioa41c7892018-03-17 02:31:42 +0100103setup_vti4() {
104 setup_vti 4 ${veth4_a_addr} ${veth4_b_addr} ${vti4_a_addr} ${vti4_b_addr} ${vti4_mask}
105}
106
107setup_vti6() {
108 setup_vti 6 ${veth6_a_addr} ${veth6_b_addr} ${vti6_a_addr} ${vti6_b_addr} ${vti6_mask}
109}
110
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100111setup_xfrm() {
Stefano Brivio380e29a2018-03-17 02:31:38 +0100112 ${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
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100113 ${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
114 ${ns_a} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
115 ${ns_a} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
116
117 ${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
118 ${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
119 ${ns_b} ip -6 xfrm policy add dir out mark 10 tmpl src ${veth6_b_addr} dst ${veth6_a_addr} proto esp mode tunnel
120 ${ns_b} ip -6 xfrm policy add dir in mark 10 tmpl src ${veth6_a_addr} dst ${veth6_b_addr} proto esp mode tunnel
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100121}
122
123setup() {
Stefano Brivio36455bd2018-03-17 02:31:41 +0100124 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return 1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100125
Stefano Brivio36455bd2018-03-17 02:31:41 +0100126 cleanup_done=0
127 for arg do
128 eval setup_${arg} || { echo " ${arg} not supported"; return 1; }
129 done
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100130}
131
132cleanup() {
Stefano Brivio36455bd2018-03-17 02:31:41 +0100133 [ ${cleanup_done} -eq 1 ] && return
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100134 ip netns del ${NS_A} 2 > /dev/null
135 ip netns del ${NS_B} 2 > /dev/null
Stefano Brivio36455bd2018-03-17 02:31:41 +0100136 cleanup_done=1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100137}
138
139mtu() {
140 ns_cmd="${1}"
141 dev="${2}"
142 mtu="${3}"
143
144 ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
145}
146
Stefano Briviof2c929f2018-03-17 02:31:40 +0100147mtu_parse() {
148 input="${1}"
149
150 next=0
151 for i in ${input}; do
152 [ ${next} -eq 1 ] && echo "${i}" && return
153 [ "${i}" = "mtu" ] && next=1
154 done
155}
156
Stefano Brivioa41c7892018-03-17 02:31:42 +0100157link_get() {
158 ns_cmd="${1}"
159 name="${2}"
160
161 ${ns_cmd} ip link show dev "${name}"
162}
163
164link_get_mtu() {
165 ns_cmd="${1}"
166 name="${2}"
167
168 mtu_parse "$(link_get "${ns_cmd}" ${name})"
169}
170
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100171route_get_dst_exception() {
Stefano Brivio822d2f82018-03-17 02:31:39 +0100172 ns_cmd="${1}"
173 dst="${2}"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100174
Stefano Brivio822d2f82018-03-17 02:31:39 +0100175 ${ns_cmd} ip route get "${dst}"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100176}
177
178route_get_dst_pmtu_from_exception() {
Stefano Brivio822d2f82018-03-17 02:31:39 +0100179 ns_cmd="${1}"
180 dst="${2}"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100181
Stefano Briviof2c929f2018-03-17 02:31:40 +0100182 mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})"
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100183}
184
185test_pmtu_vti6_exception() {
Stefano Brivio36455bd2018-03-17 02:31:41 +0100186 setup namespaces veth vti6 xfrm || return 2
187 fail=0
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100188
189 # Create route exception by exceeding link layer MTU
190 mtu "${ns_a}" veth_a 4000
191 mtu "${ns_b}" veth_b 4000
Stefano Brivioa41c7892018-03-17 02:31:42 +0100192 mtu "${ns_a}" vti6_a 5000
193 mtu "${ns_b}" vti6_b 5000
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100194 ${ns_a} ping6 -q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev/null
195
196 # Check that exception was created
Stefano Brivio822d2f82018-03-17 02:31:39 +0100197 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" = "" ]; then
Stefano Brivio36455bd2018-03-17 02:31:41 +0100198 err " tunnel exceeding link layer MTU didn't create route exception"
199 return 1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100200 fi
201
202 # Decrease tunnel MTU, check for PMTU decrease in route exception
Stefano Brivioa41c7892018-03-17 02:31:42 +0100203 mtu "${ns_a}" vti6_a 3000
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100204
Stefano Brivio822d2f82018-03-17 02:31:39 +0100205 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 3000 ]; then
Stefano Brivio36455bd2018-03-17 02:31:41 +0100206 err " decreasing tunnel MTU didn't decrease route exception PMTU"
207 fail=1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100208 fi
209
210 # Increase tunnel MTU, check for PMTU increase in route exception
Stefano Brivioa41c7892018-03-17 02:31:42 +0100211 mtu "${ns_a}" vti6_a 9000
Stefano Brivio822d2f82018-03-17 02:31:39 +0100212 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 9000 ]; then
Stefano Brivio36455bd2018-03-17 02:31:41 +0100213 err " increasing tunnel MTU didn't increase route exception PMTU"
214 fail=1
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100215 fi
216
Stefano Brivio36455bd2018-03-17 02:31:41 +0100217 return ${fail}
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100218}
219
Stefano Brivioa41c7892018-03-17 02:31:42 +0100220test_pmtu_vti4_default_mtu() {
221 setup namespaces veth vti4 || return 2
222
223 # Check that MTU of vti device is MTU of veth minus IPv4 header length
224 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
225 vti4_mtu="$(link_get_mtu "${ns_a}" vti4_a)"
226 if [ $((veth_mtu - vti4_mtu)) -ne 20 ]; then
227 err " vti MTU ${vti4_mtu} is not veth MTU ${veth_mtu} minus IPv4 header length"
228 return 1
229 fi
230}
231
Stefano Brivio35b49422018-03-17 02:31:43 +0100232test_pmtu_vti6_default_mtu() {
233 setup namespaces veth vti6 || return 2
234
235 # Check that MTU of vti device is MTU of veth minus IPv6 header length
236 veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
237 vti6_mtu="$(link_get_mtu "${ns_a}" vti6_a)"
238 if [ $((veth_mtu - vti6_mtu)) -ne 40 ]; then
239 err " vti MTU ${vti6_mtu} is not veth MTU ${veth_mtu} minus IPv6 header length"
240 return 1
241 fi
242}
243
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100244trap cleanup EXIT
245
Stefano Brivio36455bd2018-03-17 02:31:41 +0100246exitcode=0
247desc=0
248IFS="
249"
250for t in ${tests}; do
251 [ $desc -eq 0 ] && name="${t}" && desc=1 && continue || desc=0
Stefano Briviod1f1b9c2018-03-06 22:16:27 +0100252
Stefano Brivio36455bd2018-03-17 02:31:41 +0100253 (
254 unset IFS
255 eval test_${name}
256 ret=$?
257 cleanup
258
259 if [ $ret -eq 0 ]; then
260 printf "TEST: %-60s [ OK ]\n" "${t}"
261 elif [ $ret -eq 1 ]; then
262 printf "TEST: %-60s [FAIL]\n" "${t}"
263 err_flush
264 exit 1
265 elif [ $ret -eq 2 ]; then
266 printf "TEST: %-60s [SKIP]\n" "${t}"
267 err_flush
268 fi
269 )
270 [ $? -ne 0 ] && exitcode=1
271done
272
273exit ${exitcode}