Commit 280580e7 authored by Sven Meier's avatar Sven Meier Committed by Adam Wujek

bmc: more changes

Merged uncalibrated and slave state, added event handling to the individual states,
changed in all states the frame handling to table driven handling,
moved common handling from common to slave since it is actually not common,
fixed state passive to be according to standard,
added uncalibrated handling,
fixed listening and master frame handling,
parent cdf616d8
......@@ -20,7 +20,7 @@ struct pp_state_table_item pp_state_table[] = {
{ PPS_PRE_MASTER, "pre-master", pp_master,},
{ PPS_MASTER, "master", pp_master,},
{ PPS_PASSIVE, "passive", pp_passive,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_uncalibrated,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_slave,},
{ PPS_SLAVE, "slave", pp_slave,},
{ WRS_PRESENT, "uncalibrated/wr-present", wr_present,},
{ WRS_M_LOCK, "master/wr-m-lock", wr_m_lock,},
......
......@@ -10,6 +10,20 @@
#include "wr-api.h"
#include "../proto-standard/common-fun.h"
int wr_slave_execute(struct pp_instance *ppi)
{
int ret = 0;
if (pp_hooks.execute_slave)
ret = pp_hooks.execute_slave(ppi);
if (ret == 1) /* done: just return */
return 0;
if (ret < 0)
return ret;
return 0;
}
/*
* WRS_PRESENT is the entry point for a WR slave
*
......@@ -48,7 +62,7 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (e == 0)
st_com_execute_slave(ppi);
wr_slave_execute(ppi);
else {
/* nothing, just stay here again */
}
......
......@@ -11,7 +11,6 @@ OBJ-y += $D/fsm-table.o \
$D/state-listening.o \
$D/state-master.o \
$D/state-passive.o \
$D/state-uncalibrated.o \
$D/state-slave.o \
$D/common-fun.o \
$D/bmc.o \
......
......@@ -193,7 +193,7 @@ static int bmc_gm_cmp(struct pp_instance *ppi,
return -1;
}
/* if a is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
/* if A is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
if ((qualifiedb >= PP_FOREIGN_MASTER_THRESHOLD)
&& (qualifieda < PP_FOREIGN_MASTER_THRESHOLD)) {
pp_diag(ppi, bmc, 2, "Dataset A not qualified\n");
......@@ -263,7 +263,7 @@ static int bmc_topology_cmp(struct pp_instance *ppi,
return -1;
}
/* if a is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
/* if A is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
if ((qualifiedb >= PP_FOREIGN_MASTER_THRESHOLD)
&& (qualifieda < PP_FOREIGN_MASTER_THRESHOLD)) {
pp_diag(ppi, bmc, 2, "Dataset A not qualified\n");
......@@ -338,6 +338,7 @@ static int bmc_state_decision(struct pp_instance *ppi)
{
int cmpres;
struct pp_frgn_master d0;
struct DSParent *parent = DSPAR(ppi);
struct pp_globals *ppg = GLBS(ppi);
struct pp_instance *ppi_best;
struct pp_frgn_master *erbest = &ppi->frgn_master[ppi->frgn_rec_best];
......@@ -432,18 +433,24 @@ check_boundary_clk:
return PPS_FAULTY;
passive_p1:
p1(ppi);
pp_diag(ppi, bmc, 1, "%s: passive p1\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
return PPS_LISTENING;
p1(ppi);
return PPS_PASSIVE;
passive_p2:
p2(ppi);
pp_diag(ppi, bmc, 1, "%s: passive p2\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
return PPS_LISTENING;
p2(ppi);
return PPS_PASSIVE;
master_m1:
m1(ppi);
pp_diag(ppi, bmc, 1, "%s: master m1\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
return PPS_LISTENING;
m1(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
......@@ -455,8 +462,10 @@ master_m1:
return PPS_MASTER;
master_m2:
m2(ppi);
pp_diag(ppi, bmc, 1, "%s: master m2\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
return PPS_LISTENING;
m2(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
......@@ -468,8 +477,10 @@ master_m2:
return PPS_MASTER;
master_m3:
m3(ppi);
pp_diag(ppi, bmc, 1, "%s: master m3\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
return PPS_LISTENING;
m3(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
......@@ -481,12 +492,31 @@ master_m3:
return PPS_MASTER;
slave_s1:
pp_diag(ppi, bmc, 1, "%s: slave s1\n", __func__);
/* only update parent dataset if best master is on this port */
if (ppi->port_idx == GLBS(ppi)->ebest_idx)
if (ppi->port_idx == GLBS(ppi)->ebest_idx) {
/* check if we have a new master */
cmpres = pidcmp(&parent->parentPortIdentity,
&ebest->hdr.sourcePortIdentity);
s1(ppi, &ebest->hdr, &ebest->ann);
pp_diag(ppi, bmc, 1, "%s: slave s1\n", __func__);
return PPS_SLAVE;
} else {
/* set that to zero in the case we don't have the master master
* on that port */
cmpres = 0;
}
/* if we are not comming from the slave state we go to uncalibrated
* first */
if (ppi->state != PPS_SLAVE) {
return PPS_UNCALIBRATED;
} else {
/* if the master changed we go to uncalibrated*/
if (cmpres) {
pp_diag(ppi, bmc, 1,
"new master, change to uncalibrated\n");
return PPS_UNCALIBRATED;
} else
return PPS_SLAVE;
}
}
static void bmc_age_frgn_master(struct pp_instance *ppi)
......
......@@ -71,69 +71,6 @@ void pp_prepare_pointers(struct pp_instance *ppi)
}
}
/* Called by listening, passive, slave, uncalibrated */
int st_com_execute_slave(struct pp_instance *ppi)
{
int ret = 0;
if (pp_hooks.execute_slave)
ret = pp_hooks.execute_slave(ppi);
if (ret == 1) /* done: just return */
return 0;
if (ret < 0)
return ret;
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)
|| pp_timeout(ppi, PP_TO_FAULT)) {
/*
* Note: TO_FAULTY == SYNCHRONIZATION_FAULT
* should move us to UNCALIBRATED (not implemented)
*/
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
return 0;
}
/* Called by slave and uncalibrated */
int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgHeader *hdr = &ppi->received_ptp_header;
MsgSync sync;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT))
return 0;
/* t2 may be overriden by follow-up, save it immediately */
ppi->t2 = ppi->last_rcv_time;
msg_unpack_sync(buf, &sync);
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0) {
ppi->flags |= PPI_FLAG_WAITING_FOR_F_UP;
ppi->recv_sync_sequence_id = hdr->sequenceId;
/* for two-step, the stamp comes later */
ppi->t1 = hdr->cField; /* most likely 0 */
return 0;
}
/* one-step folllows */
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
ppi->t1 = sync.originTimestamp;
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
static int presp_call_servo(struct pp_instance *ppi)
{
int ret = 0;
......@@ -192,7 +129,6 @@ int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
return e;
}
int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
unsigned char *buf, int plen)
{
......@@ -239,67 +175,6 @@ int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
return 0;
}
/* Called by slave and uncalibrated */
int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgFollowUp follow;
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
pp_error("%s: Follow up message is not from current parent\n",
__func__);
return 0;
}
if (!(ppi->flags & PPI_FLAG_WAITING_FOR_F_UP)) {
pp_error("%s: Slave was not waiting a follow up message\n",
__func__);
return 0;
}
if (ppi->recv_sync_sequence_id != hdr->sequenceId) {
pp_error("%s: SequenceID %d doesn't match last Sync message %d\n",
__func__, hdr->sequenceId, ppi->recv_sync_sequence_id);
return 0;
}
msg_unpack_follow_up(buf, &follow);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
/* t1 for calculations is T1 + Csyn + Cful -- see README-cfield */
pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp);
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */
/* Call the extension; it may do it all and ask to return */
if (pp_hooks.handle_followup)
ret = pp_hooks.handle_followup(ppi, &ppi->t1);
if (ret == 1)
return 0;
if (ret < 0)
return ret;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
/*
* Called by master, listenting, passive.
* FIXME: this must be implemented to support one-step masters
*/
int st_com_master_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len)
{
/* No more used: follow up is sent right after the corresponding sync */
return 0;
}
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype)
{
int msgtype = ((char *)ppi->tx_ptp)[0] & 0xf;
......
......@@ -13,22 +13,6 @@
/* Contains all functions common to more than one state */
/* returns -1 in case of error, see below */
int st_com_execute_slave(struct pp_instance *ppi);
/* Each of the following "handle" functions" return 0 in case of correct
* message, -1 in case the message contained in buf is not proper (e.g. size
* is not the expected one
*/
int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_master_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
int len);
......
......@@ -21,7 +21,7 @@ struct pp_state_table_item pp_state_table[] __attribute__((weak)) = {
{ PPS_PRE_MASTER, "pre-master", pp_master,},
{ PPS_MASTER, "master", pp_master,},
{ PPS_PASSIVE, "passive", pp_passive,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_uncalibrated,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_slave,},
{ PPS_SLAVE, "slave", pp_slave,},
{ PPS_END_OF_TABLE,}
};
......@@ -9,9 +9,24 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
/* skip signaling and management, for binary size */
};
int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we listen */
if (pp_hooks.listening)
......@@ -19,48 +34,36 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (e)
goto out;
/* when the clock is using peer-delay, listening must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
switch (ppi->received_ptp_header.messageType) {
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
if (CONFIG_HAS_P2P)
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_R_FUP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres_followup(ppi, pkt, plen);
break;
/*
* The management of messages is now table-driven
*/
if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, pkt, plen);
} else {
if (plen)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
default:
/* disregard, nothing to do */
break;
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
out:
if (e == 0)
e = st_com_execute_slave(ppi);
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
out:
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_ANN_RECEIPT);
return 0;
return e;
}
......@@ -13,7 +13,7 @@ static int master_handle_delay_request(struct pp_instance *ppi,
unsigned char *pkt, int plen);
static pp_action *actions[] = {
[PPM_SYNC] = st_com_master_handle_sync,
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = master_handle_delay_request,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
......@@ -44,6 +44,9 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
int pre = (ppi->state == PPS_PRE_MASTER);
int e = 0; /* error var, to check errors in msg handling */
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
* passive */
/* upgrade from pre-master to master */
if (pre && pp_timeout(ppi, PP_TO_QUALIFICATION)) {
ppi->next_state = PPS_MASTER;
......@@ -96,6 +99,9 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
msgtype);
}
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
out:
switch(e) {
case PP_SEND_OK: /* 0 */
......
......@@ -9,53 +9,61 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
/* skip signaling and management, for binary size */
};
int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
* passive */
/* when the clock is using peer-delay, listening must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
switch (ppi->received_ptp_header.messageType) {
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
if (CONFIG_HAS_P2P)
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_R_FUP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres_followup(ppi, pkt, plen);
break;
default:
/* disreguard, nothing to do */
break;
/*
* The management of messages is now table-driven
*/
if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, pkt, plen);
} else {
if (plen)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
if (e == 0)
e = st_com_execute_slave(ppi);
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
if (e != 0) {
/* ignore: a lost frame is not the end of the world */
}
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_ANN_RECEIPT);
return 0;
return e;
}
......@@ -11,24 +11,109 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen);
int slave_handle_sync(struct pp_instance *ppi, unsigned char *buf, int len);
int slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len);
int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen);
static pp_action *actions[] = {
[PPM_SYNC] = st_com_slave_handle_sync,
[PPM_SYNC] = slave_handle_sync,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = st_com_slave_handle_followup,
[PPM_FOLLOW_UP] = slave_handle_followup,
[PPM_DELAY_RESP] = slave_handle_response,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
/* skip signaling and management, for binary size */
};
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgHeader *hdr = &ppi->received_ptp_header;
MsgSync sync;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT))
return 0;
/* t2 may be overriden by follow-up, save it immediately */
ppi->t2 = ppi->last_rcv_time;
msg_unpack_sync(buf, &sync);
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0) {
ppi->flags |= PPI_FLAG_WAITING_FOR_F_UP;
ppi->recv_sync_sequence_id = hdr->sequenceId;
/* for two-step, the stamp comes later */
ppi->t1 = hdr->cField; /* most likely 0 */
return 0;
}
/* one-step folllows */
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
ppi->t1 = sync.originTimestamp;
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
int slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgFollowUp follow;
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
pp_error("%s: Follow up message is not from current parent\n",
__func__);
return 0;
}
if (!(ppi->flags & PPI_FLAG_WAITING_FOR_F_UP)) {
pp_error("%s: Slave was not waiting a follow up message\n",
__func__);
return 0;
}
if (ppi->recv_sync_sequence_id != hdr->sequenceId) {
pp_error("%s: SequenceID %d doesn't match last Sync message "
"%d\n", __func__,
hdr->sequenceId, ppi->recv_sync_sequence_id);
return 0;
}
msg_unpack_follow_up(buf, &follow);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
/* t1 for calculations is T1 + Csyn + Cful -- see README-cfield */
pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp);
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */
/* Call the extension; it may do it all and ask to return */
if (pp_hooks.handle_followup)
ret = pp_hooks.handle_followup(ppi, &ppi->t1);
if (ret == 1)
return 0;
if (ret < 0)
return ret;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen)
{
int e = 0;
......@@ -73,12 +158,44 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
return 0;
}
int slave_execute(struct pp_instance *ppi)
{
int ret = 0;
if (pp_hooks.execute_slave)
ret = pp_hooks.execute_slave(ppi);
if (ret == 1) /* done: just return */
return 0;
if (ret < 0)
return ret;
return 0;
}
/*
* SLAVE and UNCALIBRATED have many things in common. This function implements
* both states. We set "uncalibrated" internally to 0 or 1.
*/
int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
int uncalibrated = (ppi->state == PPS_UNCALIBRATED);
MsgHeader *hdr = &ppi->received_ptp_header;
if (ppi->is_new_state) {
/* upgrade from uncalibrated to slave or back*/
if (uncalibrated) {
/* TODO add implementation specific MASTER_CLOCK_SELECTED event
for now just change directly to new state on next round */
ppi->next_state = PPS_SLAVE;
} else {
/* TODO add implementation specific SYNCHRONIZATION FAULT
* event */
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_UNCALIBRATED;
}
/* when entering uncalibrated init servo */
if ((ppi->state == PPS_UNCALIBRATED) && (ppi->is_new_state)) {
memset(&ppi->t1, 0, sizeof(ppi->t1));
pp_servo_init(ppi);
......@@ -103,10 +220,20 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
/*
* This function, common to passive,listening etc,
* is the core of the slave: timeout ann-receipt, hook
* This function, common to uncalibrated and slave,
* is the core of the slave: hook
*/
e = st_com_execute_slave(ppi);
e = slave_execute(ppi);
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
out:
switch(e) {
......@@ -121,7 +248,8 @@ out:
break;
}
if (ppi->next_state != ppi->state) {
if ((ppi->next_state == PPS_UNCALIBRATED)
&& (ppi->next_state != ppi->state)) {
pp_servo_init(ppi);
return e;
}
......
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Aurelio Colosimo
* Based on PTPd project v. 2.1.0 (see AUTHORS for details)
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#include "common-fun.h"
int pp_uncalibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
switch (ppi->received_ptp_header.messageType) {
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_slave_handle_sync(ppi, pkt, plen);
break;
case PPM_FOLLOW_UP:
e = st_com_slave_handle_followup(ppi, pkt, plen);
break;
default:
/* disreguard, nothing to do */
break;
}
if (e == 0)
e = st_com_execute_slave(ppi);
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
return 0;
}
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