Fix the port finite state machine.

The state machine needs to know whether a new master has just been
selected in order to choose between the slave and uncalibrated states.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2012-01-06 21:12:50 +01:00
parent c2fad7bd51
commit 222c9bb62b
5 changed files with 26 additions and 16 deletions

12
clock.c
View File

@ -230,7 +230,7 @@ struct clock *clock_create(char *phc, struct interface *iface, int count,
c->dds.numberPorts = c->nports = count;
for (i = 0; i < c->nports; i++)
port_dispatch(c->port[i], EV_INITIALIZE);
port_dispatch(c->port[i], EV_INITIALIZE, 0);
return c;
}
@ -322,7 +322,7 @@ int clock_poll(struct clock *c)
if (EV_STATE_DECISION_EVENT == event)
sde = 1;
else
port_dispatch(c->port[i], event);
port_dispatch(c->port[i], event, 0);
}
}
}
@ -435,7 +435,7 @@ struct timePropertiesDS *clock_time_properties(struct clock *c)
static void handle_state_decision_event(struct clock *c)
{
struct foreign_clock *best = NULL, *fc;
int i;
int fresh_best = 0, i;
for (i = 0; i < c->nports; i++) {
fc = port_compute_best(c->port[i]);
@ -451,8 +451,10 @@ static void handle_state_decision_event(struct clock *c)
pr_notice("selected best master clock %s",
cid2str(&best->dataset.identity));
if (c->best != best)
if (c->best != best) {
mave_reset(c->avg_delay);
fresh_best = 1;
}
c->best = best;
@ -482,6 +484,6 @@ static void handle_state_decision_event(struct clock *c)
event = EV_INITIALIZE;
break;
}
port_dispatch(c->port[i], event);
port_dispatch(c->port[i], event, fresh_best);
}
}

11
fsm.c
View File

@ -18,7 +18,7 @@
*/
#include "fsm.h"
enum port_state ptp_fsm(enum port_state state, enum fsm_event event)
enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff)
{
enum port_state next = state;
@ -195,7 +195,8 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event)
next = PS_GRAND_MASTER;
break;
case EV_RS_SLAVE:
next = PS_UNCALIBRATED;
if (mdiff)
next = PS_UNCALIBRATED;
break;
case EV_RS_PASSIVE:
next = PS_PASSIVE;
@ -209,7 +210,8 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event)
return next;
}
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event)
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
int mdiff)
{
enum port_state next = state;
@ -301,7 +303,8 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event)
next = PS_UNCALIBRATED;
break;
case EV_RS_SLAVE:
next = PS_UNCALIBRATED;
if (mdiff)
next = PS_UNCALIBRATED;
break;
default:
break;

7
fsm.h
View File

@ -58,16 +58,19 @@ enum fsm_event {
* Run the state machine for a BC or OC port.
* @param state The current state of the port.
* @param event The event to be processed.
* @param mdiff Whether a new master has been selected.
* @return The new state for the port.
*/
enum port_state ptp_fsm(enum port_state state, enum fsm_event event);
enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff);
/**
* Run the state machine for a slave only clock.
* @param state The current state of the port.
* @param event The event to be processed.
* @param mdiff Whether a new master has been selected.
* @return The new state for the port.
*/
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event);
enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event,
int mdiff);
#endif

9
port.c
View File

@ -311,10 +311,10 @@ static void port_synchronize(struct port *p,
switch (state) {
case SERVO_UNLOCKED:
case SERVO_JUMP:
port_dispatch(p, EV_SYNCHRONIZATION_FAULT);
port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0);
break;
case SERVO_LOCKED:
port_dispatch(p, EV_MASTER_CLOCK_SELECTED);
port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0);
break;
}
}
@ -794,10 +794,11 @@ struct foreign_clock *port_compute_best(struct port *p)
return p->best;
}
void port_dispatch(struct port *p, enum fsm_event event)
void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
{
enum port_state next = clock_slave_only(p->clock) ?
ptp_slave_fsm(p->state, event) : ptp_fsm(p->state, event);
ptp_slave_fsm(p->state, event, mdiff) :
ptp_fsm(p->state, event, mdiff);
if (PS_INITIALIZING == next) {
/*

3
port.h
View File

@ -69,8 +69,9 @@ struct foreign_clock *port_compute_best(struct port *port);
*
* @param port A pointer previously obtained via port_open().
* @param event One of the @a fsm_event codes.
* @param mdiff Whether a new master has been selected.
*/
void port_dispatch(struct port *port, enum fsm_event event);
void port_dispatch(struct port *p, enum fsm_event event, int mdiff);
/**
* Generates state machine events based on activity on a port's file