cmdmon: report new client and server statistics

Report the new clientlog data in the clients and serverstats reports.

Add -k option to the clients command to select between command and
NTS-KE data.
This commit is contained in:
Miroslav Lichvar 2020-05-20 12:02:03 +02:00
parent f8df4789b1
commit ab54f76a38
7 changed files with 87 additions and 36 deletions

16
candm.h
View file

@ -412,8 +412,8 @@ typedef struct {
#define PROTO_VERSION_PADDING 6 #define PROTO_VERSION_PADDING 6
/* The maximum length of padding in request packet, currently /* The maximum length of padding in request packet, currently
defined by MANUAL_LIST */ defined by CLIENT_ACCESSES_BY_INDEX3 */
#define MAX_PADDING_LENGTH 396 #define MAX_PADDING_LENGTH 484
/* ================================================== */ /* ================================================== */
@ -502,7 +502,9 @@ typedef struct {
#define RPY_MANUAL_LIST2 18 #define RPY_MANUAL_LIST2 18
#define RPY_NTP_SOURCE_NAME 19 #define RPY_NTP_SOURCE_NAME 19
#define RPY_AUTH_DATA 20 #define RPY_AUTH_DATA 20
#define N_REPLY_TYPES 21 #define RPY_CLIENT_ACCESSES_BY_INDEX3 21
#define RPY_SERVER_STATS2 22
#define N_REPLY_TYPES 23
/* Status codes */ /* Status codes */
#define STT_SUCCESS 0 #define STT_SUCCESS 0
@ -620,14 +622,17 @@ typedef struct {
typedef struct { typedef struct {
IPAddr ip; IPAddr ip;
uint32_t ntp_hits; uint32_t ntp_hits;
uint32_t nke_hits;
uint32_t cmd_hits; uint32_t cmd_hits;
uint32_t ntp_drops; uint32_t ntp_drops;
uint32_t nke_drops;
uint32_t cmd_drops; uint32_t cmd_drops;
int8_t ntp_interval; int8_t ntp_interval;
int8_t nke_interval;
int8_t cmd_interval; int8_t cmd_interval;
int8_t ntp_timeout_interval; int8_t ntp_timeout_interval;
int8_t pad;
uint32_t last_ntp_hit_ago; uint32_t last_ntp_hit_ago;
uint32_t last_nke_hit_ago;
uint32_t last_cmd_hit_ago; uint32_t last_cmd_hit_ago;
} RPY_ClientAccesses_Client; } RPY_ClientAccesses_Client;
@ -641,10 +646,13 @@ typedef struct {
typedef struct { typedef struct {
uint32_t ntp_hits; uint32_t ntp_hits;
uint32_t nke_hits;
uint32_t cmd_hits; uint32_t cmd_hits;
uint32_t ntp_drops; uint32_t ntp_drops;
uint32_t nke_drops;
uint32_t cmd_drops; uint32_t cmd_drops;
uint32_t log_drops; uint32_t log_drops;
uint32_t ntp_auth_hits;
int32_t EOR; int32_t EOR;
} RPY_ServerStats; } RPY_ServerStats;

View file

@ -2564,19 +2564,25 @@ process_cmd_serverstats(char *line)
CMD_Reply reply; CMD_Reply reply;
request.command = htons(REQ_SERVER_STATS); request.command = htons(REQ_SERVER_STATS);
if (!request_reply(&request, &reply, RPY_SERVER_STATS, 0)) if (!request_reply(&request, &reply, RPY_SERVER_STATS2, 0))
return 0; return 0;
print_report("NTP packets received : %U\n" print_report("NTP packets received : %U\n"
"NTP packets dropped : %U\n" "NTP packets dropped : %U\n"
"Command packets received : %U\n" "Command packets received : %U\n"
"Command packets dropped : %U\n" "Command packets dropped : %U\n"
"Client log records dropped : %U\n", "Client log records dropped : %U\n"
"NTS-KE connections accepted: %U\n"
"NTS-KE connections dropped : %U\n"
"Authenticated NTP packets : %U\n",
(unsigned long)ntohl(reply.data.server_stats.ntp_hits), (unsigned long)ntohl(reply.data.server_stats.ntp_hits),
(unsigned long)ntohl(reply.data.server_stats.ntp_drops), (unsigned long)ntohl(reply.data.server_stats.ntp_drops),
(unsigned long)ntohl(reply.data.server_stats.cmd_hits), (unsigned long)ntohl(reply.data.server_stats.cmd_hits),
(unsigned long)ntohl(reply.data.server_stats.cmd_drops), (unsigned long)ntohl(reply.data.server_stats.cmd_drops),
(unsigned long)ntohl(reply.data.server_stats.log_drops), (unsigned long)ntohl(reply.data.server_stats.log_drops),
(unsigned long)ntohl(reply.data.server_stats.nke_hits),
(unsigned long)ntohl(reply.data.server_stats.nke_drops),
(unsigned long)ntohl(reply.data.server_stats.ntp_auth_hits),
REPORT_END); REPORT_END);
return 1; return 1;
@ -2676,16 +2682,20 @@ process_cmd_clients(char *line)
IPAddr ip; IPAddr ip;
uint32_t i, n_clients, next_index, n_indices, min_hits, reset; uint32_t i, n_clients, next_index, n_indices, min_hits, reset;
RPY_ClientAccesses_Client *client; RPY_ClientAccesses_Client *client;
char name[50], *opt, *arg; char header[80], name[50], *opt, *arg;
int nke;
next_index = 0; next_index = 0;
min_hits = 0; min_hits = 0;
reset = 0; reset = 0;
nke = 0;
while (*line) { while (*line) {
opt = line; opt = line;
line = CPS_SplitWord(line); line = CPS_SplitWord(line);
if (strcmp(opt, "-p") == 0) { if (strcmp(opt, "-k") == 0) {
nke = 1;
} else if (strcmp(opt, "-p") == 0) {
arg = line; arg = line;
line = CPS_SplitWord(line); line = CPS_SplitWord(line);
if (sscanf(arg, "%"SCNu32, &min_hits) != 1) { if (sscanf(arg, "%"SCNu32, &min_hits) != 1) {
@ -2697,7 +2707,10 @@ process_cmd_clients(char *line)
} }
} }
print_header("Hostname NTP Drop Int IntL Last Cmd Drop Int Last"); snprintf(header, sizeof (header),
"Hostname NTP Drop Int IntL Last %6s Drop Int Last",
nke ? "NTS-KE" : "Cmd");
print_header(header);
while (1) { while (1) {
request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX3); request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX3);
@ -2706,7 +2719,7 @@ process_cmd_clients(char *line)
request.data.client_accesses_by_index.min_hits = htonl(min_hits); request.data.client_accesses_by_index.min_hits = htonl(min_hits);
request.data.client_accesses_by_index.reset = htonl(reset); request.data.client_accesses_by_index.reset = htonl(reset);
if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX2, 0)) if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX3, 0))
return 0; return 0;
n_clients = ntohl(reply.data.client_accesses_by_index.n_clients); n_clients = ntohl(reply.data.client_accesses_by_index.n_clients);
@ -2731,10 +2744,11 @@ process_cmd_clients(char *line)
client->ntp_interval, client->ntp_interval,
client->ntp_timeout_interval, client->ntp_timeout_interval,
(unsigned long)ntohl(client->last_ntp_hit_ago), (unsigned long)ntohl(client->last_ntp_hit_ago),
(unsigned long)ntohl(client->cmd_hits), (unsigned long)ntohl(nke ? client->nke_hits : client->cmd_hits),
(unsigned long)ntohl(client->cmd_drops), (unsigned long)ntohl(nke ? client->nke_drops : client->cmd_drops),
client->cmd_interval, nke ? client->nke_interval : client->cmd_interval,
(unsigned long)ntohl(client->last_cmd_hit_ago), (unsigned long)ntohl(nke ? client->last_nke_hit_ago :
client->last_cmd_hit_ago),
REPORT_END); REPORT_END);
} }

View file

@ -679,13 +679,17 @@ CLG_GetClientAccessReportByIndex(int index, int reset, uint32_t min_hits,
report->ip_addr = record->ip_addr; report->ip_addr = record->ip_addr;
report->ntp_hits = record->hits[CLG_NTP]; report->ntp_hits = record->hits[CLG_NTP];
report->nke_hits = record->hits[CLG_NTSKE];
report->cmd_hits = record->hits[CLG_CMDMON]; report->cmd_hits = record->hits[CLG_CMDMON];
report->ntp_drops = record->drops[CLG_NTP]; report->ntp_drops = record->drops[CLG_NTP];
report->nke_drops = record->drops[CLG_NTSKE];
report->cmd_drops = record->drops[CLG_CMDMON]; report->cmd_drops = record->drops[CLG_CMDMON];
report->ntp_interval = get_interval(record->rate[CLG_NTP]); report->ntp_interval = get_interval(record->rate[CLG_NTP]);
report->nke_interval = get_interval(record->rate[CLG_NTSKE]);
report->cmd_interval = get_interval(record->rate[CLG_CMDMON]); report->cmd_interval = get_interval(record->rate[CLG_CMDMON]);
report->ntp_timeout_interval = get_interval(record->ntp_timeout_rate); report->ntp_timeout_interval = get_interval(record->ntp_timeout_rate);
report->last_ntp_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_NTP]); report->last_ntp_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_NTP]);
report->last_nke_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_NTSKE]);
report->last_cmd_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_CMDMON]); report->last_cmd_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_CMDMON]);
} }
@ -705,8 +709,11 @@ void
CLG_GetServerStatsReport(RPT_ServerStatsReport *report) CLG_GetServerStatsReport(RPT_ServerStatsReport *report)
{ {
report->ntp_hits = total_hits[CLG_NTP]; report->ntp_hits = total_hits[CLG_NTP];
report->nke_hits = total_hits[CLG_NTSKE];
report->cmd_hits = total_hits[CLG_CMDMON]; report->cmd_hits = total_hits[CLG_CMDMON];
report->ntp_drops = total_drops[CLG_NTP]; report->ntp_drops = total_drops[CLG_NTP];
report->nke_drops = total_drops[CLG_NTSKE];
report->cmd_drops = total_drops[CLG_CMDMON]; report->cmd_drops = total_drops[CLG_CMDMON];
report->log_drops = total_record_drops; report->log_drops = total_record_drops;
report->ntp_auth_hits = total_ntp_auth_hits;
} }

View file

@ -1020,7 +1020,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
return; return;
} }
tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX2); tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX3);
tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices); tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices);
for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) { for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) {
@ -1031,13 +1031,17 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
UTI_IPHostToNetwork(&report.ip_addr, &client->ip); UTI_IPHostToNetwork(&report.ip_addr, &client->ip);
client->ntp_hits = htonl(report.ntp_hits); client->ntp_hits = htonl(report.ntp_hits);
client->nke_hits = htonl(report.nke_hits);
client->cmd_hits = htonl(report.cmd_hits); client->cmd_hits = htonl(report.cmd_hits);
client->ntp_drops = htonl(report.ntp_drops); client->ntp_drops = htonl(report.ntp_drops);
client->nke_drops = htonl(report.nke_drops);
client->cmd_drops = htonl(report.cmd_drops); client->cmd_drops = htonl(report.cmd_drops);
client->ntp_interval = report.ntp_interval; client->ntp_interval = report.ntp_interval;
client->nke_interval = report.nke_interval;
client->cmd_interval = report.cmd_interval; client->cmd_interval = report.cmd_interval;
client->ntp_timeout_interval = report.ntp_timeout_interval; client->ntp_timeout_interval = report.ntp_timeout_interval;
client->last_ntp_hit_ago = htonl(report.last_ntp_hit_ago); client->last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
client->last_nke_hit_ago = htonl(report.last_nke_hit_ago);
client->last_cmd_hit_ago = htonl(report.last_cmd_hit_ago); client->last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
} }
@ -1139,12 +1143,15 @@ handle_server_stats(CMD_Request *rx_message, CMD_Reply *tx_message)
RPT_ServerStatsReport report; RPT_ServerStatsReport report;
CLG_GetServerStatsReport(&report); CLG_GetServerStatsReport(&report);
tx_message->reply = htons(RPY_SERVER_STATS); tx_message->reply = htons(RPY_SERVER_STATS2);
tx_message->data.server_stats.ntp_hits = htonl(report.ntp_hits); tx_message->data.server_stats.ntp_hits = htonl(report.ntp_hits);
tx_message->data.server_stats.nke_hits = htonl(report.nke_hits);
tx_message->data.server_stats.cmd_hits = htonl(report.cmd_hits); tx_message->data.server_stats.cmd_hits = htonl(report.cmd_hits);
tx_message->data.server_stats.ntp_drops = htonl(report.ntp_drops); tx_message->data.server_stats.ntp_drops = htonl(report.ntp_drops);
tx_message->data.server_stats.nke_drops = htonl(report.nke_drops);
tx_message->data.server_stats.cmd_drops = htonl(report.cmd_drops); tx_message->data.server_stats.cmd_drops = htonl(report.cmd_drops);
tx_message->data.server_stats.log_drops = htonl(report.log_drops); tx_message->data.server_stats.log_drops = htonl(report.log_drops);
tx_message->data.server_stats.ntp_auth_hits = htonl(report.ntp_auth_hits);
} }
/* ================================================== */ /* ================================================== */

View file

@ -958,16 +958,17 @@ This command can be used to examine the effect of a series of *allow*, *allow
all*, *deny*, and *deny all* commands specified either via *chronyc*, or in all*, *deny*, and *deny all* commands specified either via *chronyc*, or in
*chronyd*'s configuration file. *chronyd*'s configuration file.
[[clients]]*clients* [*-p* _packets_] *[*-r*]:: [[clients]]*clients* [*-p* _packets_] [*-k*] [*-r*]::
This command shows a list of clients that have accessed the server, through This command shows a list of clients that have accessed the server, through
either the NTP or command ports. It does not include accesses over the NTP, command, or NTS-KE port. It does not include accesses over the Unix
the Unix domain command socket. domain command socket.
+ +
The *-p* option specifies the minimum number of received NTP or command The *-p* option specifies the minimum number of received NTP or command
packets needed to include a client in the list. The default value is 0, i.e. packets, or accepted NTS-KE connections, needed to include a client in the
all clients are reported. If the *-r* option is specified, *chronyd* will reset list. The default value is 0, i.e. all clients are reported. With the *-k*
the counters of received and dropped packets after reporting the current option the last four columns will show the NTS-KE accesses instead of command
values. accesses. If the *-r* option is specified, *chronyd* will reset the counters of
received and dropped packets or connections after reporting the current values.
+ +
An example of the output is: An example of the output is:
+ +
@ -992,20 +993,22 @@ The columns are as follows:
. The average interval between NTP packets. . The average interval between NTP packets.
. The average interval between NTP packets after limiting the response rate. . The average interval between NTP packets after limiting the response rate.
. Time since the last NTP packet was received . Time since the last NTP packet was received
. The number of command packets received from the client. . The number of command packets or NTS-KE connections received/accepted from
. The number of command packets dropped to limit the response rate. the client.
. The average interval between command packets. . The number of command packets or NTS-KE connections dropped to limit the
. Time since the last command packet was received. response rate.
. The average interval between command packets or NTS-KE connections.
. Time since the last command packet or NTS-KE connection was
received/accepted.
[[serverstats]]*serverstats*:: [[serverstats]]*serverstats*::
The *serverstats* command displays how many valid NTP and command requests The *serverstats* command displays how many valid NTP and command requests, and
*chronyd* as a server received from clients, how many of them were dropped to NTS-KE connections, *chronyd* operating as a server received from clients, and
limit the response rate as configured by the how many of them were dropped due to rate limiting. It also displays how many
<<chrony.conf.adoc#ratelimit,*ratelimit*>> and
<<chrony.conf.adoc#cmdratelimit,*cmdratelimit*>> directives, and how many
client log records were dropped due to the memory limit configured by the client log records were dropped due to the memory limit configured by the
<<chrony.conf.adoc#clientloglimit,*clientloglimit*>> directive. An example of <<chrony.conf.adoc#clientloglimit,*clientloglimit*>> directive and how many of
the output is shown below. the NTP requests (from those which were not dropped) were authenticated. An
example of the output is shown below.
+ +
---- ----
NTP packets received : 1598 NTP packets received : 1598
@ -1013,6 +1016,9 @@ NTP packets dropped : 8
Command packets received : 19 Command packets received : 19
Command packets dropped : 0 Command packets dropped : 0
Client log records dropped : 0 Client log records dropped : 0
NTS-KE connections accepted: 3
NTS-KE connections dropped : 0
Authenticated NTP packets : 189
---- ----
[[allow]]*allow* [*all*] [_subnet_]:: [[allow]]*allow* [*all*] [_subnet_]::

View file

@ -143,13 +143,15 @@ static const uint16_t reply_lengths[] = {
0, /* MANUAL_LIST - not supported */ 0, /* MANUAL_LIST - not supported */
RPY_LENGTH_ENTRY(activity), /* ACTIVITY */ RPY_LENGTH_ENTRY(activity), /* ACTIVITY */
RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */ RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS */ 0, /* SERVER_STATS - not supported */
RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */ 0, /* CLIENT_ACCESSES_BY_INDEX2 - not supported */
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */ RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */
RPY_LENGTH_ENTRY(manual_timestamp), /* MANUAL_TIMESTAMP2 */ RPY_LENGTH_ENTRY(manual_timestamp), /* MANUAL_TIMESTAMP2 */
RPY_LENGTH_ENTRY(manual_list), /* MANUAL_LIST2 */ RPY_LENGTH_ENTRY(manual_list), /* MANUAL_LIST2 */
RPY_LENGTH_ENTRY(ntp_source_name), /* NTP_SOURCE_NAME */ RPY_LENGTH_ENTRY(ntp_source_name), /* NTP_SOURCE_NAME */
RPY_LENGTH_ENTRY(auth_data), /* AUTH_DATA */ RPY_LENGTH_ENTRY(auth_data), /* AUTH_DATA */
RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX3 */
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS2 */
}; };
/* ================================================== */ /* ================================================== */

View file

@ -88,22 +88,29 @@ typedef struct {
typedef struct { typedef struct {
IPAddr ip_addr; IPAddr ip_addr;
uint32_t ntp_hits; uint32_t ntp_hits;
uint32_t nke_hits;
uint32_t cmd_hits; uint32_t cmd_hits;
uint16_t ntp_drops; uint16_t ntp_drops;
uint16_t nke_drops;
uint16_t cmd_drops; uint16_t cmd_drops;
int8_t ntp_interval; int8_t ntp_interval;
int8_t nke_interval;
int8_t cmd_interval; int8_t cmd_interval;
int8_t ntp_timeout_interval; int8_t ntp_timeout_interval;
uint32_t last_ntp_hit_ago; uint32_t last_ntp_hit_ago;
uint32_t last_nke_hit_ago;
uint32_t last_cmd_hit_ago; uint32_t last_cmd_hit_ago;
} RPT_ClientAccessByIndex_Report; } RPT_ClientAccessByIndex_Report;
typedef struct { typedef struct {
uint32_t ntp_hits; uint32_t ntp_hits;
uint32_t nke_hits;
uint32_t cmd_hits; uint32_t cmd_hits;
uint32_t ntp_drops; uint32_t ntp_drops;
uint32_t nke_drops;
uint32_t cmd_drops; uint32_t cmd_drops;
uint32_t log_drops; uint32_t log_drops;
uint32_t ntp_auth_hits;
} RPT_ServerStatsReport; } RPT_ServerStatsReport;
typedef struct { typedef struct {