Ejemplo n.º 1
0
/* handle actions and events for 'port_state' */
void doState(PtpClock *ptpClock)
{
    ptpClock->messageActivity = FALSE;

    switch (ptpClock->portDS.portState)
    {
    case PTP_LISTENING:
    case PTP_UNCALIBRATED:
    case PTP_SLAVE:
    case PTP_PRE_MASTER:
    case PTP_MASTER:
    case PTP_PASSIVE:
        /*State decision Event*/

        if (getFlag(ptpClock->events, STATE_DECISION_EVENT))
        {
            DBGV("event STATE_DECISION_EVENT\n");
            clearFlag(ptpClock->events, STATE_DECISION_EVENT);
            ptpClock->recommendedState = bmc(ptpClock);

            switch (ptpClock->recommendedState)
            {
            case PTP_MASTER:
            case PTP_PASSIVE:

                if (ptpClock->defaultDS.slaveOnly || ptpClock->defaultDS.clockQuality.clockClass == 255)
                {
                    ptpClock->recommendedState = PTP_LISTENING;
                }

                break;

            default:
                break;
            }
        }

        break;

    default:
        break;
    }

    switch (ptpClock->recommendedState)
    {
    case PTP_MASTER:

        switch (ptpClock->portDS.portState)
        {
        case PTP_PRE_MASTER:

            if (timerExpired(QUALIFICATION_TIMEOUT, ptpClock->itimer))
            {
                toState(ptpClock, PTP_MASTER);
            }

            break;

        case PTP_MASTER:
            break;
        default:
            toState(ptpClock, PTP_PRE_MASTER);
            break;
        }

        break;

    case PTP_PASSIVE:

        if (ptpClock->portDS.portState != ptpClock->recommendedState)
        {
            toState(ptpClock, PTP_PASSIVE);
        }

        break;

    case PTP_SLAVE:

        switch (ptpClock->portDS.portState)
        {
        case PTP_UNCALIBRATED:

            if (getFlag(ptpClock->events, MASTER_CLOCK_SELECTED))
            {
                DBG("event MASTER_CLOCK_SELECTED\n");
                clearFlag(ptpClock->events, MASTER_CLOCK_SELECTED);
                toState(ptpClock, PTP_SLAVE);
            }

            if (getFlag(ptpClock->events, MASTER_CLOCK_CHANGED))
            {
                DBG("event MASTER_CLOCK_CHANGED\n");
                clearFlag(ptpClock->events, MASTER_CLOCK_CHANGED);
            }

            break;

        case PTP_SLAVE:

            if (getFlag(ptpClock->events, SYNCHRONIZATION_FAULT))
            {
                DBG("event SYNCHRONIZATION_FAULT\n");
                clearFlag(ptpClock->events, SYNCHRONIZATION_FAULT);
                toState(ptpClock, PTP_UNCALIBRATED);
            }

            if (getFlag(ptpClock->events, MASTER_CLOCK_CHANGED))
            {
                DBG("event MASTER_CLOCK_CHANGED\n");
                clearFlag(ptpClock->events, MASTER_CLOCK_CHANGED);
                toState(ptpClock, PTP_UNCALIBRATED);
            }

            break;

        default:
            toState(ptpClock, PTP_UNCALIBRATED);
            break;
        }

        break;

    case PTP_LISTENING:

        if (ptpClock->portDS.portState != ptpClock->recommendedState)
        {
            toState(ptpClock, PTP_LISTENING);
        }

        break;

    case PTP_INITIALIZING:
        break;
    default:
        DBG("doState: unrecognized recommended state %d\n", ptpClock->recommendedState);
        break;
    }

    switch (ptpClock->portDS.portState)
    {
    case PTP_INITIALIZING:

        if (TRUE == doInit(ptpClock))
        {
            toState(ptpClock, PTP_LISTENING);
        }
        else
        {
            toState(ptpClock, PTP_FAULTY);
        }

        break;

    case PTP_FAULTY:
        /* imaginary troubleshooting */

        DBG("event FAULT_CLEARED\n");
        toState(ptpClock, PTP_INITIALIZING);
        return;

    case PTP_DISABLED:
        handle(ptpClock);
        break;

    case PTP_LISTENING:
    case PTP_UNCALIBRATED:
    case PTP_SLAVE:
    case PTP_PASSIVE:

        if (timerExpired(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer))
        {
            DBGV("event ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES\n");
            ptpClock->foreignMasterDS.count = 0;
            ptpClock->foreignMasterDS.i = 0;

            if (!(ptpClock->defaultDS.slaveOnly || ptpClock->defaultDS.clockQuality.clockClass == 255))
            {
                m1(ptpClock);
                ptpClock->recommendedState = PTP_MASTER;
                toState(ptpClock, PTP_MASTER);
            }
            else if (ptpClock->portDS.portState != PTP_LISTENING)
            {
                toState(ptpClock, PTP_LISTENING);
            }

            break;
        }

        handle(ptpClock);

        break;

    case PTP_MASTER:

        if (timerExpired(SYNC_INTERVAL_TIMER, ptpClock->itimer))
        {
            DBGV("event SYNC_INTERVAL_TIMEOUT_EXPIRES\n");
            issueSync(ptpClock);
        }

        if (timerExpired(ANNOUNCE_INTERVAL_TIMER, ptpClock->itimer))
        {
            DBGV("event ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES\n");
            issueAnnounce(ptpClock);
        }

        handle(ptpClock);

        issueDelayReqTimerExpired(ptpClock);

        break;
    default:
        DBG("doState: do unrecognized state %d\n", ptpClock->portDS.portState);
        break;
    }
}
Ejemplo n.º 2
0
/* handle actions and events for 'port_state' */
void 
doState(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
	UInteger8 state;
	
	ptpClock->message_activity = FALSE;
	
	/* Process record_update (BMC algorithm) before everything else */
	switch (ptpClock->portState)
	{
	case PTP_LISTENING:
	case PTP_PASSIVE:
	case PTP_SLAVE:
	case PTP_MASTER:
		/*State decision Event*/

		/* If we received a valid Announce message, and can use it (record_update), then run the BMC algorithm */
		if(ptpClock->record_update)
		{
			DBG2("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_UNCALIBRATED:
	case PTP_SLAVE:
	// passive mode behaves like the SLAVE state, in order to wait for the announce timeout of the current active master
	case PTP_PASSIVE:
		handle(rtOpts, ptpClock);
		
		/*
		 * handle SLAVE timers:
		 *   - No Announce message was received
		 *   - Time to send new delayReq  (miss of delayResp is not monitored explicitelly)
		 */
		if (timerExpired(ANNOUNCE_RECEIPT_TIMER, ptpClock->itimer))
		{
			DBG("event ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES\n");
			ptpClock->number_foreign_records = 0;
			ptpClock->foreign_record_i = 0;

			if(!ptpClock->slaveOnly && 
			   ptpClock->clockQuality.clockClass != 255) {
				m1(rtOpts,ptpClock);
				toState(PTP_MASTER, rtOpts, ptpClock);

			} else {
				/*
				 *  Force a reset when getting a timeout in state listening, that will lead to an IGMP reset
				 *  previously this was not the case when we were already in LISTENING mode
				 */
				toState(PTP_LISTENING, rtOpts, ptpClock);
			}
		}
		
		if (timerExpired(OPERATOR_MESSAGES_TIMER, ptpClock->itimer)) {
			reset_operator_messages(rtOpts, ptpClock);
		}


		if (ptpClock->delayMechanism == E2E) {
			if(timerExpired(DELAYREQ_INTERVAL_TIMER,
					ptpClock->itimer)) {
				DBG2("event DELAYREQ_INTERVAL_TIMEOUT_EXPIRES\n");
				issueDelayReq(rtOpts,ptpClock);
			}
		} else if (ptpClock->delayMechanism == P2P) {
			if (timerExpired(PDELAYREQ_INTERVAL_TIMER,
					ptpClock->itimer)) {
				DBGV("event PDELAYREQ_INTERVAL_TIMEOUT_EXPIRES\n");
				issuePDelayReq(rtOpts,ptpClock);
			}

			/* FIXME: Path delay should also rearm its timer with the value received from the Master */
		}
		break;

	case PTP_MASTER:
		/*
		 * handle SLAVE timers:
		 *   - Time to send new Sync
		 *   - Time to send new Announce
		 *   - Time to send new PathDelay
		 *      (DelayResp has no timer - as these are sent and retransmitted by the slaves)
		 */
	
		if (timerExpired(SYNC_INTERVAL_TIMER, ptpClock->itimer)) {
			DBGV("event SYNC_INTERVAL_TIMEOUT_EXPIRES\n");
			issueSync(rtOpts, ptpClock);
		}
		
		if (timerExpired(ANNOUNCE_INTERVAL_TIMER, ptpClock->itimer)) {
			DBGV("event ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES\n");
			issueAnnounce(rtOpts, ptpClock);
		}
		
		if (ptpClock->delayMechanism == P2P) {
			if (timerExpired(PDELAYREQ_INTERVAL_TIMER,
					ptpClock->itimer)) {
				DBGV("event PDELAYREQ_INTERVAL_TIMEOUT_EXPIRES\n");
				issuePDelayReq(rtOpts,ptpClock);
			}
		}
		
		// TODO: why is handle() below expiretimer, while in slave is the opposite
		handle(rtOpts, ptpClock);
		
		if (ptpClock->slaveOnly || ptpClock->clockQuality.clockClass == 255)
			toState(PTP_LISTENING, rtOpts, ptpClock);
		
		break;

	case PTP_DISABLED:
		handle(rtOpts, ptpClock);
		break;
		
	default:
		DBG("(doState) do unrecognized state\n");
		break;
	}
}