reference: add "local activate" option
This option sets an activating root distance for the local reference. The local reference will not be used until the root distance drops below the configured value for the first time. This can be used to prevent the local reference from being activated on a server which has never been synchronised with an upstream server. The default value of 0.0 causes no activating distance to be used, such that the local reference is always eligible for activation.
This commit is contained in:
parent
b8ead3485b
commit
9397ae2b0a
11 changed files with 50 additions and 20 deletions
4
candm.h
4
candm.h
|
@ -111,7 +111,8 @@
|
|||
#define REQ_DOFFSET2 71
|
||||
#define REQ_MODIFY_SELECTOPTS 72
|
||||
#define REQ_MODIFY_OFFSET 73
|
||||
#define N_REQUEST_TYPES 74
|
||||
#define REQ_LOCAL3 74
|
||||
#define N_REQUEST_TYPES 75
|
||||
|
||||
/* Structure used to exchange timespecs independent of time_t size */
|
||||
typedef struct {
|
||||
|
@ -237,6 +238,7 @@ typedef struct {
|
|||
int32_t stratum;
|
||||
Float distance;
|
||||
int32_t orphan;
|
||||
Float activate;
|
||||
int32_t EOR;
|
||||
} REQ_Local;
|
||||
|
||||
|
|
7
client.c
7
client.c
|
@ -755,22 +755,23 @@ static int
|
|||
process_cmd_local(CMD_Request *msg, char *line)
|
||||
{
|
||||
int on_off, stratum = 0, orphan = 0;
|
||||
double distance = 0.0;
|
||||
double distance = 0.0, activate = 0.0;
|
||||
|
||||
if (!strcmp(line, "off")) {
|
||||
on_off = 0;
|
||||
} else if (CPS_ParseLocal(line, &stratum, &orphan, &distance)) {
|
||||
} else if (CPS_ParseLocal(line, &stratum, &orphan, &distance, &activate)) {
|
||||
on_off = 1;
|
||||
} else {
|
||||
LOG(LOGS_ERR, "Invalid syntax for local command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg->command = htons(REQ_LOCAL2);
|
||||
msg->command = htons(REQ_LOCAL3);
|
||||
msg->data.local.on_off = htonl(on_off);
|
||||
msg->data.local.stratum = htonl(stratum);
|
||||
msg->data.local.distance = UTI_FloatHostToNetwork(distance);
|
||||
msg->data.local.orphan = htonl(orphan);
|
||||
msg->data.local.activate = UTI_FloatHostToNetwork(activate);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
8
cmdmon.c
8
cmdmon.c
|
@ -146,6 +146,7 @@ static const char permissions[] = {
|
|||
PERMIT_AUTH, /* DOFFSET2 */
|
||||
PERMIT_AUTH, /* MODIFY_SELECTOPTS */
|
||||
PERMIT_AUTH, /* MODIFY_OFFSET */
|
||||
PERMIT_AUTH, /* LOCAL3 */
|
||||
};
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -531,7 +532,8 @@ handle_local(CMD_Request *rx_message, CMD_Reply *tx_message)
|
|||
if (ntohl(rx_message->data.local.on_off)) {
|
||||
REF_EnableLocal(ntohl(rx_message->data.local.stratum),
|
||||
UTI_FloatNetworkToHost(rx_message->data.local.distance),
|
||||
ntohl(rx_message->data.local.orphan));
|
||||
ntohl(rx_message->data.local.orphan),
|
||||
UTI_FloatNetworkToHost(rx_message->data.local.activate));
|
||||
} else {
|
||||
REF_DisableLocal();
|
||||
}
|
||||
|
@ -1649,8 +1651,8 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
|
|||
case REQ_SETTIME:
|
||||
handle_settime(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
case REQ_LOCAL2:
|
||||
|
||||
case REQ_LOCAL3:
|
||||
handle_local(&rx_message, &tx_message);
|
||||
break;
|
||||
|
||||
|
|
|
@ -296,13 +296,14 @@ CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits)
|
|||
/* ================================================== */
|
||||
|
||||
int
|
||||
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
||||
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance, double *activate)
|
||||
{
|
||||
int n;
|
||||
char *cmd;
|
||||
|
||||
*stratum = 10;
|
||||
*distance = 1.0;
|
||||
*activate = 0.0;
|
||||
*orphan = 0;
|
||||
|
||||
while (*line) {
|
||||
|
@ -319,6 +320,9 @@ CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
|||
} else if (!strcasecmp(cmd, "distance")) {
|
||||
if (sscanf(line, "%lf%n", distance, &n) != 1)
|
||||
return 0;
|
||||
} else if (!strcasecmp(cmd, "activate")) {
|
||||
if (sscanf(line, "%lf%n", activate, &n) != 1)
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ extern int CPS_GetSelectOption(char *option);
|
|||
extern int CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits);
|
||||
|
||||
/* Parse a command to enable local reference */
|
||||
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance);
|
||||
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance, double *activate);
|
||||
|
||||
/* Remove extra white-space and comments */
|
||||
extern void CPS_NormalizeLine(char *line);
|
||||
|
|
6
conf.c
6
conf.c
|
@ -129,6 +129,7 @@ static int enable_local=0;
|
|||
static int local_stratum;
|
||||
static int local_orphan;
|
||||
static double local_distance;
|
||||
static double local_activate;
|
||||
|
||||
/* Threshold (in seconds) - if absolute value of initial error is less
|
||||
than this, slew instead of stepping */
|
||||
|
@ -1069,7 +1070,7 @@ parse_log(char *line)
|
|||
static void
|
||||
parse_local(char *line)
|
||||
{
|
||||
if (!CPS_ParseLocal(line, &local_stratum, &local_orphan, &local_distance))
|
||||
if (!CPS_ParseLocal(line, &local_stratum, &local_orphan, &local_distance, &local_activate))
|
||||
command_parse_error();
|
||||
enable_local = 1;
|
||||
}
|
||||
|
@ -2169,12 +2170,13 @@ CNF_GetCommandPort(void) {
|
|||
/* ================================================== */
|
||||
|
||||
int
|
||||
CNF_AllowLocalReference(int *stratum, int *orphan, double *distance)
|
||||
CNF_AllowLocalReference(int *stratum, int *orphan, double *distance, double *activate)
|
||||
{
|
||||
if (enable_local) {
|
||||
*stratum = local_stratum;
|
||||
*orphan = local_orphan;
|
||||
*distance = local_distance;
|
||||
*activate = local_activate;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
2
conf.h
2
conf.h
|
@ -108,7 +108,7 @@ extern double CNF_GetReselectDistance(void);
|
|||
extern double CNF_GetStratumWeight(void);
|
||||
extern double CNF_GetCombineLimit(void);
|
||||
|
||||
extern int CNF_AllowLocalReference(int *stratum, int *orphan, double *distance);
|
||||
extern int CNF_AllowLocalReference(int *stratum, int *orphan, double *distance, double *activate);
|
||||
|
||||
extern void CNF_SetupAccessRestrictions(void);
|
||||
|
||||
|
|
|
@ -1675,6 +1675,14 @@ The current root distance can be calculated from root delay and root dispersion
|
|||
----
|
||||
distance = delay / 2 + dispersion
|
||||
----
|
||||
*activate* _distance_:::
|
||||
This option sets an activating root distance for the local reference. The
|
||||
local reference will not be used until the root distance drops below the
|
||||
configured value for the first time. This can be used to prevent the local
|
||||
reference from being activated on a server which has never been synchronised
|
||||
with an upstream server. The default value of 0.0 causes no activating
|
||||
distance to be used, such that the local reference is always eligible for
|
||||
activation.
|
||||
*orphan*:::
|
||||
This option enables a special '`orphan`' mode, where sources with stratum equal
|
||||
to the local _stratum_ are assumed to not serve real time. They are ignored
|
||||
|
@ -1697,7 +1705,7 @@ The *orphan* mode is compatible with the *ntpd*'s orphan mode (enabled by the
|
|||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
local stratum 10 orphan distance 0.1
|
||||
local stratum 10 orphan distance 0.1 activate 0.5
|
||||
----
|
||||
|
||||
[[ntpsigndsocket]]*ntpsigndsocket* _directory_::
|
||||
|
|
|
@ -111,7 +111,7 @@ static const struct request_length request_lengths[] = {
|
|||
REQ_LENGTH_ENTRY(null, null), /* REFRESH */
|
||||
REQ_LENGTH_ENTRY(null, server_stats), /* SERVER_STATS */
|
||||
{ 0, 0 }, /* CLIENT_ACCESSES_BY_INDEX2 - not supported */
|
||||
REQ_LENGTH_ENTRY(local, null), /* LOCAL2 */
|
||||
{ 0, 0 }, /* LOCAL2 - not supported */
|
||||
REQ_LENGTH_ENTRY(ntp_data, ntp_data), /* NTP_DATA */
|
||||
{ 0, 0 }, /* ADD_SERVER2 */
|
||||
{ 0, 0 }, /* ADD_PEER2 */
|
||||
|
@ -131,6 +131,7 @@ static const struct request_length request_lengths[] = {
|
|||
REQ_LENGTH_ENTRY(doffset, null), /* DOFFSET2 */
|
||||
REQ_LENGTH_ENTRY(modify_select_opts, null), /* MODIFY_SELECTOPTS */
|
||||
REQ_LENGTH_ENTRY(modify_offset, null), /* MODIFY_OFFSET */
|
||||
REQ_LENGTH_ENTRY(local, null), /* LOCAL3 */
|
||||
};
|
||||
|
||||
static const uint16_t reply_lengths[] = {
|
||||
|
|
20
reference.c
20
reference.c
|
@ -54,6 +54,8 @@ static int enable_local_stratum;
|
|||
static int local_stratum;
|
||||
static int local_orphan;
|
||||
static double local_distance;
|
||||
static int local_activate_ok;
|
||||
static double local_activate;
|
||||
static struct timespec local_ref_time;
|
||||
static NTP_Leap our_leap_status;
|
||||
static int our_leap_sec;
|
||||
|
@ -207,6 +209,7 @@ REF_Initialise(void)
|
|||
our_frequency_sd = 0.0;
|
||||
our_offset_sd = 0.0;
|
||||
drift_file_age = 0.0;
|
||||
local_activate_ok = 0;
|
||||
|
||||
/* Now see if we can get the drift file opened */
|
||||
drift_file = CNF_GetDriftFile();
|
||||
|
@ -245,7 +248,8 @@ REF_Initialise(void)
|
|||
|
||||
correction_time_ratio = CNF_GetCorrectionTimeRatio();
|
||||
|
||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan, &local_distance);
|
||||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan,
|
||||
&local_distance, &local_activate);
|
||||
UTI_ZeroTimespec(&local_ref_time);
|
||||
|
||||
leap_when = 0;
|
||||
|
@ -1132,7 +1136,7 @@ REF_GetReferenceParams
|
|||
double *root_dispersion
|
||||
)
|
||||
{
|
||||
double dispersion, delta;
|
||||
double dispersion, delta, distance;
|
||||
|
||||
assert(initialised);
|
||||
|
||||
|
@ -1142,11 +1146,16 @@ REF_GetReferenceParams
|
|||
dispersion = 0.0;
|
||||
}
|
||||
|
||||
distance = our_root_delay / 2 + dispersion;
|
||||
|
||||
if (local_activate == 0.0 || (are_we_synchronised && distance < local_activate))
|
||||
local_activate_ok = 1;
|
||||
|
||||
/* Local reference is active when enabled and the clock is not synchronised
|
||||
or the root distance exceeds the threshold */
|
||||
|
||||
if (are_we_synchronised &&
|
||||
!(enable_local_stratum && our_root_delay / 2 + dispersion > local_distance)) {
|
||||
!(enable_local_stratum && local_activate_ok && distance > local_distance)) {
|
||||
|
||||
*is_synchronised = 1;
|
||||
|
||||
|
@ -1158,7 +1167,7 @@ REF_GetReferenceParams
|
|||
*root_delay = our_root_delay;
|
||||
*root_dispersion = dispersion;
|
||||
|
||||
} else if (enable_local_stratum) {
|
||||
} else if (enable_local_stratum && local_activate_ok) {
|
||||
|
||||
*is_synchronised = 0;
|
||||
|
||||
|
@ -1258,12 +1267,13 @@ REF_ModifyMakestep(int limit, double threshold)
|
|||
/* ================================================== */
|
||||
|
||||
void
|
||||
REF_EnableLocal(int stratum, double distance, int orphan)
|
||||
REF_EnableLocal(int stratum, double distance, int orphan, double activate)
|
||||
{
|
||||
enable_local_stratum = 1;
|
||||
local_stratum = CLAMP(1, stratum, NTP_MAX_STRATUM - 1);
|
||||
local_distance = distance;
|
||||
local_orphan = !!orphan;
|
||||
local_activate = activate;
|
||||
LOG(LOGS_INFO, "%s local reference mode", "Enabled");
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ extern void REF_ModifyMaxupdateskew(double new_max_update_skew);
|
|||
/* Modify makestep settings */
|
||||
extern void REF_ModifyMakestep(int limit, double threshold);
|
||||
|
||||
extern void REF_EnableLocal(int stratum, double distance, int orphan);
|
||||
extern void REF_EnableLocal(int stratum, double distance, int orphan, double activate);
|
||||
extern void REF_DisableLocal(void);
|
||||
|
||||
/* Check if either of the current raw and cooked time, and optionally a
|
||||
|
|
Loading…
Reference in a new issue