cmdmon: add ntpdata command

This commit is contained in:
Miroslav Lichvar 2016-11-25 15:02:35 +01:00
parent 7255f9ef74
commit 535ca64bba
11 changed files with 205 additions and 2 deletions

45
candm.h
View file

@ -94,7 +94,8 @@
#define REQ_SERVER_STATS 54 #define REQ_SERVER_STATS 54
#define REQ_CLIENT_ACCESSES_BY_INDEX2 55 #define REQ_CLIENT_ACCESSES_BY_INDEX2 55
#define REQ_LOCAL2 56 #define REQ_LOCAL2 56
#define N_REQUEST_TYPES 57 #define REQ_NTP_DATA 57
#define N_REQUEST_TYPES 58
/* Structure used to exchange timespecs independent of time_t size */ /* Structure used to exchange timespecs independent of time_t size */
typedef struct { typedef struct {
@ -310,6 +311,11 @@ typedef struct {
int32_t EOR; int32_t EOR;
} REQ_SmoothTime; } REQ_SmoothTime;
typedef struct {
IPAddr ip_addr;
int32_t EOR;
} REQ_NTPData;
/* ================================================== */ /* ================================================== */
#define PKT_TYPE_CMD_REQUEST 1 #define PKT_TYPE_CMD_REQUEST 1
@ -410,6 +416,7 @@ typedef struct {
REQ_ManualDelete manual_delete; REQ_ManualDelete manual_delete;
REQ_ReselectDistance reselect_distance; REQ_ReselectDistance reselect_distance;
REQ_SmoothTime smoothtime; REQ_SmoothTime smoothtime;
REQ_NTPData ntp_data;
} 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
@ -443,7 +450,8 @@ typedef struct {
#define RPY_SMOOTHING 13 #define RPY_SMOOTHING 13
#define RPY_SERVER_STATS 14 #define RPY_SERVER_STATS 14
#define RPY_CLIENT_ACCESSES_BY_INDEX2 15 #define RPY_CLIENT_ACCESSES_BY_INDEX2 15
#define N_REPLY_TYPES 16 #define RPY_NTP_DATA 16
#define N_REPLY_TYPES 17
/* Status codes */ /* Status codes */
#define STT_SUCCESS 0 #define STT_SUCCESS 0
@ -625,6 +633,38 @@ typedef struct {
int32_t EOR; int32_t EOR;
} RPY_Smoothing; } RPY_Smoothing;
#define RPY_NTP_FLAGS_TESTS 0x3ff
#define RPY_NTP_FLAG_INTERLEAVED 0x4000
#define RPY_NTP_FLAG_AUTHENTICATED 0x8000
typedef struct {
IPAddr remote_addr;
IPAddr local_addr;
uint16_t remote_port;
uint8_t leap;
uint8_t version;
uint8_t mode;
uint8_t stratum;
int8_t poll;
int8_t precision;
Float root_delay;
Float root_dispersion;
uint32_t ref_id;
Timespec ref_time;
Float offset;
Float peer_delay;
Float peer_dispersion;
Float response_time;
Float jitter_asymmetry;
uint16_t flags;
uint8_t tx_tss_char;
uint8_t rx_tss_char;
uint32_t total_tx_count;
uint32_t total_rx_count;
uint32_t total_valid_count;
int32_t EOR;
} RPY_NTPData;
typedef struct { typedef struct {
uint8_t version; uint8_t version;
uint8_t pkt_type; uint8_t pkt_type;
@ -653,6 +693,7 @@ typedef struct {
RPY_ManualList manual_list; RPY_ManualList manual_list;
RPY_Activity activity; RPY_Activity activity;
RPY_Smoothing smoothing; RPY_Smoothing smoothing;
RPY_NTPData ntp_data;
} data; /* Reply specific parameters */ } data; /* Reply specific parameters */
} CMD_Reply; } CMD_Reply;

View file

@ -133,6 +133,7 @@ static const char permissions[] = {
PERMIT_AUTH, /* SERVER_STATS */ PERMIT_AUTH, /* SERVER_STATS */
PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX2 */ PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX2 */
PERMIT_AUTH, /* LOCAL2 */ PERMIT_AUTH, /* LOCAL2 */
PERMIT_AUTH, /* NTP_DATA */
}; };
/* ================================================== */ /* ================================================== */
@ -1186,6 +1187,49 @@ handle_server_stats(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.server_stats.log_drops = htonl(report.log_drops); tx_message->data.server_stats.log_drops = htonl(report.log_drops);
} }
/* ================================================== */
static void
handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_NTPReport report;
UTI_IPNetworkToHost(&rx_message->data.ntp_data.ip_addr, &report.remote_addr);
if (!NSR_GetNTPReport(&report)) {
tx_message->status = htons(STT_NOSUCHSOURCE);
return;
}
tx_message->reply = htons(RPY_NTP_DATA);
UTI_IPHostToNetwork(&report.remote_addr, &tx_message->data.ntp_data.remote_addr);
UTI_IPHostToNetwork(&report.local_addr, &tx_message->data.ntp_data.local_addr);
tx_message->data.ntp_data.remote_port = htons(report.remote_port);
tx_message->data.ntp_data.leap = report.leap;
tx_message->data.ntp_data.version = report.version;
tx_message->data.ntp_data.mode = report.mode;
tx_message->data.ntp_data.stratum = report.stratum;
tx_message->data.ntp_data.poll = report.poll;
tx_message->data.ntp_data.precision = report.precision;
tx_message->data.ntp_data.root_delay = UTI_FloatHostToNetwork(report.root_delay);
tx_message->data.ntp_data.root_dispersion = UTI_FloatHostToNetwork(report.root_dispersion);
tx_message->data.ntp_data.ref_id = htonl(report.ref_id);
UTI_TimespecHostToNetwork(&report.ref_time, &tx_message->data.ntp_data.ref_time);
tx_message->data.ntp_data.offset = UTI_FloatHostToNetwork(report.offset);
tx_message->data.ntp_data.peer_delay = UTI_FloatHostToNetwork(report.peer_delay);
tx_message->data.ntp_data.peer_dispersion = UTI_FloatHostToNetwork(report.peer_dispersion);
tx_message->data.ntp_data.response_time = UTI_FloatHostToNetwork(report.response_time);
tx_message->data.ntp_data.jitter_asymmetry = UTI_FloatHostToNetwork(report.jitter_asymmetry);
tx_message->data.ntp_data.flags = htons((report.tests & RPY_NTP_FLAGS_TESTS) |
(report.interleaved ? RPY_NTP_FLAG_INTERLEAVED : 0) |
(report.authenticated ? RPY_NTP_FLAG_AUTHENTICATED : 0));
tx_message->data.ntp_data.tx_tss_char = report.tx_tss_char;
tx_message->data.ntp_data.rx_tss_char = report.rx_tss_char;
tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
}
/* ================================================== */ /* ================================================== */
/* Read a packet and process it */ /* Read a packet and process it */
@ -1573,6 +1617,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
handle_server_stats(&rx_message, &tx_message); handle_server_stats(&rx_message, &tx_message);
break; break;
case REQ_NTP_DATA:
handle_ntp_data(&rx_message, &tx_message);
break;
default: default:
DEBUG_LOG(LOGF_CmdMon, "Unhandled command %d", rx_command); DEBUG_LOG(LOGF_CmdMon, "Unhandled command %d", rx_command);
tx_message.status = htons(STT_FAILED); tx_message.status = htons(STT_FAILED);

View file

@ -186,6 +186,8 @@ struct NCR_Instance_Record {
int burst_good_samples_to_go; int burst_good_samples_to_go;
int burst_total_samples_to_go; int burst_total_samples_to_go;
/* Report from last valid response */
RPT_NTPReport report;
}; };
typedef struct { typedef struct {
@ -558,6 +560,7 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
result->local_tx.source = NTP_TS_DAEMON; result->local_tx.source = NTP_TS_DAEMON;
result->burst_good_samples_to_go = 0; result->burst_good_samples_to_go = 0;
result->burst_total_samples_to_go = 0; result->burst_total_samples_to_go = 0;
memset(&result->report, 0, sizeof (result->report));
NCR_ResetInstance(result); NCR_ResetInstance(result);
@ -1073,6 +1076,8 @@ transmit_timeout(void *arg)
++inst->tx_count; ++inst->tx_count;
inst->valid_rx = 0; inst->valid_rx = 0;
inst->updated_timestamps = 0; inst->updated_timestamps = 0;
if (sent)
inst->report.total_tx_count++;
/* If the source loses connectivity and our packets are still being sent, /* If the source loses connectivity and our packets are still being sent,
back off the sampling rate to reduce the network traffic. If it's the back off the sampling rate to reduce the network traffic. If it's the
@ -1284,6 +1289,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
stats = SRC_GetSourcestats(inst->source); stats = SRC_GetSourcestats(inst->source);
inst->report.total_rx_count++;
pkt_leap = NTP_LVM_TO_LEAP(message->lvm); pkt_leap = NTP_LVM_TO_LEAP(message->lvm);
pkt_refid = ntohl(message->reference_id); pkt_refid = ntohl(message->reference_id);
pkt_root_delay = UTI_Ntp32ToDouble(message->root_delay); pkt_root_delay = UTI_Ntp32ToDouble(message->root_delay);
@ -1585,6 +1592,35 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
assert(inst->tx_timeout_id); assert(inst->tx_timeout_id);
restart_timeout(inst, delay_time); restart_timeout(inst, delay_time);
} }
/* Update the NTP report */
inst->report.remote_addr = inst->remote_addr.ip_addr;
inst->report.local_addr = inst->local_addr.ip_addr;
inst->report.remote_port = inst->remote_addr.port;
inst->report.leap = NTP_LVM_TO_LEAP(message->lvm);
inst->report.version = NTP_LVM_TO_VERSION(message->lvm);
inst->report.mode = NTP_LVM_TO_MODE(message->lvm);
inst->report.stratum = message->stratum;
inst->report.poll = message->poll;
inst->report.precision = message->precision;
inst->report.root_delay = pkt_root_delay;
inst->report.root_dispersion = pkt_root_dispersion;
inst->report.ref_id = pkt_refid;
UTI_Ntp64ToTimespec(&message->reference_ts, &inst->report.ref_time);
inst->report.offset = offset;
inst->report.peer_delay = delay;
inst->report.peer_dispersion = dispersion;
inst->report.response_time = server_interval;
inst->report.jitter_asymmetry = SST_GetJitterAsymmetry(stats);
inst->report.tests = ((((((((test1 << 1 | test2) << 1 | test3) << 1 |
test5) << 1 | test6) << 1 | test7) << 1 |
testA) << 1 | testB) << 1 | testC) << 1 | testD;
inst->report.interleaved = interleaved_packet;
inst->report.authenticated = inst->auth_mode != AUTH_NONE;
inst->report.tx_tss_char = tss_chars[inst->local_tx.source];
inst->report.rx_tss_char = tss_chars[sample_rx_tss];
inst->report.total_valid_count++;
} }
/* Do measurement logging */ /* Do measurement logging */
@ -2140,6 +2176,14 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *n
/* ================================================== */ /* ================================================== */
void
NCR_GetNTPReport(NCR_Instance inst, RPT_NTPReport *report)
{
*report = inst->report;
}
/* ================================================== */
int int
NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all) NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
{ {

View file

@ -123,6 +123,7 @@ extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples); extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now); extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now);
extern void NCR_GetNTPReport(NCR_Instance inst, RPT_NTPReport *report);
extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all); extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
extern int NCR_CheckAccessRestriction(IPAddr *ip_addr); extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);

View file

@ -1120,6 +1120,26 @@ NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
} }
} }
/* ================================================== */
/* The ip address is assumed to be completed on input, that is how we
identify the source record. */
int
NSR_GetNTPReport(RPT_NTPReport *report)
{
NTP_Remote_Address rem_addr;
int slot, found;
rem_addr.ip_addr = report->remote_addr;
rem_addr.port = 0;
find_slot(&rem_addr, &slot, &found);
if (!found)
return 0;
NCR_GetNTPReport(get_record(slot)->data, report);
return 1;
}
/* ================================================== */ /* ================================================== */
void void

View file

@ -129,6 +129,8 @@ extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAd
extern void NSR_ReportSource(RPT_SourceReport *report, struct timespec *now); extern void NSR_ReportSource(RPT_SourceReport *report, struct timespec *now);
extern int NSR_GetNTPReport(RPT_NTPReport *report);
extern void NSR_GetActivityReport(RPT_ActivityReport *report); extern void NSR_GetActivityReport(RPT_ActivityReport *report);
#endif /* GOT_NTP_SOURCES_H */ #endif /* GOT_NTP_SOURCES_H */

View file

@ -113,6 +113,7 @@ static const struct request_length request_lengths[] = {
REQ_LENGTH_ENTRY(client_accesses_by_index, REQ_LENGTH_ENTRY(client_accesses_by_index,
client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */ client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */
REQ_LENGTH_ENTRY(local, null), /* LOCAL2 */ REQ_LENGTH_ENTRY(local, null), /* LOCAL2 */
REQ_LENGTH_ENTRY(ntp_data, ntp_data), /* NTP_DATA */
}; };
static const uint16_t reply_lengths[] = { static const uint16_t reply_lengths[] = {
@ -132,6 +133,7 @@ static const uint16_t reply_lengths[] = {
RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */ RPY_LENGTH_ENTRY(smoothing), /* SMOOTHING */
RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS */ RPY_LENGTH_ENTRY(server_stats), /* SERVER_STATS */
RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */ RPY_LENGTH_ENTRY(client_accesses_by_index), /* CLIENT_ACCESSES_BY_INDEX2 */
RPY_LENGTH_ENTRY(ntp_data), /* NTP_DATA */
}; };
/* ================================================== */ /* ================================================== */

View file

@ -131,4 +131,33 @@ typedef struct {
double remaining_time; double remaining_time;
} RPT_SmoothingReport; } RPT_SmoothingReport;
typedef struct {
IPAddr remote_addr;
IPAddr local_addr;
uint16_t remote_port;
uint8_t leap;
uint8_t version;
uint8_t mode;
uint8_t stratum;
int8_t poll;
int8_t precision;
double root_delay;
double root_dispersion;
uint32_t ref_id;
struct timespec ref_time;
double offset;
double peer_delay;
double peer_dispersion;
double response_time;
double jitter_asymmetry;
uint16_t tests;
int interleaved;
int authenticated;
char tx_tss_char;
char rx_tss_char;
uint32_t total_tx_count;
uint32_t total_rx_count;
uint32_t total_valid_count;
} RPT_NTPReport;
#endif /* GOT_REPORTS_H */ #endif /* GOT_REPORTS_H */

View file

@ -994,3 +994,11 @@ SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct ti
} }
/* ================================================== */ /* ================================================== */
double
SST_GetJitterAsymmetry(SST_Stats inst)
{
return inst->asymmetry;
}
/* ================================================== */

View file

@ -139,5 +139,7 @@ extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *repor
extern int SST_Samples(SST_Stats inst); extern int SST_Samples(SST_Stats inst);
extern double SST_GetJitterAsymmetry(SST_Stats inst);
#endif /* GOT_SOURCESTATS_H */ #endif /* GOT_SOURCESTATS_H */

View file

@ -297,6 +297,12 @@ NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
memset(report, 0, sizeof (*report)); memset(report, 0, sizeof (*report));
} }
int
NSR_GetNTPReport(RPT_NTPReport *report)
{
return 0;
}
void void
NSR_GetActivityReport(RPT_ActivityReport *report) NSR_GetActivityReport(RPT_ActivityReport *report)
{ {