cmdmon: add smoothing command
This adds a new request to get a current report on time smoothing.
This commit is contained in:
parent
43116be122
commit
fb9c2c7dc8
6 changed files with 122 additions and 13 deletions
20
candm.h
20
candm.h
|
@ -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
|
||||
|
|
31
cmdmon.c
31
cmdmon.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
10
reports.h
10
reports.h
|
@ -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 */
|
||||
|
|
63
smooth.c
63
smooth.c
|
@ -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;
|
||||
}
|
||||
|
|
4
smooth.h
4
smooth.h
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue