tsn_lib.sh 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Copyright 2021-2022 NXP
  4. REQUIRE_ISOCHRON=${REQUIRE_ISOCHRON:=yes}
  5. REQUIRE_LINUXPTP=${REQUIRE_LINUXPTP:=yes}
  6. # Tunables
  7. UTC_TAI_OFFSET=37
  8. ISOCHRON_CPU=1
  9. if [[ "$REQUIRE_ISOCHRON" = "yes" ]]; then
  10. # https://github.com/vladimiroltean/tsn-scripts
  11. # WARNING: isochron versions pre-1.0 are unstable,
  12. # always use the latest version
  13. require_command isochron
  14. fi
  15. if [[ "$REQUIRE_LINUXPTP" = "yes" ]]; then
  16. require_command phc2sys
  17. require_command ptp4l
  18. fi
  19. phc2sys_start()
  20. {
  21. local uds_address=$1
  22. local extra_args=""
  23. if ! [ -z "${uds_address}" ]; then
  24. extra_args="${extra_args} -z ${uds_address}"
  25. fi
  26. phc2sys_log="$(mktemp)"
  27. chrt -f 10 phc2sys -m \
  28. -a -rr \
  29. --step_threshold 0.00002 \
  30. --first_step_threshold 0.00002 \
  31. ${extra_args} \
  32. > "${phc2sys_log}" 2>&1 &
  33. phc2sys_pid=$!
  34. echo "phc2sys logs to ${phc2sys_log} and has pid ${phc2sys_pid}"
  35. sleep 1
  36. }
  37. phc2sys_stop()
  38. {
  39. { kill ${phc2sys_pid} && wait ${phc2sys_pid}; } 2> /dev/null
  40. rm "${phc2sys_log}" 2> /dev/null
  41. }
  42. # Replace space separators from interface list with underscores
  43. if_names_to_label()
  44. {
  45. local if_name_list="$1"
  46. echo "${if_name_list/ /_}"
  47. }
  48. ptp4l_start()
  49. {
  50. local if_names="$1"
  51. local slave_only=$2
  52. local uds_address=$3
  53. local log="ptp4l_log_$(if_names_to_label ${if_names})"
  54. local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
  55. local extra_args=""
  56. for if_name in ${if_names}; do
  57. extra_args="${extra_args} -i ${if_name}"
  58. done
  59. if [ "${slave_only}" = true ]; then
  60. extra_args="${extra_args} -s"
  61. fi
  62. # declare dynamic variables ptp4l_log_${if_name} and ptp4l_pid_${if_name}
  63. # as global, so that they can be referenced later
  64. declare -g "${log}=$(mktemp)"
  65. chrt -f 10 ptp4l -m -2 -P \
  66. --step_threshold 0.00002 \
  67. --first_step_threshold 0.00002 \
  68. --tx_timestamp_timeout 100 \
  69. --uds_address="${uds_address}" \
  70. ${extra_args} \
  71. > "${!log}" 2>&1 &
  72. declare -g "${pid}=$!"
  73. echo "ptp4l for interfaces ${if_names} logs to ${!log} and has pid ${!pid}"
  74. sleep 1
  75. }
  76. ptp4l_stop()
  77. {
  78. local if_names="$1"
  79. local log="ptp4l_log_$(if_names_to_label ${if_names})"
  80. local pid="ptp4l_pid_$(if_names_to_label ${if_names})"
  81. { kill ${!pid} && wait ${!pid}; } 2> /dev/null
  82. rm "${!log}" 2> /dev/null
  83. }
  84. cpufreq_max()
  85. {
  86. local cpu=$1
  87. local freq="cpu${cpu}_freq"
  88. local governor="cpu${cpu}_governor"
  89. # Kernel may be compiled with CONFIG_CPU_FREQ disabled
  90. if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
  91. return
  92. fi
  93. # declare dynamic variables cpu${cpu}_freq and cpu${cpu}_governor as
  94. # global, so they can be referenced later
  95. declare -g "${freq}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq)"
  96. declare -g "${governor}=$(cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor)"
  97. cat /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_max_freq > \
  98. /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
  99. echo -n "performance" > \
  100. /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
  101. }
  102. cpufreq_restore()
  103. {
  104. local cpu=$1
  105. local freq="cpu${cpu}_freq"
  106. local governor="cpu${cpu}_governor"
  107. if ! [ -d /sys/bus/cpu/devices/cpu${cpu}/cpufreq ]; then
  108. return
  109. fi
  110. echo "${!freq}" > /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_min_freq
  111. echo -n "${!governor}" > \
  112. /sys/bus/cpu/devices/cpu${cpu}/cpufreq/scaling_governor
  113. }
  114. isochron_recv_start()
  115. {
  116. local if_name=$1
  117. local uds=$2
  118. local stats_port=$3
  119. local extra_args=$4
  120. local pid="isochron_pid_${stats_port}"
  121. if ! [ -z "${uds}" ]; then
  122. extra_args="${extra_args} --unix-domain-socket ${uds}"
  123. fi
  124. isochron rcv \
  125. --interface ${if_name} \
  126. --sched-priority 98 \
  127. --sched-fifo \
  128. --utc-tai-offset ${UTC_TAI_OFFSET} \
  129. --stats-port ${stats_port} \
  130. --quiet \
  131. ${extra_args} & \
  132. declare -g "${pid}=$!"
  133. sleep 1
  134. }
  135. isochron_recv_stop()
  136. {
  137. local stats_port=$1
  138. local pid="isochron_pid_${stats_port}"
  139. { kill ${!pid} && wait ${!pid}; } 2> /dev/null
  140. }
  141. isochron_do()
  142. {
  143. local sender_if_name=$1; shift
  144. local receiver_if_name=$1; shift
  145. local sender_uds=$1; shift
  146. local receiver_uds=$1; shift
  147. local base_time=$1; shift
  148. local cycle_time=$1; shift
  149. local shift_time=$1; shift
  150. local num_pkts=$1; shift
  151. local vid=$1; shift
  152. local priority=$1; shift
  153. local dst_ip=$1; shift
  154. local isochron_dat=$1; shift
  155. local extra_args=""
  156. local receiver_extra_args=""
  157. local vrf="$(master_name_get ${sender_if_name})"
  158. local use_l2="true"
  159. if ! [ -z "${dst_ip}" ]; then
  160. use_l2="false"
  161. fi
  162. if ! [ -z "${vrf}" ]; then
  163. dst_ip="${dst_ip}%${vrf}"
  164. fi
  165. if ! [ -z "${vid}" ]; then
  166. vid="--vid=${vid}"
  167. fi
  168. if [ -z "${receiver_uds}" ]; then
  169. extra_args="${extra_args} --omit-remote-sync"
  170. fi
  171. if ! [ -z "${shift_time}" ]; then
  172. extra_args="${extra_args} --shift-time=${shift_time}"
  173. fi
  174. if [ "${use_l2}" = "true" ]; then
  175. extra_args="${extra_args} --l2 --etype=0xdead ${vid}"
  176. receiver_extra_args="--l2 --etype=0xdead"
  177. else
  178. extra_args="${extra_args} --l4 --ip-destination=${dst_ip}"
  179. receiver_extra_args="--l4"
  180. fi
  181. cpufreq_max ${ISOCHRON_CPU}
  182. isochron_recv_start "${h2}" "${receiver_uds}" 5000 "${receiver_extra_args}"
  183. isochron send \
  184. --interface ${sender_if_name} \
  185. --unix-domain-socket ${sender_uds} \
  186. --priority ${priority} \
  187. --base-time ${base_time} \
  188. --cycle-time ${cycle_time} \
  189. --num-frames ${num_pkts} \
  190. --frame-size 64 \
  191. --txtime \
  192. --utc-tai-offset ${UTC_TAI_OFFSET} \
  193. --cpu-mask $((1 << ${ISOCHRON_CPU})) \
  194. --sched-fifo \
  195. --sched-priority 98 \
  196. --client 127.0.0.1 \
  197. --sync-threshold 5000 \
  198. --output-file ${isochron_dat} \
  199. ${extra_args} \
  200. --quiet
  201. isochron_recv_stop 5000
  202. cpufreq_restore ${ISOCHRON_CPU}
  203. }