|
| 1 | +--- |
| 2 | +title: "PTP Time Synchronization" |
| 3 | +author: troglobit |
| 4 | +date: 2026-04-07 10:00:00 +0200 |
| 5 | +categories: [examples] |
| 6 | +tags: [ptp, ieee1588, gptp, timing, cli, marvell] |
| 7 | +--- |
| 8 | + |
| 9 | +The Precision Time Protocol (PTP, IEEE 1588) synchronizes clocks across a |
| 10 | +network to sub-microsecond accuracy — far beyond what NTP can achieve. Infix |
| 11 | +supports both the standard IEEE 1588 profile and the gPTP profile (IEEE |
| 12 | +802.1AS) used in Time-Sensitive Networking. This post walks through the |
| 13 | +minimal configurations needed to get two devices talking PTP. |
| 14 | + |
| 15 | +For the full story (protocol concepts, port states, boundary clocks, message |
| 16 | +format, Wireshark tips), see the [PTP section of the User's Guide][1]. |
| 17 | + |
| 18 | +### Hardware Timestamping Matters |
| 19 | + |
| 20 | +PTP accuracy depends critically on **hardware timestamping**: the NIC marks |
| 21 | +each packet with a precise timestamp as it crosses the wire, not in software |
| 22 | +where OS scheduling adds jitter in the hundreds of microseconds. |
| 23 | + |
| 24 | +Before we start, from the UNIX shell, verify that your interface supports |
| 25 | +hardware timestamps: |
| 26 | + |
| 27 | +```console |
| 28 | +admin@example:~$ sudo ethtool -T eth0 |
| 29 | +Time stamping parameters for eth0: |
| 30 | +Capabilities: |
| 31 | + hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE) |
| 32 | + software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE) |
| 33 | + hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE) |
| 34 | + software-receive (SOF_TIMESTAMPING_RX_SOFTWARE) |
| 35 | + hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE) |
| 36 | +PTP Hardware Clock: 0 |
| 37 | +Hardware Transmit Timestamp Modes: |
| 38 | + off (HWTSTAMP_TX_OFF) |
| 39 | + on (HWTSTAMP_TX_ON) |
| 40 | +``` |
| 41 | + |
| 42 | +You want `hardware-transmit` and `hardware-receive` in the output. If you |
| 43 | +only see the `software-*` variants, PTP will still run and the state machines |
| 44 | +will work, but offsets will be in the millisecond range rather than nanoseconds. |
| 45 | + |
| 46 | +#### Recommended Hardware |
| 47 | + |
| 48 | +From the [boards Infix officially supports][2], the **Marvell CN9130 CRB** |
| 49 | +is the recommended choice. Its Marvell 88E6393X 11-port switchcore is driven |
| 50 | +by the `mv88e6xxx` DSA driver, which has mature PTP hardware timestamping and |
| 51 | +is exercised regularly with `ptp4l`. |
| 52 | + |
| 53 | +The **Marvell EspressoBIN** (Armada 3720 with 88E6341 switch, same `mv88e6xxx` |
| 54 | +driver) also works well for PTP and is considerably cheaper — it is not as |
| 55 | +regularly tested but included in the `aarch64*_defconfig` and is a good choice |
| 56 | +if you already have one. |
| 57 | + |
| 58 | +The BPI-R3 and BPI-R4 are the most accessible boards, but the MediaTek MT7531 |
| 59 | +switch driver does not yet support hardware PTP timestamps; run `ethtool -T` |
| 60 | +to verify before committing to a setup. |
| 61 | + |
| 62 | +> QEMU (the x86_64 virtual target) runs `ptp4l` and exercises the full |
| 63 | +> configuration and state machine path, which is useful during development. |
| 64 | +> But the virtual NIC only provides software timestamps, so do not expect |
| 65 | +> nanosecond offsets there. |
| 66 | +{: .prompt-info } |
| 67 | + |
| 68 | +### Ordinary Clock — Time-Receiver |
| 69 | + |
| 70 | +The simplest setup: one device tracks time from another. Configure the |
| 71 | +**time-receiver** first. |
| 72 | + |
| 73 | +```console |
| 74 | +admin@receiver:/> configure |
| 75 | +admin@receiver:/config/> edit ptp instance 0 |
| 76 | +admin@receiver:/config/ptp/instance/0/> set default-ds domain-number 0 |
| 77 | +admin@receiver:/config/ptp/instance/0/> set default-ds time-receiver-only true |
| 78 | +admin@receiver:/config/ptp/instance/0/> edit port 1 |
| 79 | +admin@receiver:/config/ptp/…/0/port/1/> set underlying-interface eth0 |
| 80 | +admin@receiver:/config/ptp/…/0/port/1/> leave |
| 81 | +``` |
| 82 | + |
| 83 | +### Ordinary Clock — Grandmaster |
| 84 | + |
| 85 | +On the **grandmaster** side, lower `priority1` values win the clock election. |
| 86 | +Setting it to `1` ensures this device always wins when reachable. |
| 87 | + |
| 88 | +```console |
| 89 | +admin@grandmaster:/> configure |
| 90 | +admin@grandmaster:/config/> edit ptp instance 0 |
| 91 | +admin@grandmaster:/config/ptp/instance/0/> set default-ds domain-number 0 |
| 92 | +admin@grandmaster:/config/ptp/instance/0/> set default-ds priority1 1 |
| 93 | +admin@grandmaster:/config/ptp/instance/0/> set default-ds priority2 1 |
| 94 | +admin@grandmaster:/config/ptp/instance/0/> edit port 1 |
| 95 | +admin@grandmaster:/config/ptp/…/0/port/1/> set underlying-interface eth0 |
| 96 | +admin@grandmaster:/config/ptp/…/0/port/1/> leave |
| 97 | +``` |
| 98 | + |
| 99 | +Connect `eth0` on both boards with a direct cable or through a PTP-transparent |
| 100 | +switch, then give it a few seconds to converge. |
| 101 | + |
| 102 | +### Verifying Synchronization |
| 103 | + |
| 104 | +On the time-receiver, `show ptp` displays the live offset and path delay: |
| 105 | + |
| 106 | +```console |
| 107 | +admin@receiver:/> show ptp |
| 108 | +PTP Instance 0 Ordinary Clock · domain 0 |
| 109 | +──────────────────────────────────────────────────────────────────── |
| 110 | + Clock identity : AA-BB-CC-FF-FE-11-22-33 |
| 111 | + Grandmaster : DD-EE-FF-FF-FE-44-55-66 |
| 112 | + Priority1/Priority2 : 128 / 128 |
| 113 | + GM Priority1/Priority2 : 1 / 1 |
| 114 | + Clock class : cc-time-receiver-only |
| 115 | + GM clock class : cc-primary-sync |
| 116 | + Time source : internal-oscillator |
| 117 | + PTP timescale : yes |
| 118 | + UTC offset : 37 s |
| 119 | + Time traceable : yes |
| 120 | + Freq. traceable : yes |
| 121 | + Offset from GM : -42 ns |
| 122 | + Mean path delay : 1250 ns |
| 123 | + Steps removed : 1 |
| 124 | + |
| 125 | +──────────────────────────────────────────────────────────────────── |
| 126 | +Ports |
| 127 | +PORT INTERFACE STATE DELAY LINK DELAY (ns) |
| 128 | + 1 eth0 time-receiver E2E 0 |
| 129 | + |
| 130 | +──────────────────────────────────────────────────────────────────── |
| 131 | +Message Statistics (▼ rx ▲ tx) |
| 132 | +PORT INTERFACE SYNC ▼ SYNC ▲ ANN ▼ ANN ▲ PD ▼ PD ▲ |
| 133 | + 1 eth0 42 0 15 0 0 0 |
| 134 | +``` |
| 135 | + |
| 136 | +Port state is colour-coded in the live output — green for `time-transmitter` |
| 137 | +and `time-receiver`, yellow for transient states, red for faults. |
| 138 | + |
| 139 | +A port in `time-receiver` state with an offset in the tens-of-nanoseconds |
| 140 | +range confirms that hardware timestamping is working. If the port stays in |
| 141 | +`listening`, check the cable. If the offset is in the milliseconds, re-check |
| 142 | +`ethtool -T eth0` — you may be on software timestamping only. |
| 143 | + |
| 144 | +### gPTP / IEEE 802.1AS |
| 145 | + |
| 146 | +For TSN networks, swap the profile on both devices to `ieee802-dot1as`. The |
| 147 | +profile sets Layer 2 transport and P2P delay measurement implicitly, so no |
| 148 | +per-port configuration is needed. Time-receiver side: |
| 149 | + |
| 150 | +```console |
| 151 | +admin@receiver:/config/> edit ptp instance 0 |
| 152 | +admin@receiver:/config/ptp/instance/0/> set default-ds profile ieee802-dot1as |
| 153 | +admin@receiver:/config/ptp/instance/0/> set default-ds domain-number 0 |
| 154 | +admin@receiver:/config/ptp/instance/0/> set default-ds time-receiver-only true |
| 155 | +admin@receiver:/config/ptp/instance/0/> edit port 1 |
| 156 | +admin@receiver:/config/ptp/…/0/port/1/> set underlying-interface eth0 |
| 157 | +admin@receiver:/config/ptp/…/0/port/1/> leave |
| 158 | +``` |
| 159 | + |
| 160 | +Set `profile ieee802-dot1as` with `priority1 1` on the grandmaster side the |
| 161 | +same way as the IEEE 1588 example above. |
| 162 | + |
| 163 | +### Saving the Configuration |
| 164 | + |
| 165 | +Remember to save your changes for next boot: |
| 166 | + |
| 167 | +```console |
| 168 | +admin@example:/> copy running-config startup-config |
| 169 | +``` |
| 170 | + |
| 171 | +> For boundary clocks, transparent clocks, multiple simultaneous instances, |
| 172 | +> port interval tuning, and monitoring with Wireshark, see the |
| 173 | +> [User's Guide][1]. |
| 174 | +{: .prompt-info } |
| 175 | + |
| 176 | +[1]: https://www.kernelkit.org/infix/latest/ptp/ |
| 177 | +[2]: /posts/router-boards/ |
0 commit comments