2 # SPDX-License-Identifier: GPL-2.0
4 # Check that route PMTU values match expectations, and that initial device MTU
5 # values are assigned correctly
7 # Tests currently implemented:
9 # - pmtu_vti4_exception
10 # Set up vti tunnel on top of veth, with xfrm states and policies, in two
11 # namespaces with matching endpoints. Check that route exception is not
12 # created if link layer MTU is not exceeded, then exceed it and check that
13 # exception is created with the expected PMTU. The approach described
14 # below for IPv6 doesn't apply here, because, on IPv4, administrative MTU
15 # changes alone won't affect PMTU
17 # - pmtu_vti6_exception
18 # Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
19 # namespaces with matching endpoints. Check that route exception is
20 # created by exceeding link layer MTU with ping to other endpoint. Then
21 # decrease and increase MTU of tunnel, checking that route exception PMTU
24 # - pmtu_vti4_default_mtu
25 # Set up vti4 tunnel on top of veth, in two namespaces with matching
26 # endpoints. Check that MTU assigned to vti interface is the MTU of the
27 # lower layer (veth) minus additional lower layer headers (zero, for veth)
28 # minus IPv4 header length
30 # - pmtu_vti6_default_mtu
31 # Same as above, for IPv6
33 # - pmtu_vti4_link_add_mtu
34 # Set up vti4 interface passing MTU value at link creation, check MTU is
35 # configured, and that link is not created with invalid MTU values
37 # - pmtu_vti6_link_add_mtu
38 # Same as above, for IPv6
40 # - pmtu_vti6_link_change_mtu
41 # Set up two dummy interfaces with different MTUs, create a vti6 tunnel
42 # and check that configured MTU is used on link creation and changes, and
43 # that MTU is properly calculated instead when MTU is not configured from
46 # Kselftest framework requirement - SKIP code is 4.
50 pmtu_vti6_exception vti6: PMTU exceptions
51 pmtu_vti4_exception vti4: PMTU exceptions
52 pmtu_vti4_default_mtu vti4: default MTU assignment
53 pmtu_vti6_default_mtu vti6: default MTU assignment
54 pmtu_vti4_link_add_mtu vti4: MTU setting on link creation
55 pmtu_vti6_link_add_mtu vti6: MTU setting on link creation
56 pmtu_vti6_link_change_mtu vti6: MTU changes on link changes"
58 NS_A
="ns-$(mktemp -u XXXXXX)"
59 NS_B
="ns-$(mktemp -u XXXXXX)"
60 ns_a
="ip netns exec ${NS_A}"
61 ns_b
="ip netns exec ${NS_B}"
63 veth4_a_addr
="192.168.1.1"
64 veth4_b_addr
="192.168.1.2"
66 veth6_a_addr
="fd00:1::a"
67 veth6_b_addr
="fd00:1::b"
70 vti4_a_addr
="192.168.2.1"
71 vti4_b_addr
="192.168.2.2"
73 vti6_a_addr
="fd00:2::a"
74 vti6_b_addr
="fd00:2::b"
77 dummy6_0_addr
="fc00:1000::0"
78 dummy6_1_addr
="fc00:1001::0"
85 err_buf
="${err_buf}${1}
95 ip netns add
${NS_A} ||
return 1
100 ${ns_a} ip link add veth_a
type veth peer name veth_b ||
return 1
101 ${ns_a} ip link
set veth_b netns
${NS_B}
103 ${ns_a} ip addr add ${veth4_a_addr}/${veth4_mask} dev veth_a
104 ${ns_b} ip addr add ${veth4_b_addr}/${veth4_mask} dev veth_b
106 ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
107 ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
109 ${ns_a} ip link
set veth_a up
110 ${ns_b} ip link
set veth_b up
121 [ ${proto} -eq 6 ] && vti_type
="vti6" || vti_type
="vti"
123 ${ns_a} ip link add vti${proto}_a type ${vti_type} local ${veth_a_addr} remote ${veth_b_addr} key
10 ||
return 1
124 ${ns_b} ip link add vti${proto}_b type ${vti_type} local ${veth_b_addr} remote ${veth_a_addr} key
10
126 ${ns_a} ip addr add ${vti_a_addr}/${vti_mask} dev vti${proto}_a
127 ${ns_b} ip addr add ${vti_b_addr}/${vti_mask} dev vti${proto}_b
129 ${ns_a} ip link
set vti
${proto}_a up
130 ${ns_b} ip link
set vti
${proto}_b up
136 setup_vti
4 ${veth4_a_addr} ${veth4_b_addr} ${vti4_a_addr} ${vti4_b_addr} ${vti4_mask}
140 setup_vti
6 ${veth6_a_addr} ${veth6_b_addr} ${vti6_a_addr} ${vti6_b_addr} ${vti6_mask}
148 ${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
149 ${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
150 ${ns_a} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel
151 ${ns_a} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel
153 ${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
154 ${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
155 ${ns_b} ip -${proto} xfrm policy add dir out mark 10 tmpl src ${veth_b_addr} dst ${veth_a_addr} proto esp mode tunnel
156 ${ns_b} ip -${proto} xfrm policy add dir in mark 10 tmpl src ${veth_a_addr} dst ${veth_b_addr} proto esp mode tunnel
160 setup_xfrm
4 ${veth4_a_addr} ${veth4_b_addr}
164 setup_xfrm
6 ${veth6_a_addr} ${veth6_b_addr}
168 [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip
172 eval setup_
${arg} || { echo " ${arg} not supported"; return 1; }
177 [ ${cleanup_done} -eq 1 ] && return
178 ip netns del
${NS_A} 2 > /dev
/null
179 ip netns del
${NS_B} 2 > /dev
/null
188 ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
195 for i
in ${input}; do
196 [ ${next} -eq 1 ] && echo "${i}" && return
197 [ "${i}" = "mtu" ] && next
=1
205 ${ns_cmd} ip link show dev
"${name}"
212 mtu_parse
"$(link_get "${ns_cmd}" ${name})"
215 route_get_dst_exception
() {
219 ${ns_cmd} ip route get
"${dst}"
222 route_get_dst_pmtu_from_exception
() {
226 mtu_parse
"$(route_get_dst_exception "${ns_cmd}" ${dst})"
229 test_pmtu_vti4_exception
() {
230 setup namespaces veth vti4 xfrm4 ||
return 2
233 vti_mtu
=$
((veth_mtu
- 20))
235 # SPI SN IV ICV pad length next header
236 esp_payload_rfc4106
=$
((vti_mtu
- 4 - 4 - 8 - 16 - 1 - 1))
237 ping_payload
=$
((esp_payload_rfc4106
- 28))
239 mtu
"${ns_a}" veth_a
${veth_mtu}
240 mtu
"${ns_b}" veth_b
${veth_mtu}
241 mtu
"${ns_a}" vti4_a
${vti_mtu}
242 mtu
"${ns_b}" vti4_b
${vti_mtu}
244 # Send DF packet without exceeding link layer MTU, check that no
245 # exception is created
246 ${ns_a} ping -q -M want -i 0.1 -w 2 -s ${ping_payload} ${vti4_b_addr} > /dev
/null
247 pmtu
="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
248 if [ "${pmtu}" != "" ]; then
249 err
" unexpected exception created with PMTU ${pmtu} for IP payload length ${esp_payload_rfc4106}"
253 # Now exceed link layer MTU by one byte, check that exception is created
254 ${ns_a} ping -q -M want
-i 0.1 -w 2 -s $
((ping_payload
+ 1)) ${vti4_b_addr} > /dev
/null
255 pmtu
="$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti4_b_addr})"
256 if [ "${pmtu}" = "" ]; then
257 err
" exception not created for IP payload length $((esp_payload_rfc4106 + 1))"
261 # ...with the right PMTU value
262 if [ ${pmtu} -ne ${esp_payload_rfc4106} ]; then
263 err
" wrong PMTU ${pmtu} in exception, expected: ${esp_payload_rfc4106}"
268 test_pmtu_vti6_exception
() {
269 setup namespaces veth vti6 xfrm6 ||
return 2
272 # Create route exception by exceeding link layer MTU
273 mtu
"${ns_a}" veth_a
4000
274 mtu
"${ns_b}" veth_b
4000
275 mtu
"${ns_a}" vti6_a
5000
276 mtu
"${ns_b}" vti6_b
5000
277 ${ns_a} ping6
-q -i 0.1 -w 2 -s 60000 ${vti6_b_addr} > /dev
/null
279 # Check that exception was created
280 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" = "" ]; then
281 err
" tunnel exceeding link layer MTU didn't create route exception"
285 # Decrease tunnel MTU, check for PMTU decrease in route exception
286 mtu
"${ns_a}" vti6_a
3000
288 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 3000 ]; then
289 err
" decreasing tunnel MTU didn't decrease route exception PMTU"
293 # Increase tunnel MTU, check for PMTU increase in route exception
294 mtu
"${ns_a}" vti6_a
9000
295 if [ "$(route_get_dst_pmtu_from_exception "${ns_a}" ${vti6_b_addr})" -ne 9000 ]; then
296 err
" increasing tunnel MTU didn't increase route exception PMTU"
303 test_pmtu_vti4_default_mtu
() {
304 setup namespaces veth vti4 ||
return 2
306 # Check that MTU of vti device is MTU of veth minus IPv4 header length
307 veth_mtu
="$(link_get_mtu "${ns_a}" veth_a)"
308 vti4_mtu
="$(link_get_mtu "${ns_a}" vti4_a)"
309 if [ $
((veth_mtu
- vti4_mtu
)) -ne 20 ]; then
310 err
" vti MTU ${vti4_mtu} is not veth MTU ${veth_mtu} minus IPv4 header length"
315 test_pmtu_vti6_default_mtu
() {
316 setup namespaces veth vti6 ||
return 2
318 # Check that MTU of vti device is MTU of veth minus IPv6 header length
319 veth_mtu
="$(link_get_mtu "${ns_a}" veth_a)"
320 vti6_mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
321 if [ $
((veth_mtu
- vti6_mtu
)) -ne 40 ]; then
322 err
" vti MTU ${vti6_mtu} is not veth MTU ${veth_mtu} minus IPv6 header length"
327 test_pmtu_vti4_link_add_mtu
() {
328 setup namespaces ||
return 2
330 ${ns_a} ip link add vti4_a type vti local ${veth4_a_addr} remote ${veth4_b_addr} key
10
331 [ $?
-ne 0 ] && err
" vti not supported" && return 2
332 ${ns_a} ip link del vti4_a
338 # Check invalid values first
339 for v
in $
((min
- 1)) $
((max
+ 1)); do
340 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key
10 2>/dev
/null
341 # This can fail, or MTU can be adjusted to a proper value
342 [ $?
-ne 0 ] && continue
343 mtu
="$(link_get_mtu "${ns_a}" vti4_a)"
344 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
345 err
" vti tunnel created with invalid MTU ${mtu}"
348 ${ns_a} ip link del vti4_a
351 # Now check valid values
352 for v
in ${min} 1300 ${max}; do
353 ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key
10
354 mtu
="$(link_get_mtu "${ns_a}" vti4_a)"
355 ${ns_a} ip link del vti4_a
356 if [ "${mtu}" != "${v}" ]; then
357 err
" vti MTU ${mtu} doesn't match configured value ${v}"
365 test_pmtu_vti6_link_add_mtu
() {
366 setup namespaces ||
return 2
368 ${ns_a} ip link add vti6_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key
10
369 [ $?
-ne 0 ] && err
" vti6 not supported" && return 2
370 ${ns_a} ip link del vti6_a
374 min
=68 # vti6 can carry IPv4 packets too
376 # Check invalid values first
377 for v
in $
((min
- 1)) $
((max
+ 1)); do
378 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key
10 2>/dev
/null
379 # This can fail, or MTU can be adjusted to a proper value
380 [ $?
-ne 0 ] && continue
381 mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
382 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
383 err
" vti6 tunnel created with invalid MTU ${v}"
386 ${ns_a} ip link del vti6_a
389 # Now check valid values
390 for v
in 68 1280 1300 $
((65535 - 40)); do
391 ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key
10
392 mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
393 ${ns_a} ip link del vti6_a
394 if [ "${mtu}" != "${v}" ]; then
395 err
" vti6 MTU ${mtu} doesn't match configured value ${v}"
403 test_pmtu_vti6_link_change_mtu
() {
404 setup namespaces ||
return 2
406 ${ns_a} ip link add dummy0 mtu
1500 type dummy
407 [ $?
-ne 0 ] && err
" dummy not supported" && return 2
408 ${ns_a} ip link add dummy1 mtu
3000 type dummy
409 ${ns_a} ip link
set dummy0 up
410 ${ns_a} ip link
set dummy1 up
412 ${ns_a} ip addr add ${dummy6_0_addr}/${dummy6_mask} dev dummy0
413 ${ns_a} ip addr add ${dummy6_1_addr}/${dummy6_mask} dev dummy1
417 # Create vti6 interface bound to device, passing MTU, check it
418 ${ns_a} ip link add vti6_a mtu 1300 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr}
419 mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
420 if [ ${mtu} -ne 1300 ]; then
421 err
" vti6 MTU ${mtu} doesn't match configured value 1300"
425 # Move to another device with different MTU, without passing MTU, check
427 ${ns_a} ip link set vti6_a type vti6 remote ${dummy6_1_addr} local ${dummy6_1_addr}
428 mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
429 if [ ${mtu} -ne $
((3000 - 40)) ]; then
430 err
" vti MTU ${mtu} is not dummy MTU 3000 minus IPv6 header length"
434 # Move it back, passing MTU, check MTU is not overridden
435 ${ns_a} ip link set vti6_a mtu 1280 type vti6 remote ${dummy6_0_addr} local ${dummy6_0_addr}
436 mtu
="$(link_get_mtu "${ns_a}" vti6_a)"
437 if [ ${mtu} -ne 1280 ]; then
438 err
" vti6 MTU ${mtu} doesn't match configured value 1280"
451 for t
in ${tests}; do
452 [ $desc -eq 0 ] && name
="${t}" && desc
=1 && continue || desc
=0
460 if [ $ret -eq 0 ]; then
461 printf "TEST: %-60s [ OK ]\n" "${t}"
462 elif [ $ret -eq 1 ]; then
463 printf "TEST: %-60s [FAIL]\n" "${t}"
466 elif [ $ret -eq 2 ]; then
467 printf "TEST: %-60s [SKIP]\n" "${t}"
471 [ $?
-ne 0 ] && exitcode
=1