Merge branch 'printk-rework' into for-linus
[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, and that initial device MTU
5 # values are assigned correctly
6 #
7 # Tests currently implemented:
8 #
9 # - pmtu_ipv4
10 #       Set up two namespaces, A and B, with two paths between them over routers
11 #       R1 and R2 (also implemented with namespaces), with different MTUs:
12 #
13 #         segment a_r1    segment b_r1          a_r1: 2000
14 #       .--------------R1--------------.        b_r1: 1400
15 #       A                               B       a_r2: 2000
16 #       '--------------R2--------------'        b_r2: 1500
17 #         segment a_r2    segment b_r2
18 #
19 #       Check that PMTU exceptions with the correct PMTU are created. Then
20 #       decrease and increase the MTU of the local link for one of the paths,
21 #       A to R1, checking that route exception PMTU changes accordingly over
22 #       this path. Also check that locked exceptions are created when an ICMP
23 #       message advertising a PMTU smaller than net.ipv4.route.min_pmtu is
24 #       received
25 #
26 # - pmtu_ipv6
27 #       Same as pmtu_ipv4, except for locked PMTU tests, using IPv6
28 #
29 # - pmtu_ipv4_vxlan4_exception
30 #       Set up the same network topology as pmtu_ipv4, create a VXLAN tunnel
31 #       over IPv4 between A and B, routed via R1. On the link between R1 and B,
32 #       set a MTU lower than the VXLAN MTU and the MTU on the link between A and
33 #       R1. Send IPv4 packets, exceeding the MTU between R1 and B, over VXLAN
34 #       from A to B and check that the PMTU exception is created with the right
35 #       value on A
36 #
37 # - pmtu_ipv6_vxlan4_exception
38 #       Same as pmtu_ipv4_vxlan4_exception, but send IPv6 packets from A to B
39 #
40 # - pmtu_ipv4_vxlan6_exception
41 #       Same as pmtu_ipv4_vxlan4_exception, but use IPv6 transport from A to B
42 #
43 # - pmtu_ipv6_vxlan6_exception
44 #       Same as pmtu_ipv4_vxlan6_exception, but send IPv6 packets from A to B
45 #
46 # - pmtu_ipv4_geneve4_exception
47 #       Same as pmtu_ipv4_vxlan4_exception, but using a GENEVE tunnel instead of
48 #       VXLAN
49 #
50 # - pmtu_ipv6_geneve4_exception
51 #       Same as pmtu_ipv6_vxlan4_exception, but using a GENEVE tunnel instead of
52 #       VXLAN
53 #
54 # - pmtu_ipv4_geneve6_exception
55 #       Same as pmtu_ipv4_vxlan6_exception, but using a GENEVE tunnel instead of
56 #       VXLAN
57 #
58 # - pmtu_ipv6_geneve6_exception
59 #       Same as pmtu_ipv6_vxlan6_exception, but using a GENEVE tunnel instead of
60 #       VXLAN
61 #
62 # - pmtu_ipv{4,6}_br_vxlan{4,6}_exception
63 #       Set up three namespaces, A, B, and C, with routing between A and B over
64 #       R1. R2 is unused in these tests. A has a veth connection to C, and is
65 #       connected to B via a VXLAN endpoint, which is directly bridged to C.
66 #       MTU on the B-R1 link is lower than other MTUs.
67 #
68 #       Check that both C and A are able to communicate with B over the VXLAN
69 #       tunnel, and that PMTU exceptions with the correct values are created.
70 #
71 #                         segment a_r1    segment b_r1            b_r1: 4000
72 #                       .--------------R1--------------.    everything
73 #          C---veth     A                               B         else: 5000
74 #               ' bridge                                |
75 #                   '---- - - - - - VXLAN - - - - - - - '
76 #
77 # - pmtu_ipv{4,6}_br_geneve{4,6}_exception
78 #       Same as pmtu_ipv{4,6}_br_vxlan{4,6}_exception, with a GENEVE tunnel
79 #       instead.
80 #
81 # - pmtu_ipv{4,6}_ovs_vxlan{4,6}_exception
82 #       Set up two namespaces, B, and C, with routing between the init namespace
83 #       and B over R1. A and R2 are unused in these tests. The init namespace
84 #       has a veth connection to C, and is connected to B via a VXLAN endpoint,
85 #       which is handled by Open vSwitch and bridged to C. MTU on the B-R1 link
86 #       is lower than other MTUs.
87 #
88 #       Check that C is able to communicate with B over the VXLAN tunnel, and
89 #       that PMTU exceptions with the correct values are created.
90 #
91 #                         segment a_r1    segment b_r1            b_r1: 4000
92 #                       .--------------R1--------------.    everything
93 #          C---veth    init                             B         else: 5000
94 #               '- ovs                                  |
95 #                   '---- - - - - - VXLAN - - - - - - - '
96 #
97 # - pmtu_ipv{4,6}_ovs_geneve{4,6}_exception
98 #       Same as pmtu_ipv{4,6}_ovs_vxlan{4,6}_exception, with a GENEVE tunnel
99 #       instead.
100 #
101 # - pmtu_ipv{4,6}_fou{4,6}_exception
102 #       Same as pmtu_ipv4_vxlan4, but using a direct IPv4/IPv6 encapsulation
103 #       (FoU) over IPv4/IPv6, instead of VXLAN
104 #
105 # - pmtu_ipv{4,6}_fou{4,6}_exception
106 #       Same as pmtu_ipv4_vxlan4, but using a generic UDP IPv4/IPv6
107 #       encapsulation (GUE) over IPv4/IPv6, instead of VXLAN
108 #
109 # - pmtu_ipv{4,6}_ipv{4,6}_exception
110 #       Same as pmtu_ipv4_vxlan4, but using a IPv4/IPv6 tunnel over IPv4/IPv6,
111 #       instead of VXLAN
112 #
113 # - pmtu_vti4_exception
114 #       Set up vti tunnel on top of veth, with xfrm states and policies, in two
115 #       namespaces with matching endpoints. Check that route exception is not
116 #       created if link layer MTU is not exceeded, then exceed it and check that
117 #       exception is created with the expected PMTU. The approach described
118 #       below for IPv6 doesn't apply here, because, on IPv4, administrative MTU
119 #       changes alone won't affect PMTU
120 #
121 # - pmtu_vti6_exception
122 #       Set up vti6 tunnel on top of veth, with xfrm states and policies, in two
123 #       namespaces with matching endpoints. Check that route exception is
124 #       created by exceeding link layer MTU with ping to other endpoint. Then
125 #       decrease and increase MTU of tunnel, checking that route exception PMTU
126 #       changes accordingly
127 #
128 # - pmtu_vti4_default_mtu
129 #       Set up vti4 tunnel on top of veth, in two namespaces with matching
130 #       endpoints. Check that MTU assigned to vti interface is the MTU of the
131 #       lower layer (veth) minus additional lower layer headers (zero, for veth)
132 #       minus IPv4 header length
133 #
134 # - pmtu_vti6_default_mtu
135 #       Same as above, for IPv6
136 #
137 # - pmtu_vti4_link_add_mtu
138 #       Set up vti4 interface passing MTU value at link creation, check MTU is
139 #       configured, and that link is not created with invalid MTU values
140 #
141 # - pmtu_vti6_link_add_mtu
142 #       Same as above, for IPv6
143 #
144 # - pmtu_vti6_link_change_mtu
145 #       Set up two dummy interfaces with different MTUs, create a vti6 tunnel
146 #       and check that configured MTU is used on link creation and changes, and
147 #       that MTU is properly calculated instead when MTU is not configured from
148 #       userspace
149 #
150 # - cleanup_ipv4_exception
151 #       Similar to pmtu_ipv4_vxlan4_exception, but explicitly generate PMTU
152 #       exceptions on multiple CPUs and check that the veth device tear-down
153 #       happens in a timely manner
154 #
155 # - cleanup_ipv6_exception
156 #       Same as above, but use IPv6 transport from A to B
157 #
158 # - list_flush_ipv4_exception
159 #       Using the same topology as in pmtu_ipv4, create exceptions, and check
160 #       they are shown when listing exception caches, gone after flushing them
161 #
162 # - list_flush_ipv6_exception
163 #       Using the same topology as in pmtu_ipv6, create exceptions, and check
164 #       they are shown when listing exception caches, gone after flushing them
165
166
167 # Kselftest framework requirement - SKIP code is 4.
168 ksft_skip=4
169
170 PAUSE_ON_FAIL=no
171 VERBOSE=0
172 TRACING=0
173
174 # Some systems don't have a ping6 binary anymore
175 which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
176
177 #               Name                          Description                  re-run with nh
178 tests="
179         pmtu_ipv4_exception             ipv4: PMTU exceptions                   1
180         pmtu_ipv6_exception             ipv6: PMTU exceptions                   1
181         pmtu_ipv4_vxlan4_exception      IPv4 over vxlan4: PMTU exceptions       1
182         pmtu_ipv6_vxlan4_exception      IPv6 over vxlan4: PMTU exceptions       1
183         pmtu_ipv4_vxlan6_exception      IPv4 over vxlan6: PMTU exceptions       1
184         pmtu_ipv6_vxlan6_exception      IPv6 over vxlan6: PMTU exceptions       1
185         pmtu_ipv4_geneve4_exception     IPv4 over geneve4: PMTU exceptions      1
186         pmtu_ipv6_geneve4_exception     IPv6 over geneve4: PMTU exceptions      1
187         pmtu_ipv4_geneve6_exception     IPv4 over geneve6: PMTU exceptions      1
188         pmtu_ipv6_geneve6_exception     IPv6 over geneve6: PMTU exceptions      1
189         pmtu_ipv4_br_vxlan4_exception   IPv4, bridged vxlan4: PMTU exceptions   1
190         pmtu_ipv6_br_vxlan4_exception   IPv6, bridged vxlan4: PMTU exceptions   1
191         pmtu_ipv4_br_vxlan6_exception   IPv4, bridged vxlan6: PMTU exceptions   1
192         pmtu_ipv6_br_vxlan6_exception   IPv6, bridged vxlan6: PMTU exceptions   1
193         pmtu_ipv4_br_geneve4_exception  IPv4, bridged geneve4: PMTU exceptions  1
194         pmtu_ipv6_br_geneve4_exception  IPv6, bridged geneve4: PMTU exceptions  1
195         pmtu_ipv4_br_geneve6_exception  IPv4, bridged geneve6: PMTU exceptions  1
196         pmtu_ipv6_br_geneve6_exception  IPv6, bridged geneve6: PMTU exceptions  1
197         pmtu_ipv4_ovs_vxlan4_exception  IPv4, OVS vxlan4: PMTU exceptions       1
198         pmtu_ipv6_ovs_vxlan4_exception  IPv6, OVS vxlan4: PMTU exceptions       1
199         pmtu_ipv4_ovs_vxlan6_exception  IPv4, OVS vxlan6: PMTU exceptions       1
200         pmtu_ipv6_ovs_vxlan6_exception  IPv6, OVS vxlan6: PMTU exceptions       1
201         pmtu_ipv4_ovs_geneve4_exception IPv4, OVS geneve4: PMTU exceptions      1
202         pmtu_ipv6_ovs_geneve4_exception IPv6, OVS geneve4: PMTU exceptions      1
203         pmtu_ipv4_ovs_geneve6_exception IPv4, OVS geneve6: PMTU exceptions      1
204         pmtu_ipv6_ovs_geneve6_exception IPv6, OVS geneve6: PMTU exceptions      1
205         pmtu_ipv4_fou4_exception        IPv4 over fou4: PMTU exceptions         1
206         pmtu_ipv6_fou4_exception        IPv6 over fou4: PMTU exceptions         1
207         pmtu_ipv4_fou6_exception        IPv4 over fou6: PMTU exceptions         1
208         pmtu_ipv6_fou6_exception        IPv6 over fou6: PMTU exceptions         1
209         pmtu_ipv4_gue4_exception        IPv4 over gue4: PMTU exceptions         1
210         pmtu_ipv6_gue4_exception        IPv6 over gue4: PMTU exceptions         1
211         pmtu_ipv4_gue6_exception        IPv4 over gue6: PMTU exceptions         1
212         pmtu_ipv6_gue6_exception        IPv6 over gue6: PMTU exceptions         1
213         pmtu_ipv4_ipv4_exception        IPv4 over IPv4: PMTU exceptions         1
214         pmtu_ipv6_ipv4_exception        IPv6 over IPv4: PMTU exceptions         1
215         pmtu_ipv4_ipv6_exception        IPv4 over IPv6: PMTU exceptions         1
216         pmtu_ipv6_ipv6_exception        IPv6 over IPv6: PMTU exceptions         1
217         pmtu_vti6_exception             vti6: PMTU exceptions                   0
218         pmtu_vti4_exception             vti4: PMTU exceptions                   0
219         pmtu_vti4_default_mtu           vti4: default MTU assignment            0
220         pmtu_vti6_default_mtu           vti6: default MTU assignment            0
221         pmtu_vti4_link_add_mtu          vti4: MTU setting on link creation      0
222         pmtu_vti6_link_add_mtu          vti6: MTU setting on link creation      0
223         pmtu_vti6_link_change_mtu       vti6: MTU changes on link changes       0
224         cleanup_ipv4_exception          ipv4: cleanup of cached exceptions      1
225         cleanup_ipv6_exception          ipv6: cleanup of cached exceptions      1
226         list_flush_ipv4_exception       ipv4: list and flush cached exceptions  1
227         list_flush_ipv6_exception       ipv6: list and flush cached exceptions  1"
228
229 NS_A="ns-A"
230 NS_B="ns-B"
231 NS_C="ns-C"
232 NS_R1="ns-R1"
233 NS_R2="ns-R2"
234 ns_a="ip netns exec ${NS_A}"
235 ns_b="ip netns exec ${NS_B}"
236 ns_c="ip netns exec ${NS_C}"
237 ns_r1="ip netns exec ${NS_R1}"
238 ns_r2="ip netns exec ${NS_R2}"
239
240 # Addressing and routing for tests with routers: four network segments, with
241 # index SEGMENT between 1 and 4, a common prefix (PREFIX4 or PREFIX6) and an
242 # identifier ID, which is 1 for hosts (A and B), 2 for routers (R1 and R2).
243 # Addresses are:
244 # - IPv4: PREFIX4.SEGMENT.ID (/24)
245 # - IPv6: PREFIX6:SEGMENT::ID (/64)
246 prefix4="10.0"
247 prefix6="fc00"
248 a_r1=1
249 a_r2=2
250 b_r1=3
251 b_r2=4
252 #       ns      peer    segment
253 routing_addrs="
254         A       R1      ${a_r1}
255         A       R2      ${a_r2}
256         B       R1      ${b_r1}
257         B       R2      ${b_r2}
258 "
259 # Traffic from A to B goes through R1 by default, and through R2, if destined to
260 # B's address on the b_r2 segment.
261 # Traffic from B to A goes through R1.
262 #       ns      destination             gateway
263 routes="
264         A       default                 ${prefix4}.${a_r1}.2
265         A       ${prefix4}.${b_r2}.1    ${prefix4}.${a_r2}.2
266         B       default                 ${prefix4}.${b_r1}.2
267
268         A       default                 ${prefix6}:${a_r1}::2
269         A       ${prefix6}:${b_r2}::1   ${prefix6}:${a_r2}::2
270         B       default                 ${prefix6}:${b_r1}::2
271 "
272
273 USE_NH="no"
274 #       ns      family  nh id      destination          gateway
275 nexthops="
276         A       4       41      ${prefix4}.${a_r1}.2    veth_A-R1
277         A       4       42      ${prefix4}.${a_r2}.2    veth_A-R2
278         B       4       41      ${prefix4}.${b_r1}.2    veth_B-R1
279
280         A       6       61      ${prefix6}:${a_r1}::2   veth_A-R1
281         A       6       62      ${prefix6}:${a_r2}::2   veth_A-R2
282         B       6       61      ${prefix6}:${b_r1}::2   veth_B-R1
283 "
284
285 # nexthop id correlates to id in nexthops config above
286 #       ns    family    prefix                  nh id
287 routes_nh="
288         A       4       default                 41
289         A       4       ${prefix4}.${b_r2}.1    42
290         B       4       default                 41
291
292         A       6       default                 61
293         A       6       ${prefix6}:${b_r2}::1   62
294         B       6       default                 61
295 "
296
297 veth4_a_addr="192.168.1.1"
298 veth4_b_addr="192.168.1.2"
299 veth4_c_addr="192.168.2.10"
300 veth4_mask="24"
301 veth6_a_addr="fd00:1::a"
302 veth6_b_addr="fd00:1::b"
303 veth6_c_addr="fd00:2::c"
304 veth6_mask="64"
305
306 tunnel4_a_addr="192.168.2.1"
307 tunnel4_b_addr="192.168.2.2"
308 tunnel4_mask="24"
309 tunnel6_a_addr="fd00:2::a"
310 tunnel6_b_addr="fd00:2::b"
311 tunnel6_mask="64"
312
313 dummy6_0_prefix="fc00:1000::"
314 dummy6_1_prefix="fc00:1001::"
315 dummy6_mask="64"
316
317 err_buf=
318 tcpdump_pids=
319
320 err() {
321         err_buf="${err_buf}${1}
322 "
323 }
324
325 err_flush() {
326         echo -n "${err_buf}"
327         err_buf=
328 }
329
330 run_cmd() {
331         cmd="$*"
332
333         if [ "$VERBOSE" = "1" ]; then
334                 printf "    COMMAND: $cmd\n"
335         fi
336
337         out="$($cmd 2>&1)"
338         rc=$?
339         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
340                 echo "    $out"
341                 echo
342         fi
343
344         return $rc
345 }
346
347 # Find the auto-generated name for this namespace
348 nsname() {
349         eval echo \$NS_$1
350 }
351
352 setup_fou_or_gue() {
353         outer="${1}"
354         inner="${2}"
355         encap="${3}"
356
357         if [ "${outer}" = "4" ]; then
358                 modprobe fou || return $ksft_skip
359                 a_addr="${prefix4}.${a_r1}.1"
360                 b_addr="${prefix4}.${b_r1}.1"
361                 if [ "${inner}" = "4" ]; then
362                         type="ipip"
363                         ipproto="4"
364                 else
365                         type="sit"
366                         ipproto="41"
367                 fi
368         else
369                 modprobe fou6 || return $ksft_skip
370                 a_addr="${prefix6}:${a_r1}::1"
371                 b_addr="${prefix6}:${b_r1}::1"
372                 if [ "${inner}" = "4" ]; then
373                         type="ip6tnl"
374                         mode="mode ipip6"
375                         ipproto="4 -6"
376                 else
377                         type="ip6tnl"
378                         mode="mode ip6ip6"
379                         ipproto="41 -6"
380                 fi
381         fi
382
383         run_cmd ${ns_a} ip fou add port 5555 ipproto ${ipproto} || return $ksft_skip
384         run_cmd ${ns_a} ip link add ${encap}_a type ${type} ${mode} local ${a_addr} remote ${b_addr} encap ${encap} encap-sport auto encap-dport 5556 || return $ksft_skip
385
386         run_cmd ${ns_b} ip fou add port 5556 ipproto ${ipproto}
387         run_cmd ${ns_b} ip link add ${encap}_b type ${type} ${mode} local ${b_addr} remote ${a_addr} encap ${encap} encap-sport auto encap-dport 5555
388
389         if [ "${inner}" = "4" ]; then
390                 run_cmd ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ${encap}_a
391                 run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${encap}_b
392         else
393                 run_cmd ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ${encap}_a
394                 run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${encap}_b
395         fi
396
397         run_cmd ${ns_a} ip link set ${encap}_a up
398         run_cmd ${ns_b} ip link set ${encap}_b up
399 }
400
401 setup_fou44() {
402         setup_fou_or_gue 4 4 fou
403 }
404
405 setup_fou46() {
406         setup_fou_or_gue 4 6 fou
407 }
408
409 setup_fou64() {
410         setup_fou_or_gue 6 4 fou
411 }
412
413 setup_fou66() {
414         setup_fou_or_gue 6 6 fou
415 }
416
417 setup_gue44() {
418         setup_fou_or_gue 4 4 gue
419 }
420
421 setup_gue46() {
422         setup_fou_or_gue 4 6 gue
423 }
424
425 setup_gue64() {
426         setup_fou_or_gue 6 4 gue
427 }
428
429 setup_gue66() {
430         setup_fou_or_gue 6 6 gue
431 }
432
433 setup_ipvX_over_ipvY() {
434         inner=${1}
435         outer=${2}
436
437         if [ "${outer}" -eq 4 ]; then
438                 a_addr="${prefix4}.${a_r1}.1"
439                 b_addr="${prefix4}.${b_r1}.1"
440                 if [ "${inner}" -eq 4 ]; then
441                         type="ipip"
442                         mode="ipip"
443                 else
444                         type="sit"
445                         mode="ip6ip"
446                 fi
447         else
448                 a_addr="${prefix6}:${a_r1}::1"
449                 b_addr="${prefix6}:${b_r1}::1"
450                 type="ip6tnl"
451                 if [ "${inner}" -eq 4 ]; then
452                         mode="ipip6"
453                 else
454                         mode="ip6ip6"
455                 fi
456         fi
457
458         run_cmd ${ns_a} ip link add ip_a type ${type} local ${a_addr} remote ${b_addr} mode ${mode} || return $ksft_skip
459         run_cmd ${ns_b} ip link add ip_b type ${type} local ${b_addr} remote ${a_addr} mode ${mode}
460
461         run_cmd ${ns_a} ip link set ip_a up
462         run_cmd ${ns_b} ip link set ip_b up
463
464         if [ "${inner}" = "4" ]; then
465                 run_cmd ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ip_a
466                 run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ip_b
467         else
468                 run_cmd ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ip_a
469                 run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ip_b
470         fi
471 }
472
473 setup_ip4ip4() {
474         setup_ipvX_over_ipvY 4 4
475 }
476
477 setup_ip6ip4() {
478         setup_ipvX_over_ipvY 6 4
479 }
480
481 setup_ip4ip6() {
482         setup_ipvX_over_ipvY 4 6
483 }
484
485 setup_ip6ip6() {
486         setup_ipvX_over_ipvY 6 6
487 }
488
489 setup_namespaces() {
490         for n in ${NS_A} ${NS_B} ${NS_C} ${NS_R1} ${NS_R2}; do
491                 ip netns add ${n} || return 1
492
493                 # Disable DAD, so that we don't have to wait to use the
494                 # configured IPv6 addresses
495                 ip netns exec ${n} sysctl -q net/ipv6/conf/default/accept_dad=0
496         done
497 }
498
499 setup_veth() {
500         run_cmd ${ns_a} ip link add veth_a type veth peer name veth_b || return 1
501         run_cmd ${ns_a} ip link set veth_b netns ${NS_B}
502
503         run_cmd ${ns_a} ip addr add ${veth4_a_addr}/${veth4_mask} dev veth_a
504         run_cmd ${ns_b} ip addr add ${veth4_b_addr}/${veth4_mask} dev veth_b
505
506         run_cmd ${ns_a} ip addr add ${veth6_a_addr}/${veth6_mask} dev veth_a
507         run_cmd ${ns_b} ip addr add ${veth6_b_addr}/${veth6_mask} dev veth_b
508
509         run_cmd ${ns_a} ip link set veth_a up
510         run_cmd ${ns_b} ip link set veth_b up
511 }
512
513 setup_vti() {
514         proto=${1}
515         veth_a_addr="${2}"
516         veth_b_addr="${3}"
517         vti_a_addr="${4}"
518         vti_b_addr="${5}"
519         vti_mask=${6}
520
521         [ ${proto} -eq 6 ] && vti_type="vti6" || vti_type="vti"
522
523         run_cmd ${ns_a} ip link add vti${proto}_a type ${vti_type} local ${veth_a_addr} remote ${veth_b_addr} key 10 || return 1
524         run_cmd ${ns_b} ip link add vti${proto}_b type ${vti_type} local ${veth_b_addr} remote ${veth_a_addr} key 10
525
526         run_cmd ${ns_a} ip addr add ${vti_a_addr}/${vti_mask} dev vti${proto}_a
527         run_cmd ${ns_b} ip addr add ${vti_b_addr}/${vti_mask} dev vti${proto}_b
528
529         run_cmd ${ns_a} ip link set vti${proto}_a up
530         run_cmd ${ns_b} ip link set vti${proto}_b up
531 }
532
533 setup_vti4() {
534         setup_vti 4 ${veth4_a_addr} ${veth4_b_addr} ${tunnel4_a_addr} ${tunnel4_b_addr} ${tunnel4_mask}
535 }
536
537 setup_vti6() {
538         setup_vti 6 ${veth6_a_addr} ${veth6_b_addr} ${tunnel6_a_addr} ${tunnel6_b_addr} ${tunnel6_mask}
539 }
540
541 setup_vxlan_or_geneve() {
542         type="${1}"
543         a_addr="${2}"
544         b_addr="${3}"
545         opts="${4}"
546         br_if_a="${5}"
547
548         if [ "${type}" = "vxlan" ]; then
549                 opts="${opts} ttl 64 dstport 4789"
550                 opts_a="local ${a_addr}"
551                 opts_b="local ${b_addr}"
552         else
553                 opts_a=""
554                 opts_b=""
555         fi
556
557         run_cmd ${ns_a} ip link add ${type}_a type ${type} id 1 ${opts_a} remote ${b_addr} ${opts} || return 1
558         run_cmd ${ns_b} ip link add ${type}_b type ${type} id 1 ${opts_b} remote ${a_addr} ${opts}
559
560         if [ -n "${br_if_a}" ]; then
561                 run_cmd ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ${br_if_a}
562                 run_cmd ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ${br_if_a}
563                 run_cmd ${ns_a} ip link set ${type}_a master ${br_if_a}
564         else
565                 run_cmd ${ns_a} ip addr add ${tunnel4_a_addr}/${tunnel4_mask} dev ${type}_a
566                 run_cmd ${ns_a} ip addr add ${tunnel6_a_addr}/${tunnel6_mask} dev ${type}_a
567         fi
568
569         run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${type}_b
570         run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${type}_b
571
572         run_cmd ${ns_a} ip link set ${type}_a up
573         run_cmd ${ns_b} ip link set ${type}_b up
574 }
575
576 setup_geneve4() {
577         setup_vxlan_or_geneve geneve ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1  "df set"
578 }
579
580 setup_vxlan4() {
581         setup_vxlan_or_geneve vxlan  ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1  "df set"
582 }
583
584 setup_geneve6() {
585         setup_vxlan_or_geneve geneve ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 ""
586 }
587
588 setup_vxlan6() {
589         setup_vxlan_or_geneve vxlan  ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 ""
590 }
591
592 setup_bridged_geneve4() {
593         setup_vxlan_or_geneve geneve ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1  "df set" "br0"
594 }
595
596 setup_bridged_vxlan4() {
597         setup_vxlan_or_geneve vxlan  ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1  "df set" "br0"
598 }
599
600 setup_bridged_geneve6() {
601         setup_vxlan_or_geneve geneve ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "" "br0"
602 }
603
604 setup_bridged_vxlan6() {
605         setup_vxlan_or_geneve vxlan  ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "" "br0"
606 }
607
608 setup_xfrm() {
609         proto=${1}
610         veth_a_addr="${2}"
611         veth_b_addr="${3}"
612
613         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
614         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
615         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
616         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
617
618         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
619         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
620         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
621         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
622 }
623
624 setup_xfrm4() {
625         setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr}
626 }
627
628 setup_xfrm6() {
629         setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr}
630 }
631
632 setup_routing_old() {
633         for i in ${routes}; do
634                 [ "${ns}" = "" ]        && ns="${i}"            && continue
635                 [ "${addr}" = "" ]      && addr="${i}"          && continue
636                 [ "${gw}" = "" ]        && gw="${i}"
637
638                 ns_name="$(nsname ${ns})"
639
640                 ip -n ${ns_name} route add ${addr} via ${gw}
641
642                 ns=""; addr=""; gw=""
643         done
644 }
645
646 setup_routing_new() {
647         for i in ${nexthops}; do
648                 [ "${ns}" = "" ]        && ns="${i}"            && continue
649                 [ "${fam}" = "" ]       && fam="${i}"           && continue
650                 [ "${nhid}" = "" ]      && nhid="${i}"          && continue
651                 [ "${gw}" = "" ]        && gw="${i}"            && continue
652                 [ "${dev}" = "" ]       && dev="${i}"
653
654                 ns_name="$(nsname ${ns})"
655
656                 ip -n ${ns_name} -${fam} nexthop add id ${nhid} via ${gw} dev ${dev}
657
658                 ns=""; fam=""; nhid=""; gw=""; dev=""
659
660         done
661
662         for i in ${routes_nh}; do
663                 [ "${ns}" = "" ]        && ns="${i}"            && continue
664                 [ "${fam}" = "" ]       && fam="${i}"           && continue
665                 [ "${addr}" = "" ]      && addr="${i}"          && continue
666                 [ "${nhid}" = "" ]      && nhid="${i}"
667
668                 ns_name="$(nsname ${ns})"
669
670                 ip -n ${ns_name} -${fam} route add ${addr} nhid ${nhid}
671
672                 ns=""; fam=""; addr=""; nhid=""
673         done
674 }
675
676 setup_routing() {
677         for i in ${NS_R1} ${NS_R2}; do
678                 ip netns exec ${i} sysctl -q net/ipv4/ip_forward=1
679                 ip netns exec ${i} sysctl -q net/ipv6/conf/all/forwarding=1
680         done
681
682         for i in ${routing_addrs}; do
683                 [ "${ns}" = "" ]        && ns="${i}"            && continue
684                 [ "${peer}" = "" ]      && peer="${i}"          && continue
685                 [ "${segment}" = "" ]   && segment="${i}"
686
687                 ns_name="$(nsname ${ns})"
688                 peer_name="$(nsname ${peer})"
689                 if="veth_${ns}-${peer}"
690                 ifpeer="veth_${peer}-${ns}"
691
692                 # Create veth links
693                 ip link add ${if} up netns ${ns_name} type veth peer name ${ifpeer} netns ${peer_name} || return 1
694                 ip -n ${peer_name} link set dev ${ifpeer} up
695
696                 # Add addresses
697                 ip -n ${ns_name}   addr add ${prefix4}.${segment}.1/24  dev ${if}
698                 ip -n ${ns_name}   addr add ${prefix6}:${segment}::1/64 dev ${if}
699
700                 ip -n ${peer_name} addr add ${prefix4}.${segment}.2/24  dev ${ifpeer}
701                 ip -n ${peer_name} addr add ${prefix6}:${segment}::2/64 dev ${ifpeer}
702
703                 ns=""; peer=""; segment=""
704         done
705
706         if [ "$USE_NH" = "yes" ]; then
707                 setup_routing_new
708         else
709                 setup_routing_old
710         fi
711
712         return 0
713 }
714
715 setup_bridge() {
716         run_cmd ${ns_a} ip link add br0 type bridge || return $ksft_skip
717         run_cmd ${ns_a} ip link set br0 up
718
719         run_cmd ${ns_c} ip link add veth_C-A type veth peer name veth_A-C
720         run_cmd ${ns_c} ip link set veth_A-C netns ns-A
721
722         run_cmd ${ns_a} ip link set veth_A-C up
723         run_cmd ${ns_c} ip link set veth_C-A up
724         run_cmd ${ns_c} ip addr add ${veth4_c_addr}/${veth4_mask} dev veth_C-A
725         run_cmd ${ns_c} ip addr add ${veth6_c_addr}/${veth6_mask} dev veth_C-A
726         run_cmd ${ns_a} ip link set veth_A-C master br0
727 }
728
729 setup_ovs_vxlan_or_geneve() {
730         type="${1}"
731         a_addr="${2}"
732         b_addr="${3}"
733
734         if [ "${type}" = "vxlan" ]; then
735                 opts="${opts} ttl 64 dstport 4789"
736                 opts_b="local ${b_addr}"
737         fi
738
739         run_cmd ovs-vsctl add-port ovs_br0 ${type}_a -- \
740                 set interface ${type}_a type=${type} \
741                 options:remote_ip=${b_addr} options:key=1 options:csum=true || return 1
742
743         run_cmd ${ns_b} ip link add ${type}_b type ${type} id 1 ${opts_b} remote ${a_addr} ${opts} || return 1
744
745         run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${type}_b
746         run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${type}_b
747
748         run_cmd ${ns_b} ip link set ${type}_b up
749 }
750
751 setup_ovs_geneve4() {
752         setup_ovs_vxlan_or_geneve geneve ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1
753 }
754
755 setup_ovs_vxlan4() {
756         setup_ovs_vxlan_or_geneve vxlan  ${prefix4}.${a_r1}.1  ${prefix4}.${b_r1}.1
757 }
758
759 setup_ovs_geneve6() {
760         setup_ovs_vxlan_or_geneve geneve ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1
761 }
762
763 setup_ovs_vxlan6() {
764         setup_ovs_vxlan_or_geneve vxlan  ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1
765 }
766
767 setup_ovs_bridge() {
768         run_cmd ovs-vsctl add-br ovs_br0 || return $ksft_skip
769         run_cmd ip link set ovs_br0 up
770
771         run_cmd ${ns_c} ip link add veth_C-A type veth peer name veth_A-C
772         run_cmd ${ns_c} ip link set veth_A-C netns 1
773
774         run_cmd         ip link set veth_A-C up
775         run_cmd ${ns_c} ip link set veth_C-A up
776         run_cmd ${ns_c} ip addr add ${veth4_c_addr}/${veth4_mask} dev veth_C-A
777         run_cmd ${ns_c} ip addr add ${veth6_c_addr}/${veth6_mask} dev veth_C-A
778         run_cmd ovs-vsctl add-port ovs_br0 veth_A-C
779
780         # Move veth_A-R1 to init
781         run_cmd ${ns_a} ip link set veth_A-R1 netns 1
782         run_cmd ip addr add ${prefix4}.${a_r1}.1/${veth4_mask} dev veth_A-R1
783         run_cmd ip addr add ${prefix6}:${a_r1}::1/${veth6_mask} dev veth_A-R1
784         run_cmd ip link set veth_A-R1 up
785         run_cmd ip route add ${prefix4}.${b_r1}.1 via ${prefix4}.${a_r1}.2
786         run_cmd ip route add ${prefix6}:${b_r1}::1 via ${prefix6}:${a_r1}::2
787 }
788
789 setup() {
790         [ "$(id -u)" -ne 0 ] && echo "  need to run as root" && return $ksft_skip
791
792         cleanup
793         for arg do
794                 eval setup_${arg} || { echo "  ${arg} not supported"; return 1; }
795         done
796 }
797
798 trace() {
799         [ $TRACING -eq 0 ] && return
800
801         for arg do
802                 [ "${ns_cmd}" = "" ] && ns_cmd="${arg}" && continue
803                 ${ns_cmd} tcpdump -s 0 -i "${arg}" -w "${name}_${arg}.pcap" 2> /dev/null &
804                 tcpdump_pids="${tcpdump_pids} $!"
805                 ns_cmd=
806         done
807         sleep 1
808 }
809
810 cleanup() {
811         for pid in ${tcpdump_pids}; do
812                 kill ${pid}
813         done
814         tcpdump_pids=
815
816         for n in ${NS_A} ${NS_B} ${NS_C} ${NS_R1} ${NS_R2}; do
817                 ip netns del ${n} 2> /dev/null
818         done
819
820         ip link del veth_A-C                    2>/dev/null
821         ip link del veth_A-R1                   2>/dev/null
822         ovs-vsctl --if-exists del-port vxlan_a  2>/dev/null
823         ovs-vsctl --if-exists del-br ovs_br0    2>/dev/null
824 }
825
826 mtu() {
827         ns_cmd="${1}"
828         dev="${2}"
829         mtu="${3}"
830
831         ${ns_cmd} ip link set dev ${dev} mtu ${mtu}
832 }
833
834 mtu_parse() {
835         input="${1}"
836
837         next=0
838         for i in ${input}; do
839                 [ ${next} -eq 1 -a "${i}" = "lock" ] && next=2 && continue
840                 [ ${next} -eq 1 ] && echo "${i}" && return
841                 [ ${next} -eq 2 ] && echo "lock ${i}" && return
842                 [ "${i}" = "mtu" ] && next=1
843         done
844 }
845
846 link_get() {
847         ns_cmd="${1}"
848         name="${2}"
849
850         ${ns_cmd} ip link show dev "${name}"
851 }
852
853 link_get_mtu() {
854         ns_cmd="${1}"
855         name="${2}"
856
857         mtu_parse "$(link_get "${ns_cmd}" ${name})"
858 }
859
860 route_get_dst_exception() {
861         ns_cmd="${1}"
862         dst="${2}"
863
864         ${ns_cmd} ip route get "${dst}"
865 }
866
867 route_get_dst_pmtu_from_exception() {
868         ns_cmd="${1}"
869         dst="${2}"
870
871         mtu_parse "$(route_get_dst_exception "${ns_cmd}" ${dst})"
872 }
873
874 check_pmtu_value() {
875         expected="${1}"
876         value="${2}"
877         event="${3}"
878
879         [ "${expected}" = "any" ] && [ -n "${value}" ] && return 0
880         [ "${value}" = "${expected}" ] && return 0
881         [ -z "${value}" ] &&    err "  PMTU exception wasn't created after ${event}" && return 1
882         [ -z "${expected}" ] && err "  PMTU exception shouldn't exist after ${event}" && return 1
883         err "  found PMTU exception with incorrect MTU ${value}, expected ${expected}, after ${event}"
884         return 1
885 }
886
887 test_pmtu_ipvX() {
888         family=${1}
889
890         setup namespaces routing || return $ksft_skip
891         trace "${ns_a}"  veth_A-R1    "${ns_r1}" veth_R1-A \
892               "${ns_r1}" veth_R1-B    "${ns_b}"  veth_B-R1 \
893               "${ns_a}"  veth_A-R2    "${ns_r2}" veth_R2-A \
894               "${ns_r2}" veth_R2-B    "${ns_b}"  veth_B-R2
895
896         if [ ${family} -eq 4 ]; then
897                 ping=ping
898                 dst1="${prefix4}.${b_r1}.1"
899                 dst2="${prefix4}.${b_r2}.1"
900         else
901                 ping=${ping6}
902                 dst1="${prefix6}:${b_r1}::1"
903                 dst2="${prefix6}:${b_r2}::1"
904         fi
905
906         # Set up initial MTU values
907         mtu "${ns_a}"  veth_A-R1 2000
908         mtu "${ns_r1}" veth_R1-A 2000
909         mtu "${ns_r1}" veth_R1-B 1400
910         mtu "${ns_b}"  veth_B-R1 1400
911
912         mtu "${ns_a}"  veth_A-R2 2000
913         mtu "${ns_r2}" veth_R2-A 2000
914         mtu "${ns_r2}" veth_R2-B 1500
915         mtu "${ns_b}"  veth_B-R2 1500
916
917         # Create route exceptions
918         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst1}
919         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst2}
920
921         # Check that exceptions have been created with the correct PMTU
922         pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
923         check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1
924         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
925         check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1
926
927         # Decrease local MTU below PMTU, check for PMTU decrease in route exception
928         mtu "${ns_a}"  veth_A-R1 1300
929         mtu "${ns_r1}" veth_R1-A 1300
930         pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
931         check_pmtu_value "1300" "${pmtu_1}" "decreasing local MTU" || return 1
932         # Second exception shouldn't be modified
933         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
934         check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1
935
936         # Increase MTU, check for PMTU increase in route exception
937         mtu "${ns_a}"  veth_A-R1 1700
938         mtu "${ns_r1}" veth_R1-A 1700
939         pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
940         check_pmtu_value "1700" "${pmtu_1}" "increasing local MTU" || return 1
941         # Second exception shouldn't be modified
942         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
943         check_pmtu_value "1500" "${pmtu_2}" "changing local MTU on a link not on this path" || return 1
944
945         # Skip PMTU locking tests for IPv6
946         [ $family -eq 6 ] && return 0
947
948         # Decrease remote MTU on path via R2, get new exception
949         mtu "${ns_r2}" veth_R2-B 400
950         mtu "${ns_b}"  veth_B-R2 400
951         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1400 ${dst2}
952         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
953         check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1
954
955         # Decrease local MTU below PMTU
956         mtu "${ns_a}"  veth_A-R2 500
957         mtu "${ns_r2}" veth_R2-A 500
958         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
959         check_pmtu_value "500" "${pmtu_2}" "decreasing local MTU" || return 1
960
961         # Increase local MTU
962         mtu "${ns_a}"  veth_A-R2 1500
963         mtu "${ns_r2}" veth_R2-A 1500
964         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
965         check_pmtu_value "1500" "${pmtu_2}" "increasing local MTU" || return 1
966
967         # Get new exception
968         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1400 ${dst2}
969         pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
970         check_pmtu_value "lock 552" "${pmtu_2}" "exceeding MTU, with MTU < min_pmtu" || return 1
971 }
972
973 test_pmtu_ipv4_exception() {
974         test_pmtu_ipvX 4
975 }
976
977 test_pmtu_ipv6_exception() {
978         test_pmtu_ipvX 6
979 }
980
981 test_pmtu_ipvX_over_vxlanY_or_geneveY_exception() {
982         type=${1}
983         family=${2}
984         outer_family=${3}
985         ll_mtu=4000
986
987         if [ ${outer_family} -eq 4 ]; then
988                 setup namespaces routing ${type}4 || return $ksft_skip
989                 #                      IPv4 header   UDP header   VXLAN/GENEVE header   Ethernet header
990                 exp_mtu=$((${ll_mtu} - 20          - 8          - 8                   - 14))
991         else
992                 setup namespaces routing ${type}6 || return $ksft_skip
993                 #                      IPv6 header   UDP header   VXLAN/GENEVE header   Ethernet header
994                 exp_mtu=$((${ll_mtu} - 40          - 8          - 8                   - 14))
995         fi
996
997         trace "${ns_a}" ${type}_a    "${ns_b}"  ${type}_b \
998               "${ns_a}" veth_A-R1    "${ns_r1}" veth_R1-A \
999               "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B
1000
1001         if [ ${family} -eq 4 ]; then
1002                 ping=ping
1003                 dst=${tunnel4_b_addr}
1004         else
1005                 ping=${ping6}
1006                 dst=${tunnel6_b_addr}
1007         fi
1008
1009         # Create route exception by exceeding link layer MTU
1010         mtu "${ns_a}"  veth_A-R1 $((${ll_mtu} + 1000))
1011         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1012         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1013         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1014
1015         mtu "${ns_a}" ${type}_a $((${ll_mtu} + 1000))
1016         mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000))
1017         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${dst}
1018
1019         # Check that exception was created
1020         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
1021         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on ${type} interface"
1022 }
1023
1024 test_pmtu_ipv4_vxlan4_exception() {
1025         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan  4 4
1026 }
1027
1028 test_pmtu_ipv6_vxlan4_exception() {
1029         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan  6 4
1030 }
1031
1032 test_pmtu_ipv4_geneve4_exception() {
1033         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 4 4
1034 }
1035
1036 test_pmtu_ipv6_geneve4_exception() {
1037         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 6 4
1038 }
1039
1040 test_pmtu_ipv4_vxlan6_exception() {
1041         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan  4 6
1042 }
1043
1044 test_pmtu_ipv6_vxlan6_exception() {
1045         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception vxlan  6 6
1046 }
1047
1048 test_pmtu_ipv4_geneve6_exception() {
1049         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 4 6
1050 }
1051
1052 test_pmtu_ipv6_geneve6_exception() {
1053         test_pmtu_ipvX_over_vxlanY_or_geneveY_exception geneve 6 6
1054 }
1055
1056 test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() {
1057         type=${1}
1058         family=${2}
1059         outer_family=${3}
1060         ll_mtu=4000
1061
1062         if [ ${outer_family} -eq 4 ]; then
1063                 setup namespaces routing bridge bridged_${type}4 || return $ksft_skip
1064                 #                      IPv4 header   UDP header   VXLAN/GENEVE header   Ethernet header
1065                 exp_mtu=$((${ll_mtu} - 20          - 8          - 8                   - 14))
1066         else
1067                 setup namespaces routing bridge bridged_${type}6 || return $ksft_skip
1068                 #                      IPv6 header   UDP header   VXLAN/GENEVE header   Ethernet header
1069                 exp_mtu=$((${ll_mtu} - 40          - 8          - 8                   - 14))
1070         fi
1071
1072         trace "${ns_a}" ${type}_a    "${ns_b}"  ${type}_b \
1073               "${ns_a}" veth_A-R1    "${ns_r1}" veth_R1-A \
1074               "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B \
1075               "${ns_a}" br0          "${ns_a}"  veth-A-C  \
1076               "${ns_c}" veth_C-A
1077
1078         if [ ${family} -eq 4 ]; then
1079                 ping=ping
1080                 dst=${tunnel4_b_addr}
1081         else
1082                 ping=${ping6}
1083                 dst=${tunnel6_b_addr}
1084         fi
1085
1086         # Create route exception by exceeding link layer MTU
1087         mtu "${ns_a}"  veth_A-R1 $((${ll_mtu} + 1000))
1088         mtu "${ns_a}"  br0       $((${ll_mtu} + 1000))
1089         mtu "${ns_a}"  veth_A-C  $((${ll_mtu} + 1000))
1090         mtu "${ns_c}"  veth_C-A  $((${ll_mtu} + 1000))
1091         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1092         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1093         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1094
1095         mtu "${ns_a}" ${type}_a $((${ll_mtu} + 1000))
1096         mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000))
1097
1098         run_cmd ${ns_c} ${ping} -q -M want -i 0.1 -c 10 -s $((${ll_mtu} + 500)) ${dst} || return 1
1099         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1  -s $((${ll_mtu} + 500)) ${dst} || return 1
1100
1101         # Check that exceptions were created
1102         pmtu="$(route_get_dst_pmtu_from_exception "${ns_c}" ${dst})"
1103         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on bridged ${type} interface"
1104         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
1105         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on locally bridged ${type} interface"
1106 }
1107
1108 test_pmtu_ipv4_br_vxlan4_exception() {
1109         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception vxlan  4 4
1110 }
1111
1112 test_pmtu_ipv6_br_vxlan4_exception() {
1113         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception vxlan  6 4
1114 }
1115
1116 test_pmtu_ipv4_br_geneve4_exception() {
1117         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception geneve 4 4
1118 }
1119
1120 test_pmtu_ipv6_br_geneve4_exception() {
1121         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception geneve 6 4
1122 }
1123
1124 test_pmtu_ipv4_br_vxlan6_exception() {
1125         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception vxlan  4 6
1126 }
1127
1128 test_pmtu_ipv6_br_vxlan6_exception() {
1129         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception vxlan  6 6
1130 }
1131
1132 test_pmtu_ipv4_br_geneve6_exception() {
1133         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception geneve 4 6
1134 }
1135
1136 test_pmtu_ipv6_br_geneve6_exception() {
1137         test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception geneve 6 6
1138 }
1139
1140 test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() {
1141         type=${1}
1142         family=${2}
1143         outer_family=${3}
1144         ll_mtu=4000
1145
1146         if [ ${outer_family} -eq 4 ]; then
1147                 setup namespaces routing ovs_bridge ovs_${type}4 || return $ksft_skip
1148                 #                      IPv4 header   UDP header   VXLAN/GENEVE header   Ethernet header
1149                 exp_mtu=$((${ll_mtu} - 20          - 8          - 8                   - 14))
1150         else
1151                 setup namespaces routing ovs_bridge ovs_${type}6 || return $ksft_skip
1152                 #                      IPv6 header   UDP header   VXLAN/GENEVE header   Ethernet header
1153                 exp_mtu=$((${ll_mtu} - 40          - 8          - 8                   - 14))
1154         fi
1155
1156         if [ "${type}" = "vxlan" ]; then
1157                 tun_a="vxlan_sys_4789"
1158         elif [ "${type}" = "geneve" ]; then
1159                 tun_a="genev_sys_6081"
1160         fi
1161
1162         trace ""        "${tun_a}"  "${ns_b}"  ${type}_b \
1163               ""        veth_A-R1   "${ns_r1}" veth_R1-A \
1164               "${ns_b}" veth_B-R1   "${ns_r1}" veth_R1-B \
1165               ""        ovs_br0     ""         veth-A-C  \
1166               "${ns_c}" veth_C-A
1167
1168         if [ ${family} -eq 4 ]; then
1169                 ping=ping
1170                 dst=${tunnel4_b_addr}
1171         else
1172                 ping=${ping6}
1173                 dst=${tunnel6_b_addr}
1174         fi
1175
1176         # Create route exception by exceeding link layer MTU
1177         mtu ""         veth_A-R1 $((${ll_mtu} + 1000))
1178         mtu ""         ovs_br0   $((${ll_mtu} + 1000))
1179         mtu ""         veth_A-C  $((${ll_mtu} + 1000))
1180         mtu "${ns_c}"  veth_C-A  $((${ll_mtu} + 1000))
1181         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1182         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1183         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1184
1185         mtu ""        ${tun_a}  $((${ll_mtu} + 1000))
1186         mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000))
1187
1188         run_cmd ${ns_c} ${ping} -q -M want -i 0.1 -c 20 -s $((${ll_mtu} + 500)) ${dst} || return 1
1189
1190         # Check that exceptions were created
1191         pmtu="$(route_get_dst_pmtu_from_exception "${ns_c}" ${dst})"
1192         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on Open vSwitch ${type} interface"
1193 }
1194
1195 test_pmtu_ipv4_ovs_vxlan4_exception() {
1196         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception vxlan  4 4
1197 }
1198
1199 test_pmtu_ipv6_ovs_vxlan4_exception() {
1200         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception vxlan  6 4
1201 }
1202
1203 test_pmtu_ipv4_ovs_geneve4_exception() {
1204         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception geneve 4 4
1205 }
1206
1207 test_pmtu_ipv6_ovs_geneve4_exception() {
1208         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception geneve 6 4
1209 }
1210
1211 test_pmtu_ipv4_ovs_vxlan6_exception() {
1212         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception vxlan  4 6
1213 }
1214
1215 test_pmtu_ipv6_ovs_vxlan6_exception() {
1216         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception vxlan  6 6
1217 }
1218
1219 test_pmtu_ipv4_ovs_geneve6_exception() {
1220         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception geneve 4 6
1221 }
1222
1223 test_pmtu_ipv6_ovs_geneve6_exception() {
1224         test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception geneve 6 6
1225 }
1226
1227 test_pmtu_ipvX_over_fouY_or_gueY() {
1228         inner_family=${1}
1229         outer_family=${2}
1230         encap=${3}
1231         ll_mtu=4000
1232
1233         setup namespaces routing ${encap}${outer_family}${inner_family} || return $ksft_skip
1234         trace "${ns_a}" ${encap}_a   "${ns_b}"  ${encap}_b \
1235               "${ns_a}" veth_A-R1    "${ns_r1}" veth_R1-A \
1236               "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B
1237
1238         if [ ${inner_family} -eq 4 ]; then
1239                 ping=ping
1240                 dst=${tunnel4_b_addr}
1241         else
1242                 ping=${ping6}
1243                 dst=${tunnel6_b_addr}
1244         fi
1245
1246         if [ "${encap}" = "gue" ]; then
1247                 encap_overhead=4
1248         else
1249                 encap_overhead=0
1250         fi
1251
1252         if [ ${outer_family} -eq 4 ]; then
1253                 #                      IPv4 header   UDP header
1254                 exp_mtu=$((${ll_mtu} - 20          - 8         - ${encap_overhead}))
1255         else
1256                 #                      IPv6 header   Option 4   UDP header
1257                 exp_mtu=$((${ll_mtu} - 40          - 8        - 8       - ${encap_overhead}))
1258         fi
1259
1260         # Create route exception by exceeding link layer MTU
1261         mtu "${ns_a}"  veth_A-R1 $((${ll_mtu} + 1000))
1262         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1263         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1264         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1265
1266         mtu "${ns_a}" ${encap}_a $((${ll_mtu} + 1000))
1267         mtu "${ns_b}" ${encap}_b $((${ll_mtu} + 1000))
1268         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${dst}
1269
1270         # Check that exception was created
1271         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
1272         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on ${encap} interface"
1273 }
1274
1275 test_pmtu_ipv4_fou4_exception() {
1276         test_pmtu_ipvX_over_fouY_or_gueY 4 4 fou
1277 }
1278
1279 test_pmtu_ipv6_fou4_exception() {
1280         test_pmtu_ipvX_over_fouY_or_gueY 6 4 fou
1281 }
1282
1283 test_pmtu_ipv4_fou6_exception() {
1284         test_pmtu_ipvX_over_fouY_or_gueY 4 6 fou
1285 }
1286
1287 test_pmtu_ipv6_fou6_exception() {
1288         test_pmtu_ipvX_over_fouY_or_gueY 6 6 fou
1289 }
1290
1291 test_pmtu_ipv4_gue4_exception() {
1292         test_pmtu_ipvX_over_fouY_or_gueY 4 4 gue
1293 }
1294
1295 test_pmtu_ipv6_gue4_exception() {
1296         test_pmtu_ipvX_over_fouY_or_gueY 6 4 gue
1297 }
1298
1299 test_pmtu_ipv4_gue6_exception() {
1300         test_pmtu_ipvX_over_fouY_or_gueY 4 6 gue
1301 }
1302
1303 test_pmtu_ipv6_gue6_exception() {
1304         test_pmtu_ipvX_over_fouY_or_gueY 6 6 gue
1305 }
1306
1307 test_pmtu_ipvX_over_ipvY_exception() {
1308         inner=${1}
1309         outer=${2}
1310         ll_mtu=4000
1311
1312         setup namespaces routing ip${inner}ip${outer} || return $ksft_skip
1313
1314         trace "${ns_a}" ip_a         "${ns_b}"  ip_b  \
1315               "${ns_a}" veth_A-R1    "${ns_r1}" veth_R1-A \
1316               "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B
1317
1318         if [ ${inner} -eq 4 ]; then
1319                 ping=ping
1320                 dst=${tunnel4_b_addr}
1321         else
1322                 ping=${ping6}
1323                 dst=${tunnel6_b_addr}
1324         fi
1325
1326         if [ ${outer} -eq 4 ]; then
1327                 #                      IPv4 header
1328                 exp_mtu=$((${ll_mtu} - 20))
1329         else
1330                 #                      IPv6 header   Option 4
1331                 exp_mtu=$((${ll_mtu} - 40          - 8))
1332         fi
1333
1334         # Create route exception by exceeding link layer MTU
1335         mtu "${ns_a}"  veth_A-R1 $((${ll_mtu} + 1000))
1336         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1337         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1338         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1339
1340         mtu "${ns_a}" ip_a $((${ll_mtu} + 1000)) || return
1341         mtu "${ns_b}" ip_b $((${ll_mtu} + 1000)) || return
1342         run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${dst}
1343
1344         # Check that exception was created
1345         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst})"
1346         check_pmtu_value ${exp_mtu} "${pmtu}" "exceeding link layer MTU on ip${inner}ip${outer} interface"
1347 }
1348
1349 test_pmtu_ipv4_ipv4_exception() {
1350         test_pmtu_ipvX_over_ipvY_exception 4 4
1351 }
1352
1353 test_pmtu_ipv6_ipv4_exception() {
1354         test_pmtu_ipvX_over_ipvY_exception 6 4
1355 }
1356
1357 test_pmtu_ipv4_ipv6_exception() {
1358         test_pmtu_ipvX_over_ipvY_exception 4 6
1359 }
1360
1361 test_pmtu_ipv6_ipv6_exception() {
1362         test_pmtu_ipvX_over_ipvY_exception 6 6
1363 }
1364
1365 test_pmtu_vti4_exception() {
1366         setup namespaces veth vti4 xfrm4 || return $ksft_skip
1367         trace "${ns_a}" veth_a    "${ns_b}" veth_b \
1368               "${ns_a}" vti4_a    "${ns_b}" vti4_b
1369
1370         veth_mtu=1500
1371         vti_mtu=$((veth_mtu - 20))
1372
1373         #                                SPI   SN   IV  ICV   pad length   next header
1374         esp_payload_rfc4106=$((vti_mtu - 4   - 4  - 8 - 16  - 1          - 1))
1375         ping_payload=$((esp_payload_rfc4106 - 28))
1376
1377         mtu "${ns_a}" veth_a ${veth_mtu}
1378         mtu "${ns_b}" veth_b ${veth_mtu}
1379         mtu "${ns_a}" vti4_a ${vti_mtu}
1380         mtu "${ns_b}" vti4_b ${vti_mtu}
1381
1382         # Send DF packet without exceeding link layer MTU, check that no
1383         # exception is created
1384         run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s ${ping_payload} ${tunnel4_b_addr}
1385         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
1386         check_pmtu_value "" "${pmtu}" "sending packet smaller than PMTU (IP payload length ${esp_payload_rfc4106})" || return 1
1387
1388         # Now exceed link layer MTU by one byte, check that exception is created
1389         # with the right PMTU value
1390         run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((ping_payload + 1)) ${tunnel4_b_addr}
1391         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel4_b_addr})"
1392         check_pmtu_value "${esp_payload_rfc4106}" "${pmtu}" "exceeding PMTU (IP payload length $((esp_payload_rfc4106 + 1)))"
1393 }
1394
1395 test_pmtu_vti6_exception() {
1396         setup namespaces veth vti6 xfrm6 || return $ksft_skip
1397         trace "${ns_a}" veth_a    "${ns_b}" veth_b \
1398               "${ns_a}" vti6_a    "${ns_b}" vti6_b
1399         fail=0
1400
1401         # Create route exception by exceeding link layer MTU
1402         mtu "${ns_a}" veth_a 4000
1403         mtu "${ns_b}" veth_b 4000
1404         mtu "${ns_a}" vti6_a 5000
1405         mtu "${ns_b}" vti6_b 5000
1406         run_cmd ${ns_a} ${ping6} -q -i 0.1 -w 1 -s 60000 ${tunnel6_b_addr}
1407
1408         # Check that exception was created
1409         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
1410         check_pmtu_value any "${pmtu}" "creating tunnel exceeding link layer MTU" || return 1
1411
1412         # Decrease tunnel MTU, check for PMTU decrease in route exception
1413         mtu "${ns_a}" vti6_a 3000
1414         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
1415         check_pmtu_value "3000" "${pmtu}" "decreasing tunnel MTU" || fail=1
1416
1417         # Increase tunnel MTU, check for PMTU increase in route exception
1418         mtu "${ns_a}" vti6_a 9000
1419         pmtu="$(route_get_dst_pmtu_from_exception "${ns_a}" ${tunnel6_b_addr})"
1420         check_pmtu_value "9000" "${pmtu}" "increasing tunnel MTU" || fail=1
1421
1422         return ${fail}
1423 }
1424
1425 test_pmtu_vti4_default_mtu() {
1426         setup namespaces veth vti4 || return $ksft_skip
1427
1428         # Check that MTU of vti device is MTU of veth minus IPv4 header length
1429         veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
1430         vti4_mtu="$(link_get_mtu "${ns_a}" vti4_a)"
1431         if [ $((veth_mtu - vti4_mtu)) -ne 20 ]; then
1432                 err "  vti MTU ${vti4_mtu} is not veth MTU ${veth_mtu} minus IPv4 header length"
1433                 return 1
1434         fi
1435 }
1436
1437 test_pmtu_vti6_default_mtu() {
1438         setup namespaces veth vti6 || return $ksft_skip
1439
1440         # Check that MTU of vti device is MTU of veth minus IPv6 header length
1441         veth_mtu="$(link_get_mtu "${ns_a}" veth_a)"
1442         vti6_mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1443         if [ $((veth_mtu - vti6_mtu)) -ne 40 ]; then
1444                 err "  vti MTU ${vti6_mtu} is not veth MTU ${veth_mtu} minus IPv6 header length"
1445                 return 1
1446         fi
1447 }
1448
1449 test_pmtu_vti4_link_add_mtu() {
1450         setup namespaces || return $ksft_skip
1451
1452         run_cmd ${ns_a} ip link add vti4_a type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10
1453         [ $? -ne 0 ] && err "  vti not supported" && return $ksft_skip
1454         run_cmd ${ns_a} ip link del vti4_a
1455
1456         fail=0
1457
1458         min=68
1459         max=$((65535 - 20))
1460         # Check invalid values first
1461         for v in $((min - 1)) $((max + 1)); do
1462                 run_cmd ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10
1463                 # This can fail, or MTU can be adjusted to a proper value
1464                 [ $? -ne 0 ] && continue
1465                 mtu="$(link_get_mtu "${ns_a}" vti4_a)"
1466                 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
1467                         err "  vti tunnel created with invalid MTU ${mtu}"
1468                         fail=1
1469                 fi
1470                 run_cmd ${ns_a} ip link del vti4_a
1471         done
1472
1473         # Now check valid values
1474         for v in ${min} 1300 ${max}; do
1475                 run_cmd ${ns_a} ip link add vti4_a mtu ${v} type vti local ${veth4_a_addr} remote ${veth4_b_addr} key 10
1476                 mtu="$(link_get_mtu "${ns_a}" vti4_a)"
1477                 run_cmd ${ns_a} ip link del vti4_a
1478                 if [ "${mtu}" != "${v}" ]; then
1479                         err "  vti MTU ${mtu} doesn't match configured value ${v}"
1480                         fail=1
1481                 fi
1482         done
1483
1484         return ${fail}
1485 }
1486
1487 test_pmtu_vti6_link_add_mtu() {
1488         setup namespaces || return $ksft_skip
1489
1490         run_cmd ${ns_a} ip link add vti6_a type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10
1491         [ $? -ne 0 ] && err "  vti6 not supported" && return $ksft_skip
1492         run_cmd ${ns_a} ip link del vti6_a
1493
1494         fail=0
1495
1496         min=68                  # vti6 can carry IPv4 packets too
1497         max=$((65535 - 40))
1498         # Check invalid values first
1499         for v in $((min - 1)) $((max + 1)); do
1500                 run_cmd ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10
1501                 # This can fail, or MTU can be adjusted to a proper value
1502                 [ $? -ne 0 ] && continue
1503                 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1504                 if [ ${mtu} -lt ${min} -o ${mtu} -gt ${max} ]; then
1505                         err "  vti6 tunnel created with invalid MTU ${v}"
1506                         fail=1
1507                 fi
1508                 run_cmd ${ns_a} ip link del vti6_a
1509         done
1510
1511         # Now check valid values
1512         for v in 68 1280 1300 $((65535 - 40)); do
1513                 run_cmd ${ns_a} ip link add vti6_a mtu ${v} type vti6 local ${veth6_a_addr} remote ${veth6_b_addr} key 10
1514                 mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1515                 run_cmd ${ns_a} ip link del vti6_a
1516                 if [ "${mtu}" != "${v}" ]; then
1517                         err "  vti6 MTU ${mtu} doesn't match configured value ${v}"
1518                         fail=1
1519                 fi
1520         done
1521
1522         return ${fail}
1523 }
1524
1525 test_pmtu_vti6_link_change_mtu() {
1526         setup namespaces || return $ksft_skip
1527
1528         run_cmd ${ns_a} ip link add dummy0 mtu 1500 type dummy
1529         [ $? -ne 0 ] && err "  dummy not supported" && return $ksft_skip
1530         run_cmd ${ns_a} ip link add dummy1 mtu 3000 type dummy
1531         run_cmd ${ns_a} ip link set dummy0 up
1532         run_cmd ${ns_a} ip link set dummy1 up
1533
1534         run_cmd ${ns_a} ip addr add ${dummy6_0_prefix}1/${dummy6_mask} dev dummy0
1535         run_cmd ${ns_a} ip addr add ${dummy6_1_prefix}1/${dummy6_mask} dev dummy1
1536
1537         fail=0
1538
1539         # Create vti6 interface bound to device, passing MTU, check it
1540         run_cmd ${ns_a} ip link add vti6_a mtu 1300 type vti6 remote ${dummy6_0_prefix}2 local ${dummy6_0_prefix}1
1541         mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1542         if [ ${mtu} -ne 1300 ]; then
1543                 err "  vti6 MTU ${mtu} doesn't match configured value 1300"
1544                 fail=1
1545         fi
1546
1547         # Move to another device with different MTU, without passing MTU, check
1548         # MTU is adjusted
1549         run_cmd ${ns_a} ip link set vti6_a type vti6 remote ${dummy6_1_prefix}2 local ${dummy6_1_prefix}1
1550         mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1551         if [ ${mtu} -ne $((3000 - 40)) ]; then
1552                 err "  vti MTU ${mtu} is not dummy MTU 3000 minus IPv6 header length"
1553                 fail=1
1554         fi
1555
1556         # Move it back, passing MTU, check MTU is not overridden
1557         run_cmd ${ns_a} ip link set vti6_a mtu 1280 type vti6 remote ${dummy6_0_prefix}2 local ${dummy6_0_prefix}1
1558         mtu="$(link_get_mtu "${ns_a}" vti6_a)"
1559         if [ ${mtu} -ne 1280 ]; then
1560                 err "  vti6 MTU ${mtu} doesn't match configured value 1280"
1561                 fail=1
1562         fi
1563
1564         return ${fail}
1565 }
1566
1567 check_command() {
1568         cmd=${1}
1569
1570         if ! which ${cmd} > /dev/null 2>&1; then
1571                 err "  missing required command: '${cmd}'"
1572                 return 1
1573         fi
1574         return 0
1575 }
1576
1577 test_cleanup_vxlanX_exception() {
1578         outer="${1}"
1579         encap="vxlan"
1580         ll_mtu=4000
1581
1582         check_command taskset || return $ksft_skip
1583         cpu_list=$(grep -m 2 processor /proc/cpuinfo | cut -d ' ' -f 2)
1584
1585         setup namespaces routing ${encap}${outer} || return $ksft_skip
1586         trace "${ns_a}" ${encap}_a   "${ns_b}"  ${encap}_b \
1587               "${ns_a}" veth_A-R1    "${ns_r1}" veth_R1-A \
1588               "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B
1589
1590         # Create route exception by exceeding link layer MTU
1591         mtu "${ns_a}"  veth_A-R1 $((${ll_mtu} + 1000))
1592         mtu "${ns_r1}" veth_R1-A $((${ll_mtu} + 1000))
1593         mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
1594         mtu "${ns_r1}" veth_R1-B ${ll_mtu}
1595
1596         mtu "${ns_a}" ${encap}_a $((${ll_mtu} + 1000))
1597         mtu "${ns_b}" ${encap}_b $((${ll_mtu} + 1000))
1598
1599         # Fill exception cache for multiple CPUs (2)
1600         # we can always use inner IPv4 for that
1601         for cpu in ${cpu_list}; do
1602                 run_cmd taskset --cpu-list ${cpu} ${ns_a} ping -q -M want -i 0.1 -w 1 -s $((${ll_mtu} + 500)) ${tunnel4_b_addr}
1603         done
1604
1605         ${ns_a} ip link del dev veth_A-R1 &
1606         iplink_pid=$!
1607         sleep 1
1608         if [ "$(cat /proc/${iplink_pid}/cmdline 2>/dev/null | tr -d '\0')" = "iplinkdeldevveth_A-R1" ]; then
1609                 err "  can't delete veth device in a timely manner, PMTU dst likely leaked"
1610                 return 1
1611         fi
1612 }
1613
1614 test_cleanup_ipv6_exception() {
1615         test_cleanup_vxlanX_exception 6
1616 }
1617
1618 test_cleanup_ipv4_exception() {
1619         test_cleanup_vxlanX_exception 4
1620 }
1621
1622 run_test() {
1623         (
1624         tname="$1"
1625         tdesc="$2"
1626
1627         unset IFS
1628
1629         if [ "$VERBOSE" = "1" ]; then
1630                 printf "\n##########################################################################\n\n"
1631         fi
1632
1633         eval test_${tname}
1634         ret=$?
1635
1636         if [ $ret -eq 0 ]; then
1637                 printf "TEST: %-60s  [ OK ]\n" "${tdesc}"
1638         elif [ $ret -eq 1 ]; then
1639                 printf "TEST: %-60s  [FAIL]\n" "${tdesc}"
1640                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
1641                         echo
1642                         echo "Pausing. Hit enter to continue"
1643                         read a
1644                 fi
1645                 err_flush
1646                 exit 1
1647         elif [ $ret -eq $ksft_skip ]; then
1648                 printf "TEST: %-60s  [SKIP]\n" "${tdesc}"
1649                 err_flush
1650         fi
1651
1652         return $ret
1653         )
1654         ret=$?
1655         case $ret in
1656                 0)
1657                         all_skipped=false
1658                         [ $exitcode=$ksft_skip ] && exitcode=0
1659                 ;;
1660                 $ksft_skip)
1661                         [ $all_skipped = true ] && exitcode=$ksft_skip
1662                 ;;
1663                 *)
1664                         all_skipped=false
1665                         exitcode=1
1666                 ;;
1667         esac
1668
1669         return $ret
1670 }
1671
1672 run_test_nh() {
1673         tname="$1"
1674         tdesc="$2"
1675
1676         USE_NH=yes
1677         run_test "${tname}" "${tdesc} - nexthop objects"
1678         USE_NH=no
1679 }
1680
1681 test_list_flush_ipv4_exception() {
1682         setup namespaces routing || return $ksft_skip
1683         trace "${ns_a}"  veth_A-R1    "${ns_r1}" veth_R1-A \
1684               "${ns_r1}" veth_R1-B    "${ns_b}"  veth_B-R1 \
1685               "${ns_a}"  veth_A-R2    "${ns_r2}" veth_R2-A \
1686               "${ns_r2}" veth_R2-B    "${ns_b}"  veth_B-R2
1687
1688         dst_prefix1="${prefix4}.${b_r1}."
1689         dst2="${prefix4}.${b_r2}.1"
1690
1691         # Set up initial MTU values
1692         mtu "${ns_a}"  veth_A-R1 2000
1693         mtu "${ns_r1}" veth_R1-A 2000
1694         mtu "${ns_r1}" veth_R1-B 1500
1695         mtu "${ns_b}"  veth_B-R1 1500
1696
1697         mtu "${ns_a}"  veth_A-R2 2000
1698         mtu "${ns_r2}" veth_R2-A 2000
1699         mtu "${ns_r2}" veth_R2-B 1500
1700         mtu "${ns_b}"  veth_B-R2 1500
1701
1702         fail=0
1703
1704         # Add 100 addresses for veth endpoint on B reached by default A route
1705         for i in $(seq 100 199); do
1706                 run_cmd ${ns_b} ip addr add "${dst_prefix1}${i}" dev veth_B-R1
1707         done
1708
1709         # Create 100 cached route exceptions for path via R1, one via R2. Note
1710         # that with IPv4 we need to actually cause a route lookup that matches
1711         # the exception caused by ICMP, in order to actually have a cached
1712         # route, so we need to ping each destination twice
1713         for i in $(seq 100 199); do
1714                 run_cmd ${ns_a} ping -q -M want -i 0.1 -c 2 -s 1800 "${dst_prefix1}${i}"
1715         done
1716         run_cmd ${ns_a} ping -q -M want -i 0.1 -c 2 -s 1800 "${dst2}"
1717
1718         if [ "$(${ns_a} ip -oneline route list cache | wc -l)" -ne 101 ]; then
1719                 err "  can't list cached exceptions"
1720                 fail=1
1721         fi
1722
1723         run_cmd ${ns_a} ip route flush cache
1724         pmtu1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst_prefix}1)"
1725         pmtu2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst_prefix}2)"
1726         if [ -n "${pmtu1}" ] || [ -n "${pmtu2}" ] || \
1727            [ -n "$(${ns_a} ip route list cache)" ]; then
1728                 err "  can't flush cached exceptions"
1729                 fail=1
1730         fi
1731
1732         return ${fail}
1733 }
1734
1735 test_list_flush_ipv6_exception() {
1736         setup namespaces routing || return $ksft_skip
1737         trace "${ns_a}"  veth_A-R1    "${ns_r1}" veth_R1-A \
1738               "${ns_r1}" veth_R1-B    "${ns_b}"  veth_B-R1 \
1739               "${ns_a}"  veth_A-R2    "${ns_r2}" veth_R2-A \
1740               "${ns_r2}" veth_R2-B    "${ns_b}"  veth_B-R2
1741
1742         dst_prefix1="${prefix6}:${b_r1}::"
1743         dst2="${prefix6}:${b_r2}::1"
1744
1745         # Set up initial MTU values
1746         mtu "${ns_a}"  veth_A-R1 2000
1747         mtu "${ns_r1}" veth_R1-A 2000
1748         mtu "${ns_r1}" veth_R1-B 1500
1749         mtu "${ns_b}"  veth_B-R1 1500
1750
1751         mtu "${ns_a}"  veth_A-R2 2000
1752         mtu "${ns_r2}" veth_R2-A 2000
1753         mtu "${ns_r2}" veth_R2-B 1500
1754         mtu "${ns_b}"  veth_B-R2 1500
1755
1756         fail=0
1757
1758         # Add 100 addresses for veth endpoint on B reached by default A route
1759         for i in $(seq 100 199); do
1760                 run_cmd ${ns_b} ip addr add "${dst_prefix1}${i}" dev veth_B-R1
1761         done
1762
1763         # Create 100 cached route exceptions for path via R1, one via R2
1764         for i in $(seq 100 199); do
1765                 run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s 1800 "${dst_prefix1}${i}"
1766         done
1767         run_cmd ${ns_a} ping -q -M want -i 0.1 -w 1 -s 1800 "${dst2}"
1768         if [ "$(${ns_a} ip -oneline -6 route list cache | wc -l)" -ne 101 ]; then
1769                 err "  can't list cached exceptions"
1770                 fail=1
1771         fi
1772
1773         run_cmd ${ns_a} ip -6 route flush cache
1774         pmtu1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst_prefix1}100")"
1775         pmtu2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
1776         if [ -n "${pmtu1}" ] || [ -n "${pmtu2}" ] || \
1777            [ -n "$(${ns_a} ip -6 route list cache)" ]; then
1778                 err "  can't flush cached exceptions"
1779                 fail=1
1780         fi
1781
1782         return ${fail}
1783 }
1784
1785 usage() {
1786         echo
1787         echo "$0 [OPTIONS] [TEST]..."
1788         echo "If no TEST argument is given, all tests will be run."
1789         echo
1790         echo "Options"
1791         echo "  --trace: capture traffic to TEST_INTERFACE.pcap"
1792         echo
1793         echo "Available tests${tests}"
1794         exit 1
1795 }
1796
1797 ################################################################################
1798 #
1799 exitcode=0
1800 desc=0
1801 all_skipped=true
1802
1803 while getopts :ptv o
1804 do
1805         case $o in
1806         p) PAUSE_ON_FAIL=yes;;
1807         v) VERBOSE=1;;
1808         t) if which tcpdump > /dev/null 2>&1; then
1809                 TRACING=1
1810            else
1811                 echo "=== tcpdump not available, tracing disabled"
1812            fi
1813            ;;
1814         *) usage;;
1815         esac
1816 done
1817 shift $(($OPTIND-1))
1818
1819 IFS="   
1820 "
1821
1822 for arg do
1823         # Check first that all requested tests are available before running any
1824         command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; }
1825 done
1826
1827 trap cleanup EXIT
1828
1829 # start clean
1830 cleanup
1831
1832 HAVE_NH=no
1833 ip nexthop ls >/dev/null 2>&1
1834 [ $? -eq 0 ] && HAVE_NH=yes
1835
1836 name=""
1837 desc=""
1838 rerun_nh=0
1839 for t in ${tests}; do
1840         [ "${name}" = "" ]      && name="${t}"  && continue
1841         [ "${desc}" = "" ]      && desc="${t}"  && continue
1842
1843         if [ "${HAVE_NH}" = "yes" ]; then
1844                 rerun_nh="${t}"
1845         fi
1846
1847         run_this=1
1848         for arg do
1849                 [ "${arg}" != "${arg#--*}" ] && continue
1850                 [ "${arg}" = "${name}" ] && run_this=1 && break
1851                 run_this=0
1852         done
1853         if [ $run_this -eq 1 ]; then
1854                 run_test "${name}" "${desc}"
1855                 # if test was skipped no need to retry with nexthop objects
1856                 [ $? -eq $ksft_skip ] && rerun_nh=0
1857
1858                 if [ "${rerun_nh}" = "1" ]; then
1859                         run_test_nh "${name}" "${desc}"
1860                 fi
1861         fi
1862         name=""
1863         desc=""
1864         rerun_nh=0
1865 done
1866
1867 exit ${exitcode}