From e7a254265f0c26c80fa1c04beb9eb14064f97d2f Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 11 Mar 2020 12:20:51 +0100 Subject: [PATCH] cmdmon: add reset command The reset command drops all measurements and switches the reference to the unsynchronised state. This command can help chronyd with recovery when the measurements are known to be no longer valid or accurate, e.g. due to moving the computer to a different network, or resuming the computer from a low-power state (which resets the system clock). --- candm.h | 3 ++- client.c | 13 ++++++++++++- cmdmon.c | 17 +++++++++++++++++ doc/chronyc.adoc | 7 +++++++ pktlength.c | 1 + sources.c | 11 +++++++++++ sources.h | 2 ++ test/simulation/110-chronyc | 1 + 8 files changed, 53 insertions(+), 2 deletions(-) diff --git a/candm.h b/candm.h index 2d66997..e0d5140 100644 --- a/candm.h +++ b/candm.h @@ -103,7 +103,8 @@ #define REQ_ONOFFLINE 63 #define REQ_ADD_SOURCE 64 #define REQ_NTP_SOURCE_NAME 65 -#define N_REQUEST_TYPES 66 +#define REQ_RESET 66 +#define N_REQUEST_TYPES 67 /* Structure used to exchange timespecs independent of time_t size */ typedef struct { diff --git a/client.c b/client.c index de08be2..6f0aad2 100644 --- a/client.c +++ b/client.c @@ -1269,6 +1269,7 @@ give_help(void) "cyclelogs\0Close and re-open log files\0" "dump\0Dump all measurements to save files\0" "rekey\0Re-read keys from key file\0" + "reset\0Drop all measurements\0" "shutdown\0Stop daemon\0" "\0\0" "Client commands:\0\0" @@ -1315,7 +1316,7 @@ command_name_generator(const char *text, int state) "deny", "dns", "dump", "exit", "help", "keygen", "local", "makestep", "manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll", "maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline", - "polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist", + "polltarget", "quit", "refresh", "rekey", "reselect", "reselectdist", "reset", "retries", "rtcdata", "serverstats", "settime", "shutdown", "smoothing", "smoothtime", "sourcename", "sources", "sourcestats", "timeout", "tracking", "trimrtc", "waitsync", "writertc", @@ -2835,6 +2836,14 @@ process_cmd_shutdown(CMD_Request *msg, char *line) /* ================================================== */ +static void +process_cmd_reset(CMD_Request *msg, char *line) +{ + msg->command = htons(REQ_RESET); +} + +/* ================================================== */ + static int process_cmd_waitsync(char *line) { @@ -3129,6 +3138,8 @@ process_line(char *line) process_cmd_reselect(&tx_message, line); } else if (!strcmp(command, "reselectdist")) { do_normal_submit = process_cmd_reselectdist(&tx_message, line); + } else if (!strcmp(command, "reset")) { + process_cmd_reset(&tx_message, line); } else if (!strcmp(command, "retries")) { ret = process_cmd_retries(line); do_normal_submit = 0; diff --git a/cmdmon.c b/cmdmon.c index 7950e7a..908977e 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -134,6 +134,7 @@ static const char permissions[] = { PERMIT_AUTH, /* ONOFFLINE */ PERMIT_AUTH, /* ADD_SOURCE */ PERMIT_OPEN, /* NTP_SOURCE_NAME */ + PERMIT_AUTH, /* RESET */ }; /* ================================================== */ @@ -1218,6 +1219,18 @@ handle_ntp_source_name(CMD_Request *rx_message, CMD_Reply *tx_message) sizeof (tx_message->data.ntp_source_name.name)); } +/* ================================================== */ + +static void +handle_reset(CMD_Request *rx_message, CMD_Reply *tx_message) +{ + struct timespec cooked_now, now; + + SRC_ResetSources(); + SCH_GetLastEventTime(&cooked_now, NULL, &now); + LCL_NotifyExternalTimeStep(&now, &cooked_now, 0.0, 0.0); +} + /* ================================================== */ /* Read a packet and process it */ @@ -1595,6 +1608,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything) handle_ntp_source_name(&rx_message, &tx_message); break; + case REQ_RESET: + handle_reset(&rx_message, &tx_message); + break; + default: DEBUG_LOG("Unhandled command %d", rx_command); tx_message.status = htons(STT_FAILED); diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index 2a99a16..e97c66f 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -1171,6 +1171,13 @@ running. The *rekey* command causes *chronyd* to re-read the key file specified in the configuration file by the <> directive. +[[reset]]*reset*:: +The *reset* command causes *chronyd* to drop all measurements and switch to the +unsynchronised state. This command can help *chronyd* with recovery when the +measurements are known to be no longer valid or accurate, e.g. due to moving +the computer to a different network, or resuming the computer from a low-power +state (which resets the system clock). + [[shutdown]]*shutdown*:: The *shutdown* command causes *chronyd* to exit. This is equivalent to sending the process the SIGTERM signal. diff --git a/pktlength.c b/pktlength.c index 32b6f5a..911f725 100644 --- a/pktlength.c +++ b/pktlength.c @@ -123,6 +123,7 @@ static const struct request_length request_lengths[] = { REQ_LENGTH_ENTRY(ntp_source, null), /* ADD_SOURCE */ REQ_LENGTH_ENTRY(ntp_source_name, ntp_source_name), /* NTP_SOURCE_NAME */ + REQ_LENGTH_ENTRY(null, null), /* RESET */ }; static const uint16_t reply_lengths[] = { diff --git a/sources.c b/sources.c index b440d9d..2db0299 100644 --- a/sources.c +++ b/sources.c @@ -1252,6 +1252,17 @@ SRC_RemoveDumpFiles(void) /* ================================================== */ +void +SRC_ResetSources(void) +{ + int i; + + for (i = 0; i < n_sources; i++) + SRC_ResetInstance(sources[i]); +} + +/* ================================================== */ + int SRC_IsSyncPeer(SRC_Instance inst) { diff --git a/sources.h b/sources.h index c160029..75f0f23 100644 --- a/sources.h +++ b/sources.h @@ -114,6 +114,8 @@ extern void SRC_DumpSources(void); extern void SRC_ReloadSources(void); extern void SRC_RemoveDumpFiles(void); +extern void SRC_ResetSources(void); + extern int SRC_IsSyncPeer(SRC_Instance inst); extern int SRC_IsReachable(SRC_Instance inst); extern int SRC_ReadNumberOfSources(void); diff --git a/test/simulation/110-chronyc b/test/simulation/110-chronyc index bc6b232..e20cf3d 100755 --- a/test/simulation/110-chronyc +++ b/test/simulation/110-chronyc @@ -138,6 +138,7 @@ for chronyc_conf in \ "rekey" \ "reselect" \ "reselectdist 1e-3" \ + "reset" \ "settime 16:30" \ "settime 16:30:05" \ "settime Nov 21, 2015 16:30:05" \