/*spec 9.5.3*/ static void handleAnnounce(PtpClock *ptpClock, Boolean isFromSelf) { Boolean isFromCurrentParent = FALSE; DBGV("handleAnnounce: received\n"); if (ptpClock->msgIbufLength < ANNOUNCE_LENGTH) { ERROR("handleAnnounce: short message\n"); toState(ptpClock, PTP_FAULTY); return; } if (isFromSelf) { DBGV("handleAnnounce: ignore from self\n"); return; } switch (ptpClock->portDS.portState) { case PTP_INITIALIZING: case PTP_FAULTY: case PTP_DISABLED: DBGV("handleAnnounce: disreguard\n"); break; case PTP_UNCALIBRATED: case PTP_SLAVE: /* Valid announce message is received : BMC algorithm will be executed */ setFlag(ptpClock->events, STATE_DECISION_EVENT); isFromCurrentParent = isSamePortIdentity( &ptpClock->parentDS.parentPortIdentity, &ptpClock->msgTmpHeader.sourcePortIdentity); msgUnpackAnnounce(ptpClock->msgIbuf, &ptpClock->msgTmp.announce); if (isFromCurrentParent) { s1(ptpClock, &ptpClock->msgTmpHeader, &ptpClock->msgTmp.announce); /*Reset Timer handling Announce receipt timeout*/ timerStart(ANNOUNCE_RECEIPT_TIMER, (ptpClock->portDS.announceReceiptTimeout)*(pow2ms(ptpClock->portDS.logAnnounceInterval)), ptpClock->itimer); } else { DBGV("handleAnnounce: from another foreign master\n"); /*addForeign takes care of AnnounceUnpacking*/ addForeign(ptpClock, &ptpClock->msgTmpHeader, &ptpClock->msgTmp.announce); } break; case PTP_PASSIVE: timerStart(ANNOUNCE_RECEIPT_TIMER, (ptpClock->portDS.announceReceiptTimeout)*(pow2ms(ptpClock->portDS.logAnnounceInterval)), ptpClock->itimer); case PTP_MASTER: case PTP_PRE_MASTER: case PTP_LISTENING: default : DBGV("handleAnnounce: from another foreign master\n"); msgUnpackAnnounce(ptpClock->msgIbuf, &ptpClock->msgTmp.announce); /* Valid announce message is received : BMC algorithm will be executed */ setFlag(ptpClock->events, STATE_DECISION_EVENT); addForeign(ptpClock, &ptpClock->msgTmpHeader, &ptpClock->msgTmp.announce); break; }//switch on (portState) }
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; } }
/*spec 9.5.3*/ void handleAnnounce(MsgHeader *header, Octet *msgIbuf, ssize_t length, Boolean isFromSelf, RunTimeOpts *rtOpts, PtpClock *ptpClock) { Boolean isFromCurrentParent = FALSE; DBGV("HandleAnnounce : Announce message received : \n"); if(length < ANNOUNCE_LENGTH) { ERROR("short Announce message\n"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } //DBGV(" >> HandleAnnounce : %d \n", ptpClock->portState); switch (ptpClock->portState) { case PTP_INITIALIZING: case PTP_FAULTY: case PTP_DISABLED: DBG("Handleannounce : disregard\n"); return; case PTP_UNCALIBRATED: case PTP_SLAVE: if (isFromSelf) { DBGV("HandleAnnounce : Ignore message from self \n"); return; } /* * Valid announce message is received : BMC algorithm * will be executed */ ptpClock->record_update = TRUE; isFromCurrentParent = !memcmp( ptpClock->parentPortIdentity.clockIdentity, header->sourcePortIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH) && (ptpClock->parentPortIdentity.portNumber == header->sourcePortIdentity.portNumber); switch (isFromCurrentParent) { case TRUE: msgUnpackAnnounce(ptpClock->msgIbuf, &ptpClock->msgTmp.announce); /* update datasets (file bmc.c) */ s1(header,&ptpClock->msgTmp.announce,ptpClock, rtOpts); DBG2("___ Announce: received Announce from current Master, so reset the Announce timer\n"); /*Reset Timer handling Announce receipt timeout*/ timerStart(ANNOUNCE_RECEIPT_TIMER, (ptpClock->announceReceiptTimeout) * (pow(2,ptpClock->logAnnounceInterval)), ptpClock->itimer); #ifdef PTP_EXPERIMENTAL // remember IP address of our master for -U option // todo: add this to bmc(), to cover the very first packet ptpClock->MasterAddr = ptpClock->netPath.lastRecvAddr; #endif break; case FALSE: /*addForeign takes care of AnnounceUnpacking*/ /* the actual decision to change masters is only done in doState() / record_update == TRUE / bmc() */ /* the original code always called: addforeign(new master) + timerstart(announce) */ addForeign(ptpClock->msgIbuf,header,ptpClock); timerStart(ANNOUNCE_RECEIPT_TIMER, (ptpClock->announceReceiptTimeout) * (pow(2,ptpClock->logAnnounceInterval)), ptpClock->itimer); break; default: DBG("HandleAnnounce : (isFromCurrentParent)" "strange value ! \n"); return; } /* switch on (isFromCurrentParrent) */ break; /* * Passive case: previously, this was handled in the default, just like the master case. * This the announce would call addForeign(), but NOT reset the timer, so after 12s it would expire and we would come alive periodically * * This code is now merged with the slave case to reset the timer, and call addForeign() if it's a third master * */ case PTP_PASSIVE: if (isFromSelf) { DBGV("HandleAnnounce : Ignore message from self \n"); return; } /* * Valid announce message is received : BMC algorithm * will be executed */ ptpClock->record_update = TRUE; isFromCurrentParent = !memcmp( ptpClock->parentPortIdentity.clockIdentity, header->sourcePortIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH) && (ptpClock->parentPortIdentity.portNumber == header->sourcePortIdentity.portNumber); if (isFromCurrentParent) { msgUnpackAnnounce(ptpClock->msgIbuf, &ptpClock->msgTmp.announce); /* TODO: not in spec * datasets should not be updated by another master * this is the reason why we are PASSIVE and not SLAVE * this should be p1(ptpClock, rtOpts); */ /* update datasets (file bmc.c) */ s1(header,&ptpClock->msgTmp.announce,ptpClock, rtOpts); DBG("___ Announce: received Announce from current Master, so reset the Announce timer\n\n"); /*Reset Timer handling Announce receipt timeout*/ timerStart(ANNOUNCE_RECEIPT_TIMER, (ptpClock->announceReceiptTimeout) * (pow(2,ptpClock->logAnnounceInterval)), ptpClock->itimer); } else { /*addForeign takes care of AnnounceUnpacking*/ /* the actual decision to change masters is only done in doState() / record_update == TRUE / bmc() */ /* the original code always called: addforeign(new master) + timerstart(announce) */ DBG("___ Announce: received Announce from another master, will add to the list, as it might be better\n\n"); DBGV("this is to be decided immediatly by bmc())\n\n"); addForeign(ptpClock->msgIbuf,header,ptpClock); } break; case PTP_MASTER: case PTP_LISTENING: /* listening mode still causes timeouts in order to send IGMP refreshes */ default : if (isFromSelf) { DBGV("HandleAnnounce : Ignore message from self \n"); return; } DBGV("Announce message from another foreign master\n"); addForeign(ptpClock->msgIbuf,header,ptpClock); ptpClock->record_update = TRUE; /* run BMC() as soon as possible */ break; } /* switch on (port_state) */ }