diff options
Diffstat (limited to 'daemons/gptp/common/ether_port.cpp')
-rw-r--r-- | daemons/gptp/common/ether_port.cpp | 864 |
1 files changed, 864 insertions, 0 deletions
diff --git a/daemons/gptp/common/ether_port.cpp b/daemons/gptp/common/ether_port.cpp new file mode 100644 index 00000000..2325fb99 --- /dev/null +++ b/daemons/gptp/common/ether_port.cpp @@ -0,0 +1,864 @@ +/****************************************************************************** + + Copyright (c) 2009-2012, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#include <ieee1588.hpp> + +#include <ether_port.hpp> +#include <avbts_message.hpp> +#include <avbts_clock.hpp> + +#include <avbts_oslock.hpp> +#include <avbts_osnet.hpp> +#include <avbts_oscondition.hpp> +#include <ether_tstamper.hpp> + +#include <gptp_log.hpp> + +#include <stdio.h> + +#include <math.h> + +#include <stdlib.h> + +LinkLayerAddress EtherPort::other_multicast(OTHER_MULTICAST); +LinkLayerAddress EtherPort::pdelay_multicast(PDELAY_MULTICAST); +LinkLayerAddress EtherPort::test_status_multicast +( TEST_STATUS_MULTICAST ); + +OSThreadExitCode watchNetLinkWrapper(void *arg) +{ + EtherPort *port; + + port = (EtherPort *) arg; + if (port->watchNetLink() == NULL) + return osthread_ok; + else + return osthread_error; +} + +OSThreadExitCode openPortWrapper(void *arg) +{ + EtherPort *port; + + port = (EtherPort *) arg; + if (port->openPort(port) == NULL) + return osthread_ok; + else + return osthread_error; +} + +EtherPort::~EtherPort() +{ + delete port_ready_condition; +} + +EtherPort::EtherPort( PortInit_t *portInit ) : + CommonPort( portInit ) +{ + automotive_profile = portInit->automotive_profile; + linkUp = portInit->linkUp; + setTestMode( portInit->testMode ); + + pdelay_sequence_id = 0; + + pdelay_started = false; + pdelay_halted = false; + sync_rate_interval_timer_started = false; + + duplicate_resp_counter = 0; + last_invalid_seqid = 0; + + initialLogPdelayReqInterval = portInit->initialLogPdelayReqInterval; + operLogPdelayReqInterval = portInit->operLogPdelayReqInterval; + operLogSyncInterval = portInit->operLogSyncInterval; + + if (automotive_profile) { + setAsCapable( true ); + + if (getInitSyncInterval() == LOG2_INTERVAL_INVALID) + setInitSyncInterval( -5 ); // 31.25 ms + if (initialLogPdelayReqInterval == LOG2_INTERVAL_INVALID) + initialLogPdelayReqInterval = 0; // 1 second + if (operLogPdelayReqInterval == LOG2_INTERVAL_INVALID) + operLogPdelayReqInterval = 0; // 1 second + if (operLogSyncInterval == LOG2_INTERVAL_INVALID) + operLogSyncInterval = 0; // 1 second + } + else { + setAsCapable( false ); + + if ( getInitSyncInterval() == LOG2_INTERVAL_INVALID ) + setInitSyncInterval( -3 ); // 125 ms + if (initialLogPdelayReqInterval == LOG2_INTERVAL_INVALID) + initialLogPdelayReqInterval = 0; // 1 second + if (operLogPdelayReqInterval == LOG2_INTERVAL_INVALID) + operLogPdelayReqInterval = 0; // 1 second + if (operLogSyncInterval == LOG2_INTERVAL_INVALID) + operLogSyncInterval = 0; // 1 second + } + + /*TODO: Add intervals below to a config interface*/ + log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; + + last_sync = NULL; + last_pdelay_req = NULL; + last_pdelay_resp = NULL; + last_pdelay_resp_fwup = NULL; + + setPdelayCount(0); + setSyncCount(0); + + if (automotive_profile) { + if (isGM) { + avbSyncState = 1; + } + else { + avbSyncState = 2; + } + if (getTestMode()) + { + linkUpCount = 1; // TODO : really should check the current linkup status http://stackoverflow.com/questions/15723061/how-to-check-if-interface-is-up + linkDownCount = 0; + } + setStationState(STATION_STATE_RESERVED); + } +} + +bool EtherPort::_init_port( void ) +{ + pdelay_rx_lock = lock_factory->createLock(oslock_recursive); + port_tx_lock = lock_factory->createLock(oslock_recursive); + + pDelayIntervalTimerLock = lock_factory->createLock(oslock_recursive); + + port_ready_condition = condition_factory->createCondition(); + + return true; +} + +void EtherPort::startPDelay() +{ + if(!pdelayHalted()) { + if (automotive_profile) { + if (log_min_mean_pdelay_req_interval != PTPMessageSignalling::sigMsgInterval_NoSend) { + long long unsigned int waitTime; + waitTime = ((long long) (pow((double)2, log_min_mean_pdelay_req_interval) * 1000000000.0)); + waitTime = waitTime > EVENT_TIMER_GRANULARITY ? waitTime : EVENT_TIMER_GRANULARITY; + pdelay_started = true; + startPDelayIntervalTimer(waitTime); + } + } + else { + pdelay_started = true; + startPDelayIntervalTimer(32000000); + } + } +} + +void EtherPort::stopPDelay() +{ + haltPdelay(true); + pdelay_started = false; + clock->deleteEventTimerLocked( this, PDELAY_INTERVAL_TIMEOUT_EXPIRES); +} + +void EtherPort::startSyncRateIntervalTimer() +{ + if (automotive_profile) { + sync_rate_interval_timer_started = true; + if (isGM) { + // GM will wait up to 8 seconds for signaling rate + // TODO: This isn't according to spec but set because it is believed that some slave devices aren't signalling + // to reduce the rate + clock->addEventTimerLocked( this, SYNC_RATE_INTERVAL_TIMEOUT_EXPIRED, 8000000000 ); + } + else { + // Slave will time out after 4 seconds + clock->addEventTimerLocked( this, SYNC_RATE_INTERVAL_TIMEOUT_EXPIRED, 4000000000 ); + } + } +} + +void EtherPort::processMessage +( char *buf, int length, LinkLayerAddress *remote, uint32_t link_speed ) +{ + GPTP_LOG_VERBOSE("Processing network buffer"); + + PTPMessageCommon *msg = + buildPTPMessage( buf, (int)length, remote, this ); + + if (msg == NULL) + { + GPTP_LOG_ERROR("Discarding invalid message"); + return; + } + GPTP_LOG_VERBOSE("Processing message"); + + if( msg->isEvent() ) + { + Timestamp rx_timestamp = msg->getTimestamp(); + Timestamp phy_compensation = getRxPhyDelay( link_speed ); + GPTP_LOG_DEBUG( "RX PHY compensation: %s sec", + phy_compensation.toString().c_str() ); + phy_compensation._version = rx_timestamp._version; + rx_timestamp = rx_timestamp - phy_compensation; + msg->setTimestamp( rx_timestamp ); + } + + msg->processMessage(this); + if (msg->garbage()) + delete msg; +} + +void *EtherPort::openPort( EtherPort *port ) +{ + port_ready_condition->signal(); + + while (1) { + uint8_t buf[128]; + LinkLayerAddress remote; + net_result rrecv; + size_t length = sizeof(buf); + uint32_t link_speed; + + if ( ( rrecv = recv( &remote, buf, length, link_speed )) + == net_succeed ) + { + processMessage + ((char *)buf, (int)length, &remote, link_speed ); + } else if (rrecv == net_fatal) { + GPTP_LOG_ERROR("read from network interface failed"); + this->processEvent(FAULT_DETECTED); + break; + } + } + + return NULL; +} + +net_result EtherPort::port_send +( uint16_t etherType, uint8_t *buf, int size, MulticastType mcast_type, + PortIdentity *destIdentity, bool timestamp ) +{ + LinkLayerAddress dest; + + if (mcast_type != MCAST_NONE) { + if (mcast_type == MCAST_PDELAY) { + dest = pdelay_multicast; + } + else if (mcast_type == MCAST_TEST_STATUS) { + dest = test_status_multicast; + } + else { + dest = other_multicast; + } + } else { + mapSocketAddr(destIdentity, &dest); + } + + return send(&dest, etherType, (uint8_t *) buf, size, timestamp); +} + +void EtherPort::sendEventPort +( uint16_t etherType, uint8_t *buf, int size, MulticastType mcast_type, + PortIdentity *destIdentity, uint32_t *link_speed ) +{ + net_result rtx = port_send + ( etherType, buf, size, mcast_type, destIdentity, true ); + if( rtx != net_succeed ) + { + GPTP_LOG_ERROR("sendEventPort(): failure"); + return; + } + + *link_speed = this->getLinkSpeed(); + + return; +} + +void EtherPort::sendGeneralPort +( uint16_t etherType, uint8_t *buf, int size, MulticastType mcast_type, + PortIdentity * destIdentity ) +{ + net_result rtx = port_send(etherType, buf, size, mcast_type, destIdentity, false); + if (rtx != net_succeed) { + GPTP_LOG_ERROR("sendGeneralPort(): failure"); + } + + return; +} + +bool EtherPort::_processEvent( Event e ) +{ + bool ret; + + switch (e) { + case POWERUP: + case INITIALIZE: + if (!automotive_profile) { + if ( getPortState() != PTP_SLAVE && + getPortState() != PTP_MASTER ) + { + GPTP_LOG_STATUS("Starting PDelay"); + startPDelay(); + } + } + else { + startPDelay(); + } + + port_ready_condition->wait_prelock(); + + if( !linkWatch(watchNetLinkWrapper, (void *)this) ) + { + GPTP_LOG_ERROR("Error creating port link thread"); + ret = false; + break; + } + + if( !linkOpen(openPortWrapper, (void *)this) ) + { + GPTP_LOG_ERROR("Error creating port thread"); + ret = false; + break; + } + + port_ready_condition->wait(); + + if (automotive_profile) { + setStationState(STATION_STATE_ETHERNET_READY); + if (getTestMode()) + { + APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); + if (testStatusMsg) { + testStatusMsg->sendPort(this); + delete testStatusMsg; + } + } + if (!isGM) { + // Send an initial signalling message + PTPMessageSignalling *sigMsg = new PTPMessageSignalling(this); + if (sigMsg) { + sigMsg->setintervals(PTPMessageSignalling::sigMsgInterval_NoSend, getSyncInterval(), PTPMessageSignalling::sigMsgInterval_NoSend); + sigMsg->sendPort(this, NULL); + delete sigMsg; + } + + startSyncReceiptTimer((unsigned long long) + (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * + ((double) pow((double)2, getSyncInterval()) * + 1000000000.0))); + } + } + + ret = true; + break; + case STATE_CHANGE_EVENT: + // If the automotive profile is enabled, handle the event by + // doing nothing and returning true, preventing the default + // action from executing + if( automotive_profile ) + ret = true; + else + ret = false; + + break; + case LINKUP: + haltPdelay(false); + startPDelay(); + if (automotive_profile) { + GPTP_LOG_EXCEPTION("LINKUP"); + } + else { + GPTP_LOG_STATUS("LINKUP"); + } + + if( clock->getPriority1() == 255 || getPortState() == PTP_SLAVE ) { + becomeSlave( true ); + } else if( getPortState() == PTP_MASTER ) { + becomeMaster( true ); + } else { + clock->addEventTimerLocked(this, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES, + ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER * pow(2.0, getAnnounceInterval()) * 1000000000.0); + } + + if (automotive_profile) { + setAsCapable( true ); + + setStationState(STATION_STATE_ETHERNET_READY); + if (getTestMode()) + { + APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); + if (testStatusMsg) { + testStatusMsg->sendPort(this); + delete testStatusMsg; + } + } + + resetInitSyncInterval(); + setAnnounceInterval( 0 ); + log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; + + if (!isGM) { + // Send an initial signaling message + PTPMessageSignalling *sigMsg = new PTPMessageSignalling(this); + if (sigMsg) { + sigMsg->setintervals(PTPMessageSignalling::sigMsgInterval_NoSend, getSyncInterval(), PTPMessageSignalling::sigMsgInterval_NoSend); + sigMsg->sendPort(this, NULL); + delete sigMsg; + } + + startSyncReceiptTimer((unsigned long long) + (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * + ((double) pow((double)2, getSyncInterval()) * + 1000000000.0))); + } + + // Reset Sync count and pdelay count + setPdelayCount(0); + setSyncCount(0); + + // Start AVB SYNC at 2. It will decrement after each sync. When it reaches 0 the Test Status message + // can be sent + if (isGM) { + avbSyncState = 1; + } + else { + avbSyncState = 2; + } + + if (getTestMode()) + { + linkUpCount++; + } + } + this->timestamper_reset(); + + ret = true; + break; + case LINKDOWN: + stopPDelay(); + if (automotive_profile) { + GPTP_LOG_EXCEPTION("LINK DOWN"); + } + else { + setAsCapable(false); + GPTP_LOG_STATUS("LINK DOWN"); + } + if (getTestMode()) + { + linkDownCount++; + } + + ret = true; + break; + case ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES: + case SYNC_RECEIPT_TIMEOUT_EXPIRES: + if( !automotive_profile ) + { + ret = false; + break; + } + + // Automotive Profile specific action + if (e == SYNC_RECEIPT_TIMEOUT_EXPIRES) { + GPTP_LOG_EXCEPTION("SYNC receipt timeout"); + + startSyncReceiptTimer((unsigned long long) + (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * + ((double) pow((double)2, getSyncInterval()) * + 1000000000.0))); + } + ret = true; + break; + case PDELAY_INTERVAL_TIMEOUT_EXPIRES: + GPTP_LOG_DEBUG("PDELAY_INTERVAL_TIMEOUT_EXPIRES occured"); + { + Timestamp req_timestamp; + + PTPMessagePathDelayReq *pdelay_req = + new PTPMessagePathDelayReq(this); + PortIdentity dest_id; + getPortIdentity(dest_id); + pdelay_req->setPortIdentity(&dest_id); + + { + Timestamp pending = + PDELAY_PENDING_TIMESTAMP; + pdelay_req->setTimestamp(pending); + } + + if (last_pdelay_req != NULL) { + delete last_pdelay_req; + } + setLastPDelayReq(pdelay_req); + + getTxLock(); + pdelay_req->sendPort(this, NULL); + GPTP_LOG_DEBUG("*** Sent PDelay Request message"); + putTxLock(); + + { + long long timeout; + long long interval; + + timeout = PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER * + ((long long) + (pow((double)2,getPDelayInterval())*1000000000.0)); + + timeout = timeout > EVENT_TIMER_GRANULARITY ? + timeout : EVENT_TIMER_GRANULARITY; + clock->addEventTimerLocked + (this, PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES, timeout ); + GPTP_LOG_DEBUG("Schedule PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES, " + "PDelay interval %d, timeout %lld", + getPDelayInterval(), timeout); + + interval = + ((long long) + (pow((double)2,getPDelayInterval())*1000000000.0)); + interval = interval > EVENT_TIMER_GRANULARITY ? + interval : EVENT_TIMER_GRANULARITY; + startPDelayIntervalTimer(interval); + } + } + break; + case SYNC_INTERVAL_TIMEOUT_EXPIRES: + { + /* Set offset from master to zero, update device vs + system time offset */ + + // Send a sync message and then a followup to broadcast + PTPMessageSync *sync = new PTPMessageSync(this); + PortIdentity dest_id; + bool tx_succeed; + getPortIdentity(dest_id); + sync->setPortIdentity(&dest_id); + getTxLock(); + tx_succeed = sync->sendPort(this, NULL); + GPTP_LOG_DEBUG("Sent SYNC message"); + + if ( automotive_profile && + getPortState() == PTP_MASTER ) + { + if (avbSyncState > 0) { + avbSyncState--; + if (avbSyncState == 0) { + // Send Avnu Automotive Profile status message + setStationState(STATION_STATE_AVB_SYNC); + if (getTestMode()) { + APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); + if (testStatusMsg) { + testStatusMsg->sendPort(this); + delete testStatusMsg; + } + } + } + } + } + putTxLock(); + + if ( tx_succeed ) + { + Timestamp sync_timestamp = sync->getTimestamp(); + + GPTP_LOG_VERBOSE("Successful Sync timestamp"); + GPTP_LOG_VERBOSE("Seconds: %u", + sync_timestamp.seconds_ls); + GPTP_LOG_VERBOSE("Nanoseconds: %u", + sync_timestamp.nanoseconds); + + PTPMessageFollowUp *follow_up = new PTPMessageFollowUp(this); + PortIdentity dest_id; + getPortIdentity(dest_id); + + follow_up->setClockSourceTime(getClock()->getFUPInfo()); + follow_up->setPortIdentity(&dest_id); + follow_up->setSequenceId(sync->getSequenceId()); + follow_up->setPreciseOriginTimestamp + (sync_timestamp); + follow_up->sendPort(this, NULL); + delete follow_up; + } else { + GPTP_LOG_ERROR + ("*** Unsuccessful Sync timestamp"); + } + delete sync; + } + break; + case FAULT_DETECTED: + GPTP_LOG_ERROR("Received FAULT_DETECTED event"); + if (!automotive_profile) { + setAsCapable(false); + } + break; + case PDELAY_DEFERRED_PROCESSING: + GPTP_LOG_DEBUG("PDELAY_DEFERRED_PROCESSING occured"); + pdelay_rx_lock->lock(); + if (last_pdelay_resp_fwup == NULL) { + GPTP_LOG_ERROR("PDelay Response Followup is NULL!"); + abort(); + } + last_pdelay_resp_fwup->processMessage(this); + if (last_pdelay_resp_fwup->garbage()) { + delete last_pdelay_resp_fwup; + this->setLastPDelayRespFollowUp(NULL); + } + pdelay_rx_lock->unlock(); + break; + case PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES: + if (!automotive_profile) { + GPTP_LOG_EXCEPTION("PDelay Response Receipt Timeout"); + setAsCapable(false); + } + setPdelayCount( 0 ); + break; + + case PDELAY_RESP_PEER_MISBEHAVING_TIMEOUT_EXPIRES: + GPTP_LOG_EXCEPTION("PDelay Resp Peer Misbehaving timeout expired! Restarting PDelay"); + + haltPdelay(false); + if( getPortState() != PTP_SLAVE && + getPortState() != PTP_MASTER ) + { + GPTP_LOG_STATUS("Starting PDelay" ); + startPDelay(); + } + break; + case SYNC_RATE_INTERVAL_TIMEOUT_EXPIRED: + { + GPTP_LOG_INFO("SYNC_RATE_INTERVAL_TIMEOUT_EXPIRED occured"); + + sync_rate_interval_timer_started = false; + + bool sendSignalMessage = false; + if ( getSyncInterval() != operLogSyncInterval ) + { + setSyncInterval( operLogSyncInterval ); + sendSignalMessage = true; + } + + if (log_min_mean_pdelay_req_interval != operLogPdelayReqInterval) { + log_min_mean_pdelay_req_interval = operLogPdelayReqInterval; + sendSignalMessage = true; + } + + if (sendSignalMessage) { + if (!isGM) { + // Send operational signalling message + PTPMessageSignalling *sigMsg = new PTPMessageSignalling(this); + if (sigMsg) { + if (automotive_profile) + sigMsg->setintervals(PTPMessageSignalling::sigMsgInterval_NoChange, getSyncInterval(), PTPMessageSignalling::sigMsgInterval_NoChange); + else + sigMsg->setintervals(log_min_mean_pdelay_req_interval, getSyncInterval(), PTPMessageSignalling::sigMsgInterval_NoChange); + sigMsg->sendPort(this, NULL); + delete sigMsg; + } + + startSyncReceiptTimer((unsigned long long) + (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * + ((double) pow((double)2, getSyncInterval()) * + 1000000000.0))); + } + } + } + + break; + default: + GPTP_LOG_ERROR + ( "Unhandled event type in " + "EtherPort::processEvent(), %d", e ); + ret = false; + break; + } + + return ret; +} + +void EtherPort::recoverPort( void ) +{ + return; +} + +void EtherPort::becomeMaster( bool annc ) { + setPortState( PTP_MASTER ); + // Stop announce receipt timeout timer + clock->deleteEventTimerLocked( this, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES ); + + // Stop sync receipt timeout timer + stopSyncReceiptTimer(); + + if( annc ) { + if (!automotive_profile) { + startAnnounce(); + } + } + startSyncIntervalTimer(16000000); + GPTP_LOG_STATUS("Switching to Master" ); + + clock->updateFUPInfo(); + + return; +} + +void EtherPort::becomeSlave( bool restart_syntonization ) { + clock->deleteEventTimerLocked( this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES ); + clock->deleteEventTimerLocked( this, SYNC_INTERVAL_TIMEOUT_EXPIRES ); + + setPortState( PTP_SLAVE ); + + if (!automotive_profile) { + clock->addEventTimerLocked + (this, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES, + (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER* + (unsigned long long) + (pow((double)2,getAnnounceInterval())*1000000000.0))); + } + + GPTP_LOG_STATUS("Switching to Slave" ); + if( restart_syntonization ) clock->newSyntonizationSetPoint(); + + getClock()->updateFUPInfo(); + + return; +} + +void EtherPort::mapSocketAddr +( PortIdentity *destIdentity, LinkLayerAddress *remote ) +{ + *remote = identity_map[*destIdentity]; + return; +} + +void EtherPort::addSockAddrMap +( PortIdentity *destIdentity, LinkLayerAddress *remote ) +{ + identity_map[*destIdentity] = *remote; + return; +} + +int EtherPort::getTxTimestamp +( PTPMessageCommon *msg, Timestamp ×tamp, unsigned &counter_value, + bool last ) +{ + PortIdentity identity; + msg->getPortIdentity(&identity); + return getTxTimestamp + (&identity, msg->getMessageId(), timestamp, counter_value, last); +} + +int EtherPort::getRxTimestamp +( PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, + bool last ) +{ + PortIdentity identity; + msg->getPortIdentity(&identity); + return getRxTimestamp + (&identity, msg->getMessageId(), timestamp, counter_value, last); +} + +int EtherPort::getTxTimestamp +(PortIdentity *sourcePortIdentity, PTPMessageId messageId, + Timestamp ×tamp, unsigned &counter_value, bool last ) +{ + EtherTimestamper *timestamper = + dynamic_cast<EtherTimestamper *>(_hw_timestamper); + if (timestamper) + { + return timestamper->HWTimestamper_txtimestamp + ( sourcePortIdentity, messageId, timestamp, + counter_value, last ); + } + timestamp = clock->getSystemTime(); + return 0; +} + +int EtherPort::getRxTimestamp +( PortIdentity * sourcePortIdentity, PTPMessageId messageId, + Timestamp ×tamp, unsigned &counter_value, bool last ) +{ + EtherTimestamper *timestamper = + dynamic_cast<EtherTimestamper *>(_hw_timestamper); + if (timestamper) + { + return timestamper->HWTimestamper_rxtimestamp + (sourcePortIdentity, messageId, timestamp, counter_value, + last); + } + timestamp = clock->getSystemTime(); + return 0; +} + +void EtherPort::startPDelayIntervalTimer +( long long unsigned int waitTime ) +{ + pDelayIntervalTimerLock->lock(); + clock->deleteEventTimerLocked(this, PDELAY_INTERVAL_TIMEOUT_EXPIRES); + clock->addEventTimerLocked(this, PDELAY_INTERVAL_TIMEOUT_EXPIRES, waitTime); + pDelayIntervalTimerLock->unlock(); +} + +void EtherPort::syncDone() { + GPTP_LOG_VERBOSE("Sync complete"); + + if (automotive_profile && getPortState() == PTP_SLAVE) { + if (avbSyncState > 0) { + avbSyncState--; + if (avbSyncState == 0) { + setStationState(STATION_STATE_AVB_SYNC); + if (getTestMode()) { + APMessageTestStatus *testStatusMsg = + new APMessageTestStatus(this); + if (testStatusMsg) { + testStatusMsg->sendPort(this); + delete testStatusMsg; + } + } + } + } + } + + if (automotive_profile) { + if (!sync_rate_interval_timer_started) { + if ( getSyncInterval() != operLogSyncInterval ) + { + startSyncRateIntervalTimer(); + } + } + } + + if( !pdelay_started ) { + startPDelay(); + } +} |