1*7d4e91e0SVladimir Oltean#!/bin/bash
2*7d4e91e0SVladimir Oltean# SPDX-License-Identifier: GPL-2.0
3*7d4e91e0SVladimir Oltean# Copyright 2022 NXP
4*7d4e91e0SVladimir Oltean
5*7d4e91e0SVladimir Oltean# The script is mostly generic, with the exception of the
6*7d4e91e0SVladimir Oltean# ethtool per-TC counter names ("rx_green_prio_${tc}")
7*7d4e91e0SVladimir Oltean
8*7d4e91e0SVladimir OlteanWAIT_TIME=1
9*7d4e91e0SVladimir OlteanNUM_NETIFS=4
10*7d4e91e0SVladimir OlteanSTABLE_MAC_ADDRS=yes
11*7d4e91e0SVladimir OlteanNETIF_CREATE=no
12*7d4e91e0SVladimir Olteanlib_dir=$(dirname $0)/../../../net/forwarding
13*7d4e91e0SVladimir Olteansource $lib_dir/tc_common.sh
14*7d4e91e0SVladimir Olteansource $lib_dir/lib.sh
15*7d4e91e0SVladimir Oltean
16*7d4e91e0SVladimir Olteanrequire_command dcb
17*7d4e91e0SVladimir Oltean
18*7d4e91e0SVladimir Olteanh1=${NETIFS[p1]}
19*7d4e91e0SVladimir Olteanswp1=${NETIFS[p2]}
20*7d4e91e0SVladimir Olteanswp2=${NETIFS[p3]}
21*7d4e91e0SVladimir Olteanh2=${NETIFS[p4]}
22*7d4e91e0SVladimir Oltean
23*7d4e91e0SVladimir OlteanH1_IPV4="192.0.2.1"
24*7d4e91e0SVladimir OlteanH2_IPV4="192.0.2.2"
25*7d4e91e0SVladimir OlteanH1_IPV6="2001:db8:1::1"
26*7d4e91e0SVladimir OlteanH2_IPV6="2001:db8:1::2"
27*7d4e91e0SVladimir Oltean
28*7d4e91e0SVladimir Olteanh1_create()
29*7d4e91e0SVladimir Oltean{
30*7d4e91e0SVladimir Oltean	simple_if_init $h1 $H1_IPV4/24 $H1_IPV6/64
31*7d4e91e0SVladimir Oltean}
32*7d4e91e0SVladimir Oltean
33*7d4e91e0SVladimir Olteanh1_destroy()
34*7d4e91e0SVladimir Oltean{
35*7d4e91e0SVladimir Oltean	simple_if_fini $h1 $H1_IPV4/24 $H1_IPV6/64
36*7d4e91e0SVladimir Oltean}
37*7d4e91e0SVladimir Oltean
38*7d4e91e0SVladimir Olteanh2_create()
39*7d4e91e0SVladimir Oltean{
40*7d4e91e0SVladimir Oltean	simple_if_init $h2 $H2_IPV4/24 $H2_IPV6/64
41*7d4e91e0SVladimir Oltean}
42*7d4e91e0SVladimir Oltean
43*7d4e91e0SVladimir Olteanh2_destroy()
44*7d4e91e0SVladimir Oltean{
45*7d4e91e0SVladimir Oltean	simple_if_fini $h2 $H2_IPV4/24 $H2_IPV6/64
46*7d4e91e0SVladimir Oltean}
47*7d4e91e0SVladimir Oltean
48*7d4e91e0SVladimir Olteanh1_vlan_create()
49*7d4e91e0SVladimir Oltean{
50*7d4e91e0SVladimir Oltean	local vid=$1
51*7d4e91e0SVladimir Oltean
52*7d4e91e0SVladimir Oltean	vlan_create $h1 $vid
53*7d4e91e0SVladimir Oltean	simple_if_init $h1.$vid $H1_IPV4/24 $H1_IPV6/64
54*7d4e91e0SVladimir Oltean	ip link set $h1.$vid type vlan \
55*7d4e91e0SVladimir Oltean		egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 \
56*7d4e91e0SVladimir Oltean		ingress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
57*7d4e91e0SVladimir Oltean}
58*7d4e91e0SVladimir Oltean
59*7d4e91e0SVladimir Olteanh1_vlan_destroy()
60*7d4e91e0SVladimir Oltean{
61*7d4e91e0SVladimir Oltean	local vid=$1
62*7d4e91e0SVladimir Oltean
63*7d4e91e0SVladimir Oltean	simple_if_fini $h1.$vid $H1_IPV4/24 $H1_IPV6/64
64*7d4e91e0SVladimir Oltean	vlan_destroy $h1 $vid
65*7d4e91e0SVladimir Oltean}
66*7d4e91e0SVladimir Oltean
67*7d4e91e0SVladimir Olteanh2_vlan_create()
68*7d4e91e0SVladimir Oltean{
69*7d4e91e0SVladimir Oltean	local vid=$1
70*7d4e91e0SVladimir Oltean
71*7d4e91e0SVladimir Oltean	vlan_create $h2 $vid
72*7d4e91e0SVladimir Oltean	simple_if_init $h2.$vid $H2_IPV4/24 $H2_IPV6/64
73*7d4e91e0SVladimir Oltean	ip link set $h2.$vid type vlan \
74*7d4e91e0SVladimir Oltean		egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 \
75*7d4e91e0SVladimir Oltean		ingress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
76*7d4e91e0SVladimir Oltean}
77*7d4e91e0SVladimir Oltean
78*7d4e91e0SVladimir Olteanh2_vlan_destroy()
79*7d4e91e0SVladimir Oltean{
80*7d4e91e0SVladimir Oltean	local vid=$1
81*7d4e91e0SVladimir Oltean
82*7d4e91e0SVladimir Oltean	simple_if_fini $h2.$vid $H2_IPV4/24 $H2_IPV6/64
83*7d4e91e0SVladimir Oltean	vlan_destroy $h2 $vid
84*7d4e91e0SVladimir Oltean}
85*7d4e91e0SVladimir Oltean
86*7d4e91e0SVladimir Olteanvlans_prepare()
87*7d4e91e0SVladimir Oltean{
88*7d4e91e0SVladimir Oltean	h1_vlan_create 100
89*7d4e91e0SVladimir Oltean	h2_vlan_create 100
90*7d4e91e0SVladimir Oltean
91*7d4e91e0SVladimir Oltean	tc qdisc add dev ${h1}.100 clsact
92*7d4e91e0SVladimir Oltean	tc filter add dev ${h1}.100 egress protocol ipv4 \
93*7d4e91e0SVladimir Oltean		flower ip_proto icmp action skbedit priority 3
94*7d4e91e0SVladimir Oltean	tc filter add dev ${h1}.100 egress protocol ipv6 \
95*7d4e91e0SVladimir Oltean		flower ip_proto icmpv6 action skbedit priority 3
96*7d4e91e0SVladimir Oltean}
97*7d4e91e0SVladimir Oltean
98*7d4e91e0SVladimir Olteanvlans_destroy()
99*7d4e91e0SVladimir Oltean{
100*7d4e91e0SVladimir Oltean	tc qdisc del dev ${h1}.100 clsact
101*7d4e91e0SVladimir Oltean
102*7d4e91e0SVladimir Oltean	h1_vlan_destroy 100
103*7d4e91e0SVladimir Oltean	h2_vlan_destroy 100
104*7d4e91e0SVladimir Oltean}
105*7d4e91e0SVladimir Oltean
106*7d4e91e0SVladimir Olteanswitch_create()
107*7d4e91e0SVladimir Oltean{
108*7d4e91e0SVladimir Oltean	ip link set ${swp1} up
109*7d4e91e0SVladimir Oltean	ip link set ${swp2} up
110*7d4e91e0SVladimir Oltean
111*7d4e91e0SVladimir Oltean	# Ports should trust VLAN PCP even with vlan_filtering=0
112*7d4e91e0SVladimir Oltean	ip link add br0 type bridge
113*7d4e91e0SVladimir Oltean	ip link set ${swp1} master br0
114*7d4e91e0SVladimir Oltean	ip link set ${swp2} master br0
115*7d4e91e0SVladimir Oltean	ip link set br0 up
116*7d4e91e0SVladimir Oltean}
117*7d4e91e0SVladimir Oltean
118*7d4e91e0SVladimir Olteanswitch_destroy()
119*7d4e91e0SVladimir Oltean{
120*7d4e91e0SVladimir Oltean	ip link del br0
121*7d4e91e0SVladimir Oltean}
122*7d4e91e0SVladimir Oltean
123*7d4e91e0SVladimir Olteansetup_prepare()
124*7d4e91e0SVladimir Oltean{
125*7d4e91e0SVladimir Oltean	vrf_prepare
126*7d4e91e0SVladimir Oltean
127*7d4e91e0SVladimir Oltean	h1_create
128*7d4e91e0SVladimir Oltean	h2_create
129*7d4e91e0SVladimir Oltean	switch_create
130*7d4e91e0SVladimir Oltean}
131*7d4e91e0SVladimir Oltean
132*7d4e91e0SVladimir Olteancleanup()
133*7d4e91e0SVladimir Oltean{
134*7d4e91e0SVladimir Oltean	pre_cleanup
135*7d4e91e0SVladimir Oltean
136*7d4e91e0SVladimir Oltean	h2_destroy
137*7d4e91e0SVladimir Oltean	h1_destroy
138*7d4e91e0SVladimir Oltean	switch_destroy
139*7d4e91e0SVladimir Oltean
140*7d4e91e0SVladimir Oltean	vrf_cleanup
141*7d4e91e0SVladimir Oltean}
142*7d4e91e0SVladimir Oltean
143*7d4e91e0SVladimir Olteandscp_cs_to_tos()
144*7d4e91e0SVladimir Oltean{
145*7d4e91e0SVladimir Oltean	local dscp_cs=$1
146*7d4e91e0SVladimir Oltean
147*7d4e91e0SVladimir Oltean	# https://datatracker.ietf.org/doc/html/rfc2474
148*7d4e91e0SVladimir Oltean	# 4.2.2.1  The Class Selector Codepoints
149*7d4e91e0SVladimir Oltean	echo $((${dscp_cs} << 5))
150*7d4e91e0SVladimir Oltean}
151*7d4e91e0SVladimir Oltean
152*7d4e91e0SVladimir Olteanrun_test()
153*7d4e91e0SVladimir Oltean{
154*7d4e91e0SVladimir Oltean	local test_name=$1; shift
155*7d4e91e0SVladimir Oltean	local if_name=$1; shift
156*7d4e91e0SVladimir Oltean	local tc=$1; shift
157*7d4e91e0SVladimir Oltean	local tos=$1; shift
158*7d4e91e0SVladimir Oltean	local counter_name="rx_green_prio_${tc}"
159*7d4e91e0SVladimir Oltean	local ipv4_before
160*7d4e91e0SVladimir Oltean	local ipv4_after
161*7d4e91e0SVladimir Oltean	local ipv6_before
162*7d4e91e0SVladimir Oltean	local ipv6_after
163*7d4e91e0SVladimir Oltean
164*7d4e91e0SVladimir Oltean	ipv4_before=$(ethtool_stats_get ${swp1} "${counter_name}")
165*7d4e91e0SVladimir Oltean	ping_do ${if_name} $H2_IPV4 "-Q ${tos}"
166*7d4e91e0SVladimir Oltean	ipv4_after=$(ethtool_stats_get ${swp1} "${counter_name}")
167*7d4e91e0SVladimir Oltean
168*7d4e91e0SVladimir Oltean	if [ $((${ipv4_after} - ${ipv4_before})) -lt ${PING_COUNT} ]; then
169*7d4e91e0SVladimir Oltean		RET=1
170*7d4e91e0SVladimir Oltean	else
171*7d4e91e0SVladimir Oltean		RET=0
172*7d4e91e0SVladimir Oltean	fi
173*7d4e91e0SVladimir Oltean	log_test "IPv4 ${test_name}"
174*7d4e91e0SVladimir Oltean
175*7d4e91e0SVladimir Oltean	ipv6_before=$(ethtool_stats_get ${swp1} "${counter_name}")
176*7d4e91e0SVladimir Oltean	ping_do ${if_name} $H2_IPV6 "-Q ${tos}"
177*7d4e91e0SVladimir Oltean	ipv6_after=$(ethtool_stats_get ${swp1} "${counter_name}")
178*7d4e91e0SVladimir Oltean
179*7d4e91e0SVladimir Oltean	if [ $((${ipv6_after} - ${ipv6_before})) -lt ${PING_COUNT} ]; then
180*7d4e91e0SVladimir Oltean		RET=1
181*7d4e91e0SVladimir Oltean	else
182*7d4e91e0SVladimir Oltean		RET=0
183*7d4e91e0SVladimir Oltean	fi
184*7d4e91e0SVladimir Oltean	log_test "IPv6 ${test_name}"
185*7d4e91e0SVladimir Oltean}
186*7d4e91e0SVladimir Oltean
187*7d4e91e0SVladimir Olteanport_default_prio_get()
188*7d4e91e0SVladimir Oltean{
189*7d4e91e0SVladimir Oltean	local if_name=$1
190*7d4e91e0SVladimir Oltean	local prio
191*7d4e91e0SVladimir Oltean
192*7d4e91e0SVladimir Oltean	prio="$(dcb -j app show dev ${if_name} default-prio | \
193*7d4e91e0SVladimir Oltean		jq '.default_prio[]')"
194*7d4e91e0SVladimir Oltean	if [ -z "${prio}" ]; then
195*7d4e91e0SVladimir Oltean		prio=0
196*7d4e91e0SVladimir Oltean	fi
197*7d4e91e0SVladimir Oltean
198*7d4e91e0SVladimir Oltean	echo ${prio}
199*7d4e91e0SVladimir Oltean}
200*7d4e91e0SVladimir Oltean
201*7d4e91e0SVladimir Olteantest_port_default()
202*7d4e91e0SVladimir Oltean{
203*7d4e91e0SVladimir Oltean	local orig=$(port_default_prio_get ${swp1})
204*7d4e91e0SVladimir Oltean	local dmac=$(mac_get ${h2})
205*7d4e91e0SVladimir Oltean
206*7d4e91e0SVladimir Oltean	dcb app replace dev ${swp1} default-prio 5
207*7d4e91e0SVladimir Oltean
208*7d4e91e0SVladimir Oltean	run_test "Port-default QoS classification" ${h1} 5 0
209*7d4e91e0SVladimir Oltean
210*7d4e91e0SVladimir Oltean	dcb app replace dev ${swp1} default-prio ${orig}
211*7d4e91e0SVladimir Oltean}
212*7d4e91e0SVladimir Oltean
213*7d4e91e0SVladimir Olteantest_vlan_pcp()
214*7d4e91e0SVladimir Oltean{
215*7d4e91e0SVladimir Oltean	vlans_prepare
216*7d4e91e0SVladimir Oltean
217*7d4e91e0SVladimir Oltean	run_test "Trusted VLAN PCP QoS classification" ${h1}.100 3 0
218*7d4e91e0SVladimir Oltean
219*7d4e91e0SVladimir Oltean	vlans_destroy
220*7d4e91e0SVladimir Oltean}
221*7d4e91e0SVladimir Oltean
222*7d4e91e0SVladimir Olteantest_ip_dscp()
223*7d4e91e0SVladimir Oltean{
224*7d4e91e0SVladimir Oltean	local port_default=$(port_default_prio_get ${swp1})
225*7d4e91e0SVladimir Oltean	local tos=$(dscp_cs_to_tos 4)
226*7d4e91e0SVladimir Oltean
227*7d4e91e0SVladimir Oltean	dcb app add dev ${swp1} dscp-prio CS4:4
228*7d4e91e0SVladimir Oltean	run_test "Trusted DSCP QoS classification" ${h1} 4 ${tos}
229*7d4e91e0SVladimir Oltean	dcb app del dev ${swp1} dscp-prio CS4:4
230*7d4e91e0SVladimir Oltean
231*7d4e91e0SVladimir Oltean	vlans_prepare
232*7d4e91e0SVladimir Oltean	run_test "Untrusted DSCP QoS classification follows VLAN PCP" \
233*7d4e91e0SVladimir Oltean		${h1}.100 3 ${tos}
234*7d4e91e0SVladimir Oltean	vlans_destroy
235*7d4e91e0SVladimir Oltean
236*7d4e91e0SVladimir Oltean	run_test "Untrusted DSCP QoS classification follows port default" \
237*7d4e91e0SVladimir Oltean		${h1} ${port_default} ${tos}
238*7d4e91e0SVladimir Oltean}
239*7d4e91e0SVladimir Oltean
240*7d4e91e0SVladimir Olteantrap cleanup EXIT
241*7d4e91e0SVladimir Oltean
242*7d4e91e0SVladimir OlteanALL_TESTS="
243*7d4e91e0SVladimir Oltean	test_port_default
244*7d4e91e0SVladimir Oltean	test_vlan_pcp
245*7d4e91e0SVladimir Oltean	test_ip_dscp
246*7d4e91e0SVladimir Oltean"
247*7d4e91e0SVladimir Oltean
248*7d4e91e0SVladimir Olteansetup_prepare
249*7d4e91e0SVladimir Olteansetup_wait
250*7d4e91e0SVladimir Oltean
251*7d4e91e0SVladimir Olteantests_run
252*7d4e91e0SVladimir Oltean
253*7d4e91e0SVladimir Olteanexit $EXIT_STATUS
254