Skip to main content
  1. Posts/

PTP from scratch: from switch to OpenShift configuration

·11 mins
ptp openshift kubernetes
Teresa Giner Blog
Author
Teresa Giner Blog
Open Source enthusiast
Table of Contents

What would you do if you were given a new Arista ToR switch and a baremetal Openshift cluster and had to configure PTP on some of the nodes?

Well, if you had no idea at all of what the Precision Time Protocol is (as I had) you would start by checking out the Arista vendor instructions to enable it in the node interfaces and would finally turn to the PTP Operator documentation in Openshift to learn how to configure its CRDs. That is also what I did, so check it out!

Boundary Clock introduction #

There are two levels of configuration: global configuration at the switch level and interface configuration.

Global configuration includes general parameters for the ptp to be configured. Interface configuration includes specific interfaces where PTP packets will be received (Slave) and sent (Master).

When the switch acts as a boundary clock, there are two interfaces playing a role in PTP: a slave interface, that will read the clock timestamp from the PTP cable; and master interfaces, that will act as a grandmaster clock to other server’s slave interface.

Global switch configuration #

First, initial commands to configure ptp domain, priority, mode, and profile.

tor-sw-210#config
tor-sw-210(config)# ptp domain 24
tor-sw-210(config)# ptp profile g8275.1
tor-sw-210(config)# ptp mode boundary
tor-sw-210(config)# exit

Check the running configuration shows it corrrectly

tor-sw-210# show ptp | grep ptp
ptp domain 24
ptp local-priority 200
ptp mode boundary
ptp profile g8275.1

Slave interface configuration #

Then, configure each interface as desired.

Note: Et13/1 was already configured at the article initial point. GPS Cable was connected to Et13/1 and therefore switch is Slave, reads the hardware timestamp in this interface and acts as Slave for the GrandMaster clock at the other side of the cable.

interface Ethernet13/1
   description "uplink to core ptp switch"
   speed forced 10000full
   switchport access vlan 3
   ptp enable
   ptp transport layer2
tor-sw-210#show ptp
PTP Mode: Boundary Clock
PTP Profile: G8275.1
Clock Identity: 0x94:8e:d3:ff:ff:ed:a1:89
Grandmaster Clock Identity: 0x00:b0:ae:ff:fe:07:6f:b8
Number of slave ports: 1
Number of master ports: 1
Slave port: Ethernet13/1
Offset From Master (nanoseconds): 7
Mean Path Delay (nanoseconds): 179
Steps Removed: 2
Skew (estimated local-to-master clock frequency ratio): 1.0000052959672074
Last Sync Time: 15:05:36 UTC Aug 25 2023
Current PTP System Time: 15:05:36 UTC Aug 25 2023
   Interface       State        Transport    Delay    
                                             Mechanism
--------------- ------------ --------------- --------- 
   Et13/1          Slave        layer2       e2e

A specific vlan for PTP was also already given.

vlan 3, named ptp_vlan, was configured in Et13/1

tor-sw-210(config)#show vlan
VLAN  Name          Status    Ports
----- ------------------------------------
1     default        active    Et1/1, Et1/2, Et1/4, Et2/1
                               Et2/2, Et2/4, Et3/1, Et3/2
                               Et3/4, Et4/1, Et4/2, Et4/4
                               Et5/2, Et5/4, Et7/1, Et7/2
                               Et7/3, Et7/4, Et8/2, Et8/3
                               Et8/4, Et9/1, Et9/2, Et9/3
                               Et9/4, Et10/1, Et10/2, Et10/3
                               Et10/4, Et11/2, Et11/4, Et12/1
                               Et12/4, Et18/1, Et19/1, Et20/1
                               Et22/1, Et23/1, Et24/1, Et26/1
                               Et27/1, Et28/1, Et30/1, Et31/1
                               Et32/1
3     ptp_vlan       active    Et13/1

PTP protocol can go through both IPv4 or Layer 2. When done through IPv4, a source ip address must be defined in the ptp global configuration.

When done through Layer 2, do not define source ip address. IP level won’t be used.

Use ptp transport layer 2 as an option to each interface

Master interface configuration #

Let’s first test PTP Conectivity with RAN worker 2.

Let’s match the server MAC Addresses to the Switch Interfaces:

sh-4.4# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN m
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens1f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP 
    link/ether b4:96:91:c8:74:b0 brd ff:ff:ff:ff:ff:ff
3: ens5f0np0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
    link/ether 88:e9:a4:45:e3:c6 brd ff:ff:ff:ff:ff:ff
4: ens1f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
    link/ether b4:96:91:c8:74:b1 brd ff:ff:ff:ff:ff:ff
5: ens5f1np1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
    link/ether 88:e9:a4:45:e3:c7 brd ff:ff:ff:ff:ff:ff
    altname enp132s0f1np1
6: ens10f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether b4:96:91:d6:c4:64 brd ff:ff:ff:ff:ff:ff
    altname enp72s0f0
7: ens4f0np0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master ovs-system state UP group default qlen 1000
    link/ether 88:e9:a4:45:04:c6 brd ff:ff:ff:ff:ff:ff
    altname enp162s0f0np0
tor-sw-210#show mac address-table
          Mac Address Table
------------------------------------------------------------------

Vlan    Mac Address       Type        Ports      Moves   Last Move
----    -----------       ----        -----      -----   ---------
   1    3cec.ef79.7b07    DYNAMIC     Et12/4     1       0:10:01 ago
   1    3cec.ef79.7b08    DYNAMIC     Et12/1     1       0:11:22 ago
   1    88e9.a445.0497    DYNAMIC     Et30/1     1       0:07:12 ago
   1    88e9.a445.049a    DYNAMIC     Et31/1     1       0:07:12 ago
   1    b496.91c8.74b0    DYNAMIC     Et8/1      1       0:07:12 ago
  27    88e9.a445.04c6    DYNAMIC     Et21/1     1       19:23:56 ago

And now, check the DNS DHCP server config file to find the Openshift baremetal network interface being already used.

dhcp-host=88:e9:a4:45:04:c6,192.168.27.73,<ptpnode>.domain.com

With all this information, we have now two different options: share the same interface for both cluster- and PTP network, which is on the one hand a good idea not to dedicate a high throughput interface only for PTP traffic; or, on the other hand, having unused extra interfaces it may be interesting to separate the traffic and leave the cluster network isolated.

In our case, this last alternative made more sense, so the following configuration will be applied:

Same workerInterfaceComment
MAC AEt21/1Dnsmasq —> Openshift baremetal Network
MAC BEt8/1Available for PTP configuration

Going now back to the switch configuration, configure the master interface:

tor-sw-210#sh run interface Et8/1
interface Ethernet21/1
   speed forced 25gfull
   switchport access vlan 3
   ptp enable
   ptp role master
   ptp transport layer2

Usually we would configure the interface to be in both vlans by setting it to trunk mode.

However, the Arista switches in trunk mode were not performing as expected and therefore it was decided to keep each interface in a single vlan. Et21/1 in cert4 vlan and Et8/1 in ptp_vlan

tor-sw-210#show running-config int Et8/1
interface Ethernet26/1
   description  "ptp node interface"
   speed forced 100gfull
   switchport access vlan 3
   ptp enable
   ptp role master
   ptp transport layer2

tor-sw-210#show running-config int Et21/1
interface Ethernet21/1
   description "ocp bm ntw interface"
   speed forced 100gfull
   switchport access vlan 27
   ptp transport layer2
tor-sw-210#config
tor-sw-210(config)#interface Et8/1
tor-sw-210(config-int-Et21/1)#shutdown
tor-sw-210(config-int-Et21/1)#no shutdown
tor-sw-210(config-int-Et21/1)#write
tor-sw-210#show ptp
PTP Mode: Boundary Clock
PTP Profile: G8275.1
Clock Identity: 0x94:8e:d3:ff:ff:ed:a1:89
Grandmaster Clock Identity: 0x00:b0:ae:ff:fe:07:6f:b8
Number of slave ports: 1
Number of master ports: 1
Slave port: Ethernet13/1
Offset From Master (nanoseconds): 7
Mean Path Delay (nanoseconds): 179
Steps Removed: 2
Skew (estimated local-to-master clock frequency ratio): 1.0000052959672074
Last Sync Time: 15:05:36 UTC Aug 25 2023
Current PTP System Time: 15:05:36 UTC Aug 25 2023
   Interface       State        Transport    Delay    
                                             Mechanism
--------------- ------------ --------------- ---------
   Et8/1           Master       layer2       e2e      
   Et13/1          Slave        layer2       e2e
tor-sw-210(config)#show vlan
VLAN  Name                             Status    Ports
----- -------------------------------- --------- -------------------------------
1     default                          active    Et1/1, Et1/2, Et1/4, Et2/1
                                                 Et2/2, Et2/4, Et3/1, Et3/2
                                                 Et3/4, Et4/1, Et4/2, Et4/4
                                                 Et5/2, Et5/4, Et7/1, Et7/2
                                                 Et7/3, Et7/4, Et8/2, Et8/3
                                                 Et8/4, Et9/1, Et9/2, Et9/3
                                                 Et9/4, Et10/1, Et10/2, Et10/3
                                                 Et10/4, Et11/2, Et11/4, Et12/1
                                                 Et12/4, Et18/1, Et19/1, Et20/1
                                                 Et22/1, Et23/1, Et24/1, Et26/1
                                                 Et27/1, Et28/1, Et30/1, Et31/1
                                                 Et32/1
3     ptp_vlan                         active    Et8/1, Et13/1

For the Openshift cluster, another vlan was created with the interfaces connected to the baremetal network, called cert4 vlan (id 27). Then, iLO and Uplink were also differentiated.

Note: at this point, no isolation is taking place among any vlan.

tor-sw-210(config)#show vlan
VLAN  Name                             Status    Ports
----- -------------------------------- --------- -------------------------------
1     default                          active    Et1/1, Et1/2, Et1/4, Et2/1
                                                 Et2/2, Et2/4, Et3/1, Et3/2
                                                 Et3/4, Et4/1, Et4/2, Et4/4
                                                 Et5/1, Et5/2, Et5/4, Et7/1
                                                 Et7/2, Et7/3, Et7/4, Et8/2
                                                 Et8/2, Et8/3, Et8/4, Et9/1
                                                 Et9/2, Et9/3, Et9/4, Et10/1
                                                 Et10/2, Et10/3, Et10/4, Et11/2
                                                 Et11/4, Et12/1, Et12/4, Et18/1
                                                 Et19/1, Et20/1, Et22/1, Et23/1
                                                 Et24/1, Et26/1, Et27/1, Et28/1
                                                 Et30/1, Et31/1, Et32/1
3     ptp_vlan                         active    Et13/1, Et8/1
27    cert4                            active    Cpu, Et1/3, Et2/3, Et3/3, Et4/3
                                                 Et5/3, Et11/1, Et11/3, Et12/2
                                                 Et12/3, Et17/1, Et21/1, Et25/1
                                                 Et29/1, Et35/1
1027  cert4_ilo_net                    active    Cpu, Et35/1
3027  uplink                           active    Cpu, Et36/1

PTP Operator configuration #

Now that the switch is correctly configured and that we are able to see PTP packets in the OCP node servers, let’s configure Openshift to take these new measurements into account.

Installing the PTP Operator #

Installation steps #

  1. Manually create ns and operatorgroup
apiVersion: v1
kind: Namespace
metadata:
  name: openshift-ptp
  annotations:
    workload.openshift.io/allowed: management
  labels:
    name: openshift-ptp
    openshift.io/cluster-monitoring: "true"
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: ptp-operators
  namespace: openshift-ptp
spec:
  targetNamespaces:
  - openshift-ptp
  1. From Operator Hub install now the PTP Operator

Select openshift-ptp namespace already created

  1. PTP deploys linuxptp-daemon pod on each node

The Linux PTP implementation of the PTP runs the linuxptp and phc2sys processes.

Disabling NTP server (chronyd) through MachineConfigPool #

Start by labeling the target PTP node to be configured with an additional role.

oc label node <ptpnode>  node-role.kubernetes.io/infra=

And then create a MachineConfigPool targetting both roles (worker and the new role) and selecting the specific host.

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfigPool
metadata:
  labels:
    pools.operator.machineconfiguration.openshift.io/worker: ""
  name: ptp
spec:
  machineConfigSelector:
    matchExpressions:
      - {key: machineconfiguration.openshift.io/role, operator: In, values: [worker,infra]}
  nodeSelector:
    matchLabels:
      kubernetes.io/hostname: <ptpnode> 

Create a MachineConfig that disables NTP server in the nodes with the new role created:

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: infra
  name: 500-disable-chronyd
spec:
  config:
    ignition:
      version: 3.2.0
    systemd:
      units:
        - contents: |
            [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
            [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
            [Install]
            WantedBy=multi-user.target            
          enabled: false
          name: "chronyd.service"
  • Checking it is disabled

    $ oc debug node/<ptpnode> 
    To use host binaries, run `chroot /host`
    Pod IP: 192.168.27.73
    If you don't see a command prompt, try pressing enter.
    
    sh-4.4# chroot /host
    sh-5.1# systemctl status chronyd
    ○ chronyd.service - NTP client/server
         Loaded: loaded (/etc/systemd/system/chronyd.service; disabled; preset: enabled)
        Drop-In: /usr/lib/systemd/system/chronyd.service.d
                 └─platform-chrony.conf
         Active: inactive (dead)
           Docs: man:chronyd(8)
                 man:chrony.conf(5)
    

Configuring the PTP Operator #

The two main CRD provided by the PTP Operator need to be configured as explained below:

  • PtpOperatorConfig selects the nodes where to configure PTP

    # Example of all worker nodes PTP config
    apiVersion: ptp.openshift.io/v1
    kind: PtpOperatorConfig
    metadata:
      name: default
      namespace: openshift-ptp
    spec:
      daemonNodeSelector:
        node-role.kubernetes.io/worker: ""
    
    # Example of a  single node PTP config
    apiVersion: ptp.openshift.io/v1
    kind: PtpOperatorConfig
    metadata:
      name: default
      namespace: openshift-ptp
    spec:
      daemonNodeSelector:
        kubernetes.io/hostname: <ptpnode> 
    
  • PtpConfig configures all needed params

    apiVersion: ptp.openshift.io/v1
    kind: PtpConfig
    metadata:
      name: ordinary-clock-ptp-config
      namespace: openshift-ptp
    spec:
      profile:
        - name: ordinary-clock-<ptpnode>
          interface: "ens1f0"
          phc2sysOpts: "-a -r -n 24"
          ptp4lOpts: "-2 -s"
          ptpSchedulingPolicy: SCHED_FIFO
          ptpSchedulingPriority: 10
          ptp4lConf: |
            [global]
            #
            # Default Data Set
            #
            twoStepFlag 1
            slaveOnly 1
            priority1 128
            priority2 128
            domainNumber 24
            clockClass 255
            clockAccuracy 0xFE
            offsetScaledLogVariance 0xFFFF
            free_running 0
            freq_est_interval 1
            dscp_event 0
            dscp_general 0
            dataset_comparison G.8275.x
            G.8275.defaultDS.localPriority 128
            #
            # Port Data Set
            #
            logAnnounceInterval -3
            logSyncInterval -4
            logMinDelayReqInterval -4
            logMinPdelayReqInterval -4
            announceReceiptTimeout 3
            syncReceiptTimeout 0
            delayAsymmetry 0
            fault_reset_interval 4
            neighborPropDelayThresh 20000000
            masterOnly 0
            G.8275.portDS.localPriority 128
            #
            # Run time options
            #
            assume_two_step 0
            logging_level 6
            path_trace_enabled 0
            follow_up_info 0
            hybrid_e2e 0
            inhibit_multicast_service 0
            net_sync_monitor 0
            tc_spanning_tree 0
            tx_timestamp_timeout 50
            unicast_listen 0
            unicast_master_table 0
            unicast_req_duration 3600
            use_syslog 1
            verbose 0
            summary_interval 0
            kernel_leap 1
            check_fup_sync 0
            #
            # Servo Options
            #
            pi_proportional_const 0.0
            pi_integral_const 0.0
            pi_proportional_scale 0.0
            pi_proportional_exponent -0.3
            pi_proportional_norm_max 0.7
            pi_integral_scale 0.0
            pi_integral_exponent 0.4
            pi_integral_norm_max 0.3
            step_threshold 2.0
            first_step_threshold 0.00002
            max_frequency 900000000
            clock_servo pi
            sanity_freq_limit 200000000
            ntpshm_segment 0
            #
            # Transport options
            #
            transportSpecific 0x0
            ptp_dst_mac 01:1B:19:00:00:00
            p2p_dst_mac 01:80:C2:00:00:0E
            udp_ttl 1
            udp6_scope 0x0E
            uds_address /var/run/ptp4l
            #
            # Default interface options
            #
            clock_type OC
            network_transport L2
            delay_mechanism E2E
            time_stamping hardware
            tsproc_mode filter
            delay_filter moving_median
            delay_filter_length 10
            egressLatency 0
            ingressLatency 0
            boundary_clock_jbod 0
            #
            # Clock description
            #
            productDescription ;;
            revisionData ;;
            manufacturerIdentity 00:00:00
            userDescription ;
            timeSource 0xA0        
      recommend:
        - profile: ordinary-clock-<ptpnode>
          priority: 4
          match:
            - nodeName: "<ptpnode>"
    

Monitor the PTP Logs #

Check the logs in the linuxptp pod running in the worker node.

oc logs -f linuxptp-daemon-22qb4 -c linuxptp-daemon-container
phc2sys[13151.138]: [ptp4l.0.config] CLOCK_REALTIME rms    3 max    3 freq   +750 +/-   0 delay   487 +/-   0
ptp4l[13151.812]: [ptp4l.0.config] rms    4 max   10 freq -22641 +/-   7 delay   142 +/-   1
phc2sys[13152.138]: [ptp4l.0.config] CLOCK_REALTIME rms   19 max   19 freq   +733 +/-   0 delay   487 +/-   0
ptp4l[13153.012]: [ptp4l.0.config] rms    6 max   11 freq -22642 +/-   9 delay   143 +/-   1
phc2sys[13153.138]: [ptp4l.0.config] CLOCK_REALTIME rms    5 max    5 freq   +741 +/-   0 delay   487 +/-   0
ptp4l[13154.017]: [ptp4l.0.config] rms    5 max    9 freq -22639 +/-   9 delay   141 +/-   1
phc2sys[13154.139]: [ptp4l.0.config] CLOCK_REALTIME rms    7 max    7 freq   +752 +/-   0 delay   488 +/-   0
ptp4l[13155.027]: [ptp4l.0.config] rms    5 max   12 freq -22640 +/-   8 delay   143 +/-   1
phc2sys[13155.139]: [ptp4l.0.config] CLOCK_REALTIME rms   15 max   15 freq   +762 +/-   0 delay   488 +/-   0
ptp4l[13156.032]: [ptp4l.0.config] rms    3 max    7 freq -22643 +/-   5 delay   140 +/-   1
phc2sys[13156.139]: [ptp4l.0.config] CLOCK_REALTIME rms   14 max   14 freq   +737 +/-   0 delay   487 +/-   0
ptp4l[13157.041]: [ptp4l.0.config] rms    4 max    9 freq -22640 +/-   7 delay   142 +/-   1
$ oc rsh -c linuxptp-daemon-container linuxptp-daemon-22qb4 
sh-4.4# pmc -u -f /var/run/ptp4l.0.config -b 0 'GET PORT_DATA_SET'
sending: GET PORT_DATA_SET
	88e9a4.fffe.4504c6-1 seq 0 RESPONSE MANAGEMENT PORT_DATA_SET 
		portIdentity            88e9a4.fffe.4504c6-1
		portState               SLAVE
		logMinDelayReqInterval  -4
		peerMeanPathDelay       0
		logAnnounceInterval     -3
		announceReceiptTimeout  3
		logSyncInterval         -4
		delayMechanism          1
		logMinPdelayReqInterval -4
		versionNumber           2

Wrap up #

The Precision Time Protocol hast taken a step forward as the IEEE Standard Synchronization Protocol for Networked Control Systems in high-accuracy scenarios. While NTP achieves milliseconds accuracy, PTP reaches sub-microsecond level.

In this post, PTP is first configured in an Arista ToR Switch that connects all the OCP cluster nodes and it then explains how to install and configure the PTP Operator in Openshift. Hope it helped!

Related

Headache provisioning baremetal servers? Basic tips to clean, reset, and reboot BMCs
·2 mins
baremetal hpe-dell
New to out-of-band management (OOB)?