clock: Force a BMC election when a port link goes down.

Having one fewer port may affect the result of the BMCA.  This patch
changes the main loop so that a link down event also causes a state
decision event.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Henry Jesuiter <Henry.Jesuiter@alcnetworx.de>
master
Richard Cochran 2017-02-05 18:31:27 +01:00
parent 6b471d45ed
commit 73318c5b99
1 changed files with 13 additions and 6 deletions

19
clock.c
View File

@ -96,6 +96,7 @@ struct clock {
int pollfd_valid; int pollfd_valid;
int nports; /* does not include the UDS port */ int nports; /* does not include the UDS port */
int last_port_number; int last_port_number;
int sde;
struct hash *index2port; struct hash *index2port;
int free_running; int free_running;
int freq_est_interval; int freq_est_interval;
@ -341,6 +342,11 @@ static void clock_link_status(void *ctx, int index, int linkup)
port_dispatch(p, EV_FAULT_CLEARED, 0); port_dispatch(p, EV_FAULT_CLEARED, 0);
} else { } else {
port_dispatch(p, EV_FAULT_DETECTED, 0); port_dispatch(p, EV_FAULT_DETECTED, 0);
/*
* A port going down can affect the BMCA result.
* Force a state decision event.
*/
c->sde = 1;
} }
} }
@ -1463,7 +1469,7 @@ struct PortIdentity clock_parent_identity(struct clock *c)
int clock_poll(struct clock *c) int clock_poll(struct clock *c)
{ {
int cnt, i, sde = 0; int cnt, i;
enum fsm_event event; enum fsm_event event;
struct pollfd *cur; struct pollfd *cur;
struct port *p; struct port *p;
@ -1494,9 +1500,9 @@ int clock_poll(struct clock *c)
if (cur[i].revents & (POLLIN|POLLPRI)) { if (cur[i].revents & (POLLIN|POLLPRI)) {
event = port_event(p, i); event = port_event(p, i);
if (EV_STATE_DECISION_EVENT == event) if (EV_STATE_DECISION_EVENT == event)
sde = 1; c->sde = 1;
if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event) if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event)
sde = 1; c->sde = 1;
port_dispatch(p, event, 0); port_dispatch(p, event, 0);
/* Clear any fault after a little while. */ /* Clear any fault after a little while. */
if (PS_FAULTY == port_state(p)) { if (PS_FAULTY == port_state(p)) {
@ -1525,13 +1531,14 @@ int clock_poll(struct clock *c)
if (cur[i].revents & (POLLIN|POLLPRI)) { if (cur[i].revents & (POLLIN|POLLPRI)) {
event = port_event(c->uds_port, i); event = port_event(c->uds_port, i);
if (EV_STATE_DECISION_EVENT == event) if (EV_STATE_DECISION_EVENT == event)
sde = 1; c->sde = 1;
} }
} }
if (sde) if (c->sde) {
handle_state_decision_event(c); handle_state_decision_event(c);
c->sde = 0;
}
clock_prune_subscriptions(c); clock_prune_subscriptions(c);
return 0; return 0;
} }