Add support for multiple fault types
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>master
parent
455ebe7d22
commit
b936d35b6d
29
clock.c
29
clock.c
|
@ -72,7 +72,6 @@ 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];
|
||||||
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;
|
||||||
|
@ -123,18 +122,27 @@ 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)
|
||||||
{
|
{
|
||||||
int log_seconds = 0;
|
struct fault_interval i;
|
||||||
unsigned int scale = 0;
|
|
||||||
|
|
||||||
if (set) {
|
if (!set) {
|
||||||
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);
|
pr_debug("clearing fault on port %d", index);
|
||||||
|
return set_tmo_lin(c->fault_fd[index], 0);
|
||||||
}
|
}
|
||||||
return set_tmo_log(c->fault_fd[index], scale, log_seconds);
|
|
||||||
|
fault_interval(c->port[index], last_fault_type(c->port[index]), &i);
|
||||||
|
|
||||||
|
if (i.type == FTMO_LINEAR_SECONDS) {
|
||||||
|
pr_debug("waiting %d seconds to clear fault on port %d",
|
||||||
|
i.val, index);
|
||||||
|
return set_tmo_lin(c->fault_fd[index], i.val);
|
||||||
|
} else if (i.type == FTMO_LOG2_SECONDS) {
|
||||||
|
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
|
||||||
|
i.val, index);
|
||||||
|
return set_tmo_log(c->fault_fd[index], 1, i.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("Unsupported fault interval type %d", i.type);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clock_freq_est_reset(struct clock *c)
|
static void clock_freq_est_reset(struct clock *c)
|
||||||
|
@ -618,7 +626,6 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
|
||||||
clock_sync_interval(c, 0);
|
clock_sync_interval(c, 0);
|
||||||
|
|
||||||
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);
|
||||||
|
|
5
config.c
5
config.c
|
@ -113,10 +113,11 @@ static enum parser_result parse_pod_setting(const char *option,
|
||||||
pod->neighborPropDelayThresh = val;
|
pod->neighborPropDelayThresh = val;
|
||||||
|
|
||||||
} else if (!strcmp(option, "fault_reset_interval")) {
|
} else if (!strcmp(option, "fault_reset_interval")) {
|
||||||
|
pod->flt_interval_pertype[FT_UNSPECIFIED].type = FTMO_LOG2_SECONDS;
|
||||||
if (!strcasecmp("ASAP", value)) {
|
if (!strcasecmp("ASAP", value)) {
|
||||||
pod->fault_reset_interval = FRI_ASAP;
|
pod->flt_interval_pertype[FT_UNSPECIFIED].val = FRI_ASAP;
|
||||||
} else if (1 == sscanf(value, "%hhd", &i8)) {
|
} else if (1 == sscanf(value, "%hhd", &i8)) {
|
||||||
pod->fault_reset_interval = i8;
|
pod->flt_interval_pertype[FT_UNSPECIFIED].val = i8;
|
||||||
} else {
|
} else {
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
3
ds.h
3
ds.h
|
@ -21,6 +21,7 @@
|
||||||
#define HAVE_DS_H
|
#define HAVE_DS_H
|
||||||
|
|
||||||
#include "ddt.h"
|
#include "ddt.h"
|
||||||
|
#include "fault.h"
|
||||||
|
|
||||||
/* clock data sets */
|
/* clock data sets */
|
||||||
|
|
||||||
|
@ -124,7 +125,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*/
|
struct fault_interval flt_interval_pertype[FT_CNT];
|
||||||
UInteger32 neighborPropDelayThresh; /*nanoseconds*/
|
UInteger32 neighborPropDelayThresh; /*nanoseconds*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* @file fault.c
|
||||||
|
* @note Copyright (C) 2013 Delio Brignoli <dbrignoli@audioscience.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#include "fault.h"
|
||||||
|
|
||||||
|
static const char *fault_type_str[FT_CNT] = {
|
||||||
|
"FT_UNSPECIFIED",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *ft_str(enum fault_type ft)
|
||||||
|
{
|
||||||
|
if (ft < 0 || ft >= FT_CNT)
|
||||||
|
return "INVALID_FAULT_TYPE_ENUM";
|
||||||
|
return fault_type_str[ft];
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* @file fault.h
|
||||||
|
* @note Copyright (C) 2013 Delio Brignoli <dbrignoli@audioscience.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum fault_type {
|
||||||
|
FT_UNSPECIFIED = 0,
|
||||||
|
FT_CNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fault_tmo_type {
|
||||||
|
FTMO_LINEAR_SECONDS = 0,
|
||||||
|
FTMO_LOG2_SECONDS,
|
||||||
|
FTMO_CNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fault_interval {
|
||||||
|
enum fault_tmo_type type;
|
||||||
|
int32_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *ft_str(enum fault_type ft);
|
6
makefile
6
makefile
|
@ -29,9 +29,9 @@ VER = -DVER=$(version)
|
||||||
CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS)
|
CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS)
|
||||||
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
|
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
|
||||||
PRG = ptp4l pmc phc2sys hwstamp_ctl
|
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 \
|
OBJ = bmc.o clock.o config.o fault.o fsm.o ptp4l.o mave.o msg.o phc.o pi.o \
|
||||||
print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o \
|
port.o print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o \
|
||||||
uds.o util.o version.o
|
udp6.o uds.o util.o version.o
|
||||||
|
|
||||||
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
|
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
|
||||||
SRC = $(OBJECTS:.o=.c)
|
SRC = $(OBJECTS:.o=.c)
|
||||||
|
|
36
port.c
36
port.c
|
@ -87,6 +87,7 @@ struct port {
|
||||||
Enumeration8 delayMechanism;
|
Enumeration8 delayMechanism;
|
||||||
Integer8 logMinPdelayReqInterval;
|
Integer8 logMinPdelayReqInterval;
|
||||||
UInteger32 neighborPropDelayThresh;
|
UInteger32 neighborPropDelayThresh;
|
||||||
|
enum fault_type last_fault_type;
|
||||||
unsigned int versionNumber; /*UInteger4*/
|
unsigned int versionNumber; /*UInteger4*/
|
||||||
/* foreignMasterDS */
|
/* foreignMasterDS */
|
||||||
LIST_HEAD(fm, foreign_clock) foreign_masters;
|
LIST_HEAD(fm, foreign_clock) foreign_masters;
|
||||||
|
@ -160,6 +161,23 @@ static int source_pid_eq(struct ptp_message *m1, struct ptp_message *m2)
|
||||||
&m2->header.sourcePortIdentity);
|
&m2->header.sourcePortIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fault_type last_fault_type(struct port *port)
|
||||||
|
{
|
||||||
|
return port->last_fault_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fault_interval(struct port *port, enum fault_type ft,
|
||||||
|
struct fault_interval *i)
|
||||||
|
{
|
||||||
|
if (!port || !i)
|
||||||
|
return -EINVAL;
|
||||||
|
if (ft < 0 || ft >= FT_CNT)
|
||||||
|
return -EINVAL;
|
||||||
|
i->type = port->pod.flt_interval_pertype[ft].type;
|
||||||
|
i->val = port->pod.flt_interval_pertype[ft].val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int set_tmo_log(int fd, unsigned int scale, int log_seconds)
|
int set_tmo_log(int fd, unsigned int scale, int log_seconds)
|
||||||
{
|
{
|
||||||
struct itimerspec tmo = {
|
struct itimerspec tmo = {
|
||||||
|
@ -768,8 +786,14 @@ static int port_set_sync_tmo(struct port *p)
|
||||||
static void port_show_transition(struct port *p,
|
static void port_show_transition(struct port *p,
|
||||||
enum port_state next, enum fsm_event event)
|
enum port_state next, enum fsm_event event)
|
||||||
{
|
{
|
||||||
pr_notice("port %hu: %s to %s on %s", portnum(p),
|
if (event == EV_FAULT_DETECTED) {
|
||||||
ps_str[p->state], ps_str[next], ev_str[event]);
|
pr_notice("port %hu: %s to %s on %s (%s)", portnum(p),
|
||||||
|
ps_str[p->state], ps_str[next], ev_str[event],
|
||||||
|
ft_str(last_fault_type(p)));
|
||||||
|
} else {
|
||||||
|
pr_notice("port %hu: %s to %s on %s", portnum(p),
|
||||||
|
ps_str[p->state], ps_str[next], ev_str[event]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void port_slave_priority_warning(struct port *p)
|
static void port_slave_priority_warning(struct port *p)
|
||||||
|
@ -1120,6 +1144,7 @@ static int port_initialize(struct port *p)
|
||||||
{
|
{
|
||||||
int fd[N_TIMER_FDS], i;
|
int fd[N_TIMER_FDS], i;
|
||||||
|
|
||||||
|
p->last_fault_type = FT_UNSPECIFIED;
|
||||||
p->logMinDelayReqInterval = p->pod.logMinDelayReqInterval;
|
p->logMinDelayReqInterval = p->pod.logMinDelayReqInterval;
|
||||||
p->peerMeanPathDelay = 0;
|
p->peerMeanPathDelay = 0;
|
||||||
p->logAnnounceInterval = p->pod.logAnnounceInterval;
|
p->logAnnounceInterval = p->pod.logAnnounceInterval;
|
||||||
|
@ -1774,6 +1799,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
|
||||||
int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
|
int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
|
||||||
{
|
{
|
||||||
enum port_state next;
|
enum port_state next;
|
||||||
|
struct fault_interval i;
|
||||||
|
|
||||||
if (clock_slave_only(p->clock)) {
|
if (clock_slave_only(p->clock)) {
|
||||||
if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
|
if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
|
||||||
|
@ -1784,8 +1810,10 @@ int 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 ||
|
fault_interval(p, last_fault_type(p), &i);
|
||||||
(PS_FAULTY == next && FRI_ASAP == p->pod.fault_reset_interval)) {
|
int fri_asap = (i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
|
||||||
|
(i.val == 0 && i.type == FTMO_LINEAR_SECONDS);
|
||||||
|
if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
|
|
20
port.h
20
port.h
|
@ -186,4 +186,24 @@ int set_tmo_log(int fd, unsigned int scale, int log_seconds);
|
||||||
*/
|
*/
|
||||||
int set_tmo_lin(int fd, int seconds);
|
int set_tmo_lin(int fd, int seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a port's last fault type.
|
||||||
|
*
|
||||||
|
* @param port A port instance.
|
||||||
|
* @return One of the @ref fault_type values.
|
||||||
|
*/
|
||||||
|
enum fault_type last_fault_type(struct port *port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills passed in struct fault_interval with the value associated to a
|
||||||
|
* port and fault type.
|
||||||
|
*
|
||||||
|
* @param port A port instance.
|
||||||
|
* @param ft Fault type.
|
||||||
|
* @param i Pointer to the struct which will be filled in.
|
||||||
|
* @return Zero on success, non-zero otherwise.
|
||||||
|
*/
|
||||||
|
int fault_interval(struct port *port, enum fault_type ft,
|
||||||
|
struct fault_interval *i);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
7
ptp4l.c
7
ptp4l.c
|
@ -79,7 +79,6 @@ 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,
|
|
||||||
/* Default to very a large neighborPropDelay threshold */
|
/* Default to very a large neighborPropDelay threshold */
|
||||||
.neighborPropDelayThresh = 20000000,
|
.neighborPropDelayThresh = 20000000,
|
||||||
},
|
},
|
||||||
|
@ -174,6 +173,12 @@ int main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set fault timeouts to a default value */
|
||||||
|
for (i = 0; i < FT_CNT; i++) {
|
||||||
|
cfg_settings.pod.flt_interval_pertype[i].type = FTMO_LOG2_SECONDS;
|
||||||
|
cfg_settings.pod.flt_interval_pertype[i].val = 4;
|
||||||
|
}
|
||||||
|
|
||||||
/* Process the command line arguments. */
|
/* Process the command line arguments. */
|
||||||
progname = strrchr(argv[0], '/');
|
progname = strrchr(argv[0], '/');
|
||||||
progname = progname ? 1+progname : argv[0];
|
progname = progname ? 1+progname : argv[0];
|
||||||
|
|
Loading…
Reference in New Issue