ptpd2(8)

πŸ“¦ version 2.3.1, in opensuse-leap 16.0

πŸ’… ptpd2(8) β€” Precision Time Protocol daemon (1588-2008) πŸ’…

okay so bestie, welcome to ptpd2(8), the manual page for the Precision Time Protocol daemon. She's giving Very Serious Time Business but honestly she's iconic. Let's get into it 🫢


✨ NAME ✨

ptpd2 β€” the Precision Time Protocol daemon (1588-2008). That's it, that's the name section, short and slay πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

ptpd2 [ -?hH ] [ -e SETTING ] [ -kvOLAl ] [ -smMyEPanCV ] [ -c FILE ] [
-R DIR ] [ -f FILE ] [ -S FILE ] [ -d DOMAIN ] [ -u ADDRESS ] [ -r
NUMBER ] -i INTERFACE

🌸 DESCRIPTION 🌸

So PTPd is a daemon that implements the Precision Time Protocol (PTP) Version 2, as defined by the IEEE 1588-2008 standard. PTP was literally developed to give LAN-connected computers very precise time coordination β€” it's the group chat scheduler of the networking world, no cap ⏰

The daemon must run as root in order to be able to manipulate the system clock and use low port numbers. That part is not a suggestion, bestie, that's a requirement πŸ‘‘

PTPd is feature rich, and she supports:

  • IPv4 multicast
  • unicast
  • hybrid mode (mixed) operation
  • Ethernet mode

Even without hardware assistance, PTPd is able to achieve and maintain sub-microsecond level timing precision, and she's able to withstand PTP Grandmaster failovers, link failures and restarts with minimal impact to timing performance. Resilient queen energy honestly πŸ˜­πŸ’–

PTPd is lightweight, portable, and currently supports Linux, FreeBSD and Mac OS X, and runs on multiple CPU architectures, 32-bit and 64-bit, including x86 and ARM. She's everywhere, she's versatile, she's the main character 🌈


🧚 COMMAND-LINE CONFIGURATION 🧚

As of version 2.3.0, the configuration file is the preferred mechanism for configuring PTPd. So the options available as short options (-x) and long options (--xxxxx) mostly provide basic control over the daemon operation, and only provide the very basic PTP protocol settings.

The rest of the settings (see ptpd2.conf(5)) can also be specified as command-line options, but they take the long --key:section="value" form. Yes, it's giving fancy. Yes, it's on purpose πŸ’…


πŸŽ€ BASIC DAEMON OPTIONS πŸŽ€

  • -c, --config-file PATH β€” Path to the configuration file (see ptpd2.conf(5))
  • -k, --check-config β€” Check the configuration and exit β€” returns 0 if the configuration is correct.
  • -v, --version β€” Print the version string and exit
  • -h, --help β€” Show the help screen
  • -H, --long-help β€” Show detailed help for all settings and behaviours
  • -e, --explain SETTING β€” Show help for a single setting (section:key)
  • -O, --default-config β€” Show the default configuration and exit (the output is usable as a configuration file)
  • -L, --ignore-lock β€” Skip lock file checks and locking (also global:ignore_lock)
  • -A, --auto-lock β€” Use preset / port mode specific lock file names β€” useful when running multiple instances
  • -l, --lockfile β€” Specify the lock file path (also global:lock_file)
  • -p, --print-lockfile β€” Print the path to the lock file and exit (useful for init scripts in combination with auto lock files)
  • -R, --lock-directory DIR β€” Directory to store lock files (also global:lock_directory)
  • -f, --log-file PATH β€” Path to the log file (also global:logfile)
  • -S, --statistics-file PATH β€” Path to the statistics file (also global:statistics_file)

πŸ”₯ BASIC PTP PROTOCOL OPTIONS πŸ”₯

  • -i, --interface DEV β€” REQUIRED: the interface to use β€” eth0, etc (also ptpengine:interface)
  • -d, --domain NUMBER β€” The PTP domain number to become part of (also ptpengine:domain)
  • -s, --slaveonly β€” Slave only mode (also ptpengine:preset=slaveonly)
  • -m, --masterslave β€” Full IEEE 1588 implementation: master, slave when not best GM (also ptpengine:preset=masterslave)
  • -M, --masteronly β€” Master only mode: passive when not best GM (also ptpengine:preset=masteronly)
  • -y, --hybrid β€” Hybrid mode β€” mixed multicast and unicast operation (multicast for sync and announce, unicast for delay request and response (also ptpengine:ip_mode=hybrid)
  • -U, --unicast β€” Unicast operation β€” (also ptpengine:ip_mode=unicast). For a GM, unicast destinations must be specified (-u, --unicast-destinations, ptpengine:unicast_destinations) unless using unicast negotiation (-g, --unicast-negotiation, ptpengine:unicast_negotiation=y) for delay request and response (also ptpengine:ip_mode=hybrid). For a slave, unicast destinations must be specified if not using unicast negotiation.
  • -g, --unicast-negotiation β€” Enable unicast message delivery and interval negotiation using signaling messages, as used by the Telecom profile (also enables ptpengine:ip_mode=unicast)
  • -u, --unicast-destinations ip/host, ip/host, ... β€” List of unicast destinations β€” see --unicast (also ptpengine:ip_mode=unicast + ptpengine:unicast_destinations)
  • -E, --e2e β€” End to end delay mechanism (also ptpengine:delay_mechanism=E2E)
πŸ™ˆ real talk: in the original page this -E, --e2e entry is literally glued onto the end of the -u description with no line break, so don't come for me β€” I'm just handing it to you as its own bullet so your eyes don't have to suffer.
  • -E, --p2p β€” Peer to peer delay mechanism (also ptpengine:delay_mechanism=P2P)
  • -a, --delay-override β€” In slave state, override the delay request interval announced by the master (also ptpengine:log_delayreq_override) β€” the value of ptpengine:log_delayreq_interval is used
  • -r, --delay-interval NUMBER β€” Specify the delay request message interval (log 2) β€” (also ptpengine:log_delayreq_interval)
  • -n, --clock:no_adjust β€” Do not adjust the clock (also clock:no_adjust)
  • -D<DD...>, --debug β€” Debug level (also global:debug_level) β€” only if compiled with RUNTIME_DEBUG
  • -C, --foreground β€” Don't run in the background (also global:foreground=Y)
  • -V, --verbose β€” Run in the foreground, log all the messages to standard output (also global:verbose_foreground=Y)

πŸ’€ COMPATIBILITY OPTIONS πŸ’€

PTPd supports the following options compatible with versions before 2.3.0:

  • -b DEV β€” Network interface to use
  • -i NUMBER β€” PTP domain number
  • -g β€” Slave only mode
  • -G β€” Β΄Master mode with NTPΒ΄ (master only mode)
  • -W β€” Β΄Master mode without NTPΒ΄ (master / slave mode)
  • -U β€” Hybrid mode (mixed unicast + multicast operation)
  • -Y NUMBER β€” Delay request interval (log 2)
  • -t β€” Do not adjust the clock
⚠️ NOTE: the above options are deprecated and will be removed in subsequent versions. Until then, their use will issue a warning. So like… they still work, but they're on notice, bestie 🫠

πŸ‘‘ PTPD PORT STATES πŸ‘‘

  • init β€” INITIALIZING
  • flt β€” FAULTY
  • lstn_init β€” LISTENING (first time)
  • lstn_reset β€” LISTENING (subsequent reset)
  • pass β€” PASSIVE (not best master, not announcing)
  • uncl β€” UNCALIBRATED
  • slv β€” SLAVE
  • pmst β€” PRE-MASTER
  • mst β€” MASTER (active)
  • dsbl β€” DISABLED
  • ? (unk) β€” UNKNOWN state

Each one is a whole little era, honestly 🌟

πŸ“Š STATISTICS LOG FILE FORMAT πŸ“Š

okay so when the statistics log is turned on β€” that's ptpengine:log_statistics, or verbose foreground mode, or a log file via ptpengine:statistics_file β€” a PTPd slave will log clock sync info every single time it gets a Sync and a Delay Response message. and when PTPd starts up or flushes the log, it drops a lil comment line (starts with #) listing all the column names, so you're never squinting at mystery numbers πŸŽ€

the format is a series of comma-separated values (CSV, bestie, we love a classic) and it imports super easily into stats tools and basically every spreadsheet package for analysis and graphing. heads up though: this log can get huge if you run PTPd for long periods at high message rates 😭 so to cut down on the number of messages logged, you can use the global:statistics_log_interval setting to limit output to just one message per configured interval. the size and max number of the statistics log are also controllable β€” see ptpd2.conf(5).

and here's what each column actually means, bestie:

  • Timestamp β€” when the message was received. it can be a text date/time, a Unix timestamp (with fractional seconds), or both (in which case an extra field gets added), all depending on the global:statistics_timestamp_format setting (see ptpd2.conf(5)). plotting-software tip 🌸: when importing the log, if the software understands Unix time, set the timestamp format to unix or both β€” because some software will NOT deal properly with the fractional part of the second when it converts the text date/time.
  • State β€” the port state (see PTP PORT STATES ✨).
  • Clock ID β€” the port identity of the current best master, as defined by IEEE 1588. this is the local clock's ID if the local clock is the best master. displayed as clock_id/port(host) β€” port is the PTP clock port number, do not confuse it with UDP ports, iykyk. the clock ID is an EUI-64 64-bit ID, usually converted from the 48-bit MAC address by inserting 0xfffe between the lower and upper half of the MAC. PTPd will try to convert the clock ID back to a MAC address and look up the hostname from /etc/ethers (see ethers(5)). so populating your ethers file = your admin recognises masters by familiar hostnames, iconic πŸ‘‘
  • One Way Delay β€” current one-way delay (a.k.a. mean path delay) in seconds, calculated by PTPd in slave state from the Delay Request – Delay Response exchange. > note: if this value stays at zero, it usually means no Delay Response messages are being received β€” likely a network issue πŸ™ˆ
  • Offset From Master β€” current offset from master in seconds. this is the main output of the PTP engine in slave state, and it feeds the clock servo for clock corrections. this is the value you stare at when estimating slave performance πŸ’…
  • Slave to Master β€” intermediate offset value (seconds) pulled from the Delay Request – Delay Response exchange, used for computing one-way delay. if the last value was rejected by a filter, the previous value shows in the log. also zero if no Delay Response messages are coming in.
  • Master to Slave β€” intermediate offset value (seconds) pulled from the Sync messages, used for computing the offset from master. if the last value got rejected by a filter, the previous value shows in the log.
  • Observed Drift β€” the integral accumulator of the clock control PI servo model, i.e. the frequency difference between the slave clock and the master clock. this value stabilises once the clock offset has stabilised, and can be used (and is used) to detect clock stability ⭐
  • Last Packet Received β€” what message arrived last: S for Sync, D for Delay Response. if a slave logs no D entries, it's not receiving Delay Response messages, which could be a network issue πŸ‘€
  • One Way Delay Mean β€” one-way delay mean, computed over the last sampling window.
  • One Way Delay Std Dev β€” one-way delay standard deviation, computed over the last sampling window.
  • Offset From Master Mean β€” offset from master mean, computed over the last sampling window.
  • Offset From Master Std Dev β€” offset from master standard deviation, computed over the last sampling window.
  • Observed Drift Mean β€” observed drift / local clock frequency adjustment mean, computed over the last sampling window.
  • Observed Drift Std Dev β€” observed drift / local clock frequency adjustment standard deviation, computed over the last sampling window. the lower this value, the less aggressively the clock is being controlled β€” and therefore the more stable it is 🧚
  • raw delayMS β€” raw (unfiltered) delayMS value. great for evaluating outliers and filter performance.
  • raw delaySM β€” raw (unfiltered) delaySM value. also great for evaluating outliers and filter performance.
NOTE πŸ’–: all of those statistical measures (mean and std dev) only get computed and displayed if PTPd was built without --disable-statistics. the duration of the sampling period is controlled by the global:statistics_update_interval setting β€” see ptpd2.conf(5).

🚦 HANDLED SIGNALS 🚦

PTPd handles these signals, bestie:

  • SIGHUP β€” reload the configuration file (if used) and reopen log files
  • SIGUSR1 β€” when in slave state, force a clock step to the current Offset From Master value
  • SIGUSR2 β€” dump all PTP protocol counters to the current log target (and clear them if ptpengine:sigusr2_clears_counters is set)
  • SIGINT|SIGTERM β€” clean exit: close logs and other open files, clean up the lock file, and exit 🫢
  • SIGKILL β€” force an unclean exit πŸ’€

πŸšͺ EXIT CODES πŸšͺ

when it exits, ptpd2 returns 0 on success β€” either it started successfully in daemon mode, or it otherwise exited cleanly. 0 is also returned when you use the -k (--check-config) option and the configuration was correct ✨

a non-zero exit code means errors:

  • 3 β€” returned on lock file errors, and when ptpd2 could not be started as a daemon
  • 2 β€” returned on memory allocation errors during startup
  • 1 β€” returned for all other error conditions, like configuration errors, running ptpd2 in help mode or with no parameters, on self shutdown, network startup errors, and when attempting to run ptpd2 as non-root 😀

πŸ’» SUPPORTED PLATFORMS AND ARCHITECTURES πŸ’»

PTPd is fully supported on Linux and FreeBSD, because that's what the core devs focus on. OpenBSD and NetBSD are also supported but get less developer attention. so is Mac OS X, and as of PTPd 2.3.1 also OpenSolaris (11) derivatives (tested on OmniOS). Sun's / Oracle's Solaris 11 hasn't been tested, but in essence it should work as intended. Solaris 10 is NOT supported ❌ because it doesn't provide the SO_TIMESTAMP socket option. theoretically you could use Solaris 10 with the pf facility the way snoop does, but there's currently no ongoing effort to achieve that. patches for QNX/Neutrino have been provided but can't be officially merged yet since the devs don't have QNX available. some users have ported PTPd to other RTOS, but that hasn't been merged either.

as of 2.3.1, PTPd runs entirely in software and only relies on kernel and OS APIs, so there are zero hardware dependencies πŸŽ€ any little-endian or big-endian port of modern versions of the supported OSes should work, but only x86 and ARM are actively tested. the only dependencies even close to hardware are NIC drivers and how (and whether) they impact software timestamping.


⏱️ HARDWARE TIMESTAMPING SUPPORT ⏱️

as of 2.3.1, PTPd still does not support hardware timestamping. that functionality will show up in the upcoming version 2.4 β€” and potentially an interim 2.3.x might land that supports hardware clocks and timestamping on Linux. it's very much OS-specific and, to a large extent, hardware-specific. Linux has a PTP kernel API, but not all hardware supports it. and because PTPd supports multiple OS platforms β€” where hardware timestamping may use different mechanisms on every platform β€” it has to be rewritten in a modular way to allow all that without needlessly increasing code complexity, which is already a problem 😭 lowkey the whole reason it's taking a minute.


πŸ› BUGS πŸ›

as of ptpd 2.3.1, the (Open)Solaris (11) OS family is supported, but libpcap functionality is currently broken β€” IPv4/pcap and Ethernet transports can't be used on those systems. PTPd will compile and run, but will not receive any data πŸ’€

please report any bugs using the bug tracker on the SourceForge page: http://sourceforge.net/projects/ptpd/


πŸ‘€ SEE ALSO πŸ‘€


πŸ‘‘ AUTHORS πŸ‘‘

  • Gael Mace <gael_mace@users.sourceforge.net>
  • Alexandre Van Kempen
  • Steven Kreuzer <skreuzer@freebsd.org>
  • George Neville-Neil <gnn@freebsd.org>
  • Wojciech Owczarek <wojciech@owczarek.co.uk>

the ptpd2(8) man page was written by Wojciech Owczarek for ptpd 2.3.0 in November 2013 🫢


okay that's the whole page, bestie, you made it πŸŒˆπŸ’– this is version 2.3.1, dated June, 2015, and yes it's ptpd2(8) β€” go sync some clocks, you absolute icon, periodt βœ¨πŸŽ€

πŸ“¦ where this page comes from