1954f46d2SVladimir Oltean#!/bin/bash 2954f46d2SVladimir Oltean# SPDX-License-Identifier: GPL-2.0 3954f46d2SVladimir Oltean# Copyright 2021-2022 NXP 4954f46d2SVladimir Oltean 5954f46d2SVladimir OlteanREQUIRE_ISOCHRON=${REQUIRE_ISOCHRON:=yes} 6954f46d2SVladimir OlteanREQUIRE_LINUXPTP=${REQUIRE_LINUXPTP:=yes} 7954f46d2SVladimir Oltean 8954f46d2SVladimir Oltean# Tunables 9954f46d2SVladimir OlteanUTC_TAI_OFFSET=37 10954f46d2SVladimir OlteanISOCHRON_CPU=1 11954f46d2SVladimir Oltean 12954f46d2SVladimir Olteanif [[ "$REQUIRE_ISOCHRON" = "yes" ]]; then 13954f46d2SVladimir Oltean # https://github.com/vladimiroltean/tsn-scripts 14954f46d2SVladimir Oltean # WARNING: isochron versions pre-1.0 are unstable, 15954f46d2SVladimir Oltean # always use the latest version 16954f46d2SVladimir Oltean require_command isochron 17954f46d2SVladimir Olteanfi 18954f46d2SVladimir Olteanif [[ "$REQUIRE_LINUXPTP" = "yes" ]]; then 19954f46d2SVladimir Oltean require_command phc2sys 20954f46d2SVladimir Oltean require_command ptp4l 21954f46d2SVladimir Olteanfi 22954f46d2SVladimir Oltean 23954f46d2SVladimir Olteanphc2sys_start() 24954f46d2SVladimir Oltean{ 25*162d52dfSVladimir Oltean local uds_address=$1 26954f46d2SVladimir Oltean local extra_args="" 27954f46d2SVladimir Oltean 28954f46d2SVladimir Oltean if ! [ -z "${uds_address}" ]; then 29954f46d2SVladimir Oltean extra_args="${extra_args} -z ${uds_address}" 30954f46d2SVladimir Oltean fi 31954f46d2SVladimir Oltean 32954f46d2SVladimir Oltean phc2sys_log="$(mktemp)" 33954f46d2SVladimir Oltean 34954f46d2SVladimir Oltean chrt -f 10 phc2sys -m \ 35*162d52dfSVladimir Oltean -a -rr \ 36954f46d2SVladimir Oltean --step_threshold 0.00002 \ 37954f46d2SVladimir Oltean --first_step_threshold 0.00002 \ 38954f46d2SVladimir Oltean ${extra_args} \ 39954f46d2SVladimir Oltean > "${phc2sys_log}" 2>&1 & 40954f46d2SVladimir Oltean phc2sys_pid=$! 41954f46d2SVladimir Oltean 42954f46d2SVladimir Oltean echo "phc2sys logs to ${phc2sys_log} and has pid ${phc2sys_pid}" 43954f46d2SVladimir Oltean 44954f46d2SVladimir Oltean sleep 1 45954f46d2SVladimir Oltean} 46954f46d2SVladimir Oltean 47954f46d2SVladimir Olteanphc2sys_stop() 48954f46d2SVladimir Oltean{ 49954f46d2SVladimir Oltean { kill ${phc2sys_pid} && wait ${phc2sys_pid}; } 2> /dev/null 50954f46d2SVladimir Oltean rm "${phc2sys_log}" 2> /dev/null 51954f46d2SVladimir Oltean} 52954f46d2SVladimir Oltean 537ff9396eSVladimir Oltean# Replace space separators from interface list with underscores 547ff9396eSVladimir Olteanif_names_to_label() 557ff9396eSVladimir Oltean{ 567ff9396eSVladimir Oltean local if_name_list="$1" 577ff9396eSVladimir Oltean 587ff9396eSVladimir Oltean echo "${if_name_list/ /_}" 597ff9396eSVladimir Oltean} 607ff9396eSVladimir Oltean 61954f46d2SVladimir Olteanptp4l_start() 62954f46d2SVladimir Oltean{ 637ff9396eSVladimir Oltean local if_names="$1" 64954f46d2SVladimir Oltean local slave_only=$2 65954f46d2SVladimir Oltean local uds_address=$3 667ff9396eSVladimir Oltean local log="ptp4l_log_$(if_names_to_label ${if_names})" 677ff9396eSVladimir Oltean local pid="ptp4l_pid_$(if_names_to_label ${if_names})" 68954f46d2SVladimir Oltean local extra_args="" 69954f46d2SVladimir Oltean 707ff9396eSVladimir Oltean for if_name in ${if_names}; do 717ff9396eSVladimir Oltean extra_args="${extra_args} -i ${if_name}" 727ff9396eSVladimir Oltean done 737ff9396eSVladimir Oltean 74954f46d2SVladimir Oltean if [ "${slave_only}" = true ]; then 75954f46d2SVladimir Oltean extra_args="${extra_args} -s" 76954f46d2SVladimir Oltean fi 77954f46d2SVladimir Oltean 78954f46d2SVladimir Oltean # declare dynamic variables ptp4l_log_${if_name} and ptp4l_pid_${if_name} 79954f46d2SVladimir Oltean # as global, so that they can be referenced later 80954f46d2SVladimir Oltean declare -g "${log}=$(mktemp)" 81954f46d2SVladimir Oltean 82954f46d2SVladimir Oltean chrt -f 10 ptp4l -m -2 -P \ 83954f46d2SVladimir Oltean --step_threshold 0.00002 \ 84954f46d2SVladimir Oltean --first_step_threshold 0.00002 \ 85954f46d2SVladimir Oltean --tx_timestamp_timeout 100 \ 86954f46d2SVladimir Oltean --uds_address="${uds_address}" \ 87954f46d2SVladimir Oltean ${extra_args} \ 88954f46d2SVladimir Oltean > "${!log}" 2>&1 & 89954f46d2SVladimir Oltean declare -g "${pid}=$!" 90954f46d2SVladimir Oltean 917ff9396eSVladimir Oltean echo "ptp4l for interfaces ${if_names} logs to ${!log} and has pid ${!pid}" 92954f46d2SVladimir Oltean 93954f46d2SVladimir Oltean sleep 1 94954f46d2SVladimir Oltean} 95954f46d2SVladimir Oltean 96954f46d2SVladimir Olteanptp4l_stop() 97954f46d2SVladimir Oltean{ 987ff9396eSVladimir Oltean local if_names="$1" 997ff9396eSVladimir Oltean local log="ptp4l_log_$(if_names_to_label ${if_names})" 1007ff9396eSVladimir Oltean local pid="ptp4l_pid_$(if_names_to_label ${if_names})" 101954f46d2SVladimir Oltean 102954f46d2SVladimir Oltean { kill ${!pid} && wait ${!pid}; } 2> /dev/null 103954f46d2SVladimir Oltean rm "${!log}" 2> /dev/null 104954f46d2SVladimir Oltean} 105954f46d2SVladimir Oltean 106954f46d2SVladimir Olteancpufreq_max() 107954f46d2SVladimir Oltean{ 108954f46d2SVladimir Oltean local cpu=$1 109954f46d2SVladimir Oltean local freq="cpu${cpu}_freq" 110954f46d2SVladimir Oltean local governor="cpu${cpu}_governor" 111954f46d2SVladimir Oltean 112954f46d2SVladimir Oltean # Kernel may be compiled with CONFIG_CPU_FREQ disabled 113954f46d2SVladimir Oltean if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then 114954f46d2SVladimir Oltean return 115954f46d2SVladimir Oltean fi 116954f46d2SVladimir Oltean 117954f46d2SVladimir Oltean # declare dynamic variables cpu${cpu}_freq and cpu${cpu}_governor as 118954f46d2SVladimir Oltean # global, so they can be referenced later 119954f46d2SVladimir Oltean declare -g "${freq}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq)" 120954f46d2SVladimir Oltean declare -g "${governor}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor)" 121954f46d2SVladimir Oltean 122954f46d2SVladimir Oltean cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_max_freq > \ 123954f46d2SVladimir Oltean /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq 124954f46d2SVladimir Oltean echo -n "performance" > \ 125954f46d2SVladimir Oltean /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor 126954f46d2SVladimir Oltean} 127954f46d2SVladimir Oltean 128954f46d2SVladimir Olteancpufreq_restore() 129954f46d2SVladimir Oltean{ 130954f46d2SVladimir Oltean local cpu=$1 131954f46d2SVladimir Oltean local freq="cpu${cpu}_freq" 132954f46d2SVladimir Oltean local governor="cpu${cpu}_governor" 133954f46d2SVladimir Oltean 134954f46d2SVladimir Oltean if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then 135954f46d2SVladimir Oltean return 136954f46d2SVladimir Oltean fi 137954f46d2SVladimir Oltean 138954f46d2SVladimir Oltean echo "${!freq}" > /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq 139954f46d2SVladimir Oltean echo -n "${!governor}" > \ 140954f46d2SVladimir Oltean /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor 141954f46d2SVladimir Oltean} 142954f46d2SVladimir Oltean 143954f46d2SVladimir Olteanisochron_recv_start() 144954f46d2SVladimir Oltean{ 145954f46d2SVladimir Oltean local if_name=$1 146954f46d2SVladimir Oltean local uds=$2 147a7ce95acSVladimir Oltean local stats_port=$3 148a7ce95acSVladimir Oltean local extra_args=$4 149a7ce95acSVladimir Oltean local pid="isochron_pid_${stats_port}" 150954f46d2SVladimir Oltean 151954f46d2SVladimir Oltean if ! [ -z "${uds}" ]; then 1527d45b5fdSVladimir Oltean extra_args="${extra_args} --unix-domain-socket ${uds}" 153954f46d2SVladimir Oltean fi 154954f46d2SVladimir Oltean 155954f46d2SVladimir Oltean isochron rcv \ 156954f46d2SVladimir Oltean --interface ${if_name} \ 157954f46d2SVladimir Oltean --sched-priority 98 \ 158954f46d2SVladimir Oltean --sched-fifo \ 159954f46d2SVladimir Oltean --utc-tai-offset ${UTC_TAI_OFFSET} \ 160a7ce95acSVladimir Oltean --stats-port ${stats_port} \ 161954f46d2SVladimir Oltean --quiet \ 162954f46d2SVladimir Oltean ${extra_args} & \ 163a7ce95acSVladimir Oltean declare -g "${pid}=$!" 164954f46d2SVladimir Oltean 165954f46d2SVladimir Oltean sleep 1 166954f46d2SVladimir Oltean} 167954f46d2SVladimir Oltean 168954f46d2SVladimir Olteanisochron_recv_stop() 169954f46d2SVladimir Oltean{ 170a7ce95acSVladimir Oltean local stats_port=$1 171a7ce95acSVladimir Oltean local pid="isochron_pid_${stats_port}" 172a7ce95acSVladimir Oltean 173a7ce95acSVladimir Oltean { kill ${!pid} && wait ${!pid}; } 2> /dev/null 174954f46d2SVladimir Oltean} 175954f46d2SVladimir Oltean 176954f46d2SVladimir Olteanisochron_do() 177954f46d2SVladimir Oltean{ 178954f46d2SVladimir Oltean local sender_if_name=$1; shift 179954f46d2SVladimir Oltean local receiver_if_name=$1; shift 180954f46d2SVladimir Oltean local sender_uds=$1; shift 181954f46d2SVladimir Oltean local receiver_uds=$1; shift 182954f46d2SVladimir Oltean local base_time=$1; shift 183954f46d2SVladimir Oltean local cycle_time=$1; shift 184954f46d2SVladimir Oltean local shift_time=$1; shift 185954f46d2SVladimir Oltean local num_pkts=$1; shift 186954f46d2SVladimir Oltean local vid=$1; shift 187954f46d2SVladimir Oltean local priority=$1; shift 188954f46d2SVladimir Oltean local dst_ip=$1; shift 189954f46d2SVladimir Oltean local isochron_dat=$1; shift 190954f46d2SVladimir Oltean local extra_args="" 191954f46d2SVladimir Oltean local receiver_extra_args="" 192954f46d2SVladimir Oltean local vrf="$(master_name_get ${sender_if_name})" 193954f46d2SVladimir Oltean local use_l2="true" 194954f46d2SVladimir Oltean 195954f46d2SVladimir Oltean if ! [ -z "${dst_ip}" ]; then 196954f46d2SVladimir Oltean use_l2="false" 197954f46d2SVladimir Oltean fi 198954f46d2SVladimir Oltean 199954f46d2SVladimir Oltean if ! [ -z "${vrf}" ]; then 200954f46d2SVladimir Oltean dst_ip="${dst_ip}%${vrf}" 201954f46d2SVladimir Oltean fi 202954f46d2SVladimir Oltean 203954f46d2SVladimir Oltean if ! [ -z "${vid}" ]; then 204954f46d2SVladimir Oltean vid="--vid=${vid}" 205954f46d2SVladimir Oltean fi 206954f46d2SVladimir Oltean 207954f46d2SVladimir Oltean if [ -z "${receiver_uds}" ]; then 208954f46d2SVladimir Oltean extra_args="${extra_args} --omit-remote-sync" 209954f46d2SVladimir Oltean fi 210954f46d2SVladimir Oltean 211954f46d2SVladimir Oltean if ! [ -z "${shift_time}" ]; then 212954f46d2SVladimir Oltean extra_args="${extra_args} --shift-time=${shift_time}" 213954f46d2SVladimir Oltean fi 214954f46d2SVladimir Oltean 215954f46d2SVladimir Oltean if [ "${use_l2}" = "true" ]; then 216954f46d2SVladimir Oltean extra_args="${extra_args} --l2 --etype=0xdead ${vid}" 217954f46d2SVladimir Oltean receiver_extra_args="--l2 --etype=0xdead" 218954f46d2SVladimir Oltean else 219954f46d2SVladimir Oltean extra_args="${extra_args} --l4 --ip-destination=${dst_ip}" 220954f46d2SVladimir Oltean receiver_extra_args="--l4" 221954f46d2SVladimir Oltean fi 222954f46d2SVladimir Oltean 223954f46d2SVladimir Oltean cpufreq_max ${ISOCHRON_CPU} 224954f46d2SVladimir Oltean 225a7ce95acSVladimir Oltean isochron_recv_start "${h2}" "${receiver_uds}" 5000 "${receiver_extra_args}" 226954f46d2SVladimir Oltean 227954f46d2SVladimir Oltean isochron send \ 228954f46d2SVladimir Oltean --interface ${sender_if_name} \ 229954f46d2SVladimir Oltean --unix-domain-socket ${sender_uds} \ 230954f46d2SVladimir Oltean --priority ${priority} \ 231954f46d2SVladimir Oltean --base-time ${base_time} \ 232954f46d2SVladimir Oltean --cycle-time ${cycle_time} \ 233954f46d2SVladimir Oltean --num-frames ${num_pkts} \ 234954f46d2SVladimir Oltean --frame-size 64 \ 235954f46d2SVladimir Oltean --txtime \ 236954f46d2SVladimir Oltean --utc-tai-offset ${UTC_TAI_OFFSET} \ 237954f46d2SVladimir Oltean --cpu-mask $((1 << ${ISOCHRON_CPU})) \ 238954f46d2SVladimir Oltean --sched-fifo \ 239954f46d2SVladimir Oltean --sched-priority 98 \ 240954f46d2SVladimir Oltean --client 127.0.0.1 \ 241954f46d2SVladimir Oltean --sync-threshold 5000 \ 242954f46d2SVladimir Oltean --output-file ${isochron_dat} \ 243954f46d2SVladimir Oltean ${extra_args} \ 244954f46d2SVladimir Oltean --quiet 245954f46d2SVladimir Oltean 246a7ce95acSVladimir Oltean isochron_recv_stop 5000 247954f46d2SVladimir Oltean 248954f46d2SVladimir Oltean cpufreq_restore ${ISOCHRON_CPU} 249954f46d2SVladimir Oltean} 250