cmdmon+client: add selectopts command

This command uses the new source function to modify configured selection
options of an NTP source or reference clock.
This commit is contained in:
Miroslav Lichvar 2022-12-14 16:04:43 +01:00
parent cd278d1826
commit 26889a8cb7
7 changed files with 118 additions and 4 deletions

13
candm.h
View file

@ -109,7 +109,8 @@
#define REQ_SELECT_DATA 69 #define REQ_SELECT_DATA 69
#define REQ_RELOAD_SOURCES 70 #define REQ_RELOAD_SOURCES 70
#define REQ_DOFFSET2 71 #define REQ_DOFFSET2 71
#define N_REQUEST_TYPES 72 #define REQ_MODIFY_SELECTOPTS 72
#define N_REQUEST_TYPES 73
/* Structure used to exchange timespecs independent of time_t size */ /* Structure used to exchange timespecs independent of time_t size */
typedef struct { typedef struct {
@ -371,6 +372,15 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_SelectData; } REQ_SelectData;
/* Mask and options reuse the REQ_ADDSRC flags */
typedef struct {
IPAddr address;
uint32_t ref_id;
uint32_t mask;
uint32_t options;
int32_t EOR;
} REQ_Modify_SelectOpts;
/* ================================================== */ /* ================================================== */
#define PKT_TYPE_CMD_REQUEST 1 #define PKT_TYPE_CMD_REQUEST 1
@ -477,6 +487,7 @@ typedef struct {
REQ_NTPSourceName ntp_source_name; REQ_NTPSourceName ntp_source_name;
REQ_AuthData auth_data; REQ_AuthData auth_data;
REQ_SelectData select_data; REQ_SelectData select_data;
REQ_Modify_SelectOpts modify_select_opts;
} data; /* Command specific parameters */ } data; /* Command specific parameters */
/* Padding used to prevent traffic amplification. It only defines the /* Padding used to prevent traffic amplification. It only defines the

View file

@ -1021,6 +1021,7 @@ give_help(void)
"sources [-a] [-v]\0Display information about current sources\0" "sources [-a] [-v]\0Display information about current sources\0"
"sourcestats [-a] [-v]\0Display statistics about collected measurements\0" "sourcestats [-a] [-v]\0Display statistics about collected measurements\0"
"selectdata [-a] [-v]\0Display information about source selection\0" "selectdata [-a] [-v]\0Display information about source selection\0"
"selectopts <address|refid> <+|-options>\0Modify selection options\0"
"reselect\0Force reselecting synchronisation source\0" "reselect\0Force reselecting synchronisation source\0"
"reselectdist <dist>\0Modify reselection distance\0" "reselectdist <dist>\0Modify reselection distance\0"
"\0\0" "\0\0"
@ -1135,8 +1136,8 @@ command_name_generator(const char *text, int state)
"manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll", "manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
"maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline", "maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline",
"polltarget", "quit", "refresh", "rekey", "reload", "reselect", "reselectdist", "reset", "polltarget", "quit", "refresh", "rekey", "reload", "reselect", "reselectdist", "reset",
"retries", "rtcdata", "selectdata", "serverstats", "settime", "shutdown", "smoothing", "retries", "rtcdata", "selectdata", "selectopts", "serverstats", "settime",
"smoothtime", "sourcename", "sources", "sourcestats", "shutdown", "smoothing", "smoothtime", "sourcename", "sources", "sourcestats",
"timeout", "tracking", "trimrtc", "waitsync", "writertc", "timeout", "tracking", "trimrtc", "waitsync", "writertc",
NULL NULL
}; };
@ -2899,6 +2900,55 @@ process_cmd_reset(CMD_Request *msg, char *line)
/* ================================================== */ /* ================================================== */
static int
process_cmd_selectopts(CMD_Request *msg, char *line)
{
int mask, options, option;
uint32_t ref_id;
IPAddr ip_addr;
char *src, *opt;
src = line;
line = CPS_SplitWord(line);
ref_id = 0;
/* Don't allow hostnames to avoid conflicts with reference IDs */
if (!UTI_StringToIdIP(src, &ip_addr) && !UTI_StringToIP(src, &ip_addr)) {
ip_addr.family = IPADDR_UNSPEC;
if (CPS_ParseRefid(src, &ref_id) == 0) {
LOG(LOGS_ERR, "Invalid syntax for selectopts command");
return 0;
}
}
mask = options = 0;
while (*line != '\0') {
opt = line;
line = CPS_SplitWord(line);
if ((opt[0] != '+' && opt[0] != '-') || (option = CPS_GetSelectOption(opt + 1)) == 0) {
LOG(LOGS_ERR, "Invalid syntax for selectopts command");
return 0;
}
mask |= option;
if (opt[0] == '+')
options |= option;
}
UTI_IPHostToNetwork(&ip_addr, &msg->data.modify_select_opts.address);
msg->data.modify_select_opts.ref_id = htonl(ref_id);
msg->data.modify_select_opts.mask = htonl(mask);
msg->data.modify_select_opts.options = htonl(convert_addsrc_sel_options(options));
msg->command = htons(REQ_MODIFY_SELECTOPTS);
return 1;
}
/* ================================================== */
static int static int
process_cmd_waitsync(char *line) process_cmd_waitsync(char *line)
{ {
@ -3201,6 +3251,8 @@ process_line(char *line)
} else if (!strcmp(command, "selectdata")) { } else if (!strcmp(command, "selectdata")) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_selectdata(line); ret = process_cmd_selectdata(line);
} else if (!strcmp(command, "selectopts")) {
do_normal_submit = process_cmd_selectopts(&tx_message, line);
} else if (!strcmp(command, "serverstats")) { } else if (!strcmp(command, "serverstats")) {
do_normal_submit = 0; do_normal_submit = 0;
ret = process_cmd_serverstats(line); ret = process_cmd_serverstats(line);

View file

@ -144,6 +144,7 @@ static const char permissions[] = {
PERMIT_AUTH, /* SELECT_DATA */ PERMIT_AUTH, /* SELECT_DATA */
PERMIT_AUTH, /* RELOAD_SOURCES */ PERMIT_AUTH, /* RELOAD_SOURCES */
PERMIT_AUTH, /* DOFFSET2 */ PERMIT_AUTH, /* DOFFSET2 */
PERMIT_AUTH, /* MODIFY_SELECTOPTS */
}; };
/* ================================================== */ /* ================================================== */
@ -1370,6 +1371,24 @@ handle_select_data(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.select_data.lo_limit = UTI_FloatHostToNetwork(report.lo_limit); tx_message->data.select_data.lo_limit = UTI_FloatHostToNetwork(report.lo_limit);
} }
/* ================================================== */
static void
handle_modify_selectopts(CMD_Request *rx_message, CMD_Reply *tx_message)
{
int mask, options;
uint32_t ref_id;
IPAddr ip_addr;
UTI_IPNetworkToHost(&rx_message->data.modify_select_opts.address, &ip_addr);
ref_id = ntohl(rx_message->data.modify_select_opts.ref_id);
mask = ntohl(rx_message->data.modify_select_opts.mask);
options = convert_addsrc_select_options(ntohl(rx_message->data.modify_select_opts.options));
if (!SRC_ModifySelectOptions(&ip_addr, ref_id, options, mask))
tx_message->status = htons(STT_NOSUCHSOURCE);
}
/* ================================================== */ /* ================================================== */
/* Read a packet and process it */ /* Read a packet and process it */
@ -1766,6 +1785,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
handle_reload_sources(&rx_message, &tx_message); handle_reload_sources(&rx_message, &tx_message);
break; break;
case REQ_MODIFY_SELECTOPTS:
handle_modify_selectopts(&rx_message, &tx_message);
break;
default: default:
DEBUG_LOG("Unhandled command %d", rx_command); DEBUG_LOG("Unhandled command %d", rx_command);
tx_message.status = htons(STT_FAILED); tx_message.status = htons(STT_FAILED);

View file

@ -522,6 +522,23 @@ This column displays the current leap status of the source.
* _-_ indicates that a leap second will be deleted at the end of the month. * _-_ indicates that a leap second will be deleted at the end of the month.
* _?_ indicates the unknown status (i.e. no valid measurement was made). * _?_ indicates the unknown status (i.e. no valid measurement was made).
[[selectopts]]*selectopts* _address|refid_ [_+|-option_]...::
The *selectopts* command modifies the configured selection options of an NTP
source specified by IP address (or the _ID#XXXXXXXXXX_ identifier used for
unknown addresses), or a reference clock specified by reference ID as a string.
+
The selection options can be added with the *+* symbol or removed with the *-*
symbol. The *selectdata* command can be used to verify the configuration. The
modified options will be applied in the next source selection, e.g. when a new
measurement is made, or the *reselect* command is executed.
+
An example of using this command is shown below.
+
----
selectopts 1.2.3.4 -noselect +prefer
selectopts GPS +trust
----
[[reselect]]*reselect*:: [[reselect]]*reselect*::
To avoid excessive switching between sources, *chronyd* can stay synchronised To avoid excessive switching between sources, *chronyd* can stay synchronised
to a source even when it is not currently the best one among the available to a source even when it is not currently the best one among the available

View file

@ -129,6 +129,7 @@ static const struct request_length request_lengths[] = {
REQ_LENGTH_ENTRY(select_data, select_data), /* SELECT_DATA */ REQ_LENGTH_ENTRY(select_data, select_data), /* SELECT_DATA */
REQ_LENGTH_ENTRY(null, null), /* RELOAD_SOURCES */ REQ_LENGTH_ENTRY(null, null), /* RELOAD_SOURCES */
REQ_LENGTH_ENTRY(doffset, null), /* DOFFSET2 */ REQ_LENGTH_ENTRY(doffset, null), /* DOFFSET2 */
REQ_LENGTH_ENTRY(modify_select_opts, null), /* MODIFY_SELECTOPTS */
}; };
static const uint16_t reply_lengths[] = { static const uint16_t reply_lengths[] = {

View file

@ -164,6 +164,9 @@ for chronyc_conf in \
"reselectdist 1e-3" \ "reselectdist 1e-3" \
"reset sources" \ "reset sources" \
"selectdata" \ "selectdata" \
"selectopts 1.2.3.4 -noselect +trust +require +prefer" \
"selectopts ID#0000000001 +prefer" \
"selectopts PPS0 +prefer" \
"settime 16:30" \ "settime 16:30" \
"settime 16:30:05" \ "settime 16:30:05" \
"settime Nov 21, 2015 16:30:05" \ "settime Nov 21, 2015 16:30:05" \
@ -327,6 +330,8 @@ maxupdateskew 192.168.123.1 10.0
minpoll 192.168.123.1 3 minpoll 192.168.123.1 3
minstratum 192.168.123.1 1 minstratum 192.168.123.1 1
polltarget 192.168.123.1 10 polltarget 192.168.123.1 10
selectopts 192.168.123.1 +trust +prefer -require
selectdata
delete 192.168.123.1" delete 192.168.123.1"
run_test || test_fail run_test || test_fail
@ -345,6 +350,10 @@ check_chronyc_output "^200 OK
200 OK 200 OK
200 OK 200 OK
200 OK 200 OK
200 OK
S Name/IP Address Auth COpts EOpts Last Score Interval Leap
=======================================================================
M node1\.net1\.clk N \-PT\-\- \-PT\-\- 0 1\.0 \+0ns \+0ns \?
200 OK$" || test_fail 200 OK$" || test_fail
chronyc_conf=" chronyc_conf="

View file

@ -42,6 +42,7 @@ for command in \
"reselect" \ "reselect" \
"reselectdist 1e-3" \ "reselectdist 1e-3" \
"reset sources" \ "reset sources" \
"selectopts $server -noselect +trust +prefer +require" \
"smoothtime reset" \ "smoothtime reset" \
"smoothtime activate" \ "smoothtime activate" \
; do ; do
@ -101,7 +102,7 @@ Total good RX : [0-9]+$" || test_fail
run_chronyc "selectdata" || test_fail run_chronyc "selectdata" || test_fail
check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap check_chronyc_output "^S Name/IP Address Auth COpts EOpts Last Score Interval Leap
======================================================================= =======================================================================
s 127\.0\.0\.1 N ----- ----- 0 1\.0 \+0ns \+0ns \?$" || test_fail s 127\.0\.0\.1 N -PTR- -PTR- 0 1\.0 \+0ns \+0ns \?$" || test_fail
run_chronyc "serverstats" || test_fail run_chronyc "serverstats" || test_fail
check_chronyc_output "^NTP packets received : [0-9]+ check_chronyc_output "^NTP packets received : [0-9]+