/*Local clock is becoming Master. Table 13 (9.3.5) of the spec.*/ void m1(RunTimeOpts *rtOpts, PtpClock *ptpClock) { /*Current data set update*/ ptpClock->stepsRemoved = 0; clearTime(&ptpClock->offsetFromMaster); clearTime(&ptpClock->meanPathDelay); /*Parent data set*/ copyClockIdentity(ptpClock->parentPortIdentity.clockIdentity, ptpClock->clockIdentity); ptpClock->parentPortIdentity.portNumber = 0; ptpClock->parentStats = DEFAULT_PARENTS_STATS; ptpClock->observedParentClockPhaseChangeRate = 0; ptpClock->observedParentOffsetScaledLogVariance = 0; copyClockIdentity(ptpClock->grandmasterIdentity, ptpClock->clockIdentity); ptpClock->grandmasterClockQuality.clockAccuracy = ptpClock->clockQuality.clockAccuracy; ptpClock->grandmasterClockQuality.clockClass = ptpClock->clockQuality.clockClass; ptpClock->grandmasterClockQuality.offsetScaledLogVariance = ptpClock->clockQuality.offsetScaledLogVariance; ptpClock->grandmasterPriority1 = ptpClock->priority1; ptpClock->grandmasterPriority2 = ptpClock->priority2; /*Time Properties data set*/ ptpClock->timeSource = INTERNAL_OSCILLATOR; /* UTC vs TAI timescales */ ptpClock->currentUtcOffsetValid = DEFAULT_UTC_VALID; ptpClock->currentUtcOffset = rtOpts->currentUtcOffset; }
/*Copy local data set into header and announce message. 9.3.4 table 12*/ void copyD0(MsgHeader *header, MsgAnnounce *announce, PtpClock *ptpClock) { announce->grandmasterPriority1 = ptpClock->priority1; copyClockIdentity(announce->grandmasterIdentity, ptpClock->clockIdentity); announce->grandmasterClockQuality.clockClass = ptpClock->clockQuality.clockClass; announce->grandmasterClockQuality.clockAccuracy = ptpClock->clockQuality.clockAccuracy; announce->grandmasterClockQuality.offsetScaledLogVariance = ptpClock->clockQuality.offsetScaledLogVariance; announce->grandmasterPriority2 = ptpClock->priority2; announce->stepsRemoved = 0; copyClockIdentity(header->sourcePortIdentity.clockIdentity, ptpClock->clockIdentity); }
/** * 本地时钟即将进入PTP_MASTER状态 */ void m1(const RunTimeOpts *rtOpts, PtpClock *ptpClock) { /*Current data set update*/ ptpClock->stepsRemoved = 0; clearTime(&ptpClock->offsetFromMaster); clearTime(&ptpClock->meanPathDelay); copyClockIdentity(ptpClock->parentPortIdentity.clockIdentity, ptpClock->clockIdentity); ptpClock->parentPortIdentity.portNumber = ptpClock->portIdentity.portNumber; ptpClock->parentStats = DEFAULT_PARENTS_STATS; ptpClock->observedParentClockPhaseChangeRate = 0; ptpClock->observedParentOffsetScaledLogVariance = 0; copyClockIdentity(ptpClock->grandmasterIdentity, ptpClock->clockIdentity); ptpClock->grandmasterClockQuality.clockAccuracy = ptpClock->clockQuality.clockAccuracy; ptpClock->grandmasterClockQuality.clockClass = ptpClock->clockQuality.clockClass; ptpClock->grandmasterClockQuality.offsetScaledLogVariance = ptpClock->clockQuality.offsetScaledLogVariance; ptpClock->grandmasterPriority1 = ptpClock->priority1; ptpClock->grandmasterPriority2 = ptpClock->priority2; ptpClock->logMinDelayReqInterval = rtOpts->logMinDelayReqInterval; /*Time Properties data set*/ ptpClock->timePropertiesDS.currentUtcOffsetValid = rtOpts->timeProperties.currentUtcOffsetValid; ptpClock->timePropertiesDS.currentUtcOffset = rtOpts->timeProperties.currentUtcOffset; ptpClock->timePropertiesDS.timeTraceable = rtOpts->timeProperties.timeTraceable; ptpClock->timePropertiesDS.frequencyTraceable = rtOpts->timeProperties.frequencyTraceable; ptpClock->timePropertiesDS.ptpTimescale = rtOpts->timeProperties.ptpTimescale; ptpClock->timePropertiesDS.timeSource = rtOpts->timeProperties.timeSource; if(ptpClock->timePropertiesDS.ptpTimescale && (secondsToMidnight() < rtOpts->leapSecondNoticePeriod)) { ptpClock->timePropertiesDS.leap59 = ptpClock->clockStatus.leapDelete; ptpClock->timePropertiesDS.leap61 = ptpClock->clockStatus.leapInsert; } else { ptpClock->timePropertiesDS.leap59 = FALSE; ptpClock->timePropertiesDS.leap61 = FALSE; } }
/* Init ptpClock with run time values (initialization constants are in constants.h)*/ void initData(RunTimeOpts *rtOpts, PtpClock *ptpClock) { int i,j; j=0; DBG("initData\n"); /* Default data set */ ptpClock->twoStepFlag = TWO_STEP_FLAG; /* * init clockIdentity with MAC address and 0xFF and 0xFE. see * spec 7.5.2.2.2 */ for (i=0;i<CLOCK_IDENTITY_LENGTH;i++) { if (i==3) ptpClock->clockIdentity[i]=0xFF; else if (i==4) ptpClock->clockIdentity[i]=0xFE; else { ptpClock->clockIdentity[i]=ptpClock->port_uuid_field[j]; j++; } } ptpClock->numberPorts = NUMBER_PORTS; ptpClock->clockQuality.clockAccuracy = rtOpts->clockQuality.clockAccuracy; ptpClock->clockQuality.clockClass = rtOpts->clockQuality.clockClass; ptpClock->clockQuality.offsetScaledLogVariance = rtOpts->clockQuality.offsetScaledLogVariance; ptpClock->priority1 = rtOpts->priority1; ptpClock->priority2 = rtOpts->priority2; ptpClock->domainNumber = rtOpts->domainNumber; ptpClock->slaveOnly = rtOpts->slaveOnly; if(rtOpts->slaveOnly) rtOpts->clockQuality.clockClass = SLAVE_ONLY_CLOCK_CLASS; /* Port configuration data set */ /* * PortIdentity Init (portNumber = 1 for an ardinary clock spec * 7.5.2.3) */ copyClockIdentity(ptpClock->portIdentity.clockIdentity, ptpClock->clockIdentity); ptpClock->portIdentity.portNumber = NUMBER_PORTS; /* select the initial rate of delayreqs until we receive the first announce message */ ptpClock->logMinDelayReqInterval = rtOpts->initial_delayreq; clearTime(&ptpClock->peerMeanPathDelay); ptpClock->logAnnounceInterval = rtOpts->announceInterval; ptpClock->announceReceiptTimeout = rtOpts->announceReceiptTimeout; ptpClock->logSyncInterval = rtOpts->syncInterval; ptpClock->delayMechanism = rtOpts->delayMechanism; ptpClock->logMinPdelayReqInterval = DEFAULT_PDELAYREQ_INTERVAL; ptpClock->versionNumber = VERSION_PTP; /* * Initialize random number generator using same method as ptpv1: * seed is now initialized from the last bytes of our mac addres (collected in net.c:findIface()) */ srand((ptpClock->port_uuid_field[PTP_UUID_LENGTH - 1] << 8) + ptpClock->port_uuid_field[PTP_UUID_LENGTH - 2]); /*Init other stuff*/ ptpClock->number_foreign_records = 0; ptpClock->max_foreign_records = rtOpts->max_foreign_records; }
/*Local clock is synchronized to Ebest Table 16 (9.3.5) of the spec*/ void s1(MsgHeader *header,MsgAnnounce *announce,PtpClock *ptpClock, RunTimeOpts *rtOpts) { Boolean previousLeap59 = FALSE, previousLeap61 = FALSE; Integer16 previousUtcOffset = 0; if (ptpClock->portState == PTP_SLAVE) { previousLeap59 = ptpClock->leap59; previousLeap61 = ptpClock->leap61; previousUtcOffset = ptpClock->currentUtcOffset; } /* Current DS */ ptpClock->stepsRemoved = announce->stepsRemoved + 1; /* Parent DS */ copyClockIdentity(ptpClock->parentPortIdentity.clockIdentity, header->sourcePortIdentity.clockIdentity); ptpClock->parentPortIdentity.portNumber = header->sourcePortIdentity.portNumber; copyClockIdentity(ptpClock->grandmasterIdentity, announce->grandmasterIdentity); ptpClock->grandmasterClockQuality.clockAccuracy = announce->grandmasterClockQuality.clockAccuracy; ptpClock->grandmasterClockQuality.clockClass = announce->grandmasterClockQuality.clockClass; ptpClock->grandmasterClockQuality.offsetScaledLogVariance = announce->grandmasterClockQuality.offsetScaledLogVariance; ptpClock->grandmasterPriority1 = announce->grandmasterPriority1; ptpClock->grandmasterPriority2 = announce->grandmasterPriority2; /* Timeproperties DS */ ptpClock->currentUtcOffset = announce->currentUtcOffset; /* "Valid" is bit 2 in second octet of flagfield */ ptpClock->currentUtcOffsetValid = IS_SET(header->flagField1, UTCV); /* set PTP_PASSIVE-specific state */ p1(ptpClock, rtOpts); /* only set leap state in slave mode */ if (ptpClock->portState == PTP_SLAVE) { ptpClock->leap59 = IS_SET(header->flagField1, LI59); ptpClock->leap61 = IS_SET(header->flagField1, LI61); } ptpClock->timeTraceable = IS_SET(header->flagField1, TTRA); ptpClock->frequencyTraceable = IS_SET(header->flagField1, FTRA); ptpClock->ptpTimescale = IS_SET(header->flagField1, PTPT); ptpClock->timeSource = announce->timeSource; #if defined(MOD_TAI) && NTP_API == 4 /* * update kernel TAI offset, but only if timescale is * PTP not ARB - spec section 7.2 */ if (ptpClock->ptpTimescale && (ptpClock->currentUtcOffset != previousUtcOffset)) { setKernelUtcOffset(ptpClock->currentUtcOffset); } #endif /* MOD_TAI */ /* Leap second handling */ if (ptpClock->portState == PTP_SLAVE) { if(ptpClock->leap59 && ptpClock->leap61) { ERROR("Both Leap59 and Leap61 flags set!\n"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } /* one of the leap second flags has suddenly been unset */ if(ptpClock->leapSecondPending && !ptpClock->leapSecondInProgress && ((previousLeap59 != ptpClock->leap59) || (previousLeap61 != ptpClock->leap61))) { WARNING("=== Leap second event aborted by GM!"); ptpClock->leapSecondPending = FALSE; ptpClock->leapSecondInProgress = FALSE; timerStop(LEAP_SECOND_PAUSE_TIMER, ptpClock->itimer); /** FIXME dumblob */ #if !defined(__APPLE__) && !defined(__QNXNTO__) unsetTimexFlags(STA_INS | STA_DEL,TRUE); #endif /* apple */ } /* * one of the leap second flags has been set * or flags are lit but we have no event pending */ if( (ptpClock->leap59 || ptpClock->leap61) && ( (!ptpClock->leapSecondPending && !ptpClock->leapSecondInProgress ) || ((!previousLeap59 && ptpClock->leap59) || (!previousLeap61 && ptpClock->leap61)))) { #if !defined(__APPLE__) && !defined(__QNXNTO__) WARNING("=== Leap second pending! Setting kernel to %s " "one second at midnight\n", ptpClock->leap61 ? "add" : "delete"); if (!checkTimexFlags(ptpClock->leap61 ? STA_INS : STA_DEL)) { unsetTimexFlags(ptpClock->leap61 ? STA_DEL : STA_INS, TRUE); setTimexFlags(ptpClock->leap61 ? STA_INS : STA_DEL, FALSE); } #else WARNING("=== Leap second pending! No kernel leap second " "API support - expect a clock jump at " "midnight!\n"); #endif /* apple */ /* only set the flag, the rest happens in doState() */ ptpClock->leapSecondPending = TRUE; } if((previousUtcOffset != ptpClock->currentUtcOffset) && !ptpClock->leapSecondPending && !ptpClock->leapSecondInProgress ) { WARNING("=== UTC offset changed from %d to %d with " "no leap second pending!\n", previousUtcOffset, ptpClock->currentUtcOffset); } else if( previousUtcOffset != ptpClock->currentUtcOffset) { WARNING("=== UTC offset changed from %d to %d\n", previousUtcOffset,ptpClock->currentUtcOffset); } } }
/** * 本时钟同步到最佳主时钟Ebest */ void s1(MsgHeader *header,MsgAnnounce *announce,PtpClock *ptpClock, const RunTimeOpts *rtOpts) { Boolean previousLeap59 = FALSE; Boolean previousLeap61 = FALSE; Boolean leapChange = FALSE; Integer16 previousUtcOffset = 0; /** * Leap59: 为真时,上一分钟只有59秒(而不是60秒) * Leap61: 为真时,上一分钟只有61秒(而不是60秒) */ previousLeap59 = ptpClock->timePropertiesDS.leap59; previousLeap61 = ptpClock->timePropertiesDS.leap61; /** * International Atomic Time (TAI)和Coordinated Universal Time (UTC)之间的差值 * 2012年1月时,该值为34秒 */ previousUtcOffset = ptpClock->timePropertiesDS.currentUtcOffset; /* Current DS */ ptpClock->stepsRemoved = announce->stepsRemoved + 1; /* Parent DS */ copyClockIdentity(ptpClock->parentPortIdentity.clockIdentity, header->sourcePortIdentity.clockIdentity); ptpClock->parentPortIdentity.portNumber = header->sourcePortIdentity.portNumber; copyClockIdentity(ptpClock->grandmasterIdentity, announce->grandmasterIdentity); ptpClock->grandmasterClockQuality.clockAccuracy = announce->grandmasterClockQuality.clockAccuracy; ptpClock->grandmasterClockQuality.clockClass = announce->grandmasterClockQuality.clockClass; ptpClock->grandmasterClockQuality.offsetScaledLogVariance = announce->grandmasterClockQuality.offsetScaledLogVariance; ptpClock->grandmasterPriority1 = announce->grandmasterPriority1; ptpClock->grandmasterPriority2 = announce->grandmasterPriority2; /* use the granted interval if using signaling, otherwise we would try to arm a timer for 2^127! */ if(rtOpts->unicastNegotiation && ptpClock->parentGrants != NULL && ptpClock->parentGrants->grantData[ANNOUNCE].granted) { ptpClock->logAnnounceInterval = ptpClock->parentGrants->grantData[ANNOUNCE].logInterval; } else if (header->logMessageInterval != UNICAST_MESSAGEINTERVAL) { ptpClock->logAnnounceInterval = header->logMessageInterval; } /* Timeproperties DS */ ptpClock->timePropertiesDS.currentUtcOffset = announce->currentUtcOffset; if (ptpClock->portState != PTP_PASSIVE && ptpClock->timePropertiesDS.currentUtcOffsetValid && !IS_SET(header->flagField1, UTCV)) { if(rtOpts->alwaysRespectUtcOffset) WARNING("UTC Offset no longer valid and ptpengine:always_respect_utc_offset is set: continuing as normal\n"); else WARNING("UTC Offset no longer valid - clock jump expected\n"); } /* "Valid" is bit 2 in second octet of flagfield */ ptpClock->timePropertiesDS.currentUtcOffsetValid = IS_SET(header->flagField1, UTCV); /* set PTP_PASSIVE-specific state */ /** * 如果当前为PTP_PASSIVE状态,则重置@timePropertiesDS为初始化的设置值 */ p1(ptpClock, rtOpts); /* only set leap flags in slave state - info from leap file takes priority*/ /** * 只有当前为PTP_SLAVE状态,才更新@leap59和@leap61 */ if (ptpClock->portState == PTP_SLAVE) { if(ptpClock->clockStatus.override) { ptpClock->timePropertiesDS.currentUtcOffset = ptpClock->clockStatus.utcOffset; ptpClock->timePropertiesDS.leap59 = ptpClock->clockStatus.leapDelete; ptpClock->timePropertiesDS.leap61 = ptpClock->clockStatus.leapInsert; } else { ptpClock->timePropertiesDS.leap59 = IS_SET(header->flagField1, LI59); ptpClock->timePropertiesDS.leap61 = IS_SET(header->flagField1, LI61); } }
/* Init ptpClock with run time values (initialization constants are in constants.h)*/ void initData(RunTimeOpts *rtOpts, PtpClock *ptpClock) { int i,j; j=0; DBG("initData\n"); /* Default data set */ ptpClock->twoStepFlag = TWO_STEP_FLAG; /* * init clockIdentity with MAC address and 0xFF and 0xFE. see * spec 7.5.2.2.2 */ for (i=0;i<CLOCK_IDENTITY_LENGTH;i++) { if (i==3) ptpClock->clockIdentity[i]=0xFF; else if (i==4) ptpClock->clockIdentity[i]=0xFE; else { ptpClock->clockIdentity[i]=ptpClock->netPath.interfaceID[j]; j++; } } if(rtOpts->pidAsClockId) { uint16_t pid = htons(getpid()); memcpy(ptpClock->clockIdentity + 3, &pid, 2); } ptpClock->bestMaster = NULL; ptpClock->numberPorts = NUMBER_PORTS; ptpClock->disabled = rtOpts->portDisabled; memset(ptpClock->userDescription, 0, sizeof(ptpClock->userDescription)); memcpy(ptpClock->userDescription, rtOpts->portDescription, strlen(rtOpts->portDescription)); memset(&ptpClock->profileIdentity,0,6); if(rtOpts->ipMode == IPMODE_UNICAST && rtOpts->unicastNegotiation) { memcpy(&ptpClock->profileIdentity, &PROFILE_ID_TELECOM,6); } if(rtOpts->ipMode == IPMODE_MULTICAST &&rtOpts->delayMechanism == E2E) { memcpy(&ptpClock->profileIdentity, &PROFILE_ID_DEFAULT_E2E,6); } if(rtOpts->ipMode == IPMODE_MULTICAST &&rtOpts->delayMechanism == P2P) { memcpy(&ptpClock->profileIdentity, &PROFILE_ID_DEFAULT_P2P,6); } if(rtOpts->dot1AS) { memcpy(&ptpClock->profileIdentity, &PROFILE_ID_802_1AS,6); } ptpClock->clockQuality.clockAccuracy = rtOpts->clockQuality.clockAccuracy; ptpClock->clockQuality.clockClass = rtOpts->clockQuality.clockClass; ptpClock->clockQuality.offsetScaledLogVariance = rtOpts->clockQuality.offsetScaledLogVariance; ptpClock->priority1 = rtOpts->priority1; ptpClock->priority2 = rtOpts->priority2; ptpClock->domainNumber = rtOpts->domainNumber; if(rtOpts->slaveOnly) { ptpClock->slaveOnly = TRUE; rtOpts->clockQuality.clockClass = SLAVE_ONLY_CLOCK_CLASS; ptpClock->clockQuality.clockClass = SLAVE_ONLY_CLOCK_CLASS; } /* Port configuration data set */ /* * PortIdentity Init (portNumber = 1 for an ardinary clock spec * 7.5.2.3) */ copyClockIdentity(ptpClock->portIdentity.clockIdentity, ptpClock->clockIdentity); ptpClock->portIdentity.portNumber = rtOpts->portNumber; /* select the initial rate of delayreqs until we receive the first announce message */ ptpClock->logMinDelayReqInterval = rtOpts->initial_delayreq; clearTime(&ptpClock->peerMeanPathDelay); ptpClock->logAnnounceInterval = rtOpts->logAnnounceInterval; ptpClock->announceReceiptTimeout = rtOpts->announceReceiptTimeout; ptpClock->logSyncInterval = rtOpts->logSyncInterval; ptpClock->delayMechanism = rtOpts->delayMechanism; ptpClock->logMinPdelayReqInterval = rtOpts->logMinPdelayReqInterval; ptpClock->versionNumber = VERSION_PTP; if(rtOpts->dot1AS) { ptpClock->transportSpecific = TSP_ETHERNET_AVB; } else { ptpClock->transportSpecific = TSP_DEFAULT; } /* * Initialize random number generator using same method as ptpv1: * seed is now initialized from the last bytes of our mac addres (collected in net.c:findIface()) */ srand((ptpClock->netPath.interfaceID[PTP_UUID_LENGTH - 1] << 8) + ptpClock->netPath.interfaceID[PTP_UUID_LENGTH - 2]); /*Init other stuff*/ ptpClock->number_foreign_records = 0; ptpClock->max_foreign_records = rtOpts->max_foreign_records; }