Пример #1
0
/* pack and send various messages */
void issueSync(PtpClock *ptpClock)
{
  TimeInternal internalTime;
  TimeRepresentation originTimestamp;
  
  ++ptpClock->last_sync_event_sequence_number;
  ptpClock->grandmaster_sequence_number = ptpClock->last_sync_event_sequence_number;

  /* try to predict outgoing time stamp */
  getTime(&internalTime, ptpClock);
  fromInternalTime(&internalTime, &originTimestamp, ptpClock->halfEpoch);
  msgPackSync(ptpClock->msgObuf, FALSE, TRUE, &originTimestamp, ptpClock);
  
  if(!netSendEvent(ptpClock->msgObuf, SYNC_PACKET_LENGTH,
                   ptpClock->delayedTiming ? &internalTime : NULL,
                   ptpClock))
    toState(PTP_FAULTY, ptpClock);
  else
  {
    DBGV("sent sync message\n");
    if(ptpClock->delayedTiming)
    {
      if (internalTime.seconds || internalTime.nanoseconds) {
        /* compensate with configurable latency, then tell client real time stamp */
        addTime(&internalTime, &internalTime, &ptpClock->runTimeOpts.outboundLatency);
        issueFollowup(&internalTime, ptpClock);
      } else {
        NOTIFY("WARNING: sync message without hardware time stamp, skipped followup\n");
      }
    }
  }
}
Пример #2
0
/*Pack and send on event multicast ip adress a Sync message*/
static void issueSync(PtpClock *ptpClock)
{
    Timestamp originTimestamp;
    TimeInternal internalTime;

    /* try to predict outgoing time stamp */
    getTime(&internalTime);
    fromInternalTime(&internalTime, &originTimestamp);

    msgPackSync(ptpClock, ptpClock->msgObuf, &originTimestamp);

    if (!netSendEvent(&ptpClock->netPath, ptpClock->msgObuf, SYNC_LENGTH, &internalTime))
    {
        ERROR("issueSync: can't sent\n");
        toState(ptpClock, PTP_FAULTY);
    }
    else
    {
        DBGV("issueSync\n");
        ptpClock->sentSyncSequenceId++;

        /* sync TX timestamp is valid */

        if ((internalTime.seconds != 0) && (ptpClock->defaultDS.twoStepFlag))
        {
            // waitingForLoopback = false;
            addTime(&internalTime, &internalTime, &ptpClock->outboundLatency);
            issueFollowup(ptpClock, &internalTime);
        }
        else
        {
            // waitingForLoopback = ptpClock->twoStepFlag;
        }
    }
}
Пример #3
0
void handleSync(MsgHeader *header, Octet *msgIbuf, ssize_t length, TimeInternal *time, Boolean badTime, Boolean isFromSelf, PtpClock *ptpClock)
{
  MsgSync *sync;
  TimeInternal originTimestamp;
  
  if(length < SYNC_PACKET_LENGTH)
  {
    ERROR("short sync message\n");
    toState(PTP_FAULTY, ptpClock);
    return;
  }
  
  switch(ptpClock->port_state)
  {
  case PTP_FAULTY:
  case PTP_INITIALIZING:
  case PTP_DISABLED:
    DBGV("handleSync: disreguard\n");
    return;
    
  case PTP_UNCALIBRATED:
  case PTP_SLAVE:
    if(isFromSelf)
    {
      DBG("handleSync: ignore from self\n");
      return;
    }
    
    if(getFlag(header->flags, PTP_SYNC_BURST) && !ptpClock->burst_enabled)
      return;
    
    DBGV("handleSync: looking for uuid %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
      ptpClock->parent_uuid[0], ptpClock->parent_uuid[1], ptpClock->parent_uuid[2],
      ptpClock->parent_uuid[3], ptpClock->parent_uuid[4], ptpClock->parent_uuid[5]);
    
    if( header->sequenceId > ptpClock->parent_last_sync_sequence_number
      && header->sourceCommunicationTechnology == ptpClock->parent_communication_technology
      && header->sourcePortId == ptpClock->parent_port_id
      && !memcmp(header->sourceUuid, ptpClock->parent_uuid, PTP_UUID_LENGTH) )
    {
      /* addForeign() takes care of msgUnpackSync() */
      ptpClock->record_update = TRUE;
      sync = addForeign(ptpClock->msgIbuf, &ptpClock->msgTmpHeader, ptpClock);
      
      if(sync->syncInterval != ptpClock->sync_interval)
      {
        DBGV("message's sync interval is %d, but clock's is %d\n", sync->syncInterval, ptpClock->sync_interval);
        /* spec recommends handling a sync interval discrepancy as a fault */
      }
      
      /*
       * TODO: Sync packets without hardware time stamp are rare, but might happen.
       * Need to decide what to do with the bad default time stamp, similar to handleDelayReq().
       */

      ptpClock->sync_receive_time.seconds = time->seconds;
      ptpClock->sync_receive_time.nanoseconds = time->nanoseconds;
      
      if(!getFlag(header->flags, PTP_ASSIST))
      {
        ptpClock->waitingForFollow = FALSE;
        
        toInternalTime(&originTimestamp, &sync->originTimestamp, &ptpClock->halfEpoch);
        updateOffset(&originTimestamp, &ptpClock->sync_receive_time,
          &ptpClock->ofm_filt, ptpClock);
        updateClock(ptpClock);
      }
      else
      {
        ptpClock->waitingForFollow = TRUE;
      }
      
      s1(header, sync, ptpClock);
      
      if(!(--ptpClock->R))
      {
        issueDelayReq(ptpClock);
        
        ptpClock->Q = 0;
        ptpClock->R = getRand(&ptpClock->random_seed)%(PTP_DELAY_REQ_INTERVAL - 2) + 2;
        DBG("Q = %d, R = %d\n", ptpClock->Q, ptpClock->R);
      }
      
      DBGV("SYNC_RECEIPT_TIMER reset\n");
      timerStart(SYNC_RECEIPT_TIMER, PTP_SYNC_RECEIPT_TIMEOUT(ptpClock->sync_interval), ptpClock->itimer);
    }
    else
    {
      DBGV("handleSync: unwanted\n");
    }
    
  case PTP_MASTER:
  default:
    if( header->sourceCommunicationTechnology == ptpClock->clock_communication_technology
      || header->sourceCommunicationTechnology == PTP_DEFAULT
      || ptpClock->clock_communication_technology == PTP_DEFAULT )
    {
      if(!isFromSelf)
      {
        ptpClock->record_update = TRUE;
        addForeign(ptpClock->msgIbuf, &ptpClock->msgTmpHeader, ptpClock);
      }
      else if(ptpClock->port_state == PTP_MASTER && ptpClock->clock_followup_capable)
      {
        addTime(time, time, &ptpClock->runTimeOpts.outboundLatency);
        issueFollowup(time, ptpClock);
      }
    }
    break;
  }
}
Пример #4
0
void 
handleSync(MsgHeader *header, Octet *msgIbuf, ssize_t length, 
	   TimeInternal *time, Boolean isFromSelf, 
	   RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
	TimeInternal OriginTimestamp;
	TimeInternal correctionField;

	Boolean isFromCurrentParent = FALSE;
	DBGV("Sync message received : \n");
	
	if (length < SYNC_LENGTH) {
		ERROR("short Sync message\n");
		toState(PTP_FAULTY, rtOpts, ptpClock);
		return;
	}	

	switch (ptpClock->portState) {
	case PTP_INITIALIZING:
	case PTP_FAULTY:
	case PTP_DISABLED:
		DBGV("HandleSync : disregard\n");
		return;
		
	case PTP_UNCALIBRATED:	
	case PTP_SLAVE:
		if (isFromSelf) {
			DBGV("HandleSync: Ignore message from self \n");
			return;
		}
		isFromCurrentParent =
			!memcmp(ptpClock->parentPortIdentity.clockIdentity,
				header->sourcePortIdentity.clockIdentity,
				CLOCK_IDENTITY_LENGTH) && 
			(ptpClock->parentPortIdentity.portNumber == 
			 header->sourcePortIdentity.portNumber);
		
		if (isFromCurrentParent) {
			/* We only start our own delayReq timer after receiving the first sync */
			if (ptpClock->waiting_for_first_sync) {
				ptpClock->waiting_for_first_sync = FALSE;
				NOTICE("Received first Sync from Master\n");
				NOTICE("   going to arm DelayReq timer for the first time, with initial rate: %d\n",
					ptpClock->logMinDelayReqInterval
				);

				if (ptpClock->delayMechanism == E2E)
					timerStart(DELAYREQ_INTERVAL_TIMER,
						   pow(2,ptpClock->logMinDelayReqInterval),
						   ptpClock->itimer);
				else if (ptpClock->delayMechanism == P2P)
					timerStart(PDELAYREQ_INTERVAL_TIMER,
						   pow(2,ptpClock->logMinPdelayReqInterval),
						   ptpClock->itimer);
			}

			ptpClock->sync_receive_time.seconds = time->seconds;
			ptpClock->sync_receive_time.nanoseconds = time->nanoseconds;

			recordSync(rtOpts, header->sequenceId, time);

			if ((header->flagField[0] & PTP_TWO_STEP) == PTP_TWO_STEP) {
				DBG2("HandleSync: waiting for follow-up \n");

				ptpClock->waitingForFollow = TRUE;
				ptpClock->recvSyncSequenceId = 
					header->sequenceId;
				/*Save correctionField of Sync message*/
				integer64_to_internalTime(
					header->correctionfield,
					&correctionField);
				ptpClock->lastSyncCorrectionField.seconds = 
					correctionField.seconds;
				ptpClock->lastSyncCorrectionField.nanoseconds =
					correctionField.nanoseconds;
				break;
			} else {
				msgUnpackSync(ptpClock->msgIbuf,
					      &ptpClock->msgTmp.sync);
				integer64_to_internalTime(
					ptpClock->msgTmpHeader.correctionfield,
					&correctionField);
				timeInternal_display(&correctionField);
				ptpClock->waitingForFollow = FALSE;
				toInternalTime(&OriginTimestamp,
					       &ptpClock->msgTmp.sync.originTimestamp);
				updateOffset(&OriginTimestamp,
					     &ptpClock->sync_receive_time,
					     &ptpClock->ofm_filt,rtOpts,
					     ptpClock,&correctionField);
				updateClock(rtOpts,ptpClock);
				break;
			}
		} else {
			DBG("HandleSync: Sync message received from "
			     "another Master not our own \n");
		}
		break;

	case PTP_MASTER:
	default :
		if (!isFromSelf) {
			DBGV("HandleSync: Sync message received from "
			     "another Master  \n");
			break;
		} if (ptpClock->twoStepFlag) {
			DBGV("HandleSync: going to send followup message\n ");

			/*Add latency*/
			addTime(time,time,&rtOpts->outboundLatency);
			issueFollowup(time,rtOpts,ptpClock);
			break;
		} else {
			DBGV("HandleSync: Sync message received from self\n ");
		}
	}
}