diff --git a/src/ca/bhe.cpp b/src/ca/bhe.cpp index 3b842d107..cc3700c02 100644 --- a/src/ca/bhe.cpp +++ b/src/ca/bhe.cpp @@ -65,13 +65,15 @@ void bhe::beaconAnomalyNotify () * updates beacon period, and looks for beacon anomalies */ bool bhe::updatePeriod ( const epicsTime & programBeginTime, - const epicsTime & currentTime ) + const epicsTime & currentTime, unsigned beaconNumber, + unsigned protocolRevision ) { - double currentPeriod; - bool netChange = false; - if ( this->timeStamp == epicsTime () ) { + if ( CA_V410 ( protocolRevision ) ) { + this->lastBeaconNumber = beaconNumber; + } + this->beaconAnomalyNotify (); /* @@ -82,13 +84,23 @@ bool bhe::updatePeriod ( const epicsTime & programBeginTime, */ this->timeStamp = currentTime; - return netChange; + return false; + } + + // detect beacon duplications due to IP redundant packet routes + if ( CA_V410 ( protocolRevision ) ) { + unsigned lastBeaconNumberSave = this->lastBeaconNumber; + this->lastBeaconNumber = beaconNumber; + if ( beaconNumber != lastBeaconNumberSave + 1 ) { + return false; + } } /* * compute the beacon period (if we have seen at least two beacons) */ - currentPeriod = currentTime - this->timeStamp; + bool netChange = false; + double currentPeriod = currentTime - this->timeStamp; if ( this->averagePeriod < 0.0 ) { double totalRunningTime; diff --git a/src/ca/bhe.h b/src/ca/bhe.h index 95ea8be4e..7ab3743ef 100644 --- a/src/ca/bhe.h +++ b/src/ca/bhe.h @@ -16,6 +16,7 @@ #include "shareLib.h" +#include #include #ifdef epicsExportSharedSymbols @@ -42,7 +43,8 @@ public: epicsShareFunc bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ); epicsShareFunc void destroy (); epicsShareFunc bool updatePeriod ( const epicsTime & programBeginTime, - const epicsTime & currentTime ); + const epicsTime & currentTime, unsigned beaconNumber, + unsigned protocolRevision ); epicsShareFunc double period () const; epicsShareFunc void show ( unsigned level) const; epicsShareFunc void registerIIU ( tcpiiu & ); @@ -55,6 +57,7 @@ private: tsDLList < tcpiiu > iiuList; epicsTime timeStamp; double averagePeriod; + unsigned lastBeaconNumber; void beaconAnomalyNotify (); static tsFreeList < class bhe, 1024 > freeList; static epicsMutex freeListMutex; @@ -77,7 +80,8 @@ private: * between the 1st and 2nd beacons) */ inline bhe::bhe ( const epicsTime & initialTimeStamp, const inetAddrID & addr ) : - inetAddrID ( addr ), timeStamp ( initialTimeStamp ), averagePeriod ( - DBL_MAX ) + inetAddrID ( addr ), timeStamp ( initialTimeStamp ), averagePeriod ( - DBL_MAX ), + lastBeaconNumber ( UINT_MAX ) { # ifdef DEBUG { diff --git a/src/ca/caProto.h b/src/ca/caProto.h index 7b4dc4fb5..7028e29ee 100644 --- a/src/ca/caProto.h +++ b/src/ca/caProto.h @@ -52,6 +52,7 @@ # define CA_V47(MINOR) ((MINOR)>=7u) # define CA_V48(MINOR) ((MINOR)>=8u) # define CA_V49(MINOR) ((MINOR)>=9u) +# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */ #elif CA_MAJOR_PROTOCOL_REVISION > 4u # define CA_V41(MINOR) ( 1u ) # define CA_V42(MINOR) ( 1u ) @@ -62,6 +63,7 @@ # define CA_V47(MINOR) ( 1u ) # define CA_V48(MINOR) ( 1u ) # define CA_V49(MINOR) ( 1u ) +# define CA_V410(MINOR) ( 1u ) #else # define CA_V41(MINOR) ( 0u ) # define CA_V42(MINOR) ( 0u ) @@ -72,6 +74,7 @@ # define CA_V47(MINOR) ( 0u ) # define CA_V48(MINOR) ( 0u ) # define CA_V49(MINOR) ( 0u ) +# define CA_V410(MINOR) ( 0u ) #endif /* diff --git a/src/ca/cac.h b/src/ca/cac.h index 4f7ad6b11..6b4141fa7 100644 --- a/src/ca/cac.h +++ b/src/ca/cac.h @@ -59,8 +59,8 @@ public: virtual ~cac (); // beacon management - void beaconNotify ( const inetAddrID & addr, - const epicsTime & currentTime ); + void beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime, + unsigned beaconNumber, unsigned protocolRevision ); void repeaterSubscribeConfirmNotify (); // outstanding IO count management routines @@ -172,7 +172,7 @@ private: epicsMutex callbackMutex; epicsEvent ioDone; epicsEvent noRecvThreadsPending; - epicsEvent iiuUninstal; + epicsEvent iiuUninstall; epicsTimerQueueActive & timerQueue; char * pUserName; class udpiiu * pudpiiu; @@ -192,7 +192,6 @@ private: void privateUninstallIIU ( tcpiiu &iiu ); void flushRequestPrivate (); - void uninstallChannelPrivate ( nciu & ); void run (); bool setupUDP (); void connectAllIO ( nciu &chan ); diff --git a/src/ca/casw.cpp b/src/ca/casw.cpp index 8348cbda5..86a0251a4 100644 --- a/src/ca/casw.cpp +++ b/src/ca/casw.cpp @@ -121,8 +121,15 @@ int main ( int, char ** ) continue; } + unsigned byteCount = static_cast ( status ); pCurMsg = reinterpret_cast < const caHdr * > ( ( pCurBuf = buf ) ); - while ( status >= static_cast < int > ( sizeof ( *pCurMsg ) ) ) { + while ( byteCount ) { + size_t msgSize = epicsNTOH32 ( pCurMsg->m_postsize ) + sizeof (*pCurMsg) ; + if ( msgSize > byteCount ) { + errlogPrintf ( "CASW: udp input protocol violation\n" ); + break; + } + if ( epicsNTOH16 ( pCurMsg->m_cmmd ) == CA_PROTO_RSRV_IS_UP ) { struct sockaddr_in ina; @@ -154,6 +161,9 @@ int main ( int, char ** ) ina.sin_port = epicsNTOH16 ( serverPort ); } + unsigned beaconNumber = ntohl ( pCurMsg->m_cid ); + unsigned protocolRevision = ntohs ( pCurMsg->m_dataType ); + bool netChange; epicsTime currentTime = epicsTime::getCurrent(); @@ -162,7 +172,7 @@ int main ( int, char ** ) */ bhe *pBHE = beaconTable.lookup ( ina ); if ( pBHE ) { - netChange = pBHE->updatePeriod ( programBeginTime, currentTime ); + netChange = pBHE->updatePeriod ( programBeginTime, currentTime, beaconNumber, protocolRevision ); } else { /* @@ -189,9 +199,9 @@ int main ( int, char ** ) errlogPrintf ("CA server beacon anomaly: %s %s\n", date, host ); } } - pCurBuf += sizeof ( *pCurMsg ) + epicsNTOH32 ( pCurMsg->m_postsize ); + pCurBuf += msgSize; pCurMsg = reinterpret_cast < const caHdr * > ( pCurBuf ); - status -= sizeof ( *pCurMsg ) + epicsNTOH32 ( pCurMsg->m_postsize ); + byteCount -= msgSize; } } } diff --git a/src/ca/udpiiu.cpp b/src/ca/udpiiu.cpp index 84a1c5cb9..03b9e6fa6 100644 --- a/src/ca/udpiiu.cpp +++ b/src/ca/udpiiu.cpp @@ -608,17 +608,20 @@ bool udpiiu::beaconAction ( const caHdr &msg, ina.sin_family = AF_INET; ina.sin_addr.s_addr = msg.m_available; if ( msg.m_count != 0 ) { - ina.sin_port = epicsHTON16 ( msg.m_count ); + ina.sin_port = epicsNTOH16 ( msg.m_count ); } else { /* * old servers dont supply this and the * default port must be assumed */ - ina.sin_port = epicsHTON16 ( this->serverPort ); + ina.sin_port = epicsNTOH16 ( this->serverPort ); } + unsigned protocolRevision = epicsNTOH16 ( msg.m_dataType ); + unsigned beaconNumber = epicsNTOH32 ( msg.m_cid ); - this->pCAC ()->beaconNotify ( ina, currentTime ); + this->pCAC ()->beaconNotify ( ina, currentTime, + beaconNumber, protocolRevision ); return true; }