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: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-01-02 15:40:14 -08:00
commit f5e5d27248
4 changed files with 249 additions and 0 deletions

View File

@ -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),

View File

@ -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);

View File

@ -0,0 +1,176 @@
#!/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

View File

@ -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