int pp_slave(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; MsgDelayResp resp; int d1, d2; if (ppi->is_new_state) { pp_servo_init(ppi); if (pp_hooks.new_slave) e = pp_hooks.new_slave(ppi, pkt, plen); if (e) goto out; ppi->waiting_for_follow = FALSE; pp_timeout_restart_annrec(ppi); pp_timeout_rand(ppi, PP_TO_DELAYREQ, DSPOR(ppi)->logMinDelayReqInterval); } if (plen == 0) goto out; switch (hdr->messageType) { case PPM_ANNOUNCE: e = st_com_slave_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; case PPM_DELAY_REQ: /* Being slave, we are not waiting for a delay request */ break; case PPM_DELAY_RESP: e = (plen < PP_DELAY_RESP_LENGTH); if (e) break; msg_unpack_delay_resp(pkt, &resp); if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity, &resp.requestingPortIdentity.clockIdentity, PP_CLOCK_IDENTITY_LENGTH) == 0) && ((ppi->sent_seq[PPM_DELAY_REQ]) == hdr->sequenceId) && (DSPOR(ppi)->portIdentity.portNumber == resp.requestingPortIdentity.portNumber) && ppi->is_from_cur_par) { to_TimeInternal(&ppi->t4, &resp.receiveTimestamp); /* * FIXME: how is correctionField handled in t3/t4? * I think the master should consider it when * generating t4, and report back a modified t4 */ if (pp_hooks.handle_resp) e = pp_hooks.handle_resp(ppi); else pp_servo_got_resp(ppi); if (e) goto out; ppi->log_min_delay_req_interval = hdr->logMessageInterval; } else { pp_diag(ppi, frames, 2, "pp_slave : " "Delay Resp doesn't match Delay Req\n"); } break; /* * We are not supporting pdelay (not configured to, see * 9.5.13.1, p 106), so all the code about pdelay is removed * as a whole by one commit in our history. It can be recoverd * and fixed if needed */ default: /* disregard, nothing to do */ break; } out: if (e == 0) e = st_com_execute_slave(ppi); if (pp_timeout_z(ppi, PP_TO_DELAYREQ)) { e = msg_issue_delay_req(ppi); ppi->t3 = ppi->last_snt_time; /* Restart the timeout for next time */ pp_timeout_rand(ppi, PP_TO_DELAYREQ, DSPOR(ppi)->logMinDelayReqInterval); /* Add latency */ add_TimeInternal(&ppi->t3, &ppi->t3, &OPTS(ppi)->outbound_latency); } if (e) { ppi->next_state = PPS_FAULTY; return 0; } /* Leaving this state */ if (ppi->next_state != ppi->state) { pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT); pp_timeout_clr(ppi, PP_TO_DELAYREQ); pp_servo_init(ppi); } d1 = d2 = pp_ms_to_timeout(ppi, PP_TO_ANN_RECEIPT); if (ppi->timeouts[PP_TO_DELAYREQ]) d2 = pp_ms_to_timeout(ppi, PP_TO_DELAYREQ); ppi->next_delay = d1 < d2 ? d1 : d2; return 0; }
int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen) { int msgtype, d1, d2; int e = 0; /* error var, to check errors in msg handling */ if (ppi->is_new_state) { pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval); pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL, DSPOR(ppi)->logAnnounceInterval); /* Send an announce immediately, when becomes master */ if ((e = msg_issue_announce(ppi)) < 0) goto out; } if (pp_timeout_z(ppi, PP_TO_SYNC)) { if ((e = msg_issue_sync_followup(ppi) < 0)) goto out; /* Restart the timeout for next time */ pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval); } if (pp_timeout_z(ppi, PP_TO_ANN_INTERVAL)) { if ((e = msg_issue_announce(ppi) < 0)) goto out; /* Restart the timeout for next time */ pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL, DSPOR(ppi)->logAnnounceInterval); } if (plen == 0) goto out; /* * An extension can do special treatment of this message type, * possibly returning error or eating the message by returning * PPM_NOTHING_TO_DO */ msgtype = ppi->received_ptp_header.messageType; if (pp_hooks.master_msg) msgtype = pp_hooks.master_msg(ppi, pkt, plen, msgtype); if (msgtype < 0) { e = msgtype; goto out; } switch (msgtype) { case PPM_NOTHING_TO_DO: break; case PPM_ANNOUNCE: e = st_com_master_handle_announce(ppi, pkt, plen); break; case PPM_SYNC: e = st_com_master_handle_sync(ppi, pkt, plen); break; case PPM_DELAY_REQ: msg_issue_delay_resp(ppi, &ppi->last_rcv_time); break; /* * We are not supporting pdelay (not configured to, see * 9.5.13.1, p 106), so all the code about pdelay is removed * as a whole by one commit in our history. It can be recoverd * and fixed if needed */ default: /* disregard, nothing to do */ break; } out: if (e == 0) { if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY || (ppi->role == PPSI_ROLE_SLAVE)) ppi->next_state = PPS_LISTENING; } else { ppi->next_state = PPS_FAULTY; } d1 = pp_ms_to_timeout(ppi, PP_TO_ANN_INTERVAL); d2 = pp_ms_to_timeout(ppi, PP_TO_SYNC); ppi->next_delay = d1 < d2 ? d1 : d2; return 0; }