Subject: Re: phc2sys - does it work?

From: Richard Cochran <[email-masked]>
Date: Sun, 26 Jul 2020 11:05:51 -0700

On Sun, Jul 26, 2020 at 12:01:05PM +0100, Russell King - ARM Linux admin wrote:
> Another solution would be to avoid running NTP on any machine intending
> to be the source of PTP time on a network, but that then brings up the
> problem that you can't synchronise the PTP time source to a reference
> time, which rather makes PTP pointless unless all that you're after is
> "all my local machines say the same wrong time."

It is clear that you can't have two services both adjusting the system
time.  For example, running ntpd and chrony on the same machine won't
work, and neither does running ntpd with 'phc2sys -a -r'.

However, if you want to use NTP as the global time source on a PTP GM,
and you have a heterogeneous collection of PHC cards, then you can run

	phc2sys -a -r -r

(note the two -r flags) and ptp4l with

	boundary_clock_jbod	1
	free_running		1
	priority1		100

for example.  After ptp4l starts, it will need to be configured as a
GM, and for that you will need to provide the kernel with the correct
TAI-UTC offset.  The ntpd program will set this offset, but
unfortunately it waits until it a very long time to do so.  You can
either wait until the kernel reports a non-zero TAI-UTC offset, or you
can script/program the start up logic when starting ptp4l.  See below
for a more or less complete example script.

Just bear in mind that, because phc2sys synchronizes the PHCs to the
NTP system time using software time stamps, there might be a time
error on the order of microseconds.

The reasoning behind the above settings is:

- phc2sys -a -r -r

  Option -a makes phc2sys pay attention to the port state from ptp4l,
  and the first -r lets it synchronize the system time from the port
  with the SLAVE role.  The second -r allows phc2sys to consider the
  system time as a time source, thus when all of the ports take the
  MASTER role, phc2sys with synchronize the PHCs to the system time.

- boundary_clock_jbod=1

  This allows ptp4l to act as a BC or GM using a set of PHCs that do
  not share the same PHC.  The assumption is that some other process
  (like phc2sys or ts2phc) looks after the PHC-to-PHC synchronization.

- free_running=1

  Since the intention is to become the GM, this prevents ptp4l from
  accidentally adjusting the PHCs in the presence of a "better" remote
  GM.

- priority1=100

  This sets a higher priority in order to let the GM win the BMCA
  election.  Still you need to take care not to install a second GM in
  the network at a higher priority.

If the GM has PHCs that are either synchronized in hardware or can be
using internal PPS signals, then the configuration should be
different.  Not sure if that applies to your setup.

HTH,
Richard

---8<---
#!/bin/sh

set -e
set -x

#
# Look here for a hacked version of this program that sets the TAI-UTC offset.
# https://github.com/richardcochran/ntpclient-2015
#
adjtimex=/usr/sbin/adjtimex

#
# Read the leapfile to get the current TAI-UTC offset
#
leapfile=$(awk -e '
{
	if ($1 == "leapfile") print $2;
}
' /etc/ntp.conf)

now=`date +%s`

# NTP/UTC conversion:
# utc = ntp - 2208988800
# ntp = utc + 2208988800

offset=$(awk -v utc_now="$now" -e '
!($1~/^\#/) {
	ntp_leapsecond_date = $1;
	utc_leapsecond_date = ntp_leapsecond_date - 2208988800;
	if (utc_leapsecond_date < utc_now) {
		current_offset = $2;
	}
}
END {
	print current_offset;
}
' $leapfile)

#
# Tell the kernel the current TAI-UTC offset.
#
$adjtimex -T $offset

#
# Tell ptp4l how to act like a Grand Master.
#
while [ 1 ]; do
	if [ -e /var/run/ptp4l ]; then
		break;
	fi
	echo Waiting for /var/run/ptp4l to appear...
	sleep 1
done
exec /usr/sbin/pmc -u -b 0 \
"set GRANDMASTER_SETTINGS_NP
clockClass 248
clockAccuracy 0xfe
offsetScaledLogVariance 0xffff
currentUtcOffset $offset
leap61 0
leap59 0
currentUtcOffsetValid 1
ptpTimescale 1
timeTraceable 1
frequencyTraceable 1
timeSource 0x50
"