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 <dbrignoli@audioscience.com> Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
eec07ae240
commit
da594e78d9
21
clock.c
21
clock.c
|
@ -37,7 +37,6 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define CLK_N_PORTS (MAX_PORTS + 1) /* plus one for the UDS interface */
|
#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 N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */
|
||||||
#define MAVE_LENGTH 10
|
#define MAVE_LENGTH 10
|
||||||
#define POW2_41 ((double)(1ULL << 41))
|
#define POW2_41 ((double)(1ULL << 41))
|
||||||
|
@ -65,7 +64,7 @@ struct clock {
|
||||||
struct port *port[CLK_N_PORTS];
|
struct port *port[CLK_N_PORTS];
|
||||||
struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
|
struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
|
||||||
int fault_fd[CLK_N_PORTS];
|
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 nports; /* does not include the UDS port */
|
||||||
int free_running;
|
int free_running;
|
||||||
int freq_est_interval;
|
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)
|
static int clock_fault_timeout(struct clock *c, int index, int set)
|
||||||
{
|
{
|
||||||
struct itimerspec tmo = {
|
int log_seconds = 0;
|
||||||
{0, 0}, {0, 0}
|
unsigned int scale = 0;
|
||||||
};
|
|
||||||
if (set) {
|
if (set) {
|
||||||
pr_debug("waiting %d seconds to clear fault on port %d",
|
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
|
||||||
c->fault_timeout, index);
|
c->fault_timeout[index], index);
|
||||||
tmo.it_value.tv_sec = c->fault_timeout;
|
log_seconds = c->fault_timeout[index];
|
||||||
|
scale = 1;
|
||||||
} else {
|
} else {
|
||||||
pr_debug("clearing fault on port %d", index);
|
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)
|
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->pollfd[i].events = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->fault_timeout = FAULT_RESET_SECONDS;
|
|
||||||
c->fest.max_count = 2;
|
c->fest.max_count = 2;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
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);
|
c->port[i] = port_open(phc_index, timestamping, 1+i, &iface[i], c);
|
||||||
if (!c->port[i]) {
|
if (!c->port[i]) {
|
||||||
pr_err("failed to open port %s", iface[i].name);
|
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. */
|
/* Clear any fault after a little while. */
|
||||||
if (PS_FAULTY == port_state(c->port[i])) {
|
if (PS_FAULTY == port_state(c->port[i])) {
|
||||||
clock_fault_timeout(c, i, 1);
|
clock_fault_timeout(c, i, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
config.c
9
config.c
|
@ -106,6 +106,15 @@ static enum parser_result parse_pod_setting(const char *option,
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
pod->follow_up_info = val ? 1 : 0;
|
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
|
} else
|
||||||
return NOT_PARSED;
|
return NOT_PARSED;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ logMinDelayReqInterval 0
|
||||||
logMinPdelayReqInterval 0
|
logMinPdelayReqInterval 0
|
||||||
announceReceiptTimeout 3
|
announceReceiptTimeout 3
|
||||||
delayAsymmetry 0
|
delayAsymmetry 0
|
||||||
|
fault_reset_interval 4
|
||||||
#
|
#
|
||||||
# Run time options
|
# Run time options
|
||||||
#
|
#
|
||||||
|
|
3
ds.h
3
ds.h
|
@ -101,6 +101,8 @@ struct portDS {
|
||||||
UInteger8 versionNumber;
|
UInteger8 versionNumber;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
#define FRI_ASAP (-128)
|
||||||
|
|
||||||
struct port_defaults {
|
struct port_defaults {
|
||||||
Integer64 asymmetry;
|
Integer64 asymmetry;
|
||||||
Integer8 logAnnounceInterval;
|
Integer8 logAnnounceInterval;
|
||||||
|
@ -112,6 +114,7 @@ struct port_defaults {
|
||||||
int path_trace_enabled;
|
int path_trace_enabled;
|
||||||
int follow_up_info;
|
int follow_up_info;
|
||||||
int freq_est_interval; /*log seconds*/
|
int freq_est_interval; /*log seconds*/
|
||||||
|
int fault_reset_interval; /*log seconds*/
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
1
gPTP.cfg
1
gPTP.cfg
|
@ -20,6 +20,7 @@ logSyncInterval -3
|
||||||
logMinPdelayReqInterval 0
|
logMinPdelayReqInterval 0
|
||||||
announceReceiptTimeout 3
|
announceReceiptTimeout 3
|
||||||
delayAsymmetry 0
|
delayAsymmetry 0
|
||||||
|
fault_reset_interval 4
|
||||||
#
|
#
|
||||||
# Run time options
|
# Run time options
|
||||||
#
|
#
|
||||||
|
|
5
port.c
5
port.c
|
@ -150,7 +150,7 @@ static int source_pid_eq(struct ptp_message *m1, struct ptp_message *m2)
|
||||||
&m2->header.sourcePortIdentity);
|
&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 = {
|
struct itimerspec tmo = {
|
||||||
{0, 0}, {0, 0}
|
{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);
|
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
|
* This is a special case. Since we initialize the
|
||||||
* port immediately, we can skip right to listening
|
* port immediately, we can skip right to listening
|
||||||
|
|
16
port.h
16
port.h
|
@ -155,4 +155,20 @@ struct port *port_open(int phc_index,
|
||||||
*/
|
*/
|
||||||
enum port_state port_state(struct port *port);
|
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
|
#endif
|
||||||
|
|
7
ptp4l.8
7
ptp4l.8
|
@ -181,6 +181,13 @@ The default is 0 (disabled).
|
||||||
Include the 802.1AS data in the Follow_Up messages if enabled.
|
Include the 802.1AS data in the Follow_Up messages if enabled.
|
||||||
The default is 0 (disabled).
|
The default is 0 (disabled).
|
||||||
.TP
|
.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
|
.B delay_mechanism
|
||||||
Select the delay mechanism. Possible values are E2E, P2P and Auto.
|
Select the delay mechanism. Possible values are E2E, P2P and Auto.
|
||||||
The default is E2E.
|
The default is E2E.
|
||||||
|
|
1
ptp4l.c
1
ptp4l.c
|
@ -64,6 +64,7 @@ static struct config cfg_settings = {
|
||||||
.path_trace_enabled = 0,
|
.path_trace_enabled = 0,
|
||||||
.follow_up_info = 0,
|
.follow_up_info = 0,
|
||||||
.freq_est_interval = 1,
|
.freq_est_interval = 1,
|
||||||
|
.fault_reset_interval = 4,
|
||||||
},
|
},
|
||||||
|
|
||||||
.timestamping = TS_HARDWARE,
|
.timestamping = TS_HARDWARE,
|
||||||
|
|
Loading…
Reference in New Issue