test append
3. Network Time Protocol (网络时间协议)
本节包含 Network Time Protocol (网络时间协议, NTP) 的正式定义, 包括其数据格式, 实体, 状态变量, 事件和事件处理过程. 规范基于图1所示的实现模型, 但并不意味着该模型是规范可以基于的唯一模型. 特别是, 该规范旨在说明和阐明 NTP 的内在操作, 并作为更严格, 全面和可验证规范的基础.
3.1. Data Formats (数据格式)
本文中所有明确或隐含的数学运算均采用二进制补码定点算术. 数据被指定为整数或定点量, 位从零开始以大端方式从左 (高位) 开始编号. 由于各种实现可能会缩放外部派生的量以供内部使用, 因此不指定定点量的精度或小数点位置. 除非另有说明, 所有量均为无符号量, 可以占据完整字段宽度, 位零前面有一个隐含的零. 设计用于处理有符号量的硬件和软件包在最高有效 (符号) 位被设置时会产生令人惊讶的结果. 建议将外部派生的无符号定点量 (如时间戳) 在内部使用时右移一位, 因为完整字段宽度所代表的精度很少是合理的.
由于 NTP 时间戳是珍贵的数据, 实际上代表了协议的主要产品, 因此建立了一种特殊的时间戳格式. NTP 时间戳表示为64位无符号定点数, 以秒为单位, 相对于1900年1月1日0时. 整数部分在前32位, 小数部分在后32位. 这种格式允许方便的多精度算术和转换为 Time Protocol (时间协议) 表示 (秒), 但确实使转换为 ICMP Timestamp message (ICMP 时间戳消息) 表示 (毫秒) 变得复杂. 这种表示的精度约为200皮秒, 对于即使是最特殊的要求也应该足够.
时间戳通过在某些重要事件 (如消息到达) 发生时将本地时钟的当前值复制到时间戳来确定. 为了保持最高精度, 重要的是尽可能靠近与事件相关的硬件或软件驱动程序来完成此操作. 特别是, 应为每次链路级重传重新确定出发时间戳. 在某些情况下, 特定时间戳可能不可用, 例如当主机重新启动或协议首次启动时. 在这些情况下, 64位字段设置为零, 表示该值无效或未定义.
请注意, 自1968年某个时间以来, 最高有效位 (整数部分的第0位) 已被设置, 并且64位字段将在2036年某个时间溢出. 如果 NTP 在2036年仍在使用, 将需要某种外部手段来限定相对于1900年的时间和相对于2036年的时间 (以及136年的其他倍数). 需要此类限定的带时间戳数据将非常珍贵, 以至于适当的手段应该很容易获得. 每136年将存在一个200皮秒的间隔 (此后忽略), 在此期间64位字段将为零, 因此被认为无效.
3.2. State Variables and Parameters (状态变量和参数)
以下是协议使用的各种状态变量和参数的摘要. 它们被分为几类: system variables (系统变量), 与操作系统环境和本地时钟机制相关; peer variables (对等节点变量), 表示特定于每个对等节点的协议机器状态; packet variables (数据包变量), 表示 NTP 消息的内容; 以及 parameters (参数), 表示当前版本所有实现的固定配置常量. 对于每个类别, 变量的描述后跟其名称以及控制它的过程或值. 请注意, 变量使用小写字母, 而参数使用大写字母. 格式和使用的其他详细信息在后面的章节和附录中介绍.
3.2.1. Common Variables (公共变量)
以下变量对系统, 对等节点和数据包类别中的两个或多个是公共的. 其他变量特定于附录 C 中描述的可选认证机制. 当需要区分同名的公共变量时, 将使用变量标识符.
Peer Address (peer.peeraddr, pkt.peeraddr), Peer Port (peer.peerport, pkt.peerport): 这些是对等节点的32位互联网地址和16位端口号.
Host Address (peer.hostaddr, pkt.hostaddr), Host Port (peer.hostport, pkt.hostport): 这些是主机的32位互联网地址和16位端口号. 它们包含在状态变量中以支持多宿主.
Leap Indicator (sys.leap, peer.leap, pkt.leap): 这是一个两位代码, 警告即将在 NTP 时间尺度中插入闰秒. 这些位在插入日的23:59之前设置, 并在次日00:00之后重置. 这导致插入日的秒数 (滚动间隔) 增加或减少一秒. 对于主服务器, 这些位由操作员干预设置, 而对于辅助服务器, 这些位由协议设置. 两个位, 分别为第0位和第1位, 编码如下:
| 值 | 含义 |
|---|---|
| 00 | 无警告 |
| 01 | 最后一分钟有61秒 |
| 10 | 最后一分钟有59秒 |
| 11 | 告警条件 (时钟未同步) |
在除告警条件 (11₂) 之外的所有情况下, NTP 本身对这些位不做任何处理, 只是将它们传递给不属于 NTP 的时间转换例程. 告警条件发生在本地时钟由于任何原因未同步时, 例如首次启动或在没有主要参考源可用的较长时间之后.
Mode (peer.mode, pkt.mode): 这是一个整数, 指示关联模式, 值编码如下:
| 值 | 模式 |
|---|---|
| 0 | 未指定 |
| 1 | 对称主动 |
| 2 | 对称被动 |
| 3 | 客户端 |
| 4 | 服务器 |
| 5 | 广播 |
| 6 | 保留用于 NTP 控制消息 |
| 7 | 保留用于私人使用 |
Stratum (sys.stratum, peer.stratum, pkt.stratum): 这是一个整数, 指示本地时钟的层级, 值定义如下:
| 值 | 含义 |
|---|---|
| 0 | 未指定 |
| 1 | 主要参考 (例如, 校准的原子钟, 无线电时钟) |
| 2-255 | 辅助参考 (通过 NTP) |
出于比较目的, 零值被认为大于任何其他值. 请注意, 编码为数据包变量的整数的最大值受参数 NTP.MAXSTRATUM 的限制.
Poll Interval (sys.poll, peer.hostpoll, peer.peerpoll, pkt.poll): 这是一个有符号整数, 指示传输消息之间的最小间隔, 以2的幂次方表示的秒数. 例如, 值6表示最小间隔为64秒.
Precision (sys.precision, peer.precision, pkt.precision): 这是一个有符号整数, 指示各种时钟的精度, 以最接近2的幂次方表示的秒数. 该值必须四舍五入到下一个更大的2的幂次方; 例如, 50Hz (20ms) 或60Hz (16.67ms) 电源频率时钟将被分配值-5 (31.25ms), 而1000Hz (1ms) 晶体控制时钟将被分配值-9 (1.95ms).
Root Delay (sys.rootdelay, peer.rootdelay, pkt.rootdelay): 这是一个有符号定点数, 指示到同步子网根部主要参考源的总往返延迟, 以秒为单位. 请注意, 此变量可以取正值和负值, 具体取决于时钟精度和偏斜.
Root Dispersion (sys.rootdispersion, peer.rootdispersion, pkt.rootdispersion): 这是一个有符号定点数, 指示相对于同步子网根部主要参考源的最大误差, 以秒为单位. 只有大于零的正值是可能的.
Reference Clock Identifier (sys.refid, peer.refid, pkt.refid): 这是一个32位代码, 标识特定的参考时钟. 对于层级0 (未指定) 或层级1 (主要参考源), 这是一个四字节, 左对齐, 零填充的 ASCII 字符串. 例如:
| 层级 | 代码 | 含义 |
|---|---|---|
| 0 | DCN | DCN 路由协议 |
| 0 | TSP | TSP 时间协议 |
| 1 | ATOM | 原子钟 (校准) |
| 1 | WWVB | WWVB LF (5频段) 无线电 |
| 1 | GOES | GOES UHF (9频段) 卫星 |
| 1 | WWV | WWV HF (7频段) 无线电 |
对于层级2及以上 (辅助参考), 这是选择用于同步的对等节点的四字节互联网地址.
Reference Timestamp (sys.reftime, peer.reftime, pkt.reftime): 这是本地时钟最后更新时的本地时间, 以时间戳格式表示. 如果本地时钟从未同步, 则该值为零.
Originate Timestamp (peer.org, pkt.org): 这是对等节点发送其最新 NTP 消息时的本地时间, 以时间戳格式表示. 如果对等节点变得不可达, 则该值设置为零.
Receive Timestamp (peer.rec, pkt.rec): 这是来自对等节点的最新 NTP 消息到达时的本地时间, 以时间戳格式表示. 如果对等节点变得不可达, 则该值设置为零.
Transmit Timestamp (peer.xmt, pkt.xmt): 这是 NTP 消息离开发送方时的本地时间, 以时间戳格式表示.
3.2.2. System Variables (系统变量)
表1显示了完整的系统变量集. 除了前面描述的公共变量外, 操作系统还使用以下变量来同步本地时钟.
Local Clock (sys.clock): 这是当前本地时间, 以时间戳格式表示. 本地时间从特定机器的硬件时钟派生, 并根据所使用的设计以不同间隔递增. 第5节描述了包括调整和偏斜补偿机制的适当设计.
Clock Source (sys.peer): 这是一个选择器, 标识当前同步源. 通常这将是一个指向包含对等节点变量的结构的指针. 特殊值 NULL 表示当前没有有效的同步源.
3.2.3. Peer Variables (对等节点变量)
表2显示了完整的对等节点变量集. 除了前面描述的公共变量外, 对等节点管理和测量功能还使用以下变量.
Configured Bit (peer.config): 这是一个位, 指示关联是从配置信息创建的, 如果对等节点变得不可达, 不应解除.
Update Timestamp (peer.update): 这是收到最近 NTP 消息时的本地时间, 以时间戳格式表示. 用于计算偏斜离散度.
Reachability Register (peer.reach): 这是一个 NTP.WINDOW 位的移位寄存器, 用于确定对等节点的可达性状态, 位从最低有效 (最右) 端进入. 如果此寄存器中至少有一位设置为1, 则认为对等节点可达.
Peer Timer (peer.timer): 这是一个整数计数器, 用于控制传输 NTP 消息之间的间隔. 一旦设置为非零值, 计数器以一秒间隔递减, 直到达到零, 此时调用传输过程. 请注意, 此计时器的操作独立于本地时钟更新, 这意味着计时系统和间隔计时器系统架构必须相互独立.
3.2.4. Packet Variables (数据包变量)
表3显示了完整的数据包变量集. 除了前面描述的公共变量外, 还定义了以下变量.
Version Number (pkt.version): 这是一个整数, 指示发送方的版本号. NTP 消息将始终以当前版本号 NTP.VERSION 发送, 如果版本号与 NTP.VERSION 匹配, 将始终被接受. 在版本号更改时, 可能会根据具体情况提供例外. 附录 D 中总结了本版本与以前版本 NTP 之间互操作的具体指南.
3.2.5. Clock-Filter Variables (时钟过滤变量)
当使用第4节中建议的过滤和选择算法时, 除了前面描述的变量外, 还定义了以下状态变量.
Filter Register (peer.filter): 这是一个 NTP.SHIFT 级的移位寄存器, 每级存储一个3元组, 由与单次观测相关的测量延迟, 测量偏移量和计算离散度组成. 这些3元组从最高有效 (最左) 端进入, 向最低有效 (最右) 端移动, 并随着新观测的到来最终被丢弃.
Valid Data Counter (peer.valid): 这是一个整数计数器, 指示过滤寄存器中剩余的有效样本. 用于确定可达性状态以及何时应增加或减少轮询间隔.
Offset (peer.offset): 这是一个有符号定点数, 指示对等节点时钟相对于本地时钟的偏移量, 以秒为单位.
Delay (peer.delay): 这是一个有符号定点数, 指示对等节点时钟相对于本地时钟通过它们之间网络路径的往返延迟, 以秒为单位. 请注意, 此变量可以取正值和负值, 具体取决于时钟精度和偏斜误差累积.
Dispersion (peer.dispersion): 这是一个有符号定点数, 指示对等节点时钟相对于本地时钟通过它们之间网络路径的最大误差, 以秒为单位. 只有大于零的正值是可能的.
3.2.6. Authentication Variables (认证变量)
当使用附录 C 中建议的认证机制时, 除了前面描述的变量外, 还定义了以下状态变量. 这些变量仅在实现附录 C 中描述的可选认证机制时使用.
Authentication Enabled Bit (peer.authenable): 这是一个位, 指示关联将在认证模式下运行.
Authenticated Bit (peer.authentic): 这是一个位, 指示从对等节点收到的最后一条消息已被正确认证.
Key Identifier (peer.hostkeyid, peer.peerkeyid, pkt.keyid): 这是一个整数, 标识用于生成消息认证码的加密密钥.
Cryptographic Keys (sys.key): 这是一组64位 DES 密钥. 每个密钥按 Berkeley Unix 发行版中的方式构建, 由八个字节组成, 其中每个字节的七个低位对应于 DES 位1-7, 高位对应于 DES 奇偶校验位8.
Crypto-Checksum (pkt.check): 这是由加密过程计算的加密校验和.
3.2.7. Parameters (参数)
表4显示了在互联网系统中运行的所有实现假定的参数. 为了避免不必要的网络开销和稳定的对等关联, 有必要就这些参数的值达成一致. 以下参数假定为固定的, 适用于所有关联.
Version Number (NTP.VERSION): 这是当前 NTP 版本号 (3).
NTP Port (NTP.PORT): 这是互联网号码分配机构分配给 NTP 的端口号 (123).
Maximum Stratum (NTP.MAXSTRATUM): 这是可以编码为数据包变量的最大层级值, 也被子网路由算法解释为 "无穷大" 或不可达.
Maximum Clock Age (NTP.MAXAGE): 这是参考时钟在最后一次更新后被认为有效的最大间隔, 以秒为单位.
Maximum Skew (NTP.MAXSKEW): 这是在 NTP.MAXAGE 确定的间隔内由于本地时钟偏斜引起的最大偏移误差, 以秒为单位. 比率 φ = NTP.MAXSKEW / NTP.MAXAGE 被解释为由于所有原因引起的最大可能偏斜率.
Maximum Distance (NTP.MAXDISTANCE): 当使用第4节中建议的选择算法时, 这是可接受用于同步的对等节点的最大同步距离.
Minimum Poll Interval (NTP.MINPOLL): 这是互联网系统中任何对等节点允许的最小轮询间隔, 以2的幂次方表示的秒数.
Maximum Poll Interval (NTP.MAXPOLL): 这是互联网系统中任何对等节点允许的最大轮询间隔, 以2的幂次方表示的秒数.
Minimum Select Clocks (NTP.MINCLOCK): 当使用第4节中建议的选择算法时, 这是可接受用于同步的最小对等节点数.
Maximum Select Clocks (NTP.MAXCLOCK): 当使用第4节中建议的选择算法时, 这是考虑选择的最大对等节点数.
Minimum Dispersion (NTP.MINDISPERSE): 当使用第4节中建议的过滤算法时, 这是每个层级的最小离散度增量, 以秒为单位.
Maximum Dispersion (NTP.MAXDISPERSE): 当使用第4节中建议的过滤算法时, 这是最大对等节点离散度和缺失数据假定的离散度, 以秒为单位.
Reachability Register Size (NTP.WINDOW): 这是可达性寄存器 (peer.reach) 的大小, 以位为单位.
Filter Size (NTP.SHIFT): 当使用第4节中建议的过滤算法时, 这是时钟过滤器 (peer.filter) 移位寄存器的大小, 以级为单位.
Filter Weight (NTP.FILTER): 当使用第4节中建议的过滤算法时, 这是用于计算过滤器离散度的权重.
Select Weight (NTP.SELECT): 当使用第4节中建议的选择算法时, 这是用于计算选择离散度的权重.