selftests: forwarding: Fix ping failure due to short timeout
[sfrench/cifs-2.6.git] / tools / testing / selftests / net / forwarding / vxlan_bridge_1d_ipv6.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3
4 # +-----------------------+                          +------------------------+
5 # | H1 (vrf)              |                          | H2 (vrf)               |
6 # |    + $h1              |                          |    + $h2               |
7 # |    | 192.0.2.1/28     |                          |    | 192.0.2.2/28      |
8 # |    | 2001:db8:1::1/64 |                          |    | 2001:db8:1::2/64  |
9 # +----|------------------+                          +----|-------------------+
10 #      |                                                  |
11 # +----|--------------------------------------------------|-------------------+
12 # | SW |                                                  |                   |
13 # | +--|--------------------------------------------------|-----------------+ |
14 # | |  + $swp1                   BR1 (802.1d)             + $swp2           | |
15 # | |                                                                       | |
16 # | |  + vx1 (vxlan)                                                        | |
17 # | |    local 2001:db8:3::1                                                | |
18 # | |    remote 2001:db8:4::1 2001:db8:5::1                                 | |
19 # | |    id 1000 dstport $VXPORT                                            | |
20 # | +-----------------------------------------------------------------------+ |
21 # |                                                                           |
22 # |  2001:db8:4::0/64 via 2001:db8:3::2                                       |
23 # |  2001:db8:5::0/64 via 2001:db8:3::2                                       |
24 # |                                                                           |
25 # |    + $rp1                                                                 |
26 # |    | 2001:db8:3::1/64                                                     |
27 # +----|----------------------------------------------------------------------+
28 #      |
29 # +----|----------------------------------------------------------+
30 # |    |                                             VRP2 (vrf)   |
31 # |    + $rp2                                                     |
32 # |      2001:db8:3::2/64                                         |
33 # |                                                               |  (maybe) HW
34 # =============================================================================
35 # |                                                               |  (likely) SW
36 # |    + v1 (veth)                             + v3 (veth)        |
37 # |    | 2001:db8:4::2/64                      | 2001:db8:5::2/64 |
38 # +----|---------------------------------------|------------------+
39 #      |                                       |
40 # +----|--------------------------------+ +----|-------------------------------+
41 # |    + v2 (veth)        NS1 (netns)   | |    + v4 (veth)        NS2 (netns)  |
42 # |      2001:db8:4::1/64               | |      2001:db8:5::1/64              |
43 # |                                     | |                                    |
44 # | 2001:db8:3::0/64 via 2001:db8:4::2  | | 2001:db8:3::0/64 via 2001:db8:5::2 |
45 # | 2001:db8:5::1/128 via 2001:db8:4::2 | | 2001:db8:4::1/128 via              |
46 # |                                     | |         2001:db8:5::2              |
47 # |                                     | |                                    |
48 # | +-------------------------------+   | | +-------------------------------+  |
49 # | |                  BR2 (802.1d) |   | | |                  BR2 (802.1d) |  |
50 # | |  + vx2 (vxlan)                |   | | |  + vx2 (vxlan)                |  |
51 # | |    local 2001:db8:4::1        |   | | |    local 2001:db8:5::1        |  |
52 # | |    remote 2001:db8:3::1       |   | | |    remote 2001:db8:3::1       |  |
53 # | |    remote 2001:db8:5::1       |   | | |    remote 2001:db8:4::1       |  |
54 # | |    id 1000 dstport $VXPORT    |   | | |    id 1000 dstport $VXPORT    |  |
55 # | |                               |   | | |                               |  |
56 # | |  + w1 (veth)                  |   | | |  + w1 (veth)                  |  |
57 # | +--|----------------------------+   | | +--|----------------------------+  |
58 # |    |                                | |    |                               |
59 # | +--|----------------------------+   | | +--|----------------------------+  |
60 # | |  + w2 (veth)        VW2 (vrf) |   | | |  + w2 (veth)        VW2 (vrf) |  |
61 # | |    192.0.2.3/28               |   | | |    192.0.2.4/28               |  |
62 # | |    2001:db8:1::3/64           |   | | |    2001:db8:1::4/64           |  |
63 # | +-------------------------------+   | | +-------------------------------+  |
64 # +-------------------------------------+ +------------------------------------+
65
66 : ${VXPORT:=4789}
67 export VXPORT
68
69 : ${ALL_TESTS:="
70         ping_ipv4
71         ping_ipv6
72         test_flood
73         test_unicast
74         test_ttl
75         test_tos
76         test_ecn_encap
77         test_ecn_decap
78         reapply_config
79         ping_ipv4
80         ping_ipv6
81         test_flood
82         test_unicast
83 "}
84
85 NUM_NETIFS=6
86 source lib.sh
87 source tc_common.sh
88
89 h1_create()
90 {
91         simple_if_init $h1 192.0.2.1/28 2001:db8:1::1/64
92         tc qdisc add dev $h1 clsact
93 }
94
95 h1_destroy()
96 {
97         tc qdisc del dev $h1 clsact
98         simple_if_fini $h1 192.0.2.1/28 2001:db8:1::1/64
99 }
100
101 h2_create()
102 {
103         simple_if_init $h2 192.0.2.2/28 2001:db8:1::2/64
104         tc qdisc add dev $h2 clsact
105 }
106
107 h2_destroy()
108 {
109         tc qdisc del dev $h2 clsact
110         simple_if_fini $h2 192.0.2.2/28 2001:db8:1::2/64
111 }
112
113 rp1_set_addr()
114 {
115         ip address add dev $rp1 2001:db8:3::1/64
116
117         ip route add 2001:db8:4::0/64 nexthop via 2001:db8:3::2
118         ip route add 2001:db8:5::0/64 nexthop via 2001:db8:3::2
119 }
120
121 rp1_unset_addr()
122 {
123         ip route del 2001:db8:5::0/64 nexthop via 2001:db8:3::2
124         ip route del 2001:db8:4::0/64 nexthop via 2001:db8:3::2
125
126         ip address del dev $rp1 2001:db8:3::1/64
127 }
128
129 switch_create()
130 {
131         ip link add name br1 type bridge vlan_filtering 0 mcast_snooping 0
132         # Make sure the bridge uses the MAC address of the local port and not
133         # that of the VxLAN's device.
134         ip link set dev br1 address $(mac_get $swp1)
135         ip link set dev br1 up
136
137         ip link set dev $rp1 up
138         rp1_set_addr
139         tc qdisc add dev $rp1 clsact
140
141         ip link add name vx1 type vxlan id 1000 local 2001:db8:3::1 \
142                 dstport "$VXPORT" nolearning udp6zerocsumrx udp6zerocsumtx \
143                 tos inherit ttl 100
144         ip link set dev vx1 up
145
146         ip link set dev vx1 master br1
147         ip link set dev $swp1 master br1
148         ip link set dev $swp1 up
149         tc qdisc add dev $swp1 clsact
150
151         ip link set dev $swp2 master br1
152         ip link set dev $swp2 up
153
154         bridge fdb append dev vx1 00:00:00:00:00:00 dst 2001:db8:4::1 self
155         bridge fdb append dev vx1 00:00:00:00:00:00 dst 2001:db8:5::1 self
156 }
157
158 switch_destroy()
159 {
160         bridge fdb del dev vx1 00:00:00:00:00:00 dst 2001:db8:5::1 self
161         bridge fdb del dev vx1 00:00:00:00:00:00 dst 2001:db8:4::1 self
162
163         ip link set dev $swp2 down
164         ip link set dev $swp2 nomaster
165
166         tc qdisc del dev $swp1 clsact
167         ip link set dev $swp1 down
168         ip link set dev $swp1 nomaster
169
170         ip link set dev vx1 nomaster
171         ip link set dev vx1 down
172         ip link del dev vx1
173
174         tc qdisc del dev $rp1 clsact
175         rp1_unset_addr
176         ip link set dev $rp1 down
177
178         ip link set dev br1 down
179         ip link del dev br1
180 }
181
182 vrp2_create()
183 {
184         simple_if_init $rp2 2001:db8:3::2/64
185         __simple_if_init v1 v$rp2 2001:db8:4::2/64
186         __simple_if_init v3 v$rp2 2001:db8:5::2/64
187         tc qdisc add dev v1 clsact
188 }
189
190 vrp2_destroy()
191 {
192         tc qdisc del dev v1 clsact
193         __simple_if_fini v3 2001:db8:5::2/64
194         __simple_if_fini v1 2001:db8:4::2/64
195         simple_if_fini $rp2 2001:db8:3::2/64
196 }
197
198 ns_init_common()
199 {
200         local in_if=$1; shift
201         local in_addr=$1; shift
202         local other_in_addr=$1; shift
203         local nh_addr=$1; shift
204         local host_addr_ipv4=$1; shift
205         local host_addr_ipv6=$1; shift
206
207         ip link set dev $in_if up
208         ip address add dev $in_if $in_addr/64
209         tc qdisc add dev $in_if clsact
210
211         ip link add name br2 type bridge vlan_filtering 0
212         ip link set dev br2 up
213
214         ip link add name w1 type veth peer name w2
215
216         ip link set dev w1 master br2
217         ip link set dev w1 up
218
219         ip link add name vx2 type vxlan id 1000 local $in_addr \
220                 dstport "$VXPORT" udp6zerocsumrx
221         ip link set dev vx2 up
222         bridge fdb append dev vx2 00:00:00:00:00:00 dst 2001:db8:3::1 self
223         bridge fdb append dev vx2 00:00:00:00:00:00 dst $other_in_addr self
224
225         ip link set dev vx2 master br2
226         tc qdisc add dev vx2 clsact
227
228         simple_if_init w2 $host_addr_ipv4/28 $host_addr_ipv6/64
229
230         ip route add 2001:db8:3::0/64 nexthop via $nh_addr
231         ip route add $other_in_addr/128 nexthop via $nh_addr
232 }
233 export -f ns_init_common
234
235 ns1_create()
236 {
237         ip netns add ns1
238         ip link set dev v2 netns ns1
239         in_ns ns1 \
240               ns_init_common v2 2001:db8:4::1 2001:db8:5::1 2001:db8:4::2 \
241               192.0.2.3 2001:db8:1::3
242 }
243
244 ns1_destroy()
245 {
246         ip netns exec ns1 ip link set dev v2 netns 1
247         ip netns del ns1
248 }
249
250 ns2_create()
251 {
252         ip netns add ns2
253         ip link set dev v4 netns ns2
254         in_ns ns2 \
255               ns_init_common v4 2001:db8:5::1 2001:db8:4::1 2001:db8:5::2 \
256               192.0.2.4 2001:db8:1::4
257 }
258
259 ns2_destroy()
260 {
261         ip netns exec ns2 ip link set dev v4 netns 1
262         ip netns del ns2
263 }
264
265 setup_prepare()
266 {
267         h1=${NETIFS[p1]}
268         swp1=${NETIFS[p2]}
269
270         swp2=${NETIFS[p3]}
271         h2=${NETIFS[p4]}
272
273         rp1=${NETIFS[p5]}
274         rp2=${NETIFS[p6]}
275
276         vrf_prepare
277         forwarding_enable
278
279         h1_create
280         h2_create
281         switch_create
282
283         ip link add name v1 type veth peer name v2
284         ip link add name v3 type veth peer name v4
285         vrp2_create
286         ns1_create
287         ns2_create
288
289         r1_mac=$(in_ns ns1 mac_get w2)
290         r2_mac=$(in_ns ns2 mac_get w2)
291         h2_mac=$(mac_get $h2)
292 }
293
294 cleanup()
295 {
296         pre_cleanup
297
298         ns2_destroy
299         ns1_destroy
300         vrp2_destroy
301         ip link del dev v3
302         ip link del dev v1
303
304         switch_destroy
305         h2_destroy
306         h1_destroy
307
308         forwarding_restore
309         vrf_cleanup
310 }
311
312 # For the first round of tests, vx1 is the first device to get
313 # attached to the bridge, and at that point the local IP is already
314 # configured. Try the other scenario of attaching the devices to a an
315 # already-offloaded bridge, and only then assign the local IP.
316 reapply_config()
317 {
318         log_info "Reapplying configuration"
319
320         bridge fdb del dev vx1 00:00:00:00:00:00 dst 2001:db8:5::1 self
321         bridge fdb del dev vx1 00:00:00:00:00:00 dst 2001:db8:4::1 self
322         ip link set dev vx1 nomaster
323         rp1_unset_addr
324         sleep 5
325
326         ip link set dev vx1 master br1
327         bridge fdb append dev vx1 00:00:00:00:00:00 dst 2001:db8:4::1 self
328         bridge fdb append dev vx1 00:00:00:00:00:00 dst 2001:db8:5::1 self
329         sleep 1
330         rp1_set_addr
331         sleep 5
332 }
333
334 __ping_ipv4()
335 {
336         local vxlan_local_ip=$1; shift
337         local vxlan_remote_ip=$1; shift
338         local src_ip=$1; shift
339         local dst_ip=$1; shift
340         local dev=$1; shift
341         local info=$1; shift
342
343         RET=0
344
345         tc filter add dev $rp1 egress protocol ipv6 pref 1 handle 101 \
346                 flower ip_proto udp src_ip $vxlan_local_ip \
347                 dst_ip $vxlan_remote_ip dst_port $VXPORT $TC_FLAG action pass
348         # Match ICMP-reply packets after decapsulation, so source IP is
349         # destination IP of the ping and destination IP is source IP of the
350         # ping.
351         tc filter add dev $swp1 egress protocol ip pref 1 handle 101 \
352                 flower src_ip $dst_ip dst_ip $src_ip \
353                 $TC_FLAG action pass
354
355         # Send 100 packets and verify that at least 100 packets hit the rule,
356         # to overcome ARP noise.
357         PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip
358         check_err $? "Ping failed"
359
360         tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100
361         check_err $? "Encapsulated packets did not go through router"
362
363         tc_check_at_least_x_packets "dev $swp1 egress" 101 10 100
364         check_err $? "Decapsulated packets did not go through switch"
365
366         log_test "ping: $info"
367
368         tc filter del dev $swp1 egress
369         tc filter del dev $rp1 egress
370 }
371
372 ping_ipv4()
373 {
374         RET=0
375
376         local local_sw_ip=2001:db8:3::1
377         local remote_ns1_ip=2001:db8:4::1
378         local remote_ns2_ip=2001:db8:5::1
379         local h1_ip=192.0.2.1
380         local w2_ns1_ip=192.0.2.3
381         local w2_ns2_ip=192.0.2.4
382
383         ping_test $h1 192.0.2.2 ": local->local"
384
385         __ping_ipv4 $local_sw_ip $remote_ns1_ip $h1_ip $w2_ns1_ip $h1 \
386                 "local->remote 1"
387         __ping_ipv4 $local_sw_ip $remote_ns2_ip $h1_ip $w2_ns2_ip $h1 \
388                 "local->remote 2"
389 }
390
391 __ping_ipv6()
392 {
393         local vxlan_local_ip=$1; shift
394         local vxlan_remote_ip=$1; shift
395         local src_ip=$1; shift
396         local dst_ip=$1; shift
397         local dev=$1; shift
398         local info=$1; shift
399
400         RET=0
401
402         tc filter add dev $rp1 egress protocol ipv6 pref 1 handle 101 \
403                 flower ip_proto udp src_ip $vxlan_local_ip \
404                 dst_ip $vxlan_remote_ip dst_port $VXPORT $TC_FLAG action pass
405         # Match ICMP-reply packets after decapsulation, so source IP is
406         # destination IP of the ping and destination IP is source IP of the
407         # ping.
408         tc filter add dev $swp1 egress protocol ipv6 pref 1 handle 101 \
409                 flower src_ip $dst_ip dst_ip $src_ip $TC_FLAG action pass
410
411         # Send 100 packets and verify that at least 100 packets hit the rule,
412         # to overcome neighbor discovery noise.
413         PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip
414         check_err $? "Ping failed"
415
416         tc_check_at_least_x_packets "dev $rp1 egress" 101 100
417         check_err $? "Encapsulated packets did not go through router"
418
419         tc_check_at_least_x_packets "dev $swp1 egress" 101 100
420         check_err $? "Decapsulated packets did not go through switch"
421
422         log_test "ping6: $info"
423
424         tc filter del dev $swp1 egress
425         tc filter del dev $rp1 egress
426 }
427
428 ping_ipv6()
429 {
430         RET=0
431
432         local local_sw_ip=2001:db8:3::1
433         local remote_ns1_ip=2001:db8:4::1
434         local remote_ns2_ip=2001:db8:5::1
435         local h1_ip=2001:db8:1::1
436         local w2_ns1_ip=2001:db8:1::3
437         local w2_ns2_ip=2001:db8:1::4
438
439         ping6_test $h1 2001:db8:1::2 ": local->local"
440
441         __ping_ipv6 $local_sw_ip $remote_ns1_ip $h1_ip $w2_ns1_ip $h1 \
442                 "local->remote 1"
443         __ping_ipv6 $local_sw_ip $remote_ns2_ip $h1_ip $w2_ns2_ip $h1 \
444                 "local->remote 2"
445 }
446
447 maybe_in_ns()
448 {
449         echo ${1:+in_ns} $1
450 }
451
452 __flood_counter_add_del()
453 {
454         local add_del=$1; shift
455         local dst_ip=$1; shift
456         local dev=$1; shift
457         local ns=$1; shift
458
459         # Putting the ICMP capture both to HW and to SW will end up
460         # double-counting the packets that are trapped to slow path, such as for
461         # the unicast test. Adding either skip_hw or skip_sw fixes this problem,
462         # but with skip_hw, the flooded packets are not counted at all, because
463         # those are dropped due to MAC address mismatch; and skip_sw is a no-go
464         # for veth-based topologies.
465         #
466         # So try to install with skip_sw and fall back to skip_sw if that fails.
467
468         $(maybe_in_ns $ns) tc filter $add_del dev "$dev" ingress \
469            proto ipv6 pref 100 flower dst_ip $dst_ip ip_proto \
470            icmpv6 skip_sw action pass 2>/dev/null || \
471         $(maybe_in_ns $ns) tc filter $add_del dev "$dev" ingress \
472            proto ipv6 pref 100 flower dst_ip $dst_ip ip_proto \
473            icmpv6 skip_hw action pass
474 }
475
476 flood_counter_install()
477 {
478         __flood_counter_add_del add "$@"
479 }
480
481 flood_counter_uninstall()
482 {
483         __flood_counter_add_del del "$@"
484 }
485
486 flood_fetch_stat()
487 {
488         local dev=$1; shift
489         local ns=$1; shift
490
491         $(maybe_in_ns $ns) tc_rule_stats_get $dev 100 ingress
492 }
493
494 flood_fetch_stats()
495 {
496         local counters=("${@}")
497         local counter
498
499         for counter in "${counters[@]}"; do
500                 flood_fetch_stat $counter
501         done
502 }
503
504 vxlan_flood_test()
505 {
506         local mac=$1; shift
507         local dst=$1; shift
508         local -a expects=("${@}")
509
510         local -a counters=($h2 "vx2 ns1" "vx2 ns2")
511         local counter
512         local key
513
514         for counter in "${counters[@]}"; do
515                 flood_counter_install $dst $counter
516         done
517
518         local -a t0s=($(flood_fetch_stats "${counters[@]}"))
519         $MZ -6 $h1 -c 10 -d 100msec -p 64 -b $mac -B $dst -t icmp6 type=128 -q
520         sleep 1
521         local -a t1s=($(flood_fetch_stats "${counters[@]}"))
522
523         for key in ${!t0s[@]}; do
524                 local delta=$((t1s[$key] - t0s[$key]))
525                 local expect=${expects[$key]}
526
527                 ((expect == delta))
528                 check_err $? "${counters[$key]}: Expected to capture $expect packets, got $delta."
529         done
530
531         for counter in "${counters[@]}"; do
532                 flood_counter_uninstall $dst $counter
533         done
534 }
535
536 __test_flood()
537 {
538         local mac=$1; shift
539         local dst=$1; shift
540         local what=$1; shift
541
542         RET=0
543
544         vxlan_flood_test $mac $dst 10 10 10
545
546         log_test "VXLAN: $what"
547 }
548
549 test_flood()
550 {
551         __test_flood de:ad:be:ef:13:37 2001:db8:1::100 "flood"
552 }
553
554 vxlan_fdb_add_del()
555 {
556         local add_del=$1; shift
557         local mac=$1; shift
558         local dev=$1; shift
559         local dst=$1; shift
560
561         bridge fdb $add_del dev $dev $mac self static permanent \
562                 ${dst:+dst} $dst 2>/dev/null
563         bridge fdb $add_del dev $dev $mac master static 2>/dev/null
564 }
565
566 __test_unicast()
567 {
568         local mac=$1; shift
569         local dst=$1; shift
570         local hit_idx=$1; shift
571         local what=$1; shift
572
573         RET=0
574
575         local -a expects=(0 0 0)
576         expects[$hit_idx]=10
577
578         vxlan_flood_test $mac $dst "${expects[@]}"
579
580         log_test "VXLAN: $what"
581 }
582
583 test_unicast()
584 {
585         local -a targets=("$h2_mac $h2"
586                           "$r1_mac vx1 2001:db8:4::1"
587                           "$r2_mac vx1 2001:db8:5::1")
588         local target
589
590         for target in "${targets[@]}"; do
591                 vxlan_fdb_add_del add $target
592         done
593
594         __test_unicast $h2_mac 2001:db8:1::2 0 "local MAC unicast"
595         __test_unicast $r1_mac 2001:db8:1::3 1 "remote MAC 1 unicast"
596         __test_unicast $r2_mac 2001:db8:1::4 2 "remote MAC 2 unicast"
597
598         for target in "${targets[@]}"; do
599                 vxlan_fdb_add_del del $target
600         done
601 }
602
603 vxlan_ping_test()
604 {
605         local ping_dev=$1; shift
606         local ping_dip=$1; shift
607         local ping_args=$1; shift
608         local capture_dev=$1; shift
609         local capture_dir=$1; shift
610         local capture_pref=$1; shift
611         local expect=$1; shift
612
613         local t0=$(tc_rule_stats_get $capture_dev $capture_pref $capture_dir)
614         ping6_do $ping_dev $ping_dip "$ping_args"
615         local t1=$(tc_rule_stats_get $capture_dev $capture_pref $capture_dir)
616         local delta=$((t1 - t0))
617
618         # Tolerate a couple stray extra packets.
619         ((expect <= delta && delta <= expect + 5))
620         check_err $? "$capture_dev: Expected to capture $expect packets, got $delta."
621 }
622
623 test_ttl()
624 {
625         RET=0
626
627         tc filter add dev v1 egress pref 77 protocol ipv6 \
628                 flower ip_ttl 99 action pass
629         vxlan_ping_test $h1 2001:db8:1::3 "" v1 egress 77 10
630         tc filter del dev v1 egress pref 77 protocol ipv6
631
632         log_test "VXLAN: envelope TTL"
633 }
634
635 test_tos()
636 {
637         RET=0
638
639         tc filter add dev v1 egress pref 77 protocol ipv6 \
640                 flower ip_tos 0x14 action pass
641         vxlan_ping_test $h1 2001:db8:1::3 "-Q 0x14" v1 egress 77 10
642         vxlan_ping_test $h1 2001:db8:1::3 "-Q 0x18" v1 egress 77 0
643         tc filter del dev v1 egress pref 77 protocol ipv6
644
645         log_test "VXLAN: envelope TOS inheritance"
646 }
647
648 __test_ecn_encap()
649 {
650         local q=$1; shift
651         local tos=$1; shift
652
653         RET=0
654
655         tc filter add dev v1 egress pref 77 protocol ipv6 \
656                 flower ip_tos $tos ip_proto udp dst_port $VXPORT action pass
657         sleep 1
658         vxlan_ping_test $h1 2001:db8:1::3 "-Q $q" v1 egress 77 10
659         tc filter del dev v1 egress pref 77 protocol ipv6
660
661         log_test "VXLAN: ECN encap: $q->$tos"
662 }
663
664 test_ecn_encap()
665 {
666         # In accordance with INET_ECN_encapsulate()
667         __test_ecn_encap 0x00 0x00
668         __test_ecn_encap 0x01 0x01
669         __test_ecn_encap 0x02 0x02
670         __test_ecn_encap 0x03 0x02
671 }
672
673 vxlan_encapped_ping_do()
674 {
675         local count=$1; shift
676         local dev=$1; shift
677         local next_hop_mac=$1; shift
678         local dest_ip=$1; shift
679         local dest_mac=$1; shift
680         local inner_tos=$1; shift
681         local outer_tos=$1; shift
682         local saddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:03"
683         local daddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01"
684
685         $MZ -6 $dev -c $count -d 100msec -q \
686                 -b $next_hop_mac -B $dest_ip \
687                 -t udp tos=$outer_tos,sp=23456,dp=$VXPORT,p=$(:
688                     )"08:"$(                      : VXLAN flags
689                     )"00:00:00:"$(                : VXLAN reserved
690                     )"00:03:e8:"$(                : VXLAN VNI
691                     )"00:"$(                      : VXLAN reserved
692                     )"$dest_mac:"$(               : ETH daddr
693                     )"$(mac_get w2):"$(           : ETH saddr
694                     )"86:dd:"$(                   : ETH type
695                     )"6"$(                        : IP version
696                     )"$inner_tos"$(               : Traffic class
697                     )"0:00:00:"$(                 : Flow label
698                     )"00:08:"$(                   : Payload length
699                     )"3a:"$(                      : Next header
700                     )"04:"$(                      : Hop limit
701                     )"$saddr:"$(                  : IP saddr
702                     )"$daddr:"$(                  : IP daddr
703                     )"80:"$(                      : ICMPv6.type
704                     )"00:"$(                      : ICMPv6.code
705                     )"00:"$(                      : ICMPv6.checksum
706                     )
707 }
708 export -f vxlan_encapped_ping_do
709
710 vxlan_encapped_ping_test()
711 {
712         local ping_dev=$1; shift
713         local nh_dev=$1; shift
714         local ping_dip=$1; shift
715         local inner_tos=$1; shift
716         local outer_tos=$1; shift
717         local stat_get=$1; shift
718         local expect=$1; shift
719
720         local t0=$($stat_get)
721
722         in_ns ns1 \
723                 vxlan_encapped_ping_do 10 $ping_dev $(mac_get $nh_dev) \
724                         $ping_dip $(mac_get $h1) \
725                         $inner_tos $outer_tos
726         sleep 1
727         local t1=$($stat_get)
728         local delta=$((t1 - t0))
729
730         # Tolerate a couple stray extra packets.
731         ((expect <= delta && delta <= expect + 2))
732         check_err $? "Expected to capture $expect packets, got $delta."
733 }
734 export -f vxlan_encapped_ping_test
735
736 __test_ecn_decap()
737 {
738         local orig_inner_tos=$1; shift
739         local orig_outer_tos=$1; shift
740         local decapped_tos=$1; shift
741
742         RET=0
743
744         tc filter add dev $h1 ingress pref 77 protocol ipv6 \
745                 flower src_ip 2001:db8:1::3 dst_ip 2001:db8:1::1 \
746                 ip_tos $decapped_tos action drop
747         sleep 1
748         vxlan_encapped_ping_test v2 v1 2001:db8:3::1 \
749                                  $orig_inner_tos $orig_outer_tos \
750                                  "tc_rule_stats_get $h1 77 ingress" 10
751         tc filter del dev $h1 ingress pref 77
752
753         log_test "VXLAN: ECN decap: $orig_outer_tos/$orig_inner_tos->$decapped_tos"
754 }
755
756 test_ecn_decap_error()
757 {
758         local orig_inner_tos="0:0"
759         local orig_outer_tos=03
760
761         RET=0
762
763         vxlan_encapped_ping_test v2 v1 2001:db8:3::1 \
764                                  $orig_inner_tos $orig_outer_tos \
765                                  "link_stats_rx_errors_get vx1" 10
766
767         log_test "VXLAN: ECN decap: $orig_outer_tos/$orig_inner_tos->error"
768 }
769
770 test_ecn_decap()
771 {
772         # In accordance with INET_ECN_decapsulate()
773         __test_ecn_decap "0:0" 00 0x00
774         __test_ecn_decap "0:0" 01 0x00
775         __test_ecn_decap "0:0" 02 0x00
776         # 00 03 is tested in test_ecn_decap_error()
777         __test_ecn_decap "0:1" 00 0x01
778         __test_ecn_decap "0:1" 01 0x01
779         __test_ecn_decap "0:1" 02 0x01
780         __test_ecn_decap "0:1" 03 0x03
781         __test_ecn_decap "0:2" 00 0x02
782         __test_ecn_decap "0:2" 01 0x01
783         __test_ecn_decap "0:2" 02 0x02
784         __test_ecn_decap "0:2" 03 0x03
785         __test_ecn_decap "0:3" 00 0x03
786         __test_ecn_decap "0:3" 01 0x03
787         __test_ecn_decap "0:3" 02 0x03
788         __test_ecn_decap "0:3" 03 0x03
789         test_ecn_decap_error
790 }
791
792 test_all()
793 {
794         log_info "Running tests with UDP port $VXPORT"
795         tests_run
796 }
797
798 trap cleanup EXIT
799
800 setup_prepare
801 setup_wait
802 test_all
803
804 exit $EXIT_STATUS