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:
parent
cd278d1826
commit
26889a8cb7
7 changed files with 118 additions and 4 deletions
13
candm.h
13
candm.h
|
@ -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
|
||||||
|
|
56
client.c
56
client.c
|
@ -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);
|
||||||
|
|
23
cmdmon.c
23
cmdmon.c
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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[] = {
|
||||||
|
|
|
@ -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="
|
||||||
|
|
|
@ -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]+
|
||||||
|
|
Loading…
Reference in a new issue