Commit 53cb49ff authored by Sven Meier's avatar Sven Meier Committed by Adam Wujek

bmc: timeouts fixe and announce handling changed

Message handling for the case of received back frames changed and timeouts for announces reset according to standard
parent e1e3935d
......@@ -138,22 +138,21 @@ static int pp_packet_prefilter(struct pp_instance *ppi)
}
/*
* 9.5.2.3: if an announce message comes from another port of the same
* clock, switch all the ports but the lowest numbered one to
* PASSIVE. Since all involved ports will see each other's announce,
* we just switch __this__ instance's port's status to PASSIVE if we
* need to.
*/
if (hdr->messageType == PPM_ANNOUNCE &&
!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSPOR(ppi)->portIdentity.clockIdentity,
sizeof(ClockIdentity))) {
if (hdr->sourcePortIdentity.portNumber <
DSPOR(ppi)->portIdentity.portNumber)
ppi->next_state = PPS_PASSIVE;
return -1;
* 9.5.2.3 & 9.5.2.2: For BCs the BMC (an extention to it)
* handles the Announce (go to Passive), other messages are dropped
*/
if (!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSPOR(ppi)->portIdentity.clockIdentity,
sizeof(ClockIdentity))) {
if (DSDEF(ppi)->numberPorts > 1) {
/* Announces are handled by the BMC, since otherwise the state is overwritten */
if (hdr->messageType != PPM_ANNOUNCE) {
/* ignore messages, except announce coming from its own clock */
return -1;
}
}
}
return 0;
}
......
......@@ -190,6 +190,17 @@ static int wr_handle_announce(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ((ppi->state == WRS_PRESENT) ||
(ppi->state == WRS_S_LOCK) ||
(ppi->state == WRS_LOCKED) ||
(ppi->state == WRS_CALIBRATION) ||
(ppi->state == WRS_CALIBRATED) ||
(ppi->state == WRS_RESP_CALIB_REQ) ||
(ppi->state == WRS_WR_LINK_ON)) {
/* reset announce timeout when in the WR slave states */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
/* handshake is started in slave mode */
return 0;
}
......
......@@ -460,7 +460,7 @@ static int bmc_state_decision(struct pp_instance *ppi)
if (!bmc_idcmp(&erbest->hdr.sourcePortIdentity.clockIdentity, &DSDEF(ppi)->clockIdentity)) {
/* is this port worse than the other */
cmpres = bmc_pidcmp(&erbest->hdr.sourcePortIdentity, &DSPOR(ppi)->portIdentity);
if (cmpres > 0)
if (cmpres < 0)
goto passive_p1;
}
}
......@@ -505,27 +505,45 @@ check_boundary_clk:
passive_p1:
pp_diag(ppi, bmc, 1, "%s: passive p1\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_LISTENING)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_LISTENING;
}
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_PASSIVE)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
bmc_p1(ppi);
return PPS_PASSIVE;
passive_p2:
pp_diag(ppi, bmc, 1, "%s: passive p2\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_LISTENING)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_LISTENING;
}
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_PASSIVE)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
bmc_p2(ppi);
return PPS_PASSIVE;
master_m1:
pp_diag(ppi, bmc, 1, "%s: master m1\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_LISTENING)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_LISTENING;
}
bmc_m1(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* 9.2.6.11 a) timeout 0 */
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
}
return PPS_PRE_MASTER;
......@@ -534,13 +552,17 @@ master_m1:
master_m2:
pp_diag(ppi, bmc, 1, "%s: master m2\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_LISTENING)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_LISTENING;
}
bmc_m2(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* 9.2.6.11 a) timeout 0 */
/* 9.2.6.10 a) timeout 0 */
pp_timeout_clear(ppi, PP_TO_QUALIFICATION);
}
return PPS_PRE_MASTER;
......@@ -549,13 +571,19 @@ master_m2:
master_m3:
pp_diag(ppi, bmc, 1, "%s: master m3\n", __func__);
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY)
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_LISTENING)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_LISTENING;
}
bmc_m3(ppi);
if (ppi->state != PPS_MASTER) {
/* if not already in pre master state start qualification */
if (ppi->state != PPS_PRE_MASTER) {
/* 9.2.6.11 b) timeout steps removed+1 */
/* timeout reinit */
pp_timeout_init(ppi);
/* 9.2.6.11 b) timeout steps removed+1*/
pp_timeout_set(ppi, PP_TO_QUALIFICATION);
}
return PPS_PRE_MASTER;
......@@ -577,16 +605,26 @@ slave_s1:
}
/* if we are not comming from the slave state we go to uncalibrated
* first */
if (ppi->state != PPS_SLAVE) {
if ((ppi->state != PPS_SLAVE) &&
(ppi->state != PPS_UNCALIBRATED)) {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
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");
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_UNCALIBRATED)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_UNCALIBRATED;
} else
} else {
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_SLAVE)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
return PPS_SLAVE;
}
}
}
......
......@@ -120,6 +120,13 @@ static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
/* if we are a configured master don't add*/
if (ppi->role == PPSI_ROLE_MASTER)
return;
/* if in DISABLED, INITIALIZING or FAULTY ignore announce */
if ((ppi->state == PPS_DISABLED) ||
(ppi->state == PPS_FAULTY) ||
(ppi->state == PPS_INITIALIZING))
return;
/*
* header and announce field of each Foreign Master are
* useful to run Best Master Clock Algorithm
......@@ -144,7 +151,7 @@ static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
*/
if (!memcmp(&hdr->sourcePortIdentity,
&DSPOR(ppi)->portIdentity,
sizeof(DSPOR(ppi)->portIdentity))) {
sizeof(PortIdentity))) {
pp_diag(ppi, bmc, 2, "Announce frame from this port\n");
return;
}
......@@ -152,7 +159,7 @@ static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
/* Check if announce from a port from this clock 9.3.2.5 a) */
if (!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSDEF(ppi)->clockIdentity,
sizeof(DSDEF(ppi)->clockIdentity))) {
sizeof(ClockIdentity))) {
pp_diag(ppi, bmc, 2, "Announce frame from this clock\n");
return;
}
......@@ -170,7 +177,7 @@ static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
for (i = 0; i < ppi->frgn_rec_num; i++) {
if (!memcmp(&hdr->sourcePortIdentity,
&ppi->frgn_master[i].port_id,
sizeof(hdr->sourcePortIdentity))) {
sizeof(PortIdentity))) {
pp_diag(ppi, bmc, 2, "Foreign Master %i updated\n", i);
......
......@@ -47,12 +47,13 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happended */
pp_timeout_set(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);
}
}
......
......@@ -9,6 +9,8 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static int passive_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
......@@ -19,10 +21,33 @@ static pp_action *actions[] = {
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
[PPM_ANNOUNCE] = passive_handle_announce,
/* skip signaling and management, for binary size */
};
static int passive_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len)
{
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
struct pp_frgn_master *erbest = &ppi->frgn_master[ppi->frgn_rec_best];
ret = pp_lib_handle_announce(ppi, buf, len);
if (ret)
return ret;
if (!memcmp(&hdr->sourcePortIdentity,
&erbest->port_id,
sizeof(PortIdentity))) {
/*
* 9.2.6.11 d) reset timeout when an announce
* is received from the clock putting it into passive (erbest)
*/
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
return 0;
}
int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
......@@ -48,12 +73,13 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happended */
pp_timeout_set(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);
}
}
......
......@@ -14,8 +14,9 @@
static int slave_handle_sync(struct pp_instance *ppi, unsigned char *buf, int len);
static int slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len);
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen);
static int slave_handle_response(struct pp_instance *ppi, unsigned char *buf,
int len);
static int slave_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = slave_handle_sync,
......@@ -27,7 +28,7 @@ static pp_action *actions[] = {
#endif
[PPM_FOLLOW_UP] = slave_handle_followup,
[PPM_DELAY_RESP] = slave_handle_response,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
[PPM_ANNOUNCE] = slave_handle_announce,
/* skip signaling and management, for binary size */
};
......@@ -113,14 +114,14 @@ static int slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
return 0;
}
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen)
static int slave_handle_response(struct pp_instance *ppi, unsigned char *buf,
int len)
{
int e = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp;
msg_unpack_delay_resp(pkt, &resp);
MsgDelayResp resp;
msg_unpack_delay_resp(buf, &resp);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity,
......@@ -158,6 +159,27 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
return 0;
}
static int slave_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len)
{
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
MsgAnnounce ann;
ret = pp_lib_handle_announce(ppi, buf, len);
if (ret)
return ret;
if (ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT) {
/* 9.2.6.11 a) reset timeout */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
/* 9.5.3 Figure 29 update data set if announce from current master */
msg_unpack_announce(buf, &ann);
bmc_s1(ppi, hdr, &ann);
}
return 0;
}
static int slave_execute(struct pp_instance *ppi)
{
int ret = 0;
......@@ -206,7 +228,7 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
pp_lib_may_issue_request(ppi);
/*
* The management of messages is now table-driven
*/
......@@ -226,12 +248,13 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
e = slave_execute(ppi);
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happended */
pp_timeout_set(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);
}
}
......
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