During a timer handling we should avoid to call timerfd_settime() on a different timer because this call will invalidate the file descriptor, resulting in a EGAIN when the other timer code will performe the read().
The ANNOUNCE and RX SYNC timer code just doesn't follow this rule. The solution is to split the rearm code. --- e2e_tc.c | 26 ++++++++++++++++-------- p2p_tc.c | 26 ++++++++++++++++-------- port.c | 60 ++++++++++++++++++++++++++++++++------------------------ 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/e2e_tc.c b/e2e_tc.c index 43c69e9..c7cfd9e 100644 --- a/e2e_tc.c +++ b/e2e_tc.c @@ -74,6 +74,15 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int mdiff) }; } +static enum fsm_event e2e_announce_sync_rx_timeout_action(struct port *p) +{ + if (p->best) { + fc_clear(p->best); + } + port_set_announce_tmo(p); + return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; +} + enum fsm_event e2e_event(struct port *p, int fd_index) { int cnt, fd = p->fda.fd[fd_index]; @@ -82,15 +91,16 @@ enum fsm_event e2e_event(struct port *p, int fd_index) switch (fd_index) { case FD_ANNOUNCE_TIMER: + pr_debug("%s: announce timeout", p->log_name); + timerfd_flush(p, fd, "announce"); + + return e2e_announce_sync_rx_timeout_action(p); + case FD_SYNC_RX_TIMER: - pr_debug("%s: %s timeout", p->log_name, - fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - if (p->best) { - fc_clear(p->best); - } - port_set_announce_tmo(p); - return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; + pr_debug("%s: rx sync timeout", p->log_name); + timerfd_flush(p, fd, "rx sync"); + + return e2e_announce_sync_rx_timeout_action(p); case FD_DELAY_TIMER: pr_debug("%s: delay timeout", p->log_name); diff --git a/p2p_tc.c b/p2p_tc.c index 55a4b1c..0d6d68b 100644 --- a/p2p_tc.c +++ b/p2p_tc.c @@ -90,6 +90,15 @@ void p2p_dispatch(struct port *p, enum fsm_event event, int mdiff) }; } +static enum fsm_event p2p_announce_sync_rx_timeout_action(struct port *p) +{ + if (p->best) { + fc_clear(p->best); + } + port_set_announce_tmo(p); + return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; +} + enum fsm_event p2p_event(struct port *p, int fd_index) { int cnt, fd = p->fda.fd[fd_index]; @@ -98,15 +107,16 @@ enum fsm_event p2p_event(struct port *p, int fd_index) switch (fd_index) { case FD_ANNOUNCE_TIMER: + pr_debug("%s: announce timeout", p->log_name); + timerfd_flush(p, fd, "announce"); + + return p2p_announce_sync_rx_timeout_action(p); + case FD_SYNC_RX_TIMER: - pr_debug("%s: %s timeout", p->log_name, - fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - if (p->best) { - fc_clear(p->best); - } - port_set_announce_tmo(p); - return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; + pr_debug("%s: rx sync timeout", p->log_name); + timerfd_flush(p, fd, "rx sync"); + + return p2p_announce_sync_rx_timeout_action(p); case FD_DELAY_TIMER: pr_debug("%s: delay timeout", p->log_name); diff --git a/port.c b/port.c index e38f244..cc558eb 100644 --- a/port.c +++ b/port.c @@ -2842,6 +2842,24 @@ enum fsm_event port_event(struct port *p, int fd_index) return p->event(p, fd_index); } +static enum fsm_event bc_announce_sync_rx_timeout_action(struct port *p) +{ + if (p->best) { + fc_clear(p->best); + } + + delay_req_prune(p); + if (clock_slave_only(p->clock) && p->delayMechanism != DM_P2P && + port_renew_transport(p)) { + return EV_FAULT_DETECTED; + } + + if (p->inhibit_announce) { + return EV_NONE; + } + return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; +} + static enum fsm_event bc_event(struct port *p, int fd_index) { enum fsm_event event = EV_NONE; @@ -2850,20 +2868,25 @@ static enum fsm_event bc_event(struct port *p, int fd_index) switch (fd_index) { case FD_ANNOUNCE_TIMER: - case FD_SYNC_RX_TIMER: - pr_debug("%s: %s timeout", p->log_name, - fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - timerfd_flush(p, fd, fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); - if (p->best) { - fc_clear(p->best); - } + pr_debug("%s: announce timeout", p->log_name); + timerfd_flush(p, fd, "announce"); - if (fd_index == FD_SYNC_RX_TIMER) { - p->service_stats.sync_timeout++; + p->service_stats.announce_timeout++; + + if (p->inhibit_announce) { + port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]); } else { - p->service_stats.announce_timeout++; + port_set_announce_tmo(p); } + return bc_announce_sync_rx_timeout_action(p); + + case FD_SYNC_RX_TIMER: + pr_debug("%s: rx sync timeout", p->log_name); + timerfd_flush(p, fd, "rx sync"); + + p->service_stats.sync_timeout++; + /* * Clear out the event returned by poll(). It is only cleared * in port_*_transition(). But, when BMCA == 'noop', there is no @@ -2873,22 +2896,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index) port_clr_tmo(p->fda.fd[FD_SYNC_RX_TIMER]); } - if (p->inhibit_announce) { - port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]); - } else { - port_set_announce_tmo(p); - } - - delay_req_prune(p); - if (clock_slave_only(p->clock) && p->delayMechanism != DM_P2P && - port_renew_transport(p)) { - return EV_FAULT_DETECTED; - } - - if (p->inhibit_announce) { - return EV_NONE; - } - return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; + return bc_announce_sync_rx_timeout_action(p); case FD_DELAY_TIMER: pr_debug("%s: delay timeout", p->log_name); -- 2.40.0 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel