Kenyon Ralph

Time server

This page documents my project to build a stratum 1 NTP time server at my house. Its hostname is einstein.kenyonralph.com.

  1. GPS selection
  2. Cable Construction
  3. GPS preparation
  4. Debian GNU/Linux setup
  5. FreeBSD setup
    1. /etc/rc.conf
    2. /etc/devfs.conf
    3. /etc/ttys
    4. Kernel configuration
    5. /etc/make.conf
    6. /etc/ntp.conf
    7. Example output
  6. Conclusion
  7. Notes
  8. References

GPS selection

I selected the Garmin GPS 18x LVC for the following reasons:

I ordered the 18x (and a serial cable) on Amazon on 2011-09-05. UPS delivered it on 2011-09-09.

Cable Construction

I simply spliced the GPS 18x LVC wires onto serial and USB wires. This matches what’s documented in Garmin’s GPS 18x LVC Technical Specifications.

GPS preparation

I used a Windows Vista computer with Garmin’s SNSRXCFG_270.exe to upgrade the firmware from version 3.60 to the latest, 3.70. I also used SNSRXCFG_270.exe to set the PPS pulse width to 200 ms, and disable all NMEA sentences except GPGGA.

Debian GNU/Linux setup

Here are the steps in summary (written for Debian wheezy in February 2015):

Some details:

When you do sudo ldattach PPS /dev/ttyS0, the PPS modules will be loaded automatically and the device /dev/pps0 will be created. Place some udev rules in /etc/udev/rules.d/77-local.rules to create device symlinks and run ldattach automatically:

SUBSYSTEM=="pps", MODE="0664" GROUP="dialout"
KERNEL=="ttyS2", RUN+="/bin/stty --file=/dev/ttyS2 9600"
KERNEL=="ttyS2" SYMLINK+="gps0"
KERNEL=="pps0" SYMLINK+="gpspps0"

systemd unit to run ldattach (enable with systemctl enable ldattach@ttyS2):

[Unit]
Description=PPS Line Discipline for GPS Timekeeping for %i
Before=ntpd.service

[Service]
ExecStart=/usr/sbin/ldattach pps /dev/%i
Type=forking

[Install]
WantedBy=multi-user.target

Here is my working ntp.conf:

rlimit memlock -1
driftfile /var/lib/ntp/ntp.drift
restrict localhost
restrict default limited noquery
server darwin.kenyonralph.com iburst
pool 2.pool.ntp.org iburst
server 127.127.20.0 mode 16 minpoll 3 iburst
fudge 127.127.20.0 flag1 1 flag2 0 flag3 1 time2 0.545
leapfile /etc/ntp/leap-seconds.list

Example output after letting ntpd run for about 8 hours:

kenyon@einstein ~ % ntpq -ccv -p -crv -ckern -csysinfo
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPGGA,172617,1111.3839,N,11111.4417,W,2,11,0.8,126.3,M,-35.5,M,,*71",
poll=3418, noreply=0, badformat=0, baddata=0, fudgetime2=545.000,
stratum=0, refid=GPS, flags=5
        remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
    2.us.pool.ntp.o .POOL.          16 p    -   64    0    0.000    0.000   0.000
oGPS_NMEA(0)     .GPS.            0 l    -    8  377    0.000    0.000   0.004
+darwin.kenyonra 127.67.113.92    2 u   50   64  377   28.478    4.232   0.953
-2001:470:c:4a1: 131.188.3.220    2 u   45   64  377  200.027   11.259   0.586
-2604:a880:800:1 184.105.182.7    3 u   39   64  377   82.776    4.196   1.805
-ntp.jtsage.com  216.218.254.202  2 u   24   64  377   69.561   -1.286   0.490
-2604:a880:800:1 184.105.182.7    3 u   46   64  377   82.421    3.827   0.603
*yurizoku.tk     209.51.161.238   2 u   59   64  377   80.916    1.554   0.619
+198.110.48.12 ( 204.9.54.119     2 u   35   64  377  100.437    1.796   1.330
-108.61.194.85 ( 201.198.247.252  2 u   53   64  377   45.230   -5.521   1.041
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
version="ntpd 4.2.8p1@1.3265-o Mon Feb  9 09:59:02 UTC 2015 (1)",
processor="x86_64", system="Linux/3.16.7-ckt2", leap=00, stratum=1,
precision=-23, rootdelay=0.000, rootdisp=1.015, refid=GPS,
reftime=d884bdb9.bc1f69e3  Tue, Feb 10 2015  9:26:17.734,
clock=d884bdba.e1639551  Tue, Feb 10 2015  9:26:18.880, peer=27173, tc=3,
mintc=3, offset=-0.000130, frequency=-13.457, sys_jitter=0.004033,
clk_jitter=0.051, clk_wander=0.031, tai=35, leapsec=201507010000,
expire=201512280000
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
pll offset:            0
pll frequency:         -13.4565
maximum error:         0.0015
estimated error:       3.4e-05
kernel status:         pll ppsfreq ppstime ppssignal nano
pll time constant:     3
precision:             1e-06
frequency tolerance:   500
pps frequency:         -13.4874
pps stability:         0.280609
pps jitter:            0.050
calibration interval   256
calibration cycles:    152
jitter exceeded:       45
stability exceeded:    2
calibration errors:    0
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
system peer:        GPS_NMEA(0)
system peer mode:   client
leap indicator:     00
stratum:            1
log2 precision:     -23
root delay:         0.000
root dispersion:    1.015
reference ID:       GPS
reference time:     d884bdb9.bc1f69e3  Tue, Feb 10 2015  9:26:17.734
system jitter:      0.004033
clock jitter:       0.051
clock wander:       0.031
broadcast delay:    0.000
symm. auth. delay:  0.000

I also tried setting up a time server with FreeBSD to see if it’s any easier or better.

FreeBSD setup

This section was written in October 2011. I no longer run this FreeBSD system. I’m running the NTP server on the Linux machine described above.

I am using ntp-devel from ports.

/etc/rc.conf

ntpd_enable="YES"
ntpd_flags="-N -p /var/run/ntpd.pid -f /var/db/ntpd.drift"
ntpd_program="/usr/local/sbin/ntpd"
ntpd_sync_on_start="YES"

/etc/devfs.conf

link cuau0 gps0

/etc/ttys

Commented out ttyu*.

Kernel configuration

Put this in /usr/src/sys/amd64/conf/PPS-GENERIC:

#
# PPS -- Generic kernel configuration file for FreeBSD/amd64 PPS
#
include GENERIC
ident PPS-GENERIC
options PPS_SYNC

/etc/make.conf

KERNCONF= PPS-GENERIC GENERIC

/etc/ntp.conf

server 127.127.20.0 minpoll 3
fudge 127.127.20.0 flag1 1 flag2 0 flag3 1 time2 0.600
server darwin.kenyonralph.com iburst
server voodoo.kenyonralph.com iburst
server grunt.kenyonralph.com iburst
pool 2.us.pool.ntp.org iburst

Example output

Example output after running for a few minutes and while doing buildworld and buildkernel:

kenyon@gauss ~ % ntpq -p -c clockvar -c readvar; ntpdc -c kerninfo
        remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
oGPS_NMEA(0)     .GPS.            0 l   38   64  377    0.000    0.648   0.249
    2.us.pool.ntp.o .POOL.          16 p    -   64    0    0.000    0.000   0.002
*darwin.kenyonra 127.67.113.92    2 u   63   64  377   20.431    3.263   3.354
-voodoo.kenyonra 106.61.18.129    3 u   61   64  377    0.243    4.485   0.124
+grunt.kenyonral 106.61.18.129    3 u   64   64  377    0.182    3.521   0.225
-conquest.kjsl.c 69.36.224.15     2 u   62   64  377   26.374    5.768   2.522
-bindcat.fhsu.ed 128.138.140.44   2 u   63   64  377   75.219    4.115   1.846
-peachesgeldof.k 204.9.54.119     2 u   64   64  377   94.141    3.787   2.844
-ip-173-201-38-8 198.153.152.52   2 u   58   64  377   24.752    6.104   1.801
-druid.storyinme 130.207.244.240  2 u   56   64  377   65.657   -2.773   4.542
+cheezum.mattnor 129.7.1.66       2 u   65   64  377   45.797    2.972   2.286
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPGGA,085740,1111.1111,N,11111.1111,W,1,09,0.9,103.2,M,-35.3,M,,*77",
poll=14, noreply=0, badformat=0, baddata=0, fudgetime2=600.000,
stratum=0, refid=GPS, flags=5
associd=0 status=04ad leap_none, sync_uhf_radio, 10 events, kern,
version="ntpd 4.2.7p225@1.2483-o Fri Oct 21 04:59:50 UTC 2011 (1)",
processor="amd64", system="FreeBSD/9.0-RC1", leap=00, stratum=1,
precision=-19, rootdelay=0.000, rootdisp=2.380, refid=GPS,
reftime=d24d03df.edabdc26  Sat, Oct 22 2011  1:57:03.928,
clock=d24d0405.3f696dad  Sat, Oct 22 2011  1:57:41.247, peer=38673, tc=6,
mintc=3, offset=0.648, frequency=-4.048, sys_jitter=0.249,
clk_jitter=0.000, clk_wander=0.005
pll offset:           0.000624065 s
pll frequency:        -4.048 ppm
maximum error:        2.0824e-05 s
estimated error:      1.7e-08 s
status:               2007  pll ppsfreq ppstime nano
pll time constant:    6
precision:            1e-09 s
frequency tolerance:  496 ppm
kenyon@gauss ~ % ntpq -c "rv 38673"
associd=38673 status=973a conf, reach, sel_pps.peer, 3 events, sys_peer,
srcadr=GPS_NMEA(0), srcport=123, dstadr=127.0.0.1, dstport=123, leap=00,
stratum=0, precision=-20, rootdelay=0.000, rootdisp=0.000, refid=GPS,
reftime=d24d03de.ffd6d0b6  Sat, Oct 22 2011  1:57:02.999,
rec=d24d03df.edabdc26  Sat, Oct 22 2011  1:57:03.928, reach=377,
unreach=0, hmode=3, pmode=4, hpoll=6, ppoll=6, headway=0, flash=00 ok,
keyid=0, offset=0.648, delay=0.000, dispersion=0.928, jitter=0.249,
filtdelay=     0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00,
filtoffset=    0.65    0.70    0.76    0.80    0.86    0.91    0.99    1.06,
filtdisp=      0.00    0.96    1.92    2.88    3.84    4.80    5.76    6.72

Here is what kerninfo looks like with the PPS_SYNC kernel option:

pll offset:           0.000123674 s
pll frequency:        -3.918 ppm
maximum error:        0.000111415 s
estimated error:      1.51e-07 s
status:               2107  pll ppsfreq ppstime ppssignal nano
pll time constant:    6
precision:            1e-09 s
frequency tolerance:  496 ppm
pps frequency:        -3.918 ppm
pps stability:        0.033 ppm
pps jitter:           4.729e-06 s
calibration interval: 64 s
calibration cycles:   27
jitter exceeded:      5
stability exceeded:   0
calibration errors:   10

Conclusion

FreeBSD is much nicer than Linux (as of late 2011) at being a stratum 1 NTP server using a NMEA GPS with PPS reference clock.

As of early 2015, I would say it’s about an equal amount of effort between FreeBSD and Debian Linux. Debian Linux is a little more effort if you want to create a proper Debian package of NTP.

Notes

References

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. Revision History.