9b1654
commit 134dc3c4655fcd9f314a5e56cd50db2f87366f5a
9b1654
Author: davidjm via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net>
9b1654
Date:   Wed Nov 23 15:50:30 2022 -0800
9b1654
9b1654
    Don't re-arm fault clearing timer on unrelated netlink events
9b1654
    
9b1654
    Set the timer only when an event causes the port to transition to the
9b1654
    FAULTY state, rather than potentially re-arming the timeout when an
9b1654
    event occurs while the port was already FAULTY.
9b1654
    
9b1654
    Concretely this occurs when a port is in fault, perhaps due to a
9b1654
    single time out while polling for tx-timestamp. If any other port in the
9b1654
    system (including unrelated ones ptp4l does not even know about) cause
9b1654
    netlink messages to be sent. As it stands, clock_poll() will note that
9b1654
    the port is in fault (from before, not due to the current event) and
9b1654
    reset the timeout to its original value.
9b1654
    
9b1654
    If such unrelated netlink messages arrive at a regular enough cadence
9b1654
    the timeout may be repeatedly reset, not trigger on time (if at all) and
9b1654
    the port may not get a chance to clear its fault, perhaps indefinitely.
9b1654
    
9b1654
    Signed-off-by: David Mirabito <davidjm@arista.com>
9b1654
9b1654
diff --git a/clock.c b/clock.c
9b1654
index eea7983..451473e 100644
9b1654
--- a/clock.c
9b1654
+++ b/clock.c
9b1654
@@ -1586,6 +1586,7 @@ void clock_set_sde(struct clock *c, int sde)
9b1654
 int clock_poll(struct clock *c)
9b1654
 {
9b1654
 	int cnt, i;
9b1654
+	enum port_state prior_state;
9b1654
 	enum fsm_event event;
9b1654
 	struct pollfd *cur;
9b1654
 	struct port *p;
9b1654
@@ -1609,6 +1610,7 @@ int clock_poll(struct clock *c)
9b1654
 		/* Let the ports handle their events. */
9b1654
 		for (i = 0; i < N_POLLFD; i++) {
9b1654
 			if (cur[i].revents & (POLLIN|POLLPRI|POLLERR)) {
9b1654
+				prior_state = port_state(p);
9b1654
 				if (cur[i].revents & POLLERR) {
9b1654
 					pr_err("port %d: unexpected socket error",
9b1654
 					       port_number(p));
9b1654
@@ -1624,7 +1626,7 @@ int clock_poll(struct clock *c)
9b1654
 				}
9b1654
 				port_dispatch(p, event, 0);
9b1654
 				/* Clear any fault after a little while. */
9b1654
-				if (PS_FAULTY == port_state(p)) {
9b1654
+				if ((PS_FAULTY == port_state(p)) && (prior_state != PS_FAULTY)) {
9b1654
 					clock_fault_timeout(p, 1);
9b1654
 					break;
9b1654
 				}