🕒

PTP を使ったLinux時刻同期の設定方法

2024/11/20に公開

概要

PTP(Precision Time Protocol)は、サーバー時刻をとても正確に合わせるための仕組みです。
これはNTP(chrony)というよく使われている仕組みよりもさらに高い精度で時間を合わせることができます。
PTPを使うと、100ナノ秒(1秒の1億分の1)以内の誤差で時間を合わせることが期待できます。

PTPはNTPほど多く使われていませんが、同じネットワーク内でとても正確な時間合わせが必要なときには、とても便利な仕組みです。

ハードウェアの確認

NIC のハードウェアサポートを確認する方法

PTP でハードウェアタイムスタンプが使えるか確認するには、ethtoolコマンドを使います。

ethtool -T eth1
Time stamping parameters for eth1:
Capabilities:
    hardware-transmit     (SOF_TIMESTAMPING_TX_HARDWARE)
    software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)
    hardware-receive      (SOF_TIMESTAMPING_RX_HARDWARE)
    software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)
    software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
    hardware-raw-clock    (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 0

出力結果で、以下のパラメータが表示されていることを確認します。

ハードウェアタイムスタンプを使う場合

  • hardware-raw-clock SOF_TIMESTAMPING_RAW_HARDWARE
  • hardware-transmit SOF_TIMESTAMPING_TX_HARDWARE
  • hardware-receive SOF_TIMESTAMPING_RX_HARDWARE

ソフトウェアタイムスタンプを使う場合

  • software-system-clock SOF_TIMESTAMPING_SOFTWARE
  • software-transmit SOF_TIMESTAMPING_TX_SOFTWARE
  • software-receive SOF_TIMESTAMPING_RX_SOFTWARE

PTP の通信について

PTPはUDPの319ポート ptp-event と、320ポート ptp-general を使用します。
グランドマスターからは1秒ごとにマルチキャストパケットが送信され、スレーブからも1秒ごとにパケットが送信されます。
ファイアウォールでこれらのポートを許可する必要があります。

ファイアウォールを開ける

次のコマンドでUDPの319と320ポートを開けます。

firewall-cmd --add-port=319/udp --permanent
firewall-cmd --add-port=320/udp --permanent
firewall-cmd --reload

PTP のインストール

まず、PTP をインストールします。

dnf install linuxptp -y

これで ptp4lphc2sys という 2 つのツールがインストールされます。

PTP の設定

ptp4l の設定

/etc/sysconfig/ptp4l ファイルを編集して NIC の名前を設定します。

vi /etc/sysconfig/ptp4l

次のようにオプションを指定します(eth1でPTPを受ける場合)

OPTIONS="-f /etc/ptp4l.conf -i eth1"

/etc/ptp4l.conf ファイルの作成

以下は ptp4l の設定ファイル例です。
下記はPTP ProfileをSMPTE ST2059にした場合の例です。
同期先のグランドマスター装置の設定に合わせて調整してください。

[global]
# ドメイン番号(SMPTE ST 2059では127を指定)
domainNumber 127

# ネットワークトランスポートの設定(UDP over IPv4)
network_transport UDPv4

# アナウンス間隔(ログ秒):2^-2 = 0.25秒(250ミリ秒)
logAnnounceInterval -2

# 同期間隔(ログ秒):2^-3 = 0.125秒(125ミリ秒)
logSyncInterval -3

# 遅延要求間隔(ログ秒):2^-3 = 0.125秒(125ミリ秒)
logMinDelayReqInterval -3

# アナウンスタイムアウト(アナウンスメッセージのタイムアウト回数)
announceReceiptTimeout 3

# 優先度1(デフォルトは128)
priority1 255

# 優先度2(デフォルトは128)
priority2 255

# 遅延メカニズム(デフォルトはE2E)
delay_mechanism E2E

# P2P遅延要求間隔(ログ秒):2^0 = 1秒
# E2Eモードでは使用されませんが、互換性のために設定
logMinPdelayReqInterval 0

# クロッククラス(デフォルトは248)
clockClass 248

# クロック精度(デフォルトは0xFE)
clockAccuracy 0xFE

# オフセットスケールログのばらつき(デフォルトは0xFFFF)
offsetScaledLogVariance 0xFFFF

# 時間源(デフォルトは0xA0)
timeSource 0xA0

# スレーブ専用モードを有効にする
slaveOnly 1

# ハードウェアタイムスタンプの有効化(デフォルトは0)
use_syslog 1

# マスター専用モード(デフォルトは0)
masterOnly 0

# `transportSpecific` フィールドを無視する
ignore_transport_specific 1

# ログの有効化
verbose 1

ptp4l の起動

次のコマンドで ptp4l を起動します

ptp4l -i eth1 -m -s

次のコマンドで phc2sys を起動します

phc2sys -a -r -m

同期確認

PTP の同期状態を確認するには、以下のコマンドを実行します。

pmc -u -b0 'GET CURRENT_DATA_SET' -d 127
sending: GET CURRENT_DATA_SET
        844709.fffe.0e3b53-0 seq 0 RESPONSE MANAGEMENT CURRENT_DATA_SET
                stepsRemoved     1
                offsetFromMaster -36.0
                meanPathDelay    3261.0
  • stepsRemoved: 最上位クロックまでのホップ数
  • offsetFromMaster: マスタークロックとの時刻差(ナノ秒単位)
  • meanPathDelay: マスタークロックからの同期メッセージの遅延予測値(ナノ秒単位)
pmc -u -b0 'GET TIME_STATUS_NP' -d 127
sending: GET TIME_STATUS_NP
        844709.fffe.0e3b53-0 seq 0 RESPONSE MANAGEMENT TIME_STATUS_NP
                master_offset              -5
                ingress_time               1719292412888503147
                cumulativeScaledRateOffset +0.000000000
                scaledLastGmPhaseChange    0
                gmTimeBaseIndicator        0
                lastGmPhaseChange          0x0000'0000000000000000.0000
                gmPresent                  true
                gmIdentity                 001747.fffe.d959bd
  • gmPresent: true であれば、マスタークロックと正常に同期しています。

サービスとして自動起動する設定

ptp4lphc2sys をサービスとして設定し、システム起動時に自動的に起動するようにします。

ptp4l のサービス化

サービスファイルを作成します。

vi /etc/systemd/system/ptp4l.service

内容は以下の通りです。

[Unit]
Description=Precision Time Protocol (PTP) service
After=network-online.target

[Service]
ExecStart=/usr/sbin/ptp4l -f /etc/ptp4l.conf -i eth1 -m
Restart=on-failure

[Install]
WantedBy=multi-user.target

サービスを有効化して起動します。

systemctl enable ptp4l
systemctl start ptp4l

phc2sys のサービス化

同様に、サービスファイルを作成します。

vi /etc/systemd/system/phc2sys.service

内容は以下の通りです。

[Unit]
Description=PHC to System Clock Synchronization Service
After=ptp4l.service

[Service]
ExecStart=/usr/sbin/phc2sys -s /dev/ptp1 -c CLOCK_REALTIME -O 0 -m
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target

サービスを有効化して起動します。

systemctl enable phc2sys
systemctl start phc2sys

これで、システム起動時に自動的に ptp4lphc2sys が起動し、PTP の時刻同期が行われるようになります。

Discussion