projects/linux·blob master · refs

275 lines · 6.1 KiB

1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright 2021-2022 NXP
4
5tc_testing_scripts_dir=$(dirname $0)/../../tc-testing/scripts
6
7REQUIRE_ISOCHRON=${REQUIRE_ISOCHRON:=yes}
8REQUIRE_LINUXPTP=${REQUIRE_LINUXPTP:=yes}
9
10# Tunables
11UTC_TAI_OFFSET=37
12ISOCHRON_CPU=1
13
14if [[ "$REQUIRE_ISOCHRON" = "yes" ]]; then
15 # https://github.com/vladimiroltean/tsn-scripts
16 # WARNING: isochron versions pre-1.0 are unstable,
17 # always use the latest version
18 require_command isochron
19fi
20if [[ "$REQUIRE_LINUXPTP" = "yes" ]]; then
21 require_command phc2sys
22 require_command ptp4l
23 require_command phc_ctl
24fi
25
26phc2sys_start()
27{
28 local uds_address=$1
29 local extra_args=""
30
31 if ! [ -z "${uds_address}" ]; then
32 extra_args="${extra_args} -z ${uds_address}"
33 fi
34
35 phc2sys_log="$(mktemp)"
36
37 chrt -f 10 phc2sys -m \
38 -a -rr \
39 --step_threshold 0.00002 \
40 --first_step_threshold 0.00002 \
41 ${extra_args} \
42 > "${phc2sys_log}" 2>&1 &
43 phc2sys_pid=$!
44
45 echo "phc2sys logs to ${phc2sys_log} and has pid ${phc2sys_pid}"
46
47 sleep 1
48}
49
50phc2sys_stop()
51{
52 { kill ${phc2sys_pid} && wait ${phc2sys_pid}; } 2> /dev/null
53 rm "${phc2sys_log}" 2> /dev/null
54}
55
56# Replace space separators from interface list with underscores
57if_names_to_label()
58{
59 local if_name_list="$1"
60
61 echo "${if_name_list/ /_}"
62}
63
64ptp4l_start()
65{
66 local if_names="$1"
67 local slave_only=$2
68 local uds_address=$3
69 local log="ptp4l_log_$(if_names_to_label ${if_names})"
70 local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
71 local extra_args=""
72
73 for if_name in ${if_names}; do
74 extra_args="${extra_args} -i ${if_name}"
75 done
76
77 if [ "${slave_only}" = true ]; then
78 extra_args="${extra_args} -s"
79 fi
80
81 # declare dynamic variables ptp4l_log_${if_name} and ptp4l_pid_${if_name}
82 # as global, so that they can be referenced later
83 declare -g "${log}=$(mktemp)"
84
85 chrt -f 10 ptp4l -m -2 -P \
86 --step_threshold 0.00002 \
87 --first_step_threshold 0.00002 \
88 --tx_timestamp_timeout 100 \
89 --uds_address="${uds_address}" \
90 ${extra_args} \
91 > "${!log}" 2>&1 &
92 declare -g "${pid}=$!"
93
94 echo "ptp4l for interfaces ${if_names} logs to ${!log} and has pid ${!pid}"
95
96 sleep 1
97}
98
99ptp4l_stop()
100{
101 local if_names="$1"
102 local log="ptp4l_log_$(if_names_to_label ${if_names})"
103 local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
104
105 { kill ${!pid} && wait ${!pid}; } 2> /dev/null
106 rm "${!log}" 2> /dev/null
107}
108
109cpufreq_max()
110{
111 local cpu=$1
112 local freq="cpu${cpu}_freq"
113 local governor="cpu${cpu}_governor"
114
115 # Kernel may be compiled with CONFIG_CPU_FREQ disabled
116 if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
117 return
118 fi
119
120 # declare dynamic variables cpu${cpu}_freq and cpu${cpu}_governor as
121 # global, so they can be referenced later
122 declare -g "${freq}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq)"
123 declare -g "${governor}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor)"
124
125 cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_max_freq > \
126 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
127 echo -n "performance" > \
128 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
129}
130
131cpufreq_restore()
132{
133 local cpu=$1
134 local freq="cpu${cpu}_freq"
135 local governor="cpu${cpu}_governor"
136
137 if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
138 return
139 fi
140
141 echo "${!freq}" > /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
142 echo -n "${!governor}" > \
143 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
144}
145
146isochron_recv_start()
147{
148 local if_name=$1
149 local uds=$2
150 local stats_port=$3
151 local extra_args=$4
152 local pid="isochron_pid_${stats_port}"
153
154 if ! [ -z "${uds}" ]; then
155 extra_args="${extra_args} --unix-domain-socket ${uds}"
156 fi
157
158 isochron rcv \
159 --interface ${if_name} \
160 --sched-priority 98 \
161 --sched-fifo \
162 --utc-tai-offset ${UTC_TAI_OFFSET} \
163 --stats-port ${stats_port} \
164 --quiet \
165 ${extra_args} & \
166 declare -g "${pid}=$!"
167
168 sleep 1
169}
170
171isochron_recv_stop()
172{
173 local stats_port=$1
174 local pid="isochron_pid_${stats_port}"
175
176 { kill ${!pid} && wait ${!pid}; } 2> /dev/null
177}
178
179isochron_do()
180{
181 local sender_if_name=$1; shift
182 local receiver_if_name=$1; shift
183 local sender_uds=$1; shift
184 local receiver_uds=$1; shift
185 local base_time=$1; shift
186 local cycle_time=$1; shift
187 local shift_time=$1; shift
188 local window_size=$1; shift
189 local num_pkts=$1; shift
190 local vid=$1; shift
191 local priority=$1; shift
192 local dst_ip=$1; shift
193 local isochron_dat=$1; shift
194 local extra_args=""
195 local receiver_extra_args=""
196 local vrf="$(master_name_get ${sender_if_name})"
197 local use_l2="true"
198
199 if ! [ -z "${dst_ip}" ]; then
200 use_l2="false"
201 fi
202
203 if ! [ -z "${vrf}" ]; then
204 dst_ip="${dst_ip}%${vrf}"
205 fi
206
207 if ! [ -z "${vid}" ]; then
208 vid="--vid=${vid}"
209 fi
210
211 if [ -z "${receiver_uds}" ]; then
212 extra_args="${extra_args} --omit-remote-sync"
213 fi
214
215 if ! [ -z "${shift_time}" ]; then
216 extra_args="${extra_args} --shift-time=${shift_time}"
217 fi
218
219 if ! [ -z "${window_size}" ]; then
220 extra_args="${extra_args} --window-size=${window_size}"
221 fi
222
223 if [ "${use_l2}" = "true" ]; then
224 extra_args="${extra_args} --l2 --etype=0xdead ${vid}"
225 receiver_extra_args="--l2 --etype=0xdead"
226 else
227 extra_args="${extra_args} --l4 --ip-destination=${dst_ip}"
228 receiver_extra_args="--l4"
229 fi
230
231 cpufreq_max ${ISOCHRON_CPU}
232
233 isochron_recv_start "${h2}" "${receiver_uds}" 5000 "${receiver_extra_args}"
234
235 isochron send \
236 --interface ${sender_if_name} \
237 --unix-domain-socket ${sender_uds} \
238 --priority ${priority} \
239 --base-time ${base_time} \
240 --cycle-time ${cycle_time} \
241 --num-frames ${num_pkts} \
242 --frame-size 64 \
243 --txtime \
244 --utc-tai-offset ${UTC_TAI_OFFSET} \
245 --cpu-mask $((1 << ${ISOCHRON_CPU})) \
246 --sched-fifo \
247 --sched-priority 98 \
248 --client 127.0.0.1 \
249 --sync-threshold 5000 \
250 --output-file ${isochron_dat} \
251 ${extra_args} \
252 --quiet
253
254 isochron_recv_stop 5000
255
256 cpufreq_restore ${ISOCHRON_CPU}
257}
258
259isochron_report_num_received()
260{
261 local isochron_dat=$1; shift
262
263 # Count all received packets by looking at the non-zero RX timestamps
264 isochron report \
265 --input-file "${isochron_dat}" \
266 --printf-format "%u\n" --printf-args "R" | \
267 grep -w -v '0' | wc -l
268}
269
270taprio_wait_for_admin()
271{
272 local if_name="$1"; shift
273
274 "$tc_testing_scripts_dir/taprio_wait_for_admin.sh" "$(which tc)" "$if_name"
275}