Add a timer implementing the sync receive timeout.
This patch adds a new timer for use in 802.1AS-2011 applications. When running as a slave in gPTP mode, the program must monitor both announce and sync messages from the master. If either one goes missing, then we trigger a BMC election. The sync timeout is actually reset by a valid sync/follow up pair of messages. Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
329e4a2fff
commit
7eef4101c9
3
fd.h
3
fd.h
|
@ -20,12 +20,13 @@
|
||||||
#ifndef HAVE_FD_H
|
#ifndef HAVE_FD_H
|
||||||
#define HAVE_FD_H
|
#define HAVE_FD_H
|
||||||
|
|
||||||
#define N_TIMER_FDS 5
|
#define N_TIMER_FDS 6
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FD_EVENT,
|
FD_EVENT,
|
||||||
FD_GENERAL,
|
FD_GENERAL,
|
||||||
FD_ANNOUNCE_TIMER,
|
FD_ANNOUNCE_TIMER,
|
||||||
|
FD_SYNC_RX_TIMER,
|
||||||
FD_DELAY_TIMER,
|
FD_DELAY_TIMER,
|
||||||
FD_QUALIFICATION_TIMER,
|
FD_QUALIFICATION_TIMER,
|
||||||
FD_MANNO_TIMER,
|
FD_MANNO_TIMER,
|
||||||
|
|
17
port.c
17
port.c
|
@ -97,6 +97,7 @@ struct port {
|
||||||
TimeInterval peerMeanPathDelay;
|
TimeInterval peerMeanPathDelay;
|
||||||
Integer8 logAnnounceInterval;
|
Integer8 logAnnounceInterval;
|
||||||
UInteger8 announceReceiptTimeout;
|
UInteger8 announceReceiptTimeout;
|
||||||
|
UInteger8 syncReceiptTimeout;
|
||||||
UInteger8 transportSpecific;
|
UInteger8 transportSpecific;
|
||||||
Integer8 logSyncInterval;
|
Integer8 logSyncInterval;
|
||||||
Enumeration8 delayMechanism;
|
Enumeration8 delayMechanism;
|
||||||
|
@ -800,6 +801,12 @@ static int port_set_qualification_tmo(struct port *p)
|
||||||
1+clock_steps_removed(p->clock), p->logAnnounceInterval);
|
1+clock_steps_removed(p->clock), p->logAnnounceInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int port_set_sync_rx_tmo(struct port *p)
|
||||||
|
{
|
||||||
|
return set_tmo_log(p->fda.fd[FD_SYNC_RX_TIMER],
|
||||||
|
p->syncReceiptTimeout, p->logSyncInterval);
|
||||||
|
}
|
||||||
|
|
||||||
static int port_set_sync_tx_tmo(struct port *p)
|
static int port_set_sync_tx_tmo(struct port *p)
|
||||||
{
|
{
|
||||||
return set_tmo_log(p->fda.fd[FD_SYNC_TX_TIMER], 1, p->logSyncInterval);
|
return set_tmo_log(p->fda.fd[FD_SYNC_TX_TIMER], 1, p->logSyncInterval);
|
||||||
|
@ -832,6 +839,8 @@ static void port_synchronize(struct port *p,
|
||||||
{
|
{
|
||||||
enum servo_state state;
|
enum servo_state state;
|
||||||
|
|
||||||
|
port_set_sync_rx_tmo(p);
|
||||||
|
|
||||||
state = clock_synchronize(p->clock, ingress_ts, origin_ts,
|
state = clock_synchronize(p->clock, ingress_ts, origin_ts,
|
||||||
correction1, correction2);
|
correction1, correction2);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -1851,6 +1860,7 @@ struct foreign_clock *port_compute_best(struct port *p)
|
||||||
static void port_e2e_transition(struct port *p, enum port_state next)
|
static void port_e2e_transition(struct port *p, enum port_state next)
|
||||||
{
|
{
|
||||||
port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
|
||||||
|
port_clr_tmo(p->fda.fd[FD_SYNC_RX_TIMER]);
|
||||||
port_clr_tmo(p->fda.fd[FD_DELAY_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_DELAY_TIMER]);
|
||||||
port_clr_tmo(p->fda.fd[FD_QUALIFICATION_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_QUALIFICATION_TIMER]);
|
||||||
port_clr_tmo(p->fda.fd[FD_MANNO_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_MANNO_TIMER]);
|
||||||
|
@ -1883,6 +1893,7 @@ static void port_e2e_transition(struct port *p, enum port_state next)
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case PS_SLAVE:
|
case PS_SLAVE:
|
||||||
port_set_announce_tmo(p);
|
port_set_announce_tmo(p);
|
||||||
|
port_set_sync_rx_tmo(p);
|
||||||
port_set_delay_tmo(p);
|
port_set_delay_tmo(p);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1891,6 +1902,7 @@ static void port_e2e_transition(struct port *p, enum port_state next)
|
||||||
static void port_p2p_transition(struct port *p, enum port_state next)
|
static void port_p2p_transition(struct port *p, enum port_state next)
|
||||||
{
|
{
|
||||||
port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
|
||||||
|
port_clr_tmo(p->fda.fd[FD_SYNC_RX_TIMER]);
|
||||||
/* Leave FD_DELAY_TIMER running. */
|
/* Leave FD_DELAY_TIMER running. */
|
||||||
port_clr_tmo(p->fda.fd[FD_QUALIFICATION_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_QUALIFICATION_TIMER]);
|
||||||
port_clr_tmo(p->fda.fd[FD_MANNO_TIMER]);
|
port_clr_tmo(p->fda.fd[FD_MANNO_TIMER]);
|
||||||
|
@ -1923,6 +1935,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case PS_SLAVE:
|
case PS_SLAVE:
|
||||||
port_set_announce_tmo(p);
|
port_set_announce_tmo(p);
|
||||||
|
port_set_sync_rx_tmo(p);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1987,7 +2000,9 @@ enum fsm_event port_event(struct port *p, int fd_index)
|
||||||
|
|
||||||
switch (fd_index) {
|
switch (fd_index) {
|
||||||
case FD_ANNOUNCE_TIMER:
|
case FD_ANNOUNCE_TIMER:
|
||||||
pr_debug("port %hu: announce timeout", portnum(p));
|
case FD_SYNC_RX_TIMER:
|
||||||
|
pr_debug("port %hu: %s timeout", portnum(p),
|
||||||
|
fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce");
|
||||||
if (p->best)
|
if (p->best)
|
||||||
fc_clear(p->best);
|
fc_clear(p->best);
|
||||||
port_set_announce_tmo(p);
|
port_set_announce_tmo(p);
|
||||||
|
|
Loading…
Reference in New Issue