Skip to content

Commit

Permalink
Add summary statistics.
Browse files Browse the repository at this point in the history
Add new options to ptp4l and phc2sys to print summary statistics of the
clock instead of the individual samples.

[ RC - Fix () function prototype with (void).
     - Use unsigned for sample counter.
     - Fix over-zealous line breaks. ]

Signed-off-by: Miroslav Lichvar <[email protected]>
Signed-off-by: Richard Cochran <[email protected]>
  • Loading branch information
mlichvar authored and richardcochran committed Feb 9, 2013
1 parent c709836 commit 3136e3e
Show file tree
Hide file tree
Showing 13 changed files with 349 additions and 22 deletions.
92 changes: 83 additions & 9 deletions clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "phc.h"
#include "port.h"
#include "servo.h"
#include "stats.h"
#include "print.h"
#include "tlv.h"
#include "uds.h"
Expand All @@ -50,6 +51,13 @@ struct freq_estimator {
unsigned int count;
};

struct clock_stats {
struct stats *offset;
struct stats *freq;
struct stats *delay;
int max_count;
};

struct clock {
clockid_t clkid;
struct servo *servo;
Expand Down Expand Up @@ -80,6 +88,8 @@ struct clock {
tmv_t t1;
tmv_t t2;
struct clock_description desc;
struct clock_stats stats;
int stats_interval;
};

struct clock the_clock;
Expand All @@ -104,6 +114,9 @@ void clock_destroy(struct clock *c)
}
servo_destroy(c->servo);
mave_destroy(c->avg_delay);
stats_destroy(c->stats.offset);
stats_destroy(c->stats.freq);
stats_destroy(c->stats.delay);
memset(c, 0, sizeof(*c));
msg_cleanup();
}
Expand Down Expand Up @@ -232,6 +245,40 @@ static int clock_master_lost(struct clock *c)
return 1;
}

static void clock_stats_update(struct clock_stats *s,
int64_t offset, double freq)
{
struct stats_result offset_stats, freq_stats, delay_stats;

stats_add_value(s->offset, offset);
stats_add_value(s->freq, freq);

if (stats_get_num_values(s->offset) < s->max_count)
return;

stats_get_result(s->offset, &offset_stats);
stats_get_result(s->freq, &freq_stats);

/* Path delay stats are updated separately, they may be empty. */
if (!stats_get_result(s->delay, &delay_stats)) {
pr_info("rms %4.0f max %4.0f "
"freq %+6.0f +/- %3.0f "
"delay %5.0f +/- %3.0f",
offset_stats.rms, offset_stats.max_abs,
freq_stats.mean, freq_stats.stddev,
delay_stats.mean, delay_stats.stddev);
} else {
pr_info("rms %4.0f max %4.0f "
"freq %+6.0f +/- %3.0f",
offset_stats.rms, offset_stats.max_abs,
freq_stats.mean, freq_stats.stddev);
}

stats_reset(s->offset);
stats_reset(s->freq);
stats_reset(s->delay);
}

static enum servo_state clock_no_adjust(struct clock *c)
{
double fui;
Expand Down Expand Up @@ -278,9 +325,13 @@ static enum servo_state clock_no_adjust(struct clock *c)
tmv_dbl(tmv_sub(c->t2, f->ingress1));
freq = (1.0 - ratio) * 1e9;

pr_info("master offset %10" PRId64 " s%d freq %+7.0f "
"path delay %9" PRId64,
c->master_offset, state, freq, c->path_delay);
if (c->stats.max_count > 1) {
clock_stats_update(&c->stats, c->master_offset, freq);
} else {
pr_info("master offset %10" PRId64 " s%d freq %+7.0f "
"path delay %9" PRId64,
c->master_offset, state, freq, c->path_delay);
}

fui = 1.0 + (c->status.cumulativeScaledRateOffset + 0.0) / POW2_41;

Expand Down Expand Up @@ -433,7 +484,7 @@ UInteger8 clock_class(struct clock *c)

struct clock *clock_create(int phc_index, struct interface *iface, int count,
enum timestamp_type timestamping, struct default_ds *dds,
enum servo_type servo)
enum servo_type servo, int stats_interval)
{
int i, fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 : 0;
struct clock *c = &the_clock;
Expand Down Expand Up @@ -486,6 +537,14 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
pr_err("Failed to create moving average");
return NULL;
}
c->stats_interval = stats_interval;
c->stats.offset = stats_create();
c->stats.freq = stats_create();
c->stats.delay = stats_create();
if (!c->stats.offset || !c->stats.freq || !c->stats.delay) {
pr_err("failed to create stats");
return NULL;
}

c->dds = dds->dds;

Expand Down Expand Up @@ -834,12 +893,18 @@ void clock_path_delay(struct clock *c, struct timespec req, struct timestamp rx,
c->cur.meanPathDelay = tmv_to_TimeInterval(c->path_delay);

pr_debug("path delay %10lld %10lld", c->path_delay, pd);

if (c->stats.delay)
stats_add_value(c->stats.delay, pd);
}

void clock_peer_delay(struct clock *c, tmv_t ppd, double nrr)
{
c->path_delay = ppd;
c->nrr = nrr;

if (c->stats.delay)
stats_add_value(c->stats.delay, ppd);
}

void clock_remove_fda(struct clock *c, struct port *p, struct fdarray fda)
Expand Down Expand Up @@ -903,9 +968,13 @@ enum servo_state clock_synchronize(struct clock *c,

adj = servo_sample(c->servo, c->master_offset, ingress, &state);

pr_info("master offset %10" PRId64 " s%d freq %+7.0f "
"path delay %9" PRId64,
c->master_offset, state, adj, c->path_delay);
if (c->stats.max_count > 1) {
clock_stats_update(&c->stats, c->master_offset, adj);
} else {
pr_info("master offset %10" PRId64 " s%d freq %+7.0f "
"path delay %9" PRId64,
c->master_offset, state, adj, c->path_delay);
}

switch (state) {
case SERVO_UNLOCKED:
Expand All @@ -925,12 +994,17 @@ enum servo_state clock_synchronize(struct clock *c,

void clock_sync_interval(struct clock *c, int n)
{
int shift = c->freq_est_interval - n;
int shift;

shift = c->freq_est_interval - n;
if (shift < 0)
shift = 0;

c->fest.max_count = (1 << shift);

shift = c->stats_interval - n;
if (shift < 0)
shift = 0;
c->stats.max_count = (1 << shift);
}

struct timePropertiesDS *clock_time_properties(struct clock *c)
Expand Down
3 changes: 2 additions & 1 deletion clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ UInteger8 clock_class(struct clock *c);
* @param timestamping The timestamping mode for this clock.
* @param dds A pointer to a default data set for the clock.
* @param servo The servo that this clock will use.
* @param stats_interval Interval in which are printed clock statistics.
* @return A pointer to the single global clock instance.
*/
struct clock *clock_create(int phc_index, struct interface *iface, int count,
enum timestamp_type timestamping, struct default_ds *dds,
enum servo_type servo);
enum servo_type servo, int stats_interval);

/**
* Obtains a clock's default data set.
Expand Down
5 changes: 5 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@ static enum parser_result parse_global_setting(const char *option,
for (i = 0; i < OUI_LEN; i++)
cfg->dds.clock_desc.manufacturerIdentity[i] = oui[i];

} else if (!strcmp(option, "summary_interval")) {
if (1 != sscanf(value, "%d", &val))
return BAD_VALUE;
cfg->summary_interval = val;

} else
return NOT_PARSED;

Expand Down
1 change: 1 addition & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct config {
int print_level;
int use_syslog;
int verbose;
int summary_interval;
};

int config_read(char *name, struct config *cfg);
Expand Down
1 change: 1 addition & 0 deletions default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ follow_up_info 0
tx_timestamp_retries 100
use_syslog 1
verbose 0
summary_interval 0
#
# Servo Options
#
Expand Down
1 change: 1 addition & 0 deletions gPTP.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ follow_up_info 1
tx_timestamp_retries 100
use_syslog 1
verbose 0
summary_interval 0
#
# Servo options
#
Expand Down
8 changes: 4 additions & 4 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS)
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
PRG = ptp4l pmc phc2sys hwstamp_ctl
OBJ = bmc.o clock.o config.o fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o \
print.o raw.o servo.o sk.o tlv.o tmtab.o transport.o udp.o udp6.o uds.o util.o \
version.o
print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o \
uds.o util.o version.o

OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
SRC = $(OBJECTS:.o=.c)
Expand All @@ -52,8 +52,8 @@ ptp4l: $(OBJ)
pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \
udp6.o uds.o util.o version.o

phc2sys: msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.o sk.o sysoff.o \
tlv.o transport.o udp.o udp6.o uds.o util.o version.o
phc2sys: msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.o sk.o stats.o \
sysoff.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o

hwstamp_ctl: hwstamp_ctl.o version.o

Expand Down
11 changes: 11 additions & 0 deletions phc2sys.8
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ phc2sys \- synchronize two clocks
] [
.BI \-O " offset"
] [
.BI \-u " summary-updates"
] [
.B \-w
] [
.BI \-l " print-level"
Expand Down Expand Up @@ -112,6 +114,15 @@ Without
.B \-w
the default is 0.
.TP
.BI \-u " summary-updates"
Specify the number of clock updates included in summary statistics. The
statistics include offset root mean square (RMS), maximum absolute offset,
frequency offset mean and standard deviation, and mean of the delay in clock
readings and standard deviation. The units are nanoseconds and parts per
billion (ppb). If zero, the individual samples are printed instead of the
statistics. The messages are printed at the LOG_INFO level.
The default is 0 (disabled).
.TP
.B \-w
Wait until ptp4l is in a synchronized state.
.TP
Expand Down
Loading

0 comments on commit 3136e3e

Please sign in to comment.