Commit f5e5d272 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlxsw-Allow-setting-default-port-priority'



Ido Schimmel says:

====================
mlxsw: Allow setting default port priority

Petr says:

When LLDP APP TLV selector 1 (EtherType) is used with PID of 0, the
corresponding entry specifies "default application priority [...] when
application priority is not otherwise specified."

mlxsw currently supports this type of APP entry, but uses it only as a
fallback for unspecified DSCP rules. However non-IP traffic is prioritized
according to port-default priority, not according to the DSCP-to-prio
tables, and thus it's currently not possible to prioritize such traffic
correctly.

This patchset extends the use of the abovementioned APP entry to also set
default port priority (in patches #1 and #2) and then (in patch #3) adds a
selftest.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c9a2069b c5341bcc
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -3748,6 +3748,38 @@ mlxsw_reg_qpdsm_prio_pack(char *payload, unsigned short prio, u8 dscp)
	mlxsw_reg_qpdsm_prio_entry_color2_dscp_set(payload, prio, dscp);
}

/* QPDP - QoS Port DSCP to Priority Mapping Register
 * -------------------------------------------------
 * This register controls the port default Switch Priority and Color. The
 * default Switch Priority and Color are used for frames where the trust state
 * uses default values. All member ports of a LAG should be configured with the
 * same default values.
 */
#define MLXSW_REG_QPDP_ID 0x4007
#define MLXSW_REG_QPDP_LEN 0x8

MLXSW_REG_DEFINE(qpdp, MLXSW_REG_QPDP_ID, MLXSW_REG_QPDP_LEN);

/* reg_qpdp_local_port
 * Local Port. Supported for data packets from CPU port.
 * Access: Index
 */
MLXSW_ITEM32(reg, qpdp, local_port, 0x00, 16, 8);

/* reg_qpdp_switch_prio
 * Default port Switch Priority (default 0)
 * Access: RW
 */
MLXSW_ITEM32(reg, qpdp, switch_prio, 0x04, 0, 4);

static inline void mlxsw_reg_qpdp_pack(char *payload, u8 local_port,
				       u8 switch_prio)
{
	MLXSW_REG_ZERO(qpdp, payload);
	mlxsw_reg_qpdp_local_port_set(payload, local_port);
	mlxsw_reg_qpdp_switch_prio_set(payload, switch_prio);
}

/* QPDPM - QoS Port DSCP to Priority Mapping Register
 * --------------------------------------------------
 * This register controls the mapping from DSCP field to
@@ -10580,6 +10612,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
	MLXSW_REG(qeec),
	MLXSW_REG(qrwe),
	MLXSW_REG(qpdsm),
	MLXSW_REG(qpdp),
	MLXSW_REG(qpdpm),
	MLXSW_REG(qtctm),
	MLXSW_REG(qpsc),
+17 −0
Original line number Diff line number Diff line
@@ -368,6 +368,17 @@ err_update_qrwe:
	return err;
}

static int
mlxsw_sp_port_dcb_app_update_qpdp(struct mlxsw_sp_port *mlxsw_sp_port,
				  u8 default_prio)
{
	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
	char qpdp_pl[MLXSW_REG_QPDP_LEN];

	mlxsw_reg_qpdp_pack(qpdp_pl, mlxsw_sp_port->local_port, default_prio);
	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpdp), qpdp_pl);
}

static int
mlxsw_sp_port_dcb_app_update_qpdpm(struct mlxsw_sp_port *mlxsw_sp_port,
				   struct dcb_ieee_app_dscp_map *map)
@@ -405,6 +416,12 @@ static int mlxsw_sp_port_dcb_app_update(struct mlxsw_sp_port *mlxsw_sp_port)
	int err;

	default_prio = mlxsw_sp_port_dcb_app_default_prio(mlxsw_sp_port);
	err = mlxsw_sp_port_dcb_app_update_qpdp(mlxsw_sp_port, default_prio);
	if (err) {
		netdev_err(mlxsw_sp_port->dev, "Couldn't configure port default priority\n");
		return err;
	}

	have_dscp = mlxsw_sp_port_dcb_app_prio_dscp_map(mlxsw_sp_port,
							&prio_map);

+176 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

# Test for port-default priority. Non-IP packets ingress $swp1 and are
# prioritized according to the default priority specified at the port.
# rx_octets_prio_* counters are used to verify the prioritization.
#
# +-----------------------+
# | H1                    |
# |    + $h1              |
# |    | 192.0.2.1/28     |
# +----|------------------+
#      |
# +----|------------------+
# | SW |                  |
# |    + $swp1            |
# |      192.0.2.2/28     |
# |      APP=<prio>,1,0   |
# +-----------------------+

ALL_TESTS="
	ping_ipv4
	test_defprio
"

lib_dir=$(dirname $0)/../../../net/forwarding

NUM_NETIFS=2
: ${HIT_TIMEOUT:=1000} # ms
source $lib_dir/lib.sh

declare -a APP

defprio_install()
{
	local dev=$1; shift
	local prio=$1; shift
	local app="app=$prio,1,0"

	lldptool -T -i $dev -V APP $app >/dev/null
	lldpad_app_wait_set $dev
	APP[$prio]=$app
}

defprio_uninstall()
{
	local dev=$1; shift
	local prio=$1; shift
	local app=${APP[$prio]}

	lldptool -T -i $dev -V APP -d $app >/dev/null
	lldpad_app_wait_del
	unset APP[$prio]
}

defprio_flush()
{
	local dev=$1; shift
	local prio

	if ((${#APP[@]})); then
		lldptool -T -i $dev -V APP -d ${APP[@]} >/dev/null
	fi
	lldpad_app_wait_del
	APP=()
}

h1_create()
{
	simple_if_init $h1 192.0.2.1/28
}

h1_destroy()
{
	simple_if_fini $h1 192.0.2.1/28
}

switch_create()
{
	ip link set dev $swp1 up
	ip addr add dev $swp1 192.0.2.2/28
}

switch_destroy()
{
	defprio_flush $swp1
	ip addr del dev $swp1 192.0.2.2/28
	ip link set dev $swp1 down
}

setup_prepare()
{
	h1=${NETIFS[p1]}
	swp1=${NETIFS[p2]}

	vrf_prepare

	h1_create
	switch_create
}

cleanup()
{
	pre_cleanup

	switch_destroy
	h1_destroy

	vrf_cleanup
}

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 i

	RET=0

	defprio_install $swp1 $prio_install

	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)

	check_err $? "Default priority $prio_install/$prio_observe: Expected to capture 10 packets, got $delta."
	log_test "Default priority $prio_install/$prio_observe"

	defprio_uninstall $swp1 $prio_install
}

test_defprio()
{
	local prio

	for prio in {0..7}; do
		__test_defprio $prio $prio
	done

	defprio_install $swp1 3
	__test_defprio 0 3
	__test_defprio 1 3
	__test_defprio 2 3
	__test_defprio 4 4
	__test_defprio 5 5
	__test_defprio 6 6
	__test_defprio 7 7
	defprio_uninstall $swp1 3
}

trap cleanup EXIT

setup_prepare
setup_wait

tests_run

exit $EXIT_STATUS
+23 −0
Original line number Diff line number Diff line
@@ -225,6 +225,29 @@ log_info()
	echo "INFO: $msg"
}

busywait()
{
	local timeout=$1; shift

	local start_time="$(date -u +%s%3N)"
	while true
	do
		local out
		out=$("$@")
		local ret=$?
		if ((!ret)); then
			echo -n "$out"
			return 0
		fi

		local current_time="$(date -u +%s%3N)"
		if ((current_time - start_time > timeout)); then
			echo -n "$out"
			return 1
		fi
	done
}

setup_wait_dev()
{
	local dev=$1; shift