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