cmdmon: add smoothing command

This adds a new request to get a current report on time smoothing.
This commit is contained in:
Miroslav Lichvar 2015-06-09 11:32:37 +02:00
parent 43116be122
commit fb9c2c7dc8
6 changed files with 122 additions and 13 deletions

20
candm.h
View file

@ -89,7 +89,8 @@
#define REQ_RESELECT 48
#define REQ_RESELECTDISTANCE 49
#define REQ_MODIFY_MAKESTEP 50
#define N_REQUEST_TYPES 51
#define REQ_SMOOTHING 51
#define N_REQUEST_TYPES 52
/* Special utoken value used to log on with first exchange being the
password. (This time value has long since gone by) */
@ -422,7 +423,8 @@ typedef struct {
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
#define RPY_MANUAL_LIST 11
#define RPY_ACTIVITY 12
#define N_REPLY_TYPES 13
#define RPY_SMOOTHING 13
#define N_REPLY_TYPES 14
/* Status codes */
#define STT_SUCCESS 0
@ -577,6 +579,19 @@ typedef struct {
int32_t EOR;
} RPY_Activity;
#define RPY_SMT_FLAG_ACTIVE 0x1
#define RPY_SMT_FLAG_LEAPONLY 0x2
typedef struct {
uint32_t flags;
Float offset;
Float freq_ppm;
Float wander_ppm;
Float last_update_ago;
Float remaining_time;
int32_t EOR;
} RPY_Smoothing;
typedef struct {
uint8_t version;
uint8_t pkt_type;
@ -603,6 +618,7 @@ typedef struct {
RPY_ClientAccessesByIndex client_accesses_by_index;
RPY_ManualList manual_list;
RPY_Activity activity;
RPY_Smoothing smoothing;
} data; /* Reply specific parameters */
/* authentication of the packet, there is no hole after the actual data

View file

@ -37,6 +37,7 @@
#include "keys.h"
#include "ntp_sources.h"
#include "ntp_core.h"
#include "smooth.h"
#include "sources.h"
#include "sourcestats.h"
#include "reference.h"
@ -162,6 +163,7 @@ static const char permissions[] = {
PERMIT_AUTH, /* RESELECT */
PERMIT_AUTH, /* RESELECTDISTANCE */
PERMIT_AUTH, /* MODIFY_MAKESTEP */
PERMIT_OPEN, /* SMOOTHING */
};
/* ================================================== */
@ -1223,6 +1225,31 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
/* ================================================== */
static void
handle_smoothing(CMD_Request *rx_message, CMD_Reply *tx_message)
{
RPT_SmoothingReport report;
struct timeval now;
SCH_GetLastEventTime(&now, NULL, NULL);
if (!SMT_GetSmoothingReport(&report, &now)) {
tx_message->status = htons(STT_NOTENABLED);
return;
}
tx_message->reply = htons(RPY_SMOOTHING);
tx_message->data.smoothing.flags = htonl((report.active ? RPY_SMT_FLAG_ACTIVE : 0) |
(report.leap_only ? RPY_SMT_FLAG_LEAPONLY : 0));
tx_message->data.smoothing.offset = UTI_FloatHostToNetwork(report.offset);
tx_message->data.smoothing.freq_ppm = UTI_FloatHostToNetwork(report.freq_ppm);
tx_message->data.smoothing.wander_ppm = UTI_FloatHostToNetwork(report.wander_ppm);
tx_message->data.smoothing.last_update_ago = UTI_FloatHostToNetwork(report.last_update_ago);
tx_message->data.smoothing.remaining_time = UTI_FloatHostToNetwork(report.remaining_time);
}
/* ================================================== */
static void
handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
{
@ -1889,6 +1916,10 @@ read_from_cmd_socket(void *anything)
handle_tracking(&rx_message, &tx_message);
break;
case REQ_SMOOTHING:
handle_smoothing(&rx_message, &tx_message);
break;
case REQ_SOURCESTATS:
handle_sourcestats(&rx_message, &tx_message);
break;

View file

@ -146,6 +146,8 @@ command_unpadded_length(CMD_Request *r)
return offsetof(CMD_Request, data.modify_minstratum.EOR);
case REQ_MODIFY_POLLTARGET:
return offsetof(CMD_Request, data.modify_polltarget.EOR);
case REQ_SMOOTHING:
return offsetof(CMD_Request, data.null.EOR);
default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0);
@ -296,6 +298,8 @@ PKL_CommandPaddingLength(CMD_Request *r)
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
case REQ_MODIFY_POLLTARGET:
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
case REQ_SMOOTHING:
return PADDING_LENGTH(data.null.EOR, data.smoothing.EOR);
default:
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
assert(0);
@ -359,7 +363,8 @@ PKL_ReplyLength(CMD_Reply *r)
}
case RPY_ACTIVITY:
return offsetof(CMD_Reply, data.activity.EOR);
case RPY_SMOOTHING:
return offsetof(CMD_Reply, data.smoothing.EOR);
default:
assert(0);
}

View file

@ -112,4 +112,14 @@ typedef struct {
int unresolved;
} RPT_ActivityReport;
typedef struct {
int active;
int leap_only;
double offset;
double freq_ppm;
double wander_ppm;
double last_update_ago;
double remaining_time;
} RPT_SmoothingReport;
#endif /* GOT_REPORTS_H */

View file

@ -97,15 +97,17 @@ static struct timeval last_update;
static void
get_offset_freq(struct timeval *now, double *offset, double *freq)
get_smoothing(struct timeval *now, double *poffset, double *pfreq,
double *pwander)
{
double elapsed, length;
double elapsed, length, offset, freq, wander;
int i;
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
*offset = smooth_offset;
*freq = smooth_freq;
offset = smooth_offset;
freq = smooth_freq;
wander = 0.0;
for (i = 0; i < NUM_STAGES; i++) {
if (elapsed <= 0.0)
@ -115,13 +117,21 @@ get_offset_freq(struct timeval *now, double *offset, double *freq)
if (length >= elapsed)
length = elapsed;
*offset -= length * (2.0 * *freq + stages[i].wander * length) / 2.0;
*freq += stages[i].wander * length;
wander = stages[i].wander;
offset -= length * (2.0 * freq + wander * length) / 2.0;
freq += wander * length;
elapsed -= length;
}
if (elapsed > 0.0)
*offset -= elapsed * *freq;
if (elapsed > 0.0) {
wander = 0.0;
offset -= elapsed * freq;
}
*poffset = offset;
*pfreq = freq;
if (pwander)
*pwander = wander;
}
static void
@ -193,11 +203,12 @@ update_smoothing(struct timeval *now, double offset, double freq)
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated%s", leap_only_mode ?
" (leap seconds only)" : "");
locked = 0;
last_update = *now;
}
return;
}
get_offset_freq(now, &smooth_offset, &smooth_freq);
get_smoothing(now, &smooth_offset, &smooth_freq, NULL);
smooth_offset += offset;
smooth_freq = (smooth_freq - freq) / (1.0 - freq);
last_update = *now;
@ -258,7 +269,7 @@ SMT_GetOffset(struct timeval *now)
if (!enabled)
return 0.0;
get_offset_freq(now, &offset, &freq);
get_smoothing(now, &offset, &freq, NULL);
return offset;
}
@ -289,3 +300,35 @@ SMT_Leap(struct timeval *now, int leap)
update_smoothing(now, leap, 0.0);
}
int
SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now)
{
double length, elapsed;
int i;
if (!enabled)
return 0;
report->active = !locked;
report->leap_only = leap_only_mode;
get_smoothing(now, &report->offset, &report->freq_ppm, &report->wander_ppm);
/* Convert to ppm and negate (positive values mean faster/speeding up) */
report->freq_ppm *= -1.0e6;
report->wander_ppm *= -1.0e6;
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
if (!locked && elapsed >= 0.0) {
for (i = 0, length = 0.0; i < NUM_STAGES; i++)
length += stages[i].length;
report->last_update_ago = elapsed;
report->remaining_time = elapsed < length ? length - elapsed : 0.0;
} else {
report->last_update_ago = 0.0;
report->remaining_time = 0.0;
}
return 1;
}

View file

@ -27,6 +27,8 @@
#ifndef GOT_SMOOTH_H
#define GOT_SMOOTH_H
#include "reports.h"
extern void SMT_Initialise(void);
extern void SMT_Finalise(void);
@ -39,4 +41,6 @@ extern void SMT_Reset(struct timeval *now);
extern void SMT_Leap(struct timeval *now, int leap);
extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
#endif