PTP 标准
1588v2是网络测量和控制系统的精密时间同步协议标准,也可称为PTPv2(Precision Time Protocol Version 2,精密时间协议V2版本)。
PTP报文封装方式
IEEE 1588v2协议附录D定义了1588v2 over IPv4的报文封装,
附录E定义了1588v2 over IPv6的报文封装
附录F定义了1588v2 over IEEE 802.3 /Ethernet的报文封装。
-
IP 封装 PTP 报文格式
EVENT消息头的UDP目的端口号是319(Used for SYNC and DELAY_REQUEST messages),General消息的UDP目的端口号是320(All other messages (for example, follow-up, delay-response))。
Name | IP Address | MAC Address mapping |
---|---|---|
DefaultPTPdomain | 224.0.1.129 | 01-00-5E-00-01-81 |
AlternatePTPdomain1 | 224.0.1.130 | 01-00-5E-00-01-82 |
AlternatePTPdomain2 | 224.0.1.131 | 01-00-5E-00-01-83 |
AlternatePTPdomain3 | 224.0.1.132 | 01-00-5E-00-01-84 |
-
以太网封装 PTP 报文格式
Name | MAC address |
---|---|
Normal messages | 01-1B-19-00-00-00 |
Peer delay messages | 01-80-C2-00-00-0E |
PTP v2报文格式
PTP消息头格式
字段 | 长度 | 含义 |
---|---|---|
TranSpec | 4bit | 传送相关: 0–表示PTP消息由1588协议使用 1–表示PTP消息由802.1as协议使用 |
MsgType | 4bit | 表示消息类型。 1588v2消息分为两类:事件消息(EVENT Message)和通用消息(General Message)。 事件报文是时间概念报文,进出设备端口时需要打上精确的时间戳, 而通用报文则是非时间概念报文,进出设备不会产生时戳。 类型值0 ~ 3的为事件消息,8 ~ D为通用消息。 0x00: Sync 0x01: Delay_Req 0x02: Pdelay_Req 0x03:Pdelay_Resp 0x04-7: Reserved 0x08: Follow_Up 0x09: Delay_Resp 0x0A: Pdelay_Resp_Follow_Up 0x0B: Announce 0x0C: Signaling 0x0D: Management 0x0E-0x0F: Reserved |
Reserved1 | 4bit | 保留字段 |
VerPTP | 4bit | 表示1588协议的版本 |
MsgLength | 2byte | PTP消息的长度,即PTP消息的全部字节数目。 计入字节始于报头的第一个字节,同时包含并收尾于任何尾标的最后一个字节,或是无尾标成员时收尾于消息的最后一个字节。 |
DomainNumber | 1byte | 域编号,表示发送该消息时钟所属的域。 |
Reserved2 | 1byte | 保留字段 |
FlagField | 2byte | 标志域(详情在后表) |
CorrectionField | 8byte | 修正域,各报文都有,主要用在Sync报文中,用于补偿网络中的传输时延,E2E的频率同步。 |
Reserved3 | 4byte | 保留字段 |
SourcePortIdentity | 8byte | 源时钟ID |
SourcePortIdentity | 2byte | 源端口ID |
SequenceID | 2byte | 序列号ID,表示消息的序列号,以及关联消息的对应关系。 |
ControlField | 1byte | 控制域,由消息类型决定: 0x00:Sync 0x01:Delay_Req 0x02:Follow_Up 0x03:Delay_Resp 0x04:Management 0x05:All others 0x06-0xFF:reserved |
LogMsgInterval | 1byte | 录入消息周期,PTP消息的发送时间间隔,由消息类型决定。 |
PTP Specified Message Field | n byte | PTP消息体和消息扩展字节。 |
Announce报文格式
OriginTimestamp | 10 bytes | 源时间标签。 |
CurrentUtcOffset | 2 bytes | UTC时间的偏移。 |
Reserved | 1 bytes | 保留字段。 |
GrandmasterPriority1 | 1 bytes | grandmaster clock的优先级1。 |
GrandmasterClockQuality | 4 bytes | grandmaster clock的时钟质量,包括精度、质量等级、稳定度等。 |
GrandmasterPriority2 | 1 bytes | grandmaster clock的优先级2。 |
GrandmasterIdentity | 8 bytes | grandmaster clock的时钟ID。 |
StepsRemoved | 2 bytes | 跳数,距离时间源的路径长度。 |
TimeSource | 1 bytes | grandmaster clock的时钟源。 |
Announce报文携带信息,选出根节点和设备上的根端口(基于STP协议(生成树算法)的自动选源协议,被称为BMCA),从而生成树状的结构
Sync和Delay_Req报文格式
OriginTimestamp | 10 bytes | 源时间标签。 |
Follow Up报文格式
PreciseOriginTimestamp | 10 bytes | 精确源时间标签。PTP提供传输时间戳的机制,这个时间戳包括事件消息产生的时刻和相应的修正域,通过这个机制保证接收方接收到的是最精确的时间戳。在实际应用中时间戳分布在:originTimestamp或者preciseOriginstamp和correctionField中,由具体的执行决定。 |
Delay-Resp报文格式
receiveTimestamp | 10 bytes | Delay_Req消息的接收时间戳。 |
requestingPortIdentity | 10 bytes | 请求端口标识。 |
时钟节点的分层拓扑
时间同步网络中的每个节点,都被称为Clock。1588v2协议定义了三种基本的时钟节点类型:
- OC(Ordinary Clock,普通时钟)
节点仅有一个物理端口同网络通信,既可作为首节点(Grandmaster Clock,最高级时钟)向下游节点发布时间,也可作为末节点(Slave Clock,从时钟)从上游节点同步时间。如1588服务器一般配置为OC模式,作为整个网络的Grandmaster Clock;而用户终端(如:无线基站)作为最末端的Slave Clock设备,也配置为OC模式。
- BC(Boundary Clock,边界时钟)
节点有多个物理端口与网络通信,其中一个端口从上游设备同步时间,其余多个端口向下游设备发布时间。
- TC(Transparent Clock,透明时钟)
节点有多个物理端口与网络通信,只在端口之间处理和转发1588v2协议报文,并不从任何一个端口同步时间。TC节点分成两种类型:E2E TC(End-to-End Transparent Clock)、P2P TC(Peer-to-Peer Transparent Clock)。
E2E TC转发1588v2报文时,可测量报文经过该节点的转发时延,并且修正到1588v2报文中,在两端的OC或者BC节点计算链路时延和时间偏差进行同步。与E2E TC相比,P2P TC不仅修正转发时延,还测量并修正该节点每个端口相连链路的链路时延,在两端的OC或者BC节点计算时间偏差进行同步。
三种基本时钟节点的分层拓扑示例,如下图所示。
1588v2网络一般使用BMC算法动态建立主从层次。BMC算法,是1588v2协议规定的一种动态确定网络中各时钟主从层级的算法。BMC算法通过比较多个时钟的时间源信息(由Announce报文携带),来确定哪一个时钟更好,将网络中的时钟划分为主、从时钟,从时钟跟踪主时钟的频率或者时间。在网络发生变化,或网络中某个时钟源的属性发生改变时,BMC算法能重新选择最佳主时钟,使全网的时钟和时间达到同步。
- 从节点层面看:BMC算法通过Announce报文宣告各端口上的时钟源信息,维护本地获得的时钟数据组,按严格时钟等级选择出最佳时间源,并确定端口状态。
- 从网络层面看:BMC算法建立全网时钟的主从同步体系,确定所有节点之间的主从关系,最终建立一颗无环路、全连通、以Grandmaster Clock为根的一棵树,即生成树。其中Grandmaster Clock为全网最佳的时钟源。
如何进行时间同步的?
1588v2协议定义了两种具体的时间同步机制:E2E(End-to-End,端到端)机制和P2P(Peer-to-Peer,点到点)机制。在支持1588v2的网络中,主时钟节点可以与从时钟节点直接相连,或者隔几个中间节点相连。对于主时钟节点到从时钟节点之间的总链路延迟,E2E和P2P的测量机制不同:
- E2E实际上是直接测量两个OC或者BC之间的总链路延迟,包括其间的所有中间TC节点。
- P2P仅限于测量两个直连相连的OC,BC或者TC节点之间的逐点链路延迟。
E2E机制
E2E机制主从节点之间通过Sync,Delay_Req和Delay_Resp报文交互,使从节点计算出自身与主节点之间的时间偏差,并调整自身的时间以达到和主节点时间同步。主节点发送Sync报文有one-step和two-step模式,对于one-step方式,Sync报文带有本报文发送时刻的时间戳;对于two-step方式,Sync报文并不带有本报文发送时刻的时间戳,而只是记录本报文发送时的时间,由后续报文Follow_Up带上该Sync报文发送时刻的时间戳。
E2E机制实现时间同步过程如下图所示。
E2E机制实现时间同步
- Master在t1时刻发送Sync报文(如果配置为two-step方式,还会发送Follow_Up报文),并将t1时间戳携带在Sync报文(或Follow_Up报文)中;
- Slave在t2时刻接收到Sync报文,在本地产生t2时间戳,并从报文中提取t1时间戳;
- Slave在t3时刻发送Delay_Req报文,并在本地产生t3时间戳;
- Master在t4时刻接收到Delay_Req报文,并在本地产生t4时间戳,然后将t4时间戳携带在Delay_Resp报文中,回传给Slave;
- Slave接收到Delay_Resp报文,从报文中提取t4时间戳。最后Slave节点得到了一组时间戳(t1,t2,t3,t4)。
假设Master到Slave的发送链路延迟是t-ms,Slave到Master的发送链路延迟是t-sm,Slave和Master之间的时间偏差为Offset,则:
t2 - t1 = t-ms + Offset
t4 - t3 = t-sm - Offset
(t2 - t1) - (t4 - t3) = (t-ms + Offset) - (t-sm - Offset)
因此,Offset = [(t2 - t1) - (t4 - t3) - (t-ms - t-sm)] / 2
如果 t-ms = t-sm,即Master和Slave之间的收发链路延迟对称,那么:
Offset = [(t2 - t1) - (t4 - t3)] / 2
这样Slave就可以根据t1,t2,t3,t4 四个时间戳计算出自己和Master之间的时间偏差Offset,再对本地时间进行偏差调整,就实现了Slave与Master的时间同步。
从上述原理可以看出,1588v2时间同步是建立在Master和Slave之间的收发链路延迟对称的基础上的。如果Master和Slave之间的收发链路延迟存在不对称,将引入同步误差,误差的大小为两个方向链路延迟差值的二分之一。因此,对于一些高精度同步场景,需要对Master和Slave之间的收发链路延迟不对称进行补偿。
P2P机制
P2P机制不区分Master/Slave,所有节点都和相邻节点交互P2P报文,从而每个节点都可以计算得到和相邻节点之间的链路延迟。每个节点发送报文也有one-step和two-step模式,对于one-step方式,Pdelay_Resp报文带有本报文发送时刻的时间戳;对于two-step方式,Pdelay_Resp报文并不带有本报文发送时刻的时间戳,只是记录本报文发送时的时间,本报文发送时刻的时间戳由后续报文Pdelay_Resp_Follow_Up携带。
P2P机制计算相连链路延迟如下图所示。
P2P机制计算相连链路延迟
- 节点2在t1时刻发送Pdelay_Req报文;
- 节点1在t2时刻接收到Pdelay_Req报文,生成该报文的接收时间戳t2;
- 节点1在t3时刻发送Pdelay_Resp报文,生成该报文的发送时间戳t3:
- 对于one-step方式,把t3 – t2携带在Pdelay_Resp报文中;
- 对于two-step方式,把t3 – t2携带在Pdelay_Resp_Follow_Up报文中,或者Pdelay_Resp报文携带t2,Pdelay_Resp_Follow_Up报文携带t3;
- 节点2在t4时刻接收到Pdelay_Resp报文,在本地产生t4时间戳;最后节点2得到了一组时间戳(t1,t2,t3,t4)。
假设节点2到节点1的发送链路延迟是t-reqresp,节点1到节点2的发送链路延迟是t-respreq,可以得到节点2到节点1的总链路往返延迟为:
(t-reqresp + t-respreq)= (t4 - t1) - (t3 - t2)
如果t-reqresp = t-respreq,即节点2到节点1之间的收发链路延迟对称,那么节点2和节点1之间的链路平均延迟为:
MeanPathDelay = [(t4 - t1) - (t3 - t2)] / 2
上述过程只是不断地实时计算和更新相连链路延迟,并不进行时间同步。时间同步,还需要有Master到Slave的Sync报文(如下图所示),Master节点向Slave节点周期发送Sync报文(Slave节点得到t5/t6两个时间戳)。最终,Slave相对于Master的时间偏差:
Offset = t6 - t5 - MeanPathDelay
这样Slave就可以根据时间偏差Offset,对本地时间进行偏差调整,就实现与Master的时间同步。
报文LOG
Announce Message Log
Sync Message Log
Follow Message Log
PTP代码工具
ptp4l
GitHub - richardcochran/linuxptp: User space PTP stack for the GNU/Linux operating system.
安装 apt-get install linuxptp
使用ethtool工具查看端口支持软件或硬件时间戳功能ethtool -T ens33,针对虚拟机,只有软件时间戳。
测试指令 主机 ptp4l -4 -i ens33 -m -S 从机 ptp4l -4 -i ens33 -m -S -s
ptpd
GitHub - ptpd/ptpd: PTPd official source - master branch a.k.a. trunk
测试指令 从机 ptpd2 -g -b eth0 -C -L 主机 ptpd2 -W -b eth0 -C -L
# Timestamp, State, Clock ID, One Way Delay, Offset From Master, Slave to Master, Master to Slave, Drift, Last packet Received
One Way Delay:单向延迟均值
Offset From Master: 与主时钟之间的偏移量(以秒为单位)
Slave to Master :从 Delay Request 和 Delay Response 消息计算从机到主机单向延迟
Master to Slave :从 Sync 消息中计算与主机到从机单向延迟
Drift :从时钟和主时钟之间的频率差
使用2个虚拟机测试ptp4l,ptpd;目前存在ptpd主机,ptp4l从机 异常问题?
PTPd 移植适配
RTOS环境移植适配,需修改net.c、sys.c、timer.c、startup.c相关文件
net.c(网络接口修改适配LWIP接口)
sys.c(时钟源适配)
timer.c(定时器适配)
startup.c(启动适配,删除命令行交互)
ptpd.c(任务线程适配,配置修改)
FollowUp,DelayReq均涉及回环报文处理,net中需支持事件发送报文回环处理
可参考如下分支版本相比较ptpd主干版本,stm32_f4_ptpd已经做了RTOS环境部分优化修改
GitHub - mpthompson/stm32_f4_ptpd: IEEE 1588 PTP daemon for STM32 F4 Discovery board
问题修改项
1.Announce报文中stepsRemoved 双字节变量在buf索引61位置 ,直接赋值在移植芯片中存在字节对齐问题,规避处理
2.作为从机时钟同步,在收到FollowUp帧setTime时,因芯片差异,此处不用获取当前时间与之前计算偏移时间的差值。
首次同步时间后,整个状态机重新初始化,当时钟偏差超过秒级后重新时钟同步操作
待优化
ptpd主干版本支持日志相关功能,可优化删除
时间戳定义:GPS, UTC, and TAI Clocks
时间戳转换示例网站:时间戳(Unix timestamp)转换工具 - 在线工具 (daimin.github.io)
GPS计算时间网站:GPS Time Calculator (CN) (labsat.cn)
本地时间是由你的电脑(通过你的网络浏览器看到的)报告的时间和日期。如果你的电脑时钟精确到秒,那么上面显示的其他时间尺度也将精确到秒。
UTC,即协调世界时,通常被称为格林威治标准时间(GMT)或祖鲁时间。本地时间与UTC之间的差异取决于你所在的时区的小时数。北京时间是UTC+8小时
GPS时间是由全球定位系统地面控制站和GPS卫星本身中的原子钟实现的原子时间尺度。GPS时间从1980年6月6日的0点开始计算,由于它不受闰秒的影响,现在GPS时间比UTC时间快了18秒。
Loran-C时间是由Loran-C链发射站中的原子钟实现的原子时间尺度。Loran-C时间从1958年1月1日的0点开始计算,并且由于它也不受闰秒的影响,现在Loran-C时间比UTC时间快了27秒。
TAI,即国际原子时,是基于SI秒连续计数的国际原子时间尺度。目前,TAI比UTC快了37秒。并且TAI总是比GPS时间快了19秒。