Replace fixed-point format with floating-point in cmdmon protocol

This commit is contained in:
Miroslav Lichvar 2009-12-12 18:23:26 +01:00
parent 84f8463f2a
commit b49470117d
5 changed files with 147 additions and 71 deletions

57
candm.h
View file

@ -102,6 +102,13 @@ typedef struct {
/* This is used in tv_sec_high for 32-bit timestamps */
#define TV_NOHIGHSEC 0x7fffffff
/* 32-bit floating-point format consisting of 7-bit signed exponent
and 25-bit signed coefficient without hidden bit.
The result is calculated as: 2^(exp - 25) * coef */
typedef struct {
int32_t f;
} Float;
/* The EOR (end of record) fields are used by the offsetof operator in
pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */
@ -145,18 +152,18 @@ typedef struct {
typedef struct {
IPAddr address;
int32_t new_max_delay;
Float new_max_delay;
int32_t EOR;
} REQ_Modify_Maxdelay;
typedef struct {
IPAddr address;
int32_t new_max_delay_ratio;
Float new_max_delay_ratio;
int32_t EOR;
} REQ_Modify_Maxdelayratio;
typedef struct {
int32_t new_max_update_skew;
Float new_max_update_skew;
int32_t EOR;
} REQ_Modify_Maxupdateskew;
@ -216,8 +223,8 @@ typedef struct {
int32_t maxpoll;
int32_t presend_minpoll;
uint32_t authkey;
int32_t max_delay;
int32_t max_delay_ratio;
Float max_delay;
Float max_delay_ratio;
uint32_t flags;
int32_t EOR;
} REQ_NTP_Source;
@ -232,7 +239,7 @@ typedef struct {
} REQ_WriteRtc;
typedef struct {
int32_t dfreq;
Float dfreq;
int32_t EOR;
} REQ_Dfreq;
@ -325,7 +332,8 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline)
Version 4 : IPv6 addressing added, 64-bit time values, sourcestats
and tracking reports extended, added flags to NTP source request
and tracking reports extended, added flags to NTP source request,
replaced fixed-point format with floating-point
*/
@ -398,13 +406,6 @@ typedef struct {
#define PERMIT_LOCAL 1
#define PERMIT_AUTH 2
/* ================================================== */
/* These conversion utilities are used to convert between the internal
and the 'wire' representation of real quantities */
#define WIRE2REAL(x) ((double) ((int32_t) ntohl(x)) / 65536.0)
#define REAL2WIRE(x) (htonl((int32_t)(0.5 + 65536.0 * (x))))
/* ================================================== */
/* Reply codes */
@ -487,11 +488,11 @@ typedef struct {
Timeval ref_time;
uint32_t current_correction_s;
uint32_t current_correction_us;
int32_t freq_ppm;
int32_t resid_freq_ppm;
int32_t skew_ppm;
int32_t root_delay;
int32_t root_dispersion;
Float freq_ppm;
Float resid_freq_ppm;
Float skew_ppm;
Float root_delay;
Float root_dispersion;
int32_t EOR;
} RPY_Tracking;
@ -502,8 +503,8 @@ typedef struct {
uint32_t n_runs;
uint32_t span_seconds;
uint32_t sd_us;
int32_t resid_freq_ppm;
int32_t skew_ppm;
Float resid_freq_ppm;
Float skew_ppm;
int32_t EOR;
} RPY_Sourcestats;
@ -512,15 +513,15 @@ typedef struct {
uint16_t n_samples;
uint16_t n_runs;
uint32_t span_seconds;
int32_t rtc_seconds_fast;
int32_t rtc_gain_rate_ppm;
Float rtc_seconds_fast;
Float rtc_gain_rate_ppm;
int32_t EOR;
} RPY_Rtc;
typedef struct {
uint32_t centiseconds;
int32_t dfreq_ppm;
int32_t new_afreq_ppm;
Float dfreq_ppm;
Float new_afreq_ppm;
int32_t EOR;
} RPY_ManualTimestamp;
@ -562,9 +563,9 @@ typedef struct {
typedef struct {
Timeval when;
int32_t slewed_offset;
int32_t orig_offset;
int32_t residual;
Float slewed_offset;
Float orig_offset;
Float residual;
} RPY_ManualListSample;
typedef struct {

View file

@ -423,7 +423,7 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
if (read_address_double(line, &address, &max_delay)) {
UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay);
msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay);
msg->command = htons(REQ_MODIFY_MAXDELAY);
ok = 1;
} else {
@ -445,7 +445,7 @@ process_cmd_maxdelayratio(CMD_Request *msg, char *line)
if (read_address_double(line, &address, &max_delay_ratio)) {
UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio);
msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio);
msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
ok = 1;
} else {
@ -465,7 +465,7 @@ process_cmd_maxupdateskew(CMD_Request *msg, char *line)
double new_max_update_skew;
if (sscanf(line, "%lf", &new_max_update_skew) == 1) {
msg->data.modify_maxupdateskew.new_max_update_skew = REAL2WIRE(new_max_update_skew);
msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew);
msg->command = htons(REQ_MODIFY_MAXUPDATESKEW);
ok = 1;
} else {
@ -845,9 +845,9 @@ process_cmd_dfreq(CMD_Request *msg, char *line)
double dfreq;
msg->command = htons(REQ_DFREQ);
if (sscanf(line, "%lf", &dfreq) == 1) {
msg->data.dfreq.dfreq = REAL2WIRE(dfreq);
msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq);
} else {
msg->data.dfreq.dfreq = REAL2WIRE(0.0);
msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0);
}
}
@ -908,8 +908,8 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
msg->data.ntp_source.authkey = htonl(data.params.authkey);
msg->data.ntp_source.max_delay = REAL2WIRE(data.params.max_delay);
msg->data.ntp_source.max_delay_ratio = REAL2WIRE(data.params.max_delay_ratio);
msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay);
msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio);
msg->data.ntp_source.flags = htonl(
(data.params.online ? REQ_ADDSRC_ONLINE : 0) |
(data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0));
@ -1682,9 +1682,9 @@ process_cmd_sourcestats(char *line)
n_samples = ntohl(reply.data.sourcestats.n_samples);
n_runs = ntohl(reply.data.sourcestats.n_runs);
span_seconds = ntohl(reply.data.sourcestats.span_seconds);
resid_freq_ppm = WIRE2REAL(reply.data.sourcestats.resid_freq_ppm);
skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
sd_us = ntohl(reply.data.sourcestats.sd_us);
resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.resid_freq_ppm);
skew_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.skew_ppm);
if (ip_addr.family == IPADDR_UNSPEC)
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ref_id));
@ -1760,11 +1760,11 @@ process_cmd_tracking(char *line)
correction = (double) correction_tv.tv_sec + 1.0e-6 * correction_tv.tv_usec;
printf("System time : %.6f seconds %s of NTP time\n", fabs(correction),
(correction > 0.0) ? "slow" : "fast");
freq_ppm = WIRE2REAL(reply.data.tracking.freq_ppm);
resid_freq_ppm = WIRE2REAL(reply.data.tracking.resid_freq_ppm);
skew_ppm = WIRE2REAL(reply.data.tracking.skew_ppm);
root_delay = WIRE2REAL(reply.data.tracking.root_delay);
root_dispersion = WIRE2REAL(reply.data.tracking.root_dispersion);
freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm);
resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm);
skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);
root_delay = UTI_FloatNetworkToHost(reply.data.tracking.root_delay);
root_dispersion = UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion);
printf("Frequency : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast");
printf("Residual freq : %.3f ppm\n", resid_freq_ppm);
printf("Skew : %.3f ppm\n", skew_ppm);
@ -1796,8 +1796,8 @@ process_cmd_rtcreport(char *line)
n_samples = ntohs(reply.data.rtc.n_samples);
n_runs = ntohs(reply.data.rtc.n_runs);
span_seconds = ntohl(reply.data.rtc.span_seconds);
coef_seconds_fast = WIRE2REAL(reply.data.rtc.rtc_seconds_fast);
coef_gain_rate_ppm = WIRE2REAL(reply.data.rtc.rtc_gain_rate_ppm);
coef_seconds_fast = UTI_FloatNetworkToHost(reply.data.rtc.rtc_seconds_fast);
coef_gain_rate_ppm = UTI_FloatNetworkToHost(reply.data.rtc.rtc_gain_rate_ppm);
printf("RTC ref time (UTC) : %s", asctime(&ref_time_tm));
printf("Number of samples : %d\n", n_samples);
printf("Number of runs : %d\n", n_runs);
@ -2126,9 +2126,9 @@ process_cmd_manual_list(const char *line)
for (i=0; i<n_samples; i++) {
sample = &reply.data.manual_list.samples[i];
UTI_TimevalNetworkToHost(&sample->when, &when);
slewed_offset = WIRE2REAL(sample->slewed_offset);
orig_offset = WIRE2REAL(sample->orig_offset);
residual = WIRE2REAL(sample->residual);
slewed_offset = UTI_FloatNetworkToHost(sample->slewed_offset);
orig_offset = UTI_FloatNetworkToHost(sample->orig_offset);
residual = UTI_FloatNetworkToHost(sample->residual);
printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual);
}
return 1;
@ -2180,8 +2180,8 @@ process_cmd_settime(char *line)
if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
offset = 0.01 * (double) offset_cs;
dfreq_ppm = WIRE2REAL(reply.data.manual_timestamp.dfreq_ppm);
new_afreq_ppm = WIRE2REAL(reply.data.manual_timestamp.new_afreq_ppm);
dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
printf("Clock was %.2f seconds fast. Frequency change = %.2fppm, new frequency = %.2fppm\n",
offset, dfreq_ppm, new_afreq_ppm);
return 1;

View file

@ -881,7 +881,7 @@ handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
status = NSR_ModifyMaxdelay(&address,
WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay));
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay));
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
@ -898,7 +898,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
status = NSR_ModifyMaxdelayratio(&address,
WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
if (status) {
tx_message->status = htons(STT_SUCCESS);
} else {
@ -911,7 +911,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
static void
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
{
REF_ModifyMaxupdateskew(WIRE2REAL(rx_message->data.modify_maxupdateskew.new_max_update_skew));
REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
tx_message->status = htons(STT_SUCCESS);
}
@ -928,8 +928,8 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
tx_message->data.manual_timestamp.centiseconds = htonl(offset_cs);
tx_message->data.manual_timestamp.dfreq_ppm = REAL2WIRE(dfreq_ppm);
tx_message->data.manual_timestamp.new_afreq_ppm = REAL2WIRE(new_afreq_ppm);
tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
} else {
tx_message->status = htons(STT_NOTENABLED);
}
@ -1236,8 +1236,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio);
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddServer(&rem_addr, &params);
switch (status) {
case NSR_Success:
@ -1276,8 +1276,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio);
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddPeer(&rem_addr, &params);
switch (status) {
case NSR_Success:
@ -1350,7 +1350,7 @@ static void
handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
{
double dfreq;
dfreq = WIRE2REAL(rx_message->data.dfreq.dfreq);
dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
}
@ -1385,11 +1385,11 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec);
tx_message->data.tracking.current_correction_us = htonl(rpt.current_correction.tv_usec);
tx_message->data.tracking.freq_ppm = REAL2WIRE(rpt.freq_ppm);
tx_message->data.tracking.resid_freq_ppm = REAL2WIRE(rpt.resid_freq_ppm);
tx_message->data.tracking.skew_ppm = REAL2WIRE(rpt.skew_ppm);
tx_message->data.tracking.root_delay = REAL2WIRE(rpt.root_delay);
tx_message->data.tracking.root_dispersion = REAL2WIRE(rpt.root_dispersion);
tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
}
/* ================================================== */
@ -1410,9 +1410,9 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
tx_message->data.sourcestats.resid_freq_ppm = REAL2WIRE(report.resid_freq_ppm);
tx_message->data.sourcestats.skew_ppm = REAL2WIRE(report.skew_ppm);
tx_message->data.sourcestats.sd_us = htonl((unsigned long) (0.5 + report.sd_us));
tx_message->data.sourcestats.resid_freq_ppm = UTI_FloatHostToNetwork(report.resid_freq_ppm);
tx_message->data.sourcestats.skew_ppm = UTI_FloatHostToNetwork(report.skew_ppm);
} else {
tx_message->status = htons(STT_NOSUCHSOURCE);
}
@ -1433,8 +1433,8 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.rtc.n_samples = htons(report.n_samples);
tx_message->data.rtc.n_runs = htons(report.n_runs);
tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
tx_message->data.rtc.rtc_seconds_fast = REAL2WIRE(report.rtc_seconds_fast);
tx_message->data.rtc.rtc_gain_rate_ppm = REAL2WIRE(report.rtc_gain_rate_ppm);
tx_message->data.rtc.rtc_seconds_fast = UTI_FloatHostToNetwork(report.rtc_seconds_fast);
tx_message->data.rtc.rtc_gain_rate_ppm = UTI_FloatHostToNetwork(report.rtc_gain_rate_ppm);
} else {
tx_message->status = htons(STT_NORTC);
}
@ -1648,9 +1648,9 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
for (i=0; i<n_samples; i++) {
sample = &tx_message->data.manual_list.samples[i];
UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
sample->slewed_offset = REAL2WIRE(report[i].slewed_offset);
sample->orig_offset = REAL2WIRE(report[i].orig_offset);
sample->residual = REAL2WIRE(report[i].residual);
sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
sample->residual = UTI_FloatHostToNetwork(report[i].residual);
}
}

72
util.c
View file

@ -522,5 +522,77 @@ UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
dest->tv_sec_low = htonl(src->tv_sec);
}
/* ================================================== */
#define FLOAT_EXP_BITS 7
#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
double
UTI_FloatNetworkToHost(Float f)
{
int32_t exp, coef, x;
x = ntohl(f.f);
exp = (x >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
coef = x << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
return coef * pow(2.0, exp);
}
Float
UTI_FloatHostToNetwork(double x)
{
int32_t exp, coef, neg;
Float f;
if (x < 0.0) {
x = -x;
neg = 1;
} else {
neg = 0;
}
if (x < 1.0e-100) {
exp = coef = 0;
} else if (x > 1.0e100) {
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else {
exp = log(x) / log(2) + 1;
coef = x * pow(2.0, -exp + FLOAT_COEF_BITS) + 0.5;
assert(coef > 0);
/* we may need to shift up to two bits down */
while (coef > FLOAT_COEF_MAX + neg) {
coef >>= 1;
exp++;
}
if (exp > FLOAT_EXP_MAX) {
/* overflow */
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else if (exp < FLOAT_EXP_MIN) {
/* underflow */
if (exp + FLOAT_COEF_BITS >= FLOAT_EXP_MIN) {
coef >>= FLOAT_EXP_MIN - exp;
exp = FLOAT_EXP_MIN;
} else {
exp = coef = 0;
}
}
}
/* negate back */
if (neg)
coef = (uint32_t)-coef << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
f.f = htonl(exp << FLOAT_COEF_BITS | coef);
return f;
}
/* ================================================== */

3
util.h
View file

@ -99,6 +99,9 @@ extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
extern double UTI_FloatNetworkToHost(Float x);
extern Float UTI_FloatHostToNetwork(double x);
#if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static
#include "util.c"