250 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03# Copyright 2021-2022 NXP4 5REQUIRE_ISOCHRON=${REQUIRE_ISOCHRON:=yes}6REQUIRE_LINUXPTP=${REQUIRE_LINUXPTP:=yes}7 8# Tunables9UTC_TAI_OFFSET=3710ISOCHRON_CPU=111 12if [[ "$REQUIRE_ISOCHRON" = "yes" ]]; then13 # https://github.com/vladimiroltean/tsn-scripts14 # WARNING: isochron versions pre-1.0 are unstable,15 # always use the latest version16 require_command isochron17fi18if [[ "$REQUIRE_LINUXPTP" = "yes" ]]; then19 require_command phc2sys20 require_command ptp4l21fi22 23phc2sys_start()24{25 local uds_address=$126 local extra_args=""27 28 if ! [ -z "${uds_address}" ]; then29 extra_args="${extra_args} -z ${uds_address}"30 fi31 32 phc2sys_log="$(mktemp)"33 34 chrt -f 10 phc2sys -m \35 -a -rr \36 --step_threshold 0.00002 \37 --first_step_threshold 0.00002 \38 ${extra_args} \39 > "${phc2sys_log}" 2>&1 &40 phc2sys_pid=$!41 42 echo "phc2sys logs to ${phc2sys_log} and has pid ${phc2sys_pid}"43 44 sleep 145}46 47phc2sys_stop()48{49 { kill ${phc2sys_pid} && wait ${phc2sys_pid}; } 2> /dev/null50 rm "${phc2sys_log}" 2> /dev/null51}52 53# Replace space separators from interface list with underscores54if_names_to_label()55{56 local if_name_list="$1"57 58 echo "${if_name_list/ /_}"59}60 61ptp4l_start()62{63 local if_names="$1"64 local slave_only=$265 local uds_address=$366 local log="ptp4l_log_$(if_names_to_label ${if_names})"67 local pid="ptp4l_pid_$(if_names_to_label ${if_names})"68 local extra_args=""69 70 for if_name in ${if_names}; do71 extra_args="${extra_args} -i ${if_name}"72 done73 74 if [ "${slave_only}" = true ]; then75 extra_args="${extra_args} -s"76 fi77 78 # declare dynamic variables ptp4l_log_${if_name} and ptp4l_pid_${if_name}79 # as global, so that they can be referenced later80 declare -g "${log}=$(mktemp)"81 82 chrt -f 10 ptp4l -m -2 -P \83 --step_threshold 0.00002 \84 --first_step_threshold 0.00002 \85 --tx_timestamp_timeout 100 \86 --uds_address="${uds_address}" \87 ${extra_args} \88 > "${!log}" 2>&1 &89 declare -g "${pid}=$!"90 91 echo "ptp4l for interfaces ${if_names} logs to ${!log} and has pid ${!pid}"92 93 sleep 194}95 96ptp4l_stop()97{98 local if_names="$1"99 local log="ptp4l_log_$(if_names_to_label ${if_names})"100 local pid="ptp4l_pid_$(if_names_to_label ${if_names})"101 102 { kill ${!pid} && wait ${!pid}; } 2> /dev/null103 rm "${!log}" 2> /dev/null104}105 106cpufreq_max()107{108 local cpu=$1109 local freq="cpu${cpu}_freq"110 local governor="cpu${cpu}_governor"111 112 # Kernel may be compiled with CONFIG_CPU_FREQ disabled113 if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then114 return115 fi116 117 # declare dynamic variables cpu${cpu}_freq and cpu${cpu}_governor as118 # global, so they can be referenced later119 declare -g "${freq}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq)"120 declare -g "${governor}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor)"121 122 cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_max_freq > \123 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq124 echo -n "performance" > \125 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor126}127 128cpufreq_restore()129{130 local cpu=$1131 local freq="cpu${cpu}_freq"132 local governor="cpu${cpu}_governor"133 134 if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then135 return136 fi137 138 echo "${!freq}" > /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq139 echo -n "${!governor}" > \140 /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor141}142 143isochron_recv_start()144{145 local if_name=$1146 local uds=$2147 local stats_port=$3148 local extra_args=$4149 local pid="isochron_pid_${stats_port}"150 151 if ! [ -z "${uds}" ]; then152 extra_args="${extra_args} --unix-domain-socket ${uds}"153 fi154 155 isochron rcv \156 --interface ${if_name} \157 --sched-priority 98 \158 --sched-fifo \159 --utc-tai-offset ${UTC_TAI_OFFSET} \160 --stats-port ${stats_port} \161 --quiet \162 ${extra_args} & \163 declare -g "${pid}=$!"164 165 sleep 1166}167 168isochron_recv_stop()169{170 local stats_port=$1171 local pid="isochron_pid_${stats_port}"172 173 { kill ${!pid} && wait ${!pid}; } 2> /dev/null174}175 176isochron_do()177{178 local sender_if_name=$1; shift179 local receiver_if_name=$1; shift180 local sender_uds=$1; shift181 local receiver_uds=$1; shift182 local base_time=$1; shift183 local cycle_time=$1; shift184 local shift_time=$1; shift185 local num_pkts=$1; shift186 local vid=$1; shift187 local priority=$1; shift188 local dst_ip=$1; shift189 local isochron_dat=$1; shift190 local extra_args=""191 local receiver_extra_args=""192 local vrf="$(master_name_get ${sender_if_name})"193 local use_l2="true"194 195 if ! [ -z "${dst_ip}" ]; then196 use_l2="false"197 fi198 199 if ! [ -z "${vrf}" ]; then200 dst_ip="${dst_ip}%${vrf}"201 fi202 203 if ! [ -z "${vid}" ]; then204 vid="--vid=${vid}"205 fi206 207 if [ -z "${receiver_uds}" ]; then208 extra_args="${extra_args} --omit-remote-sync"209 fi210 211 if ! [ -z "${shift_time}" ]; then212 extra_args="${extra_args} --shift-time=${shift_time}"213 fi214 215 if [ "${use_l2}" = "true" ]; then216 extra_args="${extra_args} --l2 --etype=0xdead ${vid}"217 receiver_extra_args="--l2 --etype=0xdead"218 else219 extra_args="${extra_args} --l4 --ip-destination=${dst_ip}"220 receiver_extra_args="--l4"221 fi222 223 cpufreq_max ${ISOCHRON_CPU}224 225 isochron_recv_start "${h2}" "${receiver_uds}" 5000 "${receiver_extra_args}"226 227 isochron send \228 --interface ${sender_if_name} \229 --unix-domain-socket ${sender_uds} \230 --priority ${priority} \231 --base-time ${base_time} \232 --cycle-time ${cycle_time} \233 --num-frames ${num_pkts} \234 --frame-size 64 \235 --txtime \236 --utc-tai-offset ${UTC_TAI_OFFSET} \237 --cpu-mask $((1 << ${ISOCHRON_CPU})) \238 --sched-fifo \239 --sched-priority 98 \240 --client 127.0.0.1 \241 --sync-threshold 5000 \242 --output-file ${isochron_dat} \243 ${extra_args} \244 --quiet245 246 isochron_recv_stop 5000247 248 cpufreq_restore ${ISOCHRON_CPU}249}250