Repository navigation
linuxptp: add config & init scripts for ptp4l and phc2sys #30279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3817eeb
6cb97c7
2a4f9b4
c49d933
05d3783
bb5a283
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| config ptp4l 'ptp4l' # configures the ptp4l daemon | ||
| #option role 'auto' # role to use: 'auto' (default) - BMCA algo determines role | ||
| # 'client' - will never attempt to be a server | ||
| # 'server' - will never attempt to be a client | ||
|
|
||
| #option loglevel '6' # Logging verbosity for ptp4l (0-7). 6=INFO (default), 7=DEBUG. | ||
|
|
||
| #option require_clock_sync '0' # 0 - skip waiting for kernel to report clock is sync'd (default unless server) | ||
| # 1 - require clock-in-sync check before starting (default if server) | ||
|
|
||
| #option clock_sync_check_interval '15' # Seconds between clock discipline checks (default: 15). | ||
| # Only used when require_clock_sync is 1. | ||
|
|
||
| #option clock_sync_max_tries '8' # Max attempts before giving up clock sync wait (default: 8). | ||
| # Total wait = clock_sync_check_interval x (tries - 1), ~105s at defaults. | ||
| # Set to 0 to wait indefinitely (blocks boot until clock disciplines). | ||
|
|
||
| # For global lines in ptp4l.conf - Each item is one line like "key value" for the [global] section | ||
| #list global_opts 'clockClass 6' | ||
|
|
||
| # For extra ptp4l command line options | ||
| #list extra_args '' | ||
|
|
||
| # At least one ptp_interface section is required for ptp4l to start. | ||
| # Repeat this block for each interface ptp4l should listen on. | ||
| #config ptp_interface | ||
| # option interface 'lan' # required - UCI's interface name, init-script looks up kernel ifname as needed | ||
| # #option transport 'UDPv4' # Network transport: UDPv4 (default), UDPv6, L2. | ||
| # #option delay_mechanism 'E2E' # PTP delay mechanism: E2E (End-to-End, default), P2P (Peer-to-Peer). | ||
| # #list interface_opts 'logSyncInterval -3' | ||
|
|
||
| config phc2sys 'phc2sys' # configures the phc2sys daemon, which syncs either system clock from PHC in NIC (as a client, or vice versa as a server) | ||
| #option phc_device '/dev/ptp0' # PTP Hardware Clock device - required, no default. | ||
| # Verify this matches the PHC for your PTP interface (e.g. /dev/ptp0). | ||
| # phc2sys will not start until this is set. | ||
| # specifies clock sync'ing direction # 'phc_to_sys': PHC (sync'd by ptp4l) disciplines system clock (default unless ptp4l role is 'server') | ||
| #option sync_direction 'phc_to_sys' # 'sys_to_phc': System clock disciplines PHC (default if ptp4l's role is 'server') | ||
|
|
||
| #option loglevel '5' # Logging verbosity for phc2sys, 5 by default, 6 if stats_interval is set | ||
|
|
||
| #option stats_interval '0' # Log status updates every N seconds (N defaults to 1 when -R param (by-default) is 1Hz). | ||
| # By default/if unset, log-level (above) will be set to 5 and these messages will not be seen | ||
|
|
||
| #list extra_args '' # For other phc2sys command line options. | ||
| # Example: list extra_args '-O 0' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/bin/sh /etc/rc.common | ||
| # Init script for phc2sys from linuxptp | ||
|
|
||
| START=55 | ||
| USE_PROCD=1 | ||
| PROG=/usr/sbin/phc2sys | ||
|
|
||
| ID=phc2sys | ||
| ID_PTP4L=ptp4l | ||
|
|
||
| log() { | ||
| local loglevel=$1; shift; local msg="$*" | ||
| logger -t phc2sys-init -p daemon.$loglevel "$msg" | ||
| } | ||
|
|
||
| make_cmdline() { | ||
| local cfg=$1 | ||
| local args dev dir loglevel ptp4l_role stats_set syncdir | ||
|
|
||
| echo $PROG | ||
|
|
||
| config_get dev $cfg "phc_device" "" | ||
| [ -z "$dev" ] && { log notice "phc_device not configured, phc2sys not starting. Set 'option phc_device' in /etc/config/linuxptp."; return 1; } | ||
| ! [ -c "$dev" ] && { log crit "PHC device '$dev' not found!"; return 1; } | ||
|
|
||
| dir='phc_to_sys' | ||
| config_get ptp4l_role $ID_PTP4L "role" "auto" | ||
| [ "$ptp4l_role" = "server" ] && dir='sys_to_phc' | ||
|
|
||
| config_get syncdir $cfg "sync_direction" "$dir" | ||
| if [ "$syncdir" = "phc_to_sys" ]; then | ||
| echo "-s $dev -w" | ||
| elif [ "$syncdir" = "sys_to_phc" ]; then | ||
| echo "-s CLOCK_REALTIME -c $dev -w -O 0" | ||
| else | ||
| log err "Invalid sync_direction '$syncdir'! valid values: 'sys_to_phc', 'phc_to_sys'"; return 1 | ||
| fi | ||
|
|
||
| echo "-m" | ||
| echo "-q" | ||
|
|
||
| config_get stats_set $cfg "stats_interval" "0" | ||
| [ "$stats_set" -ge 1 ] && echo "-u $stats_set" | ||
|
|
||
| config_get loglevel $cfg "loglevel" "5" | ||
| [ "$stats_set" -ge 1 ] && config_get loglevel $cfg "loglevel" "6" | ||
| echo "-l $loglevel" | ||
|
|
||
| config_list_foreach $cfg "extra_args" echo | ||
| } | ||
|
|
||
| service_triggers() { | ||
| procd_add_reload_trigger "linuxptp" | ||
| } | ||
|
|
||
| start_service() { | ||
| local cmdline | ||
|
|
||
| config_load linuxptp | ||
|
|
||
| cmdline=$(make_cmdline $ID) || return 1 | ||
| log info "Starting phc2sys: $cmdline" | ||
|
|
||
| procd_open_instance phc2sys | ||
| procd_set_param command $cmdline | ||
| procd_set_param stdout 1 | ||
| procd_set_param stderr 1 | ||
| procd_close_instance | ||
| } | ||
|
|
||
| stop_service() { | ||
| log info "phc2sys exiting (if running)." | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,189 @@ | ||||||||||||||||||||||||||||||
| #!/bin/sh /etc/rc.common | ||||||||||||||||||||||||||||||
| # Init script for ptp4l daemon, from linuxptp package | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| START=45 | ||||||||||||||||||||||||||||||
| USE_PROCD=1 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| PROG=/usr/sbin/ptp4l | ||||||||||||||||||||||||||||||
| HELPER=/usr/sbin/sysclock-discipline-check | ||||||||||||||||||||||||||||||
| CONFIGFILE=/var/etc/ptp4l.conf | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID=ptp4l | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| log() { | ||||||||||||||||||||||||||||||
| local loglevel=$1; shift; local msg="$*" | ||||||||||||||||||||||||||||||
| logger -t ptp4l-init -p daemon.$loglevel "$msg" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| is_clock_disciplined() { | ||||||||||||||||||||||||||||||
| local output rc | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ! [ -x "$HELPER" ]; then | ||||||||||||||||||||||||||||||
| echo "Helper $HELPER not found or not executable." >&2 | ||||||||||||||||||||||||||||||
| echo "Error: Clock sync helper tool missing." | ||||||||||||||||||||||||||||||
| return 2 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| output=$($HELPER) | ||||||||||||||||||||||||||||||
| rc=$? | ||||||||||||||||||||||||||||||
| echo $output | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| [ $rc -eq 2 ] && log err "ERROR: $HELPER call unsuccessful (rc=$rc): $output" | ||||||||||||||||||||||||||||||
| return $rc | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| wait_disciplined() { | ||||||||||||||||||||||||||||||
| local check_msg interval is_synced=0 max_tries rc role tries=0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get role $ID "role" "" | ||||||||||||||||||||||||||||||
| config_get interval $ID "clock_sync_check_interval" "15" | ||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Generated by Claude Code |
||||||||||||||||||||||||||||||
| config_get max_tries $ID "clock_sync_max_tries" "8" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| log info "Preparing to start with role:$role -> checking if system clock is disciplined..." | ||||||||||||||||||||||||||||||
| while [ $is_synced -eq 0 ]; do | ||||||||||||||||||||||||||||||
| tries=$((tries + 1)) | ||||||||||||||||||||||||||||||
| check_msg=$(is_clock_disciplined); rc=$? | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if [ $rc -eq 0 ]; then | ||||||||||||||||||||||||||||||
| is_synced=1 | ||||||||||||||||||||||||||||||
| log info "sysclock-discipline-check: $check_msg. Continuing." | ||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||
| elif [ $rc -eq 1 ]; then | ||||||||||||||||||||||||||||||
| if [ "$max_tries" -gt 0 ] && [ "$tries" -ge "$max_tries" ]; then | ||||||||||||||||||||||||||||||
| log err "Clock sync wait timed out after $tries attempts. ptp4l will NOT start." | ||||||||||||||||||||||||||||||
| log err "Increase 'clock_sync_max_tries' or set 'require_clock_sync 0' to skip." | ||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+56
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bounding the wait does fix the So a The idiomatic OpenWrt hook for "retry once the clock is good" is the ntp hotplug event: sysntpd passes Minor, while in this block: with the documented Generated by Claude Code |
||||||||||||||||||||||||||||||
| if [ "$max_tries" -gt 0 ]; then | ||||||||||||||||||||||||||||||
| log info "sysclock-discipline-check: $check_msg. Waiting... ($tries/$max_tries)" | ||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||
| log info "sysclock-discipline-check: $check_msg. Waiting... (attempt $tries, unlimited)" | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||
| log crit "Clock sync check FAILED: $check_msg." | ||||||||||||||||||||||||||||||
| log err "ptp4l will NOT start. Resolve issue, or set 'require_clock_sync' to 0" | ||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
| sleep $interval | ||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+68
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This loop has no upper bound: as long as the helper keeps returning 1 ( That was survivable while the procd instance was registered before the wait. Now that the Bounding the wait would keep the guard: a max attempt count or total deadline, after which it logs and Generated by Claude Code |
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| handle_interface() { | ||||||||||||||||||||||||||||||
| local cfg=$1 delay_mechanism interface ifname transport | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get interface $cfg "interface" "" | ||||||||||||||||||||||||||||||
| [ -z "$interface" ] && { log err "Required 'interface' option missing in 'ptp_interface' section"; exit 1; } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| network_get_device ifname "$interface" | ||||||||||||||||||||||||||||||
| [ -z "$ifname" ] && { log err "Cannot resolve UCI interface '$interface' to kernel-compatible ifname."; exit 1; } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get transport $cfg "transport" "UDPv4" | ||||||||||||||||||||||||||||||
| config_get delay_mechanism $cfg "delay_mechanism" "E2E" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||
| echo "[$ifname]" | ||||||||||||||||||||||||||||||
| [ "$transport" != "UDPv4" ] && echo "network_transport $transport" | ||||||||||||||||||||||||||||||
| [ "$delay_mechanism" != "E2E" ] && echo "delay_mechanism $delay_mechanism" | ||||||||||||||||||||||||||||||
| config_list_foreach $cfg "interface_opts" echo | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| handle_global() { | ||||||||||||||||||||||||||||||
| local cfg=$1 role | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get role $cfg "role" "auto" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| echo "[global]" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| case "$role" in | ||||||||||||||||||||||||||||||
| server) printf "serverOnly 1\n";; | ||||||||||||||||||||||||||||||
| client) printf "clientOnly 1\n";; | ||||||||||||||||||||||||||||||
| auto) printf "";; | ||||||||||||||||||||||||||||||
| *) log err "Invalid role: $role! valid values: 'auto', 'client', 'server'"; return 1;; | ||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_list_foreach $cfg "global_opts" echo | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| make_configfile() { | ||||||||||||||||||||||||||||||
| local cfg=$1 iface_count rc | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| . /lib/functions/network.sh | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| mkdir -p "${CONFIGFILE%/*}" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||
| handle_global $cfg || exit 1 | ||||||||||||||||||||||||||||||
| config_foreach handle_interface ptp_interface | ||||||||||||||||||||||||||||||
| ) > "$CONFIGFILE" | ||||||||||||||||||||||||||||||
|
Comment on lines
+110
to
+117
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Generated by Claude Code |
||||||||||||||||||||||||||||||
| rc=$? | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| [ $rc -ne 0 ] && return 1 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Require at least one [interface] section beyond [global] | ||||||||||||||||||||||||||||||
| iface_count=$(grep -c '^\[' "$CONFIGFILE" 2>/dev/null) | ||||||||||||||||||||||||||||||
| if [ "${iface_count:-0}" -lt 2 ]; then | ||||||||||||||||||||||||||||||
| log notice "No PTP interfaces configured. Add a 'config ptp_interface' section to /etc/config/linuxptp." | ||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| make_cmdline() { | ||||||||||||||||||||||||||||||
| local cfg=$1 loglevel | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get loglevel $cfg "loglevel" "6" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| echo $PROG | ||||||||||||||||||||||||||||||
| echo "-l $loglevel" | ||||||||||||||||||||||||||||||
| echo "-f $CONFIGFILE" | ||||||||||||||||||||||||||||||
| echo "-m" | ||||||||||||||||||||||||||||||
| echo "-q" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_list_foreach $cfg "extra_args" echo | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| service_triggers() { | ||||||||||||||||||||||||||||||
| procd_add_reload_trigger "linuxptp" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| start_service() { | ||||||||||||||||||||||||||||||
| local clocksync_wanted cmdline rc role should_have_disciplined_clock=0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_load linuxptp | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Fast pre-check: fail immediately if no ptp_interface section carries a | ||||||||||||||||||||||||||||||
| # non-empty 'interface' option, before spending minutes in the clock-sync wait below. | ||||||||||||||||||||||||||||||
| if [ -z "$(uci -q get linuxptp.@ptp_interface[0].interface)" ]; then | ||||||||||||||||||||||||||||||
| log notice "No ptp_interface section with an 'interface' option configured in /etc/config/linuxptp. ptp4l will not start." | ||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| config_get role $ID "role" "auto" | ||||||||||||||||||||||||||||||
| [ "$role" = "server" ] && should_have_disciplined_clock=1 | ||||||||||||||||||||||||||||||
| config_get_bool clocksync_wanted $ID "require_clock_sync" "$should_have_disciplined_clock" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if [ "$clocksync_wanted" = 1 ]; then | ||||||||||||||||||||||||||||||
| wait_disciplined || return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| make_configfile $ID; rc=$? | ||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new "no PTP interfaces configured" check is the cheapest validation in Concretely: an admin sets Running Generated by Claude Code |
||||||||||||||||||||||||||||||
| if [ $rc -ne 0 ]; then | ||||||||||||||||||||||||||||||
| log err "Failed to generate $CONFIGFILE. Aborting." | ||||||||||||||||||||||||||||||
| rm -f "$CONFIGFILE" | ||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| cmdline=$(make_cmdline $ID) | ||||||||||||||||||||||||||||||
| log info "Starting ptp4l: $cmdline" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| procd_open_instance "ptp4l" | ||||||||||||||||||||||||||||||
| procd_set_param command $cmdline | ||||||||||||||||||||||||||||||
| procd_set_param file $CONFIGFILE | ||||||||||||||||||||||||||||||
| procd_set_param stdout 1 | ||||||||||||||||||||||||||||||
| procd_set_param stderr 1 | ||||||||||||||||||||||||||||||
| procd_close_instance | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| stop_service() { | ||||||||||||||||||||||||||||||
| rm -f "$CONFIGFILE" | ||||||||||||||||||||||||||||||
| log info "ptp4l exiting (if running)" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* | ||
| * Helper utility to query the kernel for the synchronization status of the | ||
| * system clock (CLOCK_REALTIME) via adjtimex(). Used by the ptp4l init script | ||
| * to delay startup in server mode until the clock is known to be accurate. | ||
| * | ||
| * Exit codes: 0 = synchronized, 1 = unsynchronized, 2 = error | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <sys/timex.h> | ||
|
|
||
| int main(void) { | ||
| struct timex txc; | ||
|
|
||
| memset(&txc, 0, sizeof(txc)); | ||
|
|
||
| if (adjtimex(&txc) < 0) { | ||
| perror("adjtimex failed"); | ||
| return 2; | ||
| } | ||
|
|
||
| if (txc.status & STA_UNSYNC) { | ||
| fprintf(stdout, "Clock status: 0x%04X (STA_UNSYNC is SET - Unsynchronized)\n", (unsigned int)txc.status); | ||
| return 1; | ||
| } else { | ||
| fprintf(stdout, "Clock status: 0x%04X (STA_UNSYNC is CLEAR - Synchronized)\n", (unsigned int)txc.status); | ||
| return 0; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit message says the config change makes it so "services do not auto-start on upgrade without explicit admin opt-in", but that only gates ptp4l. This
config phc2syssection is still active and every option in it has a working fallback:phc_devicedefaults to/dev/ptp0at phc2sys.init:22-23 andsync_directiondefaults tophc_to_sysat phc2sys.init:25-29.default_postinst()at functions.sh:401-410 runs"$i" startfor every init script the package ships, and thePKG_UPGRADEguard there covers onlyenable, notstart— so on any box that has a PHC, both installing and upgrading linuxptp starts phc2sys.The combination is worse than before this commit rather than better: ptp4l is now the daemon that refuses to start (no interface configured), so phc2sys ends up slewing
CLOCK_REALTIMEfrom a free-running, undisciplined NIC PHC, competing with whatever sysntpd/ntpd the box already runs. Previously at least ptp4l was disciplining that PHC.Gating phc2sys the same way would make the commit message's claim true for both daemons — e.g. drop the
/dev/ptp0default so an unsetphc_deviceis a hard "not configured", or add an explicitoption enabledthat both init scripts check.Generated by Claude Code