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_RESELECT 48
|
||||||
#define REQ_RESELECTDISTANCE 49
|
#define REQ_RESELECTDISTANCE 49
|
||||||
#define REQ_MODIFY_MAKESTEP 50
|
#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
|
/* Special utoken value used to log on with first exchange being the
|
||||||
password. (This time value has long since gone by) */
|
password. (This time value has long since gone by) */
|
||||||
|
@ -422,7 +423,8 @@ typedef struct {
|
||||||
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
|
#define RPY_CLIENT_ACCESSES_BY_INDEX 10
|
||||||
#define RPY_MANUAL_LIST 11
|
#define RPY_MANUAL_LIST 11
|
||||||
#define RPY_ACTIVITY 12
|
#define RPY_ACTIVITY 12
|
||||||
#define N_REPLY_TYPES 13
|
#define RPY_SMOOTHING 13
|
||||||
|
#define N_REPLY_TYPES 14
|
||||||
|
|
||||||
/* Status codes */
|
/* Status codes */
|
||||||
#define STT_SUCCESS 0
|
#define STT_SUCCESS 0
|
||||||
|
@ -577,6 +579,19 @@ typedef struct {
|
||||||
int32_t EOR;
|
int32_t EOR;
|
||||||
} RPY_Activity;
|
} 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 {
|
typedef struct {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t pkt_type;
|
uint8_t pkt_type;
|
||||||
|
@ -603,6 +618,7 @@ typedef struct {
|
||||||
RPY_ClientAccessesByIndex client_accesses_by_index;
|
RPY_ClientAccessesByIndex client_accesses_by_index;
|
||||||
RPY_ManualList manual_list;
|
RPY_ManualList manual_list;
|
||||||
RPY_Activity activity;
|
RPY_Activity activity;
|
||||||
|
RPY_Smoothing smoothing;
|
||||||
} data; /* Reply specific parameters */
|
} data; /* Reply specific parameters */
|
||||||
|
|
||||||
/* authentication of the packet, there is no hole after the actual data
|
/* 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 "keys.h"
|
||||||
#include "ntp_sources.h"
|
#include "ntp_sources.h"
|
||||||
#include "ntp_core.h"
|
#include "ntp_core.h"
|
||||||
|
#include "smooth.h"
|
||||||
#include "sources.h"
|
#include "sources.h"
|
||||||
#include "sourcestats.h"
|
#include "sourcestats.h"
|
||||||
#include "reference.h"
|
#include "reference.h"
|
||||||
|
@ -162,6 +163,7 @@ static const char permissions[] = {
|
||||||
PERMIT_AUTH, /* RESELECT */
|
PERMIT_AUTH, /* RESELECT */
|
||||||
PERMIT_AUTH, /* RESELECTDISTANCE */
|
PERMIT_AUTH, /* RESELECTDISTANCE */
|
||||||
PERMIT_AUTH, /* MODIFY_MAKESTEP */
|
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
|
static void
|
||||||
handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
|
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);
|
handle_tracking(&rx_message, &tx_message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case REQ_SMOOTHING:
|
||||||
|
handle_smoothing(&rx_message, &tx_message);
|
||||||
|
break;
|
||||||
|
|
||||||
case REQ_SOURCESTATS:
|
case REQ_SOURCESTATS:
|
||||||
handle_sourcestats(&rx_message, &tx_message);
|
handle_sourcestats(&rx_message, &tx_message);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -146,6 +146,8 @@ command_unpadded_length(CMD_Request *r)
|
||||||
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
return offsetof(CMD_Request, data.modify_minstratum.EOR);
|
||||||
case REQ_MODIFY_POLLTARGET:
|
case REQ_MODIFY_POLLTARGET:
|
||||||
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
return offsetof(CMD_Request, data.modify_polltarget.EOR);
|
||||||
|
case REQ_SMOOTHING:
|
||||||
|
return offsetof(CMD_Request, data.null.EOR);
|
||||||
default:
|
default:
|
||||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -296,6 +298,8 @@ PKL_CommandPaddingLength(CMD_Request *r)
|
||||||
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.modify_minstratum.EOR, data.null.EOR);
|
||||||
case REQ_MODIFY_POLLTARGET:
|
case REQ_MODIFY_POLLTARGET:
|
||||||
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
return PADDING_LENGTH(data.modify_polltarget.EOR, data.null.EOR);
|
||||||
|
case REQ_SMOOTHING:
|
||||||
|
return PADDING_LENGTH(data.null.EOR, data.smoothing.EOR);
|
||||||
default:
|
default:
|
||||||
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
/* If we fall through the switch, it most likely means we've forgotten to implement a new case */
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -359,7 +363,8 @@ PKL_ReplyLength(CMD_Reply *r)
|
||||||
}
|
}
|
||||||
case RPY_ACTIVITY:
|
case RPY_ACTIVITY:
|
||||||
return offsetof(CMD_Reply, data.activity.EOR);
|
return offsetof(CMD_Reply, data.activity.EOR);
|
||||||
|
case RPY_SMOOTHING:
|
||||||
|
return offsetof(CMD_Reply, data.smoothing.EOR);
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
10
reports.h
10
reports.h
|
@ -112,4 +112,14 @@ typedef struct {
|
||||||
int unresolved;
|
int unresolved;
|
||||||
} RPT_ActivityReport;
|
} 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 */
|
#endif /* GOT_REPORTS_H */
|
||||||
|
|
63
smooth.c
63
smooth.c
|
@ -97,15 +97,17 @@ static struct timeval last_update;
|
||||||
|
|
||||||
|
|
||||||
static void
|
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;
|
int i;
|
||||||
|
|
||||||
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
UTI_DiffTimevalsToDouble(&elapsed, now, &last_update);
|
||||||
|
|
||||||
*offset = smooth_offset;
|
offset = smooth_offset;
|
||||||
*freq = smooth_freq;
|
freq = smooth_freq;
|
||||||
|
wander = 0.0;
|
||||||
|
|
||||||
for (i = 0; i < NUM_STAGES; i++) {
|
for (i = 0; i < NUM_STAGES; i++) {
|
||||||
if (elapsed <= 0.0)
|
if (elapsed <= 0.0)
|
||||||
|
@ -115,13 +117,21 @@ get_offset_freq(struct timeval *now, double *offset, double *freq)
|
||||||
if (length >= elapsed)
|
if (length >= elapsed)
|
||||||
length = elapsed;
|
length = elapsed;
|
||||||
|
|
||||||
*offset -= length * (2.0 * *freq + stages[i].wander * length) / 2.0;
|
wander = stages[i].wander;
|
||||||
*freq += stages[i].wander * length;
|
offset -= length * (2.0 * freq + wander * length) / 2.0;
|
||||||
|
freq += wander * length;
|
||||||
elapsed -= length;
|
elapsed -= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elapsed > 0.0)
|
if (elapsed > 0.0) {
|
||||||
*offset -= elapsed * *freq;
|
wander = 0.0;
|
||||||
|
offset -= elapsed * freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
*poffset = offset;
|
||||||
|
*pfreq = freq;
|
||||||
|
if (pwander)
|
||||||
|
*pwander = wander;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 ?
|
LOG(LOGS_INFO, LOGF_Smooth, "Time smoothing activated%s", leap_only_mode ?
|
||||||
" (leap seconds only)" : "");
|
" (leap seconds only)" : "");
|
||||||
locked = 0;
|
locked = 0;
|
||||||
|
last_update = *now;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_offset_freq(now, &smooth_offset, &smooth_freq);
|
get_smoothing(now, &smooth_offset, &smooth_freq, NULL);
|
||||||
smooth_offset += offset;
|
smooth_offset += offset;
|
||||||
smooth_freq = (smooth_freq - freq) / (1.0 - freq);
|
smooth_freq = (smooth_freq - freq) / (1.0 - freq);
|
||||||
last_update = *now;
|
last_update = *now;
|
||||||
|
@ -258,7 +269,7 @@ SMT_GetOffset(struct timeval *now)
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
get_offset_freq(now, &offset, &freq);
|
get_smoothing(now, &offset, &freq, NULL);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
@ -289,3 +300,35 @@ SMT_Leap(struct timeval *now, int leap)
|
||||||
|
|
||||||
update_smoothing(now, leap, 0.0);
|
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
|
#ifndef GOT_SMOOTH_H
|
||||||
#define GOT_SMOOTH_H
|
#define GOT_SMOOTH_H
|
||||||
|
|
||||||
|
#include "reports.h"
|
||||||
|
|
||||||
extern void SMT_Initialise(void);
|
extern void SMT_Initialise(void);
|
||||||
|
|
||||||
extern void SMT_Finalise(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 void SMT_Leap(struct timeval *now, int leap);
|
||||||
|
|
||||||
|
extern int SMT_GetSmoothingReport(RPT_SmoothingReport *report, struct timeval *now);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue