diff options
Diffstat (limited to 'tools/testing/selftests/drivers/net')
27 files changed, 2667 insertions, 260 deletions
| diff --git a/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh b/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh index 5ba5bef44d5b..bdffe698e1d1 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh @@ -45,6 +45,7 @@ ALL_TESTS="  	blackhole_ipv6  "  NUM_NETIFS=4 +: ${TIMEOUT:=20000} # ms  source $lib_dir/tc_common.sh  source $lib_dir/lib.sh @@ -123,7 +124,7 @@ blackhole_ipv4()  		skip_hw dst_ip 198.51.100.1 src_ip 192.0.2.1 ip_proto icmp \  		action pass -	ip -4 route show 198.51.100.0/30 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload ip -4 route show 198.51.100.0/30  	check_err $? "route not marked as offloaded when should"  	ping_do $h1 198.51.100.1 @@ -147,7 +148,7 @@ blackhole_ipv6()  		skip_hw dst_ip 2001:db8:2::1 src_ip 2001:db8:1::1 \  		ip_proto icmpv6 action pass -	ip -6 route show 2001:db8:2::/120 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload ip -6 route show 2001:db8:2::/120  	check_err $? "route not marked as offloaded when should"  	ping6_do $h1 2001:db8:2::1 diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_acl_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_acl_drops.sh new file mode 100755 index 000000000000..26044e397157 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_acl_drops.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test devlink-trap ACL drops functionality over mlxsw. + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" +	ingress_flow_action_drop_test +	egress_flow_action_drop_test +" +NUM_NETIFS=4 +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ +	simple_if_init $h1 +} + +h1_destroy() +{ +	simple_if_fini $h1 +} + +h2_create() +{ +	simple_if_init $h2 +} + +h2_destroy() +{ +	simple_if_fini $h2 +} + +switch_create() +{ +	ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 + +	ip link set dev $swp1 master br0 +	ip link set dev $swp2 master br0 + +	ip link set dev br0 up +	ip link set dev $swp1 up +	ip link set dev $swp2 up + +	tc qdisc add dev $swp1 clsact +	tc qdisc add dev $swp2 clsact +} + +switch_destroy() +{ +	tc qdisc del dev $swp2 clsact +	tc qdisc del dev $swp1 clsact + +	ip link set dev $swp2 down +	ip link set dev $swp1 down + +	ip link del dev br0 +} + +setup_prepare() +{ +	h1=${NETIFS[p1]} +	swp1=${NETIFS[p2]} + +	swp2=${NETIFS[p3]} +	h2=${NETIFS[p4]} + +	h1mac=$(mac_get $h1) +	h2mac=$(mac_get $h2) + +	vrf_prepare + +	h1_create +	h2_create + +	switch_create +} + +cleanup() +{ +	pre_cleanup + +	switch_destroy + +	h2_destroy +	h1_destroy + +	vrf_cleanup +} + +ingress_flow_action_drop_test() +{ +	local mz_pid + +	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ +		flower src_mac $h1mac action pass + +	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 \ +		flower dst_ip 192.0.2.2 action drop + +	$MZ $h1 -c 0 -p 100 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ +		-t ip -d 1msec -q & +	mz_pid=$! + +	RET=0 + +	devlink_trap_drop_test ingress_flow_action_drop acl_drops $swp2 101 + +	log_test "ingress_flow_action_drop" + +	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower + +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 +} + +egress_flow_action_drop_test() +{ +	local mz_pid + +	tc filter add dev $swp2 egress protocol ip pref 2 handle 102 \ +		flower src_mac $h1mac action pass + +	tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ +		flower dst_ip 192.0.2.2 action drop + +	$MZ $h1 -c 0 -p 100 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ +		-t ip -d 1msec -q & +	mz_pid=$! + +	RET=0 + +	devlink_trap_drop_test egress_flow_action_drop acl_drops $swp2 102 + +	log_test "egress_flow_action_drop" + +	tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower + +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 2 102 +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh index 58cdbfb608e9..e7aecb065409 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l2_drops.sh @@ -107,11 +107,11 @@ source_mac_is_multicast_test()  	RET=0 -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	log_test "Source MAC is multicast" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  }  __vlan_tag_mismatch_test() @@ -132,7 +132,7 @@ __vlan_tag_mismatch_test()  	$MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Add PVID and make sure packets are no longer dropped.  	bridge vlan add vid 1 dev $swp1 pvid untagged master @@ -148,7 +148,7 @@ __vlan_tag_mismatch_test()  	devlink_trap_action_set $trap_name "drop" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  }  vlan_tag_mismatch_untagged_test() @@ -193,7 +193,7 @@ ingress_vlan_filter_test()  	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Add the VLAN on the bridge port and make sure packets are no longer  	# dropped. @@ -212,7 +212,7 @@ ingress_vlan_filter_test()  	log_test "Ingress VLAN filter" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  	bridge vlan del vid $vid dev $swp1 master  	bridge vlan del vid $vid dev $swp2 master @@ -237,7 +237,7 @@ __ingress_stp_filter_test()  	$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Change STP state to forwarding and make sure packets are no longer  	# dropped. @@ -254,7 +254,7 @@ __ingress_stp_filter_test()  	devlink_trap_action_set $trap_name "drop" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  	bridge vlan del vid $vid dev $swp1 master  	bridge vlan del vid $vid dev $swp2 master @@ -308,7 +308,7 @@ port_list_is_empty_uc_test()  	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Allow packets to be flooded to one port.  	ip link set dev $swp2 type bridge_slave flood on @@ -326,7 +326,7 @@ port_list_is_empty_uc_test()  	log_test "Port list is empty - unicast" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  	ip link set dev $swp1 type bridge_slave flood on  } @@ -354,7 +354,7 @@ port_list_is_empty_mc_test()  	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Allow packets to be flooded to one port.  	ip link set dev $swp2 type bridge_slave mcast_flood on @@ -372,7 +372,7 @@ port_list_is_empty_mc_test()  	log_test "Port list is empty - multicast" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  	ip link set dev $swp1 type bridge_slave mcast_flood on  } @@ -401,7 +401,7 @@ port_loopback_filter_uc_test()  	$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp2 +	devlink_trap_drop_test $trap_name $group_name $swp2 101  	# Allow packets to be flooded.  	ip link set dev $swp2 type bridge_slave flood on @@ -419,7 +419,7 @@ port_loopback_filter_uc_test()  	log_test "Port loopback filter - unicast" -	devlink_trap_drop_cleanup $mz_pid $swp2 ip +	devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101  }  port_loopback_filter_test() diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh index d88d8e47d11b..616f47d86a61 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh @@ -176,11 +176,11 @@ non_ip_test()  		00:00 de:ad:be:ef" &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Non IP" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101  }  __uc_dip_over_mc_dmac_test() @@ -206,11 +206,11 @@ __uc_dip_over_mc_dmac_test()  		-B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Unicast destination IP over multicast destination MAC: $desc" -	devlink_trap_drop_cleanup $mz_pid $rp2 $proto +	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101  }  uc_dip_over_mc_dmac_test() @@ -242,11 +242,11 @@ __sip_is_loopback_test()  		-b $rp1mac -B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Source IP is loopback address: $desc" -	devlink_trap_drop_cleanup $mz_pid $rp2 $proto +	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101  }  sip_is_loopback_test() @@ -277,11 +277,11 @@ __dip_is_loopback_test()  		-B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Destination IP is loopback address: $desc" -	devlink_trap_drop_cleanup $mz_pid $rp2 $proto +	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101  }  dip_is_loopback_test() @@ -313,11 +313,11 @@ __sip_is_mc_test()  		-b $rp1mac -B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Source IP is multicast: $desc" -	devlink_trap_drop_cleanup $mz_pid $rp2 $proto +	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101  }  sip_is_mc_test() @@ -345,11 +345,11 @@ ipv4_sip_is_limited_bc_test()  		-B $h2_ipv4 -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "IPv4 source IP is limited broadcast" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101  }  ipv4_payload_get() @@ -399,11 +399,11 @@ __ipv4_header_corrupted_test()  	$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "IP header corrupted: $desc: IPv4" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101  }  ipv6_payload_get() @@ -446,11 +446,11 @@ __ipv6_header_corrupted_test()  	$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "IP header corrupted: $desc: IPv6" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101  }  ip_header_corrupted_test() @@ -485,11 +485,11 @@ ipv6_mc_dip_reserved_scope_test()  		"33:33:00:00:00:00" -B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "IPv6 multicast destination IP reserved scope" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101  }  ipv6_mc_dip_interface_local_scope_test() @@ -511,11 +511,11 @@ ipv6_mc_dip_interface_local_scope_test()  		"33:33:00:00:00:00" -B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "IPv6 multicast destination IP interface-local scope" -	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" +	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101  }  __blackhole_route_test() @@ -542,10 +542,10 @@ __blackhole_route_test()  		-B $dip -d 1msec -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $rp2 +	devlink_trap_drop_test $trap_name $group_name $rp2 101  	log_test "Blackhole route: IPv$flags" -	devlink_trap_drop_cleanup $mz_pid $rp2 $proto +	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101  	ip -$flags route del blackhole $subnet  } @@ -641,13 +641,9 @@ erif_disabled_test()  	mz_pid=$!  	sleep 5 -	# In order to see this trap we need a route that points to disabled RIF. -	# When ipv6 address is flushed, there is a delay and the routes are -	# deleted before the RIF and we cannot get state that we have route -	# to disabled RIF. -	# Delete IPv6 address first and then check this trap with flushing IPv4. -	ip -6 add flush dev br0 -	ip -4 add flush dev br0 +	# Unlinking the port from the bridge will disable the RIF associated +	# with br0 as it is no longer an upper of any mlxsw port. +	ip link set dev $rp1 nomaster  	t1_packets=$(devlink_trap_rx_packets_get $trap_name)  	t1_bytes=$(devlink_trap_rx_bytes_get $trap_name) @@ -659,7 +655,6 @@ erif_disabled_test()  	log_test "Egress RIF disabled"  	kill $mz_pid && wait $mz_pid &> /dev/null -	ip link set dev $rp1 nomaster  	__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64  	ip link del dev br0 type bridge  	devlink_trap_action_set $trap_name "drop" diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh new file mode 100755 index 000000000000..47edf099a17e --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh @@ -0,0 +1,384 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test devlink-trap policer functionality over mlxsw. + +# +---------------------------------+ +# | H1 (vrf)                        | +# |    + $h1                        | +# |    | 192.0.2.1/24               | +# |    |                            | +# |    |  default via 192.0.2.2     | +# +----|----------------------------+ +#      | +# +----|----------------------------------------------------------------------+ +# | SW |                                                                      | +# |    + $rp1                                                                 | +# |        192.0.2.2/24                                                       | +# |                                                                           | +# |        198.51.100.2/24                                                    | +# |    + $rp2                                                                 | +# |    |                                                                      | +# +----|----------------------------------------------------------------------+ +#      | +# +----|----------------------------+ +# |    |  default via 198.51.100.2  | +# |    |                            | +# |    | 198.51.100.1/24            | +# |    + $h2                        | +# | H2 (vrf)                        | +# +---------------------------------+ + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" +	rate_limits_test +	burst_limits_test +	rate_test +	burst_test +" +NUM_NETIFS=4 +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ +	simple_if_init $h1 192.0.2.1/24 +	mtu_set $h1 10000 + +	ip -4 route add default vrf v$h1 nexthop via 192.0.2.2 +} + +h1_destroy() +{ +	ip -4 route del default vrf v$h1 nexthop via 192.0.2.2 + +	mtu_restore $h1 +	simple_if_fini $h1 192.0.2.1/24 +} + +h2_create() +{ +	simple_if_init $h2 198.51.100.1/24 +	mtu_set $h2 10000 + +	ip -4 route add default vrf v$h2 nexthop via 198.51.100.2 +} + +h2_destroy() +{ +	ip -4 route del default vrf v$h2 nexthop via 198.51.100.2 + +	mtu_restore $h2 +	simple_if_fini $h2 198.51.100.1/24 +} + +router_create() +{ +	ip link set dev $rp1 up +	ip link set dev $rp2 up + +	__addr_add_del $rp1 add 192.0.2.2/24 +	__addr_add_del $rp2 add 198.51.100.2/24 +	mtu_set $rp1 10000 +	mtu_set $rp2 10000 + +	ip -4 route add blackhole 198.51.100.100 + +	devlink trap set $DEVLINK_DEV trap blackhole_route action trap +} + +router_destroy() +{ +	devlink trap set $DEVLINK_DEV trap blackhole_route action drop + +	ip -4 route del blackhole 198.51.100.100 + +	mtu_restore $rp2 +	mtu_restore $rp1 +	__addr_add_del $rp2 del 198.51.100.2/24 +	__addr_add_del $rp1 del 192.0.2.2/24 + +	ip link set dev $rp2 down +	ip link set dev $rp1 down +} + +setup_prepare() +{ +	h1=${NETIFS[p1]} +	rp1=${NETIFS[p2]} + +	rp2=${NETIFS[p3]} +	h2=${NETIFS[p4]} + +	rp1_mac=$(mac_get $rp1) + +	vrf_prepare + +	h1_create +	h2_create + +	router_create +} + +cleanup() +{ +	pre_cleanup + +	router_destroy + +	h2_destroy +	h1_destroy + +	vrf_cleanup + +	# Reload to ensure devlink-trap settings are back to default. +	devlink_reload +} + +rate_limits_test() +{ +	RET=0 + +	devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null +	check_fail $? "Policer rate was changed to rate lower than limit" +	devlink trap policer set $DEVLINK_DEV policer 1 \ +		rate 2000000001 &> /dev/null +	check_fail $? "Policer rate was changed to rate higher than limit" + +	devlink trap policer set $DEVLINK_DEV policer 1 rate 1 +	check_err $? "Failed to set policer rate to minimum" +	devlink trap policer set $DEVLINK_DEV policer 1 rate 2000000000 +	check_err $? "Failed to set policer rate to maximum" + +	log_test "Trap policer rate limits" +} + +burst_limits_test() +{ +	RET=0 + +	devlink trap policer set $DEVLINK_DEV policer 1 burst 0 &> /dev/null +	check_fail $? "Policer burst size was changed to 0" +	devlink trap policer set $DEVLINK_DEV policer 1 burst 17 &> /dev/null +	check_fail $? "Policer burst size was changed to burst size that is not power of 2" +	devlink trap policer set $DEVLINK_DEV policer 1 burst 8 &> /dev/null +	check_fail $? "Policer burst size was changed to burst size lower than limit" +	devlink trap policer set $DEVLINK_DEV policer 1 \ +		burst $((2**25)) &> /dev/null +	check_fail $? "Policer burst size was changed to burst size higher than limit" + +	devlink trap policer set $DEVLINK_DEV policer 1 burst 16 +	check_err $? "Failed to set policer burst size to minimum" +	devlink trap policer set $DEVLINK_DEV policer 1 burst $((2**24)) +	check_err $? "Failed to set policer burst size to maximum" + +	log_test "Trap policer burst size limits" +} + +trap_rate_get() +{ +	local t0 t1 + +	t0=$(devlink_trap_rx_packets_get blackhole_route) +	sleep 10 +	t1=$(devlink_trap_rx_packets_get blackhole_route) + +	echo $(((t1 - t0) / 10)) +} + +policer_drop_rate_get() +{ +	local id=$1; shift +	local t0 t1 + +	t0=$(devlink_trap_policer_rx_dropped_get $id) +	sleep 10 +	t1=$(devlink_trap_policer_rx_dropped_get $id) + +	echo $(((t1 - t0) / 10)) +} + +__rate_test() +{ +	local rate pct drop_rate +	local id=$1; shift + +	RET=0 + +	devlink trap policer set $DEVLINK_DEV policer $id rate 1000 burst 16 +	devlink trap group set $DEVLINK_DEV group l3_drops policer $id + +	# Send packets at highest possible rate and make sure they are dropped +	# by the policer. Make sure measured received rate is about 1000 pps +	log_info "=== Tx rate: Highest, Policer rate: 1000 pps ===" + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac + +	sleep 5 # Take measurements when rate is stable + +	rate=$(trap_rate_get) +	pct=$((100 * (rate - 1000) / 1000)) +	((-5 <= pct && pct <= 5)) +	check_err $? "Expected rate 1000 pps, got $rate pps, which is $pct% off. Required accuracy is +-5%" +	log_info "Expected rate 1000 pps, measured rate $rate pps" + +	drop_rate=$(policer_drop_rate_get $id) +	(( drop_rate > 0 )) +	check_err $? "Expected non-zero policer drop rate, got 0" +	log_info "Measured policer drop rate of $drop_rate pps" + +	stop_traffic + +	# Send packets at a rate of 1000 pps and make sure they are not dropped +	# by the policer +	log_info "=== Tx rate: 1000 pps, Policer rate: 1000 pps ===" + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -d 1msec + +	sleep 5 # Take measurements when rate is stable + +	drop_rate=$(policer_drop_rate_get $id) +	(( drop_rate == 0 )) +	check_err $? "Expected zero policer drop rate, got a drop rate of $drop_rate pps" +	log_info "Measured policer drop rate of $drop_rate pps" + +	stop_traffic + +	# Unbind the policer and send packets at highest possible rate. Make +	# sure they are not dropped by the policer and that the measured +	# received rate is higher than 1000 pps +	log_info "=== Tx rate: Highest, Policer rate: No policer ===" + +	devlink trap group set $DEVLINK_DEV group l3_drops nopolicer + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac + +	rate=$(trap_rate_get) +	(( rate > 1000 )) +	check_err $? "Expected rate higher than 1000 pps, got $rate pps" +	log_info "Measured rate $rate pps" + +	drop_rate=$(policer_drop_rate_get $id) +	(( drop_rate == 0 )) +	check_err $? "Expected zero policer drop rate, got a drop rate of $drop_rate pps" +	log_info "Measured policer drop rate of $drop_rate pps" + +	stop_traffic + +	log_test "Trap policer rate" +} + +rate_test() +{ +	local id + +	for id in $(devlink_trap_policer_ids_get); do +		echo +		log_info "Running rate test for policer $id" +		__rate_test $id +	done +} + +__burst_test() +{ +	local t0_rx t0_drop t1_rx t1_drop rx drop +	local id=$1; shift + +	RET=0 + +	devlink trap policer set $DEVLINK_DEV policer $id rate 1000 burst 32 +	devlink trap group set $DEVLINK_DEV group l3_drops policer $id + +	# Send a burst of 64 packets and make sure that about 32 are received +	# and the rest are dropped by the policer +	log_info "=== Tx burst size: 64, Policer burst size: 32 pps ===" + +	t0_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t0_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 64 + +	t1_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t1_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	rx=$((t1_rx - t0_rx)) +	pct=$((100 * (rx - 32) / 32)) +	((-20 <= pct && pct <= 20)) +	check_err $? "Expected burst size of 32 packets, got $rx packets, which is $pct% off. Required accuracy is +-20%" +	log_info "Expected burst size of 32 packets, measured burst size of $rx packets" + +	drop=$((t1_drop - t0_drop)) +	(( drop > 0 )) +	check_err $? "Expected non-zero policer drops, got 0" +	log_info "Measured policer drops of $drop packets" + +	# Send a burst of 16 packets and make sure that 16 are received +	# and that none are dropped by the policer +	log_info "=== Tx burst size: 16, Policer burst size: 32 pps ===" + +	t0_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t0_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 16 + +	t1_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t1_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	rx=$((t1_rx - t0_rx)) +	(( rx == 16 )) +	check_err $? "Expected burst size of 16 packets, got $rx packets" +	log_info "Expected burst size of 16 packets, measured burst size of $rx packets" + +	drop=$((t1_drop - t0_drop)) +	(( drop == 0 )) +	check_err $? "Expected zero policer drops, got $drop" +	log_info "Measured policer drops of $drop packets" + +	# Unbind the policer and send a burst of 64 packets. Make sure that +	# 64 packets are received and that none are dropped by the policer +	log_info "=== Tx burst size: 64, Policer burst size: No policer ===" + +	devlink trap group set $DEVLINK_DEV group l3_drops nopolicer + +	t0_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t0_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	start_traffic $h1 192.0.2.1 198.51.100.100 $rp1_mac -c 64 + +	t1_rx=$(devlink_trap_rx_packets_get blackhole_route) +	t1_drop=$(devlink_trap_policer_rx_dropped_get $id) + +	rx=$((t1_rx - t0_rx)) +	(( rx == 64 )) +	check_err $? "Expected burst size of 64 packets, got $rx packets" +	log_info "Expected burst size of 64 packets, measured burst size of $rx packets" + +	drop=$((t1_drop - t0_drop)) +	(( drop == 0 )) +	check_err $? "Expected zero policer drops, got $drop" +	log_info "Measured policer drops of $drop packets" + +	log_test "Trap policer burst size" +} + +burst_test() +{ +	local id + +	for id in $(devlink_trap_policer_ids_get); do +		echo +		log_info "Running burst size test for policer $id" +		__burst_test $id +	done +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan.sh index fd19161dd4ec..e11a416323cf 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan.sh @@ -314,11 +314,11 @@ overlay_smac_is_mc_test()  		-B 192.0.2.17 -t udp sp=12345,dp=$VXPORT,p=$payload -q &  	mz_pid=$! -	devlink_trap_drop_test $trap_name $group_name $swp1 +	devlink_trap_drop_test $trap_name $group_name $swp1 101  	log_test "Overlay source MAC is multicast" -	devlink_trap_drop_cleanup $mz_pid $swp1 "ip" +	devlink_trap_drop_cleanup $mz_pid $swp1 "ip" 1 101  }  trap cleanup EXIT diff --git a/tools/testing/selftests/drivers/net/mlxsw/extack.sh b/tools/testing/selftests/drivers/net/mlxsw/extack.sh index d72d8488a3b2..7a0a99c1d22f 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/extack.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/extack.sh @@ -8,7 +8,8 @@ lib_dir=$(dirname $0)/../../../net/forwarding  ALL_TESTS="  	netdev_pre_up_test  	vxlan_vlan_add_test -	port_vlan_add_test +	vxlan_bridge_create_test +	bridge_create_test  "  NUM_NETIFS=2  source $lib_dir/lib.sh @@ -106,32 +107,56 @@ vxlan_vlan_add_test()  	ip link del dev br1  } -port_vlan_add_test() +vxlan_bridge_create_test()  {  	RET=0 -	ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 0 -  	# Unsupported configuration: mlxsw demands VXLAN with "noudpcsum".  	ip link add name vx1 up type vxlan id 1000 \  		local 192.0.2.17 remote 192.0.2.18 \  		dstport 4789 tos inherit ttl 100 -	ip link set dev $swp1 master br1 -	check_err $? - -	bridge vlan del dev $swp1 vid 1 +	# Test with VLAN-aware bridge. +	ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 0  	ip link set dev vx1 master br1 + +	ip link set dev $swp1 master br1 2>&1 > /dev/null \ +		| grep -q mlxsw_spectrum  	check_err $? -	bridge vlan add dev $swp1 vid 1 pvid untagged 2>&1 >/dev/null \ +	# Test with VLAN-unaware bridge. +	ip link set dev br1 type bridge vlan_filtering 0 + +	ip link set dev $swp1 master br1 2>&1 > /dev/null \  		| grep -q mlxsw_spectrum  	check_err $? -	log_test "extack - map VLAN at port" +	log_test "extack - bridge creation with VXLAN" +	ip link del dev br1  	ip link del dev vx1 +} + +bridge_create_test() +{ +	RET=0 + +	ip link add name br1 up type bridge vlan_filtering 1 +	ip link add name br2 up type bridge vlan_filtering 1 + +	ip link set dev $swp1 master br1 +	check_err $? + +	# Only one VLAN-aware bridge is supported, so this should fail with +	# an extack. +	ip link set dev $swp2 master br2 2>&1 > /dev/null \ +		| grep -q mlxsw_spectrum +	check_err $? + +	log_test "extack - multiple VLAN-aware bridges creation" + +	ip link del dev br2  	ip link del dev br1  } diff --git a/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh new file mode 100644 index 000000000000..cbe50f260a40 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +############################################################################## +# Defines + +if [[ ! -v MLXSW_CHIP ]]; then +	MLXSW_CHIP=$(devlink -j dev info $DEVLINK_DEV | jq -r '.[][]["driver"]') +	if [ -z "$MLXSW_CHIP" ]; then +		echo "SKIP: Device $DEVLINK_DEV doesn't support devlink info command" +		exit 1 +	fi +fi diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_defprio.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_defprio.sh index eff6393ce974..71066bc4b886 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_defprio.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_defprio.sh @@ -114,23 +114,12 @@ ping_ipv4()  	ping_test $h1 192.0.2.2  } -wait_for_packets() -{ -	local t0=$1; shift -	local prio_observe=$1; shift - -	local t1=$(ethtool_stats_get $swp1 rx_frames_prio_$prio_observe) -	local delta=$((t1 - t0)) -	echo $delta -	((delta >= 10)) -} -  __test_defprio()  {  	local prio_install=$1; shift  	local prio_observe=$1; shift -	local delta  	local key +	local t1  	local i  	RET=0 @@ -139,9 +128,10 @@ __test_defprio()  	local t0=$(ethtool_stats_get $swp1 rx_frames_prio_$prio_observe)  	mausezahn -q $h1 -d 100m -c 10 -t arp reply -	delta=$(busywait "$HIT_TIMEOUT" wait_for_packets $t0 $prio_observe) +	t1=$(busywait "$HIT_TIMEOUT" until_counter_is ">= $((t0 + 10))" \ +		ethtool_stats_get $swp1 rx_frames_prio_$prio_observe) -	check_err $? "Default priority $prio_install/$prio_observe: Expected to capture 10 packets, got $delta." +	check_err $? "Default priority $prio_install/$prio_observe: Expected to capture 10 packets, got $((t1 - t0))."  	log_test "Default priority $prio_install/$prio_observe"  	defprio_uninstall $swp1 $prio_install diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh index c745ce3befee..4cb2aa65278a 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh @@ -31,6 +31,7 @@ ALL_TESTS="  	ping_ipv4  	test_update  	test_no_update +	test_pedit_norewrite  	test_dscp_leftover  " @@ -56,6 +57,11 @@ zero()      echo 0  } +three() +{ +    echo 3 +} +  h1_create()  {  	simple_if_init $h1 192.0.2.1/28 @@ -103,6 +109,9 @@ switch_create()  	simple_if_init $swp1 192.0.2.2/28  	__simple_if_init $swp2 v$swp1 192.0.2.17/28 +	tc qdisc add dev $swp1 clsact +	tc qdisc add dev $swp2 clsact +  	lldptool -T -i $swp1 -V APP $(dscp_map 0) >/dev/null  	lldptool -T -i $swp2 -V APP $(dscp_map 0) >/dev/null  	lldpad_app_wait_set $swp1 @@ -115,6 +124,9 @@ switch_destroy()  	lldptool -T -i $swp1 -V APP -d $(dscp_map 0) >/dev/null  	lldpad_app_wait_del +	tc qdisc del dev $swp2 clsact +	tc qdisc del dev $swp1 clsact +  	__simple_if_fini $swp2 192.0.2.17/28  	simple_if_fini $swp1 192.0.2.2/28  } @@ -223,18 +235,36 @@ __test_update()  test_update()  { +	echo "Test net.ipv4.ip_forward_update_priority=1"  	__test_update 1 reprioritize  }  test_no_update()  { +	echo "Test net.ipv4.ip_forward_update_priority=0"  	__test_update 0 echo  } +# Test that when DSCP is updated in pedit, the DSCP rewrite is turned off. +test_pedit_norewrite() +{ +	echo "Test no DSCP rewrite after DSCP is updated by pedit" + +	tc filter add dev $swp1 ingress handle 101 pref 1 prot ip flower \ +	    action pedit ex munge ip dsfield set $((3 << 2)) retain 0xfc \ +	    action skbedit priority 3 + +	__test_update 0 three + +	tc filter del dev $swp1 ingress pref 1 +} +  # Test that when the last APP rule is removed, the prio->DSCP map is properly  # set to zeroes, and that the last APP rule does not stay active in the ASIC.  test_dscp_leftover()  { +	echo "Test that last removed DSCP rule is deconfigured correctly" +  	lldptool -T -i $swp2 -V APP -d $(dscp_map 0) >/dev/null  	lldpad_app_wait_del diff --git a/tools/testing/selftests/drivers/net/mlxsw/router_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/router_scale.sh index d231649b4f01..e93878d42596 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/router_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/router_scale.sh @@ -2,16 +2,15 @@  # SPDX-License-Identifier: GPL-2.0  ROUTER_NUM_NETIFS=4 +: ${TIMEOUT:=20000} # ms  router_h1_create()  {  	simple_if_init $h1 192.0.1.1/24 -	ip route add 193.0.0.0/8 via 192.0.1.2 dev $h1  }  router_h1_destroy()  { -	ip route del 193.0.0.0/8 via 192.0.1.2 dev $h1  	simple_if_fini $h1 192.0.1.1/24  } @@ -64,13 +63,15 @@ router_setup_prepare()  	router_create  } -router_offload_validate() +wait_for_routes()  { -	local route_count=$1 -	local offloaded_count +	local t0=$1; shift +	local route_count=$1; shift -	offloaded_count=$(ip route | grep -o 'offload' | wc -l) -	[[ $offloaded_count -ge $route_count ]] +	local t1=$(ip route | grep -o 'offload' | wc -l) +	local delta=$((t1 - t0)) +	echo $delta +	[[ $delta -ge $route_count ]]  }  router_routes_create() @@ -90,8 +91,8 @@ router_routes_create()  					break 3  				fi -				echo route add 193.${i}.${j}.${k}/32 via \ -				       192.0.2.1 dev $rp2  >> $ROUTE_FILE +				echo route add 193.${i}.${j}.${k}/32 dev $rp2 \ +					>> $ROUTE_FILE  				((count++))  			done  		done @@ -111,45 +112,19 @@ router_test()  {  	local route_count=$1  	local should_fail=$2 -	local count=0 +	local delta  	RET=0 +	local t0=$(ip route | grep -o 'offload' | wc -l)  	router_routes_create $route_count +	delta=$(busywait "$TIMEOUT" wait_for_routes $t0 $route_count) -	router_offload_validate $route_count -	check_err_fail $should_fail $? "Offload of $route_count routes" +	check_err_fail $should_fail $? "Offload routes: Expected $route_count, got $delta."  	if [[ $RET -ne 0 ]] || [[ $should_fail -eq 1 ]]; then  		return  	fi -	tc filter add dev $h2 ingress protocol ip pref 1 flower \ -		skip_sw dst_ip 193.0.0.0/8 action drop - -	for i in {0..255} -	do -		for j in {0..255} -		do -			for k in {0..255} -			do -				if [[ $count -eq $route_count ]]; then -					break 3 -				fi - -				$MZ $h1 -c 1 -p 64 -a $h1mac -b $rp1mac \ -					-A 192.0.1.1 -B 193.${i}.${j}.${k} \ -					-t ip -q -				((count++)) -			done -		done -	done - -	tc_check_packets "dev $h2 ingress" 1 $route_count -	check_err $? "Offload mismatch" - -	tc filter del dev $h2 ingress protocol ip pref 1 flower \ -		skip_sw dst_ip 193.0.0.0/8 action drop -  	router_routes_destroy  } diff --git a/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh b/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh index 5c39e5f6a480..f4031002d5e9 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh @@ -32,6 +32,7 @@ ALL_TESTS="  	devlink_reload_test  "  NUM_NETIFS=2 +: ${TIMEOUT:=20000} # ms  source $lib_dir/lib.sh  source $lib_dir/devlink_lib.sh @@ -360,20 +361,24 @@ vlan_rif_refcount_test()  	ip link add link br0 name br0.10 up type vlan id 10  	ip -6 address add 2001:db8:1::1/64 dev br0.10 -	ip -6 route get fibmatch 2001:db8:1::2 dev br0.10 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev br0.10  	check_err $? "vlan rif was not created before adding port to vlan"  	bridge vlan add vid 10 dev $swp1 -	ip -6 route get fibmatch 2001:db8:1::2 dev br0.10 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev br0.10  	check_err $? "vlan rif was destroyed after adding port to vlan"  	bridge vlan del vid 10 dev $swp1 -	ip -6 route get fibmatch 2001:db8:1::2 dev br0.10 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev br0.10  	check_err $? "vlan rif was destroyed after removing port from vlan"  	ip link set dev $swp1 nomaster -	ip -6 route get fibmatch 2001:db8:1::2 dev br0.10 | grep -q offload -	check_fail $? "vlan rif was not destroyed after unlinking port from bridge" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev br0.10 +	check_err $? "vlan rif was not destroyed after unlinking port from bridge"  	log_test "vlan rif refcount" @@ -401,22 +406,28 @@ subport_rif_refcount_test()  	ip -6 address add 2001:db8:1::1/64 dev bond1  	ip -6 address add 2001:db8:2::1/64 dev bond1.10 -	ip -6 route get fibmatch 2001:db8:1::2 dev bond1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev bond1  	check_err $? "subport rif was not created on lag device" -	ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10  	check_err $? "subport rif was not created on vlan device"  	ip link set dev $swp1 nomaster -	ip -6 route get fibmatch 2001:db8:1::2 dev bond1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev bond1  	check_err $? "subport rif of lag device was destroyed when should not" -	ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10  	check_err $? "subport rif of vlan device was destroyed when should not"  	ip link set dev $swp2 nomaster -	ip -6 route get fibmatch 2001:db8:1::2 dev bond1 | grep -q offload -	check_fail $? "subport rif of lag device was not destroyed when should" -	ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10 | grep -q offload -	check_fail $? "subport rif of vlan device was not destroyed when should" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:1::2 dev bond1 +	check_err $? "subport rif of lag device was not destroyed when should" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip -6 route get fibmatch 2001:db8:2::2 dev bond1.10 +	check_err $? "subport rif of vlan device was not destroyed when should"  	log_test "subport rif refcount" @@ -575,7 +586,8 @@ bridge_extern_learn_test()  	bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn -	bridge fdb show brport $swp1 | grep de:ad:be:ef:13:37 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		bridge fdb show brport $swp1 de:ad:be:ef:13:37  	check_err $? "fdb entry not marked as offloaded when should"  	log_test "externally learned fdb entry" @@ -595,9 +607,11 @@ neigh_offload_test()  	ip -6 neigh add 2001:db8:1::2 lladdr de:ad:be:ef:13:37 nud perm \  		dev $swp1 -	ip -4 neigh show dev $swp1 | grep 192.0.2.2 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -4 neigh show dev $swp1 192.0.2.2  	check_err $? "ipv4 neigh entry not marked as offloaded when should" -	ip -6 neigh show dev $swp1 | grep 2001:db8:1::2 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 neigh show dev $swp1 2001:db8:1::2  	check_err $? "ipv6 neigh entry not marked as offloaded when should"  	log_test "neighbour offload indication" @@ -623,25 +637,31 @@ nexthop_offload_test()  	ip -6 route add 2001:db8:2::/64 vrf v$swp1 \  		nexthop via 2001:db8:1::2 dev $swp1 -	ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -4 route show 198.51.100.0/24 vrf v$swp1  	check_err $? "ipv4 nexthop not marked as offloaded when should" -	ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route show 2001:db8:2::/64 vrf v$swp1  	check_err $? "ipv6 nexthop not marked as offloaded when should"  	ip link set dev $swp2 down  	sleep 1 -	ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload -	check_fail $? "ipv4 nexthop marked as offloaded when should not" -	ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload -	check_fail $? "ipv6 nexthop marked as offloaded when should not" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip -4 route show 198.51.100.0/24 vrf v$swp1 +	check_err $? "ipv4 nexthop marked as offloaded when should not" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip -6 route show 2001:db8:2::/64 vrf v$swp1 +	check_err $? "ipv6 nexthop marked as offloaded when should not"  	ip link set dev $swp2 up  	setup_wait -	ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -4 route show 198.51.100.0/24 vrf v$swp1  	check_err $? "ipv4 nexthop not marked as offloaded after neigh add" -	ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip -6 route show 2001:db8:2::/64 vrf v$swp1  	check_err $? "ipv6 nexthop not marked as offloaded after neigh add"  	log_test "nexthop offload indication" diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_ets.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_ets.sh index c9fc4d4885c1..94c37124a840 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/sch_ets.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_ets.sh @@ -56,11 +56,19 @@ switch_destroy()  }  # Callback from sch_ets_tests.sh -get_stats() +collect_stats()  { -	local band=$1; shift +	local -a streams=("$@") +	local stream -	ethtool_stats_get "$h2" rx_octets_prio_$band +	# Wait for qdisc counter update so that we don't get it mid-way through. +	busywait_for_counter 1000 +1 \ +		qdisc_parent_stats_get $swp2 10:$((${streams[0]} + 1)) .bytes \ +		> /dev/null + +	for stream in ${streams[@]}; do +		qdisc_parent_stats_get $swp2 10:$((stream + 1)) .bytes +	done  }  bail_on_lldpad diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh new file mode 100644 index 000000000000..0d347d48c112 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh @@ -0,0 +1,533 @@ +# SPDX-License-Identifier: GPL-2.0 + +# This test sends a >1Gbps stream of traffic from H1, to the switch, which +# forwards it to a 1Gbps port. This 1Gbps stream is then looped back to the +# switch and forwarded to the port under test $swp3, which is also 1Gbps. +# +# This way, $swp3 should be 100% filled with traffic without any of it spilling +# to the backlog. Any extra packets sent should almost 1:1 go to backlog. That +# is what H2 is used for--it sends the extra traffic to create backlog. +# +# A RED Qdisc is installed on $swp3. The configuration is such that the minimum +# and maximum size are 1 byte apart, so there is a very clear border under which +# no marking or dropping takes place, and above which everything is marked or +# dropped. +# +# The test uses the buffer build-up behavior to test the installed RED. +# +# In order to test WRED, $swp3 actually contains RED under PRIO, with two +# different configurations. Traffic is prioritized using 802.1p and relies on +# the implicit mlxsw configuration, where packet priority is taken 1:1 from the +# 802.1p marking. +# +# +--------------------------+                     +--------------------------+ +# | H1                       |                     | H2                       | +# |     + $h1.10             |                     |     + $h2.10             | +# |     | 192.0.2.1/28       |                     |     | 192.0.2.2/28       | +# |     |                    |                     |     |                    | +# |     |         $h1.11 +   |                     |     |         $h2.11 +   | +# |     |  192.0.2.17/28 |   |                     |     |  192.0.2.18/28 |   | +# |     |                |   |                     |     |                |   | +# |     \______    ______/   |                     |     \______    ______/   | +# |            \ /           |                     |            \ /           | +# |             + $h1        |                     |             + $h2        | +# +-------------|------------+                     +-------------|------------+ +#               | >1Gbps                                         | +# +-------------|------------------------------------------------|------------+ +# | SW          + $swp1                                          + $swp2      | +# |     _______/ \___________                        ___________/ \_______    | +# |    /                     \                      /                     \   | +# |  +-|-----------------+   |                    +-|-----------------+   |   | +# |  | + $swp1.10        |   |                    | + $swp2.10        |   |   | +# |  |                   |   |        .-------------+ $swp5.10        |   |   | +# |  |     BR1_10        |   |        |           |                   |   |   | +# |  |                   |   |        |           |     BR2_10        |   |   | +# |  | + $swp2.10        |   |        |           |                   |   |   | +# |  +-|-----------------+   |        |           | + $swp3.10        |   |   | +# |    |                     |        |           +-|-----------------+   |   | +# |    |   +-----------------|-+      |             |   +-----------------|-+ | +# |    |   |        $swp1.11 + |      |             |   |        $swp2.11 + | | +# |    |   |                   |      | .-----------------+ $swp5.11        | | +# |    |   |      BR1_11       |      | |           |   |                   | | +# |    |   |                   |      | |           |   |      BR2_11       | | +# |    |   |        $swp2.11 + |      | |           |   |                   | | +# |    |   +-----------------|-+      | |           |   |        $swp3.11 + | | +# |    |                     |        | |           |   +-----------------|-+ | +# |    \_______   ___________/        | |           \___________   _______/   | +# |            \ /                    \ /                       \ /           | +# |             + $swp4                + $swp5                   + $swp3      | +# +-------------|----------------------|-------------------------|------------+ +#               |                      |                         | 1Gbps +#               \________1Gbps_________/                         | +#                                   +----------------------------|------------+ +#                                   | H3                         + $h3        | +#                                   |      _____________________/ \_______    | +#                                   |     /                               \   | +#                                   |     |                               |   | +#                                   |     + $h3.10                 $h3.11 +   | +#                                   |       192.0.2.3/28    192.0.2.19/28     | +#                                   +-----------------------------------------+ + +NUM_NETIFS=8 +CHECK_TC="yes" +lib_dir=$(dirname $0)/../../../net/forwarding +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh +source qos_lib.sh + +ipaddr() +{ +	local host=$1; shift +	local vlan=$1; shift + +	echo 192.0.2.$((16 * (vlan - 10) + host)) +} + +host_create() +{ +	local dev=$1; shift +	local host=$1; shift + +	simple_if_init $dev +	mtu_set $dev 10000 + +	vlan_create $dev 10 v$dev $(ipaddr $host 10)/28 +	ip link set dev $dev.10 type vlan egress 0:0 + +	vlan_create $dev 11 v$dev $(ipaddr $host 11)/28 +	ip link set dev $dev.11 type vlan egress 0:1 +} + +host_destroy() +{ +	local dev=$1; shift + +	vlan_destroy $dev 11 +	vlan_destroy $dev 10 +	mtu_restore $dev +	simple_if_fini $dev +} + +h1_create() +{ +	host_create $h1 1 +} + +h1_destroy() +{ +	host_destroy $h1 +} + +h2_create() +{ +	host_create $h2 2 + +	# Some of the tests in this suite use multicast traffic. As this traffic +	# enters BR2_10 resp. BR2_11, it is flooded to all other ports. Thus +	# e.g. traffic ingressing through $swp2 is flooded to $swp3 (the +	# intended destination) and $swp5 (which is intended as ingress for +	# another stream of traffic). +	# +	# This is generally not a problem, but if the $swp5 throughput is lower +	# than $swp2 throughput, there will be a build-up at $swp5. That may +	# cause packets to fail to queue up at $swp3 due to shared buffer +	# quotas, and the test to spuriously fail. +	# +	# Prevent this by setting the speed of $h2 to 1Gbps. + +	ethtool -s $h2 speed 1000 autoneg off +} + +h2_destroy() +{ +	ethtool -s $h2 autoneg on +	host_destroy $h2 +} + +h3_create() +{ +	host_create $h3 3 +	ethtool -s $h3 speed 1000 autoneg off +} + +h3_destroy() +{ +	ethtool -s $h3 autoneg on +	host_destroy $h3 +} + +switch_create() +{ +	local intf +	local vlan + +	ip link add dev br1_10 type bridge +	ip link add dev br1_11 type bridge + +	ip link add dev br2_10 type bridge +	ip link add dev br2_11 type bridge + +	for intf in $swp1 $swp2 $swp3 $swp4 $swp5; do +		ip link set dev $intf up +		mtu_set $intf 10000 +	done + +	for intf in $swp1 $swp4; do +		for vlan in 10 11; do +			vlan_create $intf $vlan +			ip link set dev $intf.$vlan master br1_$vlan +			ip link set dev $intf.$vlan up +		done +	done + +	for intf in $swp2 $swp3 $swp5; do +		for vlan in 10 11; do +			vlan_create $intf $vlan +			ip link set dev $intf.$vlan master br2_$vlan +			ip link set dev $intf.$vlan up +		done +	done + +	ip link set dev $swp4.10 type vlan egress 0:0 +	ip link set dev $swp4.11 type vlan egress 0:1 +	for intf in $swp1 $swp2 $swp5; do +		for vlan in 10 11; do +			ip link set dev $intf.$vlan type vlan ingress 0:0 1:1 +		done +	done + +	for intf in $swp2 $swp3 $swp4 $swp5; do +		ethtool -s $intf speed 1000 autoneg off +	done + +	ip link set dev br1_10 up +	ip link set dev br1_11 up +	ip link set dev br2_10 up +	ip link set dev br2_11 up + +	local size=$(devlink_pool_size_thtype 0 | cut -d' ' -f 1) +	devlink_port_pool_th_set $swp3 8 $size +} + +switch_destroy() +{ +	local intf +	local vlan + +	devlink_port_pool_th_restore $swp3 8 + +	tc qdisc del dev $swp3 root 2>/dev/null + +	ip link set dev br2_11 down +	ip link set dev br2_10 down +	ip link set dev br1_11 down +	ip link set dev br1_10 down + +	for intf in $swp5 $swp4 $swp3 $swp2; do +		ethtool -s $intf autoneg on +	done + +	for intf in $swp5 $swp3 $swp2 $swp4 $swp1; do +		for vlan in 11 10; do +			ip link set dev $intf.$vlan down +			ip link set dev $intf.$vlan nomaster +			vlan_destroy $intf $vlan +		done + +		mtu_restore $intf +		ip link set dev $intf down +	done + +	ip link del dev br2_11 +	ip link del dev br2_10 +	ip link del dev br1_11 +	ip link del dev br1_10 +} + +setup_prepare() +{ +	h1=${NETIFS[p1]} +	swp1=${NETIFS[p2]} + +	swp2=${NETIFS[p3]} +	h2=${NETIFS[p4]} + +	swp3=${NETIFS[p5]} +	h3=${NETIFS[p6]} + +	swp4=${NETIFS[p7]} +	swp5=${NETIFS[p8]} + +	h3_mac=$(mac_get $h3) + +	vrf_prepare + +	h1_create +	h2_create +	h3_create +	switch_create +} + +cleanup() +{ +	pre_cleanup + +	switch_destroy +	h3_destroy +	h2_destroy +	h1_destroy + +	vrf_cleanup +} + +ping_ipv4() +{ +	ping_test $h1.10 $(ipaddr 3 10) " from host 1, vlan 10" +	ping_test $h1.11 $(ipaddr 3 11) " from host 1, vlan 11" +	ping_test $h2.10 $(ipaddr 3 10) " from host 2, vlan 10" +	ping_test $h2.11 $(ipaddr 3 11) " from host 2, vlan 11" +} + +get_tc() +{ +	local vlan=$1; shift + +	echo $((vlan - 10)) +} + +get_qdisc_handle() +{ +	local vlan=$1; shift + +	local tc=$(get_tc $vlan) +	local band=$((8 - tc)) + +	# Handle is 107: for TC1, 108: for TC0. +	echo "10$band:" +} + +get_qdisc_backlog() +{ +	local vlan=$1; shift + +	qdisc_stats_get $swp3 $(get_qdisc_handle $vlan) .backlog +} + +get_mc_transmit_queue() +{ +	local vlan=$1; shift + +	local tc=$(($(get_tc $vlan) + 8)) +	ethtool_stats_get $swp3 tc_transmit_queue_tc_$tc +} + +get_nmarked() +{ +	local vlan=$1; shift + +	ethtool_stats_get $swp3 ecn_marked +} + +get_qdisc_npackets() +{ +	local vlan=$1; shift + +	busywait_for_counter 1100 +1 \ +		qdisc_stats_get $swp3 $(get_qdisc_handle $vlan) .packets +} + +# This sends traffic in an attempt to build a backlog of $size. Returns 0 on +# success. After 10 failed attempts it bails out and returns 1. It dumps the +# backlog size to stdout. +build_backlog() +{ +	local vlan=$1; shift +	local size=$1; shift +	local proto=$1; shift + +	local tc=$((vlan - 10)) +	local band=$((8 - tc)) +	local cur=-1 +	local i=0 + +	while :; do +		local cur=$(busywait 1100 until_counter_is "> $cur" \ +					    get_qdisc_backlog $vlan) +		local diff=$((size - cur)) +		local pkts=$(((diff + 7999) / 8000)) + +		if ((cur >= size)); then +			echo $cur +			return 0 +		elif ((i++ > 10)); then +			echo $cur +			return 1 +		fi + +		$MZ $h2.$vlan -p 8000 -a own -b $h3_mac \ +		    -A $(ipaddr 2 $vlan) -B $(ipaddr 3 $vlan) \ +		    -t $proto -q -c $pkts "$@" +	done +} + +check_marking() +{ +	local vlan=$1; shift +	local cond=$1; shift + +	local npackets_0=$(get_qdisc_npackets $vlan) +	local nmarked_0=$(get_nmarked $vlan) +	sleep 5 +	local npackets_1=$(get_qdisc_npackets $vlan) +	local nmarked_1=$(get_nmarked $vlan) + +	local nmarked_d=$((nmarked_1 - nmarked_0)) +	local npackets_d=$((npackets_1 - npackets_0)) +	local pct=$((100 * nmarked_d / npackets_d)) + +	echo $pct +	((pct $cond)) +} + +ecn_test_common() +{ +	local name=$1; shift +	local vlan=$1; shift +	local limit=$1; shift +	local backlog +	local pct + +	# Build the below-the-limit backlog using UDP. We could use TCP just +	# fine, but this way we get a proof that UDP is accepted when queue +	# length is below the limit. The main stream is using TCP, and if the +	# limit is misconfigured, we would see this traffic being ECN marked. +	RET=0 +	backlog=$(build_backlog $vlan $((2 * limit / 3)) udp) +	check_err $? "Could not build the requested backlog" +	pct=$(check_marking $vlan "== 0") +	check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0." +	log_test "TC $((vlan - 10)): $name backlog < limit" + +	# Now push TCP, because non-TCP traffic would be early-dropped after the +	# backlog crosses the limit, and we want to make sure that the backlog +	# is above the limit. +	RET=0 +	backlog=$(build_backlog $vlan $((3 * limit / 2)) tcp tos=0x01) +	check_err $? "Could not build the requested backlog" +	pct=$(check_marking $vlan ">= 95") +	check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected >= 95." +	log_test "TC $((vlan - 10)): $name backlog > limit" +} + +do_ecn_test() +{ +	local vlan=$1; shift +	local limit=$1; shift +	local name=ECN + +	start_tcp_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) \ +			  $h3_mac tos=0x01 +	sleep 1 + +	ecn_test_common "$name" $vlan $limit + +	# Up there we saw that UDP gets accepted when backlog is below the +	# limit. Now that it is above, it should all get dropped, and backlog +	# building should fail. +	RET=0 +	build_backlog $vlan $((2 * limit)) udp >/dev/null +	check_fail $? "UDP traffic went into backlog instead of being early-dropped" +	log_test "TC $((vlan - 10)): $name backlog > limit: UDP early-dropped" + +	stop_traffic +	sleep 1 +} + +do_ecn_nodrop_test() +{ +	local vlan=$1; shift +	local limit=$1; shift +	local name="ECN nodrop" + +	start_tcp_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) \ +			  $h3_mac tos=0x01 +	sleep 1 + +	ecn_test_common "$name" $vlan $limit + +	# Up there we saw that UDP gets accepted when backlog is below the +	# limit. Now that it is above, in nodrop mode, make sure it goes to +	# backlog as well. +	RET=0 +	build_backlog $vlan $((2 * limit)) udp >/dev/null +	check_err $? "UDP traffic was early-dropped instead of getting into backlog" +	log_test "TC $((vlan - 10)): $name backlog > limit: UDP not dropped" + +	stop_traffic +	sleep 1 +} + +do_red_test() +{ +	local vlan=$1; shift +	local limit=$1; shift +	local backlog +	local pct + +	# Use ECN-capable TCP to verify there's no marking even though the queue +	# is above limit. +	start_tcp_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) \ +			  $h3_mac tos=0x01 + +	# Pushing below the queue limit should work. +	RET=0 +	backlog=$(build_backlog $vlan $((2 * limit / 3)) tcp tos=0x01) +	check_err $? "Could not build the requested backlog" +	pct=$(check_marking $vlan "== 0") +	check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0." +	log_test "TC $((vlan - 10)): RED backlog < limit" + +	# Pushing above should not. +	RET=0 +	backlog=$(build_backlog $vlan $((3 * limit / 2)) tcp tos=0x01) +	check_fail $? "Traffic went into backlog instead of being early-dropped" +	pct=$(check_marking $vlan "== 0") +	check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0." +	local diff=$((limit - backlog)) +	pct=$((100 * diff / limit)) +	((0 <= pct && pct <= 5)) +	check_err $? "backlog $backlog / $limit expected <= 5% distance" +	log_test "TC $((vlan - 10)): RED backlog > limit" + +	stop_traffic +	sleep 1 +} + +do_mc_backlog_test() +{ +	local vlan=$1; shift +	local limit=$1; shift +	local backlog +	local pct + +	RET=0 + +	start_tcp_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) bc +	start_tcp_traffic $h2.$vlan $(ipaddr 2 $vlan) $(ipaddr 3 $vlan) bc + +	qbl=$(busywait 5000 until_counter_is ">= 500000" \ +		       get_qdisc_backlog $vlan) +	check_err $? "Could not build MC backlog" + +	# Verify that we actually see the backlog on BUM TC. Do a busywait as +	# well, performance blips might cause false fail. +	local ebl +	ebl=$(busywait 5000 until_counter_is ">= 500000" \ +		       get_mc_transmit_queue $vlan) +	check_err $? "MC backlog reported by qdisc not visible in ethtool" + +	stop_traffic +	stop_traffic + +	log_test "TC $((vlan - 10)): Qdisc reports MC backlog" +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh new file mode 100755 index 000000000000..1c36c576613b --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +ALL_TESTS=" +	ping_ipv4 +	ecn_test +	ecn_nodrop_test +	red_test +	mc_backlog_test +" +: ${QDISC:=ets} +source sch_red_core.sh + +# do_ecn_test first build 2/3 of the requested backlog and expects no marking, +# and then builds 3/2 of it and does expect marking. The values of $BACKLOG1 and +# $BACKLOG2 are far enough not to overlap, so that we can assume that if we do +# see (do not see) marking, it is actually due to the configuration of that one +# TC, and not due to configuration of the other TC leaking over. +BACKLOG1=200000 +BACKLOG2=500000 + +install_qdisc() +{ +	local -a args=("$@") + +	tc qdisc add dev $swp3 root handle 10: $QDISC \ +	   bands 8 priomap 7 6 5 4 3 2 1 0 +	tc qdisc add dev $swp3 parent 10:8 handle 108: red \ +	   limit 1000000 min $BACKLOG1 max $((BACKLOG1 + 1)) \ +	   probability 1.0 avpkt 8000 burst 38 "${args[@]}" +	tc qdisc add dev $swp3 parent 10:7 handle 107: red \ +	   limit 1000000 min $BACKLOG2 max $((BACKLOG2 + 1)) \ +	   probability 1.0 avpkt 8000 burst 63 "${args[@]}" +	sleep 1 +} + +uninstall_qdisc() +{ +	tc qdisc del dev $swp3 parent 10:7 +	tc qdisc del dev $swp3 parent 10:8 +	tc qdisc del dev $swp3 root +} + +ecn_test() +{ +	install_qdisc ecn + +	do_ecn_test 10 $BACKLOG1 +	do_ecn_test 11 $BACKLOG2 + +	uninstall_qdisc +} + +ecn_nodrop_test() +{ +	install_qdisc ecn nodrop + +	do_ecn_nodrop_test 10 $BACKLOG1 +	do_ecn_nodrop_test 11 $BACKLOG2 + +	uninstall_qdisc +} + +red_test() +{ +	install_qdisc + +	do_red_test 10 $BACKLOG1 +	do_red_test 11 $BACKLOG2 + +	uninstall_qdisc +} + +mc_backlog_test() +{ +	install_qdisc + +	# Note that the backlog numbers here do not correspond to RED +	# configuration, but are arbitrary. +	do_mc_backlog_test 10 $BACKLOG1 +	do_mc_backlog_test 11 $BACKLOG2 + +	uninstall_qdisc +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +bail_on_lldpad +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_prio.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_prio.sh new file mode 100755 index 000000000000..76820a0e9a1b --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_prio.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +QDISC=prio +source sch_red_ets.sh diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_root.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_root.sh new file mode 100755 index 000000000000..558667ea11ec --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_root.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +ALL_TESTS=" +	ping_ipv4 +	ecn_test +	ecn_nodrop_test +	red_test +	mc_backlog_test +" +source sch_red_core.sh + +BACKLOG=300000 + +install_qdisc() +{ +	local -a args=("$@") + +	tc qdisc add dev $swp3 root handle 108: red \ +	   limit 1000000 min $BACKLOG max $((BACKLOG + 1)) \ +	   probability 1.0 avpkt 8000 burst 38 "${args[@]}" +	sleep 1 +} + +uninstall_qdisc() +{ +	tc qdisc del dev $swp3 root +} + +ecn_test() +{ +	install_qdisc ecn +	do_ecn_test 10 $BACKLOG +	uninstall_qdisc +} + +ecn_nodrop_test() +{ +	install_qdisc ecn nodrop +	do_ecn_nodrop_test 10 $BACKLOG +	uninstall_qdisc +} + +red_test() +{ +	install_qdisc +	do_red_test 10 $BACKLOG +	uninstall_qdisc +} + +mc_backlog_test() +{ +	install_qdisc +	# Note that the backlog value here does not correspond to RED +	# configuration, but is arbitrary. +	do_mc_backlog_test 10 $BACKLOG +	uninstall_qdisc +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +bail_on_lldpad +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh new file mode 100755 index 000000000000..58f3a05f08af --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh @@ -0,0 +1,222 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +ALL_TESTS=" +	port_pool_test +	port_tc_ip_test +	port_tc_arp_test +" + +NUM_NETIFS=2 +source ../../../net/forwarding/lib.sh +source ../../../net/forwarding/devlink_lib.sh +source mlxsw_lib.sh + +SB_POOL_ING=0 +SB_POOL_EGR_CPU=10 + +SB_ITC_CPU_IP=3 +SB_ITC_CPU_ARP=2 +SB_ITC=0 + +h1_create() +{ +	simple_if_init $h1 192.0.1.1/24 +} + +h1_destroy() +{ +	simple_if_fini $h1 192.0.1.1/24 +} + +h2_create() +{ +	simple_if_init $h2 192.0.1.2/24 +} + +h2_destroy() +{ +	simple_if_fini $h2 192.0.1.2/24 +} + +sb_occ_pool_check() +{ +	local dl_port=$1; shift +	local pool=$1; shift +	local exp_max_occ=$1 +	local max_occ +	local err=0 + +	max_occ=$(devlink sb -j occupancy show $dl_port \ +		  | jq -e ".[][][\"pool\"][\"$pool\"][\"max\"]") + +	if [[ "$max_occ" -ne "$exp_max_occ" ]]; then +		err=1 +	fi + +	echo $max_occ +	return $err +} + +sb_occ_itc_check() +{ +	local dl_port=$1; shift +	local itc=$1; shift +	local exp_max_occ=$1 +	local max_occ +	local err=0 + +	max_occ=$(devlink sb -j occupancy show $dl_port \ +		  | jq -e ".[][][\"itc\"][\"$itc\"][\"max\"]") + +	if [[ "$max_occ" -ne "$exp_max_occ" ]]; then +		err=1 +	fi + +	echo $max_occ +	return $err +} + +sb_occ_etc_check() +{ +	local dl_port=$1; shift +	local etc=$1; shift +	local exp_max_occ=$1; shift +	local max_occ +	local err=0 + +	max_occ=$(devlink sb -j occupancy show $dl_port \ +		  | jq -e ".[][][\"etc\"][\"$etc\"][\"max\"]") + +	if [[ "$max_occ" -ne "$exp_max_occ" ]]; then +		err=1 +	fi + +	echo $max_occ +	return $err +} + +port_pool_test() +{ +	local exp_max_occ=288 +	local max_occ + +	devlink sb occupancy clearmax $DEVLINK_DEV + +	$MZ $h1 -c 1 -p 160 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \ +		-t ip -q + +	devlink sb occupancy snapshot $DEVLINK_DEV + +	RET=0 +	max_occ=$(sb_occ_pool_check $dl_port1 $SB_POOL_ING $exp_max_occ) +	check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h1) ingress pool" + +	RET=0 +	max_occ=$(sb_occ_pool_check $dl_port2 $SB_POOL_ING $exp_max_occ) +	check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h2) ingress pool" + +	RET=0 +	max_occ=$(sb_occ_pool_check $cpu_dl_port $SB_POOL_EGR_CPU $exp_max_occ) +	check_err $? "Expected ePool($SB_POOL_EGR_CPU) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "CPU port's egress pool" +} + +port_tc_ip_test() +{ +	local exp_max_occ=288 +	local max_occ + +	devlink sb occupancy clearmax $DEVLINK_DEV + +	$MZ $h1 -c 1 -p 160 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \ +		-t ip -q + +	devlink sb occupancy snapshot $DEVLINK_DEV + +	RET=0 +	max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) +	check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h1) ingress TC - IP packet" + +	RET=0 +	max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) +	check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h2) ingress TC - IP packet" + +	RET=0 +	max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_IP $exp_max_occ) +	check_err $? "Expected egress TC($SB_ITC_CPU_IP) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "CPU port's egress TC - IP packet" +} + +port_tc_arp_test() +{ +	local exp_max_occ=96 +	local max_occ + +	if [[ $MLXSW_CHIP != "mlxsw_spectrum" ]]; then +		exp_max_occ=144 +	fi + +	devlink sb occupancy clearmax $DEVLINK_DEV + +	$MZ $h1 -c 1 -p 160 -a $h1mac -A 192.0.1.1 -t arp -q + +	devlink sb occupancy snapshot $DEVLINK_DEV + +	RET=0 +	max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) +	check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h1) ingress TC - ARP packet" + +	RET=0 +	max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) +	check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "physical port's($h2) ingress TC - ARP packet" + +	RET=0 +	max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_ARP $exp_max_occ) +	check_err $? "Expected egress TC($SB_ITC_IP2ME) max occupancy to be $exp_max_occ, but got $max_occ" +	log_test "CPU port's egress TC - ARP packet" +} + +setup_prepare() +{ +	h1=${NETIFS[p1]} +	h2=${NETIFS[p2]} + +	h1mac=$(mac_get $h1) +	h2mac=$(mac_get $h2) + +	dl_port1=$(devlink_port_by_netdev $h1) +	dl_port2=$(devlink_port_by_netdev $h2) + +	cpu_dl_port=$(devlink_cpu_port_get) + +	vrf_prepare + +	h1_create +	h2_create +} + +cleanup() +{ +	pre_cleanup + +	h2_destroy +	h1_destroy + +	vrf_cleanup +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py new file mode 100755 index 000000000000..0d4b9327c9b3 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer_configuration.py @@ -0,0 +1,416 @@ +#!/usr/bin/python +# SPDX-License-Identifier: GPL-2.0 + +import subprocess +import json as j +import random + + +class SkipTest(Exception): +    pass + + +class RandomValuePicker: +    """ +    Class for storing shared buffer configuration. Can handle 3 different +    objects, pool, tcbind and portpool. Provide an interface to get random +    values for a specific object type as the follow: +      1. Pool: +         - random size + +      2. TcBind: +         - random pool number +         - random threshold + +      3. PortPool: +         - random threshold +    """ +    def __init__(self, pools): +        self._pools = [] +        for pool in pools: +            self._pools.append(pool) + +    def _cell_size(self): +        return self._pools[0]["cell_size"] + +    def _get_static_size(self, th): +        # For threshold of 16, this works out to be about 12MB on Spectrum-1, +        # and about 17MB on Spectrum-2. +        return th * 8000 * self._cell_size() + +    def _get_size(self): +        return self._get_static_size(16) + +    def _get_thtype(self): +        return "static" + +    def _get_th(self, pool): +        # Threshold value could be any integer between 3 to 16 +        th = random.randint(3, 16) +        if pool["thtype"] == "dynamic": +            return th +        else: +            return self._get_static_size(th) + +    def _get_pool(self, direction): +        ing_pools = [] +        egr_pools = [] +        for pool in self._pools: +            if pool["type"] == "ingress": +                ing_pools.append(pool) +            else: +                egr_pools.append(pool) +        if direction == "ingress": +            arr = ing_pools +        else: +            arr = egr_pools +        return arr[random.randint(0, len(arr) - 1)] + +    def get_value(self, objid): +        if isinstance(objid, Pool): +            if objid["pool"] in [4, 8, 9, 10]: +                # The threshold type of pools 4, 8, 9 and 10 cannot be changed +                raise SkipTest() +            else: +                return (self._get_size(), self._get_thtype()) +        if isinstance(objid, TcBind): +            if objid["tc"] >= 8: +                # Multicast TCs cannot be changed +                raise SkipTest() +            else: +                pool = self._get_pool(objid["type"]) +                th = self._get_th(pool) +                pool_n = pool["pool"] +                return (pool_n, th) +        if isinstance(objid, PortPool): +            pool_n = objid["pool"] +            pool = self._pools[pool_n] +            assert pool["pool"] == pool_n +            th = self._get_th(pool) +            return (th,) + + +class RecordValuePickerException(Exception): +    pass + + +class RecordValuePicker: +    """ +    Class for storing shared buffer configuration. Can handle 2 different +    objects, pool and tcbind. Provide an interface to get the stored values per +    object type. +    """ +    def __init__(self, objlist): +        self._recs = [] +        for item in objlist: +            self._recs.append({"objid": item, "value": item.var_tuple()}) + +    def get_value(self, objid): +        if isinstance(objid, Pool) and objid["pool"] in [4, 8, 9, 10]: +            # The threshold type of pools 4, 8, 9 and 10 cannot be changed +            raise SkipTest() +        if isinstance(objid, TcBind) and objid["tc"] >= 8: +            # Multicast TCs cannot be changed +            raise SkipTest() +        for rec in self._recs: +            if rec["objid"].weak_eq(objid): +                return rec["value"] +        raise RecordValuePickerException() + + +def run_cmd(cmd, json=False): +    out = subprocess.check_output(cmd, shell=True) +    if json: +        return j.loads(out) +    return out + + +def run_json_cmd(cmd): +    return run_cmd(cmd, json=True) + + +def log_test(test_name, err_msg=None): +    if err_msg: +        print("\t%s" % err_msg) +        print("TEST: %-80s  [FAIL]" % test_name) +    else: +        print("TEST: %-80s  [ OK ]" % test_name) + + +class CommonItem(dict): +    varitems = [] + +    def var_tuple(self): +        ret = [] +        self.varitems.sort() +        for key in self.varitems: +            ret.append(self[key]) +        return tuple(ret) + +    def weak_eq(self, other): +        for key in self: +            if key in self.varitems: +                continue +            if self[key] != other[key]: +                return False +        return True + + +class CommonList(list): +    def get_by(self, by_obj): +        for item in self: +            if item.weak_eq(by_obj): +                return item +        return None + +    def del_by(self, by_obj): +        for item in self: +            if item.weak_eq(by_obj): +                self.remove(item) + + +class Pool(CommonItem): +    varitems = ["size", "thtype"] + +    def dl_set(self, dlname, size, thtype): +        run_cmd("devlink sb pool set {} sb {} pool {} size {} thtype {}".format(dlname, self["sb"], +                                                                                self["pool"], +                                                                                size, thtype)) + + +class PoolList(CommonList): +    pass + + +def get_pools(dlname, direction=None): +    d = run_json_cmd("devlink sb pool show -j") +    pools = PoolList() +    for pooldict in d["pool"][dlname]: +        if not direction or direction == pooldict["type"]: +            pools.append(Pool(pooldict)) +    return pools + + +def do_check_pools(dlname, pools, vp): +    for pool in pools: +        pre_pools = get_pools(dlname) +        try: +            (size, thtype) = vp.get_value(pool) +        except SkipTest: +            continue +        pool.dl_set(dlname, size, thtype) +        post_pools = get_pools(dlname) +        pool = post_pools.get_by(pool) + +        err_msg = None +        if pool["size"] != size: +            err_msg = "Incorrect pool size (got {}, expected {})".format(pool["size"], size) +        if pool["thtype"] != thtype: +            err_msg = "Incorrect pool threshold type (got {}, expected {})".format(pool["thtype"], thtype) + +        pre_pools.del_by(pool) +        post_pools.del_by(pool) +        if pre_pools != post_pools: +            err_msg = "Other pool setup changed as well" +        log_test("pool {} of sb {} set verification".format(pool["pool"], +                                                            pool["sb"]), err_msg) + + +def check_pools(dlname, pools): +    # Save defaults +    record_vp = RecordValuePicker(pools) + +    # For each pool, set random size and static threshold type +    do_check_pools(dlname, pools, RandomValuePicker(pools)) + +    # Restore defaults +    do_check_pools(dlname, pools, record_vp) + + +class TcBind(CommonItem): +    varitems = ["pool", "threshold"] + +    def __init__(self, port, d): +        super(TcBind, self).__init__(d) +        self["dlportname"] = port.name + +    def dl_set(self, pool, th): +        run_cmd("devlink sb tc bind set {} sb {} tc {} type {} pool {} th {}".format(self["dlportname"], +                                                                                     self["sb"], +                                                                                     self["tc"], +                                                                                     self["type"], +                                                                                     pool, th)) + + +class TcBindList(CommonList): +    pass + + +def get_tcbinds(ports, verify_existence=False): +    d = run_json_cmd("devlink sb tc bind show -j -n") +    tcbinds = TcBindList() +    for port in ports: +        err_msg = None +        if port.name not in d["tc_bind"] or len(d["tc_bind"][port.name]) == 0: +            err_msg = "No tc bind for port" +        else: +            for tcbinddict in d["tc_bind"][port.name]: +                tcbinds.append(TcBind(port, tcbinddict)) +        if verify_existence: +            log_test("tc bind existence for port {} verification".format(port.name), err_msg) +    return tcbinds + + +def do_check_tcbind(ports, tcbinds, vp): +    for tcbind in tcbinds: +        pre_tcbinds = get_tcbinds(ports) +        try: +            (pool, th) = vp.get_value(tcbind) +        except SkipTest: +            continue +        tcbind.dl_set(pool, th) +        post_tcbinds = get_tcbinds(ports) +        tcbind = post_tcbinds.get_by(tcbind) + +        err_msg = None +        if tcbind["pool"] != pool: +            err_msg = "Incorrect pool (got {}, expected {})".format(tcbind["pool"], pool) +        if tcbind["threshold"] != th: +            err_msg = "Incorrect threshold (got {}, expected {})".format(tcbind["threshold"], th) + +        pre_tcbinds.del_by(tcbind) +        post_tcbinds.del_by(tcbind) +        if pre_tcbinds != post_tcbinds: +            err_msg = "Other tc bind setup changed as well" +        log_test("tc bind {}-{} of sb {} set verification".format(tcbind["dlportname"], +                                                                  tcbind["tc"], +                                                                  tcbind["sb"]), err_msg) + + +def check_tcbind(dlname, ports, pools): +    tcbinds = get_tcbinds(ports, verify_existence=True) + +    # Save defaults +    record_vp = RecordValuePicker(tcbinds) + +    # Bind each port and unicast TC (TCs < 8) to a random pool and a random +    # threshold +    do_check_tcbind(ports, tcbinds, RandomValuePicker(pools)) + +    # Restore defaults +    do_check_tcbind(ports, tcbinds, record_vp) + + +class PortPool(CommonItem): +    varitems = ["threshold"] + +    def __init__(self, port, d): +        super(PortPool, self).__init__(d) +        self["dlportname"] = port.name + +    def dl_set(self, th): +        run_cmd("devlink sb port pool set {} sb {} pool {} th {}".format(self["dlportname"], +                                                                         self["sb"], +                                                                         self["pool"], th)) + + +class PortPoolList(CommonList): +    pass + + +def get_portpools(ports, verify_existence=False): +    d = run_json_cmd("devlink sb port pool -j -n") +    portpools = PortPoolList() +    for port in ports: +        err_msg = None +        if port.name not in d["port_pool"] or len(d["port_pool"][port.name]) == 0: +            err_msg = "No port pool for port" +        else: +            for portpooldict in d["port_pool"][port.name]: +                portpools.append(PortPool(port, portpooldict)) +        if verify_existence: +            log_test("port pool existence for port {} verification".format(port.name), err_msg) +    return portpools + + +def do_check_portpool(ports, portpools, vp): +    for portpool in portpools: +        pre_portpools = get_portpools(ports) +        (th,) = vp.get_value(portpool) +        portpool.dl_set(th) +        post_portpools = get_portpools(ports) +        portpool = post_portpools.get_by(portpool) + +        err_msg = None +        if portpool["threshold"] != th: +            err_msg = "Incorrect threshold (got {}, expected {})".format(portpool["threshold"], th) + +        pre_portpools.del_by(portpool) +        post_portpools.del_by(portpool) +        if pre_portpools != post_portpools: +            err_msg = "Other port pool setup changed as well" +        log_test("port pool {}-{} of sb {} set verification".format(portpool["dlportname"], +                                                                    portpool["pool"], +                                                                    portpool["sb"]), err_msg) + + +def check_portpool(dlname, ports, pools): +    portpools = get_portpools(ports, verify_existence=True) + +    # Save defaults +    record_vp = RecordValuePicker(portpools) + +    # For each port pool, set a random threshold +    do_check_portpool(ports, portpools, RandomValuePicker(pools)) + +    # Restore defaults +    do_check_portpool(ports, portpools, record_vp) + + +class Port: +    def __init__(self, name): +        self.name = name + + +class PortList(list): +    pass + + +def get_ports(dlname): +    d = run_json_cmd("devlink port show -j") +    ports = PortList() +    for name in d["port"]: +        if name.find(dlname) == 0 and d["port"][name]["flavour"] == "physical": +            ports.append(Port(name)) +    return ports + + +def get_device(): +    devices_info = run_json_cmd("devlink -j dev info")["info"] +    for d in devices_info: +        if "mlxsw_spectrum" in devices_info[d]["driver"]: +            return d +    return None + + +class UnavailableDevlinkNameException(Exception): +    pass + + +def test_sb_configuration(): +    # Use static seed +    random.seed(0) + +    dlname = get_device() +    if not dlname: +        raise UnavailableDevlinkNameException() + +    ports = get_ports(dlname) +    pools = get_pools(dlname) + +    check_pools(dlname, pools) +    check_tcbind(dlname, ports, pools) +    check_portpool(dlname, ports, pools) + + +test_sb_configuration() diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh index 7b2acba82a49..fd583a171db7 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh @@ -8,8 +8,9 @@ source $lib_dir/lib.sh  source $lib_dir/tc_common.sh  source $lib_dir/devlink_lib.sh -if [ "$DEVLINK_VIDDID" != "15b3:cf6c" ]; then -	echo "SKIP: test is tailored for Mellanox Spectrum-2" +if [[ "$DEVLINK_VIDDID" != "15b3:cf6c" && \ +	"$DEVLINK_VIDDID" != "15b3:cf70" ]]; then +	echo "SKIP: test is tailored for Mellanox Spectrum-2 and Spectrum-3"  	exit 1  fi diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower_scale.sh index a0795227216e..efd798a85931 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower_scale.sh @@ -8,9 +8,9 @@ tc_flower_get_target()  	# The driver associates a counter with each tc filter, which means the  	# number of supported filters is bounded by the number of available  	# counters. -	# Currently, the driver supports 12K (12,288) flow counters and six of +	# Currently, the driver supports 30K (30,720) flow counters and six of  	# these are used for multicast routing. -	local target=12282 +	local target=30714  	if ((! should_fail)); then  		echo $target diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_action_hw_stats.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_action_hw_stats.sh new file mode 100755 index 000000000000..20ed98fe5a60 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_action_hw_stats.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" +	default_hw_stats_test +	immediate_hw_stats_test +	delayed_hw_stats_test +	disabled_hw_stats_test +" +NUM_NETIFS=2 + +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ +	simple_if_init $h1 192.0.2.1/24 +} + +h1_destroy() +{ +	simple_if_fini $h1 192.0.2.1/24 +} + +switch_create() +{ +	simple_if_init $swp1 192.0.2.2/24 +	tc qdisc add dev $swp1 clsact +} + +switch_destroy() +{ +	tc qdisc del dev $swp1 clsact +	simple_if_fini $swp1 192.0.2.2/24 +} + +hw_stats_test() +{ +	RET=0 + +	local name=$1 +	local action_hw_stats=$2 +	local occ_delta=$3 +	local expected_packet_count=$4 + +	local orig_occ=$(devlink_resource_get "counters" "flow" | jq '.["occ"]') + +	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 action drop $action_hw_stats +	check_err $? "Failed to add rule with $name hw_stats" + +	local new_occ=$(devlink_resource_get "counters" "flow" | jq '.["occ"]') +	local expected_occ=$((orig_occ + occ_delta)) +	[ "$new_occ" == "$expected_occ" ] +	check_err $? "Expected occupancy of $expected_occ, got $new_occ" + +	$MZ $h1 -c 1 -p 64 -a $h1mac -b $swp1mac -A 192.0.2.1 -B 192.0.2.2 \ +		-t ip -q + +	tc_check_packets "dev $swp1 ingress" 101 $expected_packet_count +	check_err $? "Did not match incoming packet" + +	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower + +	log_test "$name hw_stats" +} + +default_hw_stats_test() +{ +	hw_stats_test "default" "" 2 1 +} + +immediate_hw_stats_test() +{ +	hw_stats_test "immediate" "hw_stats immediate" 2 1 +} + +delayed_hw_stats_test() +{ +	RET=0 + +	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 action drop hw_stats delayed +	check_fail $? "Unexpected success in adding rule with delayed hw_stats" + +	log_test "delayed hw_stats" +} + +disabled_hw_stats_test() +{ +	hw_stats_test "disabled" "hw_stats disabled" 0 0 +} + +setup_prepare() +{ +	h1=${NETIFS[p1]} +	swp1=${NETIFS[p2]} + +	h1mac=$(mac_get $h1) +	swp1mac=$(mac_get $swp1) + +	vrf_prepare + +	h1_create +	switch_create +} + +cleanup() +{ +	pre_cleanup + +	switch_destroy +	h1_destroy + +	vrf_cleanup +} + +check_tc_action_hw_stats_support + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_flower_restrictions.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_flower_restrictions.sh new file mode 100755 index 000000000000..68c80d0ec1ec --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_flower_restrictions.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" +	shared_block_drop_test +	egress_redirect_test +	multi_mirror_test +" +NUM_NETIFS=2 + +source $lib_dir/tc_common.sh +source $lib_dir/lib.sh + +switch_create() +{ +	simple_if_init $swp1 192.0.2.1/24 +	simple_if_init $swp2 192.0.2.2/24 +} + +switch_destroy() +{ +	simple_if_fini $swp2 192.0.2.2/24 +	simple_if_fini $swp1 192.0.2.1/24 +} + +shared_block_drop_test() +{ +	RET=0 + +	# It is forbidden in mlxsw driver to have mixed-bound +	# shared block with a drop rule. + +	tc qdisc add dev $swp1 ingress_block 22 clsact +	check_err $? "Failed to create clsact with ingress block" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 action drop +	check_err $? "Failed to add drop rule to ingress bound block" + +	tc qdisc add dev $swp2 ingress_block 22 clsact +	check_err $? "Failed to create another clsact with ingress shared block" + +	tc qdisc del dev $swp2 clsact + +	tc qdisc add dev $swp2 egress_block 22 clsact +	check_fail $? "Incorrect success to create another clsact with egress shared block" + +	tc filter del block 22 protocol ip pref 1 handle 101 flower + +	tc qdisc add dev $swp2 egress_block 22 clsact +	check_err $? "Failed to create another clsact with egress shared block after blocker drop rule removed" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 action drop +	check_fail $? "Incorrect success to add drop rule to mixed bound block" + +	tc qdisc del dev $swp1 clsact + +	tc qdisc add dev $swp1 egress_block 22 clsact +	check_err $? "Failed to create another clsact with egress shared block" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 action drop +	check_err $? "Failed to add drop rule to egress bound shared block" + +	tc filter del block 22 protocol ip pref 1 handle 101 flower + +	tc qdisc del dev $swp2 clsact +	tc qdisc del dev $swp1 clsact + +	log_test "shared block drop" +} + +egress_redirect_test() +{ +	RET=0 + +	# It is forbidden in mlxsw driver to have mirred redirect on +	# egress-bound block. + +	tc qdisc add dev $swp1 ingress_block 22 clsact +	check_err $? "Failed to create clsact with ingress block" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress redirect dev $swp2 +	check_err $? "Failed to add redirect rule to ingress bound block" + +	tc qdisc add dev $swp2 ingress_block 22 clsact +	check_err $? "Failed to create another clsact with ingress shared block" + +	tc qdisc del dev $swp2 clsact + +	tc qdisc add dev $swp2 egress_block 22 clsact +	check_fail $? "Incorrect success to create another clsact with egress shared block" + +	tc filter del block 22 protocol ip pref 1 handle 101 flower + +	tc qdisc add dev $swp2 egress_block 22 clsact +	check_err $? "Failed to create another clsact with egress shared block after blocker redirect rule removed" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress redirect dev $swp2 +	check_fail $? "Incorrect success to add redirect rule to mixed bound block" + +	tc qdisc del dev $swp1 clsact + +	tc qdisc add dev $swp1 egress_block 22 clsact +	check_err $? "Failed to create another clsact with egress shared block" + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress redirect dev $swp2 +	check_fail $? "Incorrect success to add redirect rule to egress bound shared block" + +	tc qdisc del dev $swp2 clsact + +	tc filter add block 22 protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress redirect dev $swp2 +	check_fail $? "Incorrect success to add redirect rule to egress bound block" + +	tc qdisc del dev $swp1 clsact + +	log_test "shared block drop" +} + +multi_mirror_test() +{ +	RET=0 + +	# It is forbidden in mlxsw driver to have multiple mirror +	# actions in a single rule. + +	tc qdisc add dev $swp1 clsact + +	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress mirror dev $swp2 +	check_err $? "Failed to add rule with single mirror action" + +	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower + +	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \ +		skip_sw dst_ip 192.0.2.2 \ +		action mirred egress mirror dev $swp2 \ +		action mirred egress mirror dev $swp1 +	check_fail $? "Incorrect success to add rule with two mirror actions" + +	tc qdisc del dev $swp1 clsact + +	log_test "multi mirror" +} + +setup_prepare() +{ +	swp1=${NETIFS[p1]} +	swp2=${NETIFS[p2]} + +	vrf_prepare + +	switch_create +} + +cleanup() +{ +	pre_cleanup + +	switch_destroy + +	vrf_cleanup +} + +check_tc_shblock_support + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_flower_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_flower_scale.sh index a6d733d2a4b4..cc0f07e72cf2 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/tc_flower_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_flower_scale.sh @@ -2,9 +2,9 @@  # SPDX-License-Identifier: GPL-2.0  # Test for resource limit of offloaded flower rules. The test adds a given -# number of flower matches for different IPv6 addresses, then generates traffic, -# and ensures each was hit exactly once. This file contains functions to set up -# a testing topology and run the test, and is meant to be sourced from a test +# number of flower matches for different IPv6 addresses, then check the offload +# indication for all of the tc flower rules. This file contains functions to set +# up a testing topology and run the test, and is meant to be sourced from a test  # script that calls the testing routine with a given number of rules.  TC_FLOWER_NUM_NETIFS=2 @@ -94,22 +94,15 @@ __tc_flower_test()  	tc_flower_rules_create $count $should_fail -	for ((i = 0; i < count; ++i)); do -		$MZ $h1 -q -c 1 -t ip -p 20 -b bc -6 \ -			-A 2001:db8:2::1 \ -			-B $(tc_flower_addr $i) -	done - -	MISMATCHES=$( -		tc -j -s filter show dev $h2 ingress | -		jq -r '[ .[] | select(.kind == "flower") | .options | -		         values as $rule | .actions[].stats.packets | -		         select(. != 1) | "\(.) on \($rule.keys.dst_ip)" ] | -		       join(", ")' -	) - -	test -z "$MISMATCHES" -	check_err $? "Expected to capture 1 packet for each IP, but got $MISMATCHES" +	offload_count=$(tc -j -s filter show dev $h2 ingress    | +			jq -r '[ .[] | select(.kind == "flower") | +			.options | .in_hw ]' | jq .[] | wc -l) +	[[ $((offload_count - 1)) -eq $count ]] +	if [[ $should_fail -eq 0 ]]; then +		check_err $? "Offload mismatch" +	else +		check_err_fail $should_fail $? "Offload more than expacted" +	fi  }  tc_flower_test() diff --git a/tools/testing/selftests/drivers/net/mlxsw/vxlan.sh b/tools/testing/selftests/drivers/net/mlxsw/vxlan.sh index 4632f51af7ab..729a86cc4ede 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/vxlan.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/vxlan.sh @@ -9,6 +9,7 @@ lib_dir=$(dirname $0)/../../../net/forwarding  ALL_TESTS="sanitization_test offload_indication_test \  	sanitization_vlan_aware_test offload_indication_vlan_aware_test"  NUM_NETIFS=2 +: ${TIMEOUT:=20000} # ms  source $lib_dir/lib.sh  setup_prepare() @@ -470,8 +471,8 @@ offload_indication_fdb_flood_test()  	bridge fdb append 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.2 -	bridge fdb show brport vxlan0 | grep 00:00:00:00:00:00 \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb 00:00:00:00:00:00 \ +		bridge fdb show brport vxlan0  	check_err $?  	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self @@ -486,11 +487,11 @@ offload_indication_fdb_bridge_test()  	bridge fdb add de:ad:be:ef:13:37 dev vxlan0 self master static \  		dst 198.51.100.2 -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan0  	check_err $? -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0  	check_err $?  	log_test "vxlan entry offload indication - initial state" @@ -500,9 +501,9 @@ offload_indication_fdb_bridge_test()  	RET=0  	bridge fdb del de:ad:be:ef:13:37 dev vxlan0 master -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan0 +	check_err $?  	log_test "vxlan entry offload indication - after removal from bridge" @@ -511,11 +512,11 @@ offload_indication_fdb_bridge_test()  	RET=0  	bridge fdb add de:ad:be:ef:13:37 dev vxlan0 master static -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan0  	check_err $? -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0  	check_err $?  	log_test "vxlan entry offload indication - after re-add to bridge" @@ -525,9 +526,9 @@ offload_indication_fdb_bridge_test()  	RET=0  	bridge fdb del de:ad:be:ef:13:37 dev vxlan0 self -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0 +	check_err $?  	log_test "vxlan entry offload indication - after removal from vxlan" @@ -536,11 +537,11 @@ offload_indication_fdb_bridge_test()  	RET=0  	bridge fdb add de:ad:be:ef:13:37 dev vxlan0 self dst 198.51.100.2 -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan0  	check_err $? -	bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0  	check_err $?  	log_test "vxlan entry offload indication - after re-add to vxlan" @@ -558,27 +559,32 @@ offload_indication_decap_route_test()  {  	RET=0 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link set dev vxlan0 down -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link set dev vxlan1 down -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	log_test "vxlan decap route - vxlan device down"  	RET=0  	ip link set dev vxlan1 up -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link set dev vxlan0 up -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	log_test "vxlan decap route - vxlan device up" @@ -586,11 +592,13 @@ offload_indication_decap_route_test()  	RET=0  	ip address delete 198.51.100.1/32 dev lo -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	ip address add 198.51.100.1/32 dev lo -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	log_test "vxlan decap route - add local route" @@ -598,16 +606,19 @@ offload_indication_decap_route_test()  	RET=0  	ip link set dev $swp1 nomaster -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link set dev $swp2 nomaster -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	ip link set dev $swp1 master br0  	ip link set dev $swp2 master br1 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	log_test "vxlan decap route - local ports enslavement" @@ -615,12 +626,14 @@ offload_indication_decap_route_test()  	RET=0  	ip link del dev br0 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link del dev br1 -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	log_test "vxlan decap route - bridge device deletion" @@ -632,16 +645,19 @@ offload_indication_decap_route_test()  	ip link set dev $swp2 master br1  	ip link set dev vxlan0 master br0  	ip link set dev vxlan1 master br1 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link del dev vxlan0 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	ip link del dev vxlan1 -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	log_test "vxlan decap route - vxlan device deletion" @@ -656,12 +672,15 @@ check_fdb_offloaded()  	local mac=00:11:22:33:44:55  	local zmac=00:00:00:00:00:00 -	bridge fdb show dev vxlan0 | grep $mac | grep self | grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $mac self \ +		bridge fdb show dev vxlan0  	check_err $? -	bridge fdb show dev vxlan0 | grep $mac | grep master | grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $mac master \ +		bridge fdb show dev vxlan0  	check_err $? -	bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show dev vxlan0  	check_err $?  } @@ -672,13 +691,15 @@ check_vxlan_fdb_not_offloaded()  	bridge fdb show dev vxlan0 | grep $mac | grep -q self  	check_err $? -	bridge fdb show dev vxlan0 | grep $mac | grep self | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $mac self \ +		bridge fdb show dev vxlan0 +	check_err $?  	bridge fdb show dev vxlan0 | grep $zmac | grep -q self  	check_err $? -	bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show dev vxlan0 +	check_err $?  }  check_bridge_fdb_not_offloaded() @@ -688,8 +709,9 @@ check_bridge_fdb_not_offloaded()  	bridge fdb show dev vxlan0 | grep $mac | grep -q master  	check_err $? -	bridge fdb show dev vxlan0 | grep $mac | grep master | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $mac master \ +		bridge fdb show dev vxlan0 +	check_err $?  }  __offload_indication_join_vxlan_first() @@ -771,12 +793,14 @@ __offload_indication_join_vxlan_last()  	ip link set dev $swp1 master br0 -	bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show dev vxlan0 +	check_err $?  	ip link set dev vxlan0 master br0 -	bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show dev vxlan0  	check_err $?  	log_test "offload indication - attach vxlan last" @@ -854,20 +878,26 @@ sanitization_vlan_aware_test()  	bridge vlan del vid 10 dev vxlan20  	bridge vlan add vid 20 dev vxlan20 pvid untagged -	# Test that offloading of an unsupported tunnel fails when it is -	# triggered by addition of VLAN to a local port -	RET=0 +	# Test that when two VXLAN tunnels with conflicting configurations +	# (i.e., different TTL) are enslaved to the same VLAN-aware bridge, +	# then the enslavement of a port to the bridge is denied. -	# TOS must be set to inherit -	ip link set dev vxlan10 type vxlan tos 42 +	# Use the offload indication of the local route to ensure the VXLAN +	# configuration was correctly rollbacked. +	ip address add 198.51.100.1/32 dev lo -	ip link set dev $swp1 master br0 -	bridge vlan add vid 10 dev $swp1 &> /dev/null +	ip link set dev vxlan10 type vxlan ttl 10 +	ip link set dev $swp1 master br0 &> /dev/null  	check_fail $? -	log_test "vlan-aware - failed vlan addition to a local port" +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $? + +	log_test "vlan-aware - failed enslavement to bridge due to conflict" -	ip link set dev vxlan10 type vxlan tos inherit +	ip link set dev vxlan10 type vxlan ttl 20 +	ip address del 198.51.100.1/32 dev lo  	ip link del dev vxlan20  	ip link del dev vxlan10 @@ -924,11 +954,11 @@ offload_indication_vlan_aware_fdb_test()  	bridge fdb add de:ad:be:ef:13:37 dev vxlan10 self master static \  		dst 198.51.100.2 vlan 10 -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan10  	check_err $? -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10  	check_err $?  	log_test "vxlan entry offload indication - initial state" @@ -938,9 +968,9 @@ offload_indication_vlan_aware_fdb_test()  	RET=0  	bridge fdb del de:ad:be:ef:13:37 dev vxlan10 master vlan 10 -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan10 +	check_err $?  	log_test "vxlan entry offload indication - after removal from bridge" @@ -949,11 +979,11 @@ offload_indication_vlan_aware_fdb_test()  	RET=0  	bridge fdb add de:ad:be:ef:13:37 dev vxlan10 master static vlan 10 -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan10  	check_err $? -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10  	check_err $?  	log_test "vxlan entry offload indication - after re-add to bridge" @@ -963,9 +993,9 @@ offload_indication_vlan_aware_fdb_test()  	RET=0  	bridge fdb del de:ad:be:ef:13:37 dev vxlan10 self -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10 +	check_err $?  	log_test "vxlan entry offload indication - after removal from vxlan" @@ -974,11 +1004,11 @@ offload_indication_vlan_aware_fdb_test()  	RET=0  	bridge fdb add de:ad:be:ef:13:37 dev vxlan10 self dst 198.51.100.2 -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self bridge fdb show brport vxlan10  	check_err $? -	bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \ +		de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10  	check_err $?  	log_test "vxlan entry offload indication - after re-add to vxlan" @@ -990,28 +1020,31 @@ offload_indication_vlan_aware_decap_route_test()  {  	RET=0 -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	# Toggle PVID flag on one VxLAN device and make sure route is still  	# marked as offloaded  	bridge vlan add vid 10 dev vxlan10 untagged -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload \ +		ip route show table local 198.51.100.1  	check_err $?  	# Toggle PVID flag on second VxLAN device and make sure route is no  	# longer marked as offloaded  	bridge vlan add vid 20 dev vxlan20 untagged -	ip route show table local | grep 198.51.100.1 | grep -q offload -	check_fail $? +	busywait "$TIMEOUT" not wait_for_offload \ +		ip route show table local 198.51.100.1 +	check_err $?  	# Toggle PVID flag back and make sure route is marked as offloaded  	bridge vlan add vid 10 dev vxlan10 pvid untagged  	bridge vlan add vid 20 dev vxlan20 pvid untagged -	ip route show table local | grep 198.51.100.1 | grep -q offload +	busywait "$TIMEOUT" wait_for_offload ip route show table local 198.51.100.1  	check_err $?  	log_test "vxlan decap route - vni map/unmap" @@ -1064,35 +1097,33 @@ offload_indication_vlan_aware_l3vni_test()  	ip link set dev vxlan0 master br0  	bridge vlan add dev vxlan0 vid 10 pvid untagged -	# No local port or router port is member in the VLAN, so tunnel should -	# not be offloaded -	bridge fdb show brport vxlan0 | grep $zmac | grep self \ -		| grep -q offload -	check_fail $? "vxlan tunnel offloaded when should not" +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show brport vxlan0 +	check_err $? "vxlan tunnel not offloaded when should"  	# Configure a VLAN interface and make sure tunnel is offloaded  	ip link add link br0 name br10 up type vlan id 10  	sysctl_set net.ipv6.conf.br10.disable_ipv6 0  	ip -6 address add 2001:db8:1::1/64 dev br10 -	bridge fdb show brport vxlan0 | grep $zmac | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show brport vxlan0  	check_err $? "vxlan tunnel not offloaded when should"  	# Unlink the VXLAN device, make sure tunnel is no longer offloaded,  	# then add it back to the bridge and make sure it is offloaded  	ip link set dev vxlan0 nomaster -	bridge fdb show brport vxlan0 | grep $zmac | grep self \ -		| grep -q offload -	check_fail $? "vxlan tunnel offloaded after unlinked from bridge" +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show brport vxlan0 +	check_err $? "vxlan tunnel offloaded after unlinked from bridge"  	ip link set dev vxlan0 master br0 -	bridge fdb show brport vxlan0 | grep $zmac | grep self \ -		| grep -q offload -	check_fail $? "vxlan tunnel offloaded despite no matching vid" +	busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show brport vxlan0 +	check_err $? "vxlan tunnel offloaded despite no matching vid"  	bridge vlan add dev vxlan0 vid 10 pvid untagged -	bridge fdb show brport vxlan0 | grep $zmac | grep self \ -		| grep -q offload +	busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \ +		bridge fdb show brport vxlan0  	check_err $? "vxlan tunnel not offloaded after adding vid"  	log_test "vxlan - l3 vni" diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh index 025a84c2ab5a..9f9741444549 100755 --- a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +++ b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh @@ -141,6 +141,16 @@ regions_test()  	check_region_snapshot_count dummy post-first-delete 2 +	devlink region new $DL_HANDLE/dummy snapshot 25 +	check_err $? "Failed to create a new snapshot with id 25" + +	check_region_snapshot_count dummy post-first-request 3 + +	devlink region del $DL_HANDLE/dummy snapshot 25 +	check_err $? "Failed to delete snapshot with id 25" + +	check_region_snapshot_count dummy post-second-delete 2 +  	log_test "regions test"  } @@ -367,6 +377,11 @@ dummy_reporter_test()  {  	RET=0 +	check_reporter_info dummy healthy 0 0 0 true + +	devlink health set $DL_HANDLE reporter dummy auto_recover false +	check_err $? "Failed to dummy reporter auto_recover option" +  	check_reporter_info dummy healthy 0 0 0 false  	local BREAK_MSG="foo bar" diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh index f101ab9441e2..dbd1e014ba17 100755 --- a/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh +++ b/tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh @@ -16,6 +16,8 @@ ALL_TESTS="  	trap_group_action_test  	bad_trap_group_test  	trap_group_stats_test +	trap_policer_test +	trap_policer_bind_test  	port_del_test  	dev_del_test  " @@ -23,6 +25,7 @@ NETDEVSIM_PATH=/sys/bus/netdevsim/  DEV_ADDR=1337  DEV=netdevsim${DEV_ADDR}  DEVLINK_DEV=netdevsim/${DEV} +DEBUGFS_DIR=/sys/kernel/debug/netdevsim/$DEV/  SLEEP_TIME=1  NETDEV=""  NUM_NETIFS=0 @@ -103,6 +106,11 @@ trap_metadata_test()  	for trap_name in $(devlink_traps_get); do  		devlink_trap_metadata_test $trap_name "input_port"  		check_err $? "Input port not reported as metadata of trap $trap_name" +		if [ $trap_name == "ingress_flow_action_drop" ] || +		   [ $trap_name == "egress_flow_action_drop" ]; then +			devlink_trap_metadata_test $trap_name "flow_action_cookie" +			check_err $? "Flow action cookie not reported as metadata of trap $trap_name" +		fi  	done  	log_test "Trap metadata" @@ -251,6 +259,119 @@ trap_group_stats_test()  	log_test "Trap group statistics"  } +trap_policer_test() +{ +	local packets_t0 +	local packets_t1 + +	if [ $(devlink_trap_policers_num_get) -eq 0 ]; then +		check_err 1 "Failed to dump policers" +	fi + +	devlink trap policer set $DEVLINK_DEV policer 1337 &> /dev/null +	check_fail $? "Did not get an error for setting a non-existing policer" +	devlink trap policer show $DEVLINK_DEV policer 1337 &> /dev/null +	check_fail $? "Did not get an error for getting a non-existing policer" + +	devlink trap policer set $DEVLINK_DEV policer 1 rate 2000 burst 16 +	check_err $? "Failed to set valid parameters for a valid policer" +	if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then +		check_err 1 "Policer rate was not changed" +	fi +	if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then +		check_err 1 "Policer burst size was not changed" +	fi + +	devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null +	check_fail $? "Policer rate was changed to rate lower than limit" +	devlink trap policer set $DEVLINK_DEV policer 1 rate 9000 &> /dev/null +	check_fail $? "Policer rate was changed to rate higher than limit" +	devlink trap policer set $DEVLINK_DEV policer 1 burst 2 &> /dev/null +	check_fail $? "Policer burst size was changed to burst size lower than limit" +	devlink trap policer set $DEVLINK_DEV policer 1 rate 65537 &> /dev/null +	check_fail $? "Policer burst size was changed to burst size higher than limit" +	echo "y" > $DEBUGFS_DIR/fail_trap_policer_set +	devlink trap policer set $DEVLINK_DEV policer 1 rate 3000 &> /dev/null +	check_fail $? "Managed to set policer rate when should not" +	echo "n" > $DEBUGFS_DIR/fail_trap_policer_set +	if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then +		check_err 1 "Policer rate was changed to an invalid value" +	fi +	if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then +		check_err 1 "Policer burst size was changed to an invalid value" +	fi + +	packets_t0=$(devlink_trap_policer_rx_dropped_get 1) +	sleep .5 +	packets_t1=$(devlink_trap_policer_rx_dropped_get 1) +	if [ ! $packets_t1 -gt $packets_t0 ]; then +		check_err 1 "Policer drop counter was not incremented" +	fi + +	echo "y"> $DEBUGFS_DIR/fail_trap_policer_counter_get +	devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null +	check_fail $? "Managed to read policer drop counter when should not" +	echo "n"> $DEBUGFS_DIR/fail_trap_policer_counter_get +	devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null +	check_err $? "Did not manage to read policer drop counter when should" + +	log_test "Trap policer" +} + +trap_group_check_policer() +{ +	local group_name=$1; shift + +	devlink -j -p trap group show $DEVLINK_DEV group $group_name \ +		| jq -e '.[][][]["policer"]' &> /dev/null +} + +trap_policer_bind_test() +{ +	devlink trap group set $DEVLINK_DEV group l2_drops policer 1 +	check_err $? "Failed to bind a valid policer" +	if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then +		check_err 1 "Bound policer was not changed" +	fi + +	devlink trap group set $DEVLINK_DEV group l2_drops policer 1337 \ +		&> /dev/null +	check_fail $? "Did not get an error for binding a non-existing policer" +	if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then +		check_err 1 "Bound policer was changed when should not" +	fi + +	devlink trap group set $DEVLINK_DEV group l2_drops policer 0 +	check_err $? "Failed to unbind a policer when using ID 0" +	trap_group_check_policer "l2_drops" +	check_fail $? "Trap group has a policer after unbinding with ID 0" + +	devlink trap group set $DEVLINK_DEV group l2_drops policer 1 +	check_err $? "Failed to bind a valid policer" + +	devlink trap group set $DEVLINK_DEV group l2_drops nopolicer +	check_err $? "Failed to unbind a policer when using 'nopolicer' keyword" +	trap_group_check_policer "l2_drops" +	check_fail $? "Trap group has a policer after unbinding with 'nopolicer' keyword" + +	devlink trap group set $DEVLINK_DEV group l2_drops policer 1 +	check_err $? "Failed to bind a valid policer" + +	echo "y"> $DEBUGFS_DIR/fail_trap_group_set +	devlink trap group set $DEVLINK_DEV group l2_drops policer 2 \ +		&> /dev/null +	check_fail $? "Managed to bind a policer when should not" +	echo "n"> $DEBUGFS_DIR/fail_trap_group_set +	devlink trap group set $DEVLINK_DEV group l2_drops policer 2 +	check_err $? "Did not manage to bind a policer when should" + +	devlink trap group set $DEVLINK_DEV group l2_drops action drop \ +		policer 1337 &> /dev/null +	check_fail $? "Did not get an error for partially modified trap group" + +	log_test "Trap policer binding" +} +  port_del_test()  {  	local group_name |