mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-16 11:12:30 +00:00

Run VXLAN packets through a gateway. Flip individual bits of the packet and/or reserved bits of the gateway, and check that the gateway treats the packets as expected. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Link: https://patch.msgid.link/388bef3c30ebc887d4e64cd86a362e2df2f2d2e1.1733412063.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
353 lines
7.2 KiB
Bash
Executable File
353 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
# +--------------------+
|
|
# | H1 (vrf) |
|
|
# | + $h1 |
|
|
# | | 192.0.2.1/28 |
|
|
# +----|---------------+
|
|
# |
|
|
# +----|--------------------------------+
|
|
# | SW | |
|
|
# | +--|------------------------------+ |
|
|
# | | + $swp1 BR1 (802.1d) | |
|
|
# | | | |
|
|
# | | + vx1 (vxlan) | |
|
|
# | | local 192.0.2.17 | |
|
|
# | | id 1000 dstport $VXPORT | |
|
|
# | +---------------------------------+ |
|
|
# | |
|
|
# | 192.0.2.32/28 via 192.0.2.18 |
|
|
# | |
|
|
# | + $rp1 |
|
|
# | | 192.0.2.17/28 |
|
|
# +--|----------------------------------+
|
|
# |
|
|
# +--|----------------------------------+
|
|
# | | |
|
|
# | + $rp2 |
|
|
# | 192.0.2.18/28 |
|
|
# | |
|
|
# | VRP2 (vrf) |
|
|
# +-------------------------------------+
|
|
|
|
: ${VXPORT:=4789}
|
|
: ${ALL_TESTS:="
|
|
default_test
|
|
plain_test
|
|
reserved_0_test
|
|
reserved_10_test
|
|
reserved_31_test
|
|
reserved_56_test
|
|
reserved_63_test
|
|
"}
|
|
|
|
NUM_NETIFS=4
|
|
source lib.sh
|
|
|
|
h1_create()
|
|
{
|
|
simple_if_init $h1 192.0.2.1/28
|
|
defer simple_if_fini $h1 192.0.2.1/28
|
|
|
|
tc qdisc add dev $h1 clsact
|
|
defer tc qdisc del dev $h1 clsact
|
|
|
|
tc filter add dev $h1 ingress pref 77 \
|
|
prot ip flower skip_hw ip_proto icmp action drop
|
|
defer tc filter del dev $h1 ingress pref 77
|
|
}
|
|
|
|
switch_create()
|
|
{
|
|
ip_link_add br1 type bridge vlan_filtering 0 mcast_snooping 0
|
|
# Make sure the bridge uses the MAC address of the local port and not
|
|
# that of the VxLAN's device.
|
|
ip_link_set_addr br1 $(mac_get $swp1)
|
|
ip_link_set_up br1
|
|
|
|
ip_link_set_up $rp1
|
|
ip_addr_add $rp1 192.0.2.17/28
|
|
ip_route_add 192.0.2.32/28 nexthop via 192.0.2.18
|
|
|
|
ip_link_set_master $swp1 br1
|
|
ip_link_set_up $swp1
|
|
}
|
|
|
|
vrp2_create()
|
|
{
|
|
simple_if_init $rp2 192.0.2.18/28
|
|
defer simple_if_fini $rp2 192.0.2.18/28
|
|
}
|
|
|
|
setup_prepare()
|
|
{
|
|
h1=${NETIFS[p1]}
|
|
swp1=${NETIFS[p2]}
|
|
|
|
rp1=${NETIFS[p3]}
|
|
rp2=${NETIFS[p4]}
|
|
|
|
vrf_prepare
|
|
defer vrf_cleanup
|
|
|
|
forwarding_enable
|
|
defer forwarding_restore
|
|
|
|
h1_create
|
|
switch_create
|
|
|
|
vrp2_create
|
|
}
|
|
|
|
vxlan_header_bytes()
|
|
{
|
|
local vni=$1; shift
|
|
local -a extra_bits=("$@")
|
|
local -a bits
|
|
local i
|
|
|
|
for ((i=0; i < 64; i++)); do
|
|
bits[i]=0
|
|
done
|
|
|
|
# Bit 4 is the I flag and is always on.
|
|
bits[4]=1
|
|
|
|
for i in ${extra_bits[@]}; do
|
|
bits[i]=1
|
|
done
|
|
|
|
# Bits 32..55 carry the VNI
|
|
local mask=0x800000
|
|
for ((i=0; i < 24; i++)); do
|
|
bits[$((i + 32))]=$(((vni & mask) != 0))
|
|
((mask >>= 1))
|
|
done
|
|
|
|
local bytes
|
|
for ((i=0; i < 8; i++)); do
|
|
local byte=0
|
|
local j
|
|
for ((j=0; j < 8; j++)); do
|
|
local bit=${bits[8 * i + j]}
|
|
((byte += bit << (7 - j)))
|
|
done
|
|
bytes+=$(printf %02x $byte):
|
|
done
|
|
|
|
echo ${bytes%:}
|
|
}
|
|
|
|
neg_bytes()
|
|
{
|
|
local bytes=$1; shift
|
|
|
|
local -A neg=([0]=f [1]=e [2]=d [3]=c [4]=b [5]=a [6]=9 [7]=8
|
|
[8]=7 [9]=6 [a]=5 [b]=4 [c]=3 [d]=2 [e]=1 [f]=0 [:]=:)
|
|
local out
|
|
local i
|
|
|
|
for ((i=0; i < ${#bytes}; i++)); do
|
|
local c=${bytes:$i:1}
|
|
out+=${neg[$c]}
|
|
done
|
|
echo $out
|
|
}
|
|
|
|
vxlan_ping_do()
|
|
{
|
|
local count=$1; shift
|
|
local dev=$1; shift
|
|
local next_hop_mac=$1; shift
|
|
local dest_ip=$1; shift
|
|
local dest_mac=$1; shift
|
|
local vni=$1; shift
|
|
local reserved_bits=$1; shift
|
|
|
|
local vxlan_header=$(vxlan_header_bytes $vni $reserved_bits)
|
|
|
|
$MZ $dev -c $count -d 100msec -q \
|
|
-b $next_hop_mac -B $dest_ip \
|
|
-t udp sp=23456,dp=$VXPORT,p=$(:
|
|
)"$vxlan_header:"$( : VXLAN
|
|
)"$dest_mac:"$( : ETH daddr
|
|
)"00:11:22:33:44:55:"$( : ETH saddr
|
|
)"08:00:"$( : ETH type
|
|
)"45:"$( : IP version + IHL
|
|
)"00:"$( : IP TOS
|
|
)"00:54:"$( : IP total length
|
|
)"99:83:"$( : IP identification
|
|
)"40:00:"$( : IP flags + frag off
|
|
)"40:"$( : IP TTL
|
|
)"01:"$( : IP proto
|
|
)"00:00:"$( : IP header csum
|
|
)"$(ipv4_to_bytes 192.0.2.3):"$( : IP saddr
|
|
)"$(ipv4_to_bytes 192.0.2.1):"$( : IP daddr
|
|
)"08:"$( : ICMP type
|
|
)"00:"$( : ICMP code
|
|
)"8b:f2:"$( : ICMP csum
|
|
)"1f:6a:"$( : ICMP request identifier
|
|
)"00:01:"$( : ICMP request seq. number
|
|
)"4f:ff:c5:5b:00:00:00:00:"$( : ICMP payload
|
|
)"6d:74:0b:00:00:00:00:00:"$( :
|
|
)"10:11:12:13:14:15:16:17:"$( :
|
|
)"18:19:1a:1b:1c:1d:1e:1f:"$( :
|
|
)"20:21:22:23:24:25:26:27:"$( :
|
|
)"28:29:2a:2b:2c:2d:2e:2f:"$( :
|
|
)"30:31:32:33:34:35:36:37"
|
|
}
|
|
|
|
vxlan_device_add()
|
|
{
|
|
ip_link_add vx1 up type vxlan id 1000 \
|
|
local 192.0.2.17 dstport "$VXPORT" \
|
|
nolearning noudpcsum tos inherit ttl 100 "$@"
|
|
ip_link_set_master vx1 br1
|
|
}
|
|
|
|
vxlan_all_reserved_bits()
|
|
{
|
|
local i
|
|
|
|
for ((i=0; i < 64; i++)); do
|
|
if ((i == 4 || i >= 32 && i < 56)); then
|
|
continue
|
|
fi
|
|
echo $i
|
|
done
|
|
}
|
|
|
|
vxlan_ping_vanilla()
|
|
{
|
|
vxlan_ping_do 10 $rp2 $(mac_get $rp1) 192.0.2.17 $(mac_get $h1) 1000
|
|
}
|
|
|
|
vxlan_ping_reserved()
|
|
{
|
|
for bit in $(vxlan_all_reserved_bits); do
|
|
vxlan_ping_do 1 $rp2 $(mac_get $rp1) \
|
|
192.0.2.17 $(mac_get $h1) 1000 "$bit"
|
|
((n++))
|
|
done
|
|
}
|
|
|
|
vxlan_ping_test()
|
|
{
|
|
local what=$1; shift
|
|
local get_stat=$1; shift
|
|
local expect=$1; shift
|
|
|
|
RET=0
|
|
|
|
local t0=$($get_stat)
|
|
|
|
"$@"
|
|
check_err $? "Failure when running $@"
|
|
|
|
local t1=$($get_stat)
|
|
local delta=$((t1 - t0))
|
|
|
|
((expect == delta))
|
|
check_err $? "Expected to capture $expect packets, got $delta."
|
|
|
|
log_test "$what"
|
|
}
|
|
|
|
__default_test_do()
|
|
{
|
|
local n_allowed_bits=$1; shift
|
|
local what=$1; shift
|
|
|
|
vxlan_ping_test "$what: clean packets" \
|
|
"tc_rule_stats_get $h1 77 ingress" \
|
|
10 vxlan_ping_vanilla
|
|
|
|
local t0=$(link_stats_get vx1 rx errors)
|
|
vxlan_ping_test "$what: mangled packets" \
|
|
"tc_rule_stats_get $h1 77 ingress" \
|
|
$n_allowed_bits vxlan_ping_reserved
|
|
local t1=$(link_stats_get vx1 rx errors)
|
|
|
|
RET=0
|
|
local expect=$((39 - n_allowed_bits))
|
|
local delta=$((t1 - t0))
|
|
((expect == delta))
|
|
check_err $? "Expected $expect error packets, got $delta."
|
|
log_test "$what: drops reported"
|
|
}
|
|
|
|
default_test_do()
|
|
{
|
|
vxlan_device_add
|
|
__default_test_do 0 "Default"
|
|
}
|
|
|
|
default_test()
|
|
{
|
|
in_defer_scope \
|
|
default_test_do
|
|
}
|
|
|
|
plain_test_do()
|
|
{
|
|
vxlan_device_add reserved_bits 0xf7ffffff000000ff
|
|
__default_test_do 0 "reserved_bits 0xf7ffffff000000ff"
|
|
}
|
|
|
|
plain_test()
|
|
{
|
|
in_defer_scope \
|
|
plain_test_do
|
|
}
|
|
|
|
reserved_test()
|
|
{
|
|
local bit=$1; shift
|
|
|
|
local allowed_bytes=$(vxlan_header_bytes 0xffffff $bit)
|
|
local reserved_bytes=$(neg_bytes $allowed_bytes)
|
|
local reserved_bits=${reserved_bytes//:/}
|
|
|
|
vxlan_device_add reserved_bits 0x$reserved_bits
|
|
__default_test_do 1 "reserved_bits 0x$reserved_bits"
|
|
}
|
|
|
|
reserved_0_test()
|
|
{
|
|
in_defer_scope \
|
|
reserved_test 0
|
|
}
|
|
|
|
reserved_10_test()
|
|
{
|
|
in_defer_scope \
|
|
reserved_test 10
|
|
}
|
|
|
|
reserved_31_test()
|
|
{
|
|
in_defer_scope \
|
|
reserved_test 31
|
|
}
|
|
|
|
reserved_56_test()
|
|
{
|
|
in_defer_scope \
|
|
reserved_test 56
|
|
}
|
|
|
|
reserved_63_test()
|
|
{
|
|
in_defer_scope \
|
|
reserved_test 63
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
setup_prepare
|
|
setup_wait
|
|
tests_run
|
|
|
|
exit $EXIT_STATUS
|