void addForeign(Octet *buf,MsgHeader *header,PtpClock *ptpClock) { int i,j; Boolean found = FALSE; j = ptpClock->foreign_record_best; /*Check if Foreign master is already known*/ for (i=0;i<ptpClock->number_foreign_records;i++) { if (!memcmp(header->sourcePortIdentity.clockIdentity, ptpClock->foreign[j].foreignMasterPortIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH) && (header->sourcePortIdentity.portNumber == ptpClock->foreign[j].foreignMasterPortIdentity.portNumber)) { /*Foreign Master is already in Foreignmaster data set*/ ptpClock->foreign[j].foreignMasterAnnounceMessages++; found = TRUE; DBGV("addForeign : AnnounceMessage incremented \n"); msgUnpackHeader(buf,&ptpClock->foreign[j].header); msgUnpackAnnounce(buf,&ptpClock->foreign[j].announce); break; } j = (j+1)%ptpClock->number_foreign_records; } /*New Foreign Master*/ if (!found) { if (ptpClock->number_foreign_records < ptpClock->max_foreign_records) { ptpClock->number_foreign_records++; } j = ptpClock->foreign_record_i; /*Copy new foreign master data set from Announce message*/ memcpy(ptpClock->foreign[j].foreignMasterPortIdentity.clockIdentity, header->sourcePortIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH); ptpClock->foreign[j].foreignMasterPortIdentity.portNumber = header->sourcePortIdentity.portNumber; ptpClock->foreign[j].foreignMasterAnnounceMessages = 0; /* * header and announce field of each Foreign Master are * usefull to run Best Master Clock Algorithm */ msgUnpackHeader(buf,&ptpClock->foreign[j].header); msgUnpackAnnounce(buf,&ptpClock->foreign[j].announce); DBGV("New foreign Master added \n"); ptpClock->foreign_record_i = (ptpClock->foreign_record_i+1) % ptpClock->max_foreign_records; } }
/*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) }
/*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) */ }