1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright 2020 NXP Semiconductors
4
5WAIT_TIME=1
6NUM_NETIFS=4
7lib_dir=$(dirname $0)/../../../net/forwarding
8source $lib_dir/tc_common.sh
9source $lib_dir/lib.sh
10
11require_command tcpdump
12
13#
14#   +---------------------------------------------+
15#   |       DUT ports         Generator ports     |
16#   | +--------+ +--------+ +--------+ +--------+ |
17#   | |        | |        | |        | |        | |
18#   | |  eth0  | |  eth1  | |  eth2  | |  eth3  | |
19#   | |        | |        | |        | |        | |
20#   +-+--------+-+--------+-+--------+-+--------+-+
21#          |         |           |          |
22#          |         |           |          |
23#          |         +-----------+          |
24#          |                                |
25#          +--------------------------------+
26
27eth0=${NETIFS[p1]}
28eth1=${NETIFS[p2]}
29eth2=${NETIFS[p3]}
30eth3=${NETIFS[p4]}
31
32eth0_mac="de:ad:be:ef:00:00"
33eth1_mac="de:ad:be:ef:00:01"
34eth2_mac="de:ad:be:ef:00:02"
35eth3_mac="de:ad:be:ef:00:03"
36
37# Helpers to map a VCAP IS1 and VCAP IS2 lookup and policy to a chain number
38# used by the kernel driver. The numbers are:
39# VCAP IS1 lookup 0:            10000
40# VCAP IS1 lookup 1:            11000
41# VCAP IS1 lookup 2:            12000
42# VCAP IS2 lookup 0 policy 0:   20000
43# VCAP IS2 lookup 0 policy 1:   20001
44# VCAP IS2 lookup 0 policy 255: 20255
45# VCAP IS2 lookup 1 policy 0:   21000
46# VCAP IS2 lookup 1 policy 1:   21001
47# VCAP IS2 lookup 1 policy 255: 21255
48IS1()
49{
50	local lookup=$1
51
52	echo $((10000 + 1000 * lookup))
53}
54
55IS2()
56{
57	local lookup=$1
58	local pag=$2
59
60	echo $((20000 + 1000 * lookup + pag))
61}
62
63ES0()
64{
65	echo 0
66}
67
68# The Ocelot switches have a fixed ingress pipeline composed of:
69#
70# +----------------------------------------------+      +-----------------------------------------+
71# |                   VCAP IS1                   |      |                  VCAP IS2               |
72# |                                              |      |                                         |
73# | +----------+    +----------+    +----------+ |      |            +----------+    +----------+ |
74# | | Lookup 0 |    | Lookup 1 |    | Lookup 2 | | --+------> PAG 0: | Lookup 0 | -> | Lookup 1 | |
75# | +----------+ -> +----------+ -> +----------+ |   |  |            +----------+    +----------+ |
76# | |key&action|    |key&action|    |key&action| |   |  |            |key&action|    |key&action| |
77# | |key&action|    |key&action|    |key&action| |   |  |            |    ..    |    |    ..    | |
78# | |    ..    |    |    ..    |    |    ..    | |   |  |            +----------+    +----------+ |
79# | +----------+    +----------+    +----------+ |   |  |                                         |
80# |                                 selects PAG  |   |  |            +----------+    +----------+ |
81# +----------------------------------------------+   +------> PAG 1: | Lookup 0 | -> | Lookup 1 | |
82#                                                    |  |            +----------+    +----------+ |
83#                                                    |  |            |key&action|    |key&action| |
84#                                                    |  |            |    ..    |    |    ..    | |
85#                                                    |  |            +----------+    +----------+ |
86#                                                    |  |      ...                                |
87#                                                    |  |                                         |
88#                                                    |  |            +----------+    +----------+ |
89#                                                    +----> PAG 254: | Lookup 0 | -> | Lookup 1 | |
90#                                                    |  |            +----------+    +----------+ |
91#                                                    |  |            |key&action|    |key&action| |
92#                                                    |  |            |    ..    |    |    ..    | |
93#                                                    |  |            +----------+    +----------+ |
94#                                                    |  |                                         |
95#                                                    |  |            +----------+    +----------+ |
96#                                                    +----> PAG 255: | Lookup 0 | -> | Lookup 1 | |
97#                                                       |            +----------+    +----------+ |
98#                                                       |            |key&action|    |key&action| |
99#                                                       |            |    ..    |    |    ..    | |
100#                                                       |            +----------+    +----------+ |
101#                                                       +-----------------------------------------+
102#
103# Both the VCAP IS1 (Ingress Stage 1) and IS2 (Ingress Stage 2) are indexed
104# (looked up) multiple times: IS1 3 times, and IS2 2 times. Each filter
105# (key and action pair) can be configured to only match during the first, or
106# second, etc, lookup.
107#
108# During one TCAM lookup, the filter processing stops at the first entry that
109# matches, then the pipeline jumps to the next lookup.
110# The driver maps each individual lookup of each individual ingress TCAM to a
111# separate chain number. For correct rule offloading, it is mandatory that each
112# filter installed in one TCAM is terminated by a non-optional GOTO action to
113# the next lookup from the fixed pipeline.
114#
115# A chain can only be used if there is a GOTO action correctly set up from the
116# prior lookup in the processing pipeline. Setting up all chains is not
117# mandatory.
118
119# NOTE: VCAP IS1 currently uses only S1_NORMAL half keys and VCAP IS2
120# dynamically chooses between MAC_ETYPE, ARP, IP4_TCP_UDP, IP4_OTHER, which are
121# all half keys as well.
122
123create_tcam_skeleton()
124{
125	local eth=$1
126
127	tc qdisc add dev $eth clsact
128
129	# VCAP IS1 is the Ingress Classification TCAM and can offload the
130	# following actions:
131	# - skbedit priority
132	# - vlan pop
133	# - vlan modify
134	# - goto (only in lookup 2, the last IS1 lookup)
135	tc filter add dev $eth ingress chain 0 pref 49152 flower \
136		skip_sw action goto chain $(IS1 0)
137	tc filter add dev $eth ingress chain $(IS1 0) pref 49152 \
138		flower skip_sw action goto chain $(IS1 1)
139	tc filter add dev $eth ingress chain $(IS1 1) pref 49152 \
140		flower skip_sw action goto chain $(IS1 2)
141	tc filter add dev $eth ingress chain $(IS1 2) pref 49152 \
142		flower skip_sw action goto chain $(IS2 0 0)
143
144	# VCAP IS2 is the Security Enforcement ingress TCAM and can offload the
145	# following actions:
146	# - trap
147	# - drop
148	# - police
149	# The two VCAP IS2 lookups can be segmented into up to 256 groups of
150	# rules, called Policies. A Policy is selected through the Policy
151	# Association Group (PAG) action of VCAP IS1 (which is the
152	# GOTO offload).
153	tc filter add dev $eth ingress chain $(IS2 0 0) pref 49152 \
154		flower skip_sw action goto chain $(IS2 1 0)
155}
156
157setup_prepare()
158{
159	create_tcam_skeleton $eth0
160
161	ip link add br0 type bridge
162	ip link set $eth0 master br0
163	ip link set $eth1 master br0
164	ip link set br0 up
165
166	ip link add link $eth3 name $eth3.100 type vlan id 100
167	ip link set $eth3.100 up
168
169	ip link add link $eth3 name $eth3.200 type vlan id 200
170	ip link set $eth3.200 up
171
172	tc filter add dev $eth0 ingress chain $(IS1 1) pref 1 \
173		protocol 802.1Q flower skip_sw vlan_id 100 \
174		action vlan pop \
175		action goto chain $(IS1 2)
176
177	tc filter add dev $eth0 egress chain $(ES0) pref 1 \
178		flower skip_sw indev $eth1 \
179		action vlan push protocol 802.1Q id 100
180
181	tc filter add dev $eth0 ingress chain $(IS1 0) pref 2 \
182		protocol ipv4 flower skip_sw src_ip 10.1.1.2 \
183		action skbedit priority 7 \
184		action goto chain $(IS1 1)
185
186	tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \
187		protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \
188		action police rate 50mbit burst 64k \
189		action goto chain $(IS2 1 0)
190}
191
192cleanup()
193{
194	ip link del $eth3.200
195	ip link del $eth3.100
196	tc qdisc del dev $eth0 clsact
197	ip link del br0
198}
199
200test_vlan_pop()
201{
202	printf "Testing VLAN pop..			"
203
204	tcpdump_start $eth2
205
206	# Work around Mausezahn VLAN builder bug
207	# (https://github.com/netsniff-ng/netsniff-ng/issues/225) by using
208	# an 8021q upper
209	$MZ $eth3.100 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip
210
211	sleep 1
212
213	tcpdump_stop
214
215	if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, ethertype IPv4"; then
216		echo "OK"
217	else
218		echo "FAIL"
219	fi
220
221	tcpdump_cleanup
222}
223
224test_vlan_push()
225{
226	printf "Testing VLAN push..			"
227
228	tcpdump_start $eth3.100
229
230	$MZ $eth2 -q -c 1 -p 64 -a $eth2_mac -b $eth3_mac -t ip
231
232	sleep 1
233
234	tcpdump_stop
235
236	if tcpdump_show | grep -q "$eth2_mac > $eth3_mac"; then
237		echo "OK"
238	else
239		echo "FAIL"
240	fi
241
242	tcpdump_cleanup
243}
244
245test_vlan_modify()
246{
247	printf "Testing VLAN modification..		"
248
249	ip link set br0 type bridge vlan_filtering 1
250	bridge vlan add dev $eth0 vid 200
251	bridge vlan add dev $eth0 vid 300
252	bridge vlan add dev $eth1 vid 300
253
254	tc filter add dev $eth0 ingress chain $(IS1 2) pref 3 \
255		protocol 802.1Q flower skip_sw vlan_id 200 \
256		action vlan modify id 300 \
257		action goto chain $(IS2 0 0)
258
259	tcpdump_start $eth2
260
261	$MZ $eth3.200 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip
262
263	sleep 1
264
265	tcpdump_stop
266
267	if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, .* vlan 300"; then
268		echo "OK"
269	else
270		echo "FAIL"
271	fi
272
273	tcpdump_cleanup
274
275	tc filter del dev $eth0 ingress chain $(IS1 2) pref 3
276
277	bridge vlan del dev $eth0 vid 200
278	bridge vlan del dev $eth0 vid 300
279	bridge vlan del dev $eth1 vid 300
280	ip link set br0 type bridge vlan_filtering 0
281}
282
283test_skbedit_priority()
284{
285	local num_pkts=100
286
287	printf "Testing frame prioritization..		"
288
289	before=$(ethtool_stats_get $eth0 'rx_green_prio_7')
290
291	$MZ $eth3 -q -c $num_pkts -p 64 -a $eth3_mac -b $eth2_mac -t ip -A 10.1.1.2
292
293	after=$(ethtool_stats_get $eth0 'rx_green_prio_7')
294
295	if [ $((after - before)) = $num_pkts ]; then
296		echo "OK"
297	else
298		echo "FAIL"
299	fi
300}
301
302trap cleanup EXIT
303
304ALL_TESTS="
305	test_vlan_pop
306	test_vlan_push
307	test_vlan_modify
308	test_skbedit_priority
309"
310
311setup_prepare
312setup_wait
313
314tests_run
315
316exit $EXIT_STATUS
317