Add support for reference clocks
This commit is contained in:
parent
ef3669fe1b
commit
ac30bb06ef
14 changed files with 453 additions and 16 deletions
|
@ -41,7 +41,7 @@ OBJS = util.o sched.o regress.o local.o \
|
||||||
logging.o conf.o cmdmon.o md5.o keys.o \
|
logging.o conf.o cmdmon.o md5.o keys.o \
|
||||||
nameserv.o acquire.o manual.o addrfilt.o \
|
nameserv.o acquire.o manual.o addrfilt.o \
|
||||||
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
|
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
|
||||||
broadcast.o
|
broadcast.o refclock.o
|
||||||
|
|
||||||
EXTRA_OBJS=@EXTRA_OBJECTS@
|
EXTRA_OBJS=@EXTRA_OBJECTS@
|
||||||
|
|
||||||
|
|
17
client.c
17
client.c
|
@ -92,6 +92,19 @@ time_to_log_form(time_t t)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
UTI_RefidToString(unsigned long ref_id)
|
||||||
|
{
|
||||||
|
unsigned int a, b, c, d;
|
||||||
|
static char result[64];
|
||||||
|
a = (ref_id>>24) & 0xff;
|
||||||
|
b = (ref_id>>16) & 0xff;
|
||||||
|
c = (ref_id>> 8) & 0xff;
|
||||||
|
d = (ref_id>> 0) & 0xff;
|
||||||
|
snprintf(result, sizeof(result), "%c%c%c%c", a, b, c, d);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
UTI_IPToDottedQuad(unsigned long ip)
|
UTI_IPToDottedQuad(unsigned long ip)
|
||||||
{
|
{
|
||||||
|
@ -1462,7 +1475,9 @@ process_cmd_sources(char *line)
|
||||||
resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
|
resid_skew = (double) (ntohl(reply.data.source_data.resid_skew)) * 1.0e-3;
|
||||||
|
|
||||||
hostname_buf[25] = 0;
|
hostname_buf[25] = 0;
|
||||||
if (no_dns) {
|
if (mode == RPY_SD_MD_REF) {
|
||||||
|
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ip_addr));
|
||||||
|
} else if (no_dns) {
|
||||||
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
|
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_IPToDottedQuad(ip_addr));
|
||||||
} else {
|
} else {
|
||||||
dns_lookup = DNS_IPAddress2Name(ip_addr);
|
dns_lookup = DNS_IPAddress2Name(ip_addr);
|
||||||
|
|
10
cmdmon.c
10
cmdmon.c
|
@ -50,6 +50,7 @@
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "pktlength.h"
|
#include "pktlength.h"
|
||||||
#include "clientlog.h"
|
#include "clientlog.h"
|
||||||
|
#include "refclock.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
@ -871,7 +872,14 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
|
||||||
/* Get data */
|
/* Get data */
|
||||||
LCL_ReadCookedTime(&now_corr, &local_clock_err);
|
LCL_ReadCookedTime(&now_corr, &local_clock_err);
|
||||||
if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
|
if (SRC_ReportSource(ntohl(rx_message->data.source_data.index), &report, &now_corr)) {
|
||||||
NSR_ReportSource(&report, &now_corr);
|
switch (SRC_GetType(ntohl(rx_message->data.source_data.index))) {
|
||||||
|
case SRC_NTP:
|
||||||
|
NSR_ReportSource(&report, &now_corr);
|
||||||
|
break;
|
||||||
|
case SRC_REFCLOCK:
|
||||||
|
RCL_ReportSource(&report, &now_corr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
tx_message->status = htons(STT_SUCCESS);
|
tx_message->status = htons(STT_SUCCESS);
|
||||||
tx_message->reply = htons(RPY_SOURCE_DATA);
|
tx_message->reply = htons(RPY_SOURCE_DATA);
|
||||||
|
|
74
conf.c
74
conf.c
|
@ -44,6 +44,7 @@
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "ntp_sources.h"
|
#include "ntp_sources.h"
|
||||||
#include "ntp_core.h"
|
#include "ntp_core.h"
|
||||||
|
#include "refclock.h"
|
||||||
#include "cmdmon.h"
|
#include "cmdmon.h"
|
||||||
#include "srcparams.h"
|
#include "srcparams.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
@ -73,6 +74,7 @@ static void parse_peer(const char *);
|
||||||
static void parse_acquisitionport(const char *);
|
static void parse_acquisitionport(const char *);
|
||||||
static void parse_port(const char *);
|
static void parse_port(const char *);
|
||||||
static void parse_server(const char *);
|
static void parse_server(const char *);
|
||||||
|
static void parse_refclock(const char *);
|
||||||
static void parse_local(const char *);
|
static void parse_local(const char *);
|
||||||
static void parse_manual(const char *);
|
static void parse_manual(const char *);
|
||||||
static void parse_initstepslew(const char *);
|
static void parse_initstepslew(const char *);
|
||||||
|
@ -187,6 +189,7 @@ typedef struct {
|
||||||
static const Command commands[] = {
|
static const Command commands[] = {
|
||||||
{"server", 6, parse_server},
|
{"server", 6, parse_server},
|
||||||
{"peer", 4, parse_peer},
|
{"peer", 4, parse_peer},
|
||||||
|
{"refclock", 8, parse_refclock},
|
||||||
{"acquisitionport", 15, parse_acquisitionport},
|
{"acquisitionport", 15, parse_acquisitionport},
|
||||||
{"port", 4, parse_port},
|
{"port", 4, parse_port},
|
||||||
{"driftfile", 9, parse_driftfile},
|
{"driftfile", 9, parse_driftfile},
|
||||||
|
@ -250,6 +253,11 @@ typedef struct {
|
||||||
static NTP_Source ntp_sources[MAX_NTP_SOURCES];
|
static NTP_Source ntp_sources[MAX_NTP_SOURCES];
|
||||||
static int n_ntp_sources = 0;
|
static int n_ntp_sources = 0;
|
||||||
|
|
||||||
|
#define MAX_RCL_SOURCES 8
|
||||||
|
|
||||||
|
static RefclockParameters refclock_sources[MAX_RCL_SOURCES];
|
||||||
|
static int n_refclock_sources = 0;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
typedef struct _AllowDeny {
|
typedef struct _AllowDeny {
|
||||||
|
@ -417,6 +425,61 @@ parse_peer(const char *line)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_refclock(const char *line)
|
||||||
|
{
|
||||||
|
int i, n, param, poll;
|
||||||
|
unsigned long ref_id;
|
||||||
|
double offset;
|
||||||
|
char name[5], cmd[10 + 1];
|
||||||
|
unsigned char ref[5];
|
||||||
|
|
||||||
|
i = n_refclock_sources;
|
||||||
|
if (i >= MAX_RCL_SOURCES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
poll = 4;
|
||||||
|
offset = 0.0;
|
||||||
|
ref_id = 0;
|
||||||
|
|
||||||
|
if (sscanf(line, "%4s %d%n", name, ¶m, &n) != 2) {
|
||||||
|
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name and parameter at line %d", line_number);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += n;
|
||||||
|
|
||||||
|
while (sscanf(line, "%10s%n", cmd, &n) == 1) {
|
||||||
|
line += n;
|
||||||
|
if (!strncasecmp(cmd, "refid", 5)) {
|
||||||
|
if (sscanf(line, "%4s%n", (char *)ref, &n) != 1)
|
||||||
|
break;
|
||||||
|
ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
|
||||||
|
} else if (!strncasecmp(cmd, "poll", 4)) {
|
||||||
|
if (sscanf(line, "%d%n", &poll, &n) != 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!strncasecmp(cmd, "offset", 6)) {
|
||||||
|
if (sscanf(line, "%lf%n", &offset, &n) != 1)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
LOG(LOGS_WARN, LOGF_Configure, "Unknown refclock parameter %s at line %d", cmd, line_number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(refclock_sources[i].driver_name, name, 4);
|
||||||
|
refclock_sources[i].driver_parameter = param;
|
||||||
|
refclock_sources[i].poll = poll;
|
||||||
|
refclock_sources[i].offset = offset;
|
||||||
|
refclock_sources[i].ref_id = ref_id;
|
||||||
|
|
||||||
|
n_refclock_sources++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_some_port(const char *line, int *portvar)
|
parse_some_port(const char *line, int *portvar)
|
||||||
{
|
{
|
||||||
|
@ -1004,6 +1067,17 @@ CNF_AddSources(void) {
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
CNF_AddRefclocks(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<n_refclock_sources; i++) {
|
||||||
|
RCL_AddRefclock(&refclock_sources[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
CNF_AddBroadcasts(void)
|
CNF_AddBroadcasts(void)
|
||||||
{
|
{
|
||||||
|
|
1
conf.h
1
conf.h
|
@ -37,6 +37,7 @@ extern void CNF_ReadFile(const char *filename);
|
||||||
|
|
||||||
extern void CNF_AddSources(void);
|
extern void CNF_AddSources(void);
|
||||||
extern void CNF_AddBroadcasts(void);
|
extern void CNF_AddBroadcasts(void);
|
||||||
|
extern void CNF_AddRefclocks(void);
|
||||||
|
|
||||||
extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
|
extern void CNF_ProcessInitStepSlew(void (*after_hook)(void *), void *anything);
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ typedef enum {
|
||||||
LOGF_SysSolaris,
|
LOGF_SysSolaris,
|
||||||
LOGF_SysSunOS,
|
LOGF_SysSunOS,
|
||||||
LOGF_SysWinnt,
|
LOGF_SysWinnt,
|
||||||
LOGF_RtcLinux
|
LOGF_RtcLinux,
|
||||||
|
LOGF_Refclock
|
||||||
} LOG_Facility;
|
} LOG_Facility;
|
||||||
|
|
||||||
/* Init function */
|
/* Init function */
|
||||||
|
|
4
main.c
4
main.c
|
@ -58,6 +58,7 @@
|
||||||
#include "manual.h"
|
#include "manual.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
#include "refclock.h"
|
||||||
#include "clientlog.h"
|
#include "clientlog.h"
|
||||||
#include "broadcast.h"
|
#include "broadcast.h"
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ MAI_CleanupAndExit(void)
|
||||||
SRC_Finalise();
|
SRC_Finalise();
|
||||||
SST_Finalise();
|
SST_Finalise();
|
||||||
REF_Finalise();
|
REF_Finalise();
|
||||||
|
RCL_Finalise();
|
||||||
RTC_Finalise();
|
RTC_Finalise();
|
||||||
CAM_Finalise();
|
CAM_Finalise();
|
||||||
NIO_Finalise();
|
NIO_Finalise();
|
||||||
|
@ -145,6 +147,7 @@ post_acquire_hook(void *anything)
|
||||||
CNF_SetupAccessRestrictions();
|
CNF_SetupAccessRestrictions();
|
||||||
|
|
||||||
RTC_StartMeasurements();
|
RTC_StartMeasurements();
|
||||||
|
RCL_StartRefclocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
@ -309,6 +312,7 @@ int main
|
||||||
NIO_Initialise();
|
NIO_Initialise();
|
||||||
CAM_Initialise();
|
CAM_Initialise();
|
||||||
RTC_Initialise();
|
RTC_Initialise();
|
||||||
|
RCL_Initialise();
|
||||||
|
|
||||||
if (SchedPriority > 0) {
|
if (SchedPriority > 0) {
|
||||||
SYS_SetScheduler(SchedPriority);
|
SYS_SetScheduler(SchedPriority);
|
||||||
|
|
|
@ -319,7 +319,7 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
|
||||||
result->local_poll = params->minpoll;
|
result->local_poll = params->minpoll;
|
||||||
|
|
||||||
/* Create a source instance for this NTP source */
|
/* Create a source instance for this NTP source */
|
||||||
result->source = SRC_CreateNewInstance(remote_addr->ip_addr); /* Will need extra params eventually */
|
result->source = SRC_CreateNewInstance(remote_addr->ip_addr, SRC_NTP);
|
||||||
|
|
||||||
result->local_rx.tv_sec = 0;
|
result->local_rx.tv_sec = 0;
|
||||||
result->local_rx.tv_usec = 0;
|
result->local_rx.tv_usec = 0;
|
||||||
|
|
213
refclock.c
Normal file
213
refclock.c
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Richard P. Curnow 2009
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Routines implementing reference clocks.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "refclock.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "local.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "sources.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "sched.h"
|
||||||
|
|
||||||
|
struct RCL_Instance_Record {
|
||||||
|
RefclockDriver *driver;
|
||||||
|
void *data;
|
||||||
|
int driver_parameter;
|
||||||
|
int poll;
|
||||||
|
int missed_samples;
|
||||||
|
unsigned long ref_id;
|
||||||
|
double offset;
|
||||||
|
SCH_TimeoutID timeout_id;
|
||||||
|
SRC_Instance source;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_RCL_SOURCES 8
|
||||||
|
|
||||||
|
static struct RCL_Instance_Record refclocks[MAX_RCL_SOURCES];
|
||||||
|
static int n_sources = 0;
|
||||||
|
|
||||||
|
static void poll_timeout(void *arg);
|
||||||
|
|
||||||
|
void
|
||||||
|
RCL_Initialise(void)
|
||||||
|
{
|
||||||
|
CNF_AddRefclocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RCL_Finalise(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_sources; i++) {
|
||||||
|
RCL_Instance inst = (RCL_Instance)&refclocks[i];
|
||||||
|
|
||||||
|
if (inst->driver->fini)
|
||||||
|
inst->driver->fini(inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RCL_AddRefclock(RefclockParameters *params)
|
||||||
|
{
|
||||||
|
RCL_Instance inst = &refclocks[n_sources];
|
||||||
|
|
||||||
|
if (n_sources == MAX_RCL_SOURCES)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
} else {
|
||||||
|
LOG_FATAL(LOGF_Refclock, "unknown refclock driver %s", params->driver_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inst->data = NULL;
|
||||||
|
inst->driver_parameter = params->driver_parameter;
|
||||||
|
inst->poll = params->poll;
|
||||||
|
inst->missed_samples = 0;
|
||||||
|
inst->offset = params->offset;
|
||||||
|
inst->timeout_id = -1;
|
||||||
|
inst->source = NULL;
|
||||||
|
|
||||||
|
if (params->ref_id)
|
||||||
|
inst->ref_id = params->ref_id;
|
||||||
|
else {
|
||||||
|
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
snprintf((char *)ref, 5, "%s%d", params->driver_name, params->driver_parameter);
|
||||||
|
inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->driver->init)
|
||||||
|
if (!inst->driver->init(inst)) {
|
||||||
|
LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LOG(LOGS_INFO, LOGF_Refclock, "refclock added");
|
||||||
|
#endif
|
||||||
|
n_sources++;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RCL_StartRefclocks(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_sources; i++) {
|
||||||
|
RCL_Instance inst = &refclocks[i];
|
||||||
|
|
||||||
|
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK);
|
||||||
|
if (inst->driver->poll)
|
||||||
|
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned long ref_id;
|
||||||
|
|
||||||
|
ref_id = report->ip_addr;
|
||||||
|
|
||||||
|
for (i = 0; i < n_sources; i++) {
|
||||||
|
RCL_Instance inst = &refclocks[i];
|
||||||
|
if (inst->ref_id == ref_id) {
|
||||||
|
report->poll = inst->poll;
|
||||||
|
report->mode = RPT_LOCAL_REFERENCE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RCL_SetDriverData(RCL_Instance instance, void *data)
|
||||||
|
{
|
||||||
|
instance->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
RCL_GetDriverData(RCL_Instance instance)
|
||||||
|
{
|
||||||
|
return instance->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RCL_GetDriverParameter(RCL_Instance instance)
|
||||||
|
{
|
||||||
|
return instance->driver_parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status)
|
||||||
|
{
|
||||||
|
double correction;
|
||||||
|
struct timeval cooked_time;
|
||||||
|
SRC_Instance inst = instance->source;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LOG(LOGS_INFO, LOGF_Refclock, "refclock offset: %f", offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SRC_SetReachable(inst);
|
||||||
|
|
||||||
|
correction = LCL_GetOffsetCorrection(sample_time);
|
||||||
|
UTI_AddDoubleToTimeval(sample_time, correction, &cooked_time);
|
||||||
|
|
||||||
|
SRC_AccumulateSample(inst, &cooked_time, offset - correction + instance->offset,
|
||||||
|
1e-6, 0.0, 0.0, 0.0, 0, leap_status);
|
||||||
|
|
||||||
|
instance->missed_samples = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
poll_timeout(void *arg)
|
||||||
|
{
|
||||||
|
double next;
|
||||||
|
|
||||||
|
RCL_Instance inst = (RCL_Instance)arg;
|
||||||
|
|
||||||
|
inst->missed_samples++;
|
||||||
|
inst->driver->poll(inst);
|
||||||
|
|
||||||
|
if (inst->missed_samples > 9)
|
||||||
|
SRC_UnsetReachable(inst->source);
|
||||||
|
|
||||||
|
if (inst->poll >= 0)
|
||||||
|
next = 1 << inst->poll;
|
||||||
|
else
|
||||||
|
next = 1.0 / (1 << -inst->poll);
|
||||||
|
|
||||||
|
inst->timeout_id = SCH_AddTimeoutByDelay(next, poll_timeout, arg);
|
||||||
|
}
|
||||||
|
|
63
refclock.h
Normal file
63
refclock.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||||
|
|
||||||
|
**********************************************************************
|
||||||
|
* Copyright (C) Richard P. Curnow 2009
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Header file for refclocks.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GOT_REFCLOCK_H
|
||||||
|
#define GOT_REFCLOCK_H
|
||||||
|
|
||||||
|
#include "srcparams.h"
|
||||||
|
#include "sources.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char driver_name[4];
|
||||||
|
int driver_parameter;
|
||||||
|
int poll;
|
||||||
|
unsigned long ref_id;
|
||||||
|
double offset;
|
||||||
|
} RefclockParameters;
|
||||||
|
|
||||||
|
typedef struct RCL_Instance_Record *RCL_Instance;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int (*init)(RCL_Instance instance);
|
||||||
|
void (*fini)(RCL_Instance instance);
|
||||||
|
int (*poll)(RCL_Instance instance);
|
||||||
|
} RefclockDriver;
|
||||||
|
|
||||||
|
extern void RCL_Initialise(void);
|
||||||
|
extern void RCL_Finalise(void);
|
||||||
|
extern int RCL_AddRefclock(RefclockParameters *params);
|
||||||
|
extern void RCL_StartRefclocks(void);
|
||||||
|
extern void RCL_StartRefclocks(void);
|
||||||
|
extern void RCL_ReportSource(RPT_SourceReport *report, struct timeval *now);
|
||||||
|
|
||||||
|
/* functions used by drivers */
|
||||||
|
extern void RCL_SetDriverData(RCL_Instance instance, void *data);
|
||||||
|
extern void *RCL_GetDriverData(RCL_Instance instance);
|
||||||
|
extern int RCL_GetDriverParameter(RCL_Instance instance);
|
||||||
|
extern int RCL_AddSample(RCL_Instance instance, struct timeval *sample_time, double offset, NTP_Leap leap_status);
|
||||||
|
|
||||||
|
#endif
|
52
sources.c
52
sources.c
|
@ -96,6 +96,9 @@ struct SRC_Instance_Record {
|
||||||
/* Flag indicating the status of the source */
|
/* Flag indicating the status of the source */
|
||||||
SRC_Status status;
|
SRC_Status status;
|
||||||
|
|
||||||
|
/* Type of the source */
|
||||||
|
SRC_Type type;
|
||||||
|
|
||||||
struct SelectInfo sel_info;
|
struct SelectInfo sel_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,6 +129,8 @@ static int selected_source_index; /* Which source index is currently
|
||||||
static void
|
static void
|
||||||
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
|
slew_sources(struct timeval *raw, struct timeval *cooked, double dfreq, double afreq,
|
||||||
double doffset, int is_step_change, void *anything);
|
double doffset, int is_step_change, void *anything);
|
||||||
|
static char *
|
||||||
|
source_to_string(SRC_Instance inst);
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Initialisation function */
|
/* Initialisation function */
|
||||||
|
@ -155,7 +160,7 @@ void SRC_Finalise(void)
|
||||||
/* Function to create a new instance. This would be called by one of
|
/* Function to create a new instance. This would be called by one of
|
||||||
the individual source-type instance creation routines. */
|
the individual source-type instance creation routines. */
|
||||||
|
|
||||||
SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
|
SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type)
|
||||||
{
|
{
|
||||||
SRC_Instance result;
|
SRC_Instance result;
|
||||||
|
|
||||||
|
@ -186,6 +191,7 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id)
|
||||||
result->ref_id = ref_id;
|
result->ref_id = ref_id;
|
||||||
result->reachable = 0;
|
result->reachable = 0;
|
||||||
result->status = SRC_BAD_STATS;
|
result->status = SRC_BAD_STATS;
|
||||||
|
result->type = type;
|
||||||
|
|
||||||
n_sources++;
|
n_sources++;
|
||||||
|
|
||||||
|
@ -280,7 +286,7 @@ void SRC_AccumulateSample
|
||||||
|
|
||||||
#ifdef TRACEON
|
#ifdef TRACEON
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
|
LOG(LOGS_INFO, LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
|
||||||
UTI_IPToDottedQuad(inst->ref_id), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
|
source_to_string(inst), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
|
/* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
|
||||||
|
@ -301,7 +307,7 @@ SRC_SetReachable(SRC_Instance inst)
|
||||||
inst->reachable = 1;
|
inst->reachable = 1;
|
||||||
|
|
||||||
#ifdef TRACEON
|
#ifdef TRACEON
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "%s", UTI_IPToDottedQuad(inst->ref_id));
|
LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Don't do selection at this point, though - that will come about
|
/* Don't do selection at this point, though - that will come about
|
||||||
|
@ -316,7 +322,7 @@ SRC_UnsetReachable(SRC_Instance inst)
|
||||||
inst->reachable = 0;
|
inst->reachable = 0;
|
||||||
|
|
||||||
#ifdef TRACEON
|
#ifdef TRACEON
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "%s%s", UTI_IPToDottedQuad(inst->ref_id),
|
LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
|
||||||
(inst->index == selected_source_index) ? "(REF)":"");
|
(inst->index == selected_source_index) ? "(REF)":"");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -349,6 +355,22 @@ compare_sort_elements(const void *a, const void *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
source_to_string(SRC_Instance inst)
|
||||||
|
{
|
||||||
|
switch (inst->type) {
|
||||||
|
case SRC_NTP:
|
||||||
|
return UTI_IPToDottedQuad(inst->ref_id);
|
||||||
|
case SRC_REFCLOCK:
|
||||||
|
return UTI_RefidToString(inst->ref_id);
|
||||||
|
default:
|
||||||
|
CROAK("Unknown source type");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* This function selects the current reference from amongst the pool
|
/* This function selects the current reference from amongst the pool
|
||||||
of sources we are holding.
|
of sources we are holding.
|
||||||
|
@ -418,7 +440,7 @@ SRC_SelectSource(unsigned long match_addr)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f",
|
LOG(LOGS_INFO, LOGF_Sources, "%s off=%f dist=%f lo=%f hi=%f",
|
||||||
UTI_IPToDottedQuad(sources[i]->ref_id),
|
source_to_string(sources[i]),
|
||||||
si->best_offset, si->root_distance,
|
si->best_offset, si->root_distance,
|
||||||
si->lo_limit, si->hi_limit);
|
si->lo_limit, si->hi_limit);
|
||||||
#endif
|
#endif
|
||||||
|
@ -491,7 +513,7 @@ SRC_SelectSource(unsigned long match_addr)
|
||||||
for (i=0; i<n_endpoints; i++) {
|
for (i=0; i<n_endpoints; i++) {
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "i=%d t=%f tag=%d addr=%s", i, sort_list[i].offset, sort_list[i].tag,
|
LOG(LOGS_INFO, LOGF_Sources, "i=%d t=%f tag=%d addr=%s", i, sort_list[i].offset, sort_list[i].tag,
|
||||||
UTI_IPToDottedQuad(sources[sort_list[i].index]->ref_id));
|
source_to_string(sources[sort_list[i].index]));
|
||||||
#endif
|
#endif
|
||||||
switch(sort_list[i].tag) {
|
switch(sort_list[i].tag) {
|
||||||
case LOW:
|
case LOW:
|
||||||
|
@ -565,12 +587,12 @@ SRC_SelectSource(unsigned long match_addr)
|
||||||
|
|
||||||
sel_sources[n_sel_sources++] = i;
|
sel_sources[n_sel_sources++] = i;
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, UTI_IPToDottedQuad(sources[i]->ref_id));
|
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is valid", i, source_to_string(sources[i]));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
sources[i]->status = SRC_FALSETICKER;
|
sources[i]->status = SRC_FALSETICKER;
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, UTI_IPToDottedQuad(sources[i]->ref_id));
|
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s is a falseticker", i, source_to_string(sources[i]));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,7 +625,7 @@ SRC_SelectSource(unsigned long match_addr)
|
||||||
sel_sources[i] = INVALID_SOURCE;
|
sel_sources[i] = INVALID_SOURCE;
|
||||||
sources[index]->status = SRC_JITTERY;
|
sources[index]->status = SRC_JITTERY;
|
||||||
#if 0
|
#if 0
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, UTI_IPToDottedQuad(sources[i]->ref_id));
|
LOG(LOGS_INFO, LOGF_Sources, "i=%d addr=%s has too much variance", i, source_to_string(sources[i]));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -658,7 +680,7 @@ SRC_SelectSource(unsigned long match_addr)
|
||||||
|
|
||||||
selected_source_index = min_distance_index;
|
selected_source_index = min_distance_index;
|
||||||
LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
|
LOG(LOGS_INFO, LOGF_Sources, "Selected source %s",
|
||||||
UTI_IPToDottedQuad(sources[selected_source_index]->ref_id));
|
source_to_string(sources[selected_source_index]));
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -935,6 +957,16 @@ SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
SRC_Type
|
||||||
|
SRC_GetType(int index)
|
||||||
|
{
|
||||||
|
if ((index >= n_sources) || (index < 0))
|
||||||
|
return -1;
|
||||||
|
return sources[index]->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
|
SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
|
||||||
{
|
{
|
||||||
SRC_Skew_Direction result = SRC_Skew_Nochange;
|
SRC_Skew_Direction result = SRC_Skew_Nochange;
|
||||||
|
|
|
@ -50,10 +50,15 @@ extern void SRC_Initialise(void);
|
||||||
/* Finalisation function */
|
/* Finalisation function */
|
||||||
extern void SRC_Finalise(void);
|
extern void SRC_Finalise(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SRC_NTP, /* NTP client/peer */
|
||||||
|
SRC_REFCLOCK /* Rerefence clock */
|
||||||
|
} SRC_Type;
|
||||||
|
|
||||||
/* Function to create a new instance. This would be called by one of
|
/* Function to create a new instance. This would be called by one of
|
||||||
the individual source-type instance creation routines. */
|
the individual source-type instance creation routines. */
|
||||||
|
|
||||||
extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id);
|
extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type);
|
||||||
|
|
||||||
/* Function to get rid of a source when it is being unconfigured.
|
/* Function to get rid of a source when it is being unconfigured.
|
||||||
This may cause the current reference source to be reselected, if this
|
This may cause the current reference source to be reselected, if this
|
||||||
|
@ -143,6 +148,8 @@ extern int SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval
|
||||||
|
|
||||||
extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report);
|
extern int SRC_ReportSourcestats(int index, RPT_SourcestatsReport *report);
|
||||||
|
|
||||||
|
extern SRC_Type SRC_GetType(int index);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SRC_Skew_Decrease,
|
SRC_Skew_Decrease,
|
||||||
SRC_Skew_Nochange,
|
SRC_Skew_Nochange,
|
||||||
|
|
16
util.c
16
util.c
|
@ -247,6 +247,22 @@ UTI_TimestampToString(NTP_int64 *ts)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
char *
|
||||||
|
UTI_RefidToString(unsigned long ref_id)
|
||||||
|
{
|
||||||
|
unsigned int a, b, c, d;
|
||||||
|
char *result;
|
||||||
|
a = (ref_id>>24) & 0xff;
|
||||||
|
b = (ref_id>>16) & 0xff;
|
||||||
|
c = (ref_id>> 8) & 0xff;
|
||||||
|
d = (ref_id>> 0) & 0xff;
|
||||||
|
result = NEXT_BUFFER;
|
||||||
|
snprintf(result, BUFFER_LENGTH, "%c%c%c%c", a, b, c, d);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
UTI_IPToDottedQuad(unsigned long ip)
|
UTI_IPToDottedQuad(unsigned long ip)
|
||||||
{
|
{
|
||||||
|
|
3
util.h
3
util.h
|
@ -72,6 +72,9 @@ extern char *UTI_TimevalToString(struct timeval *tv);
|
||||||
diagnostic display */
|
diagnostic display */
|
||||||
extern char *UTI_TimestampToString(NTP_int64 *ts);
|
extern char *UTI_TimestampToString(NTP_int64 *ts);
|
||||||
|
|
||||||
|
/* Convert ref_id into a temporary string, for diagnostics */
|
||||||
|
extern char *UTI_RefidToString(unsigned long ref_id);
|
||||||
|
|
||||||
/* Convert an IP address to dotted quad notation, for diagnostics */
|
/* Convert an IP address to dotted quad notation, for diagnostics */
|
||||||
extern char *UTI_IPToDottedQuad(unsigned long ip);
|
extern char *UTI_IPToDottedQuad(unsigned long ip);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue