Commit 420da467 authored by Jean-Claude BAU's avatar Jean-Claude BAU

Improve behavior when link up->down->up not detected.

When the link state changes rapidly, it can't be detected by PPSi. This
is the case with the BTrain configuration. So we must detect that the
peer has changed and restart the servo for a slave and use the right
protocol (extension/ptp).
parent 0e5b8817
......@@ -52,7 +52,7 @@ int wrs_update_port_info(struct pp_globals *ppg) {
pSlot->synchronized=
SRV(ppi)->servo_locked &&
(ppi->protocol_extension==PPSI_EXT_WR || ppi->protocol_extension==PPSI_EXT_L1S) &&
ppi->ext_enabled;
ppi->extState==PP_EXSTATE_ACTIVE;
} else {
if ( ppi->state==PPS_MASTER && pSlot->mode!=PORT_MODE_SLAVE ) {
pSlot->mode=PORT_MODE_MASTER;
......
......@@ -300,7 +300,7 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
return pp_leave_current_state(ppi);
/* Check protocol state */
if ( ppi->ext_enabled &&
if ( ppi->extState==PP_EXSTATE_ACTIVE &&
(ppi->pdstate==PP_PDSTATE_PDETECTION || ppi->pdstate==PP_PDSTATE_PDETECTED) &&
pp_timeout(ppi, PP_TO_PROT_STATE) ) {
pdstate_disable_extension(ppi);
......
......@@ -199,6 +199,12 @@ typedef enum {
PP_PDSTATE_FAILURE, /* Impossible to connect correctly to a peer instance - extension disabled */
} pp_pdstate_t;
typedef enum {
PP_EXSTATE_DISABLE, /* Extension is disabled */
PP_EXSTATE_ACTIVE, /* Extension active */
PP_EXSTATE_PTP /* Extension uses only PTP protocol */
} pp_exstate_t;
/*
* Structure for the individual ppsi link
*/
......@@ -279,9 +285,9 @@ struct pp_instance {
Boolean received_dresp; /* Count the number of delay response messages received for a given delay request */
Boolean received_dresp_fup; /* Count the number of delay response follow up messages received for a given delay request */
Boolean ptp_support; /* True if allow pure PTP support */
Boolean ext_enabled; /* True if the extension is enabled */
pp_pdstate_t pdstate; /* Protocol detection state */
Boolean bmca_execute; /* True: Ask fsm to run bmca state decision */
pp_pdstate_t pdstate; /* Protocol detection state */
pp_exstate_t extState; /* Extension state */
};
/* The following things used to be bit fields. Other flags are now enums */
......
......@@ -219,6 +219,7 @@ struct pp_ext_hooks {
/* If the extension requires hardware support for precise time stamp, returns 1 */
int (*require_precise_timestamp)(struct pp_instance *ppi);
int (*get_tmo_lstate_detection) (struct pp_instance *ppi);
int (*extension_state_changed)(struct pp_instance *ppi); /* Called when extension state as changed */
};
#define is_ext_hook_available(p, c) ( /*p->ext_enabled && */ p->ext_hooks->c)
......@@ -442,9 +443,12 @@ extern int ppsi_drop_tx(void);
/* link state functions to manage the extension (Enable/disable) */
static inline void pdstate_disable_extension(struct pp_instance * ppi) {
ppi->pdstate=PP_PDSTATE_FAILURE;
if ( ppi->ptp_support && ppi->ext_enabled) {
ppi->ext_enabled=FALSE;
if ( ppi->extState==PP_EXSTATE_ACTIVE) {
if ( ppi->ptp_support )
ppi->extState=ppi->ptp_support ? PP_EXSTATE_PTP : PP_EXSTATE_DISABLE;
pp_servo_init(ppi); // Reinitialize the servo
if ( is_ext_hook_available(ppi,extension_state_changed) )
ppi->ext_hooks->extension_state_changed(ppi);
}
}
......@@ -467,7 +471,11 @@ static inline void pdstate_enable_extension(struct pp_instance * ppi) {
if (ppi->pdstate != PP_PDSTATE_NONE ) {
ppi->pdstate=PP_PDSTATE_PDETECTED;
pp_timeout_reset(ppi,PP_TO_PROT_STATE);
ppi->ext_enabled=TRUE;
if ( ppi->extState!=PP_EXSTATE_ACTIVE ) {
ppi->extState=PP_EXSTATE_ACTIVE;
if ( is_ext_hook_available(ppi,extension_state_changed) )
ppi->ext_hooks->extension_state_changed(ppi);
}
}
}
......
......@@ -105,7 +105,7 @@ int wrh_servo_init(struct pp_instance *ppi)
void wrh_servo_reset(struct pp_instance *ppi)
{
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
ppi->flags = 0;
......
......@@ -49,7 +49,7 @@ static int wr_handle_resp(struct pp_instance *ppi)
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
/* This correction_field we received is already part of t4 */
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
wr_servo_got_resp(ppi);
if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
......@@ -63,7 +63,7 @@ static int wr_handle_resp(struct pp_instance *ppi)
static int wr_handle_dreq(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
}
......@@ -71,11 +71,9 @@ static int wr_handle_dreq(struct pp_instance *ppi)
return 0;
}
static int wr_sync_followup(struct pp_instance *ppi) {
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
wr_servo_got_sync(ppi);
}
else {
......@@ -100,7 +98,7 @@ static int wr_handle_followup(struct pp_instance *ppi)
static int wr_handle_presp(struct pp_instance *ppi)
{
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
wr_servo_got_presp(ppi);
if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
......@@ -124,15 +122,18 @@ static int wr_pack_announce(struct pp_instance *ppi)
static void wr_unpack_announce(struct pp_instance *ppi,void *buf, MsgAnnounce *ann)
{
int msg_len = ntohs(*(UInteger16 *) (buf + 2));
Boolean parentIsWRnode=FALSE;
Boolean resetWrProtocol=FALSE;
int slaveUncalState=ppi->state==PPS_UNCALIBRATED || ppi->state==PPS_SLAVE;
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(NULL, ext, 2, "hook: %s\n", __func__);
if (msg_len >= WR_ANNOUNCE_LENGTH) {
UInteger16 wr_flags;
Boolean parentIsWRnode;
struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgHeader *hdr = &ppi->received_ptp_header;
struct PortIdentity *pid = &hdr->sourcePortIdentity;
msg_unpack_announce_wr_tlv(buf, ann, &wr_flags);
parentIsWRnode=(wr_flags & WR_NODE_MODE)!=NON_WR;
......@@ -142,9 +143,7 @@ static void wr_unpack_announce(struct pp_instance *ppi,void *buf, MsgAnnounce *a
// - Same parent port ID but with a not continuous sequence ID (With a margin of 1)
// - The port identity is different
if ( parentIsWRnode &&
(ppi->state==PPS_SLAVE ||
ppi->state==PPS_UNCALIBRATED ||
ppi->state==PPS_LISTENING)) {
(slaveUncalState || ppi->state==PPS_LISTENING)) {
Boolean samePid=!bmc_pidcmp(pid, &wrp->parentAnnPortIdentity);
if ( !samePid ||
......@@ -152,15 +151,13 @@ static void wr_unpack_announce(struct pp_instance *ppi,void *buf, MsgAnnounce *a
(hdr->sequenceId!=wrp->parentAnnSequenceId+1 &&
hdr->sequenceId!=wrp->parentAnnSequenceId+2)
)) {
if ( ppi->state==PPS_UNCALIBRATED && wrp->state==WRS_IDLE) {
/* For other states, it is done in the state_change hook */
wrp->next_state=WRS_PRESENT;
wrp->wrMode=WR_SLAVE;
}
resetWrProtocol=slaveUncalState;
pdstate_enable_extension(ppi);
}
} else {
parentIsWRnode=FALSE;
resetWrProtocol=ppi->extState==PP_EXSTATE_ACTIVE && slaveUncalState;
}
memcpy(&wrp->parentAnnPortIdentity,pid,sizeof(struct PortIdentity));
......@@ -174,6 +171,14 @@ static void wr_unpack_announce(struct pp_instance *ppi,void *buf, MsgAnnounce *a
wrp->parentWrModeOn = (wr_flags & WR_IS_WR_MODE) != 0;
wrp->parentCalibrated =(wr_flags & WR_IS_CALIBRATED) != 0;
wrp->parentWrConfig = wr_flags & WR_NODE_MODE;
} else {
resetWrProtocol=ppi->extState==PP_EXSTATE_ACTIVE && slaveUncalState;
}
if ( resetWrProtocol ) {
ppi->state=PPS_UNCALIBRATED;
wrp->next_state=WRS_PRESENT;
wrp->wrMode=WR_SLAVE;
}
}
......@@ -182,7 +187,7 @@ static void wr_state_change(struct pp_instance *ppi)
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
// Check leaving state
if ( wrp->wrModeOn &&
......@@ -220,7 +225,7 @@ static void wr_state_change(struct pp_instance *ppi)
}
int wr_ready_for_slave(struct pp_instance *ppi) {
if ( ppi->ext_enabled ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
struct wr_dsport *wrp = WR_DSPOR(ppi);
return wrp->wrModeOn && wrp->parentWrModeOn && wrp->state == WRS_IDLE;
} else
......@@ -229,7 +234,7 @@ int wr_ready_for_slave(struct pp_instance *ppi) {
static int wr_require_precise_timestamp(struct pp_instance *ppi) {
return ppi->ext_enabled && WR_DSPOR(ppi)->wrModeOn;
return ppi->extState==PP_EXSTATE_ACTIVE && WR_DSPOR(ppi)->wrModeOn;
}
static int wr_get_tmo_lstate_detection(struct pp_instance *ppi) {
......@@ -251,6 +256,14 @@ static TimeInterval wr_get_latency (struct pp_instance *ppi) {
static int wr_is_correction_field_compliant (struct pp_instance *ppi) {
return 0;
}
static int wr_extension_state_changed( struct pp_instance * ppi) {
if ( ppi->extState==PP_EXSTATE_DISABLE || ppi->extState==PP_EXSTATE_PTP) {
wr_reset_process(ppi,WR_ROLE_NONE);
}
return 0;
}
struct pp_ext_hooks wr_ext_hooks = {
.init = wr_init,
.open = wr_open,
......@@ -272,4 +285,5 @@ struct pp_ext_hooks wr_ext_hooks = {
.get_ingress_latency=wr_get_latency,
.get_egress_latency=wr_get_latency,
.is_correction_field_compliant=wr_is_correction_field_compliant,
.extension_state_changed= wr_extension_state_changed
};
......@@ -35,7 +35,7 @@ int wr_idle(struct pp_instance *ppi, void *buf, int len, int new_state)
}
}
} else {
if ( ppi->ext_enabled && ppi->state==PPS_SLAVE ) {
if ( ppi->extState==PP_EXSTATE_ACTIVE && ppi->state==PPS_SLAVE ) {
if ( !(wrp->wrModeOn && wrp->parentWrModeOn) ) {
/* Failure detected in the protocol */
ppi->next_state=PPS_UNCALIBRATED;
......
......@@ -210,7 +210,7 @@ int msg_unpack_wrsig(struct pp_instance *ppi, void *buf,
if (tlv_type != TLV_TYPE_ORG_EXTENSION) {
pp_diag(ppi, frames, 1, "handle Signaling msg, failed, This is not "
"organization extension TLV = 0x%x\n", tlv_type);
return 1;
return 0;
}
if (tlv_organizationID != WR_TLV_ORGANIZATION_ID) {
......
......@@ -72,7 +72,7 @@ int wr_run_state_machine(struct pp_instance *ppi, void *buf, int len) {
Boolean newState;
int delay;
if ( wrp->next_state>=MAX_STATE_ACTIONS || ppi->state==PPS_INITIALIZING || !ppi->ext_enabled ) {
if ( wrp->next_state>=MAX_STATE_ACTIONS || ppi->state==PPS_INITIALIZING || !(ppi->extState==PP_EXSTATE_ACTIVE)) {
wrp->next_state=WRS_IDLE; // Force to IDLE state
}
......
......@@ -120,7 +120,7 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
pp_timeout_setall(ppi);
ppi->pdstate = PP_PDSTATE_NONE; // Default value for PTP. Can be overwritten in specific init
ppi->ext_enabled=(ppi->protocol_extension!=PPSI_EXT_NONE);
ppi->extState=(ppi->protocol_extension==PPSI_EXT_NONE) ? PP_EXSTATE_DISABLE : PP_EXSTATE_ACTIVE;
if (is_ext_hook_available(ppi,init))
ret = ppi->ext_hooks->init(ppi, buf, len);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment