Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

2.4 时间机器的记忆:PTP数据集全解析

如果PTP设备有大脑,记忆存放在哪里?

你有没有想过,一个PTP设备是如何“记住“事情的?

它记得:

  • 我是谁(clockIdentity)
  • 我现在是什么状态(MASTER还是SLAVE)
  • 我的主时钟是谁(grandmasterIdentity)
  • 我和主时钟差多少时间(offsetFromMaster)
  • 我应该每隔多久发一次Sync报文(logSyncInterval)

这些信息存在哪里?

答案就是:数据集(Data Set)

PTP数据集就像是设备的“记忆库“,存储了协议运行所需的所有状态信息。


数据集的三种“记忆类型“

在深入每个数据集之前,我们先理解数据集成员的三种分类。

静态成员(Static):出厂时决定,永不变

定义:在设备设计时确定,运行期间不会改变。

特点

  • 通常与硬件绑定
  • 不需要运行时计算
  • 不会被协议修改

典型例子

  • clockIdentity:设备的唯一标识,由硬件决定
  • numberPorts:设备有多少个PTP端口,由硬件决定

比喻:就像你的DNA,出生时就决定了,终身不变。


动态成员(Dynamic):协议运行时自动更新

定义:在协议运行过程中,根据收到的报文或测量结果自动更新。

特点

  • 实时变化
  • 不需要人工干预
  • 由协议算法控制

典型例子

  • offsetFromMaster:从时钟与主时钟的时间差,每次同步后更新
  • portState:端口当前状态,由BMCA决定
  • meanDelay:平均路径延迟,每次测量后更新

比喻:就像你的心跳频率,根据身体状况自动调整,不需要你控制。


可配置成员(Configurable):管理员可以改

定义:可以通过管理接口(SNMP、NETCONF、CLI等)修改。

特点

  • 需要管理员主动设置
  • 通常有默认值
  • 可能在运行时改变(如果管理员重新配置)

典型例子

  • priority1priority2:BMCA优先级,管理员可调整
  • domainNumber:域编号,管理员可设置
  • logSyncInterval:Sync报文发送间隔,管理员可调整

比喻:就像你的发型,可以自己决定怎么剪,也可以随时改变。


核心数据集详解

PTP定义了多个数据集,每个数据集负责一类信息。

一、defaultDS:默认数据集

作用:存储PTP实例的身份信息和全局配置。

所属:每个PTP实例一个。

关键成员详解

1. clockIdentity:我是谁
  • 类型:ClockIdentity(8字节)
  • 分类:静态
  • 含义:PTP实例的唯一标识符
  • 生成方式:基于MAC地址、EUI-64或其他唯一标识

为什么需要clockIdentity?

场景一:BMCA决胜

当两个设备的所有优先级属性都相同时,BMCA会比较clockIdentity。clockIdentity小的获胜。

场景二:环路检测

边界时钟在转发Announce报文时,可以在PATH_TRACE TLV中记录经过的clockIdentity列表。如果某个边界时钟发现自己的clockIdentity已经在列表中,说明形成了环路。

场景三:诊断

管理员可以通过clockIdentity快速定位问题设备。

2. numberPorts:我有几个端口
  • 类型:UInteger16
  • 分类:静态
  • 含义:PTP实例的端口数量
  • 取值
    • 普通时钟:1
    • 边界时钟:≥2
    • 透明时钟:≥1

为什么需要numberPorts?

在管理协议中,管理员需要知道设备有多少个端口,以便查询每个端口的状态。

3. clockQuality:我的时钟质量如何
  • 类型:结构体(clockClass + clockAccuracy + offsetScaledLogVariance)
  • 分类:动态
  • 含义:时钟的质量指标

clockQuality的三个成员

clockClass

  • 时钟等级,表示时钟的精度和可溯源性
  • 值越小,等级越高
  • 关键值:6(主参考)、7(保持模式)、248(默认)、255(仅从时钟)

clockAccuracy

  • 时钟精度,表示时钟的预期精度范围
  • 值越小,精度越高
  • 关键值:0x20(≤25ns)、0x22(≤250ns)、0x23(≤1μs)

offsetScaledLogVariance

  • 时钟稳定性,基于Allan方差
  • 值越小,稳定性越好

clockQuality如何变化?

正常状态

  • 设备接GPS,clockClass = 6
  • clockAccuracy根据GPS精度设置,如0x20

GPS信号丢失,但本地原子钟保持

  • clockClass从6变为7
  • clockAccuracy可能略有下降

本地时钟漂移超出规范

  • clockClass从7变为52
  • 表示不再适合做主时钟
4. priority1和priority2:我的优先级
  • 类型:UInteger8(0-255)
  • 分类:可配置
  • 含义:BMCA选举优先级
  • 规则:值越小,优先级越高

priority1 vs priority2的区别

  • priority1:第一优先级,通常用于区分不同“等级“的设备
  • priority2:第二优先级,通常用于区分同一“等级“内的设备

配置策略

设备类型priority1建议值priority2建议值
核心主时钟(GPS+原子钟)1010
一级备份(GPS+铷钟)2010-20
二级备份(GPS+TCXO)3010-30
普通设备128128
仅从设备200-255128
5. domainNumber:我的域
  • 类型:UInteger8(0-255)
  • 分类:可配置
  • 含义:PTP实例所属的域编号
  • 默认值:0
6. slaveOnly:我只能是从时钟吗
  • 类型:Boolean
  • 分类:可配置
  • 含义:该PTP实例是否只能作为从时钟
  • 取值
    • TRUE:永远不能成为主时钟
    • FALSE:可以成为主时钟

什么时候设置slaveOnly=TRUE?

  • 终端设备(工作站、服务器)
  • 不提供时间给他人的设备
  • 只需要同步,不需要被同步的设备

注意:当slaveOnly=TRUE时,clockClass必须设置为255。

7. sdoId:我的Profile归属
  • 类型:UInteger16(低12位有效,0-4095)
  • 分类:可配置
  • 含义:标识PTP实例使用的Profile
  • 默认值:0x000

二、currentDS:当前数据集

作用:存储PTP实例的当前同步状态。

所属:每个PTP实例一个。

关键成员详解

1. stepsRemoved:我离主时钟有多远
  • 类型:UInteger16
  • 分类:动态
  • 含义:到Grandmaster的边界时钟跳数
  • 取值
    • Grandmaster自己:0
    • 直接连接Grandmaster的从时钟:1
    • 再下一级:2
    • 以此类推

如何更新?

我是主时钟(M1/M2决策)

  • stepsRemoved = 0

我是从时钟(S1决策)

  • stepsRemoved = Ebest中的stepsRemoved + 1

示例

Grandmaster A(stepsRemoved = 0)
    ↓
Boundary Clock B(stepsRemoved = 1)
    ↓
Boundary Clock C(stepsRemoved = 2)
    ↓
Slave Clock D(stepsRemoved = 3)

stepsRemoved的作用

作用一:BMCA决策

当两个设备的grandmasterIdentity相同时,比较stepsRemoved。stepsRemoved小的优先。

作用二:防止无限传播

当stepsRemoved ≥ 255时,丢弃Announce报文,防止环路导致无限传播。

2. offsetFromMaster:我和主时钟差多少
  • 类型:TimeInterval(内部单位:纳秒 × 2¹⁶,即约15.26飞秒分辨率)
  • 分类:动态
  • 含义:从时钟时间 - 主时钟时间
  • 取值
    • 正值:从时钟比主时钟快
    • 负值:从时钟比主时钟慢
    • 零:完全同步

如何计算?

在1.4节中,我们已经详细推导了offsetFromMaster的计算公式:

offsetFromMaster = t₂ - originTimestamp - meanDelay - correctionField

其中:

  • t₂:Sync报文的接收时间戳
  • originTimestamp:Sync报文的发送时间戳
  • meanDelay:平均路径延迟
  • correctionField:各种校正值的总和

offsetFromMaster的用途

用途一:相位校正

从时钟根据offsetFromMaster调整自己的时间。如果offsetFromMaster = +1μs,说明从时钟快了1μs,需要减去1μs。

用途二:同步质量监控

管理员可以监控offsetFromMaster的变化,判断同步质量。如果offsetFromMaster剧烈波动,说明网络不稳定或时钟有问题。

3. meanDelay:平均延迟
  • 类型:TimeInterval(纳秒 × 2¹⁶)
  • 分类:动态
  • 含义:平均路径延迟或平均链路延迟
  • 取决于延迟机制
    • E2E机制:meanDelay = meanPathDelay(端到端路径延迟)
    • P2P机制:meanDelay = meanLinkDelay(对等链路延迟)
    • 无延迟机制:meanDelay = 0

如何计算?

在1.4节中,我们已经详细推导了meanPathDelay的计算公式:

meanPathDelay = [(t₂ - t₁) + (t₄ - t₃)] / 2

其中:

  • t₁:Sync报文的发送时间戳
  • t₂:Sync报文的接收时间戳
  • t₃:Delay_Req报文的发送时间戳
  • t₄:Delay_Req报文的接收时间戳

三、parentDS:父时钟数据集

作用:存储关于父PTP实例(上游主时钟)的信息。

所属:每个PTP实例一个。

关键成员详解

1. parentPortIdentity:我的上级是谁
  • 类型:PortIdentity(clockIdentity + portNumber)
  • 分类:动态
  • 含义:父时钟的端口标识

示例

如果从时钟从某个边界时钟的端口2接收时间信号,那么:

  • parentPortIdentity.clockIdentity = 边界时钟的clockIdentity
  • parentPortIdentity.portNumber = 2
2. grandmasterIdentity:终极主时钟是谁
  • 类型:ClockIdentity(8字节)
  • 分类:动态
  • 含义:Grandmaster的标识

parentPortIdentity vs grandmasterIdentity的区别

Grandmaster A
    ↓
Boundary Clock B(端口2)
    ↓
Slave Clock C

对于从时钟C:

  • parentPortIdentity = B的端口2的标识
  • grandmasterIdentity = A的clockIdentity
3. grandmasterClockQuality:主时钟的质量
  • 类型:结构体(clockClass + clockAccuracy + offsetScaledLogVariance)
  • 分类:动态
  • 含义:Grandmaster的时钟质量

从时钟需要知道Grandmaster的质量,以便在Announce报文中传播给下游设备。

4. grandmasterPriority1和grandmasterPriority2
  • 类型:UInteger8
  • 分类:动态
  • 含义:Grandmaster的BMCA优先级

四、timePropertiesDS:时间属性数据集

作用:存储时间尺度和溯源信息。

所属:每个PTP实例一个。

关键成员详解

1. currentUtcOffset:TAI与UTC的差
  • 类型:Integer16
  • 分类:动态(主时钟可配置)
  • 含义:TAI - UTC的当前值
  • 截至2026年:37秒

如何更新?

  • 主时钟:从GPS信号中提取,或人工配置
  • 从时钟:从Announce报文中获取,或人工配置
2. currentUtcOffsetValid:UTC偏移有效吗
  • 类型:Boolean
  • 分类:动态
  • 含义:currentUtcOffset是否有效
  • 取值
    • TRUE:有效
    • FALSE:无效,不应使用

什么时候是FALSE?

  • 主时钟失去GPS信号,无法获取最新的闰秒信息
  • 主时钟的时间源不可靠
3. leap59和leap61:闰秒预告
  • 类型:Boolean
  • 分类:动态
  • 含义
    • leap59=TRUE:当月最后一分钟将有59秒(负闰秒)
    • leap61=TRUE:当月最后一分钟将有61秒(正闰秒)

注意:leap59和leap61不能同时为TRUE。

4. ptpTimescale:使用哪种时间尺度
  • 类型:Boolean
  • 分类:动态(主时钟可配置)
  • 含义
    • TRUE:PTP时间尺度(TAI)
    • FALSE:ARB时间尺度
5. timeTraceable:时间可溯源吗
  • 类型:Boolean
  • 分类:动态
  • 含义:时间是否可溯源到国际标准
6. frequencyTraceable:频率可溯源吗
  • 类型:Boolean
  • 分类:动态
  • 含义:频率是否可溯源到国际标准
7. timeSource:时间源类型
  • 类型:Enumeration8
  • 分类:动态
  • 含义:主时钟的时间来自哪种类型的源
  • 典型值
    • 0x20:GNSS(GPS等)
    • 0x10:ATOMIC_CLOCK(原子钟)
    • 0x50:NTP
    • 0xA0:INTERNAL_OSCILLATOR(内部振荡器)

五、portDS:端口数据集

作用:存储每个PTP端口的状态和配置。

所属:每个PTP端口一个。

关键成员详解

1. portIdentity:端口标识
  • 类型:PortIdentity(clockIdentity + portNumber)
  • 分类:静态
  • 含义:端口的唯一标识
2. portState:端口状态
  • 类型:Enumeration8
  • 分类:动态
  • 含义:端口当前状态
  • 取值
    • 0x01:INITIALIZING
    • 0x02:FAULTY
    • 0x03:DISABLED
    • 0x04:LISTENING
    • 0x05:PRE_MASTER
    • 0x06:MASTER
    • 0x07:PASSIVE
    • 0x08:UNCALIBRATED
    • 0x09:SLAVE
3. logAnnounceInterval:Announce报文间隔
  • 类型:Integer8
  • 分类:可配置
  • 含义:Announce报文的发送间隔,以log₂秒表示
  • 计算:间隔 = 2^(logAnnounceInterval) 秒
  • 默认值:1(即间隔 = 2秒)
  • 典型范围:-3到+4(即125ms到16秒)

示例

logAnnounceInterval间隔
-3125毫秒
-2250毫秒
-1500毫秒
01秒
12秒(默认)
24秒
38秒
416秒
4. announceReceiptTimeout:Announce超时
  • 类型:UInteger8
  • 分类:可配置
  • 含义:未收到Announce报文的超时倍数
  • 计算:超时时间 = announceReceiptTimeout × 2^(logAnnounceInterval)
  • 默认值:3
  • 典型范围:2-10

示例

当logAnnounceInterval=1(间隔2秒)、announceReceiptTimeout=3时:

  • 超时时间 = 3 × 2 = 6秒

如果6秒内未收到Announce报文,触发ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES事件。

5. logSyncInterval:Sync报文间隔
  • 类型:Integer8
  • 分类:可配置
  • 含义:Sync报文的发送间隔,以log₂秒表示
  • 计算:间隔 = 2^(logSyncInterval) 秒
  • 默认值:0(即间隔 = 1秒)
  • 典型范围:-7到+1(即7.8ms到2秒)

为什么通常Sync间隔比Announce间隔小?

Sync报文用于时间同步,频率越高,同步精度越高。

Announce报文用于BMCA,不需要那么频繁,节省带宽。

6. logMinDelayReqInterval:Delay_Req最小间隔
  • 类型:Integer8
  • 分类:动态(主时钟通告)
  • 含义:从时钟发送Delay_Req报文的最小间隔,以log₂秒表示
  • 计算:间隔 = 2^(logMinDelayReqInterval) 秒
  • 默认值:0(即间隔 = 1秒)

为什么是主时钟通告?

主时钟知道自己的处理能力。如果主时钟处理能力有限,可以要求从时钟降低Delay_Req频率,避免过载。

7. delayMechanism:延迟测量机制
  • 类型:Enumeration8
  • 分类:可配置
  • 含义:端口使用的延迟测量机制
  • 取值
    • 0x01:E2E(端到端)
    • 0x02:P2P(对等)
    • 0x03:COMMON_P2P(公共P2P)
    • 0x04:SPECIAL(特殊端口)
    • 0xFE:NO_MECHANISM(无延迟机制)

关键规则

  • 同一PTP通信路径上的所有端口,必须使用相同的delayMechanism
  • 混用E2E和P2P会导致无法正确测量延迟
8. versionNumber和minorVersionNumber:PTP版本
  • 类型:UInteger4
  • 分类:可配置
  • 含义:PTP协议版本
  • IEEE 1588-2019:versionNumber=2, minorVersionNumber=1

数据集之间的关系

关系图

PTP实例
├── defaultDS(身份和配置)
├── currentDS(当前同步状态)
├── parentDS(父时钟信息)
├── timePropertiesDS(时间属性)
└── portDS[](每个端口一个)
    ├── portDS[1]
    ├── portDS[2]
    └── ...

数据流动

主时钟发送Announce报文

主时钟的数据集 → Announce报文
├── defaultDS.clockIdentity → sourcePortIdentity.clockIdentity
├── defaultDS.clockQuality → grandmasterClockQuality
├── defaultDS.priority1 → grandmasterPriority1
├── defaultDS.priority2 → grandmasterPriority2
├── currentDS.stepsRemoved → stepsRemoved
├── timePropertiesDS.currentUtcOffset → currentUtcOffset
└── ...

从时钟接收Announce报文

Announce报文 → 从时钟的数据集
├── sourcePortIdentity → parentDS.parentPortIdentity
├── grandmasterIdentity → parentDS.grandmasterIdentity
├── grandmasterClockQuality → parentDS.grandmasterClockQuality
├── grandmasterPriority1 → parentDS.grandmasterPriority1
├── stepsRemoved + 1 → currentDS.stepsRemoved
└── ...

数据集更新规则

M1/M2决策(我成为主时钟)

当BMCA决定我是主时钟时,按以下规则更新数据集:

currentDS

  • stepsRemoved = 0
  • offsetFromMaster = 0
  • meanDelay = 0

parentDS

  • parentPortIdentity.clockIdentity = defaultDS.clockIdentity
  • parentPortIdentity.portNumber = 0
  • grandmasterIdentity = defaultDS.clockIdentity
  • grandmasterClockQuality = defaultDS.clockQuality
  • grandmasterPriority1 = defaultDS.priority1
  • grandmasterPriority2 = defaultDS.priority2

timePropertiesDS

  • 根据外部时间源(如GPS)更新各项属性

S1决策(我成为从时钟)

当BMCA决定我是从时钟时,按以下规则更新数据集:

currentDS

  • stepsRemoved = Ebest.stepsRemoved + 1

parentDS

  • parentPortIdentity = Ebest.sourcePortIdentity
  • grandmasterIdentity = Ebest.grandmasterIdentity
  • grandmasterClockQuality = Ebest.grandmasterClockQuality
  • grandmasterPriority1 = Ebest.grandmasterPriority1
  • grandmasterPriority2 = Ebest.grandmasterPriority2

timePropertiesDS

  • currentUtcOffset = Ebest.currentUtcOffset
  • leap59 = Ebest.leap59
  • leap61 = Ebest.leap61
  • ptpTimescale = Ebest.ptpTimescale
  • timeTraceable = Ebest.timeTraceable
  • frequencyTraceable = Ebest.frequencyTraceable
  • timeSource = Ebest.timeSource

一个完整的例子

让我们用一个完整的例子,演示数据集如何工作。

场景

主时钟A(接GPS)
    ↓
边界时钟B
    ↓
从时钟C(5G基站)

初始状态

主时钟A的数据集:

数据集成员
defaultDSclockIdentity00-1B-19-00-00-00-00-01
defaultDSclockClass6
defaultDSclockAccuracy0x20
defaultDSpriority110
defaultDSpriority210
defaultDSslaveOnlyFALSE
currentDSstepsRemoved0
timePropertiesDSptpTimescaleTRUE
timePropertiesDScurrentUtcOffset37
timePropertiesDStimeTraceableTRUE
timePropertiesDSfrequencyTraceableTRUE
timePropertiesDStimeSource0x20(GNSS)

主时钟A发送Announce报文

Announce报文内容:

字段
sourcePortIdentity00-1B-19-00-00-00-00-01, portNumber=1
grandmasterIdentity00-1B-19-00-00-00-00-01
grandmasterClockQuality{class:6, accuracy:0x20, variance:…}
grandmasterPriority110
grandmasterPriority210
stepsRemoved0
currentUtcOffset37
ptpTimescaleTRUE
timeTraceableTRUE
frequencyTraceableTRUE
timeSource0x20

边界时钟B接收Announce报文

边界时钟B更新数据集:

数据集成员更新后的值
currentDSstepsRemoved0 + 1 = 1
parentDSparentPortIdentityA的端口1
parentDSgrandmasterIdentity00-1B-19-00-00-00-00-01
parentDSgrandmasterPriority110
timePropertiesDScurrentUtcOffset37
timePropertiesDStimeTraceableTRUE

边界时钟B转发Announce报文

Announce报文内容(更新后):

| 字段 | 值 | |:—|:—|:—| | sourcePortIdentity | B的clockIdentity, portNumber=2 | | grandmasterIdentity | 00-1B-19-00-00-00-00-01 | | grandmasterClockQuality | {class:6, accuracy:0x20, variance:…} | | grandmasterPriority1 | 10 | | stepsRemoved | 1(原值0 + 1) | | currentUtcOffset | 37 |

从时钟C接收Announce报文

从时钟C更新数据集:

数据集成员更新后的值
currentDSstepsRemoved1 + 1 = 2
parentDSparentPortIdentityB的端口2
parentDSgrandmasterIdentity00-1B-19-00-00-00-00-01
timePropertiesDScurrentUtcOffset37

从时钟C的应用

从时钟C的应用层查询时间信息:

问题1:我同步到哪个主时钟?
答案:parentDS.grandmasterIdentity = 00-1B-19-00-00-00-00-01(主时钟A)

问题2:我离主时钟多远?
答案:currentDS.stepsRemoved = 2(经过2个边界时钟)

问题3:我离上级时钟差多少?
答案:currentDS.offsetFromMaster = +125ns(假设当前测量值)

问题4:现在UTC时间是多少?
答案:PTP时间 - timePropertiesDS.currentUtcOffset
     = (当前PTP时间) - 37

小结:数据集的核心要点

数据集分类

  • defaultDS:身份和全局配置
  • currentDS:当前同步状态
  • parentDS:父时钟信息
  • timePropertiesDS:时间属性
  • portDS:端口状态和配置

成员分类

  • 静态:出厂决定,不变
  • 动态:协议运行时自动更新
  • 可配置:管理员可以修改

关键数据集成员

  • defaultDS.clockIdentity:设备唯一标识
  • defaultDS.clockQuality:时钟质量
  • currentDS.offsetFromMaster:时间偏差
  • currentDS.stepsRemoved:到主时钟的跳数
  • parentDS.grandmasterIdentity:主时钟标识
  • timePropertiesDS.currentUtcOffset:闰秒偏移

数据流动

  • 主时钟发送Announce:数据集 → 报文
  • 从时钟接收Announce:报文 → 数据集

下集预告

现在,我们知道了PTP设备如何存储和管理信息。

但还有一个问题:PTP端口有9种状态,它们之间如何转换?什么事件触发状态转换?

下一节,我们将深入讲解端口状态机——PTP协议的“心脏“。你会看到,PTP定义了一套完整的状态转换规则,确保协议的正确运行。

【悬念留给2.5】

你可能好奇:为什么要有INITIALIZING、PRE_MASTER、UNCALIBRATED这些“中间状态“?直接从LISTENING跳到MASTER或SLAVE不行吗?

答案是:不行。这些中间状态是协议稳定性的关键。如果省略它们,可能导致多个设备同时声称自己是主时钟,或者从时钟在未稳定时就开始工作。

下一节,我们详细解读每个状态的作用和转换规则。