250 lines
5.5 KiB
Bash
250 lines
5.5 KiB
Bash
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
# Copyright 2021-2022 NXP
|
|
|
|
REQUIRE_ISOCHRON=${REQUIRE_ISOCHRON:=yes}
|
|
REQUIRE_LINUXPTP=${REQUIRE_LINUXPTP:=yes}
|
|
|
|
# Tunables
|
|
UTC_TAI_OFFSET=37
|
|
ISOCHRON_CPU=1
|
|
|
|
if [[ "$REQUIRE_ISOCHRON" = "yes" ]]; then
|
|
# https://github.com/vladimiroltean/tsn-scripts
|
|
# WARNING: isochron versions pre-1.0 are unstable,
|
|
# always use the latest version
|
|
require_command isochron
|
|
fi
|
|
if [[ "$REQUIRE_LINUXPTP" = "yes" ]]; then
|
|
require_command phc2sys
|
|
require_command ptp4l
|
|
fi
|
|
|
|
phc2sys_start()
|
|
{
|
|
local uds_address=$1
|
|
local extra_args=""
|
|
|
|
if ! [ -z "${uds_address}" ]; then
|
|
extra_args="${extra_args} -z ${uds_address}"
|
|
fi
|
|
|
|
phc2sys_log="$(mktemp)"
|
|
|
|
chrt -f 10 phc2sys -m \
|
|
-a -rr \
|
|
--step_threshold 0.00002 \
|
|
--first_step_threshold 0.00002 \
|
|
${extra_args} \
|
|
> "${phc2sys_log}" 2>&1 &
|
|
phc2sys_pid=$!
|
|
|
|
echo "phc2sys logs to ${phc2sys_log} and has pid ${phc2sys_pid}"
|
|
|
|
sleep 1
|
|
}
|
|
|
|
phc2sys_stop()
|
|
{
|
|
{ kill ${phc2sys_pid} && wait ${phc2sys_pid}; } 2> /dev/null
|
|
rm "${phc2sys_log}" 2> /dev/null
|
|
}
|
|
|
|
# Replace space separators from interface list with underscores
|
|
if_names_to_label()
|
|
{
|
|
local if_name_list="$1"
|
|
|
|
echo "${if_name_list/ /_}"
|
|
}
|
|
|
|
ptp4l_start()
|
|
{
|
|
local if_names="$1"
|
|
local slave_only=$2
|
|
local uds_address=$3
|
|
local log="ptp4l_log_$(if_names_to_label ${if_names})"
|
|
local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
|
|
local extra_args=""
|
|
|
|
for if_name in ${if_names}; do
|
|
extra_args="${extra_args} -i ${if_name}"
|
|
done
|
|
|
|
if [ "${slave_only}" = true ]; then
|
|
extra_args="${extra_args} -s"
|
|
fi
|
|
|
|
# declare dynamic variables ptp4l_log_${if_name} and ptp4l_pid_${if_name}
|
|
# as global, so that they can be referenced later
|
|
declare -g "${log}=$(mktemp)"
|
|
|
|
chrt -f 10 ptp4l -m -2 -P \
|
|
--step_threshold 0.00002 \
|
|
--first_step_threshold 0.00002 \
|
|
--tx_timestamp_timeout 100 \
|
|
--uds_address="${uds_address}" \
|
|
${extra_args} \
|
|
> "${!log}" 2>&1 &
|
|
declare -g "${pid}=$!"
|
|
|
|
echo "ptp4l for interfaces ${if_names} logs to ${!log} and has pid ${!pid}"
|
|
|
|
sleep 1
|
|
}
|
|
|
|
ptp4l_stop()
|
|
{
|
|
local if_names="$1"
|
|
local log="ptp4l_log_$(if_names_to_label ${if_names})"
|
|
local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
|
|
|
|
{ kill ${!pid} && wait ${!pid}; } 2> /dev/null
|
|
rm "${!log}" 2> /dev/null
|
|
}
|
|
|
|
cpufreq_max()
|
|
{
|
|
local cpu=$1
|
|
local freq="cpu${cpu}_freq"
|
|
local governor="cpu${cpu}_governor"
|
|
|
|
# Kernel may be compiled with CONFIG_CPU_FREQ disabled
|
|
if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
|
|
return
|
|
fi
|
|
|
|
# declare dynamic variables cpu${cpu}_freq and cpu${cpu}_governor as
|
|
# global, so they can be referenced later
|
|
declare -g "${freq}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq)"
|
|
declare -g "${governor}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor)"
|
|
|
|
cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_max_freq > \
|
|
/sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
|
|
echo -n "performance" > \
|
|
/sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
|
|
}
|
|
|
|
cpufreq_restore()
|
|
{
|
|
local cpu=$1
|
|
local freq="cpu${cpu}_freq"
|
|
local governor="cpu${cpu}_governor"
|
|
|
|
if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
|
|
return
|
|
fi
|
|
|
|
echo "${!freq}" > /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
|
|
echo -n "${!governor}" > \
|
|
/sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
|
|
}
|
|
|
|
isochron_recv_start()
|
|
{
|
|
local if_name=$1
|
|
local uds=$2
|
|
local stats_port=$3
|
|
local extra_args=$4
|
|
local pid="isochron_pid_${stats_port}"
|
|
|
|
if ! [ -z "${uds}" ]; then
|
|
extra_args="${extra_args} --unix-domain-socket ${uds}"
|
|
fi
|
|
|
|
isochron rcv \
|
|
--interface ${if_name} \
|
|
--sched-priority 98 \
|
|
--sched-fifo \
|
|
--utc-tai-offset ${UTC_TAI_OFFSET} \
|
|
--stats-port ${stats_port} \
|
|
--quiet \
|
|
${extra_args} & \
|
|
declare -g "${pid}=$!"
|
|
|
|
sleep 1
|
|
}
|
|
|
|
isochron_recv_stop()
|
|
{
|
|
local stats_port=$1
|
|
local pid="isochron_pid_${stats_port}"
|
|
|
|
{ kill ${!pid} && wait ${!pid}; } 2> /dev/null
|
|
}
|
|
|
|
isochron_do()
|
|
{
|
|
local sender_if_name=$1; shift
|
|
local receiver_if_name=$1; shift
|
|
local sender_uds=$1; shift
|
|
local receiver_uds=$1; shift
|
|
local base_time=$1; shift
|
|
local cycle_time=$1; shift
|
|
local shift_time=$1; shift
|
|
local num_pkts=$1; shift
|
|
local vid=$1; shift
|
|
local priority=$1; shift
|
|
local dst_ip=$1; shift
|
|
local isochron_dat=$1; shift
|
|
local extra_args=""
|
|
local receiver_extra_args=""
|
|
local vrf="$(master_name_get ${sender_if_name})"
|
|
local use_l2="true"
|
|
|
|
if ! [ -z "${dst_ip}" ]; then
|
|
use_l2="false"
|
|
fi
|
|
|
|
if ! [ -z "${vrf}" ]; then
|
|
dst_ip="${dst_ip}%${vrf}"
|
|
fi
|
|
|
|
if ! [ -z "${vid}" ]; then
|
|
vid="--vid=${vid}"
|
|
fi
|
|
|
|
if [ -z "${receiver_uds}" ]; then
|
|
extra_args="${extra_args} --omit-remote-sync"
|
|
fi
|
|
|
|
if ! [ -z "${shift_time}" ]; then
|
|
extra_args="${extra_args} --shift-time=${shift_time}"
|
|
fi
|
|
|
|
if [ "${use_l2}" = "true" ]; then
|
|
extra_args="${extra_args} --l2 --etype=0xdead ${vid}"
|
|
receiver_extra_args="--l2 --etype=0xdead"
|
|
else
|
|
extra_args="${extra_args} --l4 --ip-destination=${dst_ip}"
|
|
receiver_extra_args="--l4"
|
|
fi
|
|
|
|
cpufreq_max ${ISOCHRON_CPU}
|
|
|
|
isochron_recv_start "${h2}" "${receiver_uds}" 5000 "${receiver_extra_args}"
|
|
|
|
isochron send \
|
|
--interface ${sender_if_name} \
|
|
--unix-domain-socket ${sender_uds} \
|
|
--priority ${priority} \
|
|
--base-time ${base_time} \
|
|
--cycle-time ${cycle_time} \
|
|
--num-frames ${num_pkts} \
|
|
--frame-size 64 \
|
|
--txtime \
|
|
--utc-tai-offset ${UTC_TAI_OFFSET} \
|
|
--cpu-mask $((1 << ${ISOCHRON_CPU})) \
|
|
--sched-fifo \
|
|
--sched-priority 98 \
|
|
--client 127.0.0.1 \
|
|
--sync-threshold 5000 \
|
|
--output-file ${isochron_dat} \
|
|
${extra_args} \
|
|
--quiet
|
|
|
|
isochron_recv_stop 5000
|
|
|
|
cpufreq_restore ${ISOCHRON_CPU}
|
|
}
|