/* 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"); } } } }
/*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; } } }
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; } }
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 "); } } }