]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
use common structure for NTP samples
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 1 Aug 2018 14:28:26 +0000 (16:28 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 3 Aug 2018 15:21:02 +0000 (17:21 +0200)
Define a structure for NTP samples and use it to pass samples from
the ntp_core and refclock code to sources and sourcestats.

ntp.h
ntp_core.c
refclock.c
sources.c
sources.h
sourcestats.c
sourcestats.h
test/unit/sources.c

diff --git a/ntp.h b/ntp.h
index 801f2642a41cb6d4efad10160f64734b05b17c07..7b7f361c3f635f81406a8223c21c73a5638cc316 100644 (file)
--- a/ntp.h
+++ b/ntp.h
@@ -121,4 +121,19 @@ typedef struct {
 #define NTP_REFID_LOCAL 0x7F7F0101UL /* 127.127.1.1 */
 #define NTP_REFID_SMOOTH 0x7F7F01FFUL /* 127.127.1.255 */
 
+/* Structure used to save NTP measurements.  time is the local time at which
+   the sample is to be considered to have been made and offset is the offset at
+   the time (positive indicates that the local clock is slow relative to the
+   source).  root_delay/root_dispersion include peer_delay/peer_dispersion. */
+typedef struct {
+  struct timespec time;
+  double offset;
+  double peer_delay;
+  double peer_dispersion;
+  double root_delay;
+  double root_dispersion;
+  int stratum;
+  NTP_Leap leap;
+} NTP_Sample;
+
 #endif /* GOT_NTP_H */
index cebaa20ca34c474b9bde627d8f1c5e80442f61c1..398e464dc1b8b594a5955acf42c020e75a81cd86 100644 (file)
@@ -1455,6 +1455,7 @@ static int
 receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
                NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length)
 {
+  NTP_Sample sample;
   SST_Stats stats;
 
   int pkt_leap, pkt_version;
@@ -1463,24 +1464,6 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
   double pkt_root_dispersion;
   AuthenticationMode pkt_auth_mode;
 
-  /* The local time to which the (offset, delay, dispersion) triple will
-     be taken to relate.  For client/server operation this is practically
-     the same as either the transmit or receive time.  The difference comes
-     in symmetric active mode, when the receive may come minutes after the
-     transmit, and this time will be midway between the two */
-  struct timespec sample_time;
-
-  /* The estimated offset in seconds, a positive value indicates that the local
-     clock is SLOW of the remote source and a negative value indicates that the
-     local clock is FAST of the remote source */
-  double offset;
-
-  /* The estimated peer delay, dispersion and distance */
-  double delay, dispersion, distance;
-
-  /* The total root delay and dispersion */
-  double root_delay, root_dispersion;
-
   /* The skew and estimated frequency offset relative to the remote source */
   double skew, source_freq_lo, source_freq_hi;
 
@@ -1622,23 +1605,23 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
     precision = LCL_GetSysPrecisionAsQuantum() + UTI_Log2ToDouble(message->precision);
 
     /* Calculate delay */
-    delay = fabs(local_interval - remote_interval);
-    if (delay < precision)
-      delay = precision;
+    sample.peer_delay = fabs(local_interval - remote_interval);
+    if (sample.peer_delay < precision)
+      sample.peer_delay = precision;
     
     /* Calculate offset.  Following the NTP definition, this is negative
        if we are fast of the remote source. */
-    offset = UTI_DiffTimespecsToDouble(&remote_average, &local_average);
+    sample.offset = UTI_DiffTimespecsToDouble(&remote_average, &local_average);
 
     /* Apply configured correction */
-    offset += inst->offset_correction;
+    sample.offset += inst->offset_correction;
 
     /* We treat the time of the sample as being midway through the local
        measurement period.  An analysis assuming constant relative
        frequency and zero network delay shows this is the only possible
        choice to estimate the frequency difference correctly for every
        sample pair. */
-    sample_time = local_average;
+    sample.time = local_average;
     
     SST_GetFrequencyRange(stats, &source_freq_lo, &source_freq_hi);
 
@@ -1646,8 +1629,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
     skew = (source_freq_hi - source_freq_lo) / 2.0;
     
     /* and then calculate peer dispersion */
-    dispersion = MAX(precision, MAX(local_transmit.err, local_receive.err)) +
-                 skew * fabs(local_interval);
+    sample.peer_dispersion = MAX(precision, MAX(local_transmit.err, local_receive.err)) +
+                             skew * fabs(local_interval);
     
     /* If the source is an active peer, this is the minimum assumed interval
        between previous two transmissions (if not constrained by minpoll) */
@@ -1661,10 +1644,11 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
        processing time is sane, and in interleaved symmetric mode that the
        measured delay and intervals between remote timestamps don't indicate
        a missed response */
-    testA = delay - dispersion <= inst->max_delay && precision <= inst->max_delay &&
+    testA = sample.peer_delay - sample.peer_dispersion <= inst->max_delay &&
+            precision <= inst->max_delay &&
             !(inst->mode == MODE_CLIENT && response_time > MAX_SERVER_INTERVAL) &&
             !(inst->mode == MODE_ACTIVE && interleaved_packet &&
-              (delay > 0.5 * prev_remote_poll_interval ||
+              (sample.peer_delay > 0.5 * prev_remote_poll_interval ||
                UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts) <= 0 ||
                (inst->remote_poll <= inst->prev_local_poll &&
                 UTI_DiffTimespecsToDouble(&remote_transmit, &prev_remote_transmit) >
@@ -1673,14 +1657,14 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
     /* Test B requires in client mode that the ratio of the round trip delay
        to the minimum one currently in the stats data register is less than an
        administrator-defined value */
-    testB = check_delay_ratio(inst, stats, &sample_time, delay);
+    testB = check_delay_ratio(inst, stats, &sample.time, sample.peer_delay);
 
     /* Test C requires that the ratio of the increase in delay from the minimum
        one in the stats data register to the standard deviation of the offsets
        in the register is less than an administrator-defined value or the
        difference between measured offset and predicted offset is larger than
        the increase in delay */
-    testC = check_delay_dev_ratio(inst, stats, &sample_time, offset, delay);
+    testC = check_delay_dev_ratio(inst, stats, &sample.time, sample.offset, sample.peer_delay);
 
     /* Test D requires that the remote peer is not synchronised to us to
        prevent a synchronisation loop */
@@ -1688,8 +1672,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
             pkt_refid != UTI_IPToRefid(&local_addr->ip_addr);
   } else {
     remote_interval = local_interval = response_time = 0.0;
-    offset = delay = dispersion = 0.0;
-    sample_time = rx_ts->ts;
+    sample.offset = sample.peer_delay = sample.peer_dispersion = 0.0;
+    sample.time = rx_ts->ts;
     local_receive = *rx_ts;
     local_transmit = inst->local_tx;
     testA = testB = testC = testD = 0;
@@ -1699,9 +1683,10 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
      the additional tests passed */
   good_packet = testA && testB && testC && testD;
 
-  root_delay = pkt_root_delay + delay;
-  root_dispersion = pkt_root_dispersion + dispersion;
-  distance = dispersion + 0.5 * delay;
+  sample.root_delay = pkt_root_delay + sample.peer_delay;
+  sample.root_dispersion = pkt_root_dispersion + sample.peer_dispersion;
+  sample.stratum = MAX(message->stratum, inst->min_stratum);
+  sample.leap = (NTP_Leap)pkt_leap;
 
   /* Update the NTP timestamps.  If it's a valid packet from a synchronised
      source, the timestamps may be used later when processing a packet in the
@@ -1770,7 +1755,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
             UTI_Ntp64ToString(&message->receive_ts),
             UTI_Ntp64ToString(&message->transmit_ts));
   DEBUG_LOG("offset=%.9f delay=%.9f dispersion=%f root_delay=%f root_dispersion=%f",
-            offset, delay, dispersion, root_delay, root_dispersion);
+            sample.offset, sample.peer_delay, sample.peer_dispersion,
+            sample.root_delay, sample.root_dispersion);
   DEBUG_LOG("remote_interval=%.9f local_interval=%.9f response_time=%.9f txs=%c rxs=%c",
             remote_interval, local_interval, response_time,
             tss_chars[local_transmit.source], tss_chars[local_receive.source]);
@@ -1793,25 +1779,20 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
 
     if (good_packet) {
       /* Do this before we accumulate a new sample into the stats registers, obviously */
-      estimated_offset = SST_PredictOffset(stats, &sample_time);
-
-      SRC_AccumulateSample(inst->source,
-                           &sample_time,
-                           offset, delay, dispersion,
-                           root_delay, root_dispersion,
-                           MAX(message->stratum, inst->min_stratum),
-                           (NTP_Leap) pkt_leap);
+      estimated_offset = SST_PredictOffset(stats, &sample.time);
 
+      SRC_AccumulateSample(inst->source, &sample);
       SRC_SelectSource(inst->source);
 
       /* Now examine the registers.  First though, if the prediction is
          not even within +/- the peer distance of the peer, we are clearly
          not tracking the peer at all well, so we back off the sampling
          rate depending on just how bad the situation is. */
-      error_in_estimate = fabs(-offset - estimated_offset);
+      error_in_estimate = fabs(-sample.offset - estimated_offset);
 
       /* Now update the polling interval */
-      adjust_poll(inst, get_poll_adj(inst, error_in_estimate, distance));
+      adjust_poll(inst, get_poll_adj(inst, error_in_estimate,
+                                     sample.peer_dispersion + 0.5 * sample.peer_delay));
 
       /* If we're in burst mode, check whether the burst is completed and
          revert to the previous mode */
@@ -1878,9 +1859,9 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
     inst->report.root_dispersion = pkt_root_dispersion;
     inst->report.ref_id = pkt_refid;
     UTI_Ntp64ToTimespec(&message->reference_ts, &inst->report.ref_time);
-    inst->report.offset = offset;
-    inst->report.peer_delay = delay;
-    inst->report.peer_dispersion = dispersion;
+    inst->report.offset = sample.offset;
+    inst->report.peer_delay = sample.peer_delay;
+    inst->report.peer_dispersion = sample.peer_dispersion;
     inst->report.response_time = response_time;
     inst->report.jitter_asymmetry = SST_GetJitterAsymmetry(stats);
     inst->report.tests = ((((((((test1 << 1 | test2) << 1 | test3) << 1 |
@@ -1897,14 +1878,14 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
   /* Do measurement logging */
   if (logfileid != -1 && (log_raw_measurements || synced_packet)) {
     LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d %1d%1d%1d %1d%1d%1d%d  %2d %2d %4.2f %10.3e %10.3e %10.3e %10.3e %10.3e %08"PRIX32" %1d%1c %1c %1c",
-            UTI_TimeToLogForm(sample_time.tv_sec),
+            UTI_TimeToLogForm(sample.time.tv_sec),
             UTI_IPToString(&inst->remote_addr.ip_addr),
             leap_chars[pkt_leap],
             message->stratum,
             test1, test2, test3, test5, test6, test7, testA, testB, testC, testD,
             inst->local_poll, message->poll,
             inst->poll_score,
-            offset, delay, dispersion,
+            sample.offset, sample.peer_delay, sample.peer_dispersion,
             pkt_root_delay, pkt_root_dispersion, pkt_refid,
             NTP_LVM_TO_MODE(message->lvm), interleaved_packet ? 'I' : 'B',
             tss_chars[local_transmit.source],
index 0791d47037fd741c4d884926dfd69634dafa5aa0..4d98f84838bf4d5949f2884f67cfd3fb801ac624 100644 (file)
@@ -651,26 +651,30 @@ poll_timeout(void *arg)
   }
   
   if (!(inst->driver->poll && inst->driver_polled < (1 << (inst->poll - inst->driver_poll)))) {
-    double offset, dispersion;
-    struct timespec sample_time;
-    int sample_ok, stratum;
+    NTP_Sample sample;
+    int sample_ok;
 
-    sample_ok = filter_get_sample(&inst->filter, &sample_time, &offset, &dispersion);
+    sample_ok = filter_get_sample(&inst->filter, &sample.time,
+                                  &sample.offset, &sample.peer_dispersion);
     inst->driver_polled = 0;
 
     if (sample_ok) {
+      sample.peer_delay = inst->delay;
+      sample.root_delay = sample.peer_delay;
+      sample.root_dispersion = sample.peer_dispersion;
+      sample.leap = inst->leap_status;
+
       if (inst->pps_active && inst->lock_ref == -1)
         /* Handle special case when PPS is used with local stratum */
-        stratum = pps_stratum(inst, &sample_time);
+        sample.stratum = pps_stratum(inst, &sample.time);
       else
-        stratum = inst->stratum;
+        sample.stratum = inst->stratum;
 
       SRC_UpdateReachability(inst->source, 1);
-      SRC_AccumulateSample(inst->source, &sample_time, offset,
-          inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
+      SRC_AccumulateSample(inst->source, &sample);
       SRC_SelectSource(inst->source);
 
-      log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
+      log_sample(inst, &sample.time, 1, 0, 0.0, sample.offset, sample.peer_dispersion);
     } else {
       SRC_UpdateReachability(inst->source, 0);
     }
index 4a3adb3a0a305be3c82ccf089760b0cf12e02e6d..a5178565922b5cfaa20e6c45adb7911817b196a1 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -329,38 +329,24 @@ SRC_GetSourcestats(SRC_Instance instance)
    This function causes the frequency estimation to be re-run for the
    designated source, and the clock selection procedure to be re-run
    afterwards.
-
-   Parameters are described in sources.h
-
    */
 
-void SRC_AccumulateSample
-(SRC_Instance inst, 
- struct timespec *sample_time,
- double offset, 
- double peer_delay,
- double peer_dispersion,
- double root_delay, 
- double root_dispersion, 
- int stratum,
- NTP_Leap leap_status)
+void
+SRC_AccumulateSample(SRC_Instance inst, NTP_Sample *sample)
 {
 
   assert(initialised);
 
   DEBUG_LOG("ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
-            source_to_string(inst), UTI_TimespecToString(sample_time), -offset,
-            root_delay, root_dispersion, stratum);
+            source_to_string(inst), UTI_TimespecToString(&sample->time), -sample->offset,
+            sample->root_delay, sample->root_dispersion, sample->stratum);
 
   if (REF_IsLeapSecondClose()) {
     LOG(LOGS_INFO, "Dropping sample around leap second");
     return;
   }
 
-  /* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
-     IS FLIPPED */
-  SST_AccumulateSample(inst->stats, sample_time, -offset, peer_delay, peer_dispersion,
-                       root_delay, root_dispersion, stratum, leap_status);
+  SST_AccumulateSample(inst->stats, sample);
   SST_DoNewRegression(inst->stats);
 }
 
index 60d28fde26ad4dcba0eafa5ef3bd23df76fe7751..c160029ed4f94ac607b65b349d75f9dbb146ef2b 100644 (file)
--- a/sources.h
+++ b/sources.h
@@ -80,34 +80,8 @@ extern void SRC_SetRefid(SRC_Instance instance, uint32_t ref_id, IPAddr *addr);
 extern SST_Stats SRC_GetSourcestats(SRC_Instance instance);
 
 /* This function is called by one of the source drivers when it has
-   a new sample that is to be accumulated.
-
-   This function causes the frequency estimation to be re-run for the
-   designated source, and the clock selection procedure to be re-run
-   afterwards.
-
-   sample_time is the local time at which the sample is to be
-   considered to have been made, in terms of doing a regression fit of
-   offset against local time.
-
-   offset is the offset at the time, in seconds.  Positive indicates
-   that the local clock is SLOW relative to the source, negative
-   indicates that the local clock is FAST relative to it.
-
-   root_delay and root_dispersion are in seconds, and are as per
-   RFC 5905.  root_dispersion only includes the peer's root dispersion
-   + local sampling precision + skew dispersion accrued during the
-   measurement.  It is the job of the source statistics algorithms +
-   track.c to add on the extra dispersion due to the residual standard
-   deviation of the offsets from this source after regression, to form
-   the root_dispersion field in the packets transmitted to clients or
-   peers.
-
-   stratum is the stratum of the source that supplied the sample.
-
-   */
-
-extern void SRC_AccumulateSample(SRC_Instance instance, struct timespec *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum, NTP_Leap leap_status);
+   a new sample that is to be accumulated */
+extern void SRC_AccumulateSample(SRC_Instance instance, NTP_Sample *sample);
 
 /* This routine sets the source as receiving reachability updates */
 extern void SRC_SetActive(SRC_Instance inst);
index 0c1962473e8b4c293f80032a1045b8c9e5bbf467..21dc179f20301039bd46a3a09dfebd14e412591f 100644 (file)
@@ -289,11 +289,7 @@ prune_register(SST_Stats inst, int new_oldest)
 /* ================================================== */
 
 void
-SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time,
-                     double offset,
-                     double peer_delay, double peer_dispersion,
-                     double root_delay, double root_dispersion,
-                     int stratum, NTP_Leap leap)
+SST_AccumulateSample(SST_Stats inst, NTP_Sample *sample)
 {
   int n, m;
 
@@ -305,7 +301,7 @@ SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time,
 
   /* Make sure it's newer than the last sample */
   if (inst->n_samples &&
-      UTI_CompareTimespecs(&inst->sample_times[inst->last_sample], sample_time) >= 0) {
+      UTI_CompareTimespecs(&inst->sample_times[inst->last_sample], &sample->time) >= 0) {
     LOG(LOGS_WARN, "Out of order sample detected, discarding history for %s",
         inst->ip_addr ? UTI_IPToString(inst->ip_addr) : UTI_RefidToString(inst->refid));
     SST_ResetInstance(inst);
@@ -315,15 +311,17 @@ SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time,
     (MAX_SAMPLES * REGRESS_RUNS_RATIO);
   m = n % MAX_SAMPLES;
 
-  inst->sample_times[n] = *sample_time;
-  inst->offsets[n] = offset;
-  inst->orig_offsets[m] = offset;
-  inst->peer_delays[n] = peer_delay;
-  inst->peer_dispersions[m] = peer_dispersion;
-  inst->root_delays[m] = root_delay;
-  inst->root_dispersions[m] = root_dispersion;
-  inst->stratum = stratum;
-  inst->leap = leap;
+  /* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
+     IS FLIPPED */
+  inst->sample_times[n] = sample->time;
+  inst->offsets[n] = -sample->offset;
+  inst->orig_offsets[m] = -sample->offset;
+  inst->peer_delays[n] = sample->peer_delay;
+  inst->peer_dispersions[m] = sample->peer_dispersion;
+  inst->root_delays[m] = sample->root_delay;
+  inst->root_dispersions[m] = sample->root_dispersion;
+  inst->stratum = sample->stratum;
+  inst->leap = sample->leap;
  
   if (inst->peer_delays[n] < inst->fixed_min_delay)
     inst->peer_delays[n] = 2.0 * inst->fixed_min_delay - inst->peer_delays[n];
index 53f1ff07201f431585446801fdb6b76f66105b6b..c991c655cd95aa025492b95fc81689a8803c9ef7 100644 (file)
@@ -51,19 +51,8 @@ extern void SST_ResetInstance(SST_Stats inst);
 /* This function changes the reference ID and IP address */
 extern void SST_SetRefid(SST_Stats inst, uint32_t refid, IPAddr *addr);
 
-/* This function accumulates a single sample into the statistics handler
-
-   sample_time is the epoch at which the sample is to be considered to
-   have been made.
-
-   offset is the offset of the local clock relative to the source in
-   seconds.  Positive indicates that the local clock if FAST (contrary
-   to the NTP parts of the software)
-
-   stratum is the stratum of the source from which the sample came.
-  */
-
-extern void SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time, double offset, double peer_delay, double peer_dispersion, double root_delay, double root_dispersion, int stratum, NTP_Leap leap);
+/* This function accumulates a single sample into the statistics handler */
+extern void SST_AccumulateSample(SST_Stats inst, NTP_Sample *sample);
 
 /* This function runs the linear regression operation on the data.  It
    finds the set of most recent samples that give the tightest
index 735ed0d31f01334252b3fb010021687ba533df40..b81f80836911cf9d275540fab572ac6a6d173d33 100644 (file)
@@ -26,10 +26,9 @@ test_unit(void)
 {
   SRC_Instance srcs[16];
   RPT_SourceReport report;
+  NTP_Sample sample;
   IPAddr addr;
   int i, j, k, l, samples, sel_options;
-  double offset, delay, disp;
-  struct timespec ts;
 
   CNF_Initialise(0, 0);
   LCL_Initialise();
@@ -59,21 +58,25 @@ test_unit(void)
 
       samples = (i + j) % 5 + 3;
 
-      offset = TST_GetRandomDouble(-1.0, 1.0);
+      sample.offset = TST_GetRandomDouble(-1.0, 1.0);
 
       for (k = 0; k < samples; k++) {
-        SCH_GetLastEventTime(&ts, NULL, NULL);
-        UTI_AddDoubleToTimespec(&ts, TST_GetRandomDouble(k - samples, k - samples + 1), &ts);
-
-        offset += TST_GetRandomDouble(-1.0e-2, 1.0e-2);
-        delay = TST_GetRandomDouble(1.0e-6, 1.0e-1);
-        disp = TST_GetRandomDouble(1.0e-6, 1.0e-1);
+        SCH_GetLastEventTime(&sample.time, NULL, NULL);
+        UTI_AddDoubleToTimespec(&sample.time, TST_GetRandomDouble(k - samples, k - samples + 1),
+                                &sample.time);
+
+        sample.offset += TST_GetRandomDouble(-1.0e-2, 1.0e-2);
+        sample.peer_delay = TST_GetRandomDouble(1.0e-6, 1.0e-1);
+        sample.peer_dispersion = TST_GetRandomDouble(1.0e-6, 1.0e-1);
+        sample.root_delay = sample.peer_delay;
+        sample.root_dispersion = sample.peer_dispersion;
+        sample.stratum = 1;
+        sample.leap = LEAP_Normal;
 
         DEBUG_LOG("source %d sample %d offset %f delay %f disp %f", j, k,
-                  offset, delay, disp);
+                  sample.offset, sample.peer_delay, sample.peer_dispersion);
 
-        SRC_AccumulateSample(srcs[j], &ts, offset, delay, disp, delay, disp,
-                             1, LEAP_Normal);
+        SRC_AccumulateSample(srcs[j], &sample);
       }
 
       for (k = 0; k <= j; k++) {
@@ -125,7 +128,7 @@ test_unit(void)
     }
 
     for (j = 0; j < sizeof (srcs) / sizeof (srcs[0]); j++) {
-      SRC_ReportSource(j, &report, &ts);
+      SRC_ReportSource(j, &report, &sample.time);
       SRC_DestroyInstance(srcs[j]);
     }
   }