chiark / gitweb /
timedated: ignore initial delta in history data
[elogind.git] / src / timedate / timedate-sntp.c
index e4aad36cc5499f42e410bbe0a59a227bf972f8c8..a85b37775290146f5afefab2cd5caa00b4ed9ef8 100644 (file)
 #define ADJ_SETOFFSET                   0x0100  /* add 'time' to current time */
 #endif
 
-/* Maximum delta in seconds which the system clock is gradually adjusted
- * to approach the network time. Deltas larger that this are set by letting
- * the system time jump. The maximum for adjtime is 500ms.
- */
-#define NTP_MAX_ADJUST                  0.2
+/* expected accuracy of time synchronization; used to adjust the poll interval */
+#define NTP_ACCURACY_SEC                0.2
 
 /*
- * "Define the required accuracy of the system clock, then calculate the
- * maximum timeout. Use the longest maximum timeout possible given the system
- * constraints to minimize time server aggregate load."
- *
  * "A client MUST NOT under any conditions use a poll interval less
  * than 15 seconds."
  */
-#define NTP_POLL_INTERVAL_MIN_SEC       16
+#define NTP_POLL_INTERVAL_MIN_SEC       32
 #define NTP_POLL_INTERVAL_MAX_SEC       2048
-#define NTP_ACCURACY_SEC                0.1
 
+/*
+ * Maximum delta in seconds which the system clock is gradually adjusted
+ * (slew) to approach the network time. Deltas larger that this are set by
+ * letting the system time jump. The kernel's limit for adjtime is 0.5s.
+ */
+#define NTP_MAX_ADJUST                  0.4
+
+/* NTP protocol, packet header */
 #define NTP_LEAP_PLUSSEC                1
 #define NTP_LEAP_MINUSSEC               2
 #define NTP_LEAP_NOTINSYNC              3
@@ -205,7 +205,7 @@ static int sntp_send_request(SNTPContext *sntp) {
          * matching answer to our request.
          *
          * The actual value does not matter, We do not care about the correct
-         * NTP UINT_MAX fraction, we just pass the plain nanosecond value.
+         * NTP UINT_MAX fraction; we just pass the plain nanosecond value.
          */
         clock_gettime(CLOCK_MONOTONIC, &sntp->trans_time_mon);
         clock_gettime(CLOCK_REALTIME, &sntp->trans_time);
@@ -265,7 +265,12 @@ static int sntp_arm_timer(SNTPContext *sntp, usec_t next) {
         }
 
         e = sd_event_source_get_event(sntp->event_receive);
-        r = sd_event_add_monotonic(e, &sntp->event_timer, now(CLOCK_MONOTONIC) + next, 0, sntp_timer, sntp);
+        r = sd_event_add_time(
+                        e,
+                        &sntp->event_timer,
+                        CLOCK_MONOTONIC,
+                        now(CLOCK_MONOTONIC) + next, 0,
+                        sntp_timer, sntp);
         if (r < 0)
                 return r;
 
@@ -288,7 +293,7 @@ static int sntp_clock_watch(sd_event_source *source, int fd, uint32_t revents, v
         }
 
         /* resync */
-        log_info("System time changed, resyncing.");
+        log_info("System time changed. Resyncing.");
         sntp->poll_resync = true;
         sntp_send_request(sntp);
 
@@ -394,6 +399,12 @@ static bool sntp_sample_spike_detection(SNTPContext *sntp, double offset, double
         double jitter;
         double j;
 
+        sntp->packet_count++;
+
+        /* ignore initial sample */
+        if (sntp->packet_count == 1)
+                return false;
+
         /* store the current data in our samples array */
         idx_cur = sntp->samples_idx;
         idx_new = (idx_cur + 1) % ELEMENTSOF(sntp->samples);
@@ -401,10 +412,8 @@ static bool sntp_sample_spike_detection(SNTPContext *sntp, double offset, double
         sntp->samples[idx_new].offset = offset;
         sntp->samples[idx_new].delay = delay;
 
-        sntp->packet_count++;
-        jitter = sntp->samples_jitter;
-
         /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
+        jitter = sntp->samples_jitter;
         for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(sntp->samples); i++)
                 if (sntp->samples[i].delay > 0 && sntp->samples[i].delay < sntp->samples[idx_min].delay)
                         idx_min = i;
@@ -442,7 +451,7 @@ static void sntp_adjust_poll(SNTPContext *sntp, double offset, bool spike) {
         }
 
         /* set to minimal poll interval */
-        if (fabs(offset) > NTP_ACCURACY_SEC) {
+        if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
                 sntp->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
                 return;
         }
@@ -494,24 +503,24 @@ static int sntp_receive_response(sd_event_source *source, int fd, uint32_t reven
         int r;
 
         if (revents & (EPOLLHUP|EPOLLERR)) {
-                log_debug("Server connection returned error, closing.");
+                log_debug("Server connection returned error. Closing.");
                 sntp_server_disconnect(sntp);
                 return -ENOTCONN;
         }
 
         len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
         if (len < 0) {
-                log_debug("Error receiving message, disconnecting");
+                log_debug("Error receiving message. Disconnecting.");
                 return -EINVAL;
         }
 
         if (iov.iov_len < sizeof(struct ntp_msg)) {
-                log_debug("Invalid response from server, disconnecting");
+                log_debug("Invalid response from server. Disconnecting.");
                 return -EINVAL;
         }
 
         if (sntp->server_addr.sin_addr.s_addr != server_addr.sin_addr.s_addr) {
-                log_debug("Response from unknown server, disconnecting");
+                log_debug("Response from unknown server. Disconnecting.");
                 return -EINVAL;
         }
 
@@ -527,35 +536,35 @@ static int sntp_receive_response(sd_event_source *source, int fd, uint32_t reven
                 }
         }
         if (!recv_time) {
-                log_debug("Invalid packet timestamp, disconnecting");
+                log_debug("Invalid packet timestamp. Disconnecting.");
                 return -EINVAL;
         }
 
         ntpmsg = iov.iov_base;
         if (!sntp->pending) {
-                log_debug("Unexpected reply, ignoring");
+                log_debug("Unexpected reply. Ignoring.");
                 return 0;
         }
 
         /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
-        if (be32toh(ntpmsg->origin_time.sec) != sntp->trans_time.tv_sec + OFFSET_1900_1970||
+        if (be32toh(ntpmsg->origin_time.sec) != sntp->trans_time.tv_sec + OFFSET_1900_1970 ||
             be32toh(ntpmsg->origin_time.frac) != sntp->trans_time.tv_nsec) {
-                log_debug("Invalid reply, not our transmit time, ignoring");
+                log_debug("Invalid reply; not our transmit time. Ignoring.");
                 return 0;
         }
 
         if (NTP_FIELD_LEAP(ntpmsg->field) == NTP_LEAP_NOTINSYNC) {
-                log_debug("Server is not synchronized, disconnecting");
+                log_debug("Server is not synchronized. Disconnecting.");
                 return -EINVAL;
         }
 
         if (NTP_FIELD_VERSION(ntpmsg->field) != 4) {
-                log_debug("Response NTPv%d, disconnecting", NTP_FIELD_VERSION(ntpmsg->field));
+                log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg->field));
                 return -EINVAL;
         }
 
         if (NTP_FIELD_MODE(ntpmsg->field) != NTP_MODE_SERVER) {
-                log_debug("Unsupported mode %d, disconnecting", NTP_FIELD_MODE(ntpmsg->field));
+                log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg->field));
                 return -EINVAL;
         }
 
@@ -579,7 +588,7 @@ static int sntp_receive_response(sd_event_source *source, int fd, uint32_t reven
          *  Transmit Timestamp      T3   time reply sent by server
          *  Destination Timestamp   T4   time reply received by client
          *
-         *  The roundtrip delay d and system clock offset t are defined as:
+         *  The round-trip delay, d, and system clock offset, t, are defined as:
          *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
          */
         clock_gettime(CLOCK_MONOTONIC, &now_ts);
@@ -661,7 +670,7 @@ int sntp_server_connect(SNTPContext *sntp, const char *server) {
         sntp->server_addr.sin_family = AF_INET;
         sntp->server_addr.sin_addr.s_addr = inet_addr(server);
 
-        sntp->poll_interval_usec = 2 * NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
+        sntp->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
 
         return sntp_send_request(sntp);
 }