# Install ```bash sudo apt install gpsd gpsd-clients pps-tools chrony linuxptp ``` # GPSD change */etc/default/gpsd* to have ```bash # Default settings for the gpsd init script and the hotplug wrapper. # Start the gpsd daemon automatically at boot time START_DAEMON="true" # Use USB hotplugging to add new USB devices automatically to the daemon USBAUTO="true" # Devices gpsd should collect to at boot time. # They need to be read/writeable, either by user gpsd or the group dialout. DEVICES="/dev/ttyAMA0 /dev/pps0" # Other options you want to pass to gpsd GPSD_OPTIONS="-n" ``` and then restart gpsd.service # Chrony The PTP server can also be used to server NTP edit /etc/chrony.conf to have the following ```bash # This directive specifies the location of the file containing ID/key pairs for # NTP authentication. keyfile /etc/chrony/chrony.keys # This directive specifies the file into which chronyd will store the rate # information. driftfile /var/lib/chrony/chrony.drift # Save NTS keys and cookies. ntsdumpdir /var/lib/chrony # Uncomment the following line to turn logging on. #log tracking measurements statistics # Log files location. logdir /var/log/chrony # Stop bad estimates upsetting machine clock. maxupdateskew 100.0 # This directive enables kernel synchronisation (every 11 minutes) of the # real-time clock. Note that it can't be used along with the 'rtcfile' directive. rtcsync # Step the system clock instead of slewing it if the adjustment is larger than # one second, but only in the first three clock updates. makestep 1 3 # Get TAI-UTC offset and leap seconds from the system tz database. # This directive must be commented out when using time sources serving # leap-smeared time. leapseclist /usr/share/zoneinfo/leap-seconds.list # Include configuration files found in /etc/chrony/conf.d. #confdir /etc/chrony/conf.d # ACL # I have set it to RFC1918 because I'm using my firewall to explicitly allow access to NTP server allow 192.168.0.0/16 allow 10.0.0.0/8 allow 172.16.0.0/12 # Explicitly tell clients that we are stratum 1 local stratum 1 # Onboard GPS clock #refclock SHM 0 refid NMEA offset 0.000 precision 1e-3 poll 3 noselect refclock SHM 0 refid NMEA offset 0.0 precision 1e-1 poll 3 noselect refclock PPS /dev/pps0 refid PPS lock NMEA poll 3 ``` then restart chrony.service # PTP sudo mv /etc/linuxptp/ptp4l.conf /etc/linuxptp/ptp4l.conf.original Then edit the ptp4l.conf file sudo vim /etc/linuxptp/ptp4l.conf ```bash [global] verbose 1 # Use NIC hardware timestamping / PHC time_stamping hardware # PTP domain domainNumber 0 # Normal IEEE 1588 over UDP/IPv4 network_transport UDPv4 delay_mechanism E2E # Force this node to serve, not become a client/slave (won't revert to slave). serverOnly 1 # BMCA priority; lower wins priority1 128 priority2 128 # Advertise GNSS/PPS-backed grandmaster quality # clockClass=6 for GNSS reference # other classes = https://documentation.nokia.com/srlinux/24-10/books/network-synchronization/ieee-1588-ptp.html clockClass 6 clockAccuracy 0x23 offsetScaledLogVariance 0xFFFF # timeSource is where time comes from (this value doesn't discipline anything, it is only informational) # | Value | Meaning | Use case | # | -----: | --------------------- | --------------------------------------- | # | `0x10` | `ATOMIC_CLOCK` | Direct atomic/rubidium/cesium reference | # | `0x20` | `GPS` | GPS/GNSS-disciplined time source | # | `0x30` | `TERRESTRIAL_RADIO` | Radio time source | # | `0x40` | `PTP` | Synced from another external PTP source | # | `0x50` | `NTP` | Synced from NTP | # | `0x60` | `HAND_SET` | Manually set by human/operator | # | `0x90` | `OTHER` | Other external source | # | `0xA0` | `INTERNAL_OSCILLATOR` | Free-running/local oscillator/default | timeSource 0x20 # Useful while testing summary_interval 1 [eth0] ``` To test manually run these commands in separate windows. First run the **ptp4l** command, and then the **phc2sys** command ```bash sudo ptp4l -i eth0 -f /etc/linuxptp/ptp4l.conf -m sudo phc2sys -s CLOCK_REALTIME -c /dev/ptp0 -w --step_threshold=0.5 -m # -s CLOCK_REALTIME source = Linux system clock, disciplined by chrony/PPS # -c /dev/ptp0 destination = NIC PTP hardware clock # -w wait for ptp4l and get UTC/PTP offset from it # -m print logs ``` ## Verifying You can use the following commands to see if the PTP server works correctly. ```bash sudo pmc -u -b 0 'GET PORT_DATA_SET' sudo pmc -u -b 0 'GET GRANDMASTER_SETTINGS_NP' sudo pmc -u -b 0 'GET TIME_STATUS_NP' ``` The first command should return MASTER as portState The second command should return 0x20 as the timeSource and 0x23 as the clockAccuracy. Just like we have set in /etc/linuxptp/ptp4l.conf The third command returns the gmIdentity which is the MAC address of the NIC ## Making the PTP persistent In order to make the PTP persistent, create a systemd service sudo vim /etc/systemd/system/ptp4l-gm.service ```bash [Unit] Description=PTP grandmaster on eth0 After=network-online.target chrony.service Wants=network-online.target Requires=chrony.service [Service] Type=simple ExecStart=/usr/sbin/ptp4l -i eth0 -f /etc/linuxptp/ptp4l.conf -m Restart=always RestartSec=3 [Install] WantedBy=multi-user.target ``` and a second phyc2sys service sudo vim /etc/systemd/system/phc2sys-gm.service ```bash [Unit] Description=Sync eth0 PHC from chrony-disciplined system clock After=ptp4l-gm.service chrony.service Requires=ptp4l-gm.service chrony.service [Service] Type=simple ExecStart=/usr/sbin/phc2sys -s CLOCK_REALTIME -c /dev/ptp0 -O 37 --step_threshold=0.5 -m Restart=always RestartSec=3 [Install] WantedBy=multi-user.target ``` ### Enable the services ```bash sudo systemctl daemon-reload sudo systemctl enable --now ptp4l-gm.service sudo systemctl enable --now phc2sys-gm.service ```