1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="
5	manual_with_verification_h1_to_h2
6	manual_with_verification_h2_to_h1
7	manual_without_verification_h1_to_h2
8	manual_without_verification_h2_to_h1
9	manual_failed_verification_h1_to_h2
10	manual_failed_verification_h2_to_h1
11	lldp
12"
13
14NUM_NETIFS=2
15REQUIRE_MZ=no
16PREEMPTIBLE_PRIO=0
17lib_dir=$(dirname "$0")
18source "$lib_dir"/../../../net/forwarding/lib.sh
19
20traffic_test()
21{
22	local if=$1; shift
23	local src=$1; shift
24	local num_pkts=10000
25	local before=
26	local after=
27	local delta=
28
29	if [ ${has_pmac_stats[$if]} = false ]; then
30		src="aggregate"
31	fi
32
33	before=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src)
34
35	$MZ $if -q -c $num_pkts -p 64 -b bcast -t ip -R $PREEMPTIBLE_PRIO
36
37	after=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src)
38
39	delta=$((after - before))
40
41	# Allow an extra 1% tolerance for random packets sent by the stack
42	[ $delta -ge $num_pkts ] && [ $delta -le $((num_pkts + 100)) ]
43}
44
45manual_with_verification()
46{
47	local tx=$1; shift
48	local rx=$1; shift
49
50	RET=0
51
52	# It isn't completely clear from IEEE 802.3-2018 Figure 99-5: Transmit
53	# Processing state diagram whether the "send_r" variable (send response
54	# to verification frame) should be taken into consideration while the
55	# MAC Merge TX direction is disabled. That being said, at least the
56	# NXP ENETC does not, and requires tx-enabled on in order to respond to
57	# the link partner's verification frames.
58	ethtool --set-mm $rx tx-enabled on
59	ethtool --set-mm $tx verify-enabled on tx-enabled on
60
61	# Wait for verification to finish
62	sleep 1
63
64	ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \
65		grep -q 'SUCCEEDED'
66	check_err "$?" "Verification did not succeed"
67
68	ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true'
69	check_err "$?" "pMAC TX is not active"
70
71	traffic_test $tx "pmac"
72	check_err "$?" "Traffic did not get sent through $tx's pMAC"
73
74	ethtool --set-mm $tx verify-enabled off tx-enabled off
75	ethtool --set-mm $rx tx-enabled off
76
77	log_test "Manual configuration with verification: $tx to $rx"
78}
79
80manual_with_verification_h1_to_h2()
81{
82	manual_with_verification $h1 $h2
83}
84
85manual_with_verification_h2_to_h1()
86{
87	manual_with_verification $h2 $h1
88}
89
90manual_without_verification()
91{
92	local tx=$1; shift
93	local rx=$1; shift
94
95	RET=0
96
97	ethtool --set-mm $tx verify-enabled off tx-enabled on
98
99	ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \
100		grep -q 'DISABLED'
101	check_err "$?" "Verification is not disabled"
102
103	ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true'
104	check_err "$?" "pMAC TX is not active"
105
106	traffic_test $tx "pmac"
107	check_err "$?" "Traffic did not get sent through $tx's pMAC"
108
109	ethtool --set-mm $tx verify-enabled off tx-enabled off
110
111	log_test "Manual configuration without verification: $tx to $rx"
112}
113
114manual_without_verification_h1_to_h2()
115{
116	manual_without_verification $h1 $h2
117}
118
119manual_without_verification_h2_to_h1()
120{
121	manual_without_verification $h2 $h1
122}
123
124manual_failed_verification()
125{
126	local tx=$1; shift
127	local rx=$1; shift
128
129	RET=0
130
131	ethtool --set-mm $rx pmac-enabled off
132	ethtool --set-mm $tx verify-enabled on tx-enabled on
133
134	# Wait for verification to time out
135	sleep 1
136
137	ethtool --json --show-mm $tx | jq -r '.[]."verify-status"' | \
138		grep -q 'SUCCEEDED'
139	check_fail "$?" "Verification succeeded when it shouldn't have"
140
141	ethtool --json --show-mm $tx | jq -r '.[]."tx-active"' | grep -q 'true'
142	check_fail "$?" "pMAC TX is active when it shouldn't have"
143
144	traffic_test $tx "emac"
145	check_err "$?" "Traffic did not get sent through $tx's eMAC"
146
147	ethtool --set-mm $tx verify-enabled off tx-enabled off
148	ethtool --set-mm $rx pmac-enabled on
149
150	log_test "Manual configuration with failed verification: $tx to $rx"
151}
152
153manual_failed_verification_h1_to_h2()
154{
155	manual_failed_verification $h1 $h2
156}
157
158manual_failed_verification_h2_to_h1()
159{
160	manual_failed_verification $h2 $h1
161}
162
163smallest_supported_add_frag_size()
164{
165	local iface=$1
166	local rx_min_frag_size=
167
168	rx_min_frag_size=$(ethtool --json --show-mm $iface | \
169		jq '.[]."rx-min-frag-size"')
170
171	if [ $rx_min_frag_size -le 60 ]; then
172		echo 0
173	elif [ $rx_min_frag_size -le 124 ]; then
174		echo 1
175	elif [ $rx_min_frag_size -le 188 ]; then
176		echo 2
177	elif [ $rx_min_frag_size -le 252 ]; then
178		echo 3
179	else
180		echo "$iface: RX min frag size $rx_min_frag_size cannot be advertised over LLDP"
181		exit 1
182	fi
183}
184
185expected_add_frag_size()
186{
187	local iface=$1
188	local requested=$2
189	local min=$(smallest_supported_add_frag_size $iface)
190
191	[ $requested -le $min ] && echo $min || echo $requested
192}
193
194lldp_change_add_frag_size()
195{
196	local add_frag_size=$1
197	local pattern=
198
199	lldptool -T -i $h1 -V addEthCaps addFragSize=$add_frag_size >/dev/null
200	# Wait for TLVs to be received
201	sleep 2
202	pattern=$(printf "Additional fragment size: %d" \
203			 $(expected_add_frag_size $h1 $add_frag_size))
204	lldptool -i $h2 -t -n -V addEthCaps | grep -q "$pattern"
205}
206
207lldp()
208{
209	RET=0
210
211	systemctl start lldpad
212
213	# Configure the interfaces to receive and transmit LLDPDUs
214	lldptool -L -i $h1 adminStatus=rxtx >/dev/null
215	lldptool -L -i $h2 adminStatus=rxtx >/dev/null
216
217	# Enable the transmission of Additional Ethernet Capabilities TLV
218	lldptool -T -i $h1 -V addEthCaps enableTx=yes >/dev/null
219	lldptool -T -i $h2 -V addEthCaps enableTx=yes >/dev/null
220
221	# Wait for TLVs to be received
222	sleep 2
223
224	lldptool -i $h1 -t -n -V addEthCaps | \
225		grep -q "Preemption capability active"
226	check_err "$?" "$h1 pMAC TX is not active"
227
228	lldptool -i $h2 -t -n -V addEthCaps | \
229		grep -q "Preemption capability active"
230	check_err "$?" "$h2 pMAC TX is not active"
231
232	lldp_change_add_frag_size 3
233	check_err "$?" "addFragSize 3"
234
235	lldp_change_add_frag_size 2
236	check_err "$?" "addFragSize 2"
237
238	lldp_change_add_frag_size 1
239	check_err "$?" "addFragSize 1"
240
241	lldp_change_add_frag_size 0
242	check_err "$?" "addFragSize 0"
243
244	traffic_test $h1 "pmac"
245	check_err "$?" "Traffic did not get sent through $h1's pMAC"
246
247	traffic_test $h2 "pmac"
248	check_err "$?" "Traffic did not get sent through $h2's pMAC"
249
250	systemctl stop lldpad
251
252	log_test "LLDP"
253}
254
255h1_create()
256{
257	ip link set dev $h1 up
258
259	tc qdisc add dev $h1 root mqprio num_tc 4 map 0 1 2 3 \
260		queues 1@0 1@1 1@2 1@3 \
261		fp P E E E \
262		hw 1
263
264	ethtool --set-mm $h1 pmac-enabled on tx-enabled off verify-enabled off
265}
266
267h2_create()
268{
269	ip link set dev $h2 up
270
271	ethtool --set-mm $h2 pmac-enabled on tx-enabled off verify-enabled off
272
273	tc qdisc add dev $h2 root mqprio num_tc 4 map 0 1 2 3 \
274		queues 1@0 1@1 1@2 1@3 \
275		fp P E E E \
276		hw 1
277}
278
279h1_destroy()
280{
281	ethtool --set-mm $h1 pmac-enabled off tx-enabled off verify-enabled off
282
283	tc qdisc del dev $h1 root
284
285	ip link set dev $h1 down
286}
287
288h2_destroy()
289{
290	tc qdisc del dev $h2 root
291
292	ethtool --set-mm $h2 pmac-enabled off tx-enabled off verify-enabled off
293
294	ip link set dev $h2 down
295}
296
297setup_prepare()
298{
299	h1=${NETIFS[p1]}
300	h2=${NETIFS[p2]}
301
302	h1_create
303	h2_create
304}
305
306cleanup()
307{
308	pre_cleanup
309
310	h2_destroy
311	h1_destroy
312}
313
314check_ethtool_mm_support
315check_tc_fp_support
316require_command lldptool
317bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually"
318
319for netif in ${NETIFS[@]}; do
320	ethtool --show-mm $netif 2>&1 &> /dev/null
321	if [[ $? -ne 0 ]]; then
322		echo "SKIP: $netif does not support MAC Merge"
323		exit $ksft_skip
324	fi
325
326	if check_ethtool_pmac_std_stats_support $netif eth-mac; then
327		has_pmac_stats[$netif]=true
328	else
329		has_pmac_stats[$netif]=false
330		echo "$netif does not report pMAC statistics, falling back to aggregate"
331	fi
332done
333
334trap cleanup EXIT
335
336setup_prepare
337setup_wait
338
339tests_run
340
341exit $EXIT_STATUS
342