Advanced PTP Configuration

Caution

Parameters are written to the ptp4l configuration file without error checking. Caution must be taken to ensure that parameter names and values are correct as errors will cause ptp4l launch failures.

Configure BMCA Tiebreaker for Site Boot/Reboot Scenarios

During a site-wide power outage, both the CSR (Cell Site Router) and the StarlingX PTP node lose power simultaneously. When power is restored, a race condition can lead to the StarlingX accepting an incorrect time from the CSR.

The following diagram illustrates the problematic scenario with the default configuration (clockClass=248, priority2=128):

CSR (Cell Site Router)                        StarlingX (prod)
 |                                                 |
 X  <<<< Site-wide power outage >>>>               X
 |                                                 |
 |                                  [Boots with valid RTC: 2026-04-10 14:44:38]
 |                                  [PHC and CLOCK_REALTIME = good time]
 |                                                 |
 |                                  [ptp4l starts: clockClass=248, priority2=128]
 |                                  [Listening for Announce messages...]
 |                                                 |
 | [Boots, NO GNSS lock]                           |
 | [Time = epoch 1970-01-01]                       |
 |                                                 |
 |---Announce(clockClass=248, priority2=128)----->>|
 |                                                 |
 |                          [BMCA: clockClass tied (248 = 248)]
 |                          [BMCA: clockAccuracy tied]
 |                          [BMCA: offsetScaledLogVariance tied]
 |                          [BMCA: priority2 tied (128 = 128)]
 |                          [BMCA: clockIdentity tiebreaker]
 |                          [CSR 0xc8... < prod 0xf0... — CSR WINS]
 |                                                 |
 |---Sync(time=1970-01-01)------------------------>>|
 |                          [Step correction: PHC set to 1970!]
 |                          [CLOCK_REALTIME = 1970]
 |                                                 |
 |  ~10 minutes pass...                            |
 |                                                 |
 | [GNSS lock acquired]                            |
 |---Announce(clockClass=6, time=2026)------------>>|
 |                                                 |
 |                          [Step already used — can only SLEW]
 |                          [Slew from 1970 to 2026 = ~56 years]
 |                          [IMPOSSIBLE — system time NEVER recovers]
 |                                                 |

The root cause is that with identical clockClass=248 and priority2=128, the BMCA falls through to the clockIdentity tiebreaker. The CSR’s clockIdentity is numerically lower, and it is selected, causing StarlingX to accept the wrong time before GNSS lock.

The ptp4l configuration can be adjusted to prevent this scenario by leveraging the BMCA tiebreaker fields to ensure the StarlingX does not accept the CSR as master while the CSR is in freerun state.

About this task

The BMCA selects the best clock source by comparing the following fields in order. At each step, the lower value takes precedence:

BMCA Tiebreaker

Comparison Rule

CSR

StarlingX (problematic)

StarlingX (proposed)

priority1

Compared first, lower wins

128

128

clockClass

Lower wins

248

248

clockAccuracy

Lower wins

0xfe

0xfe

offsetScaledLogVariance

Lower wins

65535

65535

priority2

Lower wins

128

128

99

clockIdentity

Final tiebreaker, numerically lower wins

0xc8ca79fffee5af80

0xf0b2b9fffe0415f3

With the problematic configuration (clockClass=248, priority2=128), all BMCA fields are tied and the comparison falls through to clockIdentity. The CSR’s clockIdentity is numerically lower, so it is selected and the StarlingX accepts the CSR’s epoch time.

With the proposed configuration (clockClass=248, priority2=99), the BMCA proceeds through clockClass, clockAccuracy, and offsetScaledLogVariance (all tied), then reaches priority2. At priority2, the StarlingX value of 99 is lower than the CSR value of 128, so it is selected and StarlingX does not accept the CSR as its master during the reboot window.

Once the CSR acquires GNSS lock and advertises clockClass=6, it will naturally be selected by the BMCA (6 < 248) and the StarlingX will accept it as master with the correct time.

Caution

The CSR should be configured as “master-only” on the StarlingX-facing port to ensure that the CSR would never accept the StarlingX as master.

Configuration To Apply

The following changes are required on the ptp4l instance:

  • Add global ptp4l parameter: priority2=99

  • Don’t modify default parameter: clockClass=248

  • Don’t add global ptp4l parameters: BMCA=noop, slaveOnly=1

~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> priority2=99

Default Data Set Fields

The following fields are part of the DEFAULT_DATA_SET of the local clock and are compared by the BMCA against the foreign master’s Announce message:

507c6f.fffe.21bb24-0 seq 0 RESPONSE MANAGEMENT DEFAULT_DATA_SET
        twoStepFlag             1
        slaveOnly               0
        numberPorts             1
        priority1               128
        clockClass              248
        clockAccuracy           0xfe
        offsetScaledLogVariance 0xffff
        priority2               99
        clockIdentity           507c6f.fffe.21bb24
        domainNumber            24
priority1

The priority1 attribute of the local clock. It is used in the best master selection algorithm, lower values take precedence. Must be in the range 0 to 255. The default is 128.

clockClass

The clockClass attribute of the local clock. It denotes the traceability of the time distributed by the grandmaster clock. The default is 248.

clockAccuracy

The clockAccuracy attribute of the local clock. It is used in the best master selection algorithm. The default is 0xFE.

offsetScaledLogVariance

The offsetScaledLogVariance attribute of the local clock. It characterizes the stability of the clock. The default is 0xFFFF.

priority2

The priority2 attribute of the local clock. It is used in the best master selection algorithm, lower values take precedence. Must be in the range 0 to 255. The default is 128.

clockIdentity

The clockIdentity attribute of the local clock. The clockIdentity is an 8-octet array and should be written in textual form in this configuration. It should be unique since it is used to identify the specific clock. If default is used or if not set at all, the clockIdentity will be automatically generated. The default is “000000.0000.000000”.

Choosing the priority2 Value

The priority2 value must be lower than the CSR’s priority2 to win the BMCA tiebreaker. Use the pmc tool to query the DEFAULT_DATA_SET across the network and determine the lowest priority2 value in use:

~(keystone_admin)]$ sudo pmc -i <interface> -b 3 -f /etc/linuxptp/ptpinstance/ptp4l-<instance>.conf 'GET DEFAULT_DATA_SET'

Based on the network query results, if the minimum priority2 across all foreign masters is 100, the StarlingX should be configured with a value lower than that (e.g. 99). This value may differ per network deployment.

Configure ITU-T G.8275.1 Grandmaster Settings Fields

Users can configure ptp4l instances to set the PTP Announce messages fields in conformance with the ITU-T G.8275.1/Y.1369.1 PTP profile. This configuration is recommended for nodes that are configured as a T-GM or T-BC and using the G.8275.1 PTP profile.

Prerequisites

  • The system should be configured with at least one ptp4l instance. See Configure PTP Service Using the CLI for more information.

  • Any ptp4l instances using the G.8275.1 profile must be configured with the dataset_comparison=G.8275.x instance parameter. This parameter enables the G.8275.1 PTP profile for the ptp4l instance.

    ~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> dataset_comparison=G.8275.x
    

About this task

The following section provides additional details about the relevant Announce message fields and how to configure their value.

507c6f.fffe.21bb24-0 seq 0 RESPONSE MANAGEMENT GRANDMASTER_SETTINGS_NP
        clockClass              6
        clockAccuracy           0x20
        offsetScaledLogVariance 0x4e5d
        currentUtcOffset        37
        leap61                  0
        leap59                  0
        currentUtcOffsetValid   1
        ptpTimescale            1
        timeTraceable           1
        frequencyTraceable      1
        timeSource              0x20

Each of the fields are explained below:

clockClass

This field is dynamically set by StarlingX based on the state of the Primary Reference Time Clock (PRTC) used by the ptp4l instance. No user configuration is required.

clockAccuracy

Default value (not locked to PRTC): 0xfe

Default value (locked to PRTC): 0x20

When a ptp4l instance is locked to a PRTC, the value will be dynamically updated to 0x20.

If the ptp4l instance is connected to an Enhanced Primary Reference Time Clock (ePRTC), the locked value can be changed by using a ptp4l instance parameter.

~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> clockAccuracy=0x21
offsetScaledLogVariance

Default value (not locked to PRTC): 0xffff

Default value (locked to PRTC): 0x4e5d

The offsetScaledLogVariance attribute characterizes the stability of the clock. If the ptp4l instance is connected to an ePRTC, the locked value can be changed by using a ptp4l instance parameter.

~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> offsetScaledLogVariance=0x4b32
currentUtcOffset

Default value: 37

The current offset between TAI and UTC. This value does not need to be altered unless IERS introduces a new leap-second into UTC. If necessary, the value can be altered for testing purposes using a ptp4l instance parameter.

~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> utc_offset=37
leap61

Default value: 0

This attribute is used to handle the addition of a new leap-second. StarlingX does not currently support altering the leap61 attribute.

leap59

Default value: 0

This attribute is used to handle the addition of a new leap-second. StarlingX does not currently support altering the leap59 attribute.

currentUtcOffsetValid

Default value: 0

This attribute is dynamically set by StarlingX based on the ptp4l instance’s connection to a PRTC. When a PRTC is connected to the ptp4l instance, currentUtcOffsetValid will be set to 1.

ptpTimescale

Default value: 1

This attribute should always be set to 1 according to the G.8275.1 PTP profile.

timeTraceable

Default value: 0

This attribute is dynamically set by StarlingX based on the ptp4l instance’s connection to a PRTC. When a PRTC is connected to the ptp4l instance, timeTraceable will be set to 1.

frequencyTraceable

Default value: 0

This attribute is dynamically set by StarlingX based on the ptp4l instance’s connection to a PRTC. When a PRTC with frequency information is connected to the ptp4l instance, frequencyTraceable will be set to 1.

timeSource

Default value: 0xa0

This attribute describes the type of clock used for the PRTC. The default value of 0xa0 indicates the use of an internal oscillator on the PTP NIC. StarlingX will automatically update this value to 0x20 (GPS) if it detects that the ptp4l instance is utilizing a GPS time source.

Users can change this attribute using a ptp4l instance parameter. For a comprehensive list of time source types and their respective values, consult the G.8275.1 standard.

~(keystone_admin)]$ system ptp-instance-parameter-add <ptp4l instance> timeSource=0x20

Apply PTP configuration

After assigning ptp4l instance parameters, apply the new PTP configuration using system ptp-instance-apply.

Verify Announce Message Attributes

The PTP Announce Message Attributes can be viewed using the pmc tool.

sudo pmc -u -b 0 -f /etc/linuxptp/ptpinstance/<ptp4l instance config file> 'GET GRANDMASTER_SETTINGS_NP'

sending: GET GRANDMASTER_SETTINGS_NP
  507c6f.fffe.21bb24-0 seq 0 RESPONSE MANAGEMENT GRANDMASTER_SETTINGS_NP
          clockClass              6
          clockAccuracy           0x20
          offsetScaledLogVariance 0x4e5d
          currentUtcOffset        37
          leap61                  0
          leap59                  0
          currentUtcOffsetValid   1
          ptpTimescale            1
          timeTraceable           1
          frequencyTraceable      1
          timeSource              0x20

The log output for dynamically updated values can be found in /var/log/collectd.log.

Ts2phc Offset Spike Mitigation

ts2phc can be configured to detect and ignore intermittent offset spikes that may result in incorrect clock adjustments. This behavior is controlled using the global instance parameter max_phc_update_skip_cnt. The max_phc_update_skip_cnt parameter is the number of consecutive offset spikes in a row that will be ignored. For example, setting max_phc_update_skip_cnt to 120 would allow ts2phc to ignore 120 consecutive offset spike incidents before adjusting the clock.

Offset Spike Characterization

The StarlingX systems using the realtime kernel may experience an intermittent offset spike behavior in ts2phc. This intermittent offset spike behavior results from GNSS messages that take time to arrive at the userspace ts2phc application. The delayed GNSS messages can cause ts2phc application to calculate an incorrect adjustment value for the PHCs. This results in ts2phc making large adjustments to its PHCs and can cause unstable system time. An example of this behavior can be seen in the log snippet below. If log events similar to the given example are observed, configuring offset spike mitigation in ts2phc can improve timing stability by detecting and ignoring these large offset calculations.

Example:

2024-03-07T15:39:57.821 controller-1 ts2phc: debug [212517.301] ts11 nmea sentence: GNRMC
2024-03-07T15:39:58.001 controller-1 ts2phc: debug [212517.480] ts11 nmea delay: 820982637 ns
### Large nmea delay value above ^^ indicates an offset spike has occurred

2024-03-07T15:39:58.001 controller-1 ts2phc: debug [212517.480] ts11 enp81s0f1 extts index 0 at 1709826035.000000000 corr 0 src 1709826034.179042651 diff 1000000000 servo state 2
2024-03-07T15:39:58.001 controller-1 ts2phc: debug [212517.480] ts11 enp81s0f1 master offset1000000000 s2 freq +900000000
### Ts2phc makes large adjustment ^^ to clock, resulting in degraded timing accuracy

2024-03-07T15:39:58.058 controller-1 ts2phc: debug [212517.538] ts11 nmea sentence: GNRMC
2024-03-07T15:39:58.935 controller-1 ts2phc: debug [212518.413] ts11 nmea delay: 58600490 ns
2024-03-07T15:39:58.935 controller-1 ts2phc: debug [212518.413] ts11 enp81s0f1 extts index 0 at 1709826035.100878397 corr 0 src 1709826036.874841070 diff -899121603 servo state 2
2024-03-07T15:39:58.935 controller-1 ts2phc: debug [212518.413] ts11 enp81s0f1 master offset -899121603 s2 freq -899121603
### Subsequent cycles show wide swings ^^ in clock adjustments as ts2phc stabilizes

2024-03-07T15:39:58.999 controller-1 ts2phc: debug [212518.479] ts11 nmea sentence: GNRMC
2024-03-07T15:39:59.834 controller-1 ts2phc: debug [212519.313] ts11 nmea delay: -449462 ns
2024-03-07T15:39:59.834 controller-1 ts2phc: debug [212519.313] ts11 enp81s0f1 extts index 0 at 1709826036.996688203 corr 0 src 1709826037.833824291 diff -3311797 servo state 2
2024-03-07T15:39:59.834 controller-1 ts2phc: debug [212519.313] ts11 enp81s0f1 master offset -3311797 s2 freq -273048278
2024-03-07T15:40:04.178 controller-1 ts2phc: debug [212523.658] ts11 nmea sentence: GNRMC [… omitted lines]
2024-03-07T15:40:32.054 controller-1 ts2phc: debug [212551.534] ts11 nmea sentence: GNRMC
2024-03-07T15:40:33.000 controller-1 ts2phc: debug [212552.480] ts11 nmea delay: 54715299 ns
2024-03-07T15:40:33.000 controller-1 ts2phc: debug [212552.480] ts11 enp81s0f1 extts index 0 at 1709826070.000000003 corr 0 src 1709826070.945357401 diff 3 servo state 2
2024-03-07T15:40:33.000 controller-1 ts2phc: debug [212552.480] ts11 enp81s0f1 master offset          3 s2 freq      +2
2024-03-07T15:40:33.054 controller-1 ts2phc: debug [212552.534] ts11 nmea sentence: GNRMC
2024-03-07T15:40:34.002 controller-1 ts2phc: debug [212553.480] ts11 nmea delay: 54504252 ns
2024-03-07T15:40:34.002 controller-1 ts2phc: debug [212553.480] ts11 enp81s0f1 extts index 0 at 1709826071.000000001 corr 0 src 1709826071.945587288 diff 1 servo state 2
2024-03-07T15:40:34.002 controller-1 ts2phc: debug [212553.480] ts11 enp81s0f1 master offset          1 s2 freq      +0
### After a period of 25-30 seconds, ts2phc has stabilized and is back to small adjustments

Configure Offset Spike Mitigation

The offset spike mitigation behavior is enabled in ts2phc by default with a value of max_phc_update_skip_cnt = 120.

To configure the number of consecutive offset spikes that will be ignored by ts2phc, use the following PTP instance parameter:

system ptp-instance-parameter-add <ts2phc instance name> max_phc_update_skip_cnt=120

# Apply the configuration. This will restart all PTP services.
system ptp-instance-apply

The value 120 will allow ts2phc to ignore up to 120 consecutive offset spikes. This value may need to be adjusted based on testing and observation in your environment. Consecutive occurrences are not observed often, with subsequent updates arriving in a timely manner.

Disable Offset Spike Mitigation

The offset spike mitigation can be disabled by setting max_phc_update_skip_cnt=0.

Offset mitigation log example:

2024-03-07T15:41:04.639 controller-1 ts2phc: debug [212584.120] ts11 nmea sentence: GNRMC
2024-03-07T15:41:05.013 controller-1 ts2phc: debug [212584.493] ts11 nmea delay: 639834481 ns
### Large nmea delay above ^^ indicating an offset spike has occurred

2024-03-07T15:41:05.013 controller-1 ts2phc: debug [212584.493] ts11 enp81s0f1 extts index 0 at 1709826102.000000000 corr 0 src 1709826101.373785045 diff 1000000000 servo state 2
2024-03-07T15:41:05.013 controller-1 ts2phc: debug [212584.493] ts11 Offset spike detected. Skip current PHC update enp81s0f1 offset 1000000000 s2 freq      +0
### Mitigation catches this and skips adjusting the clock ^^

2024-03-07T15:41:05.013 controller-1 ts2phc: debug [212584.493] ts11 Current skip count: 1
### “Current skip count” ^^ indicates the number of consecutive spikes detected
### Because the next update to arrive does not have an offset spike, the current skip count will be reset to 0 and will begin incrementing again when another spike occurs

2024-03-07T15:41:05.063 controller-1 ts2phc: debug [212584.543] ts11 nmea sentence: GNRMC
2024-03-07T15:41:06.001 controller-1 ts2phc: debug [212585.480] ts11 nmea delay: 63592544 ns
2024-03-07T15:41:06.001 controller-1 ts2phc: debug [212585.480] ts11 enp81s0f1 extts index 0 at 1709826103.000000000 corr 0 src 1709826103.936434314 diff 0 servo state 2
2024-03-07T15:41:06.001 controller-1 ts2phc: debug [212585.480] ts11 enp81s0f1 master offset          0 s2 freq      +0
### Subsequent ts2phc adjustments are small because the clock remained tightly synced

2024-03-07T15:41:06.067 controller-1 ts2phc: debug [212585.533] ts11 nmea sentence: GNRMC
2024-03-07T15:41:07.000 controller-1 ts2phc: debug [212586.480] ts11 nmea delay: 53524772 ns
2024-03-07T15:41:07.000 controller-1 ts2phc: debug [212586.480] ts11 enp81s0f1 extts index 0 at 1709826104.000000000 corr 0 src 1709826104.946499286 diff 0 servo state 2
2024-03-07T15:41:07.000 controller-1 ts2phc: debug [212586.480] ts11 enp81s0f1 master offset          0 s2 freq      +0
2024-03-07T15:41:07.050 controller-1 ts2phc: debug [212586.530] ts11 nmea sentence: GNRMC
2024-03-07T15:41:08.000 controller-1 ts2phc: debug [212587.480] ts11 nmea delay: 50802510 ns
2024-03-07T15:41:08.000 controller-1 ts2phc: debug [212587.480] ts11 enp81s0f1 extts index 0 at 1709826104.999999999 corr 0 src 1709826105.949221716 diff -1 servo state 2
2024-03-07T15:41:08.000 controller-1 ts2phc: debug [212587.480] ts11 enp81s0f1 master offset         -1 s2 freq      -1

Ts2phc config file example:

[global]
##
## Default Data Set
##
leapfile /usr/share/zoneinfo/leap-seconds.list
message_tag ts11
ts2phc.nmea_serialport /dev/gnss0
ts2phc.pulsewidth 100000000
logging_level 7
max_phc_update_skip_cnt 120

[enp81s0f1]
##
## Associated interface: enp81s0f1
##
ts2phc.extts_polarity rising

Adjust ts2phc Holdover Interval

In a PTP T-GM deployment, the system typically receives ToD information and 1 PPS signal from a GNSS receiver to maintain accurate time synchronization.

The ts2phc utility synchronizes the NIC PHC with the GNSS timing information. The ToD information is acquired through NMEA serial messages from the configured GNSS serial port, while the 1 PPS signal is received from the GNSS receiver via the DPLL.

When the GNSS signal becomes unavailable, the ToD information stream halts. As a result, ts2phc no longer adjusts PHC. Although the NIC’s PHC continues being adjusted using the DPLL’s internal oscillator as a reference, ts2phc stops adjusting it by default. This causes the PHC values to diverge from the accurate time reference, eventually triggering out-of-tolerance alarms.

To maintain PHC synchronization during temporary GNSS outages, ts2phc supports a holdover mode configured through the ts2phc.holdover parameter. This parameter specifies the holdover interval (in seconds) during which ts2phc continues synchronizing the PHC after the ToD information becomes unavailable.

During holdover, ts2phc continues to adjust the PHC using the DPLL’s 1 PPS signal as a frequency reference to maintain timing accuracy.

However, the holdover mode only operates when the servo is stable (SERVO_LOCKED_STABLE state). To enable this state, configure the servo_offset_threshold parameter to define the maximum offset value (in nanoseconds) that indicates stable synchronization. The servo is considered stable when the number of offset samples specified by servo_num_offset_values remain below the servo_offset_threshold value.

Note

Holdover is not supported when using the -a option or when ts2phc.extts_polarity is set to both.

To configure the holdover mode on a ts2phc instance, use the system ptp-instance-parameter-add command to set the holdover parameters. The following example configures a 4 hours holdover period (14400 seconds) with stability criteria of 5 offset samples below 10 nanoseconds.

~(keystone_admin)]$ system ptp-instance-parameter-add <ts2phc instance> ts2phc.holdover=14400 servo_num_offset_values=5 servo_offset_threshold=10

T-BC Clock Class Compliance

StarlingX manages the clockClass field in PTP Announce messages to comply with the ITU-T G.8275 specification for Telecom Boundary Clock (T-BC) nodes. The collectd |PTP| plugin dynamically sets the clockClass value based on the timing chain’s state.

The following clockClass values are used:

clockClass

Condition

6

Locked to a GNSS source via ts2phc (T-GM).

7

In holdover, within the configured holdover_seconds threshold.

135

T-BC in holdover after losing its upstream grandmaster.

140

Holdover has expired (holdover_seconds exceeded for the timing source). Indicates degraded accuracy.

165

Freerun after holdover expiry. The node is no longer traceable.

248

Freerun with no prior lock (default unlocked state).

When a T-BC is locked to an upstream grandmaster, collectd reads the clockClass directly from the grandmaster and does not override it. When the grandmaster connection is lost, the T-BC transitions through holdover (135) and, once the holdover timer expires, to freerun (165).

Note

The holdover duration is controlled by the holdover_seconds monitoring parameter. See PTP Instance Monitoring Parameters for configuration details.

phc2sys Out-of-Tolerance Monitoring

StarlingX raises out-of-tolerance alarms for phc2sys instances when the measured time offset exceeds the configured thresholds. This monitoring applies to both standard and HA phc2sys configurations.

The alarm entity ID format is:

host=<hostname>.instance=<phc2sys-instance-name>.ptp=out-of-tolerance

For HA phc2sys configurations, the offset of the currently active source is used for the threshold comparison.

The offset thresholds are configured using the monitoring section parameters offset_threshold_minor_nsec and offset_threshold_major_nsec. See PTP Instance Monitoring Parameters for configuration details.

To verify that phc2sys monitoring is active, check the collectd log after applying the configuration.

~(keystone_admin)]$ grep "phc2sys" /var/log/collectd.log