2.12 PTP的十种语言:报文格式全解析
如果PTP报文会说话
想象PTP报文是“信使“,在网络中穿梭。
它们携带不同的“信件“:
- Sync:“主时钟说,现在是10:00:00.000000000秒”
- Announce:“我是主时钟,我的clockClass是6,clockAccuracy是0x20”
- Delay_Req:“请告诉我,你什么时候收到这条消息?”
- Delay_Resp:“我在10:00:01.000000100秒收到你的请求”
每种报文都有特定的格式和用途。今天,我们就来“解读“PTP的十种报文。
PTP报文的分类
事件报文(Event Messages)
特点:
- 需要打时间戳
- 精确性要求高
- 通常由硬件处理
报文类型:
| 报文 | 类型值 | 用途 |
|---|---|---|
| Sync | 0x0 | 携带时间信息 |
| Delay_Req | 0x1 | 请求延迟测量 |
| Pdelay_Req | 0x2 | 对等延迟测量请求 |
| Pdelay_Resp | 0x3 | 对等延迟测量响应 |
为什么需要时间戳?
这些报文用于时间同步和延迟测量,必须精确记录发送和接收时间。
通用报文(General Messages)
特点:
- 不需要打时间戳
- 携带配置和状态信息
- 可以由软件处理
报文类型:
| 报文 | 类型值 | 用途 |
|---|---|---|
| Follow_Up | 0x8 | 携带精确时间戳(two-step模式) |
| Delay_Resp | 0x9 | 延迟测量响应 |
| Pdelay_Resp_Follow_Up | 0xA | 对等延迟测量精确时间戳 |
| Announce | 0xB | 主时钟公告 |
| Signaling | 0xC | 信令 |
| Management | 0xD | 管理 |
公共报文头部:所有报文的“信封“
头部结构(34字节)
每个PTP报文都以一个34字节的公共头部开始。
| 字段 | 字节数 | 含义 |
|---|---|---|
| majorSdoId + messageType | 1 | 高4位:sdoId高位;低4位:报文类型 |
| minorVersionPTP + versionPTP | 1 | 高4位:次版本号;低4位:主版本号 |
| messageLength | 2 | 整个报文的字节数 |
| domainNumber | 1 | 域编号 |
| minorSdoId | 1 | sdoId低位 |
| flagField | 2 | 标志位 |
| correctionField | 8 | 校正值 |
| messageTypeSpecific | 4 | 消息类型特定字段 |
| sourcePortIdentity | 10 | 发送端口的标识 |
| sequenceId | 2 | 序列号 |
| controlField | 1 | 控制字段(已过时) |
| logMessageInterval | 1 | 消息间隔 |
关键字段详解
messageType(报文类型)
低4位标识报文类型:
- 0x0:Sync
- 0x1:Delay_Req
- 0x2:Pdelay_Req
- 0x3:Pdelay_Resp
- 0x8:Follow_Up
- 0x9:Delay_Resp
- 0xA:Pdelay_Resp_Follow_Up
- 0xB:Announce
- 0xC:Signaling
- 0xD:Management
高4位(majorSdoId):
用于域隔离(见2.3节)。
domainNumber + sdoId
domainNumber(1字节)+ majorSdoId(高4位)+ minorSdoId(1字节)= 完整的域标识。
flagField(标志位)
16位标志位,各位含义:
| 字节 | 位 | 名称 | 含义 |
|---|---|---|---|
| 0 | 0 | alternateMasterFlag | TRUE表示发送端口不在MASTER状态 |
| 0 | 1 | twoStepFlag | TRUE表示会有Follow_Up |
| 0 | 2 | unicastFlag | TRUE表示单播 |
| 0 | 5-6 | profileSpecific1/2 | Profile定义 |
| 1 | 0 | leap61 | 当月最后一分钟61秒 |
| 1 | 1 | leap59 | 当月最后一分钟59秒 |
| 1 | 2 | currentUtcOffsetValid | UTC偏移有效 |
| 1 | 3 | ptpTimescale | TRUE表示PTP时间尺度 |
| 1 | 4 | timeTraceable | 时间可溯源 |
| 1 | 5 | frequencyTraceable | 频率可溯源 |
| 1 | 6 | synchronizationUncertain | 同步不确定 |
correctionField(校正字段)
8字节有符号整数,表示对报文的校正值。
单位:2⁻¹⁶ 纳秒,即 1/65536 纳秒 ≈ 0.01526皮秒。
换算公式:
- correctionField → 秒:
seconds = correctionField / (65536 × 10⁹) - 纳秒部分:
nanoseconds = correctionField / 65536
示例:
correctionField = 0x0000000000028000(十进制:163840)
值 = 163840 / 65536 = 2.5纳秒
用途:
- 携带小数纳秒部分
- 透明时钟累加驻留时间
- 路径不对称校正值
sourcePortIdentity(发送端口标识)
10字节:
- 前8字节:clockIdentity
- 后2字节:portNumber
示例:
clockIdentity = 00-1B-19-00-00-00-00-01
portNumber = 0x0001
sourcePortIdentity = 00-1B-19-00-00-00-00-01-00-01
sequenceId(序列号)
2字节,标识报文的序号。
用途:
- 关联Sync和Follow_Up
- 关联Delay_Req和Delay_Resp
- 检测丢包
各报文类型详解
Sync报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| originTimestamp | 10 | 44 |
originTimestamp(10字节):
- 6字节:秒部分(整数秒)
- 4字节:纳秒部分
one-step模式:
Sync报文的originTimestamp携带发送时间的整数秒部分,correctionField携带小数纳秒部分。
two-step模式:
Sync报文的originTimestamp为0或估计值,精确时间戳由Follow_Up携带。
Follow_Up报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| preciseOriginTimestamp | 10 | 44 |
preciseOriginTimestamp(10字节):
精确的Sync发送时间戳。
关联规则:
Follow_Up报文的sequenceId必须与对应的Sync报文相同。
Delay_Req报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| originTimestamp | 10 | 44 |
| reserved | 10 | 54 |
originTimestamp:
标准规定设为0(因为从时钟发送时不知道自己时间的准确值)。
reserved字段:
10字节保留字段,必须设为0。
为什么有保留字段?
为了与Pdelay_Req/Pdelay_Resp报文保持相同长度(54字节),简化硬件时间戳单元的设计。
Delay_Resp报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| receiveTimestamp | 10 | 44 |
| requestingPortIdentity | 10 | 54 |
receiveTimestamp(10字节):
主时钟接收Delay_Req的时间。
requestingPortIdentity(10字节):
发送Delay_Req的端口标识(用于关联)。
示例:
从时钟发送Delay_Req(sequenceId = 100)。 主时钟在1000.000001000秒接收Delay_Req。 主时钟发送Delay_Resp:
- receiveTimestamp = 1000.000001000秒
- requestingPortIdentity = 从时钟的portIdentity
- sequenceId = 100
Pdelay_Req报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| originTimestamp | 10 | 44 |
| reserved | 10 | 54 |
reserved字段:
10字节保留字段,使报文长度与Pdelay_Resp一致。
用途:
P2P机制中,测量两个端口之间的链路延迟。
Pdelay_Resp报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| requestReceiptTimestamp | 10 | 44 |
| requestingPortIdentity | 10 | 54 |
requestReceiptTimestamp:
响应者接收Pdelay_Req的时间(t2)。
one-step模式:
Pdelay_Resp的correctionField携带(t3 - t2),即响应者的响应延迟。
two-step模式:
Pdelay_Resp携带t2,Pdelay_Resp_Follow_Up携带t3。
Pdelay_Resp_Follow_Up报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| responseOriginTimestamp | 10 | 44 |
| requestingPortIdentity | 10 | 54 |
responseOriginTimestamp:
响应者发送Pdelay_Resp的时间(t3)。
Announce报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| originTimestamp | 10 | 44 |
| currentUtcOffset | 2 | 46 |
| reserved | 1 | 47 |
| grandmasterPriority1 | 1 | 48 |
| grandmasterClockQuality | 4 | 52 |
| grandmasterPriority2 | 1 | 53 |
| grandmasterIdentity | 8 | 61 |
| stepsRemoved | 2 | 63 |
| timeSource | 1 | 64 |
grandmasterClockQuality(4字节):
| 子字段 | 字节数 | 含义 |
|---|---|---|
| clockClass | 1 | 时钟类别 |
| clockAccuracy | 1 | 时钟精度 |
| offsetScaledLogVariance | 2 | 方差(对数刻度) |
stepsRemoved:
到Grandmaster的边界时钟跳数。
timeSource:
Grandmaster的时间源类型(如GNSS、原子钟)。
用途:
- 主时钟广播自己的信息
- 用于BMCA决策
- 传播时间属性(UTC偏移、闰秒等)
Signaling报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| targetPortIdentity | 10 | 44 |
| 后缀(TLV序列) | 可变 | 44+ |
用途:
- 单播协商
- 路径追踪
- 其他信令功能
后缀:
一个或多个TLV(Type-Length-Value)实体。
Management报文
格式:
| 字段 | 字节数 | 累计 |
|---|---|---|
| 公共头部 | 34 | 34 |
| targetPortIdentity | 10 | 44 |
| startingBoundaryHops | 1 | 45 |
| boundaryHops | 1 | 46 |
| reserved | 1 | 47 |
| actionField | 1 | 48 |
| reserved | 1 | 49 |
| managementTLV | 可变 | 49+ |
actionField:
- 0:GET(读取)
- 1:SET(设置)
- 2:RESPONSE(响应)
- 3:COMMAND(命令)
- 4:ACKNOWLEDGE(确认)
用途:
- 配置PTP设备
- 查询状态
- 故障诊断
报文长度汇总
| 报文类型 | 基础长度(字节) | 备注 |
|---|---|---|
| Sync | 44 | 可加TLV |
| Delay_Req | 54 | 可加TLV,含10字节保留 |
| Follow_Up | 44 | 可加TLV |
| Delay_Resp | 54 | 可加TLV |
| Pdelay_Req | 54 | 含10字节保留 |
| Pdelay_Resp | 54 | 可加TLV |
| Pdelay_Resp_Follow_Up | 54 | 可加TLV |
| Announce | 64 | 可加TLV,含1字节保留 |
| Signaling | 44+ | 头部+TLV序列 |
| Management | 49+ | 头部+管理TLV |
一个完整的报文示例
Sync报文(one-step)
十六进制表示:
00 01 00 2C // majorSdoId=0, messageType=0x0(Sync), minorVersion=1, version=2, length=44
00 00 00 00 // domainNumber=0, minorSdoId=0
00 00 // flagField=0
00 00 00 00 00 00 00 00 // correctionField=0
00 00 00 00 // messageTypeSpecific=0
00 1B 19 00 00 00 00 01 00 01 // sourcePortIdentity
00 64 // sequenceId=100
00 00 // controlField=0, logMessageInterval=0
00 00 00 00 03 E8 // originTimestamp秒=1000(6字节UInteger48)
00 00 00 00 // originTimestamp纳秒=0
解读:
- 报文类型:Sync
- PTP版本:2.1
- 域:0
- 发送端口:clockIdentity=00-1B-19-00-00-00-00-01, portNumber=1
- 序列号:100
- 发送时间:1000.000000000秒
Announce报文
十六进制表示(简化):
0B 01 00 40 // messageType=0xB(Announce), minorVersion=1, version=2, length=64
00 00 00 00 // domainNumber=0, minorSdoId=0, flagField=0
...
00 1B 19 00 00 00 00 01 00 01 // sourcePortIdentity
00 64 // sequenceId=100
...
00 00 00 00 00 00 00 00 // originTimestamp=0
00 25 // currentUtcOffset=37
00 // reserved
0A // grandmasterPriority1=10
06 20 00 00 // clockClass=6, clockAccuracy=0x20, variance=0
0A // grandmasterPriority2=10
00 1B 19 00 00 00 00 01 // grandmasterIdentity
00 00 // stepsRemoved=0
20 // timeSource=0x20(GNSS)
解读:
- 报文类型:Announce
- 报文长度:64字节
- 发送端口:clockIdentity=00-1B-19-00-00-00-00-01, portNumber=1
- Grandmaster信息:
- priority1=10, priority2=10
- clockClass=6, clockAccuracy=0x20
- timeSource=GNSS
- stepsRemoved=0(发送者自己就是Grandmaster)
小结:PTP报文的核心要点
报文分类:
- 事件报文:需要时间戳(Sync、Delay_Req、Pdelay_Req、Pdelay_Resp)
- 通用报文:不需要时间戳(Follow_Up、Delay_Resp、Pdelay_Resp_Follow_Up、Announce、Signaling、Management)
公共头部:
- 34字节
- 包含报文类型、域标识、校正字段、发送端口等
关键报文:
- Sync:时间同步
- Announce:主时钟公告
- Delay_Req/Resp:E2E延迟测量
- Pdelay系列:P2P延迟测量
报文关联:
- 通过sequenceId关联相关报文
- 通过sourcePortIdentity标识发送者
报文长度要点:
- Sync/Follow_Up:44字节
- Delay_Req/Pdelay系列:54字节
- Announce:64字节
下集预告
PTP报文格式是固定的,但有时需要扩展功能。
下一节,我们将讲解TLV扩展机制——如何在固定格式基础上,灵活扩展PTP功能。
【悬念留给2.13】
你可能注意到:PTP报文有一个“后缀“部分,可以携带TLV。
TLV是什么?它能做什么?
- PATH_TRACE TLV:记录报文经过的路径
- CUMULATIVE_RATE_RATIO TLV:携带频率信息
- AUTHENTICATION TLV:安全认证
下一节,我们详细解读TLV扩展机制。