TS2PHC(8)

πŸ“¦ version 4.4, in fedora 43, fedora 44

ts2phc πŸ’– (that's the ts2phc(8) page from the System Manager's Manual, bestie, and it's so good)

✨ NAME ✨

ts2phc β€” Synchronizes one or more PTP Hardware Clocks using external time stamps. πŸ•°οΈβœ¨


🌸 SYNOPSIS 🌸

ts2phc [ -hmqv ] [ -c device|name ] [ -f config ] [ -l print-level ] [
-s device|name ] [ long-options ] ...

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so picture this: ts2phc synchronizes PTP Hardware Clocks (PHC) to external time stamp signals. πŸŽ€ A single source may be used to distribute time to one or more PHC devices. one source, many clocks, all vibing on the same timeline. iconic behavior fr fr πŸ’…


πŸ’œ OPTIONS πŸ’œ

  • -a β€” Adjust the direction of synchronization automatically. πŸͺ„ The program figures out which PHC should be the reference clock for time distribution and which should be the destinations by querying the port states from the running instance of ptp4l. Heads up though, bestie: using this option, the PPS signal distribution hierarchy still remains fixed as per the configuration file. Which implies that using this option, a PPS source of the PHC kind may become a target clock, and a PPS sink may become a reference clock. 😭 Other, non-PHC types of PPS sources (generic, NMEA) cannot become target clocks. no cap. Clocks which are not part of ptp4l's list of ports are not synchronized. This option is useful when the boundary_clock_jbod option of ptp4l is also enabled. πŸ”₯
  • -c device|name β€” Specifies a PHC to be synchronized. The clock may be identified by its character device (like /dev/ptp0) or its associated network interface (like eth0). 🫢 This option may be given multiple times β€” collect them all, main character energy.
  • -f config β€” Read configuration from the specified file. πŸ“„ No configuration file is read by default. (yes, default is literally nothing, she's independent like that πŸ’…)
  • -h β€” Displays the command line help summary. πŸ†˜
  • -l print-level β€” Sets the maximum syslog level of messages which should be printed or sent to the system logger. The default is 6 (LOG_INFO). ⭐
  • -m β€” Prints log messages to the standard output. πŸ‘€
  • -q β€” Prevents sending log messages to the system logger. 🀫 quiet luxury
  • -s device|name β€” Specifies the source of the Time of Day (ToD) data. ⏰ Use the key word "generic" for an external 1-PPS without ToD information. When using a PHC as the time source, the clock may be identified by its character device (like /dev/ptp0) or its associated network interface (like eth0). Use the key word "nmea" for an external 1-PPS from a GPS providing ToD information via the RMC NMEA sentence. πŸ›°οΈ
  • -v β€” Prints the software version and exits. bye bestie πŸ‘‹

🌈 LONG OPTIONS 🌈

Each and every configuration file option (see below) may also appear as a "long" style command line argument. πŸŽ€ For example, the use_syslog option may be set using either of these two forms.

--use_syslog 1   --use_syslog=1

Option values given on the command line override values in the global section of the configuration file. the command line is the main character here, periodt. πŸ‘‘


πŸ“ CONFIGURATION FILE πŸ“

The configuration file is divided into sections. πŸ“š Each section starts with a line containing its name enclosed in brackets and it follows with settings. Each setting is placed on a separate line, it contains the name of the option and the value separated by whitespace characters. Empty lines and lines starting with # are ignored. (so go ahead, comment your little heart out πŸ’–)

There are two different section types.

  1. The global section (indicated as [global]) sets the program options and the default time sink options. Other sections are clock specific sections, and they override the default options. πŸ¦‹
  2. Time sink sections give the name of the configured PHC (e.g. [eth0]). Time sinks specified in the configuration file need not be specified with the -c command line option. ✨

🌸 GLOBAL OPTIONS 🌸

okay bestie, this is the big one β€” the global config directives that shape how the whole program behaves. every single one of these goes in the config file (except the one that literally can't go in the config file, and you'll know it when you see it πŸ’€). read carefully, they all matter.

  • active_key_id β€” used together with the spp and sa_file directives to say which key, out of the Security Association that spp points at, gets used for outbound icv calculations. all the Security Associations come from the file named in sa_file. so yeah, it needs both spp and sa_file to even make sense. value has to be in the range of 1 to 2^32-1, inclusive. default is 0 (disabled).
  • clock_servo β€” the servo that syncs your local clock. valid values, listen up:
    • "pi" β€” a PI controller
    • "linreg" β€” an adaptive controller using linear regression
    • "ntpshm" β€” the NTP SHM reference clock, lets another process do the syncing
    • "refclock_sock" β€” the chrony SOCK reference clock, same deal
    • "nullf" β€” a servo that always dials frequency offset to zero (for use in SyncE nodes)

default is "pi". πŸ‘‘

  • first_step_threshold β€” the maximum offset, in seconds, that the servo will fix by changing the clock frequency (or phase, when you're on the nullf servo) instead of straight-up stepping the clock. this only applies on the first update. set it to 0.0 and the servo will not step the clock on start. default is 0.00002 (that's 20 microseconds).
  • free_running β€” set it to 1 and no PHC gets adjusted at all. honestly so useful for test scenarios, like when you wanna see how well a group of local clocks are synchronized to each other. default is 0 (adjust the clocks).
  • leapfile β€” the path to the current leap seconds definition file. on a Debian system this file comes from the tzdata package and lives at /usr/share/zoneinfo/leap-seconds.list. if a leapfile is configured, it gets reloaded whenever it's modified. default is an empty string, which makes the program fall back on a hard coded table reflecting the known leap seconds as of the software's release date.
  • logging_level β€” the maximum logging level of messages that should be printed. default is 6 (LOG_INFO).
  • max_frequency β€” the maximum allowed frequency adjustment of the clock, in parts per billion. this is an additional limit on top of whatever the hardware allows. set it to 0 and the hardware limit is used instead. default is 900000000 (90%).
  • message_tag β€” the tag added to every message printed to standard output or the system log. if the tag contains the string "{level}", that gets replaced with the log level of the message as a number. default is an empty string β€” and fun fact, you cannot set this in the configuration file, because the option requires an argument. πŸ™ˆ
  • ntpshm_segment β€” the number of the SHM segment used by the ntpshm servo. default is 0.
  • pi_integral_const β€” the integral constant of the PI controller. set it to 0.0 and the integral constant gets computed by this formula from the current sync interval. default is 0.0.
ki = min(ki_scale * sync^ki_exponent, ki_norm_max / sync)
  • pi_integral_exponent β€” the ki_exponent constant in the formula that sets the PI controller's integral constant from the sync interval. default is 0.4.
  • pi_integral_norm_max β€” the ki_norm_max constant in the formula that sets the PI controller's integral constant from the sync interval. default is 0.3.
  • pi_integral_scale β€” the ki_scale constant in the formula that sets the PI controller's integral constant from the sync interval. default is 0.3.
  • pi_proportional_const β€” the proportional constant of the PI controller. set it to 0.0 and the proportional constant gets computed by this formula from the current sync interval. default is 0.0.
kp = min(kp_scale * sync^kp_exponent, kp_norm_max / sync)
  • pi_proportional_exponent β€” the kp_exponent constant in the formula that sets the PI controller's proportional constant from the sync interval. default is -0.3.
  • pi_proportional_norm_max β€” the kp_norm_max constant in the formula that sets the PI controller's proportional constant from the sync interval. default is 0.7
  • pi_proportional_scale β€” the kp_scale constant in the formula that sets the PI controller's proportional constant from the sync interval. default is 0.7.
  • sa_file β€” specifies the location of the file containing Security Associations used for immediate security processing of the Authentication TLV, in support of the optional security mechanism defined in ieee1588-2019 ch 14.16. peek at SECURITY ASSOCIATION OPTIONS for the tea on what goes inside the file. default is an empty string (disabled).
  • servo_num_offset_values β€” how many offset values get considered before transitioning from the SERVO_LOCKED to the SERVO_LOCKED_STABLE state. the transition happens once the last servo_num_offset_values offsets are all below the servo_offset_threshold value. default is 10.
  • servo_offset_threshold β€” the offset threshold used for transitioning from the SERVO_LOCKED to the SERVO_LOCKED_STABLE state. the transition happens once the last servo_num_offset_values offsets are all below the threshold value. default value of offset_threshold is 0 (disabled).
  • step_threshold β€” the maximum offset, in seconds, that the servo will correct by changing the clock frequency instead of stepping the clock. set it to 0.0 and the servo will never step the clock except on start. default is 0.0.
  • spp β€” specifies the security parameters pointer for the security association you want to use for authentication tlv support. if you set it, the port owning the spp will attempt to attach (outbound) and check (inbound) authentication tlvs for all messages, in accordance with the corresponding security association sourced via the sa_file directive. not compatible with one step ports. must be in the range of -1 to 255, inclusive. default is -1 (disabled).
  • ts2phc.holdover β€” the holdover interval, in seconds. when the ToD information stops working (think: GNSS receiver lost its fix 😭), ts2phc is allowed to keep synchronizing the target clock for that specified interval, as long as the servo is in the SERVO_LOCKED_STABLE state. that servo state needs to be enabled via the servo_offset_threshold option first. heads up: holdover is not supported with the -a option, and not when ts2phc.extts_polarity is set to both. default is 0 (disabled).
  • ts2phc.nmea_delay β€” the minimum expected delay of NMEA RMC messages, in nanoseconds. if the maximum delay is longer than 1 second β€” or longer than 'ts2phc.pulsewidth' when 'ts2phc.extts_polarity' is set to "both" β€” you need to set this accordingly so the timestamps from NMEA messages get correctly assigned to the pulses from the PPS signal, and so wrong PPS edges get rejected when edge rejection is enabled. default is 0 nanoseconds.
  • ts2phc.nmea_remote_host, ts2phc.nmea_remote_port β€” specifies the remote host providing ToD information when you're using the "nmea" PPS signal source. note that if both of these are specified, that remote connection gets used in preference to the configured serial port. both default to the empty string, meaning not specified.
  • ts2phc.nmea_serialport, ts2phc.nmea_baudrate β€” specifies the serial port and the baudrate in bps for the character device providing ToD information when you're using the "nmea" PPS signal source. note that if ts2phc.nmea_remote_host and ts2phc.nmea_remote_port are both specified, that remote connection wins over the configured serial port. default serial port is "/dev/ttyS0". default baudrate is 9600 bps.
  • ts2phc.perout_phase β€” configures the offset between the beginning of the second and the PPS source's rising edge. only available for the PHC kind of PPS source. supported range is 0 to 999999999 nanoseconds. default is 0 nanoseconds, but leaving this option unspecified means the phase is not transmitted to the kernel β€” instead PPS gets requested to start at an absolute time equal to the nearest 2nd full second since the start of the program. that should give the same effect, but it may not work with drivers that don't support starting periodic output at an absolute time. 🫠
  • ts2phc.pulsewidth β€” the pulse width of the external PPS signal, in nanoseconds. when 'ts2phc.extts_polarity' is "both", that given pulse width is used to detect and discard the time stamp of the unwanted edge. if the PPS source is of the PHC kind, an attempt is made to ask the kernel to actually emit using this pulse width. if that fails, it's assumed the specified pulse width is correct, and the value gets used in the edge rejection algorithm instead. supported range is 1000000 to 990000000 nanoseconds. default is 500000000 nanoseconds.
  • ts2phc.tod_source β€” specifies the source of Time of Day (ToD) data. use the key word "generic" for an external 1-PPS without ToD information. when using a PHC as the time source, the clock can be identified by its character device (like /dev/ptp0) or by its associated network interface (like eth0). use the key word "nmea" for an external 1-PPS from a GPS providing ToD information via the RMC NMEA sentence. default is "generic"
  • use_syslog β€” print messages to the system log if enabled. default is 1 (enabled).
  • verbose β€” print messages to the standard output if enabled. default is 0 (disabled).

✨ TIME SINK OPTIONS ✨

okay bestie this is the section where we pick the exact physical bits of hardware the clock is gonna talk to πŸ’… every one of these lives in your config file and every one of them matters, so let's go one by one

  • ts2phc.channel β€” which external time stamping channel or periodic output channel we're using, periodt. some PHC devices come with programmable pins and one or more time stamping channels, and this option is how you pick the specific one you want. when you're using a PHC device as the PPS source, this is the knob that selects the periodic output channel. default is channel 0. πŸŽ€
  • ts2phc.extts_correction β€” the value, in nanoseconds, that gets added to every single PPS time stamp. default is 0, aka no correction at all. if your stamps are consistently a lil off, this is your girl. ✨
  • ts2phc.extts_polarity β€” the polarity of the external PPS signal, and your options are literally just "rising" or "falling". some PHC devices always time stamp both edges β€” messy of them, honestly β€” and setting this option to "both" lets ts2phc work with those devices by detecting and ignoring the unwanted edge. πŸ™ˆ if you go the "both" route, be sure to set ts2phc.pulsewidth to the correct value, no cap. default is "rising". πŸ‘‘
  • ts2phc.master β€” set this to 1 and you're configuring the given PHC device as the source of the PPS signal. default is 0, which means it's rocking the time sink role. two completely different vibes, pick wisely. πŸ¦‹
  • ts2phc.pin_index β€” the pin index you wanna use. some PHC devices feature programmable pins, and this option is how you configure a particular pin for the external time stamping or periodic output function. default is pin index 0. ⭐

πŸ’€ WARNING πŸ’€

okay this part is the serious part, bestie, so put your phone down for a sec 🫢

be cautious when you're sharing the same configuration file between ptp4l, phc2sys, and ts2phc.

keep in mind that values specified in the configuration file take precedence over the default values. so if an option that's common to the other programs is set in that config file, then that value gets applied to all the programs using the file β€” and that might not be what you expected at all. 😭 it's giving chaos, it's giving surprise behavior, it's giving "why is my clock doing that."

it is recommended to use separate configuration files for ptp4l, phc2sys, and ts2phc so you avoid any unexpected behavior. fr fr, just give each one its own file, they deserve their own space. πŸ’–


🌸 SEE ALSO 🌸

go read those too, they're iconic in their own right πŸ‘‘


and that's a wrap on this whole page, bestie!! πŸŽ€ this one comes from linuxptp and it's dated March 2024 β€” page TS2PHC(8) if you're keeping receipts. now go sync something and slay βœ¨πŸ’…πŸŒˆ

πŸ“¦ where this page comes from