]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: add server support for experimental extension field
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 10 Nov 2021 13:56:31 +0000 (14:56 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 16 Nov 2021 09:23:20 +0000 (10:23 +0100)
Maintain a server monotonic timescale needed for the experimental
extension field. It follows the best estimate of frequency without
time corrections. Implement it as an offset relative to the NTP time,
starting at zero, using a slew handler to cancel time corrections of the
NTP clock. The 32-bit epoch ID is set to a random value on start and
every step of the system clock.

ntp_core.c

index 9eb67587c3fdf938fe9f6d7bf344c5e1c93a1943..bb92af5e3a32c6ebba09ce5ba5c32ed5bd8b8938 100644 (file)
@@ -294,6 +294,11 @@ static int server_sock_fd6;
 
 static ADF_AuthTable access_auth_table;
 
+/* Current offset between monotonic and cooked time, and its epoch ID
+   which is reset on clock steps */
+static double server_mono_offset;
+static uint32_t server_mono_epoch;
+
 /* Characters for printing synchronisation status and timestamping source */
 static const char leap_chars[4] = {'N', '+', '-', '?'};
 static const char tss_chars[3] = {'D', 'K', 'H'};
@@ -380,6 +385,20 @@ zero_local_timestamp(NTP_Local_Timestamp *ts)
 
 /* ================================================== */
 
+static void
+handle_slew(struct timespec *raw, struct timespec *cooked, double dfreq,
+            double doffset, LCL_ChangeType change_type, void *anything)
+{
+  if (change_type == LCL_ChangeAdjust) {
+    server_mono_offset += doffset;
+  } else {
+    UTI_GetRandomBytes(&server_mono_epoch, sizeof (server_mono_epoch));
+    server_mono_offset = 0.0;
+  }
+}
+
+/* ================================================== */
+
 void
 NCR_Initialise(void)
 {
@@ -396,6 +415,9 @@ NCR_Initialise(void)
   /* Server socket will be opened when access is allowed */
   server_sock_fd4 = INVALID_SOCK_FD;
   server_sock_fd6 = INVALID_SOCK_FD;
+
+  LCL_AddParameterChangeHandler(handle_slew, NULL);
+  handle_slew(NULL, NULL, 0.0, 0.0, LCL_ChangeUnknownStep, NULL);
 }
 
 /* ================================================== */
@@ -405,6 +427,8 @@ NCR_Finalise(void)
 {
   unsigned int i;
 
+  LCL_RemoveParameterChangeHandler(handle_slew, NULL);
+
   if (server_sock_fd4 != INVALID_SOCK_FD)
     NIO_CloseServerSocket(server_sock_fd4);
   if (server_sock_fd6 != INVALID_SOCK_FD)
@@ -925,6 +949,38 @@ receive_timeout(void *arg)
 
 /* ================================================== */
 
+static int
+add_ext_exp1(NTP_Packet *message, NTP_PacketInfo *info, struct timespec *rx,
+             double root_delay, double root_dispersion)
+{
+  struct timespec mono_rx;
+  NTP_ExtFieldExp1 exp1;
+  NTP_int64 ts_fuzz;
+
+  memset(&exp1, 0, sizeof (exp1));
+  exp1.magic = htonl(NTP_EF_EXP1_MAGIC);
+
+  if (info->mode != MODE_CLIENT) {
+    exp1.root_delay = UTI_DoubleToNtp32f28(root_delay);
+    exp1.root_dispersion = UTI_DoubleToNtp32f28(root_dispersion);
+    UTI_AddDoubleToTimespec(rx, server_mono_offset, &mono_rx);
+    UTI_GetNtp64Fuzz(&ts_fuzz, message->precision);
+    UTI_TimespecToNtp64(&mono_rx, &exp1.mono_receive_ts, &ts_fuzz);
+    exp1.mono_epoch = htonl(server_mono_epoch);
+  }
+
+  if (!NEF_AddField(message, info, NTP_EF_EXP1, &exp1, sizeof (exp1))) {
+    DEBUG_LOG("Could not add EF");
+    return 0;
+  }
+
+  info->ext_field_flags |= NTP_EF_FLAG_EXP1;
+
+  return 1;
+}
+
+/* ================================================== */
+
 static int
 transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
                 int interleaved, /* Flag enabling interleaved mode */
@@ -1070,6 +1126,11 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
     return 0;
 
   if (ext_field_flags) {
+    if (ext_field_flags & NTP_EF_FLAG_EXP1) {
+      if (!add_ext_exp1(&message, &info, &local_receive,
+                        our_root_delay, our_root_dispersion))
+        return 0;
+    }
   }
 
   do {