]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
timesync: save and expose NTP responce on bus
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 30 Apr 2018 13:37:02 +0000 (22:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 3 May 2018 09:05:14 +0000 (18:05 +0900)
src/timesync/meson.build
src/timesync/timesyncd-bus.c
src/timesync/timesyncd-manager.c
src/timesync/timesyncd-manager.h
src/timesync/timesyncd-ntp-message.h [new file with mode: 0644]

index 5ecf98a02976eed5d79850807790701e52f7fe04..c8113ff30bc72711d9dd674e903ac8f83b526bee 100644 (file)
@@ -10,6 +10,7 @@ systemd_timesyncd_sources = files('''
         timesyncd-conf.h
         timesyncd-manager.c
         timesyncd-manager.h
+        timesyncd-ntp-message.h
         timesyncd-server.c
         timesyncd-server.h
 '''.split())
index eb1c0b9c4867042faea912b94fb78a5d0fa662a5..1932043fb95c9ed439ac5def6a8d0b229bc44e51 100644 (file)
@@ -95,6 +95,62 @@ static int property_get_current_server_address(
         return sd_bus_message_close_container(reply);
 }
 
+static usec_t ntp_ts_short_to_usec(const struct ntp_ts_short *ts) {
+        return be16toh(ts->sec) * USEC_PER_SEC + (be16toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x10000ULL;
+}
+
+static usec_t ntp_ts_to_usec(const struct ntp_ts *ts) {
+        return (be32toh(ts->sec) - OFFSET_1900_1970) * USEC_PER_SEC + (be32toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x100000000ULL;
+}
+
+static int property_get_ntp_message(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        int r;
+
+        assert(m);
+        assert(reply);
+
+        r = sd_bus_message_open_container(reply, 'r', "uuuuittayttttbtt");
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "uuuuitt",
+                                  NTP_FIELD_LEAP(m->ntpmsg.field),
+                                  NTP_FIELD_VERSION(m->ntpmsg.field),
+                                  NTP_FIELD_MODE(m->ntpmsg.field),
+                                  m->ntpmsg.stratum,
+                                  m->ntpmsg.precision,
+                                  ntp_ts_short_to_usec(&m->ntpmsg.root_delay),
+                                  ntp_ts_short_to_usec(&m->ntpmsg.root_dispersion));
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_array(reply, 'y', m->ntpmsg.refid, 4);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "ttttbtt",
+                                  timespec_load(&m->origin_time),
+                                  ntp_ts_to_usec(&m->ntpmsg.recv_time),
+                                  ntp_ts_to_usec(&m->ntpmsg.trans_time),
+                                  timespec_load(&m->dest_time),
+                                  m->spike,
+                                  m->packet_count,
+                                  (usec_t) (m->samples_jitter * USEC_PER_SEC));
+        if (r < 0)
+                return r;
+
+        return sd_bus_message_close_container(reply);
+}
+
 static const sd_bus_vtable manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
@@ -107,6 +163,8 @@ static const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_min_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_usec), 0),
+        SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Frequency", "x", NULL, offsetof(Manager, drift_freq), 0),
 
         SD_BUS_VTABLE_END
 };
index 520e4e1f0ff36771c96201512c98c625c38aca6b..4f639577ad4280dd9a38aed24dff41c4a3cab40a 100644 (file)
@@ -28,7 +28,6 @@
 #include "network-util.h"
 #include "ratelimit.h"
 #include "socket-util.h"
-#include "sparse-endian.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
  */
 #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
-#define NTP_MODE_CLIENT                 3
-#define NTP_MODE_SERVER                 4
-#define NTP_FIELD_LEAP(f)               (((f) >> 6) & 3)
-#define NTP_FIELD_VERSION(f)            (((f) >> 3) & 7)
-#define NTP_FIELD_MODE(f)               ((f) & 7)
-#define NTP_FIELD(l, v, m)              (((l) << 6) | ((v) << 3) | (m))
-
 /* Default of maximum acceptable root distance in microseconds. */
 #define NTP_MAX_ROOT_DISTANCE           (5 * USEC_PER_SEC)
 
 /* Maximum number of missed replies before selecting another source. */
 #define NTP_MAX_MISSED_REPLIES          2
 
-/*
- * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
- * in seconds relative to 0h on 1 January 1900."
- */
-#define OFFSET_1900_1970        UINT64_C(2208988800)
-
 #define RETRY_USEC (30*USEC_PER_SEC)
 #define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
 #define RATELIMIT_BURST 10
 
 #define TIMEOUT_USEC (10*USEC_PER_SEC)
 
-struct ntp_ts {
-        be32_t sec;
-        be32_t frac;
-} _packed_;
-
-struct ntp_ts_short {
-        be16_t sec;
-        be16_t frac;
-} _packed_;
-
-struct ntp_msg {
-        uint8_t field;
-        uint8_t stratum;
-        int8_t poll;
-        int8_t precision;
-        struct ntp_ts_short root_delay;
-        struct ntp_ts_short root_dispersion;
-        char refid[4];
-        struct ntp_ts reference_time;
-        struct ntp_ts origin_time;
-        struct ntp_ts recv_time;
-        struct ntp_ts trans_time;
-} _packed_;
-
 static int manager_arm_timer(Manager *m, usec_t next);
 static int manager_clock_watch_setup(Manager *m);
 static int manager_listen_setup(Manager *m);
@@ -357,18 +315,18 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
         (void) touch("/var/lib/systemd/timesync/clock");
         (void) touch("/run/systemd/timesync/synchronized");
 
-        m->drift_ppm = tmx.freq / 65536;
+        m->drift_freq = tmx.freq;
 
         log_debug("  status       : %04i %s\n"
                   "  time now     : %"PRI_TIME".%03"PRI_USEC"\n"
                   "  constant     : %"PRI_TIMEX"\n"
                   "  offset       : %+.3f sec\n"
-                  "  freq offset  : %+"PRI_TIMEX" (%i ppm)\n",
+                  "  freq offset  : %+"PRI_TIMEX" (%+"PRI_TIMEX" ppm)\n",
                   tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
                   tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC,
                   tmx.constant,
                   (double)tmx.offset / NSEC_PER_SEC,
-                  tmx.freq, m->drift_ppm);
+                  tmx.freq, tmx.freq / 65536);
 
         return 0;
 }
@@ -652,10 +610,18 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
                         log_error_errno(r, "Failed to call clock_adjtime(): %m");
         }
 
-        log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
-                  m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
+        /* Save NTP response */
+        m->ntpmsg = ntpmsg;
+        m->origin_time = m->trans_time;
+        m->dest_time = *recv_time;
+        m->spike = spike;
+
+        log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+"PRI_TIMEX"ppm%s",
+                  m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_freq / 65536,
                   spike ? " (ignored)" : "");
 
+        (void) sd_bus_emit_properties_changed(m->bus, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", "NTPMessage", NULL);
+
         if (!m->good) {
                 _cleanup_free_ char *pretty = NULL;
 
index 500f94c5cad83f12b5eb763131d67b4a3608d825..1f045662544dc84f41a9b92fc6e2efd5f141a7c0 100644 (file)
@@ -7,6 +7,8 @@
   Copyright 2014 Kay Sievers, Lennart Poettering
 ***/
 
+#include <sys/timex.h>
+
 #include "sd-bus.h"
 #include "sd-event.h"
 #include "sd-network.h"
@@ -15,6 +17,7 @@
 #include "list.h"
 #include "ratelimit.h"
 #include "time-util.h"
+#include "timesyncd-ntp-message.h"
 
 typedef struct Manager Manager;
 
@@ -81,7 +84,7 @@ struct Manager {
         /* last change */
         bool jumped;
         bool sync;
-        int drift_ppm;
+        long drift_freq;
 
         /* watch for time changes */
         sd_event_source *event_clock_watch;
@@ -92,6 +95,11 @@ struct Manager {
 
         /* RTC runs in local time, leave it alone */
         bool rtc_local_time;
+
+        /* NTP response */
+        struct ntp_msg ntpmsg;
+        struct timespec origin_time, dest_time;
+        bool spike;
 };
 
 int manager_new(Manager **ret);
diff --git a/src/timesync/timesyncd-ntp-message.h b/src/timesync/timesyncd-ntp-message.h
new file mode 100644 (file)
index 0000000..14fba6d
--- /dev/null
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sparse-endian.h"
+
+/* NTP protocol, packet header */
+#define NTP_LEAP_PLUSSEC                1
+#define NTP_LEAP_MINUSSEC               2
+#define NTP_LEAP_NOTINSYNC              3
+#define NTP_MODE_CLIENT                 3
+#define NTP_MODE_SERVER                 4
+#define NTP_FIELD_LEAP(f)               (((f) >> 6) & 3)
+#define NTP_FIELD_VERSION(f)            (((f) >> 3) & 7)
+#define NTP_FIELD_MODE(f)               ((f) & 7)
+#define NTP_FIELD(l, v, m)              (((l) << 6) | ((v) << 3) | (m))
+
+/*
+ * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
+ * in seconds relative to 0h on 1 January 1900."
+ */
+#define OFFSET_1900_1970        UINT64_C(2208988800)
+
+struct ntp_ts {
+        be32_t sec;
+        be32_t frac;
+} _packed_;
+
+struct ntp_ts_short {
+        be16_t sec;
+        be16_t frac;
+} _packed_;
+
+struct ntp_msg {
+        uint8_t field;
+        uint8_t stratum;
+        int8_t poll;
+        int8_t precision;
+        struct ntp_ts_short root_delay;
+        struct ntp_ts_short root_dispersion;
+        char refid[4];
+        struct ntp_ts reference_time;
+        struct ntp_ts origin_time;
+        struct ntp_ts recv_time;
+        struct ntp_ts trans_time;
+} _packed_;