/**
* @file protocol.c
* @date Wed Jun 23 09:40:39 2010
*
* @brief The code that handles the IEEE-1588 protocol and state machine
*
*
*/
#include "ptpd.h"
Boolean doInit(RunTimeOpts*,PtpClock*);
void doState(RunTimeOpts*,PtpClock*);
void toState(UInteger8,RunTimeOpts*,PtpClock*);
void handle(RunTimeOpts*,PtpClock*);
void handleAnnounce(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handleSync(MsgHeader*,Octet*,ssize_t,TimeInternal*,Boolean,RunTimeOpts*,PtpClock*);
void handleFollowUp(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handlePDelayReq(MsgHeader*,Octet*,ssize_t,TimeInternal*,Boolean,RunTimeOpts*,PtpClock*);
void handleDelayReq(MsgHeader*,Octet*,ssize_t,TimeInternal*,Boolean,RunTimeOpts*,PtpClock*);
void handlePDelayResp(MsgHeader*,Octet*,TimeInternal* ,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handleDelayResp(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handlePDelayRespFollowUp(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handleManagement(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void handleSignaling(MsgHeader*,Octet*,ssize_t,Boolean,RunTimeOpts*,PtpClock*);
void issueAnnounce(RunTimeOpts*,PtpClock*);
void issueSync(RunTimeOpts*,PtpClock*);
void issueFollowup(TimeInternal*,RunTimeOpts*,PtpClock*);
void issuePDelayReq(RunTimeOpts*,PtpClock*);
void issueDelayReq(RunTimeOpts*,PtpClock*);
void issuePDelayResp(TimeInternal*,MsgHeader*,RunTimeOpts*,PtpClock*);
void issueDelayResp(TimeInternal*,MsgHeader*,RunTimeOpts*,PtpClock*);
void issuePDelayRespFollowUp(TimeInternal*,MsgHeader*,RunTimeOpts*,PtpClock*);
void issueManagement(MsgHeader*,MsgManagement*,RunTimeOpts*,PtpClock*);
void addForeign(Octet*,MsgHeader*,PtpClock*);
/* loop forever. doState() has a switch for the actions and events to be
checked for 'port_state'. the actions and events may or may not change
'port_state' by calling toState(), but once they are done we loop around
again and perform the actions required for the new 'port_state'. */
void
protocol(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
DBG("event POWERUP\n");
toState(PTP_INITIALIZING, rtOpts, ptpClock);
DBGV("Debug Initializing...");
for(;;)
{
if(ptpClock->portState != PTP_INITIALIZING)
doState(rtOpts, ptpClock);
else if(!doInit(rtOpts, ptpClock))
return;
if(ptpClock->message_activity)
DBGV("activity\n");
else
DBGV("no activity\n");
}
}
/* perform actions required when leaving 'port_state' and entering 'state' */
void
toState(UInteger8 state, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
ptpClock->message_activity = TRUE;
/* leaving state tasks */
switch(ptpClock->portState)
{
case PTP_MASTER:
timerStop(SYNC_INTERVAL_TIMER, ptpClock->itimer);
timerStop(ANNOUNCE_INTERVAL_TIMER, ptpClock->itimer);
timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
break;
case PTP_SLAVE:
timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
if (rtOpts->E2E_mode)
timerStop(DELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
else
timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
initClock(rtOpts, ptpClock);
break;
case PTP_PASSIVE:
timerStop(PDELAYREQ_INTERVAL_TIMER, ptpClock->itimer);
timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
break;
case PTP_LISTENING:
timerStop(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer);
break;
default:
break;
}
/* entering state tasks */
/*
* No need of PRE_MASTER state because of only ordinary clock
* implementation.
*/
switch(state)
{
case PTP_INITIALIZING:
DBG("state PTP_INITIALIZING\n");
ptpClock->portState = PTP_INITIALIZING;
break;
case PTP_FAULTY:
DBG("state PTP_FAULTY\n");
ptpClock->portState = PTP_FAULTY;
break;
case PTP_DISABLED:
DBG("state PTP_DISABLED\n");
ptpClock->portState = PTP_DISABLED;
break;
case PTP_LISTENING:
DBG("state PTP_LISTENING\n");
timerStart(ANNOUNCE_RECEIPT_TIMER,
(ptpClock->announceReceiptTimeout) *
(pow(2,ptpClock->logAnnounceInterval)),
ptpClock->itimer);
ptpClock->portState = PTP_LISTENING;
break;
case PTP_MASTER:
DBG("state PTP_MASTER\n");
timerStart(SYNC_INTERVAL_TIMER,
pow(2,ptpClock->logSyncInterval), ptpClock->itimer);
DBG("SYNC INTERVAL TIMER : %f \n",
pow(2,ptpClock->logSyncInterval));
timerStart(ANNOUNCE_INTERVAL_TIMER,
pow(2,ptpClock->logAnnounceInterval),
ptpClock->itimer);
timerStart(PDELAYREQ_INTERVAL_TIMER,
pow(2,ptpClock->logMinPdelayReqInterval),
ptpClock->itimer);
ptpClock->portState = PTP_MASTER;
break;
case PTP_PASSIVE:
DBG("state PTP_PASSIVE\n");
timerStart(PDELAYREQ_INTERVAL_TIMER,
pow(2,ptpClock->logMinPdelayReqInterval),
ptpClock->itimer);
timerStart(ANNOUNCE_RECEIPT_TIMER,
(ptpClock->announceReceiptTimeout) *
(pow(2,ptpClock->logAnnounceInterval)),
ptpClock->itimer);
ptpClock->portState = PTP_PASSIVE;
break;
case PTP_UNCALIBRATED:
DBG("state PTP_UNCALIBRATED\n");
ptpClock->portState = PTP_UNCALIBRATED;
break;
case PTP_SLAVE:
DBG("state PTP_SLAVE\n");
initClock(rtOpts, ptpClock);
ptpClock->waitingForFollow = FALSE;
ptpClock->pdelay_req_send_time.seconds = 0;
ptpClock->pdelay_req_send_time.nanoseconds = 0;
ptpClock->pdelay_req_receive_time.seconds = 0;
ptpClock->pdelay_req_receive_time.nanoseconds = 0;
ptpClock->pdelay_resp_send_time.seconds = 0;
ptpClock->pdelay_resp_send_time.nanoseconds = 0;
ptpClock->pdelay_resp_receive_time.seconds = 0;
ptpClock->pdelay_resp_receive_time.nanoseconds = 0;
timerStart(ANNOUNCE_RECEIPT_TIMER,
(ptpClock->announceReceiptTimeout) *
(pow(2,ptpClock->logAnnounceInterval)),
ptpClock->itimer);
if (rtOpts->E2E_mode)
timerStart(DELAYREQ_INTERVAL_TIMER,
pow(2,ptpClock->logMinDelayReqInterval),
ptpClock->itimer);
else
timerStart(PDELAYREQ_INTERVAL_TIMER,
pow(2,ptpClock->logMinPdelayReqInterval),
ptpClock->itimer);
ptpClock->portState = PTP_SLAVE;
break;
default:
DBG("to unrecognized state\n");
break;
}
if(rtOpts->displayStats)
displayStats(rtOpts, ptpClock);
}
Boolean
doInit(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
DBG("manufacturerIdentity: %s\n", MANUFACTURER_ID);
/* initialize networking */
netShutdown(&ptpClock->netPath);
if(!netInit(&ptpClock->netPath, rtOpts, ptpClock)) {
ERROR("failed to initialize network\n");
toState(PTP_FAULTY, rtOpts, ptpClock);
return FALSE;
}
/* initialize other stuff */
initData(rtOpts, ptpClock);
initTimer();
initClock(rtOpts, ptpClock);
m1(ptpClock);
msgPackHeader(ptpClock->msgObuf, ptpClock);
toState(PTP_LISTENING, rtOpts, ptpClock);
return TRUE;
}
/* handle actions and events for 'port_state' */
void
doState(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
UInteger8 state;
ptpClock->message_activity = FALSE;
switch(ptpClock->portState)
{
case PTP_LISTENING:
case PTP_PASSIVE:
case PTP_SLAVE:
case PTP_MASTER:
/*State decision Event*/
if(ptpClock->record_update)
{
DBGV("event STATE_DECISION_EVENT\n");
ptpClock->record_update = FALSE;
state = bmc(ptpClock->foreign, rtOpts, ptpClock);
if(state != ptpClock->portState)
toState(state, rtOpts, ptpClock);
}
break;
default:
break;
}
switch(ptpClock->portState)
{
case PTP_FAULTY:
/* imaginary troubleshooting */
DBG("event FAULT_CLEARED\n");
toState(PTP_INITIALIZING, rtOpts, ptpClock);
return;
case PTP_LISTENING:
case PTP_PASSIVE:
case PTP_UNCALIBRATED:
case PTP_SLAVE:
handle(rtOpts, ptpClock);
if(timerExpired(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer))
{
DBGV("event ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES\n");
ptpClock->number_foreign_records = 0;
ptpClock->foreign_record_i = 0;
if(!ptpClock->slaveOnly &&
ptpClock->clockQuality.clockClass != 255) {
m1(ptpClock);
toState(PTP_MASTER, rtOpts, ptpClock);
}
- 1
- 2
- 3
前往页