cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vxlan_bridge_1d_ipv6.sh (21791B)


      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}
     67export 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
     85NUM_NETIFS=6
     86source lib.sh
     87source tc_common.sh
     88
     89h1_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
     95h1_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
    101h2_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
    107h2_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
    113rp1_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
    121rp1_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
    129switch_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
    158switch_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
    182vrp2_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
    190vrp2_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
    198ns_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}
    233export -f ns_init_common
    234
    235ns1_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
    244ns1_destroy()
    245{
    246	ip netns exec ns1 ip link set dev v2 netns 1
    247	ip netns del ns1
    248}
    249
    250ns2_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
    259ns2_destroy()
    260{
    261	ip netns exec ns2 ip link set dev v4 netns 1
    262	ip netns del ns2
    263}
    264
    265setup_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
    294cleanup()
    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.
    316reapply_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=11 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
    372ping_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=11 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
    428ping_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
    447maybe_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
    476flood_counter_install()
    477{
    478	__flood_counter_add_del add "$@"
    479}
    480
    481flood_counter_uninstall()
    482{
    483	__flood_counter_add_del del "$@"
    484}
    485
    486flood_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
    494flood_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
    504vxlan_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
    549test_flood()
    550{
    551	__test_flood de:ad:be:ef:13:37 2001:db8:1::100 "flood"
    552}
    553
    554vxlan_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
    583test_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
    603vxlan_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 + 2))
    620	check_err $? "$capture_dev: Expected to capture $expect packets, got $delta."
    621}
    622
    623test_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
    635test_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 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
    664test_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
    673vxlan_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}
    708export -f vxlan_encapped_ping_do
    709
    710vxlan_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}
    734export -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
    756test_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
    770test_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
    792test_all()
    793{
    794	log_info "Running tests with UDP port $VXPORT"
    795	tests_run
    796}
    797
    798trap cleanup EXIT
    799
    800setup_prepare
    801setup_wait
    802test_all
    803
    804exit $EXIT_STATUS