4693f0
commit 10d4e7f8b0525bbf72981e3e5fcf0c10833a7631
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Tue Jan 3 20:55:18 2017 +0100
4693f0
4693f0
    port: Make the finite state machine into a function variable.
4693f0
    
4693f0
    This allows adding new FSM flavors in the future.
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/port.c b/port.c
4693f0
index a1ad6f6..afe0057 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -94,6 +94,8 @@ struct port {
4693f0
 	unsigned int pdr_missing;
4693f0
 	unsigned int multiple_seq_pdr_count;
4693f0
 	unsigned int multiple_pdr_detected;
4693f0
+	enum port_state (*state_machine)(enum port_state state,
4693f0
+					 enum fsm_event event, int mdiff);
4693f0
 	/* portDS */
4693f0
 	struct PortIdentity portIdentity;
4693f0
 	enum port_state     state; /*portState*/
4693f0
@@ -2142,10 +2144,8 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 		if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
4693f0
 			port_slave_priority_warning(p);
4693f0
 		}
4693f0
-		next = ptp_slave_fsm(p->state, event, mdiff);
4693f0
-	} else {
4693f0
-		next = ptp_fsm(p->state, event, mdiff);
4693f0
 	}
4693f0
+	next = p->state_machine(p->state, event, mdiff);
4693f0
 
4693f0
 	if (!fault_interval(p, last_fault_type(p), &i) &&
4693f0
 	    ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
4693f0
@@ -2555,6 +2555,7 @@ struct port *port_open(int phc_index,
4693f0
 
4693f0
 	memset(p, 0, sizeof(*p));
4693f0
 
4693f0
+	p->state_machine = clock_slave_only(clock) ? ptp_slave_fsm : ptp_fsm;
4693f0
 	p->phc_index = phc_index;
4693f0
 	p->jbod = config_get_int(cfg, interface->name, "boundary_clock_jbod");
4693f0
 	transport = config_get_int(cfg, interface->name, "network_transport");
4693f0
4693f0
commit 80a28a9dc322f28b991effc44ec1c5362a598281
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Tue Jan 3 20:55:33 2017 +0100
4693f0
4693f0
    Change a misleading fault handling function signature.
4693f0
    
4693f0
    Looking at the fault logic in port_dispatch(), you might think that
4693f0
    the function, fault_interval(), checks whether a fault is active, but
4693f0
    you would be wrong, since that function always returns zero.
4693f0
    
4693f0
    This patch removes the superfluous input error checking inside of
4693f0
    fault_interval() and changes the return type to void, making the
4693f0
    actual behavior explicit.  Dropping the input check is safe because
4693f0
    that function has exactly two callers, both of whom always provide
4693f0
    valid inputs.
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/port.c b/port.c
4693f0
index afe0057..6c9aa72 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -205,16 +205,11 @@ enum fault_type last_fault_type(struct port *port)
4693f0
 	return port->last_fault_type;
4693f0
 }
4693f0
 
4693f0
-int fault_interval(struct port *port, enum fault_type ft,
4693f0
-	struct fault_interval *i)
4693f0
+void fault_interval(struct port *port, enum fault_type ft,
4693f0
+		    struct fault_interval *i)
4693f0
 {
4693f0
-	if (!port || !i)
4693f0
-		return -EINVAL;
4693f0
-	if (ft < 0 || ft >= FT_CNT)
4693f0
-		return -EINVAL;
4693f0
 	i->type = port->flt_interval_pertype[ft].type;
4693f0
 	i->val = port->flt_interval_pertype[ft].val;
4693f0
-	return 0;
4693f0
 }
4693f0
 
4693f0
 int port_fault_fd(struct port *port)
4693f0
@@ -2147,9 +2142,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 	}
4693f0
 	next = p->state_machine(p->state, event, mdiff);
4693f0
 
4693f0
-	if (!fault_interval(p, last_fault_type(p), &i) &&
4693f0
-	    ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
4693f0
-	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS)))
4693f0
+	fault_interval(p, last_fault_type(p), &i);
4693f0
+	if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
4693f0
+	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS))
4693f0
 		fri_asap = 1;
4693f0
 	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
4693f0
 		/*
4693f0
diff --git a/port.h b/port.h
4693f0
index 19dec4a..d2e0865 100644
4693f0
--- a/port.h
4693f0
+++ b/port.h
4693f0
@@ -318,9 +318,8 @@ enum fault_type last_fault_type(struct port *port);
4693f0
  * @param port        A port instance.
4693f0
  * @param ft          Fault type.
4693f0
  * @param i           Pointer to the struct which will be filled in.
4693f0
- * @return Zero on success, non-zero otherwise.
4693f0
  */
4693f0
-int fault_interval(struct port *port, enum fault_type ft,
4693f0
-	struct fault_interval *i);
4693f0
+void fault_interval(struct port *port, enum fault_type ft,
4693f0
+		    struct fault_interval *i);
4693f0
 
4693f0
 #endif
4693f0
4693f0
commit 1f66948d3853c8b08c7f52c9c8daecb361164a43
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Tue Jan 3 20:55:42 2017 +0100
4693f0
4693f0
    Make the fault handling code more readable.
4693f0
    
4693f0
    The code that decides whether a fault qualifies for ASAP treatment is
4693f0
    a tangle of logical operators.  This patch replaces the open coded
4693f0
    logic with a helper function whose name makes the intent clear.  This
4693f0
    is a cosmetic change only.
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/port.c b/port.c
4693f0
index 6c9aa72..02dbabb 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -161,6 +161,19 @@ static void announce_to_dataset(struct ptp_message *m, struct port *p,
4693f0
 	out->receiver     = p->portIdentity;
4693f0
 }
4693f0
 
4693f0
+static int clear_fault_asap(struct fault_interval *faint)
4693f0
+{
4693f0
+	switch (faint->type) {
4693f0
+	case FTMO_LINEAR_SECONDS:
4693f0
+		return faint->val == 0 ? 1 : 0;
4693f0
+	case FTMO_LOG2_SECONDS:
4693f0
+		return faint->val == FRI_ASAP ? 1 : 0;
4693f0
+	case FTMO_CNT:
4693f0
+		return 0;
4693f0
+	}
4693f0
+	return 0;
4693f0
+}
4693f0
+
4693f0
 static int msg_current(struct ptp_message *m, struct timespec now)
4693f0
 {
4693f0
 	int64_t t1, t2, tmo;
4693f0
@@ -2143,9 +2156,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 	next = p->state_machine(p->state, event, mdiff);
4693f0
 
4693f0
 	fault_interval(p, last_fault_type(p), &i);
4693f0
-	if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) ||
4693f0
-	     (i.val == 0 && i.type == FTMO_LINEAR_SECONDS))
4693f0
+	if (clear_fault_asap(&i)) {
4693f0
 		fri_asap = 1;
4693f0
+	}
4693f0
 	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
4693f0
 		/*
4693f0
 		 * This is a special case. Since we initialize the
4693f0
4693f0
commit 01ee947457813078f63d606c310818d6dedb4ca3
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Tue Jan 3 20:55:50 2017 +0100
4693f0
4693f0
    Disentangle initialization from fault clearing.
4693f0
    
4693f0
    Although leaving the INITIALIZING state and clearing the FAULTY state
4693f0
    ASAP both result in a port entering the LISTENING state, still there
4693f0
    is no benefit from conflating the two.  In the FAULTY case, the
4693f0
    current code actually skips the INITIALIZING state altogether.
4693f0
    
4693f0
    This patch separates the two cases resulting in two benefits.  First,
4693f0
    the check for ASAP fault status is only made when a fault is actually
4693f0
    present, unlike the present unconditional check.  Second, this change
4693f0
    will allow us to cleanly support alternative state machines later on.
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/port.c b/port.c
4693f0
index 02dbabb..ebe7342 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -2145,8 +2145,6 @@ static void port_p2p_transition(struct port *p, enum port_state next)
4693f0
 int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 {
4693f0
 	enum port_state next;
4693f0
-	struct fault_interval i;
4693f0
-	int fri_asap = 0;
4693f0
 
4693f0
 	if (clock_slave_only(p->clock)) {
4693f0
 		if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
4693f0
@@ -2155,11 +2153,15 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 	}
4693f0
 	next = p->state_machine(p->state, event, mdiff);
4693f0
 
4693f0
-	fault_interval(p, last_fault_type(p), &i);
4693f0
-	if (clear_fault_asap(&i)) {
4693f0
-		fri_asap = 1;
4693f0
+	if (PS_FAULTY == next) {
4693f0
+		struct fault_interval i;
4693f0
+		fault_interval(p, last_fault_type(p), &i);
4693f0
+		if (clear_fault_asap(&i)) {
4693f0
+			pr_notice("port %hu: clearing fault immediately", portnum(p));
4693f0
+			next = PS_INITIALIZING;
4693f0
+		}
4693f0
 	}
4693f0
-	if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) {
4693f0
+	if (PS_INITIALIZING == next) {
4693f0
 		/*
4693f0
 		 * This is a special case. Since we initialize the
4693f0
 		 * port immediately, we can skip right to listening
4693f0
4693f0
commit b738afb6044a8c59310fc13f646c8f5c4dcf2963
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Thu Oct 27 15:20:36 2016 +0200
4693f0
4693f0
    fsm: Make the transition out of INITIALIZING part of the FSM code.
4693f0
    
4693f0
    The state machines in 1588 do not specify an event that causes a transition
4693f0
    out of the initializing state.  This was left as a local issue.  For this
4693f0
    transition, the current code assigns the next state outside of the FSM.  But
4693f0
    doing so prevents an alternative FSM to handle this transition differently.
4693f0
    
4693f0
    By introducing a new event, this patch places this transition where it
4693f0
    belongs, namely under the control of the FSM code,
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/fsm.c b/fsm.c
4693f0
index d1423e7..ce6efad 100644
4693f0
--- a/fsm.c
4693f0
+++ b/fsm.c
4693f0
@@ -27,7 +27,16 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff)
4693f0
 
4693f0
 	switch (state) {
4693f0
 	case PS_INITIALIZING:
4693f0
-		next = PS_LISTENING;
4693f0
+		switch (event) {
4693f0
+		case EV_FAULT_DETECTED:
4693f0
+			next = PS_FAULTY;
4693f0
+			break;
4693f0
+		case EV_INIT_COMPLETE:
4693f0
+			next = PS_LISTENING;
4693f0
+			break;
4693f0
+		default:
4693f0
+			break;
4693f0
+		}
4693f0
 		break;
4693f0
 
4693f0
 	case PS_FAULTY:
4693f0
@@ -220,7 +229,16 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
4693f0
 
4693f0
 	switch (state) {
4693f0
 	case PS_INITIALIZING:
4693f0
-		next = PS_LISTENING;
4693f0
+		switch (event) {
4693f0
+		case EV_FAULT_DETECTED:
4693f0
+			next = PS_FAULTY;
4693f0
+			break;
4693f0
+		case EV_INIT_COMPLETE:
4693f0
+			next = PS_LISTENING;
4693f0
+			break;
4693f0
+		default:
4693f0
+			break;
4693f0
+		}
4693f0
 		break;
4693f0
 
4693f0
 	case PS_FAULTY:
4693f0
diff --git a/fsm.h b/fsm.h
4693f0
index 5d4ae91..0616daa 100644
4693f0
--- a/fsm.h
4693f0
+++ b/fsm.h
4693f0
@@ -48,6 +48,7 @@ enum fsm_event {
4693f0
 	EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES,
4693f0
 	EV_SYNCHRONIZATION_FAULT,
4693f0
 	EV_MASTER_CLOCK_SELECTED,
4693f0
+	EV_INIT_COMPLETE,
4693f0
 	EV_RS_MASTER,
4693f0
 	EV_RS_GRAND_MASTER,
4693f0
 	EV_RS_SLAVE,
4693f0
diff --git a/port.c b/port.c
4693f0
index ebe7342..5f1646b 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -2120,6 +2120,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
4693f0
 		break;
4693f0
 	case PS_LISTENING:
4693f0
 		port_set_announce_tmo(p);
4693f0
+		port_set_delay_tmo(p);
4693f0
 		break;
4693f0
 	case PS_PRE_MASTER:
4693f0
 		port_set_qualification_tmo(p);
4693f0
@@ -2158,7 +2159,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 		fault_interval(p, last_fault_type(p), &i);
4693f0
 		if (clear_fault_asap(&i)) {
4693f0
 			pr_notice("port %hu: clearing fault immediately", portnum(p));
4693f0
-			next = PS_INITIALIZING;
4693f0
+			next = p->state_machine(next, EV_FAULT_CLEARED, 0);
4693f0
 		}
4693f0
 	}
4693f0
 	if (PS_INITIALIZING == next) {
4693f0
@@ -2170,14 +2171,12 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 		if (port_is_enabled(p)) {
4693f0
 			port_disable(p);
4693f0
 		}
4693f0
-		next = port_initialize(p) ? PS_FAULTY : PS_LISTENING;
4693f0
-		port_show_transition(p, next, event);
4693f0
-		p->state = next;
4693f0
-		if (next == PS_LISTENING && p->delayMechanism == DM_P2P) {
4693f0
-			port_set_delay_tmo(p);
4693f0
+		if (port_initialize(p)) {
4693f0
+			event = EV_FAULT_DETECTED;
4693f0
+		} else {
4693f0
+			event = EV_INIT_COMPLETE;
4693f0
 		}
4693f0
-		port_notify_event(p, NOTIFY_PORT_STATE);
4693f0
-		return 1;
4693f0
+		next = p->state_machine(next, event, 0);
4693f0
 	}
4693f0
 
4693f0
 	if (next == p->state)
4693f0
diff --git a/util.c b/util.c
4693f0
index 594b49f..2b880ff 100644
4693f0
--- a/util.c
4693f0
+++ b/util.c
4693f0
@@ -61,6 +61,7 @@ const char *ev_str[] = {
4693f0
 	"ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES",
4693f0
 	"SYNCHRONIZATION_FAULT",
4693f0
 	"MASTER_CLOCK_SELECTED",
4693f0
+	"INIT_COMPLETE",
4693f0
 	"RS_MASTER",
4693f0
 	"RS_GRAND_MASTER",
4693f0
 	"RS_SLAVE",
4693f0
4693f0
commit 6b471d45edfdfa835a9115ce4be96d92f100e2ac
4693f0
Author: Richard Cochran <richardcochran@gmail.com>
4693f0
Date:   Sun Feb 5 18:25:18 2017 +0100
4693f0
4693f0
    port: Change port_dispatch() into a void function.
4693f0
    
4693f0
    This global function used to return an error code, but now it always
4693f0
    returns zero.  This patch converts the function signature to return void
4693f0
    and simplifies the main clock loop by removing the useless test.
4693f0
    
4693f0
    Signed-off-by: Richard Cochran <richardcochran@gmail.com>
4693f0
4693f0
diff --git a/clock.c b/clock.c
4693f0
index a6a1a1a..f027305 100644
4693f0
--- a/clock.c
4693f0
+++ b/clock.c
4693f0
@@ -1463,7 +1463,7 @@ struct PortIdentity clock_parent_identity(struct clock *c)
4693f0
 
4693f0
 int clock_poll(struct clock *c)
4693f0
 {
4693f0
-	int cnt, err, i, sde = 0;
4693f0
+	int cnt, i, sde = 0;
4693f0
 	enum fsm_event event;
4693f0
 	struct pollfd *cur;
4693f0
 	struct port *p;
4693f0
@@ -1490,14 +1490,14 @@ int clock_poll(struct clock *c)
4693f0
 	cur++;
4693f0
 	LIST_FOREACH(p, &c->ports, list) {
4693f0
 		/* Let the ports handle their events. */
4693f0
-		for (i = err = 0; i < N_POLLFD && !err; i++) {
4693f0
+		for (i = 0; i < N_POLLFD; i++) {
4693f0
 			if (cur[i].revents & (POLLIN|POLLPRI)) {
4693f0
 				event = port_event(p, i);
4693f0
 				if (EV_STATE_DECISION_EVENT == event)
4693f0
 					sde = 1;
4693f0
 				if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event)
4693f0
 					sde = 1;
4693f0
-				err = port_dispatch(p, event, 0);
4693f0
+				port_dispatch(p, event, 0);
4693f0
 				/* Clear any fault after a little while. */
4693f0
 				if (PS_FAULTY == port_state(p)) {
4693f0
 					clock_fault_timeout(p, 1);
4693f0
diff --git a/port.c b/port.c
4693f0
index 5f1646b..0f99b1b 100644
4693f0
--- a/port.c
4693f0
+++ b/port.c
4693f0
@@ -2143,7 +2143,7 @@ static void port_p2p_transition(struct port *p, enum port_state next)
4693f0
 	};
4693f0
 }
4693f0
 
4693f0
-int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
+void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 {
4693f0
 	enum port_state next;
4693f0
 
4693f0
@@ -2180,7 +2180,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 	}
4693f0
 
4693f0
 	if (next == p->state)
4693f0
-		return 0;
4693f0
+		return;
4693f0
 
4693f0
 	port_show_transition(p, next, event);
4693f0
 
4693f0
@@ -2196,12 +2196,11 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
4693f0
 	if (p->jbod && next == PS_UNCALIBRATED) {
4693f0
 		if (clock_switch_phc(p->clock, p->phc_index)) {
4693f0
 			p->last_fault_type = FT_SWITCH_PHC;
4693f0
-			return port_dispatch(p, EV_FAULT_DETECTED, 0);
4693f0
+			port_dispatch(p, EV_FAULT_DETECTED, 0);
4693f0
+			return;
4693f0
 		}
4693f0
 		clock_sync_interval(p->clock, p->log_sync_interval);
4693f0
 	}
4693f0
-
4693f0
-	return 0;
4693f0
 }
4693f0
 
4693f0
 enum fsm_event port_event(struct port *p, int fd_index)
4693f0
diff --git a/port.h b/port.h
4693f0
index d2e0865..b00bc64 100644
4693f0
--- a/port.h
4693f0
+++ b/port.h
4693f0
@@ -69,10 +69,8 @@ struct foreign_clock *port_compute_best(struct port *port);
4693f0
  * @param port A pointer previously obtained via port_open().
4693f0
  * @param event One of the @a fsm_event codes.
4693f0
  * @param mdiff Whether a new master has been selected.
4693f0
- * @return Zero if the port's file descriptor array is still valid,
4693f0
- *         and non-zero if it has become invalid.
4693f0
  */
4693f0
-int port_dispatch(struct port *p, enum fsm_event event, int mdiff);
4693f0
+void port_dispatch(struct port *p, enum fsm_event event, int mdiff);
4693f0
 
4693f0
 /**
4693f0
  * Generates state machine events based on activity on a port's file