Chapter 16: Understanding Timekeeping with systemd

On modern computer systems, it's vitally important to maintain accurate time. To do that, our computers obtain the current time from a time server while using some implementation of the Network Time Protocol (NTP). In this chapter, we'll look at these various implementations and discuss the pros and cons of each.

In this chapter, we will cover the following topics:

  • Understanding the importance of accurate time
  • Comparing NTP implementations
  • Understanding chrony
  • Understanding systemd-timesyncd
  • Understanding the Precision Time Protocol (PTP)

All right, it's time to get started!

Technical requirements

Timekeeping is done differently in the Ubuntu and RHEL worlds. So, we'll be using both Ubuntu Server and two AlmaLinux virtual machines to look at both of these.

Check out the following link to see the Code in Action video: https://bit.ly/3Dh4byf

Understanding the importance of accurate time

Accurate timekeeping on computers wasn't always real important. My very first computer job involved working with a pair of transistorized computers that were each the size of a refrigerator, and that had orders of magnitude less processing power than a modern smartphone. There was no hardware clock, and there was no NTP. Every time we rebooted these beasts, we just looked at our notoriously inaccurate wall clock and manually entered the time from it. Things didn't change much with the early personal computers. I mean, you still had to set the time manually, but they did eventually come with battery-powered hardware clocks that would still keep time when you shut the computers down.

Nowadays, it's critically important for computers to maintain accurate time. Scientific computing, log keeping, database updating, and financial transactions all require it. Certain security protocols, such as Kerberos, DNSSEC, and Transport Layer Security (TLS) also require it. Modern stock exchanges use automated trading bots that require it. For these reasons and others besides, mankind invented the NTP.

The basic concept of NTP is easy to understand. Every modern operating system includes an NTP client. Every time you boot your computer, the NTP client obtains the correct time from a highly accurate NTP server that's someplace on the internet. To ensure even greater time accuracy, some organizations might use a local time source, which could be either a local server or something such as a GPS clock.

There are several software implementations of NTP. Let's do a quick comparison of them.

Comparing NTP implementations

The Original Guy (OG), or reference implementation, of the NTP world is ntpd. It was created way back in the 1980s and served us well for a long time. You can use it on client machines to keep their time synchronized, or you can set it up as a time server. However, it does have several shortcomings, including numerous security problems that were found during a code audit in 2017.

The chrony implementation, which can also be used as either a client or a server, was created from scratch to fix the shortcomings of ntpd. Unlike ntpd, chrony has the following features:

  • It works well on computers that have unstable network connections or that get turned off for long periods.
  • It works better with virtual machines.
  • It can adjust itself better when the speed of the hardware clock oscillator fluctuates due to a temperature change.
  • It can achieve sub-microsecond accuracy by using hardware timestamping and a hardware reference clock.

RHEL 7 and its clones were the first Linux distros to ship with chrony instead of ntpd. The RHEL 8 and SUSE distros also use chrony by default.

Another alternative is systemd-timesyncd, which is part of the systemd ecosystem. Unlike ntpd and chrony, systemd-timesyncd is an implementation of the lighter-weight Simple Network Time Protocol (SNTP), instead of the full-blown NTP. SNTP requires less processing power, which makes it better for low-resource computers. The downside is that SNTP and systemd-timesyncd lack some of the bells and whistles that NTP has. For example, you can't use them to set up a time server, and you can't use them with either hardware timestamping or hardware reference clocks. So, you can forget about getting that good sub-microsecond accuracy with systemd-timesyncd. On the other hand, SNTP and systemd-timesyncd might be all you need for most situations. Ubuntu uses systemd-timesyncd by default, and it will work fine for you most of the time. If it doesn't, it's easy to switch your machine over to chrony.

The Precision Time Protocol (PTP) isn't an implementation of NTP. Rather, it's an entirely different protocol that's designed for extreme – and I do mean extreme – timekeeping accuracy. To use it, you must have a precision time source on the local network, and you must have switches and routers that can work with it. It uses hardware timestamping and hardware reference clocks to achieve picosecond accuracy.

Okay, that does it for our overview. Now, let's talk a bit about chrony. We'll look at it on the AlmaLinux machine since Alma uses it by default.

Understanding chrony on the AlmaLinux machine

There are two components in the chrony system. We have chronyd as the daemon and chronyc as the user interface. The chronyd component can run in either client or server mode. First, let's look at the unit file for chonyd.

The chronyd.service file

There are a few interesting things to look at in the /lib/systemd/system/chronyd.service file. In the [Unit] section, we have this:

[Unit]

Description=NTP client/server

Documentation=man:chronyd(8) man:chrony.conf(5)

After=ntpdate.service sntp.service ntpd.service

Conflicts=ntpd.service systemd-timesyncd.service

ConditionCapability=CAP_SYS_TIME

The Conflicts= line indicates that we can't run multiple NTP implementations together on the same machine. If systemd detects that either ntpd or systemd-timesyncd is running, then chronyd will fail to start. The ConditionCapability= line indicates that this service runs under a non-privileged account, even though no non-privileged user account is configured in either this unit file or in the /etc/chrony.conf file. Instead, chronyd is hardcoded to run under the non-privileged chrony account. We can confirm this with a simple ps aux command, like so:

[donnie@localhost ~]$ ps aux | grep chrony

chrony       727  0.0  0.1 128912  3588 ?        S    15:23   0:00 /usr/sbin/chronyd

donnie      1901  0.0  0.0  12112  1092 pts/0    R+   16:44   0:00 grep --color=auto chrony

[donnie@localhost ~]$

Because chronyd does run under a non-privileged user account, we need to set the CAP_SYS_TIME capability for that non-privileged user account so that it can set the system time.

Next, let's look at the [Service] section of the chronyd.service file:

[Service]

Type=forking

PIDFile=/run/chrony/chronyd.pid

EnvironmentFile=-/etc/sysconfig/chronyd

ExecStart=/usr/sbin/chronyd $OPTIONS

ExecStartPost=/usr/libexec/chrony-helper update-daemon

PrivateTmp=yes

ProtectHome=yes

ProtectSystem=full

The ExecStart= line starts chronyd with options that it obtained from the file that's referenced in the EnvironmentFile= line. If we go there, we'll see that no options have been configured:

[donnie@localhost system]$ cd /etc/sysconfig/

[donnie@localhost sysconfig]$ cat chronyd

# Command-line options for chronyd

OPTIONS=""

[donnie@localhost sysconfig]$

The chrony-helper program that's referenced in the ExecStartPost= line is a shell script that obtains the addresses of NTP servers from either a DHCP or a DNS server. At the moment, this line doesn't do anything for us. This is because chronyd is currently configured to contact a pool of NTP servers that is listed in the /etc/chrony.conf file, as shown here:

[donnie@localhost sysconfig]$ cd /etc/

[donnie@localhost etc]$ cat chrony.conf

# Use public servers from the pool.ntp.org project.

# Please consider joining the pool (http://www.pool.ntp.org/join.html).

pool 2.cloudlinux.pool.ntp.org iburst

. . .

. . .

At the bottom of the [Service] section, we can see the PrivateTmp=yes, ProtectHome=yes, and ProtectSystem=full lines, which add a measure of security.

Finally, there's the [Install] section of the chronyd.service file:

[Install]

WantedBy=multi-user.target

Okay, there's nothing exciting here. It's just the standard WantedBy= line that makes this service run in multi-user mode.

Next, let's look at the chrony.conf file.

The chrony.conf file

Most chronyd configuration is done in the /etc/chrony.conf file. (The only exception would be on those rare occasions where you might want to configure some options in the /etc/sysconfig/chronyd file.) I'm not going to cover every option in the file because you can read about them by going to the chrony.conf man page. However, I will point out a couple of things that you might need to reconfigure.

By default, chrony.conf is configured to obtain the current time from a pool of time servers that are out on the internet, as we see here:

pool 2.cloudlinux.pool.ntp.org iburst

The iburst option at the end allows chronyd to update the clock a bit faster when you first boot up the machine. Large organizations might have local timeservers to prevent all machines on their network from going out to the internet to obtain the time. In those cases, you would need to configure this line with the IP address of the local timeserver. (We'll look at this a bit later when we set up a time server.)

For increased timekeeping accuracy, you can enable hardware timestamping by removing the # symbol from the beginning of the following line:

#hwtimestamp *

The only catch is that the network interface adapters in your computer must support hardware timestamping. To verify that, use the ethtool -T command, followed by the name of your network interface adapter. Here's what that looks like on one of my old 2009-model Hewlett-Packard machines:

donnie@localhost:~> sudo ethtool -T eth1

Time stamping parameters for eth1:

Capabilities:

software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)

software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)

software-system-clock (SOF_TIMESTAMPING_SOFTWARE)

PTP Hardware Clock: none

Hardware Transmit Timestamp Modes: none

Hardware Receive Filter Modes: none

donnie@localhost:~>

Well, that's not good. There's no PTP hardware clock, and there's no hardware timestamping. Let's see if things look any better on my Dell Precision workstation, which is several years newer:

Figure 16.1 – Hardware timestamping on my Dell Precision T3610 workstation

Yes, this does look better. We see a PTP hardware clock and hardware timestamping. The bad part is that at the moment, I can't take advantage of this, because this machine is running Lubuntu Linux. Lubuntu, just like Ubuntu, runs systemd-timesyncd, which can't take advantage of hardware timestamping. But that's okay for now. If I were to ever feel the need to, I could easily switch this machine over to chrony. (I'll show you how to do that in just a bit.)

Now, let's skip to the bottom of the chrony.conf file, where we see these lines:

# Specify directory for log files.

logdir /var/log/chrony

# Select which information is logged.

#log measurements statistics tracking

Here, we can see that it's configured to store chronyd logs in the /var/log/chrony/ directory. But if we were to go there now, we'd see nothing but an empty directory. That's because the line at the bottom, which tells chronyd what information to log, is commented out. To change that, just remove the # symbol from the beginning of the line so that it now looks like this:

log measurements statistics tracking

Then, restart chronyd:

[donnie@localhost ~]$ sudo systemctl restart chronyd

[donnie@localhost ~]$

You should now see log files in the /var/log/chrony/ directory:

[donnie@localhost ~]$ cd /var/log/chrony/

[donnie@localhost chrony]$ ls -l

total 12

-rw-r--r--. 1 chrony chrony 2603 Aug 24 14:29 measurements.log

-rw-r--r--. 1 chrony chrony 1287 Aug 24 14:29 statistics.log

-rw-r--r--. 1 chrony chrony  792 Aug 24 14:29 tracking.log

[donnie@localhost chrony]$

This pretty much covers the basics. Let's get a bit fancier by setting up a chronyd time server.

Setting up a chronyd time server

For this demo, you'll need two Alma virtual machines. We'll set up one as the time server and the other to use the time server. (Ideally, we'd want the time server to have a static IP address, but we won't worry about that for now.)

On the time server machine, edit the /etc/chrony.conf file. Here's the line that you'll change:

#allow 192.168.0.0/16

Remove # from the beginning of the line and change the network address so that it matches your own. For me, the network address is correct, but the netmask is wrong. So, I'll change the line so that it looks like this:

allow 192.168.0.0/24

Next, restart chronyd:

[donnie@localhost ~]$ sudo systemctl restart chronyd

[donnie@localhost ~]$

The final step for setting up the time server is to open the appropriate firewall ports:

[donnie@localhost ~]$ sudo firewall-cmd --permanent --add-service=ntp

success

[donnie@localhost ~]$ sudo firewall-cmd --reload

success

[donnie@localhost ~]$

Now, switch over to the other Alma virtual machine and edit the /etc/chrony.conf file on it. Comment out the pool line and add a line that points to the IP address of the time server virtual machine. The two lines should now look something like this:

#pool 2.cloudlinux.pool.ntp.org iburst

server 192.168.0.14 iburst

Save the file and restart the chronyd service. When you look at the status of chronyd, you should see that this machine now obtains its time from your time server. It should look something like this:

[donnie@logserver ~]$ systemctl status chronyd

● chronyd.service - NTP client/server

   Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled)

   Active: active (running) since Tue 2021-08-24 14:59:43 EDT; 55s ago

. . .

. . .

Aug 24 14:59:48 logserver chronyd[15558]: Selected source 192.168.0.14

Aug 24 14:59:48 logserver chronyd[15558]: System clock TAI offset set to 37 seconds

[donnie@logserver ~]$

Note

Sometimes need to preface this command with sudo in order to see information about the network time sources.

That's all there is to it. Let's change gears now and look at the chronyc client utility.

Using chronyc

You can use the chronyc utility to either look at information about the chronyd service or to dynamically configure certain aspects of the chronyd service. Let's start by looking at tracking information on our time server:

[donnie@localhost ~]$ chronyc tracking

Reference ID    : 32CDF46C (50-205-244-108-static.hfc.comcastbusiness.net)

Stratum         : 3

Ref time (UTC)  : Tue Aug 24 19:16:00 2021

System time     : 0.000093940 seconds fast of NTP time

Last offset     : -0.000033931 seconds

RMS offset      : 0.000185221 seconds

Frequency       : 10909.050 ppm fast

Residual freq   : +0.002 ppm

Skew            : 0.344 ppm

Root delay      : 0.016927114 seconds

Root dispersion : 0.018588312 seconds

Update interval : 128.6 seconds

Leap status     : Normal

[donnie@localhost ~]$

Rather than go over everything here, I'm going to let you read about it by going to the chronyc man page. However, I do want to talk about the Reference ID line at the top.

The Reference ID line just tells us the hostname or the IP address of the remote time server that this local timeserver is synchronized to. We see that this local time server is synchronized to a remote time server that's operated either by Comcast or by an organization that uses Comcast hosting. Note that this remote time server is a member of the pool that's configured in the chrony.conf file.

Now, let's look at the Alma machine that we set up as a client of this local time server:

[donnie@logserver ~]$ chronyc tracking

Reference ID    : C0A8000E (192.168.0.14)

. . .

. . .

[donnie@logserver ~]$

As expected, we see the IP address of the local time server.

The sources command will show you all of the time servers that our machine can access. Here are the time servers that are in the default pool for the Alma machines:

[donnie@localhost ~]$ chronyc sources

210 Number of sources = 4

MS Name/IP address                 Stratum Poll Reach LastRx Last sample               

===============================================================================

^* 50-205-244-108-static.hf>    2   9   377   349   -551us[ -384us] +/-   43ms

^+ clock.nyc.he.net                    2   8   377    13  +1084us[+1084us] +/-   51ms

^+ t2.time.gq1.yahoo.com         2   9   377    92   +576us[ +576us] +/-   49ms

^+ linode.appus.org                   2   8   377    23   +895us[ +895us] +/-   70ms

[donnie@localhost ~]$

As before, I'll let you look at the chronyc man page to see what all the fields are.

So far, we've been able to look at everything with normal user privileges. Looking at other types of information might require sudo privileges, as we see here on the time server:

[donnie@localhost ~]$ sudo chronyc clients

[sudo] password for donnie:

Hostname                      NTP   Drop Int IntL Last     Cmd   Drop Int  Last

===============================================================================

192.168.0.7                    29      0   8   -   129        0      0   -     -

localhost                       0      0   -   -     -       8      0   8   287

[donnie@localhost ~]$

Very cool. We see the IP address of the virtual machine that we set up as a client of this local time server.

Just for fun, let's see how much work our local time server has been doing:

[donnie@localhost ~]$ sudo chronyc serverstats

NTP packets received       : 84

NTP packets dropped        : 0

Command packets received   : 20

Command packets dropped    : 0

Client log records dropped : 0

[donnie@localhost ~]$

This shows the number of NTP packets and command packets that were received from the clients.

There's a whole lot more to this command than what I can show you here. Your best bet is to read all about it by going to the chronyc man page.

That's about it for chronyd and chronyc. So, let's shift over to the Ubuntu machine and look at systemd-timesyncd.

Understanding systemd-timesyncd

Ubuntu uses systemd-timesyncd by default. It's a simple, lightweight system that's easy to configure. Before we get to that, let's take a quick look at the systemd-timesyncd.service file.

The systemd-timesyncd.service file

The [Unit] section of the /lib/systemd/system/systemd-timesyncd.service file looks like this:

[Unit]

Description=Network Time Synchronization

Documentation=man:systemd-timesyncd.service(8)

ConditionCapability=CAP_SYS_TIME

ConditionVirtualization=!container

DefaultDependencies=no

After=systemd-sysusers.service

Before=time-set.target sysinit.target shutdown.target

Conflicts=shutdown.target

Wants=time-set.target time-sync.target

Note the ConditionVirtualization=!container line. The ConditionVirtualization= part checks to see if the operating system is running in a virtualized environment. In this case, it wants to see whether it's running in a container. The ! in front of container denotes a negation. In other words, if systemd detects that this operating system is running in a container, then the systemd-timesyncd service won't start.

In the [Service] section, you'll see a lot more security-related parameters than you saw in the chronyd.service file on the Alma machine. There are so many that I can only show you some of them here:

[Service]

AmbientCapabilities=CAP_SYS_TIME

CapabilityBoundingSet=CAP_SYS_TIME

ExecStart=!!/lib/systemd/systemd-timesyncd

LockPersonality=yes

MemoryDenyWriteExecute=yes

NoNewPrivileges=yes

. . .

. . .

SystemCallFilter=@system-service @clock

Type=notify

User=systemd-timesync

WatchdogSec=3min

This makes sense, considering that Ubuntu uses AppArmor as its mandatory access control system instead of SELinux, which is what the Alma machine uses. A default configuration of AppArmor doesn't provide near as much protection as a default configuration of SELinux, so it makes sense to include more security directives in this service file. Also, note the User=systemd-timesync line, which configures the non-privileged user account for this service.

The [Install] section is a bit different from what we're used to:

[Install]

WantedBy=sysinit.target

Alias=dbus-org.freedesktop.timesync1.service

Instead of getting started as part of multi-user.target, systemd-timesyncd gets started as part of sysinit.target. So, it gets started much earlier in the boot process.

Next, let's briefly look at how to configure systemd-timesyncd.

The timesyncd.conf file

When I said that we'll briefly cover this, I really did mean briefly. That's because there's not a whole lot to configure. Here's the entirety of the /etc/systemd/timesyncd.conf file:

[Time]

#NTP=

#FallbackNTP=ntp.ubuntu.com

#RootDistanceMaxSec=5

#PollIntervalMinSec=32

#PollIntervalMaxSec=2048

Everything is commented out, which means that everything is set with its default values. The first thing to notice is that there's nothing set for the NTP= line and that the FallbackNTP= line points to a pool of time servers at ntp.ubuntu.com. So, this machine will only obtain its time from one of the time servers that's in that pool. The remaining three parameters are set with sane values that you'll likely never have to change. (I'll let you read about them in the timesyncd.conf man page.)

That's enough about this file for now. Now, let's look at a couple of timedatectl options.

Using timedatectl

Two timedatectl viewing options are specific to systemd-timesyncd. The timesync-status option looks like this:

donnie@ubuntu2004-staticip:/etc/systemd$ timedatectl timesync-status

       Server: 91.189.94.4 (ntp.ubuntu.com)

Poll interval: 32s (min: 32s; max 34min 8s)

         Leap: normal                      

      Version: 4                           

      Stratum: 2                           

    Reference: 8CCBCC4D                    

    Precision: 1us (-23)                   

Root distance: 45.074ms (max: 5s)          

       Offset: -336.094ms                  

        Delay: 101.668ms                   

       Jitter: 1.560ms                     

Packet count: 214                         

    Frequency: -500.000ppm                 

donnie@ubuntu2004-staticip:/etc/systemd$

At the top, we see the remote time server that this machine accesses, and we see that it's a member of the ntp.ubunutu.com pool. Further down, we see that Rootdistance from the time servers comes in at 45.07 milliseconds, which is well within the five seconds that's set in the timesyncd.conf file.

The other timedatectl option is show-timesync, which looks something like this:

donnie@ubuntu2004-staticip:~$ timedatectl show-timesync

FallbackNTPServers=ntp.ubuntu.com

ServerName=ntp.ubuntu.com

ServerAddress=91.189.89.198

RootDistanceMaxUSec=5s

PollIntervalMinUSec=32s

PollIntervalMaxUSec=34min 8s

PollIntervalUSec=32s

NTPMessage={ Leap=0, Version=4, Mode=4, Stratum=2, Precision=-23, RootDelay=1.129ms, RootDispersion=30.349ms, Reference=11FD227B, OriginateTimestamp=Tue 2021-08-24 17:16:48 EDT, ReceiveTimestamp=Tue 2021-08-24 17:16:48 EDT, TransmitTimestamp=Tue 2021-08-24 17:16:48 EDT, DestinationTimestamp=Tue 2021-08-24 17:16:48 EDT, Ignored=no PacketCount=1, Jitter=0 }

Frequency=-32768000

donnie@ubuntu2004-staticip:~$

This shows the same information that's in the timesync-status option, except that it's now in a machine-readable format.

Next, let's edit the /etc/systemd/timesyncd.conf file so that this machine will obtain its time from our local AlmaLinux time server. We'll just uncomment the #NTP= line and add the IP address of the Alma machine. It should now look something like this:

NTP=192.168.0.14

After restarting the systemd-timesyncd service, we should see that this machine now obtains its time from our local time server, as we see here:

donnie@ubuntu2004-staticip:~$ timedatectl timesync-status

       Server: 192.168.0.14 (192.168.0.14)

Poll interval: 32s (min: 32s; max 34min 8s)

         Leap: normal                      

      Version: 4                           

      Stratum: 3                           

    Reference: 32CDF46C                    

    Precision: 1us (-25)                   

Root distance: 27.884ms (max: 5s)          

       Offset: -279.517ms                  

        Delay: 470us                       

       Jitter: 0                           

Packet count: 1                           

    Frequency: -500.000ppm                 

donnie@ubuntu2004-staticip:~$

There's an excellent chance that systemd-timedatectl is all you'll ever need. But what if you really need the extra features and precision that come with chrony? Well, let's see if we can switch our Ubuntu machine over to chrony.

Configuring Ubuntu to use chrony

The first step is to stop and disable systemd-timesyncd, like this:

donnie@ubuntu2004-staticip:~$ sudo systemctl disable --now systemd-timesyncd

Removed /etc/systemd/system/dbus-org.freedesktop.timesync1.service.

Removed /etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service.

donnie@ubuntu2004-staticip:~$

Now, install the chrony package, like this:

donnie@ubuntu2004-staticip:~$ sudo apt install chrony

Since this is Ubuntu, the chronyd service will be enabled and started automatically when the installation completes. The only difference from what you saw on the Alma machine is that the chrony.conf file on Ubuntu is in the /etc/chrony/ directory.

Sometimes, you just need to be precise. So, let's talk a bit about PTP.

Understanding the Precision Time Protocol

For many financial, scientific, and enterprise applications, you've just got to have the most accurate time possible. In these instances, getting the time from a remote time server on the Internet just doesn't meet your needs. So, you need something better. With proper hardware, PTP can keep your network time synchronized to picosecond accuracy. The whole explanation of PTP is rather complex, so allow me to simplify things a bit.

An overview of PTP

Unlike NTP, PTP cannot obtain its time from a remote time server that's out on the internet. Instead, PTP can only be used within a Local Area Network (LAN) and will obtain its time from a local source. This local time source, which is usually called the Grandmaster Clock, will most likely obtain its time from a Global Positioning System (GPS) satellite, and will then synchronize the clocks on the other network devices to the GPS time. To do this, the Grandmaster Clock sends sync messages out to the network. The client devices will respond by sending back delay request messages, and the Grandmaster Clock will respond with delay response messages. The network packets that carry these messages all have timestamps that will be used in the calculations for figuring out how to adjust the time on the network devices. To make this all work, your network must be set up with switches and routers that can transfer these messages.

In addition to the Grandmaster Clock, there are three other types of clocks that can be found on a PTP network:

  • Ordinary clocks: These clocks are on the end user devices such as servers, desktop clients, IoT devices, and so forth.
  • Transparent clocks: These are the network switches that transfer the messages between the Grandmaster Clock and the ordinary clocks. Transparent clocks can't send messages beyond their VLAN boundaries.
  • Boundary clocks: These are optional and are only needed if you need to divide your network into different VLANs. Instead of just transferring messages between the Grandmaster and the ordinary clocks, a boundary clock synchronizes with the Grandmaster, and then sends out sync messages to the ordinary clocks on its VLAN. The advantage of using boundary clocks is that it helps prevent the Grandmaster from getting overwhelmed with delay request messages.

It is possible to set up a Linux server as a boundary clock, but you probably won't. Most likely, your organization will obtain its transparent clocks and boundary clocks from its preferred network equipment vendor, such as Cisco or Juniper. So, how would you use PTP with Linux? Mostly, you'd just set up PTP on your servers, desktop machines, and IoT devices so that they would obtain their time from a PTP server rather than from an NTP server. Let's check it out.

Installing PTP

To set up either a Linux server, a Linux desktop, or a Linux IoT device to obtain its time from a PTP source, you'll have to install the linuxptp package. On the Alma machine, you'd do:

[donnie@logserver ~]$ sudo dnf install linuxptp

On the Ubuntu machine, you'd do:

donnie@ubuntu2004:~$ sudo apt install linuxptp

Next, stop and disable whichever timekeeping service your machine is running. If your machine is running chroynd, the command would be:

[donnie@logserver ~]$ sudo systemctl disable --now chronyd

If your machine is running systemd-timesyncd, the command would be:

donnie@ubuntu2004:~$ sudo systemctl disable --now systemd-timesyncd

Installing the linuxptp package installs two different services, which are the ptp4l service and the phc2sys service. Before we can enable or start the PTP services, we'll need to configure them. Let's look at how to do this on the Alma machine.

Configuring PTP with software timestamping on AlmaLinux

The first step is to edit the /etc/sysconfig/ptp4l file. When you first open the file, you'll see this:

OPTIONS="-f /etc/ptp4l.conf -i eth0"

This default configuration is for a master server, and it has the wrong network adapter name. We'll add the -s option to make this run in client mode and change the network adapter's name. You won't have hardware timestamping available on your virtual machines, even if it is available on the network adapter of your host computer. To deal with that, we'll also add the -S option to make it use software timestamping. The edited line should look something like this:

OPTIONS="-f /etc/ptp4l.conf -S -s -i enp0s3"

(Of course, use your own network adapter's name in place of mine.)

Now, enable and start the ptp4l service:

[donnie@logserver ~]$ sudo systemctl enable --now ptp4l

The service does run, even though there's no PTP time source on my network. Regardless, the last line of the systemctl status output shows that the ptp4l service has selected the best master clock. I have no idea where that clock is, but it doesn't matter. In a real-life scenario, you would know because you'd be dealing with a real clock:

[donnie@logserver ~]$ systemctl status ptp4l

● ptp4l.service - Precision Time Protocol (PTP) service

   Loaded: loaded (/usr/lib/systemd/system/ptp4l.service; enabled; vendor preset: disabled)

   Active: active (running) since Wed 2021-08-25 18:16:26 EDT; 8s ago

Main PID: 1841 (ptp4l)

    Tasks: 1 (limit: 4938)

   Memory: 276.0K

   CGroup: /system.slice/ptp4l.service

           └─1841 /usr/sbin/ptp4l -f /etc/ptp4l.conf -S -s -i enp0s3

. . .

. . .

Aug 25 18:16:33 logserver ptp4l[1841]: [5697.998] selected local clock 080027.fffe.94a66f as best master

[donnie@logserver ~]$

Okay, we're good with the software timestamping. Now, let's look at hardware timestamping.

Configuring PTP with hardware timestamping on AlmaLinux

Using hardware timestamping gives you the most precise timekeeping that you can get. The only catch is that the network interface adapters on your machine have to be capable of doing hardware timestamping. Fortunately, that shouldn't be a problem with newer computers. (In the Understanding chrony section, I showed you how to verify whether your network adapter does support hardware timestamping.)

The first step is to edit the /etc/sysconfig/ptp4l file, as you did previously. This time, leave out the -S option so that the edited line looks like this:

OPTIONS="-f /etc/ptp4l.conf -s -i enp0s3"

Next, you'll need to configure and enable the phc2sys service so that the computer clock can synchronize with the PTP hardware clock that's in the network adapter. The first step is to configure the /etc/sysconfig/phc2sys file. By default, the file looks like this:

OPTIONS="-a -r"

Change that line so that it looks something like this:

OPTIONS="-c CLOCK_REALTIME -s enp0s3 -w"

Here's the breakdown:

  • -c CLOCK_REALTIME: The -c option specifies the clock that is to be synchronized. CLOCK_REALTIME is the normal computer clock.
  • -s enp0s3: In this file, -s specifies the device that will be used for synchronization. In this case, we're using the PTP hardware clock that's in the enp0s3 network adapter to synchronize the normal system clock.
  • -w: This tells the phc2sys service to wait until the ptp4l service is in a synchronized state before attempting to synchronize the system clock.

The final step is to restart the ptp4l service and to enable and start the phc2sys service. Note that this will fail on your virtual machine because the VirtualBox network adapter doesn't have a PTP hardware clock. When you've seen what you need to see, disable the ptp4l and phc2sys services and re-enable the chronyd service.

Next, let's look at how to do all of this on Ubuntu.

Configuring PTP with software timestamping on Ubuntu

There are no supplementary PTP configuration files on Ubuntu, so you'll need to edit the ptp4l.service file. Start by doing:

donnie@ubuntu2004:~$ sudo systemctl edit --full ptp4l

In the [Service] section, you'll need to change the ExecStart line, which looks like this:

ExecStart=/usr/sbin/ptp4l -f /etc/linuxptp/ptp4l.conf -i eth0

Change it so that it looks something like this:

ExecStart=/usr/sbin/ptp4l -f /etc/linuxptp/ptp4l.conf -S -s -i enp0s3

Finally, enable and start the ptp4l service, as you did previously on the Alma machine.

Now, let's wrap this up by configuring hardware timestamping on Ubuntu.

Configuring PTP with hardware timestamping on Ubuntu

Again, start by editing the ptp4l.service file. This time, enable hardware timestamping by leaving out the -S option so that the ExecStart line will look like this:

ExecStart=/usr/sbin/ptp4l -f /etc/linuxptp/ptp4l.conf -s -i enp0s3

Next, edit the phc2sys.service file by doing:

donnie@ubuntu2004:~$ sudo systemctl edit --full phc2sys

In the [Service] section, make the ExecStart line look something like this:

ExecStart=/usr/sbin/phc2sys -c CLOCK_REALTIME -s enp0s3 -w

The final step is to restart the ptp4l service and to enable and start the phc2sys service. Alas, that will also fail this time, due to not having the PTP hardware clock in the VirtualBox network adapter. When you've seen what you want to see, change the virtual machine back to whichever timekeeping service that you were using before.

All right, that's it for timekeeping. I think it's time to wrap this baby up.

Summary

As always, we've covered a lot of ground and had a bit of fun in the process. We started by discussing why accurate timekeeping is so important and then did a quick overview of the various implementations of timekeeping software. We then took a detailed look at chrony and systemd-timesyncd. We wrapped up with a quick look at PTP.

In the next chapter, we'll look at systemd's relationship with boot managers and bootloaders. I'll see you there.

Questions

Answer the following questions to test your knowledge of this chapter:

  1. In the chrony.conf file, which of the following lines will allow chronyd to function as a time server?

    A. network 192.168.0.0/24

    B. allow 192.168.0.0/24

    C. permit 192.168.0.0/24

    D. listen 192.168.0.0/24

  2. How would you set up systemd-timesyncd to function as a time server? (We will assume that we're on the 192.168.0.0/24 network.)

    A. Add a network 192.168.0.0/24 line to the timesyncd.conf file.

    B. Add a permit 192.168.0.0/24 line to the timesyncd.conf file.

    C. Add an allow 192.168.0.0/24 line to the timesyncd.conf file.

    D. You can't.

  3. For dealing with PTP, which of the following clock types allows messages to flow between the PTP master clock and the client machines on the same VLAN?

    A. Boundary clocks

    B. Grandmaster clocks

    C. Router clocks

    D. Transparent clocks

  4. When dealing with PTP, which service causes a machine's system clock to synchronize with the PTP hardware clock in the network adapter?

    A. phc2sys

    B. ptp4l

    C. ptp

    D. clock

Answers

  1. B
  2. D
  3. D
  4. A

Further reading

To learn more about the topics covered in this chapter, take a look at the following resources:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.23.130