After the timer expiration, just after the poll(), we can read fron the
timer file descriptor a 64bit value that represents the number of
expirations that have occured. This value is useful for debug. In
addition, when we use a periodic timer the timer will be locked until
the read of this value.
---
e2e_tc.c | 4 ++++
p2p_tc.c | 4 ++++
port.c | 28 ++++++++++++++++++++++++++++
port.h | 10 ++++++++++
4 files changed, 46 insertions(+)
diff --git a/e2e_tc.c b/e2e_tc.c
index 2f8e821..43c69e9 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -85,6 +85,7 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
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);
}
@@ -93,6 +94,7 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
case FD_DELAY_TIMER:
pr_debug("%s: delay timeout", p->log_name);
+ timerfd_flush(p, fd, "delay");
port_set_delay_tmo(p);
delay_req_prune(p);
tc_prune(p);
@@ -112,6 +114,7 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
case FD_QUALIFICATION_TIMER:
pr_debug("%s: qualification timeout", p->log_name);
+ timerfd_flush(p, fd, "qualification");
return EV_QUALIFICATION_TIMEOUT_EXPIRES;
case FD_MANNO_TIMER:
@@ -119,6 +122,7 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
case FD_UNICAST_REQ_TIMER:
case FD_UNICAST_SRV_TIMER:
pr_err("unexpected timer expiration");
+ timerfd_flush(p, fd, "unexpected");
return EV_NONE;
case FD_RTNL:
diff --git a/p2p_tc.c b/p2p_tc.c
index 75cb3b9..55a4b1c 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -101,6 +101,7 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
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);
}
@@ -109,12 +110,14 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
case FD_DELAY_TIMER:
pr_debug("%s: delay timeout", p->log_name);
+ timerfd_flush(p, fd, "delay");
port_set_delay_tmo(p);
tc_prune(p);
return p2p_delay_request(p) ? EV_FAULT_DETECTED : EV_NONE;
case FD_QUALIFICATION_TIMER:
pr_debug("%s: qualification timeout", p->log_name);
+ timerfd_flush(p, fd, "qualification");
return EV_QUALIFICATION_TIMEOUT_EXPIRES;
case FD_MANNO_TIMER:
@@ -122,6 +125,7 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
case FD_UNICAST_REQ_TIMER:
case FD_UNICAST_SRV_TIMER:
pr_err("unexpected timer expiration");
+ timerfd_flush(p, fd, "unexpected");
return EV_NONE;
case FD_RTNL:
diff --git a/port.c b/port.c
index 16434b5..005bbbc 100644
--- a/port.c
+++ b/port.c
@@ -2852,6 +2852,7 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
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);
}
@@ -2890,6 +2891,7 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
case FD_DELAY_TIMER:
pr_debug("%s: delay timeout", p->log_name);
+ timerfd_flush(p, fd, "delay");
port_set_delay_tmo(p);
delay_req_prune(p);
p->service_stats.delay_timeout++;
@@ -2909,11 +2911,13 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
case FD_QUALIFICATION_TIMER:
pr_debug("%s: qualification timeout", p->log_name);
+ timerfd_flush(p, fd, "qualification");
p->service_stats.qualification_timeout++;
return EV_QUALIFICATION_TIMEOUT_EXPIRES;
case FD_MANNO_TIMER:
pr_debug("%s: master tx announce timeout", p->log_name);
+ timerfd_flush(p, fd, "master announce");
port_set_manno_tmo(p);
p->service_stats.master_announce_timeout++;
clock_update_leap_status(p->clock);
@@ -2922,6 +2926,7 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
case FD_SYNC_TX_TIMER:
pr_debug("%s: master sync timeout", p->log_name);
+ timerfd_flush(p, fd, "master sync timeout");
port_set_sync_tx_tmo(p);
p->service_stats.master_sync_timeout++;
return port_tx_sync(p, NULL, p->seqnum.sync++) ?
@@ -2929,11 +2934,13 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
case FD_UNICAST_SRV_TIMER:
pr_debug("%s: unicast service timeout", p->log_name);
+ timerfd_flush(p, fd, "unicast service");
p->service_stats.unicast_service_timeout++;
return unicast_service_timer(p) ? EV_FAULT_DETECTED : EV_NONE;
case FD_UNICAST_REQ_TIMER:
pr_debug("%s: unicast request timeout", p->log_name);
+ timerfd_flush(p, fd, "unicast request");
p->service_stats.unicast_request_timeout++;
return unicast_client_timer(p) ? EV_FAULT_DETECTED : EV_NONE;
@@ -3548,3 +3555,24 @@ void port_update_unicast_state(struct port *p)
p->unicast_state_dirty = false;
}
}
+
+uint64_t timerfd_flush(struct port *p, int fd, char *fd_name)
+{
+ uint64_t val = 0;
+ ssize_t res = read(fd, &val, sizeof(val));
+
+ if (res < 0) {
+ pr_err("port %u: Error on read %s timer (%"PRId64 ", %m)",
+ portnum(p), fd_name, res);
+ val = 0;
+ } else if (res != sizeof(val)) {
+ pr_err("port %u: Error on read %s timer (%"PRId64 ")",
+ portnum(p), fd_name, res);
+ val = 0;
+ } else if (val != 1) {
+ pr_warning("port %u: Missing %"PRIu64" ticks on %s timer",
+ portnum(p), val, fd_name);
+ }
+
+ return val;
+}
diff --git a/port.h b/port.h
index 57c8c2f..0b5b5b0 100644
--- a/port.h
+++ b/port.h
@@ -364,4 +364,14 @@ void tc_cleanup(void);
*/
void port_update_unicast_state(struct port *p);
+/**
+ * Flush the timer fd reading the number of elapsed tick.
+ *
+ * @param p A port instance.
+ * @param fd A file descriptor previously opened with timerfd_create(2).
+ * @param fd_name A symbolic name for error logging
+ * @return Number of elapsed ticks
+ */
+uint64_t timerfd_flush(struct port *p, int fd, char *fd_name);
+
#endif
--
2.41.0
_______________________________________________
Linuxptp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel