UInteger8 bmcStateDecision(MsgHeader *header, MsgSync *sync, RunTimeOpts *rtOpts, PtpClock *ptpClock) { if(rtOpts->slaveOnly) { s1(header, sync, ptpClock); return PTP_SLAVE; } copyD0(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.sync, ptpClock); if(ptpClock->msgTmp.sync.grandmasterClockStratum < 3) { if(bmcDataSetComparison(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.sync, header, sync, ptpClock) > 0) { m1(ptpClock); return PTP_MASTER; } s1(header, sync, ptpClock); return PTP_PASSIVE; } else if(bmcDataSetComparison(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.sync, header, sync, ptpClock) > 0 && ptpClock->msgTmp.sync.grandmasterClockStratum != 255) { m1(ptpClock); return PTP_MASTER; } else { s1(header, sync, ptpClock); return PTP_SLAVE; } }
UInteger8 bmcStateDecision(MsgHeader *header, // PTP header info MsgSync *sync, // Sync message data RunTimeOpts *rtOpts, // Run time options PtpClock *ptpClock // Main PTP data structure ) { /* Test if run time option is set for Slave only, * if so, run s1 and return SLAVE state */ if(rtOpts->slaveOnly) { s1(header, sync, ptpClock); return PTP_SLAVE; } copyD0(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.sync, ptpClock); if(ptpClock->msgTmp.sync.grandmasterClockStratum < 3) { /* Grandmaster Statum is less than 3 (accurate clock) */ if( bmcDataSetComparison(&ptpClock->msgTmpHeader, // Current RX PTP header &ptpClock->msgTmp.sync, // Current RX SYNC data header, sync, ptpClock ) > 0 ) { /* Stratum is less 3 and we are a better clock, run m1 and return MASTER state */ m1(ptpClock); return PTP_MASTER; } s1(header, sync, ptpClock); return PTP_PASSIVE; } else if(bmcDataSetComparison(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.sync, header, sync, ptpClock ) > 0 && ptpClock->msgTmp.sync.grandmasterClockStratum != 255 ) { /* Grandmaster stratum is 3 or more, but not equal to 255 and we are a better clock, * return MASTER */ m1(ptpClock); return PTP_MASTER; } else { /* Grandmaster stratum is 255 or we are not a better clock, return SLAVE state */ s1(header, sync, ptpClock); return PTP_SLAVE; } }
UInteger8 bmc(ForeignMasterRecord *foreignMaster, RunTimeOpts *rtOpts, PtpClock *ptpClock) { Integer16 i,best; DBGV("number_foreign_records : %d \n", ptpClock->number_foreign_records); if (!ptpClock->number_foreign_records) if (ptpClock->portState == PTP_MASTER) { m1(rtOpts,ptpClock); return ptpClock->portState; } for (i=1,best = 0; i<ptpClock->number_foreign_records;i++) if ((bmcDataSetComparison(&foreignMaster[i].header, &foreignMaster[i].announce, &foreignMaster[best].header, &foreignMaster[best].announce, ptpClock)) < 0) best = i; DBGV("Best record : %d \n",best); ptpClock->foreign_record_best = best; return (bmcStateDecision(&foreignMaster[best].header, &foreignMaster[best].announce, rtOpts,ptpClock)); }
UInteger8 bmc(ForeignMasterRecord *foreign, RunTimeOpts *rtOpts, PtpClock *ptpClock ) { Integer16 i, best; /* Check if any foreign masters */ if(!ptpClock->number_foreign_records) { DBGV("bmc: number_foreign_records is zero, state: %u\n", ptpClock->port_state ); /* No foreign masters, run m1 if we are currently master */ if(ptpClock->port_state == PTP_MASTER) { DBGV("bmc: calling m1\n"); m1(ptpClock); } return ptpClock->port_state; /* no change */ } DBGV("bmc: number_foreign_records is non zero, state: %u\n", ptpClock->port_state ); /* There is at least one foreign master. Scan through foreign master database and compare * to look for best master to use */ for(i = 1, best = 0; i < ptpClock->number_foreign_records; ++i) { /* Check current loop indx record versus current "best" record */ if(bmcDataSetComparison(&foreign[i].header, &foreign[i].sync, &foreign[best].header, &foreign[best].sync, ptpClock ) > 0) { /* Current loop index is better than previous "best", set new "best" */ best = i; } DBGV("bmc: comparison loop i=%d, best=%d\n",i,best); } /* Best record found, store index to best foreign master */ DBGV("bmc: best record %d\n", best); ptpClock->foreign_record_best = best; /* Now that best is found, determine recommended state */ return bmcStateDecision(&foreign[best].header, &foreign[best].sync, rtOpts, ptpClock ); }
/*State decision algorithm 9.3.3 Fig 26*/ UInteger8 bmcStateDecision(MsgHeader *header, MsgAnnounce *announce, RunTimeOpts *rtOpts, PtpClock *ptpClock) { Integer8 comp; if (rtOpts->slaveOnly) { s1(header,announce,ptpClock, rtOpts); return PTP_SLAVE; } if ((!ptpClock->number_foreign_records) && (ptpClock->portState == PTP_LISTENING)) return PTP_LISTENING; copyD0(&ptpClock->msgTmpHeader,&ptpClock->msgTmp.announce,ptpClock); DBGV("local clockQuality.clockClass: %d \n", ptpClock->clockQuality.clockClass); comp = bmcDataSetComparison(&ptpClock->msgTmpHeader, &ptpClock->msgTmp.announce, header, announce, ptpClock); if (ptpClock->clockQuality.clockClass < 128) { if (comp < 0) { m1(rtOpts, ptpClock); return PTP_MASTER; } else if (comp > 0) { s1(header,announce,ptpClock, rtOpts); return PTP_PASSIVE; } else { DBG("Error in bmcDataSetComparison..\n"); } } else { if (comp < 0) { m1(rtOpts,ptpClock); return PTP_MASTER; } else if (comp > 0) { s1(header,announce,ptpClock, rtOpts); return PTP_SLAVE; } else { DBG("Error in bmcDataSetComparison..\n"); } } /* MB: Is this the return code below correct? */ /* Anyway, it's a valid return code. */ return PTP_FAULTY; }
UInteger8 bmc(ForeignMasterRecord *foreign, RunTimeOpts *rtOpts, PtpClock *ptpClock) { Integer16 i, best; if(!ptpClock->number_foreign_records) { if(ptpClock->port_state == PTP_MASTER) m1(ptpClock); return ptpClock->port_state; /* no change */ } for(i = 1, best = 0; i < ptpClock->number_foreign_records; ++i) { if(bmcDataSetComparison(&foreign[i].header, &foreign[i].sync, &foreign[best].header, &foreign[best].sync, ptpClock) > 0) best = i; } DBGV("bmc: best record %d\n", best); ptpClock->foreign_record_best = best; return bmcStateDecision(&foreign[best].header, &foreign[best].sync, rtOpts, ptpClock); }