From 66086a4030e16e9a2c5dd48d5d6538a08cf7bfad Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 30 Apr 2018 22:37:02 +0900 Subject: [PATCH] timesync: save and expose NTP responce on bus --- src/timesync/meson.build | 1 + src/timesync/timesyncd-bus.c | 58 +++++++++++++++++++++++++++ src/timesync/timesyncd-manager.c | 60 ++++++---------------------- src/timesync/timesyncd-manager.h | 10 ++++- src/timesync/timesyncd-ntp-message.h | 45 +++++++++++++++++++++ 5 files changed, 126 insertions(+), 48 deletions(-) create mode 100644 src/timesync/timesyncd-ntp-message.h diff --git a/src/timesync/meson.build b/src/timesync/meson.build index 5ecf98a0297..c8113ff30bc 100644 --- a/src/timesync/meson.build +++ b/src/timesync/meson.build @@ -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()) diff --git a/src/timesync/timesyncd-bus.c b/src/timesync/timesyncd-bus.c index eb1c0b9c486..1932043fb95 100644 --- a/src/timesync/timesyncd-bus.c +++ b/src/timesync/timesyncd-bus.c @@ -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 }; diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c index 520e4e1f0ff..4f639577ad4 100644 --- a/src/timesync/timesyncd-manager.c +++ b/src/timesync/timesyncd-manager.c @@ -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" @@ -50,59 +49,18 @@ */ #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; diff --git a/src/timesync/timesyncd-manager.h b/src/timesync/timesyncd-manager.h index 500f94c5cad..1f045662544 100644 --- a/src/timesync/timesyncd-manager.h +++ b/src/timesync/timesyncd-manager.h @@ -7,6 +7,8 @@ Copyright 2014 Kay Sievers, Lennart Poettering ***/ +#include + #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 index 00000000000..14fba6d2cc0 --- /dev/null +++ b/src/timesync/timesyncd-ntp-message.h @@ -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_;