[ntpsec commit] Forward-port patches for NTP Classic [Bug 2859]...

Eric S. Raymond esr at ntpsec.org
Thu Oct 22 18:34:46 UTC 2015


Module:    ntpsec
Branch:    master
Commit:    14d6f208a21a2f9402f8c90ac299be21df60b5bd
Changeset: http://git.ntpsec.org/ntpsec/commit/?id=14d6f208a21a2f9402f8c90ac299be21df60b5bd

Author:    Eric S. Raymond <esr at thyrsus.com>
Date:      Thu Oct 22 14:33:29 2015 -0400

Forward-port patches for NTP Classic [Bug 2859]...

...Improve raw DCF77 robustness decoding, from Frank Kardel

---

 NEWS                    |  2 +
 include/parse.h         |  6 +--
 libparse/clk_meinberg.c |  4 +-
 libparse/clk_rawdcf.c   | 99 +++++++++++++++++++++++++++++++++++++++++++------
 libparse/clk_schmid.c   |  4 +-
 libparse/parse.c        |  8 +---
 ntpd/refclock_parse.c   |  8 ++--
 7 files changed, 102 insertions(+), 29 deletions(-)

diff --git a/NEWS b/NEWS
index 7ae3833..3193d4e 100644
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,9 @@ on user-visible changes.
   robust, and require 2 consecutive timestamps to be consistent.
 * [Bug 2845] Harden memory allocation in ntpd; implement and
   use 'eallocarray(...)' where appropriate.
+* [Bug 2846] Report 'unsynchronized' status during the leap second.
 * [Bug 2855] Implement conditional leap smear feature; includes
   later fixes for parser support and reporting leap smear in the REFID.
+* [Bug 2859] Improve raw DCF77 robustness decoding.  Frank Kardel.
 
 // end
diff --git a/include/parse.h b/include/parse.h
index ba2bd0e..afedeef 100644
--- a/include/parse.h
+++ b/include/parse.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1989-2005 by Frank Kardel <kardel at ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel at ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-clause
  */
@@ -68,7 +68,7 @@
  * feature information
  */
 #define PARSEB_S_LEAP		  0x00010000 /* supports LEAP */
-#define PARSEB_S_ANTENNA	  0x00020000 /* supports antenna information */
+#define PARSEB_S_CALLBIT	  0x00020000 /* supports callbit information */
 #define PARSEB_S_PPS     	  0x00040000 /* supports PPS time stamping */
 #define PARSEB_S_POSITION	  0x00080000 /* supports position information (GPS) */
 
@@ -94,7 +94,7 @@
 #define PARSE_LEAPSECOND(x)	(PARSE_SYNC(x) && ((x) & PARSEB_LEAP_SECOND))
 
 #define PARSE_S_LEAP(x)		((x) & PARSEB_S_LEAP)
-#define PARSE_S_ANTENNA(x)	((x) & PARSEB_S_ANTENNA)
+#define PARSE_S_CALLBIT(x)	((x) & PARSEB_S_CALLBIT)
 #define PARSE_S_PPS(x)		((x) & PARSEB_S_PPS)
 #define PARSE_S_POSITION(x)	((x) & PARSEB_S_POSITION)
 
diff --git a/libparse/clk_meinberg.c b/libparse/clk_meinberg.c
index f1cf4da..d99da18 100644
--- a/libparse/clk_meinberg.c
+++ b/libparse/clk_meinberg.c
@@ -1,7 +1,7 @@
 /*
  * Meinberg clock support
  *
- * Copyright (c) 1989-2005 by Frank Kardel <kardel at ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel at ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -363,7 +363,7 @@ cvt_meinberg(
 
 		if (format->flags & MBG_EXTENDED)
 		{
-			clock_time->flags |= PARSEB_S_ANTENNA;
+			clock_time->flags |= PARSEB_S_CALLBIT;
 
 			/*
 			 * DCF77 does not encode the direction -
diff --git a/libparse/clk_rawdcf.c b/libparse/clk_rawdcf.c
index b738243..aaf310f 100644
--- a/libparse/clk_rawdcf.c
+++ b/libparse/clk_rawdcf.c
@@ -1,13 +1,14 @@
 /*
  * Raw DCF77 pulse clock support
  *
- * Copyright (c) 1989-2006 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <config.h>
 #include "ntp_fp.h"
+#include "timevalops.h"
 #include "ntp_unixtime.h"
 #include "ntp_calendar.h"
 
@@ -68,7 +69,9 @@ static parse_cvt_fnc_t cvt_rawdcf;
 static parse_inp_fnc_t inp_rawdcf;
 
 typedef struct last_tcode {
-	time_t tcode;	/* last converted time code */
+	time_t      tcode;	/* last converted time code */
+        timestamp_t tminute;	/* sample time for minute start */
+        timestamp_t timeout;	/* last timeout timestamp */
 } last_tcode_t;
 
 #define BUFFER_MAX	61
@@ -191,7 +194,7 @@ convert_rawdcf(
 	const unsigned char *c = dcfprm->zerobits;
 	int i;
 
-	parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer));
+	parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%.*s\"\n", size, buffer));
 
 	if (size < 57)
 	{
@@ -229,7 +232,7 @@ convert_rawdcf(
 		 */
 		parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n"));
 
-		clock_time->flags  = PARSEB_S_ANTENNA|PARSEB_S_LEAP;
+		clock_time->flags  = PARSEB_S_CALLBIT|PARSEB_S_LEAP;
 		clock_time->utctime= 0;
 		clock_time->usecond= 0;
 		clock_time->second = 0;
@@ -270,7 +273,7 @@ convert_rawdcf(
 		if (ext_bf(buffer, DCF_R, dcfprm->zerobits))
 		    clock_time->flags |= PARSEB_CALLBIT;
 
-		parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n",
+		parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %02d:%02d, %02d.%02d.%02d, flags 0x%lx\n",
 				       (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year,
 				       (u_long)clock_time->flags));
 		return CVT_OK;
@@ -280,7 +283,7 @@ convert_rawdcf(
 		/*
 		 * bad format - not for us
 		 */
-		msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%s\"", buffer);
+	    msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%.*s\"", size, buffer);
 		return CVT_FAIL|CVT_BADFMT;
 	}
 }
@@ -442,6 +445,8 @@ cvt_rawdcf(
 		if (*c) c++;
 	}
 
+	*s = '\0';
+
         if (rtc == CVT_NONE)
         {
 	       rtc = convert_rawdcf(buffer, size, &dcfparameter, clock_time);
@@ -452,14 +457,14 @@ cvt_rawdcf(
 			newtime = parse_to_unixtime(clock_time, &rtc);
 			if ((rtc == CVT_OK) && t)
 			{
-				if ((newtime - t->tcode) == 60) /* guard against multi bit errors */
+				if ((newtime - t->tcode) <= 600) /* require a successful telegram within last 10 minutes */
 				{
-					parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: minute delta check OK\n"));
+				        parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: recent timestamp check OK\n"));
 					clock_time->utctime = newtime;
 				}
 				else
 				{
-					parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: minute delta check FAIL - ignore timestamp\n"));
+					parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: recent timestamp check FAIL - ignore timestamp\n"));
 					rtc = CVT_SKIP;
 				}
 				t->tcode            = newtime;
@@ -493,13 +498,52 @@ pps_rawdcf(
 	return CVT_NONE;
 }
 
+static long
+calc_usecdiff(
+	timestamp_t *ref,
+	timestamp_t *base,
+	long         offset
+	)
+{
+	struct timeval delta;
+	long delta_usec = 0;
+	l_fp delt;
+
+	delt = ref->fp;
+	delt.l_i -= offset;
+	L_SUB(&delt, &base->fp);
+	TSTOTV(&delt, &delta);
+
+	delta_usec = 1000000 * (int32_t)delta.tv_sec + delta.tv_usec;
+	return delta_usec;
+}
+
 static u_long
 snt_rawdcf(
 	parse_t *parseio,
 	timestamp_t *ptime
 	)
 {
-	if ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK)
+	/*
+	 * only synthesize if all of following conditions are met:
+	 * - CVT_OK parse_status (we have a time stamp base)
+	 * - ABS(ptime - tminute - (parse_index - 1) sec) < 500ms (spaced by 1 sec +- 500ms)
+	 * - minute marker is available (confirms minute raster as base)
+	 */
+	last_tcode_t  *t = (last_tcode_t *)parseio->parse_pdata;
+	long delta_usec = -1;
+
+	if (t != NULL && t->tminute.tv.tv_sec != 0) {
+		delta_usec = calc_usecdiff(ptime, &t->tminute, parseio->parse_index - 1);
+		if (delta_usec < 0)
+			delta_usec = -delta_usec;
+	}
+
+	parseprintf(DD_RAWDCF,("parse: snt_rawdcf: synth for offset %d seconds - absolute usec error %ld\n",
+			       parseio->parse_index - 1, delta_usec));
+
+	if (((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) &&
+	    (delta_usec < 500000 && delta_usec >= 0)) /* only if minute marker is available */
 	{
 		parseio->parse_dtime.parse_stime = *ptime;
 
@@ -532,10 +576,43 @@ inp_rawdcf(
 
 	if (parse_timedout(parseio, tstamp, &timeout))
 	{
-		parseprintf(DD_PARSE, ("inp_rawdcf: time out seen\n"));
+		last_tcode_t *t = (last_tcode_t *)parseio->parse_pdata;
+		long delta_usec;
 
+		parseprintf(DD_RAWDCF, ("inp_rawdcf: time out seen\n"));
+		/* finish collection */
 		(void) parse_end(parseio);
+
+		if (t != NULL)
+		{
+			/* remember minute start sample time if timeouts occur in minute raster */
+			if (t->timeout.tv.tv_sec != 0)
+			{
+				delta_usec = calc_usecdiff(tstamp, &t->timeout, 60);
+				if (delta_usec < 0)
+					delta_usec = -delta_usec;
+			}
+			else
+			{
+				delta_usec = -1;
+			}
+
+			if (delta_usec < 500000 && delta_usec >= 0)
+			{
+				parseprintf(DD_RAWDCF, ("inp_rawdcf: timeout time difference %ld usec - minute marker set\n", delta_usec));
+				/* collect minute markers only if spaced by 60 seconds */
+				t->tminute = *tstamp;
+			}
+			else
+			{
+				parseprintf(DD_RAWDCF, ("inp_rawdcf: timeout time difference %ld usec - minute marker cleared\n", delta_usec));
+				memset((char *)&t->tminute, 0, sizeof(t->tminute));
+			}
+			t->timeout = *tstamp;
+		}
 		(void) parse_addchar(parseio, ch);
+
+		/* pass up to higher layers */
 		return PARSE_INP_TIME;
 	}
 	else
diff --git a/libparse/clk_schmid.c b/libparse/clk_schmid.c
index 1c590d0..55c31f7 100644
--- a/libparse/clk_schmid.c
+++ b/libparse/clk_schmid.c
@@ -6,7 +6,7 @@
  * Schmid clock support
  * based on information and testing from Adam W. Feigin et. al (Swisstime iis.ethz.ch)
  *
- * Copyright (c) 1989-2005 by Frank Kardel <kardel at ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel at ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -150,7 +150,7 @@ cvt_schmid(
 				    }
 			    }
 
-			    clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA;
+			    clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_CALLBIT;
 
 			    return CVT_OK;
 		    }
diff --git a/libparse/parse.c b/libparse/parse.c
index 8610187..b511418 100644
--- a/libparse/parse.c
+++ b/libparse/parse.c
@@ -1,13 +1,7 @@
 /*
  * Parser module for reference clock
  *
- * PARSEKERNEL define switches between two personalities of the module
- * if PARSEKERNEL is defined this module can be used
- * as kernel module. In this case the time stamps will be
- * a struct timeval.
- * when PARSEKERNEL is not defined NTP time stamps will be used.
- *
- * Copyright (c) 1989-2005 by Frank Kardel <kardel at ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel at ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/ntpd/refclock_parse.c b/ntpd/refclock_parse.c
index 4d7eb8b..8fbcec1 100644
--- a/ntpd/refclock_parse.c
+++ b/ntpd/refclock_parse.c
@@ -5,7 +5,7 @@
  *   On systems that support PPSAPI (RFC2783) PPSAPI is the
  *   preferred interface.
  *
- * Copyright (c) 1989-2009 by Frank Kardel <kardel at ntp.org>
+ * Copyright (c) 1989-2015 by Frank Kardel <kardel at ntp.org>
  * Copyright 2015 by the NTPsec project contributors
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -2029,7 +2029,7 @@ parsestate(
 	  {
 		  { PARSEB_S_LEAP,     "LEAP INDICATION" },
 		  { PARSEB_S_PPS,      "PPS SIGNAL" },
-		  { PARSEB_S_ANTENNA,  "ANTENNA" },
+		  { PARSEB_S_CALLBIT,  "CALLBIT" },
 		  { PARSEB_S_POSITION, "POSITION" },
 		  { 0,		       NULL }
 	  };
@@ -2051,7 +2051,7 @@ parsestate(
 		i++;
 	}
 
-	if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
+	if (lstate & (PARSEB_S_LEAP|PARSEB_S_CALLBIT|PARSEB_S_PPS|PARSEB_S_POSITION))
 	{
 		if (s != t)
 			t = ap(buffer, size, t, "; ");
@@ -2482,7 +2482,7 @@ parse_start(
 	if (!notice)
         {
 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
-			msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2009, Frank Kardel");
+			msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2015, Frank Kardel");
 		notice = 1;
 	}
 



More information about the vc mailing list