一. 简介
早在1985年,业界就提出了NTP(Network Time Protocol)(RFC1305)协议,可以将多台终端的时间同步在500us-50ms的精确度范围以内。在1992年,业界又有了SNTP(Simple Network Time Protocol)协议(RFC2030),可以将多台终端的时间同步在50-150ms的精确度范围以内。之后在2002年,终于又有了更高精度的时间同步协议:PTP(Precision Time Protocol)(IEEE 1588-2002),精度提高到了10ns-100us。后续2008年又提出了v2版本IEEE 1588-2008,进一步将精度提升到了1ns-500ns的时间范围内,这就是目前通用的纳秒级高精度时间同步协议了,也就是本文的重点分析内容。另外,在2019年,还有一篇补充文档IEEE 1588-2019 。再后续,还有针对音视频以及时延敏感网络的 IEEE 802.1AS。
二. 算法原理介绍
PTP的设计原理并不复杂:由一个绝对领导权的master发布时间并对slave们进行时间同步。精髓在于通过带上时间戳的请求及回复,了解双向链路各自的时延情况。
总体来说,一共会有四条消息,时序如下
- T1时间,master发送sync message给slave,收到的时间是T2
- master发送 sync follow up message
- T3时间,slave发送delay request message,收到的时间是T4
- master发送delay respond message
假设master相对slave时间偏差为Toffset
,则T1 + Delay + Toffset == T2
, 即 T2 - T1 == Delay + Toffset
。我们想知道时间偏差,需要将时延的因素给去掉。
另一方面,T3 + Delay - Toffset == T4
, 即 T4 - T3 == Delay - Toffset
所以 Delay == ((T2 - T1) + (T4 - T3)) / 2
时间偏差 Toffset == ((T2 - T1) - (T4 - T3)) / 2
对于slave,则应该将时间更新为time - Toffset
这里实际上在实现机制上存在两种:可以将follow up消息包含在sync message中一起发过去,省略一条消息,这种称之为One-Step Clock,反之则是Two-Step Clock。
为什么需要两种:两步对于那些T1时间创建而并未发送的包有奇效。
BMCA(Best Master Clock Algorithm):确保只有一个grand master的存在,其实现机制类似于raft的leader election。
三. 源码分析
编译LinuxPTP,会得到多个可执行文件,其名字极其功能如下
- hwstamp_ctl(8):用于获取/设置硬件时间戳,利用SIOCSHWTSTAMP ioctl(2)实现,属于debug工具,ptp4l不需要该工具实现时钟设置。
- nsm(8):NetSync Monitor (NSM) client的实现,属于PTP协议扩展内容,用于监控网络内各支持NSM的客户端之间的时钟差值。
- phc2sys(8):核心模块,用于同步系统内两个或者多个时钟。一般是获取来自ptp4ll的时间然后进行操作。
- phc_ctl(8):用于控制PHC时钟设备。
- pmc(8):PTP管理客户端(PTP Management Client)。
- ptp4l(8):核心模块,包含Boundary Clock (BC), Ordinary Clock (OC), and Transparent Clock (TC)几个部分功能。
- timemaster(8):使用ptp4l和phc2sys混合chronyd或者ntpd取同步NTP/PTP时钟源,通过比较选用最佳时钟。
- ts2phc(8):同步PTP硬件时钟(PHC)给外部设备,可用于分发时间。
- tz2alt(8):保存各种修改及时间调节的log到local time zone database。
四. 实现优化
可以通过netmap实现kernal bypass进行效率优化。
五. 智能网卡使用方案
参考思科手册,发现思科的智能网卡支持PPS和PTP两种模式,其中对于PTP多为slave,对部分产品亦可作为master。
六. LinuxPTP(ptp4l) vs ptpd
ptpd是比较早出现的,之后有一个叫做Richard Cochran的大佬发现了ptpd存在诸如版本老旧、代码庞杂且难以阅读、难以维护扩展等问题,并且在社区提出观点后未得到响应,于是自己写了ptp4l,并且意图实现跨操作系统并支持硬件时间戳的ptp版本。