diff --git a/config.c b/config.c index 0b3abb4..afb2e6b 100644 --- a/config.c +++ b/config.c @@ -112,6 +112,16 @@ static enum parser_result parse_pod_setting(const char *option, return BAD_VALUE; pod->neighborPropDelayThresh = val; + } else if (!strcmp(option, "fault_badpeernet_interval")) { + pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].type = FTMO_LINEAR_SECONDS; + if (!strcasecmp("ASAP", value)) { + pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = 0; + } else if (1 != sscanf(value, "%d", &val)) { + pod->flt_interval_pertype[FT_BAD_PEER_NETWORK].val = val; + } else { + return BAD_VALUE; + } + } else if (!strcmp(option, "fault_reset_interval")) { pod->flt_interval_pertype[FT_UNSPECIFIED].type = FTMO_LOG2_SECONDS; if (!strcasecmp("ASAP", value)) { diff --git a/fault.c b/fault.c index 6f48169..7fcf019 100644 --- a/fault.c +++ b/fault.c @@ -20,6 +20,7 @@ static const char *fault_type_str[FT_CNT] = { "FT_UNSPECIFIED", + "FT_BAD_PEER_NETWORK", }; const char *ft_str(enum fault_type ft) diff --git a/fault.h b/fault.h index d7ac2b6..8d62c38 100644 --- a/fault.h +++ b/fault.h @@ -20,6 +20,7 @@ enum fault_type { FT_UNSPECIFIED = 0, + FT_BAD_PEER_NETWORK, FT_CNT, }; diff --git a/port.c b/port.c index e47f276..d922047 100644 --- a/port.c +++ b/port.c @@ -73,6 +73,8 @@ struct port { int log_sync_interval; struct nrate_estimator nrate; unsigned int pdr_missing; + unsigned int multiple_seq_pdr_count; + unsigned int multiple_pdr_detected; /* portDS */ struct port_defaults pod; struct PortIdentity portIdentity; @@ -430,6 +432,13 @@ static int port_capable(struct port *p) goto not_capable; } + if (p->multiple_seq_pdr_count) { + if (p->asCapable) + pr_debug("port %hu: multiple sequential peer delay resp, " + "resetting asCapable", portnum(p)); + goto not_capable; + } + if (!p->peer_portid_valid) { if (p->asCapable) pr_debug("port %hu: invalid peer port id, " @@ -838,6 +847,11 @@ static int port_pdelay_request(struct port *p) struct ptp_message *msg; int cnt, pdulen; + /* If multiple pdelay resp were not detected the counter can be reset */ + if (!p->multiple_pdr_detected) + p->multiple_seq_pdr_count = 0; + p->multiple_pdr_detected = 0; + msg = msg_allocate(); if (!msg) return -1; @@ -1144,6 +1158,8 @@ static int port_initialize(struct port *p) { int fd[N_TIMER_FDS], i; + p->multiple_seq_pdr_count = 0; + p->multiple_pdr_detected = 0; p->last_fault_type = FT_UNSPECIFIED; p->logMinDelayReqInterval = p->pod.logMinDelayReqInterval; p->peerMeanPathDelay = 0; @@ -1583,7 +1599,14 @@ static int process_pdelay_resp(struct port *p, struct ptp_message *m) if (p->peer_delay_resp) { if (!source_pid_eq(p->peer_delay_resp, m)) { pr_err("port %hu: multiple peer responses", portnum(p)); - return -1; + if (!p->multiple_pdr_detected) { + p->multiple_pdr_detected = 1; + p->multiple_seq_pdr_count++; + } + if (p->multiple_seq_pdr_count >= 3) { + p->last_fault_type = FT_BAD_PEER_NETWORK; + return -1; + } } } if (!p->peer_delay_req) { diff --git a/ptp4l.8 b/ptp4l.8 index be0d3a6..98a7674 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -188,6 +188,13 @@ 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 fault_badpeernet_interval +The time in seconds between the detection of a peer network misconfiguration +and the fault being reset. The port is disabled for the duration of the +interval. The value is in seconds and the special key word ASAP will let +the fault be reset immediately. +The default is 16 seconds. +.TP .B delay_mechanism Select the delay mechanism. Possible values are E2E, P2P and Auto. The default is E2E.