はじめに
年末にPPS信号を出力可能なUSBタイプのGPSレシーバーを購入してほったらかしていたが、時間ができたのでNTPサーバを構築してみる。
10年くらい前にも安いUSBタイプのGPSレシーバーを購入して構築したことはあったが、PPS無しだと精度が悪くNICTとかのタイムサービスのクライアントにした方がずっとましだった(PPS信号の出力可能なUSBタイプのGPSレシーバーは値段が高い)。今ではラズパイと安いGPSレシーバーの組み合わせで手軽にPPS使ったNTPサーバを構築できるので、わざわざUSBタイプのGPSレシーバーを使う必要は無いが、動かしたいのは自宅に構築してあるIntel FreeBSDサーバで。
ということで今回構築にあたってネットで調べてみたが、GPSレシーバーのチューニングまで踏み込んだ情報が得られなかったので、検証しながら備忘録代わりに記事を書いてみることにした。
使用する機材
PC&OS
PCが古いのはメインPCを入れ替えたときの余剰パーツでサーバを作ってるため。
項目 | |
---|---|
CPU | Core i7-7700T |
マザーボード | H270M-ITX |
OS | FreeBSD 13.0R |
GPSレシーバー
いずれもAmazonで購入。
GPSレシーバー | モジュール | PPS | 転送速度 | ドライバ |
---|---|---|---|---|
VFAN GPS USBレジーバー( |
UBX-G70xx系(u-blox7) | 無 | 9600(デフォルト),19200,38400,56700,115200 | uplcom |
GLOBALSAT BU-353S4 | EB-5365RC SiRF IV | 無 | 4800(デフォルト),9600,19200,38400 | umodem |
LOCOSYS LS23030-V2 | MediaTek MT3339 | 有 | 115200(デフォルト),230400,46080,921600,3000000 | umodem |
ugen0.4: <u-blox AG - www.u-blox.com u-blox 7 - GPS/GNSS Receiver> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
ugen0.3: <Prolific Technology Inc. USB-Serial Controller D> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
ugen0.5: <Prolific Technology Inc. USB-Serial Controller> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
準備
インストールするソフト
ntpdはOS標準のものを使用。
ソフトウェア | 用途 |
---|---|
gpsd | GPSの動作確認とubxtoolを使ったu-bloxモジュール設定 |
munin | 各remoteのoffsetをグラフにするため、下記のntp_offsetsをテキトーに書き換えたpluginを5分間隔で実行 |
topless | ntpqを定期実行して状態の確認に使用(Linuxのwatchコマンドに相当) |
#!/bin/sh
# -*- sh -*-
nodelay=${nodelay:-}
do_autoconf () {
ntpq -c help >/dev/null 2>&1 || { echo 'no (no ntpq program)'; exit 0; }
case "$(ntpq -n -p 2>/dev/null | wc -l)" in
0)
echo 'no (unable to list peers)'
exit 0
;;
1|2)
echo 'no (no peers?)'
exit 0
;;
*)
echo yes
exit 0
;;
esac
}
do_config () {
cat <<EOF
graph_title NTP Peers
graph_args --base 1000 --vertical-label msec --lower-limit 0
graph_category time
graph_info Currently our peer.
EOF
ntpq -p -w | tail -n +3 | sed -E -e 's/^ ([a-zA-Z])/.\1/g' -e '/^[^ ]*$/ N;s/\n//g' \
| grep -v POOL \
| sed -E -e 's/^(.)([^ .]+)([^ ]*) .*([-+][.0-9]+) +[0-9.]+$/\2.label \1 \2\3/g' | sort
case $nodelay in
1) echo "delay.graph no";;
esac
}
do_ () {
ntpq -p -w | tail -n +3 | sed -E -e 's/^ ([a-zA-Z])/.\1/g' -e '/^[^ ]*$/ N;s/\n//g' \
| grep -v POOL \
| sed -E -e 's/^(.)([^ .]+)([^ ]*) .*([-+][.0-9]+) +[0-9.]+$/\2.value \4/g' | sort
}
case $1 in
autoconf|config|'')
"do_$1"
exit $?
;;
*)
echo "Don't know how to do that" >&2
exit 1
;;
esac
echo 'What am I doing here?' >&2
exit 1
OSの設定
昔のFreeBSDはカーネルコンパイルが必要だったが、今はsysctlの設定だけでPPSを使用できるようになっている(man ucom参照)。
hw.usb.ucom.pps_mode="2"
gps用デバイス
ntpdではデバイスが/dev/gpsN, /dev/ppsN, /dev/gpsppsN(NMEAドライバでPPSを使う場合)と決まっているので、元のttyデバイスのリンクを張る必要がある。ただ、今回使用するBU-353S4とLS23030-V2は同じドライバになっており、検証のために抜き差してデバイス番号変わると面倒。なのでdevdから呼び出したスクリプトでリンクを張る(ついでに転送速度の設定)。なおスクリプトにはGPSレシーバーの設定も追記する予定。
# GPS-353 (UBX-G70xx | u-blox 7)
attach 20 {
device-name "umodem[0-9]+";
match "vendor" "0x1546";
match "product" "0x01a7";
action "/root/bin/gps0.sh $device-name 0";
};
# GLOBALSAT BU-353S4 (G Star IV)
attach 20 {
device-name "uplcom[0-9]+";
match "vendor" "0x067b";
match "product" "0x2303";
action "/root/bin/gps1.sh $device-name 1";
};
# LS23030-V2
attach 20 {
device-name "uplcom[0-9]+";
match "vendor" "0x067b";
match "product" "0x23a3";
action "/root/bin/gps2.sh $device-name 2";
};
#!/bin/sh
sysctl_arg=`echo $1 | sed -e 's/^\([^0-9]*\)\(.*\)$/dev.\1.\2/g'`
ttyname=`sysctl -n ${sysctl_arg}.ttyname`
ln -sf /dev/cua${ttyname} /dev/gps$2
ln -sf /dev/cua${ttyname} /dev/pps$2
stty -f /dev/cua${ttyname}.init 115200
ntpの設定
serverとfudgeのみ抜粋。まず各GPSレシーバーの特性を把握、設定してから運用に入るので、GPSは全部noselect付。またgpsdは使用しない。
参照するタイムサーバはNICT、INTERNET MULTIFEED、Google、Cloudflare。
# GPS-353
server 127.127.20.0 mode 32 minpoll 2 maxpoll 4 iburst noselect
fudge 127.127.20.0 time2 0.000 refid GPS0
# BU-353S4
server 127.127.20.1 mode 0 minpoll 2 maxpoll 4 iburst noselect
fudge 127.127.20.1 time2 0.000 refid GPS1
# LS23030-V2
server 127.127.20.2 mode 80 minpoll 2 maxpoll 4 iburst noselect
fudge 127.127.20.2 time2 0.000 refid GPS2
# LS23030-V2 for PPS
server 127.127.22.2 minpoll 2 noselect
fudge 127.127.22.2 time1 0.000 refid PPS2
pool ntp.nict.jp minpoll 6 maxpoll 9 iburst prefer
server ntp1.jst.mfeed.ad.jp minpoll 6 maxpoll 9 iburst prefer
server ntp2.jst.mfeed.ad.jp minpoll 6 maxpoll 9 iburst prefer
server ntp3.jst.mfeed.ad.jp minpoll 6 maxpoll 9 iburst prefer
server time1.google.com minpoll 6 maxpoll 9 iburst prefer
server time.cloudflare.com nts minpoll 6 maxpoll 9 iburst prefer
GPS-353はNMEAではなくバイナリモードになっていたので、ubxtoolを使ってNMEAモードに変更しておく。
動作確認
検証は数日動かしてから。
remote refid st t when poll reach delay offset jitter
==============================================================================
GPS_NMEA(0) .GPS0. 0 l 2 8 377 0.000 -87.574 2.895
GPS_NMEA(1) .GPS1. 0 l 8 8 377 0.000 -302.28 0.979
GPS_NMEA(2) .GPS2. 0 l 5 8 377 0.000 -107.98 3.214
PPS(2) .PPS2. 0 l 4 8 377 0.000 -108.94 0.031
ntp.nict.jp .POOL. 16 p - 64 0 0.000 +0.000 0.004
#time.cloudflare 10.23.8.4 3 u 247 512 377 174.823 -51.882 6.364
*ntp1.jst.mfeed. 133.243.236.17 2 u 57 512 377 18.306 -2.175 10.588
+ntp2.jst.mfeed. 133.243.236.18 2 u 413 512 377 17.074 -5.456 3.678
+ntp3.jst.mfeed. 133.243.236.19 2 u 144 512 377 18.452 -2.925 4.138
+time1.google.co .GOOG. 1 u 449 512 377 51.406 -3.223 2.745
+ntp-b2.nict.go. .NICT. 1 u 133 512 377 12.050 -4.611 3.268
補足
gpsdによるGPSレシーバー設定変更の抑制
gpsdとかで動作確認してると、NMEAからバイナリモードに変わったりすることがあった。gpsdのドキュメント読んだらgpsdはGPSレシーバーとネゴシエーションして最適な設定に変更するとのこと。設定を変えられたく無い場合は--passiveを付ける。