在工业网络、广电音视频、分布式测量和金融交易系统里,PTP(Precision Time Protocol,IEEE 1588)承担着把微秒级时间偏差传递到每台设备的任务。一个 PTP 域中必须有一个最高时间源,叫做 Grandmaster(GM,主时钟)。商用 Grandmaster 设备通常价格不低,如果只是搭建测试环境、做实验室授时或验证 PTP 同步链路,完全可以用 GNSS 接收器、一块支持硬件时间戳的网卡和 Linux 时间同步软件栈,自己搭出一台 Stratum 1 级别的 PTP Grandmaster。本文会从 PTP 授时原理开始,逐步完成硬件选型、驱动验证、chrony 驯服、PHC 校准、ptp4l 发布,最后用 Wireshark 抓包和从时钟验证结果。
搭建这套系统的过程,本质上是在解决三个时间同步问题:系统时钟如何锁定 GNSS 绝对时间、网卡 PHC 如何获得与系统时钟一致的时间基准、PTP 协议如何把这个时间基准发布给网络中的从时钟。三个问题各自对应一个软件组件:chrony、phc2sys、ptp4l。只要把这三层链路打通,一台低成本 PTP Grandmaster 就基本完成。为了让读者在动手前对整条链路有整体认识,下面先讲清楚 PTP Grandmaster 干什么,以及预算方案为什么可行。
1. PTP Grandmaster 是什么,为什么预算方案可行
这一节先澄清概念,再描述本文方案的整体架构。很多读者会在 NTP 资料里见过 Stratum 1,在 PTP 资料里见过 Grandmaster,两者之间有关系但不完全等价,先说明这一点可以避免后续配置时产生混淆。
1.1 Stratum 1 与 Grandmaster 的关系
在 NTP 体系里,Stratum 1 表示“直接连接参考时钟源的 NTP 服务器”。参考时钟源可以是 GNSS 接收机、铷原子钟或广播时码,它本身通常被看作 Stratum 0。系统只要直接从参考时钟取时,就能作为 Stratum 1 时间服务器向网络提供时间。
在 IEEE 1588 PTP 体系里,没有 Stratum 的概念,取而代之的是 Grandmaster。每一个 PTP 域通过 BMCA(Best Master Clock Algorithm,最佳主时钟算法)从所有时钟节点中选出一个 Grandmaster,其他节点同步到它。Grandmaster 是否可信,用 clockClass、clockAccuracy、offsetScaledLogVariance 等时钟质量参数描述,而不是用 NTP 的 stratum 表示。
工程实践中,人们经常把“直接由 GNSS 基准源驯服、对外提供 PTP 服务的主时钟”称为 Stratum 1 PTP Grandmaster。这是一个方便的混用说法,重点其实是:这台设备的时间来自 GNSS,并且以 PTP 协议对外发布时间。理解了这一层,配置时就知道目标不是简单跑起 ptp4l,而是让 ptp4l 发出去的每一个时间戳都真正对齐 GNSS UTC 时间。
1.2 预算方案通过软件链路实现 GM
商用 PTP Grandmaster 通常把 GNSS 接收机、高稳晶振、PTP 硬件引擎集成在一台设备里,通过硬件模块直接生成 PTP 报文时间戳。预算方案没有专用硬件,因此要用软件链路把时间一级一级传递下去:
- GNSS 接收机输出 NMEA 报文和 1PPS 脉冲。
- chrony 读取 NMEA 得到绝对时间,读取 1PPS 得到精确到纳秒级的秒边界,把系统时钟驯服到 GNSS。
- phc2sys 以系统时钟为基准,校准网卡的 PTP Hardware Clock(PHC)。
- ptp4l 从 PHC 读取硬件时间戳并生成 Sync、Announce、Follow_Up 等 PTP 报文,对外作为 Grandmaster 工作。
这个软件链路里,最关键的是步骤 3 和 4 不能颠倒。ptp4l 作为 Grandmaster 时,使用的是网卡 PHC 的时间,而不是系统时钟时间。如果 PHC 没有先校准,PTP 报文携带的时间就会偏离 UTC 数秒甚至数十年。很多第一次搭建的人只启动了 ptp4l,看到 Master 角色已经起来,但 Slave 端永远无法同步,原因往往就在这里。
1.3 本文搭建目标与适用边界
本文最终目标是让读者得到一台可以正常对外发布 PTP 时间的 Grandmaster,并能够用第二台设备作为 Slave 验证同步误差。整套方案适合这些场景:
- 实验室内部搭建 PTP 测试环境。
- 音视频设备、工业控制设备联调时需要本地 PTP 主时钟。
- 验证 PTP 协议行为、分析报文、学习硬件时间戳机制。
- 需要一台低成本 GPS 驯服时钟作为开发平台。
需要提前说明的是,软件链路方案和电信级商用设备有差距。商用设备通常在硬件层面将 GNSS 1PPS 直接驯服本地振荡器,并直接生成 PTP 时间戳,端到端误差可以做到几十纳秒量级。预算方案通过系统时钟和 PHC 校准,通常能做到几百纳秒到几微秒的端到端误差。这个精度对绝大多数实验和中小型网络足够,但如果目标是电信级同步,还是应该采用专用设备或带 GNSS 输入的时钟卡。
2. 理解 PTP 授时原理,才能把硬件选对
很多人配置 PTP 时只记住命令,不理解报文交互,导致问题出现后无从排查。这一节用较短的篇幅讲清楚 PTP 授时的核心机制,其中“硬件时间戳”这个点直接决定硬件选型,必须重点理解。
2.1 PTP 的同步过程:Sync、Follow_Up、Delay_Req、Delay_Resp
PTP 同步的核心思想是测量主时钟和从时钟之间的时间偏差以及网络路径延迟。假设已经选出 Grandmaster,主时钟会周期性地发送 Sync 报文。如果采用 two-step 模式,主时钟发送 Sync 后,再发送一条 Follow_Up 报文,里面携带 Sync 报文离开主时钟时的精确时间戳 T1。
从时钟在本地记录 Sync 报文到达时间 T2,然后发送 Delay_Req 报文,记录发送时间 T3。主时钟收到 Delay_Req 后记录到达时间 T4,并通过 Delay_Resp 报文把 T4 回传给从时钟。
根据这四个时间戳,从时钟可以计算出主从时间偏差 offset 和网络路径延迟 delay:
- delay = ((T2 - T1) + (T4 - T3)) / 2
- offset = (T2 - T1) - delay
这个计算成立的前提是网络上下行路径延迟对称。实际网络中,交换队列、链路速率、报文优先级都会影响对称性,这也是精度无法无限提高的原因之一。PTP 报文通常会打上 802.1p 优先级别,交换机也会尽量优先转发 PTP 事件报文,从而减少排队抖动。
2.2 硬件时间戳为什么是关键
PTP 有两种打时间戳的方式:软件时间戳和硬件时间戳。软件时间戳在报文进入内核协议栈、应用层收发时由系统读取时间,中间经过中断、调度、协议栈处理,延迟可能是几十微秒甚至毫秒级,并且抖动很大。
硬件时间戳由网卡在报文离开物理网口、到达物理网口的瞬间读取时间,延迟稳定在纳秒级。对 Grandmaster 来说,硬件时间戳尤其重要,因为 Sync 报文携带的时间戳必须是“报文真正离开网线的那一瞬间”。如果这个时间戳是软件时间戳,即使系统时钟被 GPS 驯服得很好,PTP 从时钟算出来的 offset 也会被打上很大的噪声。
所以,搭建 PTP Grandmaster 时,承担 PTP 业务的网卡必须支持硬件时间戳,最好支持 PTP Hardware Clock。可以通过 ethtool -T 命令在购买前或装机后确认。
2.3 Grandmaster 如何被选出
PTP 域启动后,每个节点先处于监听状态,周期性地发送 Announce 报文,并接收其他节点的 Announce 报文。Announce 报文里携带时钟质量信息,包括 priority1、clockClass、clockAccuracy、offsetScaledLogVariance、priority2 和 clockIdentity。
BMCA 会比较这些参数,优先级从高到低大致是:
- 接收方是否在该端口上收到更优的 Announce 报文。
- priority1 数值更小的胜出。
- clockClass 数值更小的胜出。
- clockAccuracy 数值更小的胜出。
- offsetScaledLogVariance 数值更小的胜出。
- priority2 数值更小的胜出。
- clockIdentity 数值更小的胜出。
当网络中只有一台候选主时钟时,它自然成为 Grandmaster。如果网络中已经存在其他 PTP 时钟,想让自己成为 Grandmaster,可以调低 priority1,或者配置 masterOnly 让节点只做主时钟。这里要注意,直接把所有节点的 priority1 调成相同值,BMCA 依然会根据后面几项完成比较,不会出现“无人做主时钟”的静止状态。
2.4 PTP 报文类型速查
在后续 Wireshark 分析中会频繁看到这些报文,先整理成一张表:
| 报文类型 | 作用 | 消息编码 | 备注 |
|---|---|---|---|
| Sync | 主时钟发送的同步报文 | 0x0 | 事件报文,需要打硬件时间戳 |
| Announce | 广播时钟质量,供 BMCA 选主 | 0x1 | 普通报文 |
| Follow_Up | two-step 模式下携带 Sync 精确发送时间 | 0x2 | 普通报文 |
| Delay_Req | 从时钟发送的延迟请求 | 0x3 | 事件报文 |
| Delay_Resp | 主时钟回传 Delay_Req 到达时间 | 0x4 | 普通报文 |
| PDelay_Req | 用于 peer delay 机制 | 0x5 | 点对点延时测量 |
| PDelay_Resp | peer delay 响应 | 0x6 | 点对点延时测量 |
默认情况下,PTP 报文可以通过 UDP 319/320 端口传输,也可以直接封装在以太网二层,使用以太网类型 0x88F7。后续抓包时可以根据这两种特征设置抓包过滤器。
3. 预算硬件选型参考
本节从实用角度给出硬件选型建议。预算方案的精髓是:GNSS 负责绝对时间,网卡负责精确时间戳,主机只负责运行软件。所以钱应该花在 GNSS 接收机天线和网卡上,主机配置可以普通一些。
3.1 GNSS 接收机:NMEA 与 1PPS 缺一不可
预算方案里,GNSS 接收机需要同时提供两种信号:
- NMEA 报文:包含经纬度、UTC 时间、日期、卫星状态,用于提供绝对秒信息。
- 1PPS 脉冲:每秒输出一个上升沿,用于提供高精度的秒边界。
常见的 u-blox 系列模块以及多种国产 GPS/BDS 模块都支持 1PPS 输出。选型时优先选择带 timing 或 survey 能力的型号,这些型号在静态授时场景下表现更稳定。如果没有特殊授时型号,使用普通 GNSS 模块也足够做实验,但要注意模块必须能通过某个 GPIO 输出 1PPS。
天线同样重要。预算方案最容易忽略天线位置,GNSS 模块放在室内、靠近金属窗框、被 USB 供电线挡住,都会导致搜星缓慢或定位不稳固。建议使用有源 GNSS 天线,并将天线固定在窗外,确保上方有足够开阔的天空视野。天线接口通常是 SMA 或 IPEX,需要根据模块选配转接线。
3.2 主机与网卡:硬件时间戳是底线
主机可以使用 x86 小主机、旧笔记本或者 NanoPi 一类开发板,只要能运行完整 Linux 内核、具备串口或 USB 接口连接 GNSS 模块即可。性能要求很低,双核处理器、1GB 内存都可以跑完整链路。
真正决定成败的是 PTP 网卡。建议选择明确支持 IEEE 1588 或 802.1AS 的网卡,常见的有:
- Intel I210、I211、I225、I226 系列。
- 集成在部分服务器主板上的 Intel X550、X710 等。
- 部分 Mellanox 网卡也支持硬件时间戳,但驱动和应用配置差异较大。
用树莓派做预算方案时要注意:树莓派板载网卡不一定支持 PTP 硬件时间戳。如果网卡不支持,ptp4l 会退化为软件时间戳,PTP 从端误差会明显增大。可以用外接 USB 转千兆网卡,但 USB 以太网芯片也要确认是否支持 IEEE 1588 硬件时间戳。
3.3 预算分层配置参考
下面给出三个档位的配置参考。价格会随市场变化,这里只描述相对定位:
| 档位 | 主机 | 网卡 | GNSS | 适合场景 |
|---|---|---|---|---|
| 入门实验档 | 树莓派或旧笔记本 | 板载或 USB,软件时间戳可接受 | 普通 GNSS 模块 | 学习 PTP 协议、验证报文旅程 |
| 常规预算档 | x86 小主机 | Intel I210/I225 | 带 1PPS 的 u-blox 模块 | 实验室 PTP 授时、从端精度验证 |
| 偏生产档 | 带 PCIe 的工控机 | 双口 Intel 网卡 | 授时型 GNSS 模块 + 有源天线 | 需要长时间稳定运行和更好精度 |
入门档只能帮助你理解 PTP 工作流程,不能作为严格意义上的高精度 Grandmaster。常规预算档是本文主要描述的目标。
4. 系统准备与基础能力验证
硬件到位后,先不要急着配置 PTP,而是先把操作系统基础能力验证一遍。这一节的目标是确认 GNSS 数据能读、PPS 设备存在、网卡硬件时间戳可用。三项验证全部通过后,再进入时间同步配置。
4.1 系统与内核模块准备
本文以 Debian/Ubuntu 类系统为例,CentOS/RHEL 系也可以通过对应包管理器安装。系统建议使用较新的内核,至少 5.x,这样 PPS 和 PHC 驱动支持比较完整。
先更新系统:
sudo apt update sudo apt upgrade -y安装需要用到的软件包:
sudo apt install -y linuxptp chrony gpsd gpsd-clients pps-tools ethtool tshark其中 linuxptp 提供 ptp4l 和 phc2sys,chrony 负责系统时间驯服,gpsd 负责读取 GNSS 串口数据并共享给 chrony,pps-tools 提供 ppstest,ethtool 用来验证网卡时间戳能力,tshark 用于命令行抓包,也可以只安装 wireshark 使用图形界面。
连接 GNSS 模块后,查看设备节点:
ls -l /dev/ttyUSB* /dev/ttyACM* /dev/pps* dmesg | grep -E "usb|tty|pps"如果 GNSS 模块通过 USB 转串口连接,通常会看到 /dev/ttyUSB0。如果 PPS 引脚也接入 USB 转串口芯片的 DCD 引脚,会生成 /dev/pps0。如果使用的是 GPIO PPS,需要先加载 pps-gpio 驱动,并在设备树或内核参数中做对应配置。
4.2 验证 GNSS NMEA 数据
先直接用串口工具读取 GNSS 数据,确认模块能收到卫星信号并输出 UTC 时间:
sudo gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock sudo gpspipe -r -n 5正常输出会包含 $GPGGA、$GPRMC 等 NMEA 句子。重点看 GGA 或 RMC 里的 UTC 时间、定位状态和卫星数:
$GPRMC,081405.00,A,3115.1111,N,12134.2222,E,0.0,0.0,150223,0.0,E,A*3E- A 表示定位有效。
- 081405.00 表示 UTC 时间 08:14:05。
- 3115.1111,N 是经纬度信息。
如果一直输出逗号占位没有具体数值,或者状态为 V,说明天线信号太弱或者模块还没完成定位,先把天线移到视野开阔的位置。
4.3 验证 PPS 设备
使用 pps-tools 自带的 ppstest 检查 PPS 是否每秒产生一个脉冲:
sudo ppstest /dev/pps0正常输出:
trying PPS source "/dev/pps0" found PPS source "/dev/pps0" ok, found 1 source(s), now start fetching data... source 0 - assert 1676533944.999999920, sequence: 12345 source 0 - assert 1676533945.999999912, sequence: 12346注意两点:
- assert 时间后面的秒数应该逐秒递增。
- 连续两个脉冲之间的间隔应该接近 1 秒。
如果 /dev/pps0 不存在,常见原因是内核没有启用 PPS 支持,或者 USB 转串口的 DCD 引脚没有接 PPS 信号。还有一种情况是 GNSS 模块在未定位成功时不会输出 PPS,需要先让模块定位。
4.4 验证网卡硬件时间戳能力
查看 PTP 业务网卡的时间戳能力:
ethtool -T eth0