From gitlab at mg.gitlab.com Tue Aug 12 00:14:56 2025 From: gitlab at mg.gitlab.com (Hal Murray (@hal.murray)) Date: Tue, 12 Aug 2025 00:14:56 +0000 Subject: [Git][NTPsec/ntpsec][master] CI: Update two Debian jobs Message-ID: <689a8780c7e27_2cd67f4258a8@gitlab-sidekiq-low-urgency-cpu-bound-v2-554588f964-vkjzk.mail> Hal Murray pushed to branch master at NTPsec / ntpsec Commits: a56c0197 by James Browning at 2025-08-11T17:11:02-07:00 CI: Update two Debian jobs - - - - - 2 changed files: - .gitlab-ci.yml - .gitlab-opttest-ci.yml Changes: ===================================== .gitlab-ci.yml ===================================== @@ -95,9 +95,9 @@ AsciiDoc-classic3-Debian-Old: - DEBIAN_FRONTEND="noninteractive" apt-get install -y python3-dev asciidoc-base - python3 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build --disable-nts -AsciiDoc-classic2-Debian-Old: +AsciiDoc-classic-Python2: <<: *job_definition - image: $CI_REGISTRY/ntpsec/ntpsec/debian-oldstable + image: $CI_REGISTRY/ntpsec/ntpsec/python2 script: - apt-get update - DEBIAN_FRONTEND="noninteractive" apt-get install -y python2-dev asciidoc-base ===================================== .gitlab-opttest-ci.yml ===================================== @@ -95,7 +95,7 @@ freebsd-options-tester: rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' -.deb_old_option_tester: &deb_old_option_tester +.deb_oldold_option_tester: &deb_oldold_option_tester stage: test needs: [] script: @@ -112,9 +112,9 @@ debian-i386-options-tester: image: i386/debian:stable-slim <<: *deb_option_tester_py3_only -debian-oldstable-options-tester: - image: debian:oldstable-slim - <<: *deb_old_option_tester +debian-oldoldstable-options-tester: + image: debian:oldoldstable-slim + <<: *deb_oldold_option_tester debian-stable-options-tester: image: debian:stable-slim View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/commit/a56c0197c5383c33351c67c6f67378f677d6ee52 -- View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/commit/a56c0197c5383c33351c67c6f67378f677d6ee52 You're receiving this email because of your account on gitlab.com. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gitlab at mg.gitlab.com Tue Aug 12 00:20:55 2025 From: gitlab at mg.gitlab.com (Hal Murray (@hal.murray)) Date: Tue, 12 Aug 2025 00:20:55 +0000 Subject: [Git][NTPsec/ntpsec][master] 3 commits: Make the CI jobs more correct in function Message-ID: <689a88e743f6a_2cd6844758eb@gitlab-sidekiq-low-urgency-cpu-bound-v2-554588f964-znhh8.mail> Hal Murray pushed to branch master at NTPsec / ntpsec Commits: 4697d70e by James Browning at 2025-08-11T17:16:59-07:00 Make the CI jobs more correct in function - - - - - b4aa2029 by James Browning at 2025-08-11T17:16:59-07:00 wafhelpers/bin_test.py: never set PYTHONPATH ... - test installed files only when DESTDIR unset - test built files only for bin_test, build, and check ATM. - otherwise do not run bin_test We set PYTHONPATH to the built module distorting the results. We also set PATH to the target folder, warping results. Stop doing those and document a little better. - - - - - 16dbe2b0 by James Browning at 2025-08-11T17:16:59-07:00 CI: Update four Debian jobs - Bump Python minor by two for debian-{,old}stable-basic - Move AsciiDoc-classic2-Debian-Old to python2 - Move debian-oldstable-options-tester to debian:oldoldstable - - - - - 2 changed files: - .gitlab-ci.yml - wafhelpers/bin_test.py Changes: ===================================== .gitlab-ci.yml ===================================== @@ -2,6 +2,7 @@ pages: stage: build image: $CI_REGISTRY/ntpsec/ntpsec/alpine-pages script: + - echo /tmp/docbot-local/lib/python3.12/site-packages > /usr/lib/python3.12/site-packages/ntpsec.pth - mkdir -p public/latest - python3 ./waf configure --prefix=/tmp/docbot-local --htmldir=`pwd`/public/latest/ --enable-doc --disable-manpage build install - tar -C /tmp/docbot-local/share/doc/ntpsec/ -cf - .|tar -C public/latest/ -xf - @@ -30,10 +31,20 @@ include: tags: - gitlab-org +prisoner-0: + <<: *job_definition + image: $CI_REGISTRY/ntpsec/ntpsec/alpine + script: + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" + - DESTDIR=prison python3 ./waf install uninstall + - DESTDIR=build/prison python3 ./waf install uninstall + - DESTDIR=../prison python3 ./waf install uninstall + alpine-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/alpine script: + - echo /usr/local/lib/python3.12/site-packages > /usr/lib/python3.12/site-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -49,6 +60,7 @@ alpine-edge-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/alpine-edge script: + - echo /usr/local/lib/python3.12/site-packages > /usr/lib/python3.12/site-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -72,7 +84,7 @@ alpine-edge-refclocks: # - ln -sv src/asciidoc3.py asciidoc3/asciidoc3 # - asciidoc3/asciidoc3 --version || echo -n # - PATH="$PWD/asciidoc3:$PATH" python3 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build - + AsciiDoc-py3-Alpine: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/alpine @@ -93,7 +105,7 @@ AsciiDoc-classic3-Debian-Old: script: - apt-get update - DEBIAN_FRONTEND="noninteractive" apt-get install -y python3-dev asciidoc-base - - python3 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build --disable-nts + - python3 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build --disable-nts --pyshebang "/usr/bin/env python3" AsciiDoc-classic-Python2: <<: *job_definition @@ -101,12 +113,13 @@ AsciiDoc-classic-Python2: script: - apt-get update - DEBIAN_FRONTEND="noninteractive" apt-get install -y python2-dev asciidoc-base - - python2 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build --disable-nts + - python2 ./waf configure --enable-warnings --enable-Werror --enable-doc --enable-manpage build --disable-nts --pyshebang "/usr/bin/env python3" debian-oldstable-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-oldstable script: + - echo /usr/local/lib/python3.11/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --disable-nts build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -115,12 +128,13 @@ debian-oldstable-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-oldstable script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --disable-nts --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --disable-nts --refclock=all build --pyshebang "/usr/bin/env python3" debian-stable-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-stable script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -129,12 +143,13 @@ debian-stable-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-stable script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" debian-testing-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-testing script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -143,13 +158,14 @@ debian-testing-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-testing script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" debian-unstable-basic: allow_failure: true <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-unstable script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -159,12 +175,13 @@ debian-unstable-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-unstable script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" ubuntu-latest-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-latest script: + - echo /usr/local/lib/python3.12/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -173,13 +190,14 @@ ubuntu-latest-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-latest script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" ubuntu-devel-basic: <<: *job_definition allow_failure: true image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-devel script: + - echo /usr/local/lib/python3.9/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -189,12 +207,13 @@ ubuntu-devel-refclocks: allow_failure: true image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-devel script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" ubuntu-rolling-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-rolling script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -203,7 +222,7 @@ ubuntu-rolling-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/ubuntu-rolling script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" freebsd-basic: <<: *job_definition @@ -221,7 +240,7 @@ freebsd-basic: freebsd-refclocks: <<: *job_definition script: - - python ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" tags: - freebsd rules: @@ -239,7 +258,7 @@ centos-latest-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/centos-latest script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" fedora-latest-basic: <<: *job_definition @@ -273,6 +292,7 @@ clang-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/clang script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3/dist-packages/ntpsec.pth - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --check-c-compiler=clang build --pyshebang "/usr/bin/env python3" - python3 ./waf install - python3 ./waf uninstall @@ -281,7 +301,7 @@ clang-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/clang script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --check-c-compiler=clang --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --check-c-compiler=clang --refclock=all build --pyshebang "/usr/bin/env python3" openSUSE-leap-basic: <<: *job_definition @@ -295,7 +315,7 @@ openSUSE-leap-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/opensuse-leap script: - - python3 ./waf configure --enable-warnings --disable-doc --disable-manpage --disable-nts --refclock=all build + - python3 ./waf configure --enable-warnings --disable-doc --disable-manpage --disable-nts --refclock=all build --pyshebang "/usr/bin/env python3" # debian-stable-basic-32bit: # <<: *job_definition @@ -313,13 +333,13 @@ debian-stable-mDNS-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-stable-mdns script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build --pyshebang "/usr/bin/env python3" debian-stable-mDNS-refclocks: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/debian-stable-mdns script: - - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build + - python3 ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" cross-armhf-build: allow_failure: true @@ -351,13 +371,10 @@ gentoo-basic: <<: *job_definition image: $CI_REGISTRY/ntpsec/ntpsec/gentoo script: + - echo /usr/local/lib/python3.13/site-packages/ > /usr/lib/python3.13/site-packages/ntpsec.pth - python ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage build - - DESTDIR=build/prison python ./waf install - - DESTDIR=./prison python ./waf install - - DESTDIR=../prison python ./waf install - python ./waf install - python ./waf uninstall - - rm -rvf build/prison ./prison ../prison gentoo-refclocks: <<: *job_definition @@ -397,7 +414,7 @@ macos-basic: macos-refclocks: <<: *job_definition script: - - PKG_CONFIG_PATH=${HOMEBREW_PREFIX}/opt/openssl/lib/pkgconfig python ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build || cat build/config.log + - PKG_CONFIG_PATH=${HOMEBREW_PREFIX}/opt/openssl/lib/pkgconfig python ./waf configure --enable-warnings --enable-Werror --disable-doc --disable-manpage --refclock=all build --pyshebang "/usr/bin/env python3" || cat build/config.log tags: - saas-macos-medium-m1 rules: ===================================== wafhelpers/bin_test.py ===================================== @@ -2,7 +2,15 @@ # # SPDX-License-Identifier: BSD-2-Clause -"""Run a suite of tests on the listed binaries.""" +"""Run a suite of tests on the listed binaries. + +| command | DESTDIR | value | tests | +| === | === | === | === | +| bin_test, build, check | n/a | False as TEST_BUILD | build/main | +| install | no | True as TEST_INSTALL | $PREFIX/bin, $PREFIX/sbin | +| install | yes | None as TEST_NO | nothing | +| * | n/a | None as TEST_NO | nothing | +""" from __future__ import print_function import os import os.path @@ -17,6 +25,9 @@ NTPD = "main/ntpd" NTPFROB = "main/ntpfrob" NTPTIME = "main/ntptime" POPEN = waflib.Utils.subprocess.Popen +TEST_BUILD = 0 +TEST_NO = 1 +TEST_INSTALL = 2 test_logs = [] @@ -32,7 +43,7 @@ def bin_test_summary(_ctx): waflib.Logs.pprint(i[0], i[1]) -def run(cmd, expected, python=None): +def run(cmd, expected): """Run an individual test.""" prefix = "running: " + " ".join(cmd) @@ -40,11 +51,7 @@ def run(cmd, expected, python=None): addLog("YELLOW", prefix + " SKIPPING (does not exist)") return None - if python: - cmd = [python[0]] + list(cmd) - p = POPEN(cmd, env={'PATH': os.environ['PATH'], - 'PYTHONPATH': '%s/main/tests/pylib' % - waflib.Context.out_dir}, + p = POPEN(cmd, env={"PATH": os.environ["PATH"]}, universal_newlines=True, stdin=waflib.Utils.subprocess.PIPE, stdout=waflib.Utils.subprocess.PIPE, @@ -65,11 +72,35 @@ def run(cmd, expected, python=None): return False -def etl_cases(installed, version, params): +def do_we_test(ctx): + """Evaluate if we should test and how.""" + if ctx.cmd in ["build", "check", "bin_test"]: + return TEST_BUILD + if ctx.cmd == "install": + if bool(waflib.Options.options.destdir): + waflib.Logs.pprint( + "YELLOW", "bin_test disabled in DESTDIR installs." + ) + return TEST_NO + return TEST_INSTALL + if "uninstall" == ctx.cmd: + return TEST_NO + # Probably add more cases here... + waflib.Logs.pprint( + "RED", "Please report that bin_test is broken for `./waf %s`!" + % ctx.cmd + ) + sys.exit(1) + + +def etl_cases(ctx, version, params): """Convert cmd_list_* to run() arguments.""" ret = [] + installed = do_we_test(ctx) + if installed is TEST_NO: + return [] for dest_dir, bld_dir, name, flag in params: - if not installed: + if installed != TEST_INSTALL: prefix = waflib.Context.out_dir + os.sep + bld_dir else: prefix = waflib.Options.options.destdir + dest_dir @@ -117,12 +148,11 @@ def cmd_bin_test(ctx): if ctx.env['PYTHON_CURSES']: cmd_list_python += cmd_list_python_curses - INSTALL = bool('install' == ctx.cmd) - for cmd in etl_cases(INSTALL, version, cmd_list): + for cmd in etl_cases(ctx, version, cmd_list): rets.append(run(cmd[0], cmd[1])) if 'none' != ctx.env['ntpc']: - for cmd in etl_cases(INSTALL, version, cmd_list_python): - rets.append(run(cmd[0], cmd[1], ctx.env['PYTHON'])) + for cmd in etl_cases(ctx, version, cmd_list_python): + rets.append(run(cmd[0], cmd[1])) def test_s(number): """Return values for string formatting.""" @@ -130,10 +160,13 @@ def cmd_bin_test(ctx): skips = sum(int(None is i) for i in rets) fails = sum(int(False is i) for i in rets) - if fails: - bin_test_summary(ctx) if skips: waflib.Logs.pprint('YELLOW', "%d binary test%s skipped!" % test_s(skips)) if fails: - ctx.fatal("%d binary test%s failed!" % test_s(fails)) + # on failure print number of failed tests and the summary + waflib.Logs.pprint( + "RED", "%d binary test%s failed!" % test_s(fails) + ) + bin_test_summary(ctx) + sys.exit(1) View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/a56c0197c5383c33351c67c6f67378f677d6ee52...16dbe2b07bc70b37e73aa76f850db2705f7c5dd9 -- View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/a56c0197c5383c33351c67c6f67378f677d6ee52...16dbe2b07bc70b37e73aa76f850db2705f7c5dd9 You're receiving this email because of your account on gitlab.com. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gitlab at mg.gitlab.com Sat Aug 23 22:16:11 2025 From: gitlab at mg.gitlab.com (Hal Murray (@hal.murray)) Date: Sat, 23 Aug 2025 22:16:11 +0000 Subject: [Git][NTPsec/ntpsec][master] 5 commits: Squish compiler warning Message-ID: <68aa3dabe39ed_2cd6f10436c4@gitlab-sidekiq-low-urgency-cpu-bound-v2-65dcf9c9f4-4cpqj.mail> Hal Murray pushed to branch master at NTPsec / ntpsec Commits: 386e8c76 by Hal Murray at 2025-08-12T00:43:04-07:00 Squish compiler warning A maybe-uninitialized that showed up with -O3 - - - - - 5dd22f1b by Hal Murray at 2025-08-21T23:32:27-07:00 Fix sandbox to build on Raspbian 9 (stretch) - - - - - ad76338d by Hal Murray at 2025-08-21T23:45:15-07:00 move fix_WNRO so hpgps driver can use it no functional changes - - - - - 0539c4c9 by Hal Murray at 2025-08-21T23:54:07-07:00 Major update to HPGPS driver Fix gps WNRO glitch in Z3801A (2025-Aug-17 => 2006-Jan-01) "scpi >" eliminated from clockstats several internal variables added to clockstats - - - - - 83fa4924 by Hal Murray at 2025-08-21T23:58:57-07:00 Minor tweaks to HOWTO-OpenSSL - - - - - 9 changed files: - HOWTO-OpenSSL - NEWS.adoc - docs/driver_hpgps.adoc - include/ntp_refclock.h - ntpd/ntp_refclock.c - ntpd/ntp_sandbox.c - ntpd/ntp_signd.c - ntpd/refclock_hpgps.c - ntpd/refclock_nmea.c Changes: ===================================== HOWTO-OpenSSL ===================================== @@ -86,10 +86,10 @@ time make -j4 |& tee make.log # ./apps/openssl without the wrapper will use the installed libraries The above check is broken on Fedora (I think Fedora needs some old/weak crypto that default OpenSSL - no longer provides. I haven't gone donw this rabbit hole.) + no longer provides. I haven't gone down this rabbit hole.) It works on Debian, Ubuntu and FreeBSD. -time make test |& tee test.log +time make test -j4 |& tee test.log time make build_docs |& tee docs.log sudo make install |& tee install.log ===================================== NEWS.adoc ===================================== @@ -12,6 +12,11 @@ on user-visible changes. ## Repository Head + Major update to HPGPS driver + Fix gps WNRO glitch in Z3801A + "scpi >" eliminated from clockstats + several internal variables added to clockstats + ## 2025-04-18: 1.2.4 * waf has been upgraded to version 2.1.4 ===================================== docs/driver_hpgps.adoc ===================================== @@ -11,12 +11,10 @@ Serial Port: /dev/hpgps__u__; 9600 bps 8N1, 19200 bps 7N2 for the HP Z3801A == Warning -As of September 2017 we have reports that the internal clock on a -Z3801A was observed to roll over to 1998 (see -link:rollover.html[Rollover issues in time sources]). Users should -audit for rollover before deploying any of these devices. One or more "g" -suffixes on your 'time1' option may be useful as a workaround if -your device does not support setting the era date. +Old gear, like the Z3801A has GPS WNRO problems (see +link:rollover.html[Rollover issues in time sources]). +The driver should adjust the time forward by N*1024 weeks +to get a sane time. == Description @@ -34,10 +32,17 @@ off in the thousands. They use HP SmartClock (TM) to implement an Enhanced GPS receiver. The receiver accuracy when locked to GPS in normal operation is better than 1 ?s. The accuracy when operating in holdover is typically -better than 10 ?s per day. The receiver should be operated with -factory default settings. Initial driver operation: expects the -receiver to be already locked to GPS, configured and able to output -timecode format 2 messages. +better than 10 ?s per day. + +The driver expects the receiver to be running in UTC mode +and T2 mode. You can set that up using: + +------------------------------------- + :ptime:tcode:format F2 + :diag:gps:utc 1 +------------------------------------- + +The latter isn't documented and needs a reboot to take effect. The driver uses the poll sequence +:PTIME:TCODE?+ to get a response from the receiver. The receiver responds with a timecode string of ASCII @@ -103,9 +108,9 @@ your documentation for details. +flag2 {0 | 1}+:: Not used by this driver. +flag3 {0 | 1}+:: - Not used by this driver. + Adds extra stats to the clockstats line +flag4 {0 | 1}+:: - Not used by this driver. + Adds a status page to clockstats. +subtype+:: Setting mode 1 configures for the HP Z3801A. +mode+:: @@ -117,6 +122,38 @@ your documentation for details. +baud+ 'number':: Overrides the default baud rate. +== Monitor Data + +The last T2 sentence that is accepted or rejected is written to the +clockstats file and available with +ntpq -c clockvar+. If +flag3+ is set, +several more internal variables are logged. + +---------------------------------------------------------------------------- +60908 28302.174 HPGPS(0) T220060105075143300003B 64 0 +3 +1.07000E+002 0 +1.5E-006 0 +660669 +2.60128E+001 +---------------------------------------------------------------------------- + +.Clockstats +[cols="10%,20%,70%",options="header"] +|============================================================================= +|Column|Sample |Meaning +|1 |60908 |MJD +|2 |28302.174 |Time of day in seconds +|3 |HPGPS(0) |Driver type and unit. +|4 |T2... |T2 sentence from unit +|5 |64 |Number of sentences accepted and used for timekeeping +|6 |0 |Number of sentences rejected +|||Below only if flag3 is on +|7 |+3 | result from :GPS:SAT:TRAC:COUNT? +|8 |+1.07000E+002 | result from :ROSC:HOLD:DUR? (duration of this or last holdover) +|9 |0 | 1 if in holdover +|10 |+1.5E-006 | result from :ROSC:HOLD:TUNC:PRED? +|11 |0 | ??? +|12 |+660669 | result from DIAG:ROSC:EFC:ABS? (DAC value) +|13 |+2.60128E+001 | result from :DIAG:ROSC:EFC:REL? (-100 to 100) +|============================================================================= + + + == Configuration Example ---------------------------------------------------------------------------- ===================================== include/ntp_refclock.h ===================================== @@ -195,6 +195,10 @@ extern size_t refclock_gtraw (struct recvbuf *, char *, size_t, l_fp *); extern bool indicate_refclock_packet(struct refclockio *, struct recvbuf *); +extern void fix_WNRO (struct timespec *dt, int *wnro, + const struct peer *peer); + + extern struct refclock refclock_none; #ifdef CLOCK_ARBITER ===================================== ntpd/ntp_refclock.c ===================================== @@ -12,6 +12,7 @@ #include "lib_strbuf.h" #include "ntp_calendar.h" #include "timespecops.h" +#include "PIVOT.h" #include @@ -1087,4 +1088,36 @@ refclock_catcher( return PPS_OK; } #endif /* HAVE_PPSAPI */ + +/* Early GPS has a 10 bit week number field. + * That's a bit less than 20 years. + * GPS started in 1980. We have now wrapped twice: Aug 1999 and Apr 2019. + * https://en.wikipedia.org/wiki/GPS_week_number_rollover + * + * Some firmware fixes the date to be at least the firmware build date. + * That gives valid time for 20 years from the build date. + * It also means that old GPS units can break at any time, + * not just on 1024 week boundaries. + * + * This code wraps based on our build date. + * But using a build date would break repeatable builds. + * So we use a pivot date that gets updated at release time. + * So our code should work for 1024 weeks from the release date. + * + * Modern GPS satellites have added 3 more bits. + * Old firmware doesn't know about them. + */ + +void fix_WNRO (struct timespec *dt, int *wnro, const struct peer *peer) { + int i; + for (i=0; dt->tv_sec < RELEASE_DATE; i++) { + dt->tv_sec += 1024*7*86400; + } + if (*wnro != i) { + *wnro = i; + msyslog(LOG_INFO, "REFCLOCK: %s date advanced by %d weeks, WNRO", \ + refclock_name(peer), *wnro*1024); + } +}; + #endif /* REFCLOCK */ ===================================== ntpd/ntp_sandbox.c ===================================== @@ -406,7 +406,10 @@ int scmp_sc[] = { * rather than generate a trap. */ SCMP_SYS(clone), /* threads */ +#ifdef __NR_clone3 + /* Doesn't exist on 4.19.66, Raspbian 9 (stretch) */ SCMP_SYS(clone3), +#endif SCMP_SYS(kill), /* generate signal */ SCMP_SYS(madvise), SCMP_SYS(mprotect), ===================================== ntpd/ntp_signd.c ===================================== @@ -298,6 +298,7 @@ send_via_ntp_signd( { uint32_t op_reply = 0; + samba_reply.op = 0; /* keep compiler happy */ memcpy(&samba_reply, reply, header_length > reply_len ? reply_len: header_length); op_reply = ntohl(samba_reply.op); if (reply_len < header_length) { ===================================== ntpd/refclock_hpgps.c ===================================== @@ -3,12 +3,13 @@ */ #include "config.h" -#include "ntp.h" #include "ntpd.h" #include "ntp_io.h" +#include "ntp_assert.h" #include "ntp_calendar.h" #include "ntp_refclock.h" #include "ntp_stdlib.h" +#include "timespecops.h" #include #include @@ -45,11 +46,10 @@ * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005 * * - * The receiver should be operated with factory default settings. * Initial driver operation: expects the receiver to be already locked * to GPS, configured and able to output timecode format 2 messages. * - * The driver uses the poll sequence :PTIME:TCODE? to get a response from + * The driver uses the poll sequence :PTIME:CODE? to get a response from * the receiver. The receiver responds with a timecode string of ASCII * printing characters, followed by a , followed by a prompt string * issued by the receiver, in the following format: @@ -71,9 +71,20 @@ * -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05 * -0.953175 on an HP 9000 Model 370 HP-UX 9.10 * - * This receiver also provides a 1PPS signal, but I haven't figured out - * how to deal with any of the CLK or PPS stuff yet. Stay tuned. + * This receiver also provides a 1PPS signal. + * Use the ATOM driver (22) to take advantage of it. + * That requires kernel support. * + * There should always be one request in the pipeline. + * Whenever a message is received, another one is asked for. + * Normally, the next time messages arrives a second later. + * The status page takes 2 seconds. (even at 19200) + * The timer routine will recover if a message gets dropped + * due to an error or an unplugged cable or loss of power or ... + * If flag4 is set, each polling interval does a dance to get + * the status page. The receive routine asks for status + * rather than time, and the status collection code asks for + * the time after it has collected the whole status message. */ /* @@ -82,6 +93,8 @@ * is recorded in the clockstats file. */ +#define HPDEBUG false + /* * Interface definitions */ @@ -93,29 +106,34 @@ #define NAME "HPGPS" /* shortname */ #define DESCRIPTION "HP GPS Time and Frequency Reference Receiver" -#define SMAX 23*80+1 /* for :SYSTEM:PRINT? status screen response */ -#define MTZONE 2 /* number of fields in timezone reply */ +/* Size of buffer for status screen from :SYSTEM:STATUS? + * (This code used to use :SYSTEM:PRINT? + * I can't find any doc for that. Hal, 2025-Aug-19.) + * The Z3801A manual shows 22 lines. + * Newer versions of firmware have 23 lines of up to 79 characters. + * Not all lines were full. Hal Murray, Nov 2023 + */ +#define LMAX 24 /* lines in status screen, plus spare */ +#define SMAX LMAX*80+1 /* characters */ + #define MTCODET2 12 /* number of fields in timecode format T2 */ #define NTCODET2 21 /* number of chars to checksum in format T2 */ -/* - * Tables to compute the day of year from yyyymmdd timecode. - * Viva la leap. - */ -static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - /* * Unit control structure */ struct hpgpsunit { - int pollcnt; /* poll message counter */ - int tzhour; /* timezone offset, hours */ - int tzminute; /* timezone offset, minutes */ - int linecnt; /* set for expected multiple line responses */ + int idlesec; /* seconds since last message */ + bool didpoll; /* poll called recently */ + unsigned int cmndcnt; /* collecting data */ + int linecnt; /* collecting text for status screen */ char *lastptr; /* pointer to receiver response data */ + int wnro; char statscrn[SMAX]; /* receiver status screen buffer */ +/* Statisitics since last poll: */ + int timecnt; /* Valid time code messages received */ + int errorcnt; /* Errors in received messages */ }; /* @@ -124,6 +142,9 @@ struct hpgpsunit { static bool hpgps_start (int, struct peer *); static void hpgps_receive (struct recvbuf *); static void hpgps_poll (int, struct peer *); +static void hpgps_timer (int, struct peer *); +static void hpgps_write(struct peer *peer, const char *msg); +static bool hpgps_receive_T2(struct peer *const peer); /* * Transfer vector @@ -135,18 +156,31 @@ struct refclock refclock_hpgps = { hpgps_poll, /* transmit poll message */ NULL, /* not used (old hpgps_control) */ NULL, /* initialize driver */ - NULL /* timer - not used */ + hpgps_timer /* called once per second */ }; +/* commands to get extra info */ +const char *commands[] = { + ":GPS:SAT:TRAC:COUNT?\r", /* sats being tracked */ + ":ROSC:HOLD:DUR?\r", /* duration,state 1 if in holdover */ + ":ROSC:HOLD:TUNC:PRED?\r", /* 1 day holdover estimate */ + ":DIAG:ROSC:EFC:ABS?\r", /* DAC value */ + ":DIAG:ROSC:EFC:REL?\r" /* -100 to 100 */ + }; +/* Get E-230 if data not available + * Test case is PTIME:LEAP:GPST? (hex time of next leap) + * PTIME:LEAP:ACC?\n:SYST:ERR? + * scpi > +18 + * scpi > +0,"No error" + * :PTIME:LEAP:GPST?\n:SYST:ERR? + * scpi > E-230> -230,"Data corrupt or stale" +//":PTIME:TINT?\r*CLS\r", /x error if no sats, no data */ +//"DIAG:LIF:COUN?\n", /x uptime in units of 3 hours */ /* * hpgps_start - open the devices and initialize data for processing */ -static bool -hpgps_start( - int unit, - struct peer *peer - ) +bool hpgps_start(int unit, struct peer *peer) { struct hpgpsunit *up; struct refclockproc *pp; @@ -155,11 +189,19 @@ hpgps_start( unsigned int speed; char device[20]; + snprintf(device, sizeof(device), DEVICE, unit); + /* refclock_open flushes junk, but a quick restart may leave + * a time-request in the pipeline. + * waits are evil, but this doesn't get called during normal operations. + */ + sleep(2); /* * Open serial port. Use CLK line discipline, if available. * Default is HP 58503A, mode arg selects HP Z3801A */ - snprintf(device, sizeof(device), DEVICE, unit); + /* mode parameter to server config line shares ttl slot */ + /* Need mode rather than flag because this was called + * before following fudge line was even parsed. */ ldisc = LDISC_STD; speed = SPEED232; /* subtype parameter to server config line shares mode slot */ @@ -197,20 +239,20 @@ hpgps_start( pp->clockdesc = DESCRIPTION; memcpy((char *)&pp->refid, REFID, REFIDLEN); peer->sstclktype = CTL_SST_TS_UHF; - up->tzhour = 0; - up->tzminute = 0; *up->statscrn = '\0'; up->lastptr = up->statscrn; - up->pollcnt = 2; + + up->didpoll = false; + up->idlesec = 0; + up->timecnt = 0; + up->errorcnt = 0; /* * Get the identifier string, which is logged but otherwise ignored, - * and get the local timezone information */ up->linecnt = 1; - if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20) - refclock_report(peer, CEVNT_FAULT); + hpgps_write(peer, "*IDN?\r"); return true; } @@ -219,47 +261,85 @@ hpgps_start( /* * hpgps_receive - receive data from the serial interface */ -static void -hpgps_receive( - struct recvbuf *rbufp - ) +void hpgps_receive(struct recvbuf *rbufp) { - struct hpgpsunit *up; - struct refclockproc *pp; - struct peer *peer; - l_fp trtmp; - char tcodechar1; /* identifies timecode format */ - char tcodechar2; /* identifies timecode format */ - char timequal; /* time figure of merit: 0-9 */ - char freqqual; /* frequency figure of merit: 0-3 */ - char leapchar; /* leapsecond: + or 0 or - */ - char servchar; /* request for service: 0 = no, 1 = yes */ - char syncchar; /* time info is invalid: 0 = no, 1 = yes */ - short expectedsm; /* expected timecode byte checksum */ - short tcodechksm; /* computed timecode byte checksum */ - int i,m,n; - int month, day, lastday; - char *tcp; /* timecode pointer (skips over the prompt) */ - char prompt[BMAX]; /* prompt in response from receiver */ + struct peer * const peer = rbufp->recv_peer; + struct refclockproc * const pp = peer->procptr; + struct hpgpsunit * const up = pp->unitptr; + + l_fp rd_timestamp; /* - * Initialize pointers and read the receiver response + * read the receiver response */ - peer = rbufp->recv_peer; - pp = peer->procptr; - up = pp->unitptr; *pp->a_lastcode = '\0'; - pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp); + pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &rd_timestamp); DPRINT(1, ("hpgps: lencode: %d timecode:%s\n", pp->lencode, pp->a_lastcode)); +if (HPDEBUG) { + printf("HP in:%3d %s\n", pp->lencode, pp->a_lastcode); +} /* * If there's no characters in the reply, we can quit now */ if (pp->lencode == 0) return; + /* Strip off leading prompt to cleanup log files. */ + while (1) { + if (strstr(pp->a_lastcode, "scpi > ") == pp->a_lastcode) { + pp->lencode -= 7; + memmove(pp->a_lastcode, pp->a_lastcode+7, pp->lencode+1); + continue; + } + if (pp->a_lastcode[0] == 'E' && + pp->a_lastcode[1] == '-' && + pp->a_lastcode[5] == '>' && + pp->a_lastcode[6] == ' ') { + /* "E-nnn> " Error code */ + msyslog(LOG_ERR, "HPGPS(%d) error: %s", + pp->refclkunit, pp->a_lastcode); + DPRINT(0, ("hpgps: error: %s\n", pp->a_lastcode)); + hpgps_write(peer, "*CLS\r\r"); + pp->lencode -= 7; + memmove(pp->a_lastcode, pp->a_lastcode+7, pp->lencode+1); + continue; + } + break; + } + + if (up->cmndcnt > 0) { + /* some values are 2 part: +1.17000E+002,0 + * split them here to avoid postprocessing before gnuplot + */ + char *comma = strchr(pp->a_lastcode, ','); + if (NULL != comma) { + *comma = ' '; + } + *up->lastptr++ = ' '; + memcpy(up->lastptr, pp->a_lastcode, (size_t)pp->lencode); + up->lastptr += pp->lencode; + if (up->cmndcnt < COUNTOF(commands)) { + hpgps_write(peer, commands[up->cmndcnt++]); + return; + } + *up->lastptr++ = 0; +if (HPDEBUG) { + printf("HPlog: %s\n", up->statscrn); +} + record_clock_stats(peer, up->statscrn); + up->cmndcnt = 0; + if ((pp->sloppyclockflag & CLK_FLAG4) ) { + up->linecnt = LMAX; + hpgps_write(peer, ":SYSTEM:STATUS?\r"); + } else { + hpgps_write(peer, ":PTIME:TCODE?\r"); + } + return; + } + /* * If linecnt is greater than zero, we are getting information only, * such as the receiver identification string or the receiver status @@ -267,73 +347,107 @@ hpgps_receive( * screen buffer. When we have the last line, write the buffer to * the clockstats file and return without further processing. * - * If linecnt is zero, we are expecting either the timezone - * or a timecode. At this point, also write the response - * to the clockstats file, and go on to process the prompt (if any), - * timezone, or timecode and timestamp. + * If linecnt is zero, we are expecting a timecode. */ - if (up->linecnt-- > 0) { + if (up->linecnt > 0) { + up->linecnt--; + /* Silently drop whole line if it doesn't fit. */ if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) { - *up->lastptr++ = '\n'; + if ( (up->lastptr != up->statscrn) || (up->linecnt > 0) ) + /* ID string stays on same line */ + *up->lastptr++ = '\n'; memcpy(up->lastptr, pp->a_lastcode, (size_t)pp->lencode); up->lastptr += pp->lencode; } - if (up->linecnt == 0) { - record_clock_stats(peer, up->statscrn); + /* Status screen is 22 or 23 lines */ + if ( (up->linecnt == 0) || + (strstr(pp->a_lastcode, "Self Test:") == pp->a_lastcode) ) { + up->linecnt = 0; + record_clock_stats(peer, up->statscrn); + hpgps_write(peer, ":PTIME:TCODE?\r"); } - return; } - record_clock_stats(peer, pp->a_lastcode); - pp->lastrec = trtmp; + pp->lastrec = rd_timestamp; + + up->idlesec = 0; + + if (hpgps_receive_T2(peer)) return; + if (!up->didpoll) { + /* error ?? */ + return; + } + + REQUIRE(up->didpoll); + up->didpoll = false; up->lastptr = up->statscrn; *up->lastptr = '\0'; - up->pollcnt = 2; + /* Do FLAG3 first. End of FLAG3 processing starts FLAG4 */ + if (pp->sloppyclockflag & CLK_FLAG3) { + up->lastptr += snprintf(up->statscrn, sizeof(up->statscrn), + "%s %d %d ", pp->a_lastcode, up->timecnt, up->errorcnt); + up->timecnt = up->errorcnt = 0; + up->cmndcnt = 0; + hpgps_write(peer, commands[up->cmndcnt++]); + } else if (pp->sloppyclockflag & CLK_FLAG4) { + up->linecnt = LMAX; + hpgps_write(peer, ":SYSTEM:STATUS?\r"); + } else { + mprintf_clock_stats(peer, + "%s %d %d", pp->a_lastcode, up->timecnt, up->errorcnt); + up->timecnt = up->errorcnt = 0; + hpgps_write(peer, ":PTIME:TCODE?\r"); + } +} - /* - * We get down to business: get a prompt if one is there, issue - * a clear status command if it contains an error indication. - * Next, check for either the timezone reply or the timecode reply - * and decode it. If we don't recognize the reply, or don't get the - * proper number of decoded fields, or get an out of range timezone, - * or if the timecode checksum is bad, then we declare bad format - * and exit. - * - * Timezone format (including nominal prompt): - * scpi > -H,-M +/* return true if all OK + * false is error or didpoll + */ +bool hpgps_receive_T2(struct peer *const peer) +{ + struct refclockproc * const pp = peer->procptr; + struct hpgpsunit * const up = pp->unitptr; + + l_fp rd_reftime; + char tcodechar1; /* identifies timecode format */ + char tcodechar2; /* identifies timecode format */ + char timequal; /* time figure of merit: 0-9 */ + char freqqual; /* frequency figure of merit: 0-3 */ + char leapchar; /* leapsecond: + or 0 or - */ + char servchar; /* request for service: 0 = no, 1 = yes */ + char syncchar; /* time info is invalid: 0 = no, 1 = yes */ + short expectedsm; /* expected timecode byte checksum */ + short tcodechksm; /* computed timecode byte checksum */ + int m, n; + struct tm tm; /* temp storage for parsed data */ + struct timespec date; /* time stamp derived from serial port */ + char *tcp; /* timecode pointer (skips over the prompt) */ + + /* We get down to business: + * Check for a timecode reply and decode it. + * If we don't recognize the reply, or don't get the proper + * number of decoded fields, or if the timecode checksum is bad, + * then we declare bad format and exit. * - * Timecode format (including nominal prompt): - * scpi > T2yyyymmddhhmmssMFLRVcc + * Timecode format (after removing prompt): + * T2yyyymmddhhmmssTFLRVcc * */ - strlcpy(prompt, pp->a_lastcode, sizeof(prompt)); - tcp = strrchr(pp->a_lastcode,'>'); - if (tcp == NULL) { - tcp = pp->a_lastcode; - } else { - tcp++; - } - prompt[tcp - pp->a_lastcode] = '\0'; - while ((*tcp == ' ') || (*tcp == '\t')) { - tcp++; + tcp = pp->a_lastcode; + /* Not expected to happen. Beware of filling up log files. */ + if (*tcp == ' ') { + msyslog(LOG_INFO, "HPGPS(%d) Leading space: '%s'", + pp->refclkunit, pp->a_lastcode); } + while ((*tcp == ' ') || (*tcp == '\t')) tcp++; /* - * deal with an error indication in the prompt here - */ - if (strrchr(prompt,'E') > strrchr(prompt,'s')){ - DPRINT(1, ("hpgps: error indicated in prompt: %s\n", prompt)); - if (write(pp->io.fd, "*CLS\r\r", 6) != 6) - refclock_report(peer, CEVNT_FAULT); - } - - /* - * make sure we got a timezone or timecode format and + * make sure we got a timecode format and * then process accordingly */ m = sscanf(tcp,"%c%c", &tcodechar1, &tcodechar2); @@ -341,63 +455,32 @@ hpgps_receive( if (m != 2){ DPRINT(1, ("hpgps: no format indicator\n")); refclock_report(peer, CEVNT_BADREPLY); - return; + up->errorcnt++; + return(false); } - switch (tcodechar1) { - - case '+': - case '-': - m = sscanf(tcp,"%d,%d", &up->tzhour, &up->tzminute); - if (m != MTZONE) { - DPRINT(1, ("hpgps: only %d fields recognized in timezone\n", m)); - refclock_report(peer, CEVNT_BADREPLY); - return; - } - if ((up->tzhour < -12) || (up->tzhour > 13) || - (up->tzminute < -59) || (up->tzminute > 59)){ - DPRINT(1, ("hpgps: timezone %d, %d out of range\n", - up->tzhour, up->tzminute)); - refclock_report(peer, CEVNT_BADREPLY); - return; - } - return; - - case 'T': - break; - - default: - DPRINT(1, ("hpgps: unrecognized reply format %c%c\n", + if ('T' != tcodechar1 || '2' != tcodechar2) { + DPRINT(1, ("hpgps: unrecognized reply format %c%c\n", tcodechar1, tcodechar2)); refclock_report(peer, CEVNT_BADREPLY); - return; - } /* end of tcodechar1 switch */ - - - switch (tcodechar2) { + up->errorcnt++; + return(false); + } - case '2': - m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx", - &pp->year, &month, &day, &pp->hour, &pp->minute, - &pp->second, - &timequal, &freqqual, &leapchar, &servchar, - &syncchar, - (short unsigned int*)&expectedsm); - n = NTCODET2; - if (m != MTCODET2){ - DPRINT(1, ("hpgps: only %d fields recognized in timecode\n", m)); - refclock_report(peer, CEVNT_BADREPLY); - return; - } - break; + m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec, + &timequal, &freqqual, &leapchar, &servchar, &syncchar, + (short unsigned int*)&expectedsm); - default: - DPRINT(1, ("hpgps: unrecognized timecode format %c%c\n", - tcodechar1, tcodechar2)); + if (m != MTCODET2){ + DPRINT(1, ("hpgps: only %d fields recognized in timecode\n", m)); refclock_report(peer, CEVNT_BADREPLY); - return; - } /* end of tcodechar2 format switch */ + up->errorcnt++; + return(false); + } + /* * Compute and verify the checksum. @@ -405,6 +488,7 @@ hpgps_receive( * before the expected checksum. Bail out if incorrect. */ tcodechksm = 0; + n = NTCODET2; while (n-- > 0) { tcodechksm += *tcp++; } @@ -414,81 +498,20 @@ hpgps_receive( DPRINT(1, ("hpgps: checksum %2hX doesn't match %2hX expected\n", tcodechksm, expectedsm)); refclock_report(peer, CEVNT_BADREPLY); - return; - } - - /* - * Compute the day of year from the yyyymmdd format. - */ - if (month < 1 || month > 12 || day < 1) { - refclock_report(peer, CEVNT_BADTIME); - return; - } - - if ( ! is_leapyear(pp->year) ) { /* Y2KFixes */ - /* not a leap year */ - if (day > day1tab[month - 1]) { - refclock_report(peer, CEVNT_BADTIME); - return; - } - for (i = 0; i < month - 1; i++) { - day += day1tab[i]; - } - lastday = 365; - } else { - /* a leap year */ - if (day > day2tab[month - 1]) { - refclock_report(peer, CEVNT_BADTIME); - return; - } - for (i = 0; i < month - 1; i++) { - day += day2tab[i]; - } - lastday = 366; - } - - /* - * Deal with the timezone offset here. The receiver timecode is in - * local time = UTC + :PTIME:TZONE, so SUBTRACT the timezone values. - * For example, Pacific Standard Time is -8 hours , 0 minutes. - * Deal with the underflows and overflows. - */ - pp->minute -= up->tzminute; - pp->hour -= up->tzhour; - - if (pp->minute < 0) { - pp->minute += 60; - pp->hour--; - } - if (pp->minute > 59) { - pp->minute -= 60; - pp->hour++; - } - if (pp->hour < 0) { - pp->hour += 24; - day--; - if (day < 1) { - pp->year--; - if ( is_leapyear(pp->year) ) /* Y2KFixes */ - day = 366; - else - day = 365; - } + up->errorcnt++; + return(false); } - if (pp->hour > 23) { - pp->hour -= 24; - day++; - if (day > lastday) { - pp->year++; - day = 1; - } + if (timequal > '4') { + DPRINT(0, ("hpgps: TFOM %c too big\n", timequal)); + refclock_report(peer, CEVNT_BADREPLY); + up->errorcnt++; + return(false); } - pp->yday = day; /* - * Decode the MFLRV indicators. + * Decode the TFLRV indicators. * NEED TO FIGURE OUT how to deal with the request for service, * time quality, and frequency quality indicators some day. */ @@ -508,12 +531,12 @@ hpgps_receive( * but that seems too likely to introduce other bugs. */ case '+': - if ((month==6) || (month==12)) + if ((tm.tm_mon==6) || (tm.tm_mon==12)) pp->leap = LEAP_ADDSECOND; break; case '-': - if ((month==6) || (month==12)) + if ((tm.tm_mon==6) || (tm.tm_mon==12)) pp->leap = LEAP_DELSECOND; break; @@ -521,7 +544,8 @@ hpgps_receive( DPRINT(1, ("hpgps: unrecognized leap indicator: %c\n", leapchar)); refclock_report(peer, CEVNT_BADTIME); - return; + up->errorcnt++; + return(false); } /* end of leapchar switch */ } @@ -533,55 +557,85 @@ hpgps_receive( * time, which may cause a paranoid protocol module to chuck out * the data. */ - if (!refclock_process(pp)) { - refclock_report(peer, CEVNT_BADTIME); - return; - } - pp->lastref = pp->lastrec; - refclock_receive(peer); + tm.tm_year -= 1900; + tm.tm_mon -= 1; + date.tv_nsec = 0; + date.tv_sec = timegm(&tm); /* No error checking */ - /* - * If CLK_FLAG4 is set, ask for the status screen response. - */ - if (pp->sloppyclockflag & CLK_FLAG4){ - up->linecnt = 22; - if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15) - refclock_report(peer, CEVNT_FAULT); + /* Z3801A broke 2025-Aug-17 => 2006-Jam-01 */ + fix_WNRO(&date, &up->wnro, peer); + + rd_reftime = tspec_stamp_to_lfp(date); + refclock_process_offset(pp, rd_reftime, pp->lastrec, pp->fudgetime1); + up->timecnt++; + + if(up->didpoll) { + return(false); } + + hpgps_write(peer, ":PTIME:TCODE?\r"); + return(true); } /* * hpgps_poll - called by the transmit procedure */ -static void -hpgps_poll( - int unit, - struct peer *peer - ) +void hpgps_poll(int unit, struct peer *peer) { + UNUSED_ARG(unit); + struct refclockproc *pp; struct hpgpsunit *up; + + pp = peer->procptr; + up = (struct hpgpsunit *)pp->unitptr; + + pp->lastref = pp->lastrec; + refclock_receive(peer); + + up->didpoll = true; + + pp->polls++; +} + +/* + * hpgps_timer - called once per second + */ +static void hpgps_timer(int unit, struct peer *peer) +{ struct refclockproc *pp; + struct hpgpsunit *up; UNUSED_ARG(unit); - /* - * Time to poll the clock. The HP 58503A responds to a - * ":PTIME:TCODE?" by returning a timecode in the format specified - * above. If nothing is heard from the clock for two polls, - * declare a timeout and keep going. - */ pp = peer->procptr; up = pp->unitptr; - if (up->pollcnt == 0) { - refclock_report(peer, CEVNT_TIMEOUT); - } else { - up->pollcnt--; + + if (up->idlesec++ == 5) + refclock_report(peer, CEVNT_TIMEOUT); + if (up->idlesec >= 5) { + /* FIXME: logging (happens on some commands) */ + /* Timeout. Poke it again. + * This recovers from the cable being unplugged for a while. + */ + hpgps_write(peer, ":PTIME:TCODE?\r"); + up->cmndcnt = 0; + up->linecnt = 0; } - if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) { +} + + +static void hpgps_write(struct peer *peer, const char *msg) { + struct refclockproc *pp = peer->procptr; + int len = strlen(msg); +if (HPDEBUG) { + static int counter = 0; + char copy[64]; /* msg ends with \r */ + strlcpy(copy, msg, sizeof(copy)); + *strstr(copy, "\r") = 0; + printf("HPout: %d %s\n", counter++, copy); +} + if (write(pp->io.fd, msg, len) != len) refclock_report(peer, CEVNT_FAULT); - } - else - pp->polls++; } ===================================== ntpd/refclock_nmea.c ===================================== @@ -31,7 +31,6 @@ #include "ntp_refclock.h" #include "ntp_stdlib.h" #include "timespecops.h" -#include "PIVOT.h" #ifdef HAVE_PPSAPI # include "ppsapi_timepps.h" @@ -273,8 +272,6 @@ static bool parse_time (struct timespec *dt, nmea_data *, int idx); static bool parse_date (struct timespec *dt, nmea_data*, int idx, enum date_fmt fmt); static bool kludge_day (struct timespec *dt); -static bool fix_WNRO (struct timespec *dt, int *wnro, \ - const struct peer *peer); static void save_ltc (struct refclockproc * const, const char * const, size_t); @@ -1684,36 +1681,4 @@ static bool kludge_day (struct timespec *dt) { return true; } -/* Early GPS has a 10 bit week number field. - * That's a bit less than 20 years. - * GPS started in 1980. We have now wrapped twice: Aug 1999 and Apr 2019. - * https://en.wikipedia.org/wiki/GPS_week_number_rollover - * - * Some firmware fixes the date to be at least the firmware build date. - * That gives valid time for 20 years from the build date. - * It also means that old GPS units can break at any time, - * not just on 1024 week boundaries. - * - * This code wraps based on our build date. - * But using a build date would break repeatable builds. - * So we use a pivot date that gets updated at release time. - * So our code should work for 1024 weeks from the release date. - * - * Modern GPS satellites have added 3 more bits. - * Old firmware doesn't know about them. - */ - -static bool fix_WNRO (struct timespec *dt, int *wnro, const struct peer *peer) { - int i; - for (i=0; dt->tv_sec < RELEASE_DATE; i++) { - dt->tv_sec += 1024*7*86400; - } - if (*wnro != i) { - *wnro = i; - msyslog(LOG_INFO, "REFCLOCK: %s date advanced by %d weeks, WNRO", \ - refclock_name(peer), *wnro*1024); - } - return true; -}; - // end View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/16dbe2b07bc70b37e73aa76f850db2705f7c5dd9...83fa4924b8f656bf9e5a729bc1e1bb2f942a59fe -- View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/16dbe2b07bc70b37e73aa76f850db2705f7c5dd9...83fa4924b8f656bf9e5a729bc1e1bb2f942a59fe You're receiving this email because of your account on gitlab.com. -------------- next part -------------- An HTML attachment was scrubbed... URL: