~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/drivers/net/ocelot/psfp.sh

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/bin/bash
  2 # SPDX-License-Identifier: GPL-2.0
  3 # Copyright 2021-2022 NXP
  4 
  5 # Note: On LS1028A, in lack of enough user ports, this setup requires patching
  6 # the device tree to use the second CPU port as a user port
  7 
  8 WAIT_TIME=1
  9 NUM_NETIFS=4
 10 STABLE_MAC_ADDRS=yes
 11 NETIF_CREATE=no
 12 lib_dir=$(dirname $0)/../../../net/forwarding
 13 source $lib_dir/tc_common.sh
 14 source $lib_dir/lib.sh
 15 source $lib_dir/tsn_lib.sh
 16 
 17 UDS_ADDRESS_H1="/var/run/ptp4l_h1"
 18 UDS_ADDRESS_SWP1="/var/run/ptp4l_swp1"
 19 
 20 # Tunables
 21 NUM_PKTS=1000
 22 STREAM_VID=100
 23 STREAM_PRIO=6
 24 # Use a conservative cycle of 10 ms to allow the test to still pass when the
 25 # kernel has some extra overhead like lockdep etc
 26 CYCLE_TIME_NS=10000000
 27 # Create two Gate Control List entries, one OPEN and one CLOSE, of equal
 28 # durations
 29 GATE_DURATION_NS=$((${CYCLE_TIME_NS} / 2))
 30 # Give 2/3 of the cycle time to user space and 1/3 to the kernel
 31 FUDGE_FACTOR=$((${CYCLE_TIME_NS} / 3))
 32 # Shift the isochron base time by half the gate time, so that packets are
 33 # always received by swp1 close to the middle of the time slot, to minimize
 34 # inaccuracies due to network sync
 35 SHIFT_TIME_NS=$((${GATE_DURATION_NS} / 2))
 36 
 37 h1=${NETIFS[p1]}
 38 swp1=${NETIFS[p2]}
 39 swp2=${NETIFS[p3]}
 40 h2=${NETIFS[p4]}
 41 
 42 H1_IPV4="192.0.2.1"
 43 H2_IPV4="192.0.2.2"
 44 H1_IPV6="2001:db8:1::1"
 45 H2_IPV6="2001:db8:1::2"
 46 
 47 # Chain number exported by the ocelot driver for
 48 # Per-Stream Filtering and Policing filters
 49 PSFP()
 50 {
 51         echo 30000
 52 }
 53 
 54 psfp_chain_create()
 55 {
 56         local if_name=$1
 57 
 58         tc qdisc add dev $if_name clsact
 59 
 60         tc filter add dev $if_name ingress chain 0 pref 49152 flower \
 61                 skip_sw action goto chain $(PSFP)
 62 }
 63 
 64 psfp_chain_destroy()
 65 {
 66         local if_name=$1
 67 
 68         tc qdisc del dev $if_name clsact
 69 }
 70 
 71 psfp_filter_check()
 72 {
 73         local expected=$1
 74         local packets=""
 75         local drops=""
 76         local stats=""
 77 
 78         stats=$(tc -j -s filter show dev ${swp1} ingress chain $(PSFP) pref 1)
 79         packets=$(echo ${stats} | jq ".[1].options.actions[].stats.packets")
 80         drops=$(echo ${stats} | jq ".[1].options.actions[].stats.drops")
 81 
 82         if ! [ "${packets}" = "${expected}" ]; then
 83                 printf "Expected filter to match on %d packets but matched on %d instead\n" \
 84                         "${expected}" "${packets}"
 85         fi
 86 
 87         echo "Hardware filter reports ${drops} drops"
 88 }
 89 
 90 h1_create()
 91 {
 92         simple_if_init $h1 $H1_IPV4/24 $H1_IPV6/64
 93 }
 94 
 95 h1_destroy()
 96 {
 97         simple_if_fini $h1 $H1_IPV4/24 $H1_IPV6/64
 98 }
 99 
100 h2_create()
101 {
102         simple_if_init $h2 $H2_IPV4/24 $H2_IPV6/64
103 }
104 
105 h2_destroy()
106 {
107         simple_if_fini $h2 $H2_IPV4/24 $H2_IPV6/64
108 }
109 
110 switch_create()
111 {
112         local h2_mac_addr=$(mac_get $h2)
113 
114         ip link set ${swp1} up
115         ip link set ${swp2} up
116 
117         ip link add br0 type bridge vlan_filtering 1
118         ip link set ${swp1} master br0
119         ip link set ${swp2} master br0
120         ip link set br0 up
121 
122         bridge vlan add dev ${swp2} vid ${STREAM_VID}
123         bridge vlan add dev ${swp1} vid ${STREAM_VID}
124         # PSFP on Ocelot requires the filter to also be added to the bridge
125         # FDB, and not be removed
126         bridge fdb add dev ${swp2} \
127                 ${h2_mac_addr} vlan ${STREAM_VID} static master
128 
129         psfp_chain_create ${swp1}
130 
131         tc filter add dev ${swp1} ingress chain $(PSFP) pref 1 \
132                 protocol 802.1Q flower skip_sw \
133                 dst_mac ${h2_mac_addr} vlan_id ${STREAM_VID} \
134                 action gate base-time 0.000000000 \
135                 sched-entry OPEN  ${GATE_DURATION_NS} -1 -1 \
136                 sched-entry CLOSE ${GATE_DURATION_NS} -1 -1
137 }
138 
139 switch_destroy()
140 {
141         psfp_chain_destroy ${swp1}
142         ip link del br0
143 }
144 
145 txtime_setup()
146 {
147         local if_name=$1
148 
149         tc qdisc add dev ${if_name} clsact
150         # Classify PTP on TC 7 and isochron on TC 6
151         tc filter add dev ${if_name} egress protocol 0x88f7 \
152                 flower action skbedit priority 7
153         tc filter add dev ${if_name} egress protocol 802.1Q \
154                 flower vlan_ethtype 0xdead action skbedit priority 6
155         tc qdisc add dev ${if_name} handle 100: parent root mqprio num_tc 8 \
156                 queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
157                 map 0 1 2 3 4 5 6 7 \
158                 hw 1
159         # Set up TC 6 for SO_TXTIME. tc-mqprio queues count from 1.
160         tc qdisc replace dev ${if_name} parent 100:$((${STREAM_PRIO} + 1)) etf \
161                 clockid CLOCK_TAI offload delta ${FUDGE_FACTOR}
162 }
163 
164 txtime_cleanup()
165 {
166         local if_name=$1
167 
168         tc qdisc del dev ${if_name} root
169         tc qdisc del dev ${if_name} clsact
170 }
171 
172 setup_prepare()
173 {
174         vrf_prepare
175 
176         h1_create
177         h2_create
178         switch_create
179 
180         txtime_setup ${h1}
181 
182         # Set up swp1 as a master PHC for h1, synchronized to the local
183         # CLOCK_REALTIME.
184         phc2sys_start ${UDS_ADDRESS_SWP1}
185 
186         # Assumption true for LS1028A: h1 and h2 use the same PHC. So by
187         # synchronizing h1 to swp1 via PTP, h2 is also implicitly synchronized
188         # to swp1 (and both to CLOCK_REALTIME).
189         ptp4l_start ${h1} true ${UDS_ADDRESS_H1}
190         ptp4l_start ${swp1} false ${UDS_ADDRESS_SWP1}
191 
192         # Make sure there are no filter matches at the beginning of the test
193         psfp_filter_check 0
194 }
195 
196 cleanup()
197 {
198         pre_cleanup
199 
200         ptp4l_stop ${swp1}
201         ptp4l_stop ${h1}
202         phc2sys_stop
203         isochron_recv_stop
204 
205         txtime_cleanup ${h1}
206 
207         h2_destroy
208         h1_destroy
209         switch_destroy
210 
211         vrf_cleanup
212 }
213 
214 debug_incorrectly_dropped_packets()
215 {
216         local isochron_dat=$1
217         local dropped_seqids
218         local seqid
219 
220         echo "Packets incorrectly dropped:"
221 
222         dropped_seqids=$(isochron report \
223                 --input-file "${isochron_dat}" \
224                 --printf-format "%u RX hw %T\n" \
225                 --printf-args "qR" | \
226                 grep 'RX hw 0.000000000' | \
227                 awk '{print $1}')
228 
229         for seqid in ${dropped_seqids}; do
230                 isochron report \
231                         --input-file "${isochron_dat}" \
232                         --start ${seqid} --stop ${seqid} \
233                         --printf-format "seqid %u scheduled for %T, HW TX timestamp %T\n" \
234                         --printf-args "qST"
235         done
236 }
237 
238 debug_incorrectly_received_packets()
239 {
240         local isochron_dat=$1
241 
242         echo "Packets incorrectly received:"
243 
244         isochron report \
245                 --input-file "${isochron_dat}" \
246                 --printf-format "seqid %u scheduled for %T, HW TX timestamp %T, HW RX timestamp %T\n" \
247                 --printf-args "qSTR" |
248                 grep -v 'HW RX timestamp 0.000000000'
249 }
250 
251 run_test()
252 {
253         local base_time=$1
254         local expected=$2
255         local test_name=$3
256         local debug=$4
257         local isochron_dat="$(mktemp)"
258         local extra_args=""
259         local received
260 
261         isochron_do \
262                 "${h1}" \
263                 "${h2}" \
264                 "${UDS_ADDRESS_H1}" \
265                 "" \
266                 "${base_time}" \
267                 "${CYCLE_TIME_NS}" \
268                 "${SHIFT_TIME_NS}" \
269                 "${NUM_PKTS}" \
270                 "${STREAM_VID}" \
271                 "${STREAM_PRIO}" \
272                 "" \
273                 "${isochron_dat}"
274 
275         # Count all received packets by looking at the non-zero RX timestamps
276         received=$(isochron report \
277                 --input-file "${isochron_dat}" \
278                 --printf-format "%u\n" --printf-args "R" | \
279                 grep -w -v '0' | wc -l)
280 
281         if [ "${received}" = "${expected}" ]; then
282                 RET=0
283         else
284                 RET=1
285                 echo "Expected isochron to receive ${expected} packets but received ${received}"
286         fi
287 
288         log_test "${test_name}"
289 
290         if [ "$RET" = "1" ]; then
291                 ${debug} "${isochron_dat}"
292         fi
293 
294         rm ${isochron_dat} 2> /dev/null
295 }
296 
297 test_gate_in_band()
298 {
299         # Send packets in-band with the OPEN gate entry
300         run_test 0.000000000 ${NUM_PKTS} "In band" \
301                 debug_incorrectly_dropped_packets
302 
303         psfp_filter_check ${NUM_PKTS}
304 }
305 
306 test_gate_out_of_band()
307 {
308         # Send packets in-band with the CLOSE gate entry
309         run_test 0.005000000 0 "Out of band" \
310                 debug_incorrectly_received_packets
311 
312         psfp_filter_check $((2 * ${NUM_PKTS}))
313 }
314 
315 trap cleanup EXIT
316 
317 ALL_TESTS="
318         test_gate_in_band
319         test_gate_out_of_band
320 "
321 
322 setup_prepare
323 setup_wait
324 
325 tests_run
326 
327 exit $EXIT_STATUS

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php