669 lines
19 KiB
Bash
669 lines
19 KiB
Bash
|
#!/bin/bash
|
||
|
# SPDX-License-Identifier: GPL-2.0
|
||
|
# Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
|
||
|
|
||
|
# The script is adopted to work with the Microchip KSZ switch driver.
|
||
|
|
||
|
ETH_FCS_LEN=4
|
||
|
|
||
|
WAIT_TIME=1
|
||
|
NUM_NETIFS=4
|
||
|
REQUIRE_JQ="yes"
|
||
|
REQUIRE_MZ="yes"
|
||
|
STABLE_MAC_ADDRS=yes
|
||
|
NETIF_CREATE=no
|
||
|
lib_dir=$(dirname $0)/../../../net/forwarding
|
||
|
source $lib_dir/tc_common.sh
|
||
|
source $lib_dir/lib.sh
|
||
|
|
||
|
require_command dcb
|
||
|
|
||
|
h1=${NETIFS[p1]}
|
||
|
swp1=${NETIFS[p2]}
|
||
|
swp2=${NETIFS[p3]}
|
||
|
h2=${NETIFS[p4]}
|
||
|
|
||
|
H1_IPV4="192.0.2.1"
|
||
|
H2_IPV4="192.0.2.2"
|
||
|
H1_IPV6="2001:db8:1::1"
|
||
|
H2_IPV6="2001:db8:1::2"
|
||
|
|
||
|
# On h1_ and h2_create do not set IP addresses to avoid interaction with the
|
||
|
# system, to keep packet counters clean.
|
||
|
h1_create()
|
||
|
{
|
||
|
simple_if_init $h1
|
||
|
sysctl_set net.ipv6.conf.${h1}.disable_ipv6 1
|
||
|
# Get the MAC address of the interface to use it with mausezahn
|
||
|
h1_mac=$(ip -j link show dev ${h1} | jq -e '.[].address')
|
||
|
}
|
||
|
|
||
|
h1_destroy()
|
||
|
{
|
||
|
sysctl_restore net.ipv6.conf.${h1}.disable_ipv6
|
||
|
simple_if_fini $h1
|
||
|
}
|
||
|
|
||
|
h2_create()
|
||
|
{
|
||
|
simple_if_init $h2
|
||
|
sysctl_set net.ipv6.conf.${h2}.disable_ipv6 1
|
||
|
h2_mac=$(ip -j link show dev ${h2} | jq -e '.[].address')
|
||
|
}
|
||
|
|
||
|
h2_destroy()
|
||
|
{
|
||
|
sysctl_restore net.ipv6.conf.${h2}.disable_ipv6
|
||
|
simple_if_fini $h2
|
||
|
}
|
||
|
|
||
|
switch_create()
|
||
|
{
|
||
|
ip link set ${swp1} up
|
||
|
ip link set ${swp2} up
|
||
|
sysctl_set net.ipv6.conf.${swp1}.disable_ipv6 1
|
||
|
sysctl_set net.ipv6.conf.${swp2}.disable_ipv6 1
|
||
|
|
||
|
# Ports should trust VLAN PCP even with vlan_filtering=0
|
||
|
ip link add br0 type bridge
|
||
|
ip link set ${swp1} master br0
|
||
|
ip link set ${swp2} master br0
|
||
|
ip link set br0 up
|
||
|
sysctl_set net.ipv6.conf.br0.disable_ipv6 1
|
||
|
}
|
||
|
|
||
|
switch_destroy()
|
||
|
{
|
||
|
sysctl_restore net.ipv6.conf.${swp2}.disable_ipv6
|
||
|
sysctl_restore net.ipv6.conf.${swp1}.disable_ipv6
|
||
|
|
||
|
ip link del br0
|
||
|
}
|
||
|
|
||
|
setup_prepare()
|
||
|
{
|
||
|
vrf_prepare
|
||
|
|
||
|
h1_create
|
||
|
h2_create
|
||
|
switch_create
|
||
|
}
|
||
|
|
||
|
cleanup()
|
||
|
{
|
||
|
pre_cleanup
|
||
|
|
||
|
h2_destroy
|
||
|
h1_destroy
|
||
|
switch_destroy
|
||
|
|
||
|
vrf_cleanup
|
||
|
}
|
||
|
|
||
|
set_apptrust_order()
|
||
|
{
|
||
|
local if_name=$1
|
||
|
local order=$2
|
||
|
|
||
|
dcb apptrust set dev ${if_name} order ${order}
|
||
|
}
|
||
|
|
||
|
# Function to extract a specified field from a given JSON stats string
|
||
|
extract_network_stat() {
|
||
|
local stats_json=$1
|
||
|
local field_name=$2
|
||
|
|
||
|
echo $(echo "$stats_json" | jq -r "$field_name")
|
||
|
}
|
||
|
|
||
|
run_test()
|
||
|
{
|
||
|
local test_name=$1;
|
||
|
local apptrust_order=$2;
|
||
|
local port_prio=$3;
|
||
|
local dscp_ipv=$4;
|
||
|
local dscp=$5;
|
||
|
local have_vlan=$6;
|
||
|
local pcp_ipv=$7;
|
||
|
local vlan_pcp=$8;
|
||
|
local ip_v6=$9
|
||
|
|
||
|
local rx_ipv
|
||
|
local tx_ipv
|
||
|
|
||
|
RET=0
|
||
|
|
||
|
# Send some packet to populate the switch MAC table
|
||
|
$MZ ${h2} -a ${h2_mac} -b ${h1_mac} -p 64 -t icmp echores -c 1
|
||
|
|
||
|
# Based on the apptrust order, set the expected Internal Priority values
|
||
|
# for the RX and TX paths.
|
||
|
if [ "${apptrust_order}" == "" ]; then
|
||
|
echo "Apptrust order not set."
|
||
|
rx_ipv=${port_prio}
|
||
|
tx_ipv=${port_prio}
|
||
|
elif [ "${apptrust_order}" == "dscp" ]; then
|
||
|
echo "Apptrust order is DSCP."
|
||
|
rx_ipv=${dscp_ipv}
|
||
|
tx_ipv=${dscp_ipv}
|
||
|
elif [ "${apptrust_order}" == "pcp" ]; then
|
||
|
echo "Apptrust order is PCP."
|
||
|
rx_ipv=${pcp_ipv}
|
||
|
tx_ipv=${pcp_ipv}
|
||
|
elif [ "${apptrust_order}" == "pcp dscp" ]; then
|
||
|
echo "Apptrust order is PCP DSCP."
|
||
|
if [ ${have_vlan} -eq 1 ]; then
|
||
|
rx_ipv=$((dscp_ipv > pcp_ipv ? dscp_ipv : pcp_ipv))
|
||
|
tx_ipv=${pcp_ipv}
|
||
|
else
|
||
|
rx_ipv=${dscp_ipv}
|
||
|
tx_ipv=${dscp_ipv}
|
||
|
fi
|
||
|
else
|
||
|
RET=1
|
||
|
echo "Error: Unknown apptrust order ${apptrust_order}"
|
||
|
log_test "${test_name}"
|
||
|
return
|
||
|
fi
|
||
|
|
||
|
# Most/all? of the KSZ switches do not provide per-TC counters. There
|
||
|
# are only tx_hi and rx_hi counters, which are used to count packets
|
||
|
# which are considered as high priority and most likely not assigned
|
||
|
# to the queue 0.
|
||
|
# On the ingress path, packets seem to get high priority status
|
||
|
# independently of the DSCP or PCP global mapping. On the egress path,
|
||
|
# the high priority status is assigned based on the DSCP or PCP global
|
||
|
# map configuration.
|
||
|
# The thresholds for the high priority status are not documented, but
|
||
|
# it seems that the switch considers packets as high priority on the
|
||
|
# ingress path if detected Internal Priority is greater than 0. On the
|
||
|
# egress path, the switch considers packets as high priority if
|
||
|
# detected Internal Priority is greater than 1.
|
||
|
if [ ${rx_ipv} -ge 1 ]; then
|
||
|
local expect_rx_high_prio=1
|
||
|
else
|
||
|
local expect_rx_high_prio=0
|
||
|
fi
|
||
|
|
||
|
if [ ${tx_ipv} -ge 2 ]; then
|
||
|
local expect_tx_high_prio=1
|
||
|
else
|
||
|
local expect_tx_high_prio=0
|
||
|
fi
|
||
|
|
||
|
# Use ip tool to get the current switch packet counters. ethool stats
|
||
|
# need to be recalculated to get the correct values.
|
||
|
local swp1_stats=$(ip -s -j link show dev ${swp1})
|
||
|
local swp2_stats=$(ip -s -j link show dev ${swp2})
|
||
|
local swp1_rx_packets_before=$(extract_network_stat "$swp1_stats" \
|
||
|
'.[0].stats64.rx.packets')
|
||
|
local swp1_rx_bytes_before=$(extract_network_stat "$swp1_stats" \
|
||
|
'.[0].stats64.rx.bytes')
|
||
|
local swp2_tx_packets_before=$(extract_network_stat "$swp2_stats" \
|
||
|
'.[0].stats64.tx.packets')
|
||
|
local swp2_tx_bytes_before=$(extract_network_stat "$swp2_stats" \
|
||
|
'.[0].stats64.tx.bytes')
|
||
|
local swp1_rx_hi_before=$(ethtool_stats_get ${swp1} "rx_hi")
|
||
|
local swp2_tx_hi_before=$(ethtool_stats_get ${swp2} "tx_hi")
|
||
|
|
||
|
# Assamble the mausezahn command based on the test parameters
|
||
|
# For the testis with ipv4 or ipv6, use icmp response packets,
|
||
|
# to avoid interaction with the system, to keep packet counters
|
||
|
# clean.
|
||
|
if [ ${ip_v6} -eq 0 ]; then
|
||
|
local ip="-a ${h1_mac} -b ${h2_mac} -A ${H1_IPV4} \
|
||
|
-B ${H2_IPV4} -t icmp unreach,code=1,dscp=${dscp}"
|
||
|
else
|
||
|
local ip="-6 -a ${h1_mac} -b ${h2_mac} -A ${H1_IPV6} \
|
||
|
-B ${H2_IPV6} -t icmp6 type=1,code=0,dscp=${dscp}"
|
||
|
fi
|
||
|
|
||
|
if [ ${have_vlan} -eq 1 ]; then
|
||
|
local vlan_pcp_opt="-Q ${vlan_pcp}:0"
|
||
|
else
|
||
|
local vlan_pcp_opt=""
|
||
|
fi
|
||
|
$MZ ${h1} ${ip} -c ${PING_COUNT} -d 10msec ${vlan_pcp_opt}
|
||
|
|
||
|
# Wait until the switch packet counters are updated
|
||
|
sleep 6
|
||
|
|
||
|
local swp1_stats=$(ip -s -j link show dev ${swp1})
|
||
|
local swp2_stats=$(ip -s -j link show dev ${swp2})
|
||
|
|
||
|
local swp1_rx_packets_after=$(extract_network_stat "$swp1_stats" \
|
||
|
'.[0].stats64.rx.packets')
|
||
|
local swp1_rx_bytes_after=$(extract_network_stat "$swp1_stats" \
|
||
|
'.[0].stats64.rx.bytes')
|
||
|
local swp2_tx_packets_after=$(extract_network_stat "$swp2_stats" \
|
||
|
'.[0].stats64.tx.packets')
|
||
|
local swp2_tx_bytes_after=$(extract_network_stat "$swp2_stats" \
|
||
|
'.[0].stats64.tx.bytes')
|
||
|
|
||
|
local swp1_rx_packets_diff=$((${swp1_rx_packets_after} - \
|
||
|
${swp1_rx_packets_before}))
|
||
|
local swp2_tx_packets_diff=$((${swp2_tx_packets_after} - \
|
||
|
${swp2_tx_packets_before}))
|
||
|
|
||
|
local swp1_rx_hi_after=$(ethtool_stats_get ${swp1} "rx_hi")
|
||
|
local swp2_tx_hi_after=$(ethtool_stats_get ${swp2} "tx_hi")
|
||
|
|
||
|
# Test if any packets were received on swp1, we will rx before and after
|
||
|
if [ ${swp1_rx_packets_diff} -lt ${PING_COUNT} ]; then
|
||
|
echo "Not expected amount of received packets on ${swp1}"
|
||
|
echo "before ${swp1_rx_packets_before} after ${swp1_rx_packets_after}"
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
# Test if any packets were transmitted on swp2, we will tx before and after
|
||
|
if [ ${swp2_tx_packets_diff} -lt ${PING_COUNT} ]; then
|
||
|
echo "Not expected amount of transmitted packets on ${swp2}"
|
||
|
echo "before ${swp2_tx_packets_before} after ${swp2_tx_packets_after}"
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
# tx/rx_hi counted in bytes. So, we need to compare the difference in bytes
|
||
|
local swp1_rx_bytes_diff=$(($swp1_rx_bytes_after - $swp1_rx_bytes_before))
|
||
|
local swp2_tx_bytes_diff=$(($swp2_tx_bytes_after - $swp2_tx_bytes_before))
|
||
|
local swp1_rx_hi_diff=$(($swp1_rx_hi_after - $swp1_rx_hi_before))
|
||
|
local swp2_tx_hi_diff=$(($swp2_tx_hi_after - $swp2_tx_hi_before))
|
||
|
|
||
|
if [ ${expect_rx_high_prio} -eq 1 ]; then
|
||
|
swp1_rx_hi_diff=$((${swp1_rx_hi_diff} - \
|
||
|
${swp1_rx_packets_diff} * ${ETH_FCS_LEN}))
|
||
|
if [ ${swp1_rx_hi_diff} -ne ${swp1_rx_bytes_diff} ]; then
|
||
|
echo "Not expected amount of high priority packets received on ${swp1}"
|
||
|
echo "RX hi diff: ${swp1_rx_hi_diff}, expected RX bytes diff: ${swp1_rx_bytes_diff}"
|
||
|
RET=1
|
||
|
fi
|
||
|
else
|
||
|
if [ ${swp1_rx_hi_diff} -ne 0 ]; then
|
||
|
echo "Unexpected amount of high priority packets received on ${swp1}"
|
||
|
echo "RX hi diff: ${swp1_rx_hi_diff}, expected 0"
|
||
|
RET=1
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
if [ ${expect_tx_high_prio} -eq 1 ]; then
|
||
|
swp2_tx_hi_diff=$((${swp2_tx_hi_diff} - \
|
||
|
${swp2_tx_packets_diff} * ${ETH_FCS_LEN}))
|
||
|
if [ ${swp2_tx_hi_diff} -ne ${swp2_tx_bytes_diff} ]; then
|
||
|
echo "Not expected amount of high priority packets transmitted on ${swp2}"
|
||
|
echo "TX hi diff: ${swp2_tx_hi_diff}, expected TX bytes diff: ${swp2_tx_bytes_diff}"
|
||
|
RET=1
|
||
|
fi
|
||
|
else
|
||
|
if [ ${swp2_tx_hi_diff} -ne 0 ]; then
|
||
|
echo "Unexpected amount of high priority packets transmitted on ${swp2}"
|
||
|
echo "TX hi diff: ${swp2_tx_hi_diff}, expected 0"
|
||
|
RET=1
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
log_test "${test_name}"
|
||
|
}
|
||
|
|
||
|
run_test_dscp()
|
||
|
{
|
||
|
# IPv4 test
|
||
|
run_test "$1" "$2" "$3" "$4" "$5" 0 0 0 0
|
||
|
# IPv6 test
|
||
|
run_test "$1" "$2" "$3" "$4" "$5" 0 0 0 1
|
||
|
}
|
||
|
|
||
|
run_test_dscp_pcp()
|
||
|
{
|
||
|
# IPv4 test
|
||
|
run_test "$1" "$2" "$3" "$4" "$5" 1 "$6" "$7" 0
|
||
|
# IPv6 test
|
||
|
run_test "$1" "$2" "$3" "$4" "$5" 1 "$6" "$7" 1
|
||
|
}
|
||
|
|
||
|
port_default_prio_get()
|
||
|
{
|
||
|
local if_name=$1
|
||
|
local prio
|
||
|
|
||
|
prio="$(dcb -j app show dev ${if_name} default-prio | \
|
||
|
jq '.default_prio[]')"
|
||
|
if [ -z "${prio}" ]; then
|
||
|
prio=0
|
||
|
fi
|
||
|
|
||
|
echo ${prio}
|
||
|
}
|
||
|
|
||
|
test_port_default()
|
||
|
{
|
||
|
local orig_apptrust=$(port_get_default_apptrust ${swp1})
|
||
|
local orig_prio=$(port_default_prio_get ${swp1})
|
||
|
local apptrust_order=""
|
||
|
|
||
|
RET=0
|
||
|
|
||
|
# Make sure no other priority sources will interfere with the test
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
|
||
|
for val in $(seq 0 7); do
|
||
|
dcb app replace dev ${swp1} default-prio ${val}
|
||
|
if [ $val -ne $(port_default_prio_get ${swp1}) ]; then
|
||
|
RET=1
|
||
|
break
|
||
|
fi
|
||
|
|
||
|
run_test_dscp "Port-default QoS classification, prio: ${val}" \
|
||
|
"${apptrust_order}" ${val} 0 0
|
||
|
done
|
||
|
|
||
|
set_apptrust_order ${swp1} "${orig_apptrust}"
|
||
|
if [[ "$orig_apptrust" != "$(port_get_default_apptrust ${swp1})" ]]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
dcb app replace dev ${swp1} default-prio ${orig_prio}
|
||
|
if [ $orig_prio -ne $(port_default_prio_get ${swp1}) ]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
log_test "Port-default QoS classification"
|
||
|
}
|
||
|
|
||
|
port_get_default_apptrust()
|
||
|
{
|
||
|
local if_name=$1
|
||
|
|
||
|
dcb -j apptrust show dev ${if_name} | jq -r '.order[]' | \
|
||
|
tr '\n' ' ' | xargs
|
||
|
}
|
||
|
|
||
|
test_port_apptrust()
|
||
|
{
|
||
|
local original_dscp_prios_swp1=$(get_dscp_prios ${swp1})
|
||
|
local orig_apptrust=$(port_get_default_apptrust ${swp1})
|
||
|
local orig_port_prio=$(port_default_prio_get ${swp1})
|
||
|
local order_variants=("pcp dscp" "dscp" "pcp")
|
||
|
local apptrust_order
|
||
|
local port_prio
|
||
|
local dscp_prio
|
||
|
local pcp_prio
|
||
|
local dscp
|
||
|
local pcp
|
||
|
|
||
|
RET=0
|
||
|
|
||
|
# First, test if apptrust configuration as taken by the kernel
|
||
|
for order in "${order_variants[@]}"; do
|
||
|
set_apptrust_order ${swp1} "${order}"
|
||
|
if [[ "$order" != "$(port_get_default_apptrust ${swp1})" ]]; then
|
||
|
RET=1
|
||
|
break
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
log_test "Apptrust, supported variants"
|
||
|
|
||
|
# To test if the apptrust configuration is working as expected, we need
|
||
|
# to set DSCP priorities for the switch port.
|
||
|
init_dscp_prios "${swp1}" "${original_dscp_prios_swp1}"
|
||
|
|
||
|
# Start with a simple test where all apptrust sources are disabled
|
||
|
# default port priority is 0, DSCP priority is mapped to 7.
|
||
|
# No high priority packets should be received or transmitted.
|
||
|
port_prio=0
|
||
|
dscp_prio=7
|
||
|
dscp=4
|
||
|
|
||
|
dcb app replace dev ${swp1} default-prio ${port_prio}
|
||
|
dcb app replace dev ${swp1} dscp-prio ${dscp}:${dscp_prio}
|
||
|
|
||
|
apptrust_order=""
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
# Test with apptrust sources disabled, Packets should get port default
|
||
|
# priority which is 0
|
||
|
run_test_dscp "Apptrust, all disabled. DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp}
|
||
|
|
||
|
apptrust_order="pcp"
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
# If PCP is enabled, packets should get PCP priority, which is not
|
||
|
# set in this test (no VLAN tags are present in the packet). No high
|
||
|
# priority packets should be received or transmitted.
|
||
|
run_test_dscp "Apptrust, PCP enabled. DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp}
|
||
|
|
||
|
apptrust_order="dscp"
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
# If DSCP is enabled, packets should get DSCP priority which is set to 7
|
||
|
# in this test. High priority packets should be received and transmitted.
|
||
|
run_test_dscp "Apptrust, DSCP enabled. DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp}
|
||
|
|
||
|
apptrust_order="pcp dscp"
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
# If PCP and DSCP are enabled, PCP would have higher apptrust priority
|
||
|
# so packets should get PCP priority. But in this test VLAN PCP is not
|
||
|
# set, so it should get DSCP priority which is set to 7. High priority
|
||
|
# packets should be received and transmitted.
|
||
|
run_test_dscp "Apptrust, PCP and DSCP are enabled. DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp}
|
||
|
|
||
|
# If VLAN PCP is set, it should have higher apptrust priority than DSCP
|
||
|
# so packets should get VLAN PCP priority. Send packets with VLAN PCP
|
||
|
# set to 0, DSCP set to 7. Packets should get VLAN PCP priority.
|
||
|
# No high priority packets should be transmitted. Due to nature of the
|
||
|
# switch, high priority packets will be received.
|
||
|
pcp_prio=0
|
||
|
pcp=0
|
||
|
run_test_dscp_pcp "Apptrust, PCP and DSCP are enabled. PCP ${pcp_prio}, DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp} ${pcp_prio} ${pcp}
|
||
|
|
||
|
# If VLAN PCP is set to 7, it should have higher apptrust priority than
|
||
|
# DSCP so packets should get VLAN PCP priority. Send packets with VLAN
|
||
|
# PCP set to 7, DSCP set to 7. Packets should get VLAN PCP priority.
|
||
|
# High priority packets should be received and transmitted.
|
||
|
pcp_prio=7
|
||
|
pcp=7
|
||
|
run_test_dscp_pcp "Apptrust, PCP and DSCP are enabled. PCP ${pcp_prio}, DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp} ${pcp_prio} ${pcp}
|
||
|
# Now make sure that the switch is able to handle the case where DSCP
|
||
|
# priority is set to 0 and PCP priority is set to 7. Packets should get
|
||
|
# PCP priority. High priority packets should be received and transmitted.
|
||
|
dscp_prio=0
|
||
|
dcb app replace dev ${swp1} dscp-prio ${dscp}:${dscp_prio}
|
||
|
run_test_dscp_pcp "Apptrust, PCP and DSCP are enabled. PCP ${pcp_prio}, DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp} ${pcp_prio} ${pcp}
|
||
|
# If both VLAN PCP and DSCP are set to 0, packets should get 0 priority.
|
||
|
# No high priority packets should be received or transmitted.
|
||
|
pcp_prio=0
|
||
|
pcp=0
|
||
|
run_test_dscp_pcp "Apptrust, PCP and DSCP are enabled. PCP ${pcp_prio}, DSCP-prio ${dscp}:${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp} ${pcp_prio} ${pcp}
|
||
|
|
||
|
# Restore original priorities
|
||
|
if ! restore_priorities "${swp1}" "${original_dscp_prios_swp1}"; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
set_apptrust_order ${swp1} "${orig_apptrust}"
|
||
|
if [ "$orig_apptrust" != "$(port_get_default_apptrust ${swp1})" ]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
dcb app replace dev ${swp1} default-prio ${orig_port_prio}
|
||
|
if [ $orig_port_prio -ne $(port_default_prio_get ${swp1}) ]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
log_test "Apptrust, restore original settings"
|
||
|
}
|
||
|
|
||
|
# Function to get current DSCP priorities
|
||
|
get_dscp_prios() {
|
||
|
local if_name=$1
|
||
|
dcb -j app show dev ${if_name} | jq -c '.dscp_prio'
|
||
|
}
|
||
|
|
||
|
# Function to set a specific DSCP priority on a device
|
||
|
replace_dscp_prio() {
|
||
|
local if_name=$1
|
||
|
local dscp=$2
|
||
|
local prio=$3
|
||
|
dcb app replace dev ${if_name} dscp-prio ${dscp}:${prio}
|
||
|
}
|
||
|
|
||
|
# Function to compare DSCP maps
|
||
|
compare_dscp_maps() {
|
||
|
local old_json=$1
|
||
|
local new_json=$2
|
||
|
local dscp=$3
|
||
|
local prio=$4
|
||
|
|
||
|
# Create a modified old_json with the expected change for comparison
|
||
|
local modified_old_json=$(echo "$old_json" |
|
||
|
jq --argjson dscp $dscp --argjson prio $prio \
|
||
|
'map(if .[0] == $dscp then [$dscp, $prio] else . end)' |
|
||
|
tr -d " \n")
|
||
|
|
||
|
# Compare new_json with the modified_old_json
|
||
|
if [[ "$modified_old_json" == "$new_json" ]]; then
|
||
|
return 0
|
||
|
else
|
||
|
return 1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# Function to set DSCP priorities
|
||
|
set_and_verify_dscp() {
|
||
|
local port=$1
|
||
|
local dscp=$2
|
||
|
local new_prio=$3
|
||
|
|
||
|
local old_prios=$(get_dscp_prios $port)
|
||
|
|
||
|
replace_dscp_prio "$port" $dscp $new_prio
|
||
|
|
||
|
# Fetch current settings and compare
|
||
|
local current_prios=$(get_dscp_prios $port)
|
||
|
if ! compare_dscp_maps "$old_prios" "$current_prios" $dscp $new_prio; then
|
||
|
echo "Error: Unintended changes detected in DSCP map for $port after setting DSCP $dscp to $new_prio."
|
||
|
return 1
|
||
|
fi
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
# Function to restore original priorities
|
||
|
restore_priorities() {
|
||
|
local port=$1
|
||
|
local original_prios=$2
|
||
|
|
||
|
echo "Removing test artifacts for $port"
|
||
|
local current_prios=$(get_dscp_prios $port)
|
||
|
local prio_str=$(echo "$current_prios" |
|
||
|
jq -r 'map("\(.[0]):\(.[1])") | join(" ")')
|
||
|
dcb app del dev $port dscp-prio $prio_str
|
||
|
|
||
|
echo "Restoring original DSCP priorities for $port"
|
||
|
local restore_str=$(echo "$original_prios" |
|
||
|
jq -r 'map("\(.[0]):\(.[1])") | join(" ")')
|
||
|
dcb app add dev $port dscp-prio $restore_str
|
||
|
|
||
|
local current_prios=$(get_dscp_prios $port)
|
||
|
if [[ "$original_prios" != "$current_prios" ]]; then
|
||
|
echo "Error: Failed to restore original DSCP priorities for $port"
|
||
|
return 1
|
||
|
fi
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
# Initialize DSCP priorities. Set them to predictable values for testing.
|
||
|
init_dscp_prios() {
|
||
|
local port=$1
|
||
|
local original_prios=$2
|
||
|
|
||
|
echo "Removing any existing DSCP priority mappins for $port"
|
||
|
local prio_str=$(echo "$original_prios" |
|
||
|
jq -r 'map("\(.[0]):\(.[1])") | join(" ")')
|
||
|
dcb app del dev $port dscp-prio $prio_str
|
||
|
|
||
|
# Initialize DSCP priorities list
|
||
|
local dscp_prios=""
|
||
|
for dscp in {0..63}; do
|
||
|
dscp_prios+=("$dscp:0")
|
||
|
done
|
||
|
|
||
|
echo "Setting initial DSCP priorities map to 0 for $port"
|
||
|
dcb app add dev $port dscp-prio ${dscp_prios[@]}
|
||
|
}
|
||
|
|
||
|
# Main function to test global DSCP map across specified ports
|
||
|
test_global_dscp_map() {
|
||
|
local ports=("$swp1" "$swp2")
|
||
|
local original_dscp_prios_port0=$(get_dscp_prios ${ports[0]})
|
||
|
local orig_apptrust=$(port_get_default_apptrust ${swp1})
|
||
|
local orig_port_prio=$(port_default_prio_get ${swp1})
|
||
|
local apptrust_order="dscp"
|
||
|
local port_prio=0
|
||
|
local dscp_prio
|
||
|
local dscp
|
||
|
|
||
|
RET=0
|
||
|
|
||
|
set_apptrust_order ${swp1} "${apptrust_order}"
|
||
|
dcb app replace dev ${swp1} default-prio ${port_prio}
|
||
|
|
||
|
# Initialize DSCP priorities
|
||
|
init_dscp_prios "${ports[0]}" "$original_dscp_prios_port0"
|
||
|
|
||
|
# Loop over each DSCP index
|
||
|
for dscp in {0..63}; do
|
||
|
# and test each Internal Priority value
|
||
|
for dscp_prio in {0..7}; do
|
||
|
# do it for each port. This is to test if the global DSCP map
|
||
|
# is accessible from all ports.
|
||
|
for port in "${ports[@]}"; do
|
||
|
if ! set_and_verify_dscp "$port" $dscp $dscp_prio; then
|
||
|
RET=1
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
# Test if the DSCP priority is correctly applied to the packets
|
||
|
run_test_dscp "DSCP (${dscp}) QoS classification, prio: ${dscp_prio}" \
|
||
|
"${apptrust_order}" ${port_prio} ${dscp_prio} ${dscp}
|
||
|
if [ ${RET} -eq 1 ]; then
|
||
|
break
|
||
|
fi
|
||
|
done
|
||
|
done
|
||
|
|
||
|
# Restore original priorities
|
||
|
if ! restore_priorities "${ports[0]}" "${original_dscp_prios_port0}"; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
set_apptrust_order ${swp1} "${orig_apptrust}"
|
||
|
if [[ "$orig_apptrust" != "$(port_get_default_apptrust ${swp1})" ]]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
dcb app replace dev ${swp1} default-prio ${orig_port_prio}
|
||
|
if [ $orig_port_prio -ne $(port_default_prio_get ${swp1}) ]; then
|
||
|
RET=1
|
||
|
fi
|
||
|
|
||
|
log_test "DSCP global map"
|
||
|
}
|
||
|
|
||
|
trap cleanup EXIT
|
||
|
|
||
|
ALL_TESTS="
|
||
|
test_port_default
|
||
|
test_port_apptrust
|
||
|
test_global_dscp_map
|
||
|
"
|
||
|
|
||
|
setup_prepare
|
||
|
setup_wait
|
||
|
tests_run
|
||
|
|
||
|
exit $EXIT_STATUS
|