From da594e78d9692596347131583a9576ba1ee9dc75 Mon Sep 17 00:00:00 2001 From: Delio Brignoli Date: Wed, 30 Jan 2013 16:28:54 +0100 Subject: [PATCH] Make the fault reset interval a per-port configuration parameter. A timeout of 15 seconds is not always acceptable, make it configurable. By popular consensus, instead of using a linear number of seconds, use the 2^N format for the time interval, just like the other intervals in the PTP data sets. In addition to numeric values, let the configuration file support 'ASAP' to have the fault reset immediately. [RC - moved the handling of special case tmo=0 and added a break out of the fd event loop in case the fds have been closed. - changed the linear seconds option to log second instead. - changed the commit message to reflect the final version. ] Signed-off-by: Delio Brignoli Signed-off-by: Richard Cochran --- clock.c | 21 +++++++++++---------- config.c | 9 +++++++++ default.cfg | 1 + ds.h | 3 +++ gPTP.cfg | 1 + port.c | 5 +++-- port.h | 16 ++++++++++++++++ ptp4l.8 | 7 +++++++ ptp4l.c | 1 + 9 files changed, 52 insertions(+), 12 deletions(-) diff --git a/clock.c b/clock.c index 5d5ccbf..5523297 100644 --- a/clock.c +++ b/clock.c @@ -37,7 +37,6 @@ #include "util.h" #define CLK_N_PORTS (MAX_PORTS + 1) /* plus one for the UDS interface */ -#define FAULT_RESET_SECONDS 15 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */ #define MAVE_LENGTH 10 #define POW2_41 ((double)(1ULL << 41)) @@ -65,7 +64,7 @@ struct clock { struct port *port[CLK_N_PORTS]; struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD]; int fault_fd[CLK_N_PORTS]; - time_t fault_timeout; + int8_t fault_timeout[CLK_N_PORTS]; int nports; /* does not include the UDS port */ int free_running; int freq_est_interval; @@ -110,17 +109,18 @@ void clock_destroy(struct clock *c) static int clock_fault_timeout(struct clock *c, int index, int set) { - struct itimerspec tmo = { - {0, 0}, {0, 0} - }; + int log_seconds = 0; + unsigned int scale = 0; + if (set) { - pr_debug("waiting %d seconds to clear fault on port %d", - c->fault_timeout, index); - tmo.it_value.tv_sec = c->fault_timeout; + pr_debug("waiting 2^{%d} seconds to clear fault on port %d", + c->fault_timeout[index], index); + log_seconds = c->fault_timeout[index]; + scale = 1; } else { pr_debug("clearing fault on port %d", index); } - return timerfd_settime(c->fault_fd[index], 0, &tmo, NULL); + return set_tmo(c->fault_fd[index], scale, log_seconds); } static void clock_freq_est_reset(struct clock *c) @@ -479,10 +479,10 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count, c->pollfd[i].events = 0; } - c->fault_timeout = FAULT_RESET_SECONDS; c->fest.max_count = 2; for (i = 0; i < count; i++) { + c->fault_timeout[i] = iface[i].pod.fault_reset_interval; c->port[i] = port_open(phc_index, timestamping, 1+i, &iface[i], c); if (!c->port[i]) { pr_err("failed to open port %s", iface[i].name); @@ -722,6 +722,7 @@ int clock_poll(struct clock *c) /* Clear any fault after a little while. */ if (PS_FAULTY == port_state(c->port[i])) { clock_fault_timeout(c, i, 1); + break; } } } diff --git a/config.c b/config.c index a4a6261..7262049 100644 --- a/config.c +++ b/config.c @@ -106,6 +106,15 @@ static enum parser_result parse_pod_setting(const char *option, return BAD_VALUE; pod->follow_up_info = val ? 1 : 0; + } else if (!strcmp(option, "fault_reset_interval")) { + if (!strcasecmp("ASAP", value)) { + pod->fault_reset_interval = FRI_ASAP; + } else if (1 == sscanf(value, "%hhd", &i8)) { + pod->fault_reset_interval = i8; + } else { + return BAD_VALUE; + } + } else return NOT_PARSED; diff --git a/default.cfg b/default.cfg index ee2700d..d551a3b 100644 --- a/default.cfg +++ b/default.cfg @@ -21,6 +21,7 @@ logMinDelayReqInterval 0 logMinPdelayReqInterval 0 announceReceiptTimeout 3 delayAsymmetry 0 +fault_reset_interval 4 # # Run time options # diff --git a/ds.h b/ds.h index 514679b..27f9ab7 100644 --- a/ds.h +++ b/ds.h @@ -101,6 +101,8 @@ struct portDS { UInteger8 versionNumber; } PACKED; +#define FRI_ASAP (-128) + struct port_defaults { Integer64 asymmetry; Integer8 logAnnounceInterval; @@ -112,6 +114,7 @@ struct port_defaults { int path_trace_enabled; int follow_up_info; int freq_est_interval; /*log seconds*/ + int fault_reset_interval; /*log seconds*/ }; #endif diff --git a/gPTP.cfg b/gPTP.cfg index f186e78..3c47e28 100644 --- a/gPTP.cfg +++ b/gPTP.cfg @@ -20,6 +20,7 @@ logSyncInterval -3 logMinPdelayReqInterval 0 announceReceiptTimeout 3 delayAsymmetry 0 +fault_reset_interval 4 # # Run time options # diff --git a/port.c b/port.c index 8b03bd9..c521c18 100644 --- a/port.c +++ b/port.c @@ -150,7 +150,7 @@ static int source_pid_eq(struct ptp_message *m1, struct ptp_message *m2) &m2->header.sourcePortIdentity); } -static int set_tmo(int fd, unsigned int scale, int log_seconds) +int set_tmo(int fd, unsigned int scale, int log_seconds) { struct itimerspec tmo = { {0, 0}, {0, 0} @@ -1419,7 +1419,8 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff) next = ptp_fsm(p->state, event, mdiff); } - if (PS_INITIALIZING == next) { + if (PS_INITIALIZING == next || + (PS_FAULTY == next && FRI_ASAP == p->pod.fault_reset_interval)) { /* * This is a special case. Since we initialize the * port immediately, we can skip right to listening diff --git a/port.h b/port.h index 2fc71e4..d98f610 100644 --- a/port.h +++ b/port.h @@ -155,4 +155,20 @@ struct port *port_open(int phc_index, */ enum port_state port_state(struct port *port); +/** + * Utility function for setting or resetting a file descriptor timer. + * + * This function sets the timer 'fd' to the value M(2^N), where M is + * the value of the 'scale' parameter and N in the value of the + * 'log_seconds' parameter. + * + * Passing both 'scale' and 'log_seconds' as zero disables the timer. + * + * @param fd A file descriptor previously opened with timerfd_create(2). + * @param scale The multiplicative factor for the timer. + * @param log_seconds The exponential factor for the timer. + * @return Zero on success, non-zero otherwise. + */ +int set_tmo(int fd, unsigned int scale, int log_seconds); + #endif diff --git a/ptp4l.8 b/ptp4l.8 index fadf854..0b9f558 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -181,6 +181,13 @@ The default is 0 (disabled). Include the 802.1AS data in the Follow_Up messages if enabled. The default is 0 (disabled). .TP +.B fault_reset_interval +The time in seconds between the detection of a port's fault and the fault +being reset. This value is expressed as a power of two. Setting this +value to -128 or to the special key word "ASAP" will let the fault be +reset immediately. +The default is 4 (16 seconds). +.TP .B delay_mechanism Select the delay mechanism. Possible values are E2E, P2P and Auto. The default is E2E. diff --git a/ptp4l.c b/ptp4l.c index 4fc0c88..f486516 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -64,6 +64,7 @@ static struct config cfg_settings = { .path_trace_enabled = 0, .follow_up_info = 0, .freq_est_interval = 1, + .fault_reset_interval = 4, }, .timestamping = TS_HARDWARE,