diff options
author | andrew-elder <aelder@audioscience.com> | 2017-04-28 15:26:51 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-28 15:26:51 -0400 |
commit | 3a716d352430125181da647af4f8ddeabdf9151b (patch) | |
tree | a897a41f60fc766594b6543cd2a83c6af7e9a97d /daemons | |
parent | 76413ddd9e921445c9e775169fc07babd0b8530d (diff) | |
parent | 27182b036e83309e7bf6eb33ac49289aa020f537 (diff) | |
download | Open-AVB-3a716d352430125181da647af4f8ddeabdf9151b.tar.gz |
Merge pull request #585 from christopher-s-hall/open-avb-next
Separate common port functionality from Ethernet port functionality
Diffstat (limited to 'daemons')
28 files changed, 3825 insertions, 3320 deletions
diff --git a/daemons/gptp/common/ap_message.cpp b/daemons/gptp/common/ap_message.cpp index c216e6b3..df121838 100644 --- a/daemons/gptp/common/ap_message.cpp +++ b/daemons/gptp/common/ap_message.cpp @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <ieee1588.hpp> #include <avbts_clock.hpp> #include <avbap_message.hpp> -#include <avbts_port.hpp> +#include <ether_port.hpp> #include <avbts_ostimer.hpp> #include <gptp_log.hpp> @@ -55,11 +55,11 @@ APMessageTestStatus::~APMessageTestStatus() { } -APMessageTestStatus::APMessageTestStatus(IEEE1588Port * port) +APMessageTestStatus::APMessageTestStatus( EtherPort *port ) { } -void APMessageTestStatus::sendPort(IEEE1588Port * port) +void APMessageTestStatus::sendPort( EtherPort * port ) { static uint16_t sequenceId = 0; diff --git a/daemons/gptp/common/avbap_message.hpp b/daemons/gptp/common/avbap_message.hpp index fc72c0f5..4c66f758 100644 --- a/daemons/gptp/common/avbap_message.hpp +++ b/daemons/gptp/common/avbap_message.hpp @@ -88,9 +88,9 @@ class APMessageTestStatus { public: /** * @brief Default constructor. Creates APMessageTestStatus - * @param port IEEE1588Port + * @param port EtherPort */ - APMessageTestStatus(IEEE1588Port * port); + APMessageTestStatus( EtherPort *port ); /** * @brief Destroys APMessageTestStatus interface @@ -99,11 +99,11 @@ class APMessageTestStatus { /** * @brief Assembles APMessageTestStatus message on the - * IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * EtherPort payload + * @param port EtherPort where the message will be assembled * @return void */ - void sendPort(IEEE1588Port * port); + void sendPort( EtherPort *port ); }; diff --git a/daemons/gptp/common/avbts_clock.hpp b/daemons/gptp/common/avbts_clock.hpp index 0f7e60cf..464b90d1 100644 --- a/daemons/gptp/common/avbts_clock.hpp +++ b/daemons/gptp/common/avbts_clock.hpp @@ -36,7 +36,7 @@ #include <stdint.h> #include <ieee1588.hpp> -#include <avbts_port.hpp> +#include <common_port.hpp> #include <avbts_ostimerq.hpp> #include <avbts_osipc.hpp> @@ -121,7 +121,7 @@ private: float _ppm; int _phase_error_violation; - IEEE1588Port *port_list[MAX_PORTS]; + CommonPort *port_list[MAX_PORTS]; static Timestamp start_time; Timestamp last_sync_time; @@ -163,12 +163,13 @@ private: /** * @brief Add a new event to the timer queue - * @param target IEEE1588Port target + * @param target EtherPort target * @param e Event to be added * @param time_ns Time in nanoseconds */ void addEventTimer - ( IEEE1588Port * target, Event e, unsigned long long time_ns ); + ( CommonPort *target, Event e, + unsigned long long time_ns ); /** * @brief Deletes an event from the timer queue @@ -176,7 +177,7 @@ private: * @param e Event to be removed * @return void */ - void deleteEventTimer(IEEE1588Port * target, Event e); + void deleteEventTimer( CommonPort *target, Event e ); public: /** * @brief Instantiates a IEEE 1588 Clock @@ -467,12 +468,13 @@ public: * @param index Port's index * @return void */ - void registerPort(IEEE1588Port * port, uint16_t index) { + void registerPort( CommonPort *port, uint16_t index ) + { if (index < MAX_PORTS) { port_list[index - 1] = port; } ++number_ports; - } + } /** * @brief Gets the current port list instance @@ -480,7 +482,7 @@ public: * @param ports [out] Pointer to the port list * @return */ - void getPortList(int &count, IEEE1588Port ** &ports) { + void getPortList(int &count, CommonPort ** &ports) { ports = this->port_list; count = number_ports; return; @@ -494,13 +496,13 @@ public: /** * @brief Adds an event to the timer queue using a lock - * @param target IEEE1588Port target + * @param target EtherPort target * @param e Event to be added * @param time_ns event time in nanoseconds * @return void */ void addEventTimerLocked - ( IEEE1588Port * target, Event e, unsigned long long time_ns ); + ( CommonPort *target, Event e, unsigned long long time_ns ); /** * @brief Deletes and event from the timer queue using a lock @@ -508,7 +510,7 @@ public: * @param e Event to be deleted * @return */ - void deleteEventTimerLocked(IEEE1588Port * target, Event e); + void deleteEventTimerLocked( CommonPort *target, Event e ); /** * @brief Calculates the master to local clock rate difference @@ -542,15 +544,11 @@ public: * @param asCapable asCapable flag */ void setMasterOffset - ( IEEE1588Port * port, int64_t master_local_offset, Timestamp local_time, - FrequencyRatio master_local_freq_offset, - int64_t local_system_offset, - Timestamp system_time, - FrequencyRatio local_system_freq_offset, - unsigned sync_count, - unsigned pdelay_count, - PortState port_state, - bool asCapable ); + ( CommonPort *port, int64_t master_local_offset, + Timestamp local_time, FrequencyRatio master_local_freq_offset, + int64_t local_system_offset, Timestamp system_time, + FrequencyRatio local_system_freq_offset, unsigned sync_count, + unsigned pdelay_count, PortState port_state, bool asCapable ); /** * @brief Get the IEEE1588Clock identity value @@ -574,7 +572,7 @@ public: */ void restartPDelayAll() { int number_ports, i, j = 0; - IEEE1588Port **ports; + CommonPort **ports; getPortList( number_ports, ports ); @@ -590,7 +588,7 @@ public: */ int getTxLockAll() { int number_ports, i, j = 0; - IEEE1588Port **ports; + CommonPort **ports; getPortList( number_ports, ports ); @@ -610,7 +608,7 @@ public: */ int putTxLockAll() { int number_ports, i, j = 0; - IEEE1588Port **ports; + CommonPort **ports; getPortList( number_ports, ports ); diff --git a/daemons/gptp/common/avbts_message.hpp b/daemons/gptp/common/avbts_message.hpp index 40472bd9..55492022 100644 --- a/daemons/gptp/common/avbts_message.hpp +++ b/daemons/gptp/common/avbts_message.hpp @@ -235,9 +235,10 @@ protected: public: /** * @brief Creates the PTPMessageCommon interface - * @param port IEEE1588Port where the message interface is connected to. + * @param port EtherPort where the message interface is + * connected to. */ - PTPMessageCommon(IEEE1588Port * port); + PTPMessageCommon( CommonPort *port ); /** * @brief Destroys PTPMessageCommon interface */ @@ -359,7 +360,7 @@ protected: * @param port IEEE1588 port * @return void */ - virtual void processMessage(IEEE1588Port * port); + virtual void processMessage( EtherPort *port ); /** * @brief Builds PTP common header @@ -369,7 +370,8 @@ protected: void buildCommonHeader(uint8_t * buf); friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress * remote, + EtherPort *port ); }; /*Exact fit. No padding*/ @@ -505,7 +507,7 @@ class PTPMessageAnnounce:public PTPMessageCommon { /** * @brief Creates the PTPMessageAnnounce interface */ - PTPMessageAnnounce(IEEE1588Port * port); + PTPMessageAnnounce( CommonPort * port ); /** * @brief Destroys the PTPMessageAnnounce interface @@ -573,22 +575,25 @@ class PTPMessageAnnounce:public PTPMessageCommon { /** * @brief Processes PTP message - * @param port IEEE1588Port + * @param port EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); /** - * @brief Assembles PTPMessageAnnounce message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessageAnnounce message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( CommonPort *port, PortIdentity *destIdentity); - friend PTPMessageCommon *buildPTPMessage(char *buf, int size, - LinkLayerAddress * remote, - IEEE1588Port * port); + friend PTPMessageCommon *buildPTPMessage + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); }; /** @@ -602,9 +607,9 @@ class PTPMessageSync : public PTPMessageCommon { public: /** * @brief Default constructor. Creates PTPMessageSync - * @param port IEEE1588Port + * @param port EtherPort */ - PTPMessageSync(IEEE1588Port * port); + PTPMessageSync( EtherPort *port ); /** * @brief Destroys PTPMessageSync interface @@ -613,10 +618,10 @@ class PTPMessageSync : public PTPMessageCommon { /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); /** * @brief Gets origin timestamp value @@ -627,15 +632,19 @@ class PTPMessageSync : public PTPMessageCommon { } /** - * @brief Assembles PTPMessageSync message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessageSync message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + (EtherPort *port, PortIdentity *destIdentity ); friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress * remote, + EtherPort *port ); }; /* Exact fit. No padding*/ @@ -841,22 +850,26 @@ public: /** * @brief Builds the PTPMessageFollowUP object */ - PTPMessageFollowUp(IEEE1588Port * port); + PTPMessageFollowUp( EtherPort *port ); /** - * @brief Assembles PTPMessageFollowUp message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessageFollowUp message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( EtherPort *port, PortIdentity *destIdentity ); /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); + /** * @brief Gets the precise origin timestamp value * @return preciseOriginTimestamp value @@ -887,7 +900,8 @@ public: } friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); }; /** @@ -910,22 +924,25 @@ class PTPMessagePathDelayReq : public PTPMessageCommon { /** * @brief Builds the PTPMessagePathDelayReq message */ - PTPMessagePathDelayReq(IEEE1588Port * port); + PTPMessagePathDelayReq( EtherPort *port ); /** - * @brief Assembles PTPMessagePathDelayReq message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessagePathDelayReq message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( EtherPort *port, PortIdentity *destIdentity ); /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); /** * @brief Gets origin timestamp value @@ -936,7 +953,8 @@ class PTPMessagePathDelayReq : public PTPMessageCommon { } friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); }; /** @@ -957,22 +975,25 @@ public: /** * @brief Builds the PTPMessagePathDelayResp object */ - PTPMessagePathDelayResp(IEEE1588Port * port); + PTPMessagePathDelayResp( EtherPort *port ); /** - * @brief Assembles PTPMessagePathDelayResp message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessagePathDelayResp message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( EtherPort *port, PortIdentity *destIdentity ); /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); /** * @brief Sets the request receipt timestamp @@ -1005,7 +1026,8 @@ public: } friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); }; /** @@ -1022,7 +1044,7 @@ public: /** * @brief Builds the PTPMessagePathDelayRespFollowUp object */ - PTPMessagePathDelayRespFollowUp(IEEE1588Port * port); + PTPMessagePathDelayRespFollowUp( EtherPort *port ); /** * @brief Destroys the PTPMessagePathDelayRespFollowUp object @@ -1030,19 +1052,22 @@ public: ~PTPMessagePathDelayRespFollowUp(); /** - * @brief Assembles PTPMessageRespFollowUp message on the IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * @brief Assembles PTPMessageRespFollowUp message on the + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( EtherPort *port, PortIdentity *destIdentity ); /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); /** * @brief Sets the response origin timestamp @@ -1075,7 +1100,8 @@ public: } friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); }; /*Exact fit. No padding*/ @@ -1198,7 +1224,7 @@ public: /** * @brief Builds the PTPMessageSignalling object */ - PTPMessageSignalling(IEEE1588Port * port); + PTPMessageSignalling( EtherPort *port ); /** * @brief Destroys the PTPMessageSignalling object @@ -1216,22 +1242,25 @@ public: /** * @brief Assembles PTPMessageSignalling message on the - * IEEE1588Port payload - * @param port IEEE1588Port where the message will be assembled + * EtherPort payload + * @param port EtherPort where the message will be + * assembled * @param destIdentity [in] Destination PortIdentity * @return void */ - void sendPort(IEEE1588Port * port, PortIdentity * destIdentity); + void sendPort + ( EtherPort *port, PortIdentity *destIdentity ); /** * @brief Processes PTP messages - * @param port [in] IEEE1588Port + * @param port [in] EtherPort * @return void */ - void processMessage(IEEE1588Port * port); + void processMessage( EtherPort *port ); friend PTPMessageCommon *buildPTPMessage - (char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port); + ( char *buf, int size, LinkLayerAddress *remote, + EtherPort * port); }; #endif diff --git a/daemons/gptp/common/avbts_oscondition.hpp b/daemons/gptp/common/avbts_oscondition.hpp index 5072cfab..93511391 100644 --- a/daemons/gptp/common/avbts_oscondition.hpp +++ b/daemons/gptp/common/avbts_oscondition.hpp @@ -109,7 +109,7 @@ public: * @brief Creates OSCondition class * @return Pointer to OSCondition object */ - virtual OSCondition * createCondition() = 0; + virtual OSCondition *createCondition() const = 0; /** * @brief Destroys OSCondition objects diff --git a/daemons/gptp/common/avbts_osipc.hpp b/daemons/gptp/common/avbts_osipc.hpp index 4d3daf3a..14819964 100644 --- a/daemons/gptp/common/avbts_osipc.hpp +++ b/daemons/gptp/common/avbts_osipc.hpp @@ -36,7 +36,7 @@ #include <stdint.h> #include <ptptypes.hpp> -#include <avbts_port.hpp> +#include <ether_port.hpp> /**@file*/ diff --git a/daemons/gptp/common/avbts_oslock.hpp b/daemons/gptp/common/avbts_oslock.hpp index 9de07e58..c53b904b 100644 --- a/daemons/gptp/common/avbts_oslock.hpp +++ b/daemons/gptp/common/avbts_oslock.hpp @@ -103,7 +103,7 @@ class OSLockFactory { * @param type Enumeration OSLockType * @return Pointer to an enumeration of type OSLock */ - virtual OSLock * createLock(OSLockType type) = 0; + virtual OSLock *createLock(OSLockType type) const = 0; virtual ~OSLockFactory() = 0; }; diff --git a/daemons/gptp/common/avbts_osnet.hpp b/daemons/gptp/common/avbts_osnet.hpp index bb190a8f..1319326c 100644 --- a/daemons/gptp/common/avbts_osnet.hpp +++ b/daemons/gptp/common/avbts_osnet.hpp @@ -325,7 +325,7 @@ class OSNetworkInterface { /** * @brief Watch for netlink changes. */ - virtual void watchNetLink(IEEE1588Port *pPort) = 0; + virtual void watchNetLink( CommonPort *pPort ) = 0; /** * @brief Provides generic method for getting the payload offset diff --git a/daemons/gptp/common/avbts_osthread.hpp b/daemons/gptp/common/avbts_osthread.hpp index d191b650..9464512f 100644 --- a/daemons/gptp/common/avbts_osthread.hpp +++ b/daemons/gptp/common/avbts_osthread.hpp @@ -47,6 +47,7 @@ typedef enum { osthread_ok, osthread_error } OSThreadExitCode; * @brief Provides the OSThreadExitCode callback format */ typedef OSThreadExitCode(*OSThreadFunction) (void *); +typedef void *OSThreadFunctionArg; /** * @brief Provides a generic interface for threads @@ -81,7 +82,7 @@ public: * @brief Creates a new thread * @return Pointer to OSThread object */ - virtual OSThread * createThread() = 0; + virtual OSThread * createThread() const = 0; /** * @brief Destroys the new thread diff --git a/daemons/gptp/common/avbts_ostimer.hpp b/daemons/gptp/common/avbts_ostimer.hpp index f416f008..cacdfc95 100644 --- a/daemons/gptp/common/avbts_ostimer.hpp +++ b/daemons/gptp/common/avbts_ostimer.hpp @@ -65,7 +65,7 @@ public: * @brief Creates the OSTimer * @return Pointer to OSTimer object */ - virtual OSTimer * createTimer() = 0; + virtual OSTimer *createTimer() const = 0; /* * Destroys the OSTimer previsouly created diff --git a/daemons/gptp/common/avbts_port.hpp b/daemons/gptp/common/avbts_port.hpp deleted file mode 100644 index d1806099..00000000 --- a/daemons/gptp/common/avbts_port.hpp +++ /dev/null @@ -1,1712 +0,0 @@ -/****************************************************************************** - - 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. - -******************************************************************************/ - -#ifndef AVBTS_PORT_HPP -#define AVBTS_PORT_HPP - -#include <ieee1588.hpp> -#include <avbts_message.hpp> -#include <avbap_message.hpp> - -#include <avbts_ostimer.hpp> -#include <avbts_oslock.hpp> -#include <avbts_osnet.hpp> -#include <avbts_osthread.hpp> -#include <avbts_oscondition.hpp> -#include <ipcdef.hpp> -#include <gptp_log.hpp> - -#include <stdint.h> - -#include <map> -#include <list> - -/**@file*/ - -#define GPTP_MULTICAST 0x0180C200000EULL /*!< GPTP multicast adddress */ -#define PDELAY_MULTICAST GPTP_MULTICAST /*!< PDELAY Multicast value */ -#define OTHER_MULTICAST GPTP_MULTICAST /*!< OTHER multicast value */ -#define TEST_STATUS_MULTICAST 0x011BC50AC000ULL /*!< AVnu Automotive profile test status msg Multicast value */ - -#define PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< PDelay timeout multiplier*/ -#define SYNC_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< Sync receipt timeout multiplier*/ -#define ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< Announce receipt timeout multiplier*/ - -#define LOG2_INTERVAL_INVALID -127 /* Simple out of range Log base 2 value used for Sync and PDelay msg internvals */ - -/** - * @brief PortType enumeration. Selects between delay request-response (E2E) mechanism - * or PTPV1 or PTPV2 P2P (peer delay) mechanism. - */ -typedef enum { - V1, - V2_E2E, - V2_P2P -} PortType; - -/** - * @brief PortIdentity interface - * Defined at IEEE 802.1AS Clause 8.5.2 - */ -class PortIdentity { -private: - ClockIdentity clock_id; - uint16_t portNumber; -public: - /** - * @brief Default Constructor - */ - PortIdentity() { }; - - /** - * @brief Constructs PortIdentity interface. - * @param clock_id Clock ID value as defined at IEEE 802.1AS Clause 8.5.2.2 - * @param portNumber Port Number - */ - PortIdentity(uint8_t * clock_id, uint16_t * portNumber) { - this->portNumber = *portNumber; - this->portNumber = PLAT_ntohs(this->portNumber); - this->clock_id.set(clock_id); - } - - /** - * @brief Implements the operator '!=' overloading method. Compares clock_id and portNumber. - * @param cmp Constant PortIdentity value to be compared against. - * @return TRUE if the comparison value differs from the object's PortIdentity value. FALSE otherwise. - */ - bool operator!=(const PortIdentity & cmp) const { - return - !(this->clock_id == cmp.clock_id) || - this->portNumber != cmp.portNumber ? true : false; - } - - /** - * @brief Implements the operator '==' overloading method. Compares clock_id and portNumber. - * @param cmp Constant PortIdentity value to be compared against. - * @return TRUE if the comparison value equals to the object's PortIdentity value. FALSE otherwise. - */ - bool operator==(const PortIdentity & cmp)const { - return - this->clock_id == cmp.clock_id && - this->portNumber == cmp.portNumber ? true : false; - } - - /** - * @brief Implements the operator '<' overloading method. Compares clock_id and portNumber. - * @param cmp Constant PortIdentity value to be compared against. - * @return TRUE if the comparison value is lower than the object's PortIdentity value. FALSE otherwise. - */ - bool operator<(const PortIdentity & cmp)const { - return - this->clock_id < cmp.clock_id ? - true : this->clock_id == cmp.clock_id && - this->portNumber < cmp.portNumber ? true : false; - } - - /** - * @brief Implements the operator '>' overloading method. Compares clock_id and portNumber. - * @param cmp Constant PortIdentity value to be compared against. - * @return TRUE if the comparison value is greater than the object's PortIdentity value. FALSE otherwise. - */ - bool operator>(const PortIdentity & cmp)const { - return - this->clock_id > cmp.clock_id ? - true : this->clock_id == cmp.clock_id && - this->portNumber > cmp.portNumber ? true : false; - } - - /** - * @brief Gets the ClockIdentity string - * @param id [out] Pointer to an array of octets. - * @return void - */ - void getClockIdentityString(uint8_t *id) { - clock_id.getIdentityString(id); - } - - /** - * @brief Sets the ClockIdentity. - * @param clock_id Clock Identity to be set. - * @return void - */ - void setClockIdentity(ClockIdentity clock_id) { - this->clock_id = clock_id; - } - - /** - * @brief Gets the clockIdentity value - * @return A copy of Clock identity value. - */ - ClockIdentity getClockIdentity( void ) { - return this->clock_id; - } - - /** - * @brief Gets the port number following the network byte order, i.e. Big-Endian. - * @param id [out] Port number - * @return void - */ - void getPortNumberNO(uint16_t * id) { // Network byte order - uint16_t portNumberNO = PLAT_htons(portNumber); - *id = portNumberNO; - } - - /** - * @brief Gets the port number in the host byte order, which can be either Big-Endian - * or Little-Endian, depending on the processor where it is running. - * @param id Port number - * @return void - */ - void getPortNumber(uint16_t * id) { // Host byte order - *id = portNumber; - } - - /** - * @brief Sets the Port number - * @param id [in] Port number - * @return void - */ - void setPortNumber(uint16_t * id) { - portNumber = *id; - } -}; - -/** - * @brief Provides a map for the identityMap member of IEEE1588Port class - */ -typedef std::map < PortIdentity, LinkLayerAddress > IdentityMap_t; - -/** - * @brief Structure for initializing the IEEE1588 class - */ -typedef struct { - /* clock IEEE1588Clock instance */ - IEEE1588Clock * clock; - - /* index Interface index */ - uint16_t index; - - /* forceSlave Forces port to be slave */ - bool forceSlave; - - /* timestamper Hardware timestamper instance */ - HWTimestamper * timestamper; - - /* offset Initial clock offset */ - int32_t offset; - - /* net_label Network label */ - InterfaceLabel * net_label; - - /* automotive_profile set the AVnu automotive profile */ - bool automotive_profile; - - /* Set to true if the port is the grandmaster. Used for fixed GM in the the AVnu automotive profile */ - bool isGM; - - /* Set to true if the port is the grandmaster. Used for fixed GM in the the AVnu automotive profile */ - bool testMode; - - /* Set to true if the port's network interface is up. Used to filter false LINKUP/LINKDOWN events */ - bool linkUp; - - /* gPTP 10.2.4.4 */ - char initialLogSyncInterval; - - /* gPTP 11.5.2.2 */ - char initialLogPdelayReqInterval; - - /* CDS 6.2.1.5 */ - char operLogPdelayReqInterval; - - /* CDS 6.2.1.6 */ - char operLogSyncInterval; - - /* condition_factory OSConditionFactory instance */ - OSConditionFactory * condition_factory; - - /* thread_factory OSThreadFactory instance */ - OSThreadFactory * thread_factory; - - /* timer_factory OSTimerFactory instance */ - OSTimerFactory * timer_factory; - - /* lock_factory OSLockFactory instance */ - OSLockFactory * lock_factory; -} IEEE1588PortInit_t; - - -/** - * @brief Structure for IEE1588Port Counters - */ -typedef struct { - int32_t ieee8021AsPortStatRxSyncCount; - int32_t ieee8021AsPortStatRxFollowUpCount; - int32_t ieee8021AsPortStatRxPdelayRequest; - int32_t ieee8021AsPortStatRxPdelayResponse; - int32_t ieee8021AsPortStatRxPdelayResponseFollowUp; - int32_t ieee8021AsPortStatRxAnnounce; - int32_t ieee8021AsPortStatRxPTPPacketDiscard; - int32_t ieee8021AsPortStatRxSyncReceiptTimeouts; - int32_t ieee8021AsPortStatAnnounceReceiptTimeouts; - int32_t ieee8021AsPortStatPdelayAllowedLostResponsesExceeded; - int32_t ieee8021AsPortStatTxSyncCount; - int32_t ieee8021AsPortStatTxFollowUpCount; - int32_t ieee8021AsPortStatTxPdelayRequest; - int32_t ieee8021AsPortStatTxPdelayResponse; - int32_t ieee8021AsPortStatTxPdelayResponseFollowUp; - int32_t ieee8021AsPortStatTxAnnounce; -} IEEE1588PortCounters_t; - - -/** - * @brief Provides the IEEE 1588 port interface - */ -class IEEE1588Port { - static LinkLayerAddress other_multicast; - static LinkLayerAddress pdelay_multicast; - static LinkLayerAddress test_status_multicast; - - PortIdentity port_identity; - /* directly connected node */ - PortIdentity peer_identity; - - OSNetworkInterface *net_iface; - LinkLayerAddress local_addr; - int link_delay[4]; - - /* Port Status */ - unsigned sync_count; // 0 for master, ++ for each sync receive as slave - // set to 0 when asCapable is false, increment for each pdelay recvd - unsigned pdelay_count; - bool linkUp; - - /* Port Configuration */ - unsigned char delay_mechanism; - PortState port_state; - char log_mean_unicast_sync_interval; - char log_mean_sync_interval; - char log_mean_announce_interval; - char log_min_mean_delay_req_interval; - char log_min_mean_pdelay_req_interval; - bool burst_enabled; - static const int64_t ONE_WAY_DELAY_DEFAULT = 3600000000000; - static const int64_t INVALID_LINKDELAY = 3600000000000; - static const int64_t NEIGHBOR_PROP_DELAY_THRESH = 800; - static const unsigned int DEFAULT_SYNC_RECEIPT_THRESH = 5; - static const unsigned int DUPLICATE_RESP_THRESH = 3; - - unsigned int duplicate_resp_counter; - uint16_t last_invalid_seqid; - - /* Signed value allows this to be negative result because of inaccurate - timestamp */ - int64_t one_way_delay; - int64_t neighbor_prop_delay_thresh; - - /*Sync threshold*/ - unsigned int sync_receipt_thresh; - unsigned int wrongSeqIDCounter; - - /* Implementation Specific data/methods */ - IEEE1588Clock *clock; - - bool _syntonize; - - bool asCapable; - - /* Automotive Profile : Static variables */ - // port_state : already defined as port_state - bool isGM; - bool testMode; - // asCapable : already defined as asCapable - char initialLogPdelayReqInterval; - char initialLogSyncInterval; - char operLogPdelayReqInterval; - char operLogSyncInterval; - bool automotive_profile; - - // Test Status variables - uint32_t linkUpCount; - uint32_t linkDownCount; - StationState_t stationState; - - - /* Automotive Profile : Persistant variables */ - // neighborPropDelay : defined as one_way_delay ?? - // rateRatio : Optional and didn't fine this variable. Will proceed without writing it. - // neighborRateRatio : defined as _peer_rate_offset ?? - - // Automotive Profile AVB SYNC state indicator. > 0 will inditate valid AVB SYNC state - uint32_t avbSyncState; - - int32_t *rate_offset_array; - uint32_t rate_offset_array_size; - uint32_t rate_offset_count; - uint32_t rate_offset_index; - - FrequencyRatio _peer_rate_offset; - Timestamp _peer_offset_ts_theirs; - Timestamp _peer_offset_ts_mine; - bool _peer_offset_init; - - int32_t _initial_clock_offset; - int32_t _current_clock_offset; - - PTPMessageAnnounce *qualified_announce; - - uint16_t announce_sequence_id; - uint16_t signal_sequence_id; - uint16_t sync_sequence_id; - - uint16_t pdelay_sequence_id; - PTPMessagePathDelayReq *last_pdelay_req; - PTPMessagePathDelayResp *last_pdelay_resp; - PTPMessagePathDelayRespFollowUp *last_pdelay_resp_fwup; - - /* Network socket description - physical interface number that object represents */ - uint16_t ifindex; - - IdentityMap_t identity_map; - - PTPMessageSync *last_sync; - - OSThread *listening_thread; - - OSThread *link_thread; - - OSCondition *port_ready_condition; - - OSLock *pdelay_rx_lock; - OSLock *port_tx_lock; - - OSLock *syncReceiptTimerLock; - OSLock *syncIntervalTimerLock; - OSLock *announceIntervalTimerLock; - OSLock *pDelayIntervalTimerLock; - - OSThreadFactory *thread_factory; - OSTimerFactory *timer_factory; - - HWTimestamper *_hw_timestamper; - - net_result port_send - (uint16_t etherType, uint8_t * buf, int size, MulticastType mcast_type, - PortIdentity * destIdentity, bool timestamp); - - InterfaceLabel *net_label; - - OSLockFactory *lock_factory; - OSConditionFactory *condition_factory; - - bool pdelay_started; - bool pdelay_halted; - bool sync_rate_interval_timer_started; - - uint16_t lastGmTimeBaseIndicator; - - IEEE1588PortCounters_t counters; - - public: - bool forceSlave; //!< Forces port to be slave. Added for testing. - - /** - * @brief Serializes (i.e. copy over buf pointer) the information from - * the variables (in that order): - * - asCapable; - * - Port Sate; - * - Link Delay; - * - Neighbor Rate Ratio - * @param buf [out] Buffer where to put the results. - * @param count [inout] Length of buffer. It contains maximum length to be written - * when the function is called, and the value is decremented by the same amount the - * buf size increases. - * @return TRUE if it has successfully written to buf all the values or if buf is NULL. - * FALSE if count should be updated with the right size. - */ - bool serializeState( void *buf, long *count ); - - /** - * @brief Restores the serialized state from the buffer. Copies the information from buffer - * to the variables (in that order): - * - asCapable; - * - Port State; - * - Link Delay; - * - Neighbor Rate Ratio - * @param buf Buffer containing the serialized state. - * @param count Buffer lenght. It is decremented by the same size of the variables that are - * being copied. - * @return TRUE if everything was copied successfully, FALSE otherwise. - */ - bool restoreSerializedState( void *buf, long *count ); - - /** - * @brief Switches port to a gPTP master - * @param annc If TRUE, starts announce event timer. - * @return void - */ - void becomeMaster( bool annc ); - - /** - * @brief Switches port to a gPTP slave. - * @param restart_syntonization if TRUE, restarts the syntonization - * @return void - */ - void becomeSlave( bool restart_syntonization ); - - /** - * @brief Starts pDelay event timer. - * @return void - */ - void startPDelay(); - - /** - * @brief Stops PDelay event timer - * @return void - */ - void stopPDelay(); - - /** - * @brief Enable/Disable PDelay Request messages - * @param hlt True to HALT (stop sending), False to resume (start sending). - */ - void haltPdelay(bool hlt) - { - pdelay_halted = hlt; - } - - /** - * @brief Get the status of pdelayHalted condition. - * @return True PdelayRequest halted. False when PDelay Request is running - */ - bool pdelayHalted(void) - { - return pdelay_halted; - } - - /** - * @brief Starts Sync Rate Interval event timer. Used for the - * Automotive Profile. - * @return void - */ - void startSyncRateIntervalTimer(); - - /** - * @brief Starts announce event timer - * @return void - */ - void startAnnounce(); - - /** - * @brief Starts pDelay event timer if not yet started. - * @return void - */ - void syncDone() { - GPTP_LOG_VERBOSE("Sync complete"); - - if (automotive_profile && port_state == PTP_SLAVE) { - if (avbSyncState > 0) { - avbSyncState--; - if (avbSyncState == 0) { - setStationState(STATION_STATE_AVB_SYNC); - if (testMode) { - APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); - if (testStatusMsg) { - testStatusMsg->sendPort(this); - delete testStatusMsg; - } - } - } - } - } - - if (automotive_profile) { - if (!sync_rate_interval_timer_started) { - if (log_mean_sync_interval != operLogSyncInterval) { - startSyncRateIntervalTimer(); - } - } - } - - if( !pdelay_started ) { - startPDelay(); - } - } - - /** - * @brief Gets a pointer to timer_factory object - * @return timer_factory pointer - */ - OSTimerFactory *getTimerFactory() { - return timer_factory; - } - - /** - * @brief Restart PDelay - * @return void - */ - void restartPDelay() { - _peer_offset_init = false; - } - - /** - * @brief Sets asCapable flag - * @param ascap flag to be set. If FALSE, marks peer_offset_init as false. - * @return void - */ - void setAsCapable(bool ascap) { - if (ascap != asCapable) { - GPTP_LOG_STATUS("AsCapable: %s", - ascap == true ? "Enabled" : "Disabled"); - } - if(!ascap){ - _peer_offset_init = false; - } - asCapable = ascap; - } - - /** - * @brief Gets the asCapable flag - * @return asCapable flag. - */ - bool getAsCapable() { return( asCapable ); } - - /** - * @brief Gets the AVnu automotive profile flag - * @return automotive_profile flag - */ - bool getAutomotiveProfile() { return( automotive_profile ); } - - /** - * @brief Destroys a IEEE1588Port - */ - ~IEEE1588Port(); - - /** - * @brief Creates the IEEE1588Port interface. Will be - * deprecated when the Windows platform suports - * Automotive profile. - * @param clock IEEE1588Clock instance - * @param index Interface index - * @param forceSlave Forces port to be slave - * @param timestamper Hardware timestamper instance - * @param offset Initial clock offset - * @param net_label Network label - * @param condition_factory OSConditionFactory instance - * @param thread_factory OSThreadFactory instance - * @param timer_factory OSTimerFactory instance - * @param lock_factory OSLockFactory instance - */ - IEEE1588Port - (IEEE1588Clock * clock, uint16_t index, - bool forceSlave, - HWTimestamper * timestamper, - int32_t offset, InterfaceLabel * net_label, - OSConditionFactory * condition_factory, - OSThreadFactory * thread_factory, - OSTimerFactory * timer_factory, - OSLockFactory * lock_factory); - - /** - * @brief Creates the IEEE1588Port interface. - * @param init IEEE1588PortInit initialization parameters - */ - IEEE1588Port(IEEE1588PortInit_t *portInit); - - /** - * @brief Initializes the port. Creates network interface, initializes - * hardware timestamper and create OS locks conditions - * @return FALSE if error during building the interface. TRUE if success - */ - bool init_port(int delay[4]); - - /** - * @brief Currently doesnt do anything. Just returns. - * @return void - */ - void recoverPort(void); - - /** - * @brief Watch for link up and down events. - * @return Its an infinite loop. Returns NULL in case of error. - */ - void *watchNetLink(void); - - /** - * @brief Receives messages from the network interface - * @return Its an infinite loop. Returns NULL in case of error. - */ - void *openPort(IEEE1588Port *port); - - /** - * @brief Get the payload offset inside a packet - * @return 0 - */ - unsigned getPayloadOffset(); - - /** - * @brief Sends and event to a IEEE1588 port. It includes timestamp - * @param buf [in] Pointer to the data buffer - * @param len Size of the message - * @param mcast_type Enumeration MulticastType (pdlay, none or other). Depracated. - * @param destIdentity Destination port identity - * @return void - */ - void sendEventPort - (uint16_t etherType, uint8_t * buf, int len, MulticastType mcast_type, - PortIdentity * destIdentity); - - /** - * @brief Sends a general message to a port. No timestamps - * @param buf [in] Pointer to the data buffer - * @param len Size of the message - * @param mcast_type Enumeration MulticastType (pdelay, none or other). Depracated. - * @param destIdentity Destination port identity - * @return void - */ - void sendGeneralPort - (uint16_t etherType, uint8_t * buf, int len, MulticastType mcast_type, - PortIdentity * destIdentity); - - /** - * @brief Process all events for a IEEE1588Port - * @param e Event to be processed - * @return void - */ - void processEvent(Event e); - - /** - * @brief Gets the "best" announce - * @return Pointer to PTPMessageAnnounce - */ - PTPMessageAnnounce *calculateERBest(void); - - /** - * @brief Adds a foreign master. - * @param msg [in] PTP announce message - * @return void - * @todo Currently not implemented - */ - void addForeignMaster(PTPMessageAnnounce * msg); - - /** - * @brief Remove a foreign master. - * @param msg [in] PTP announce message - * @return void - * @todo Currently not implemented - */ - void removeForeignMaster(PTPMessageAnnounce * msg); - - /** - * @brief Remove all foreign masters. - * @return void - * @todo Currently not implemented - */ - void removeForeignMasterAll(void); - - - /** - * @brief Adds a new qualified announce the port. IEEE 802.1AS Clause 10.3.10.2 - * @param msg PTP announce message - * @return void - */ - void addQualifiedAnnounce(PTPMessageAnnounce * msg) { - if( qualified_announce != NULL ) delete qualified_announce; - qualified_announce = msg; - } - /** - * @brief Gets the local_addr - * @return LinkLayerAddress - */ - LinkLayerAddress *getLocalAddr(void) { - return &local_addr; - } - - /** - * @brief Gets the sync interval value - * @return Sync Interval - */ - char getSyncInterval(void) { - return log_mean_sync_interval; - } - - /** - * @brief Sets the sync interval value - * @param val time interval - * @return none - */ - void setSyncInterval(char val) { - log_mean_sync_interval = val;; - } - - /** - * @brief Sets the sync interval back to initial value - * @return none - */ - void setInitSyncInterval(void) { - log_mean_sync_interval = initialLogSyncInterval;; - } - - /** - * @brief Start sync receipt timer - * @param waitTime time interval - * @return none - */ - void startSyncReceiptTimer(long long unsigned int waitTime); - - /** - * @brief Stop sync receipt timer - * @return none - */ - void stopSyncReceiptTimer(void); - - /** - * @brief Start sync interval timer - * @param waitTime time interval in nanoseconds - * @return none - */ - void startSyncIntervalTimer(long long unsigned int waitTime); - - /** - * @brief Gets the announce interval - * @return Announce interval - */ - char getAnnounceInterval(void) { - return log_mean_announce_interval; - } - - /** - * @brief Sets the announce interval - * @param val time interval - * @return none - */ - void setAnnounceInterval(char val) { - log_mean_announce_interval = val; - } - - /** - * @brief Start announce interval timer - * @param waitTime time interval - * @return none - */ - void startAnnounceIntervalTimer(long long unsigned int waitTime); - - /** - * @brief Gets the pDelay minimum interval - * @return PDelay interval - */ - char getPDelayInterval(void) { - return log_min_mean_pdelay_req_interval; - } - - /** - * @brief Sets the pDelay minimum interval - * @param val time interval - * @return none - */ - void setPDelayInterval(char val) { - log_min_mean_pdelay_req_interval = val; - } - - /** - * @brief Sets the pDelay minimum interval back to initial - * value - * @return none */ - void setInitPDelayInterval(void) { - log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; - } - - /** - * @brief Start pDelay interval timer - * @param waitTime time interval - * @return none - */ - void startPDelayIntervalTimer(long long unsigned int waitTime); - - /** - * @brief Gets the portState information - * @return PortState - */ - PortState getPortState(void) { - return port_state; - } - - /** - * @brief Sets the PortState - * @param state value to be set - * @return void - */ - void setPortState( PortState state ) { - port_state = state; - } - - /** - * @brief Gets port identity - * @param identity [out] Reference to PortIdentity - * @return void - */ - void getPortIdentity(PortIdentity & identity) { - identity = this->port_identity; - } - - /** - * @brief Gets the burst_enabled flag - * @return burst_enabled - */ - bool burstEnabled(void) { - return burst_enabled; - } - - /** - * @brief Increments announce sequence id and returns - * @return Next announce sequence id. - */ - uint16_t getNextAnnounceSequenceId(void) { - return announce_sequence_id++; - } - - /** - * @brief Increments signal sequence id and returns - * @return Next signal sequence id. - */ - uint16_t getNextSignalSequenceId(void) { - return signal_sequence_id++; - } - - /** - * @brief Increments sync sequence ID and returns - * @return Next synce sequence id. - */ - uint16_t getNextSyncSequenceId(void) { - return sync_sequence_id++; - } - - /** - * @brief Increments PDelay sequence ID and returns. - * @return Next PDelay sequence id. - */ - uint16_t getNextPDelaySequenceId(void) { - return pdelay_sequence_id++; - } - - /** - * @brief Gets last sync sequence number from parent - * @return Parent last sync sequence number - * @todo Not currently implemented. - */ - uint16_t getParentLastSyncSequenceNumber(void); - - /** - * @brief Sets last sync sequence number from parent - * @param num Sequence number - * @return void - * @todo Currently not implemented. - */ - void setParentLastSyncSequenceNumber(uint16_t num); - - /** - * @brief Gets a pointer to IEEE1588Clock - * @return Pointer to clock - */ - IEEE1588Clock *getClock(void); - - /** - * @brief Sets last sync ptp message - * @param msg [in] PTP sync message - * @return void - */ - void setLastSync(PTPMessageSync * msg) { - last_sync = msg; - } - - /** - * @brief Gets last sync message - * @return PTPMessageSync last sync - */ - PTPMessageSync *getLastSync(void) { - return last_sync; - } - - /** - * @brief Locks PDelay RX - * @return TRUE if acquired the lock. FALSE otherwise - */ - bool getPDelayRxLock() { - return pdelay_rx_lock->lock() == oslock_ok ? true : false; - } - - /** - * @brief Do a trylock on the PDelay RX - * @return TRUE if acquired the lock. FALSE otherwise. - */ - bool tryPDelayRxLock() { - return pdelay_rx_lock->trylock() == oslock_ok ? true : false; - } - - /** - * @brief Unlocks PDelay RX. - * @return TRUE if success. FALSE otherwise - */ - bool putPDelayRxLock() { - return pdelay_rx_lock->unlock() == oslock_ok ? true : false; - } - - /** - * @brief Locks the TX port - * @return TRUE if success. FALSE otherwise. - */ - bool getTxLock() { - return port_tx_lock->lock() == oslock_ok ? true : false; - } - - /** - * @brief Unlocks the port TX. - * @return TRUE if success. FALSE otherwise. - */ - bool putTxLock() { - return port_tx_lock->unlock() == oslock_ok ? true : false; - } - - /** - * @brief Gets the hardware timestamper version - * @return HW timestamper version - */ - int getTimestampVersion() { - return _hw_timestamper->getVersion(); - } - - /** - * @brief Sets the last_pdelay_req message - * @param msg [in] PTPMessagePathDelayReq message to set - * @return void - */ - void setLastPDelayReq(PTPMessagePathDelayReq * msg) { - last_pdelay_req = msg; - } - - /** - * @brief Gets the last PTPMessagePathDelayReq message - * @return Last pdelay request - */ - PTPMessagePathDelayReq *getLastPDelayReq(void) { - return last_pdelay_req; - } - - /** - * @brief Sets the last PTPMessagePathDelayResp message - * @param msg [in] Last pdelay response - * @return void - */ - void setLastPDelayResp(PTPMessagePathDelayResp * msg) { - last_pdelay_resp = msg; - } - - /** - * @brief Gets the last PTPMessagePathDelayResp message - * @return Last pdelay response - */ - PTPMessagePathDelayResp *getLastPDelayResp(void) { - return last_pdelay_resp; - } - - /** - * @brief Sets the last PTPMessagePathDelayRespFollowUp message - * @param msg [in] last pdelay response follow up - * @return void - */ - void setLastPDelayRespFollowUp(PTPMessagePathDelayRespFollowUp * msg) { - last_pdelay_resp_fwup = msg; - } - - /** - * @brief Gets the last PTPMessagePathDelayRespFollowUp message - * @return last pdelay response follow up - */ - PTPMessagePathDelayRespFollowUp *getLastPDelayRespFollowUp(void) { - return last_pdelay_resp_fwup; - } - - /** - * @brief Gets the Peer rate offset. Used to calculate neighbor rate ratio. - * @return FrequencyRatio peer rate offset - */ - FrequencyRatio getPeerRateOffset(void) { - return _peer_rate_offset; - } - - /** - * @brief Sets the peer rate offset. Used to calculate neighbor rate ratio. - * @param offset Offset to be set - * @return void - */ - void setPeerRateOffset( FrequencyRatio offset ) { - _peer_rate_offset = offset; - } - - /** - * @brief Sets peer offset timestamps - * @param mine Local timestamps - * @param theirs Remote timestamps - * @return void - */ - void setPeerOffset(Timestamp mine, Timestamp theirs) { - _peer_offset_ts_mine = mine; - _peer_offset_ts_theirs = theirs; - _peer_offset_init = true; - } - - /** - * @brief Gets peer offset timestamps - * @param mine [out] Reference to local timestamps - * @param theirs [out] Reference to remote timestamps - * @return TRUE if peer offset has already been initialized. FALSE otherwise. - */ - bool getPeerOffset(Timestamp & mine, Timestamp & theirs) { - mine = _peer_offset_ts_mine; - theirs = _peer_offset_ts_theirs; - return _peer_offset_init; - } - - /** - * @brief Adjusts the clock frequency. - * @param freq_offset Frequency offset - * @return TRUE if adjusted. FALSE otherwise. - */ - bool _adjustClockRate( FrequencyRatio freq_offset ) { - if( _hw_timestamper ) { - return _hw_timestamper->HWTimestamper_adjclockrate((float) freq_offset ); - } - return false; - } - - /** - * @brief Adjusts the clock frequency. - * @param freq_offset Frequency offset - * @return TRUE if adjusted. FALSE otherwise. - */ - bool adjustClockRate( FrequencyRatio freq_offset ) { - return _adjustClockRate( freq_offset ); - } - - /** - * @brief Gets extended error message from hardware timestamper - * @param msg [out] Extended error message - * @return void - */ - void getExtendedError(char *msg) { - if (_hw_timestamper) { - _hw_timestamper->HWTimestamper_get_extderror(msg); - } else { - *msg = '\0'; - } - } - - /** - * @brief Initializes the hwtimestamper - */ - void timestamper_init(void); - - /** - * @brief Resets the hwtimestamper - */ - void timestamper_reset(void); - - - /** - * @brief Gets RX timestamp based on port identity - * @param sourcePortIdentity [in] Source port identity - * @param sequenceId Sequence ID - * @param timestamp [out] RX timestamp - * @param counter_value [out] timestamp count value - * @param last If true, removes the rx lock. - * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. - */ - int getRxTimestamp - (PortIdentity * sourcePortIdentity, PTPMessageId messageId, - Timestamp & timestamp, unsigned &counter_value, bool last); - - /** - * @brief Gets TX timestamp based on port identity - * @param sourcePortIdentity [in] Source port identity - * @param sequenceId Sequence ID - * @param timestamp [out] TX timestamp - * @param counter_value [out] timestamp count value - * @param last If true, removes the TX lock - * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. - */ - int getTxTimestamp - (PortIdentity * sourcePortIdentity, PTPMessageId messageId, - Timestamp & timestamp, unsigned &counter_value, bool last); - - /** - * @brief Gets TX timestamp based on PTP message - * @param msg PTPMessageCommon message - * @param timestamp [out] TX timestamp - * @param counter_value [out] timestamp count value - * @param last If true, removes the TX lock - * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. - */ - int getTxTimestamp - (PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, - bool last); - - /** - * @brief Gets RX timestamp based on PTP message - * @param msg PTPMessageCommon message - * @param timestamp [out] RX timestamp - * @param counter_value [out] timestamp count value - * @param last If true, removes the RX lock - * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. - */ - int getRxTimestamp - (PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, - bool last); - - /** - * @brief Get the cross timestamping information. - * The gPTP subsystem uses these samples to calculate - * ratios which can be used to translate or extrapolate - * one clock into another clock reference. The gPTP service - * uses these supplied cross timestamps to perform internal - * rate estimation and conversion functions. - * @param system_time [out] System time - * @param device_time [out] Device time - * @param local_clock [out] Local clock - * @param nominal_clock_rate [out] Nominal clock rate - * @return True in case of success. FALSE in case of error - */ - void getDeviceTime - (Timestamp & system_time, Timestamp & device_time, uint32_t & local_clock, - uint32_t & nominal_clock_rate); - - /** - * @brief Gets the link delay information. - * @return one way delay if delay > 0, or zero otherwise. - */ - uint64_t getLinkDelay(void) { - return one_way_delay > 0LL ? one_way_delay : 0LL; - } - - /** - * @brief Gets the link delay information. - * @param [in] delay Pointer to the delay information - * @return True if valid, false if invalid - */ - bool getLinkDelay(uint64_t *delay) { - if(delay == NULL) { - return false; - } - *delay = getLinkDelay(); - return *delay < INVALID_LINKDELAY; - } - - /** - * @brief Sets link delay information. - * Signed value allows this to be negative result because - * of inaccurate timestamps. - * @param delay Link delay - * @return True if one_way_delay is lower or equal than neighbor propagation delay threshold - * False otherwise - */ - bool setLinkDelay(int64_t delay) { - one_way_delay = delay; - int64_t abs_delay = (one_way_delay < 0 ? -one_way_delay : one_way_delay); - - if (testMode) { - GPTP_LOG_STATUS("Link delay: %d", delay); - } - - return (abs_delay <= neighbor_prop_delay_thresh); - } - - /** - * @brief Sets the internal variabl sync_receipt_thresh, which is the - * flag that monitors the amount of wrong syncs enabled before switching - * the ptp to master. - * @param th Threshold to be set - * @return void - */ - void setSyncReceiptThresh(unsigned int th) - { - sync_receipt_thresh = th; - } - - /** - * @brief Gets the internal variabl sync_receipt_thresh, which is the - * flag that monitors the amount of wrong syncs enabled before switching - * the ptp to master. - * @return sync_receipt_thresh value - */ - unsigned int getSyncReceiptThresh(void) - { - return sync_receipt_thresh; - } - - /** - * @brief Sets the wrongSeqIDCounter variable - * @param cnt Value to be set - * @return void - */ - void setWrongSeqIDCounter(unsigned int cnt) - { - wrongSeqIDCounter = cnt; - } - - /** - * @brief Gets the wrongSeqIDCounter value - * @param [out] cnt Pointer to the counter value. It must be valid - * @return TRUE if ok and lower than the syncReceiptThreshold value. FALSE otherwise - */ - bool getWrongSeqIDCounter(unsigned int *cnt) - { - if( cnt == NULL ) - { - return false; - } - *cnt = wrongSeqIDCounter; - - return( *cnt < getSyncReceiptThresh() ); - } - - /** - * @brief Increments the wrongSeqIDCounter value - * @param [out] cnt Pointer to the counter value. Must be valid - * @return TRUE if incremented value is lower than the syncReceiptThreshold. FALSE otherwise. - */ - bool incWrongSeqIDCounter(unsigned int *cnt) - { - if( getAsCapable() ) - { - wrongSeqIDCounter++; - } - bool ret = wrongSeqIDCounter < getSyncReceiptThresh(); - - if( cnt != NULL) - { - *cnt = wrongSeqIDCounter; - } - - return ret; - } - - /** - * @brief Sets the value of last duplicated SeqID - * @param seqid Value to set - * @return void - */ - void setLastInvalidSeqID(uint16_t seqid) - { - last_invalid_seqid = seqid; - } - - /** - * @brief Get the value of last invalid seqID - * @return Last invalid seq id - */ - uint16_t getLastInvalidSeqID(void) - { - return last_invalid_seqid; - } - - /** - * @brief Sets the duplicate pdelay_resp counter. - * @param cnt Value to be set - */ - void setDuplicateRespCounter(unsigned int cnt) - { - duplicate_resp_counter = cnt; - } - - /** - * @brief Gets the current value of pdelay_resp duplicate messages counter - * @return Counter value - */ - unsigned int getDuplicateRespCounter(void) - { - return duplicate_resp_counter; - } - - /** - * @brief Increment the duplicate PDelayResp message counter - * @return True if it equals the threshold, False otherwise - */ - bool incrementDuplicateRespCounter(void) - { - return ++duplicate_resp_counter == DUPLICATE_RESP_THRESH; - } - - /** - * @brief Sets the neighbor propagation delay threshold - * @param delay Delay in nanoseconds - * @return void - */ - void setNeighPropDelayThresh(int64_t delay) { - neighbor_prop_delay_thresh = delay; - } - - /** - * @brief Changes the port state - * @param state Current state - * @param changed_external_master TRUE if external master has changed, FALSE otherwise - * @return void - */ - void recommendState(PortState state, bool changed_external_master); - - /** - * @brief Maps socket addr to the remote link layer address - * @param destIdentity [in] PortIdentity remote - * @param remote [in] remote link layer address - * @return void - */ - void mapSocketAddr - (PortIdentity * destIdentity, LinkLayerAddress * remote); - - /** - * @brief Adds New sock addr map - * @param destIdentity [in] PortIdentity remote - * @param remote [in] remote link layer address - * @return void - */ - void addSockAddrMap - (PortIdentity * destIdentity, LinkLayerAddress * remote); - - /** - * @brief Sets current pdelay count value. - * @param cnt [in] pdelay count value - * @return void - */ - void setPdelayCount(unsigned int cnt) { - pdelay_count = cnt; - } - - /** - * @brief Increments Pdelay count - * @return void - */ - void incPdelayCount() { - ++pdelay_count; - } - - /** - * @brief Gets current pdelay count value. It is set to zero - * when asCapable is false. - * @return pdelay count - */ - unsigned getPdelayCount() { - return pdelay_count; - } - - /** - * @brief Sets current sync count value. - * @param cnt [in] sync count value - * @return void - */ - void setSyncCount(unsigned int cnt) { - sync_count = cnt; - } - - /** - * @brief Increments sync count - * @return void - */ - void incSyncCount() { - ++sync_count; - } - - /** - * @brief Gets current sync count value. It is set to zero - * when master and incremented at each sync received for slave. - * @return sync count - */ - unsigned getSyncCount() { - return sync_count; - } - - /** - * @brief Gets link up count - * @return Link up count - */ - uint32_t getLinkUpCount() { - return linkUpCount; - } - - /** - * @brief Gets link down count - * @return Link down count - */ - uint32_t getLinkDownCount() { - return linkDownCount; - } - - /** - * @brief Sets the Station State for the Test Status message - * @param StationState_t [in] The station state - * @return none - */ - void setStationState(StationState_t _stationState) { - stationState = _stationState; - if (stationState == STATION_STATE_ETHERNET_READY) { - GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_ETHERNET_READY"); - } - else if (stationState == STATION_STATE_AVB_SYNC) { - GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_AVB_SYNC"); - } - else if (stationState == STATION_STATE_AVB_MEDIA_READY) { - GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_AVB_MEDIA_READY"); - } - } - - /** - * @brief Gets the Station State for the Test Status - * message - * @return station state - */ - StationState_t getStationState() { - return stationState; - } - - - /** - * @brief Gets the lastGmTimeBaseIndicator - * @return uint16 of the lastGmTimeBaseIndicator - */ - uint16_t getLastGmTimeBaseIndicator(void) { - return lastGmTimeBaseIndicator; - } - - /** - * @brief Sets the lastGmTimeBaseIndicator - * @param gmTimeBaseIndicator from last Follow up message - * @return void - */ - void setLastGmTimeBaseIndicator(uint16_t gmTimeBaseIndicator) { - lastGmTimeBaseIndicator = gmTimeBaseIndicator; - } - - /** - * @brief Gets the testMode - * @return bool of the test mode value - */ - bool getTestMode(void) { - return testMode; - } - - /** - * @brief Sets the linkUp status - * @param bool of the linkUp status - * @return void - */ - void setLinkUpState(bool state) { - linkUp = state; - } - - /** - * @brief Gets the linkUp status - * @return bool of the linkUp status - */ - bool getLinkUpState(void) { - return linkUp; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxSyncCount - * @return void - */ - void incCounter_ieee8021AsPortStatRxSyncCount(void) { - counters.ieee8021AsPortStatRxSyncCount++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxFollowUpCount - * @return void - */ - void incCounter_ieee8021AsPortStatRxFollowUpCount(void) { - counters.ieee8021AsPortStatRxFollowUpCount++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxPdelayRequest - * @return void - */ - void incCounter_ieee8021AsPortStatRxPdelayRequest(void) { - counters.ieee8021AsPortStatRxPdelayRequest++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxPdelayResponse - * @return void - */ - void incCounter_ieee8021AsPortStatRxPdelayResponse(void) { - counters.ieee8021AsPortStatRxPdelayResponse++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxPdelayResponseFollowUp - * @return void - */ - void incCounter_ieee8021AsPortStatRxPdelayResponseFollowUp(void) { - counters.ieee8021AsPortStatRxPdelayResponseFollowUp++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxAnnounce - * @return void - */ - void incCounter_ieee8021AsPortStatRxAnnounce(void) { - counters.ieee8021AsPortStatRxAnnounce++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxPTPPacketDiscard - * @return void - */ - void incCounter_ieee8021AsPortStatRxPTPPacketDiscard(void) { - counters.ieee8021AsPortStatRxPTPPacketDiscard++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatRxSyncReceiptTimeouts - * @return void - */ - void incCounter_ieee8021AsPortStatRxSyncReceiptTimeouts(void) { - counters.ieee8021AsPortStatRxSyncReceiptTimeouts++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatAnnounceReceiptTimeouts - * @return void - */ - void incCounter_ieee8021AsPortStatAnnounceReceiptTimeouts(void) { - counters.ieee8021AsPortStatAnnounceReceiptTimeouts++; - } - - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatPdelayAllowedLostResponsesExceeded - * @return void - */ - // TODO: Not called - void incCounter_ieee8021AsPortStatPdelayAllowedLostResponsesExceeded(void) { - counters.ieee8021AsPortStatPdelayAllowedLostResponsesExceeded++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxSyncCount - * @return void - */ - void incCounter_ieee8021AsPortStatTxSyncCount(void) { - counters.ieee8021AsPortStatTxSyncCount++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxFollowUpCount - * @return void - */ - void incCounter_ieee8021AsPortStatTxFollowUpCount(void) { - counters.ieee8021AsPortStatTxFollowUpCount++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxPdelayRequest - * @return void - */ - void incCounter_ieee8021AsPortStatTxPdelayRequest(void) { - counters.ieee8021AsPortStatTxPdelayRequest++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxPdelayResponse - * @return void - */ - void incCounter_ieee8021AsPortStatTxPdelayResponse(void) { - counters.ieee8021AsPortStatTxPdelayResponse++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxPdelayResponseFollowUp - * @return void - */ - void incCounter_ieee8021AsPortStatTxPdelayResponseFollowUp(void) { - counters.ieee8021AsPortStatTxPdelayResponseFollowUp++; - } - - /** - * @brief Increment IEEE Port counter: - * ieee8021AsPortStatTxAnnounce - * @return void - */ - void incCounter_ieee8021AsPortStatTxAnnounce(void) { - counters.ieee8021AsPortStatTxAnnounce++; - } - - /** - * @brief Logs port counters - * @return void - */ - void logIEEEPortCounters(void) { - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxSyncCount : %u", counters.ieee8021AsPortStatRxSyncCount); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxFollowUpCount : %u", counters.ieee8021AsPortStatRxFollowUpCount); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxPdelayRequest : %u", counters.ieee8021AsPortStatRxPdelayRequest); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxPdelayResponse : %u", counters.ieee8021AsPortStatRxPdelayResponse); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxPdelayResponseFollowUp : %u", counters.ieee8021AsPortStatRxPdelayResponseFollowUp); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxAnnounce : %u", counters.ieee8021AsPortStatRxAnnounce); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxPTPPacketDiscard : %u", counters.ieee8021AsPortStatRxPTPPacketDiscard); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatRxSyncReceiptTimeouts : %u", counters.ieee8021AsPortStatRxSyncReceiptTimeouts); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatAnnounceReceiptTimeouts : %u", counters.ieee8021AsPortStatAnnounceReceiptTimeouts); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatPdelayAllowedLostResponsesExceeded : %u", counters.ieee8021AsPortStatPdelayAllowedLostResponsesExceeded); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxSyncCount : %u", counters.ieee8021AsPortStatTxSyncCount); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxFollowUpCount : %u", counters.ieee8021AsPortStatTxFollowUpCount); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxPdelayRequest : %u", counters.ieee8021AsPortStatTxPdelayRequest); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxPdelayResponse : %u", counters.ieee8021AsPortStatTxPdelayResponse); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxPdelayResponseFollowUp : %u", counters.ieee8021AsPortStatTxPdelayResponseFollowUp); - GPTP_LOG_STATUS("IEEE Port Counter ieee8021AsPortStatTxAnnounce : %u", counters.ieee8021AsPortStatTxAnnounce); - } -}; - -#endif diff --git a/daemons/gptp/common/common_port.cpp b/daemons/gptp/common/common_port.cpp new file mode 100644 index 00000000..a5116083 --- /dev/null +++ b/daemons/gptp/common/common_port.cpp @@ -0,0 +1,709 @@ +/****************************************************************************** + + 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 <common_port.hpp> +#include <avbts_clock.hpp> + +CommonPort::CommonPort( PortInit_t *portInit ) : + thread_factory( portInit->thread_factory ), + timer_factory( portInit->timer_factory ), + lock_factory( portInit->lock_factory ), + condition_factory( portInit->condition_factory ), + _hw_timestamper( portInit->timestamper ), + clock( portInit->clock ), + isGM( portInit->isGM ) +{ + one_way_delay = ONE_WAY_DELAY_DEFAULT; + neighbor_prop_delay_thresh = NEIGHBOR_PROP_DELAY_THRESH; + net_label = portInit->net_label; + link_thread = thread_factory->createThread(); + listening_thread = thread_factory->createThread(); + sync_receipt_thresh = DEFAULT_SYNC_RECEIPT_THRESH; + wrongSeqIDCounter = 0; + memset(phy_delay, 0, sizeof(phy_delay)); + _peer_rate_offset = 1.0; + _peer_offset_init = false; + ifindex = portInit->index; + testMode = false; + port_state = PTP_INITIALIZING; + clock->registerPort(this, ifindex); + qualified_announce = NULL; + announce_sequence_id = 0; + signal_sequence_id = 0; + sync_sequence_id = 0; + initialLogSyncInterval = portInit->initialLogSyncInterval; + log_mean_announce_interval = 0; + pdelay_count = 0; + asCapable = false; +} + +CommonPort::~CommonPort() +{ + delete qualified_announce; +} + +bool CommonPort::init_port( int phy_delay[4] ) +{ + log_mean_sync_interval = initialLogSyncInterval; + + if (!OSNetworkInterfaceFactory::buildInterface + ( &net_iface, factory_name_t("default"), net_label, + _hw_timestamper)) + return false; + + this->net_iface->getLinkLayerAddress(&local_addr); + clock->setClockIdentity(&local_addr); + memcpy(this->phy_delay, phy_delay, sizeof(this->phy_delay)); + + this->timestamper_init(); + + port_identity.setClockIdentity(clock->getClockIdentity()); + port_identity.setPortNumber(&ifindex); + + syncReceiptTimerLock = lock_factory->createLock(oslock_recursive); + syncIntervalTimerLock = lock_factory->createLock(oslock_recursive); + announceIntervalTimerLock = lock_factory->createLock(oslock_recursive); + + return _init_port(); +} + +void CommonPort::timestamper_init( void ) +{ + if( _hw_timestamper != NULL ) + { + _hw_timestamper->init_phy_delay(this->phy_delay); + if( !_hw_timestamper->HWTimestamper_init + ( net_label, net_iface )) + { + GPTP_LOG_ERROR + ( "Failed to initialize hardware timestamper, " + "falling back to software timestamping" ); + return; + } + } +} + +void CommonPort::timestamper_reset( void ) +{ + if( _hw_timestamper != NULL ) + { + _hw_timestamper->init_phy_delay(this->phy_delay); + _hw_timestamper->HWTimestamper_reset(); + } +} + +PTPMessageAnnounce *CommonPort::calculateERBest( void ) +{ + return qualified_announce; +} + +void CommonPort::recommendState +( PortState state, bool changed_external_master ) +{ + bool reset_sync = false; + switch (state) { + case PTP_MASTER: + if ( getPortState() != PTP_MASTER ) + { + setPortState( PTP_MASTER ); + // Start announce receipt timeout timer + // Start sync receipt timeout timer + becomeMaster( true ); + reset_sync = true; + } + break; + case PTP_SLAVE: + if ( getPortState() != PTP_SLAVE ) + { + becomeSlave( true ); + reset_sync = true; + } else { + if( changed_external_master ) { + GPTP_LOG_STATUS("Changed master!" ); + clock->newSyntonizationSetPoint(); + clock->updateFUPInfo(); + reset_sync = true; + } + } + break; + default: + GPTP_LOG_ERROR + ("Invalid state change requested by call to " + "1588Port::recommendState()"); + break; + } + if( reset_sync ) sync_count = 0; + return; +} + +bool CommonPort::serializeState( void *buf, off_t *count ) +{ + bool ret = true; + + if( buf == NULL ) { + *count = sizeof(port_state)+sizeof(_peer_rate_offset)+ + sizeof(asCapable)+sizeof(one_way_delay); + return true; + } + + if( port_state != PTP_MASTER && port_state != PTP_SLAVE ) { + *count = 0; + ret = false; + goto bail; + } + + /* asCapable */ + if( ret && *count >= (off_t) sizeof( asCapable )) { + memcpy( buf, &asCapable, sizeof( asCapable )); + *count -= sizeof( asCapable ); + buf = ((char *)buf) + sizeof( asCapable ); + } else if( ret == false ) { + *count += sizeof( asCapable ); + } else { + *count = sizeof( asCapable )-*count; + ret = false; + } + + /* Port State */ + if( ret && *count >= (off_t) sizeof( port_state )) { + memcpy( buf, &port_state, sizeof( port_state )); + *count -= sizeof( port_state ); + buf = ((char *)buf) + sizeof( port_state ); + } else if( ret == false ) { + *count += sizeof( port_state ); + } else { + *count = sizeof( port_state )-*count; + ret = false; + } + + /* Link Delay */ + if( ret && *count >= (off_t) sizeof( one_way_delay )) { + memcpy( buf, &one_way_delay, sizeof( one_way_delay )); + *count -= sizeof( one_way_delay ); + buf = ((char *)buf) + sizeof( one_way_delay ); + } else if( ret == false ) { + *count += sizeof( one_way_delay ); + } else { + *count = sizeof( one_way_delay )-*count; + ret = false; + } + + /* Neighbor Rate Ratio */ + if( ret && *count >= (off_t) sizeof( _peer_rate_offset )) { + memcpy( buf, &_peer_rate_offset, sizeof( _peer_rate_offset )); + *count -= sizeof( _peer_rate_offset ); + buf = ((char *)buf) + sizeof( _peer_rate_offset ); + } else if( ret == false ) { + *count += sizeof( _peer_rate_offset ); + } else { + *count = sizeof( _peer_rate_offset )-*count; + ret = false; + } + + bail: + return ret; +} + +bool CommonPort::restoreSerializedState +( void *buf, off_t *count ) +{ + bool ret = true; + + /* asCapable */ + if( ret && *count >= (off_t) sizeof( asCapable )) { + memcpy( &asCapable, buf, sizeof( asCapable )); + *count -= sizeof( asCapable ); + buf = ((char *)buf) + sizeof( asCapable ); + } else if( ret == false ) { + *count += sizeof( asCapable ); + } else { + *count = sizeof( asCapable )-*count; + ret = false; + } + + /* Port State */ + if( ret && *count >= (off_t) sizeof( port_state )) { + memcpy( &port_state, buf, sizeof( port_state )); + *count -= sizeof( port_state ); + buf = ((char *)buf) + sizeof( port_state ); + } else if( ret == false ) { + *count += sizeof( port_state ); + } else { + *count = sizeof( port_state )-*count; + ret = false; + } + + /* Link Delay */ + if( ret && *count >= (off_t) sizeof( one_way_delay )) { + memcpy( &one_way_delay, buf, sizeof( one_way_delay )); + *count -= sizeof( one_way_delay ); + buf = ((char *)buf) + sizeof( one_way_delay ); + } else if( ret == false ) { + *count += sizeof( one_way_delay ); + } else { + *count = sizeof( one_way_delay )-*count; + ret = false; + } + + /* Neighbor Rate Ratio */ + if( ret && *count >= (off_t) sizeof( _peer_rate_offset )) { + memcpy( &_peer_rate_offset, buf, sizeof( _peer_rate_offset )); + *count -= sizeof( _peer_rate_offset ); + buf = ((char *)buf) + sizeof( _peer_rate_offset ); + } else if( ret == false ) { + *count += sizeof( _peer_rate_offset ); + } else { + *count = sizeof( _peer_rate_offset )-*count; + ret = false; + } + + return ret; +} + +void CommonPort::startSyncReceiptTimer +( long long unsigned int waitTime ) +{ + syncReceiptTimerLock->lock(); + clock->deleteEventTimerLocked( this, SYNC_RECEIPT_TIMEOUT_EXPIRES ); + clock->addEventTimerLocked + ( this, SYNC_RECEIPT_TIMEOUT_EXPIRES, waitTime ); + syncReceiptTimerLock->unlock(); +} + +void CommonPort::stopSyncReceiptTimer( void ) +{ + syncReceiptTimerLock->lock(); + clock->deleteEventTimerLocked( this, SYNC_RECEIPT_TIMEOUT_EXPIRES ); + syncReceiptTimerLock->unlock(); +} + +void CommonPort::startSyncIntervalTimer +( long long unsigned int waitTime ) +{ + syncIntervalTimerLock->lock(); + clock->deleteEventTimerLocked(this, SYNC_INTERVAL_TIMEOUT_EXPIRES); + clock->addEventTimerLocked + (this, SYNC_INTERVAL_TIMEOUT_EXPIRES, waitTime); + syncIntervalTimerLock->unlock(); +} + +void CommonPort::startAnnounceIntervalTimer +( long long unsigned int waitTime ) +{ + announceIntervalTimerLock->lock(); + clock->deleteEventTimerLocked + ( this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES ); + clock->addEventTimerLocked + ( this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES, waitTime ); + announceIntervalTimerLock->unlock(); +} + +bool CommonPort::processStateChange( Event e ) +{ + bool changed_external_master; + uint8_t LastEBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; + int number_ports, j; + PTPMessageAnnounce *EBest = NULL; + char EBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; + CommonPort **ports; + + // Nothing to do if we are slave only + if ( clock->getPriority1() == 255 ) + return true; + + clock->getPortList(number_ports, ports); + + /* Find EBest for all ports */ + j = 0; + for (int i = 0; i < number_ports; ++i) { + while (ports[j] == NULL) + ++j; + if ( ports[j]->getPortState() == PTP_DISABLED || + ports[j]->getPortState() == PTP_FAULTY ) + { + continue; + } + if( EBest == NULL ) + { + EBest = ports[j]->calculateERBest(); + } + else if( ports[j]->calculateERBest() ) + { + if( ports[j]-> + calculateERBest()->isBetterThan(EBest)) + { + EBest = ports[j]->calculateERBest(); + } + } + } + + if (EBest == NULL) + { + return true; + } + + /* Check if we've changed */ + clock->getLastEBestIdentity(). + getIdentityString( LastEBestClockIdentity ); + EBest->getGrandmasterIdentity( EBestClockIdentity ); + if( memcmp( EBestClockIdentity, LastEBestClockIdentity, + PTP_CLOCK_IDENTITY_LENGTH ) != 0 ) + { + ClockIdentity newGM; + changed_external_master = true; + newGM.set((uint8_t *) EBestClockIdentity ); + clock->setLastEBestIdentity( newGM ); + } + else + { + changed_external_master = false; + } + + if( clock->isBetterThan( EBest )) + { + // We're Grandmaster, set grandmaster info to me + ClockIdentity clock_identity; + unsigned char priority1; + unsigned char priority2; + ClockQuality clock_quality; + + clock_identity = getClock()->getClockIdentity(); + getClock()->setGrandmasterClockIdentity( clock_identity ); + priority1 = getClock()->getPriority1(); + getClock()->setGrandmasterPriority1( priority1 ); + priority2 = getClock()->getPriority2(); + getClock()->setGrandmasterPriority2( priority2 ); + clock_quality = getClock()->getClockQuality(); + getClock()->setGrandmasterClockQuality( clock_quality ); + } + + j = 0; + for( int i = 0; i < number_ports; ++i ) + { + while (ports[j] == NULL) + ++j; + if ( ports[j]->getPortState() == + PTP_DISABLED || + ports[j]->getPortState() == + PTP_FAULTY) + { + continue; + } + if (clock->isBetterThan(EBest)) + { + // We are the GrandMaster, all ports are master + EBest = NULL; // EBest == NULL : we were grandmaster + ports[j]->recommendState( PTP_MASTER, + changed_external_master ); + } else { + if( EBest == ports[j]->calculateERBest() ) { + // The "best" Announce was received on this + // port + ClockIdentity clock_identity; + unsigned char priority1; + unsigned char priority2; + ClockQuality *clock_quality; + + ports[j]->recommendState + ( PTP_SLAVE, changed_external_master ); + clock_identity = + EBest->getGrandmasterClockIdentity(); + getClock()->setGrandmasterClockIdentity + ( clock_identity ); + priority1 = EBest->getGrandmasterPriority1(); + getClock()->setGrandmasterPriority1 + ( priority1 ); + priority2 = + EBest->getGrandmasterPriority2(); + getClock()->setGrandmasterPriority2 + ( priority2 ); + clock_quality = + EBest->getGrandmasterClockQuality(); + getClock()->setGrandmasterClockQuality + (*clock_quality); + } else { + /* Otherwise we are the master because we have + sync'd to a better clock */ + ports[j]->recommendState + (PTP_MASTER, changed_external_master); + } + } + } + + return true; +} + + +bool CommonPort::processSyncAnnounceTimeout( Event e ) +{ + // Nothing to do + if( clock->getPriority1() != 255 ) + return true; + + // Restart timer + if( e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES ) { + clock->addEventTimerLocked + (this, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES, + (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER* + (unsigned long long) + (pow((double)2,getAnnounceInterval())* + 1000000000.0))); + } else { + startSyncReceiptTimer + ((unsigned long long) + (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * + ((double) pow((double)2, getSyncInterval()) * + 1000000000.0))); + } + + if ( getPortState() == PTP_INITIALIZING || + getPortState() == PTP_UNCALIBRATED || + getPortState() == PTP_SLAVE || + getPortState() == PTP_PRE_MASTER ) + { + GPTP_LOG_STATUS( + "*** %s Timeout Expired - Becoming Master", + e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES ? "Announce" : + "Sync" ); + { + // We're Grandmaster, set grandmaster info to me + ClockIdentity clock_identity; + unsigned char priority1; + unsigned char priority2; + ClockQuality clock_quality; + + clock_identity = getClock()->getClockIdentity(); + getClock()->setGrandmasterClockIdentity + ( clock_identity ); + priority1 = getClock()->getPriority1(); + getClock()->setGrandmasterPriority1( priority1 ); + priority2 = getClock()->getPriority2(); + getClock()->setGrandmasterPriority2( priority2 ); + clock_quality = getClock()->getClockQuality(); + getClock()->setGrandmasterClockQuality + ( clock_quality ); + } + setPortState( PTP_MASTER ); + Timestamp system_time; + Timestamp device_time; + + uint32_t local_clock, nominal_clock_rate; + + getDeviceTime(system_time, device_time, + local_clock, nominal_clock_rate); + + (void) clock->calcLocalSystemClockRateDifference + ( device_time, system_time ); + + setQualifiedAnnounce( NULL ); + + // Add timers for Announce and Sync, this is as close to + // immediately as we get + if( clock->getPriority1() != 255) + { + clock->addEventTimerLocked + ( this, SYNC_INTERVAL_TIMEOUT_EXPIRES, + 16000000 ); + } + startAnnounce(); + } + + return true; +} + +bool CommonPort::processEvent( Event e ) +{ + bool ret; + + switch( e ) + { + default: + // Unhandled event + ret = _processEvent( e ); + break; + + case POWERUP: + case INITIALIZE: + GPTP_LOG_DEBUG("Received POWERUP/INITIALIZE event"); + + // If port has been configured as master or slave, run media + // specific configuration. If it hasn't been configured + // start announce message time + if( clock->getPriority1() == 255 || + port_state == PTP_SLAVE ) + { + becomeSlave( true ); + } + else if( port_state == PTP_MASTER ) + { + becomeMaster( true ); + } + else + { + startAnnounce(); + } + + // Do any media specific initialization + ret = _processEvent( e ); + break; + + case STATE_CHANGE_EVENT: + ret = _processEvent( e ); + + // If this event wasn't handled in a media specific way, call + // the default action + if( !ret ) + ret = processStateChange( e ); + break; + + case ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES: + case SYNC_RECEIPT_TIMEOUT_EXPIRES: + if (e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES) { + incCounter_ieee8021AsPortStatAnnounceReceiptTimeouts(); + } + else if (e == SYNC_RECEIPT_TIMEOUT_EXPIRES) { + incCounter_ieee8021AsPortStatRxSyncReceiptTimeouts(); + } + + ret = _processEvent( e ); + + // If this event wasn't handled in a media specific way, call + // the default action + if( !ret ) + ret = processSyncAnnounceTimeout( e ); + break; + + case ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES: + GPTP_LOG_DEBUG("ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES occured"); + if( !asCapable ) + { + ret = true; + break; + } + + // Send an announce message + { + PTPMessageAnnounce *annc = + new PTPMessageAnnounce(this); + PortIdentity dest_id; + PortIdentity gmId; + ClockIdentity clock_id = clock->getClockIdentity(); + gmId.setClockIdentity(clock_id); + getPortIdentity( dest_id ); + annc->setPortIdentity( &dest_id ); + annc->sendPort( this, NULL ); + delete annc; + } + + startAnnounceIntervalTimer + ((uint64_t)( pow((double)2, getAnnounceInterval()) * + 1000000000.0 )); + ret = true; + break; + + case SYNC_INTERVAL_TIMEOUT_EXPIRES: + GPTP_LOG_DEBUG("SYNC_INTERVAL_TIMEOUT_EXPIRES occured"); + // If asCapable is true attempt some media specific action + ret = true; + if( asCapable ) + ret = _processEvent( e ); + + /* Do getDeviceTime() after transmitting sync frame + causing an update to local/system timestamp */ + { + Timestamp system_time; + Timestamp device_time; + uint32_t local_clock, nominal_clock_rate; + FrequencyRatio local_system_freq_offset; + int64_t local_system_offset; + + getDeviceTime + ( system_time, device_time, + local_clock, nominal_clock_rate ); + + GPTP_LOG_VERBOSE + ( "port::processEvent(): System time: %u,%u " + "Device Time: %u,%u", + system_time.seconds_ls, + system_time.nanoseconds, + device_time.seconds_ls, + device_time.nanoseconds ); + + local_system_offset = + TIMESTAMP_TO_NS(system_time) - + TIMESTAMP_TO_NS(device_time); + local_system_freq_offset = + clock->calcLocalSystemClockRateDifference + ( device_time, system_time ); + clock->setMasterOffset + ( this, 0, device_time, 1.0, + local_system_offset, system_time, + local_system_freq_offset, getSyncCount(), + pdelay_count, port_state, asCapable ); + } + + // Call media specific action for completed sync + syncDone(); + + // Restart the timer + startSyncIntervalTimer + ((uint64_t)( pow((double)2, getSyncInterval()) * + 1000000000.0 )); + + break; + } + + return ret; +} + +void CommonPort::getDeviceTime +( Timestamp &system_time, Timestamp &device_time, + uint32_t &local_clock, uint32_t &nominal_clock_rate ) +{ + if (_hw_timestamper) { + _hw_timestamper->HWTimestamper_gettime + ( &system_time, &device_time, + &local_clock, &nominal_clock_rate ); + } else { + device_time = system_time = clock->getSystemTime(); + local_clock = nominal_clock_rate = 0; + } + + return; +} + +void CommonPort::startAnnounce() +{ + startAnnounceIntervalTimer(16000000); +} diff --git a/daemons/gptp/common/common_port.hpp b/daemons/gptp/common/common_port.hpp new file mode 100644 index 00000000..da333a74 --- /dev/null +++ b/daemons/gptp/common/common_port.hpp @@ -0,0 +1,1344 @@ +/****************************************************************************** + + 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. + +******************************************************************************/ + + +#ifndef COMMON_PORT_HPP +#define COMMON_PORT_HPP + +#include <avbts_message.hpp> +#include <avbts_osthread.hpp> +#include <avbts_oscondition.hpp> +#include <avbts_ostimer.hpp> +#include <avbts_oslock.hpp> +#include <avbts_osnet.hpp> + +#include <math.h> + +class IEEE1588Clock; + +/** + * @brief PortIdentity interface + * Defined at IEEE 802.1AS Clause 8.5.2 + */ +class PortIdentity { +private: + ClockIdentity clock_id; + uint16_t portNumber; +public: + /** + * @brief Default Constructor + */ + PortIdentity() { }; + + /** + * @brief Constructs PortIdentity interface. + * @param clock_id Clock ID value as defined at IEEE 802.1AS Clause + * 8.5.2.2 + * @param portNumber Port Number + */ + PortIdentity(uint8_t * clock_id, uint16_t * portNumber) + { + this->portNumber = *portNumber; + this->portNumber = PLAT_ntohs(this->portNumber); + this->clock_id.set(clock_id); + } + + /** + * @brief Implements the operator '!=' overloading method. Compares + * clock_id and portNumber. + * @param cmp Constant PortIdentity value to be compared against. + * @return TRUE if the comparison value differs from the object's + * PortIdentity value. FALSE otherwise. + */ + bool operator!=(const PortIdentity & cmp) const + { + return + !(this->clock_id == cmp.clock_id) || + this->portNumber != cmp.portNumber ? true : false; + } + + /** + * @brief Implements the operator '==' overloading method. Compares + * clock_id and portNumber. + * @param cmp Constant PortIdentity value to be compared against. + * @return TRUE if the comparison value equals to the object's + * PortIdentity value. FALSE otherwise. + */ + bool operator==(const PortIdentity & cmp)const + { + return + this->clock_id == cmp.clock_id && + this->portNumber == cmp.portNumber ? true : false; + } + + /** + * @brief Implements the operator '<' overloading method. Compares + * clock_id and portNumber. + * @param cmp Constant PortIdentity value to be compared against. + * @return TRUE if the comparison value is lower than the object's + * PortIdentity value. FALSE otherwise. + */ + bool operator<(const PortIdentity & cmp)const + { + return + this->clock_id < cmp.clock_id ? + true : this->clock_id == cmp.clock_id && + this->portNumber < cmp.portNumber ? true : false; + } + + /** + * @brief Implements the operator '>' overloading method. Compares + * clock_id and portNumber. + * @param cmp Constant PortIdentity value to be compared against. + * @return TRUE if the comparison value is greater than the object's + * PortIdentity value. FALSE otherwise. + */ + bool operator>(const PortIdentity & cmp)const + { + return + this->clock_id > cmp.clock_id ? + true : this->clock_id == cmp.clock_id && + this->portNumber > cmp.portNumber ? true : false; + } + + /** + * @brief Gets the ClockIdentity string + * @param id [out] Pointer to an array of octets. + * @return void + */ + void getClockIdentityString(uint8_t *id) + { + clock_id.getIdentityString(id); + } + + /** + * @brief Sets the ClockIdentity. + * @param clock_id Clock Identity to be set. + * @return void + */ + void setClockIdentity(ClockIdentity clock_id) + { + this->clock_id = clock_id; + } + + /** + * @brief Gets the clockIdentity value + * @return A copy of Clock identity value. + */ + ClockIdentity getClockIdentity( void ) { + return this->clock_id; + } + + /** + * @brief Gets the port number following the network byte order, i.e. + * Big-Endian. + * @param id [out] Port number + * @return void + */ + void getPortNumberNO(uint16_t * id) // Network byte order + { + uint16_t portNumberNO = PLAT_htons(portNumber); + *id = portNumberNO; + } + + /** + * @brief Gets the port number in the host byte order, which can be + * either Big-Endian + * or Little-Endian, depending on the processor where it is running. + * @param id Port number + * @return void + */ + void getPortNumber(uint16_t * id) // Host byte order + { + *id = portNumber; + } + + /** + * @brief Sets the Port number + * @param id [in] Port number + * @return void + */ + void setPortNumber(uint16_t * id) + { + portNumber = *id; + } +}; + +/** + * @brief Structure for initializing the port class + */ +typedef struct { + /* clock IEEE1588Clock instance */ + IEEE1588Clock * clock; + + /* index Interface index */ + uint16_t index; + + /* timestamper Hardware timestamper instance */ + HWTimestamper * timestamper; + + /* net_label Network label */ + InterfaceLabel *net_label; + + /* automotive_profile set the AVnu automotive profile */ + bool automotive_profile; + + /* Set to true if the port is the grandmaster. Used for fixed GM in + * the the AVnu automotive profile */ + bool isGM; + + /* Set to true if the port is the grandmaster. Used for fixed GM in + * the the AVnu automotive profile */ + bool testMode; + + /* Set to true if the port's network interface is up. Used to filter + * false LINKUP/LINKDOWN events */ + bool linkUp; + + /* gPTP 10.2.4.4 */ + char initialLogSyncInterval; + + /* gPTP 11.5.2.2 */ + char initialLogPdelayReqInterval; + + /* CDS 6.2.1.5 */ + char operLogPdelayReqInterval; + + /* CDS 6.2.1.6 */ + char operLogSyncInterval; + + /* condition_factory OSConditionFactory instance */ + OSConditionFactory * condition_factory; + + /* thread_factory OSThreadFactory instance */ + OSThreadFactory * thread_factory; + + /* timer_factory OSTimerFactory instance */ + OSTimerFactory * timer_factory; + + /* lock_factory OSLockFactory instance */ + OSLockFactory * lock_factory; +} PortInit_t; + + +/** + * @brief Structure for Port Counters + */ +typedef struct { + int32_t ieee8021AsPortStatRxSyncCount; + int32_t ieee8021AsPortStatRxFollowUpCount; + int32_t ieee8021AsPortStatRxPdelayRequest; + int32_t ieee8021AsPortStatRxPdelayResponse; + int32_t ieee8021AsPortStatRxPdelayResponseFollowUp; + int32_t ieee8021AsPortStatRxAnnounce; + int32_t ieee8021AsPortStatRxPTPPacketDiscard; + int32_t ieee8021AsPortStatRxSyncReceiptTimeouts; + int32_t ieee8021AsPortStatAnnounceReceiptTimeouts; + int32_t ieee8021AsPortStatPdelayAllowedLostResponsesExceeded; + int32_t ieee8021AsPortStatTxSyncCount; + int32_t ieee8021AsPortStatTxFollowUpCount; + int32_t ieee8021AsPortStatTxPdelayRequest; + int32_t ieee8021AsPortStatTxPdelayResponse; + int32_t ieee8021AsPortStatTxPdelayResponseFollowUp; + int32_t ieee8021AsPortStatTxAnnounce; +} PortCounters_t; + + +/** + * @brief Port functionality common to all network media + */ +class CommonPort +{ +private: + LinkLayerAddress local_addr; + PortIdentity port_identity; + + /* Network socket description + physical interface number that object represents */ + uint16_t ifindex; + + + /* Signed value allows this to be negative result because of inaccurate + timestamp */ + int64_t one_way_delay; + int64_t neighbor_prop_delay_thresh; + + InterfaceLabel *net_label; + + OSNetworkInterface *net_iface; + int phy_delay[4]; + + PortState port_state; + bool testMode; + + char log_mean_sync_interval; + char log_mean_announce_interval; + char initialLogSyncInterval; + + /*Sync threshold*/ + unsigned int sync_receipt_thresh; + unsigned int wrongSeqIDCounter; + + PortCounters_t counters; + + OSThread *listening_thread; + OSThread *link_thread; + + FrequencyRatio _peer_rate_offset; + Timestamp _peer_offset_ts_theirs; + Timestamp _peer_offset_ts_mine; + bool _peer_offset_init; + bool asCapable; + unsigned sync_count; /* 0 for master, increment for each sync + * received as slave */ + unsigned pdelay_count; + + PTPMessageAnnounce *qualified_announce; + + uint16_t announce_sequence_id; + uint16_t signal_sequence_id; + uint16_t sync_sequence_id; + + uint16_t lastGmTimeBaseIndicator; + + OSLock *syncReceiptTimerLock; + OSLock *syncIntervalTimerLock; + OSLock *announceIntervalTimerLock; + +protected: + static const unsigned int DEFAULT_SYNC_RECEIPT_THRESH = 5; + static const int64_t INVALID_LINKDELAY = 3600000000000; + static const int64_t ONE_WAY_DELAY_DEFAULT = INVALID_LINKDELAY; + static const int64_t NEIGHBOR_PROP_DELAY_THRESH = 800; + + OSThreadFactory const * const thread_factory; + OSTimerFactory const * const timer_factory; + OSLockFactory const * const lock_factory; + OSConditionFactory const * const condition_factory; + HWTimestamper * const _hw_timestamper; + IEEE1588Clock * const clock; + const bool isGM; + +public: + CommonPort( PortInit_t *portInit ); + virtual ~CommonPort(); + + /** + * @brief Global media dependent port initialization + * @param [in] phy_delay array representing delays introduced by the + * device PHY + * @return true on success + */ + bool init_port( int phy_delay[4] ); + + /** + * @brief Media specific port initialization + * @return true on success + */ + virtual bool _init_port( void ) = 0; + + /** + * @brief Initializes the hwtimestamper + */ + void timestamper_init( void ); + + /** + * @brief Resets the hwtimestamper + */ + void timestamper_reset( void ); + + /** + * @brief Gets the link delay information. + * @return one way delay if delay > 0, or zero otherwise. + */ + uint64_t getLinkDelay( void ) + { + return one_way_delay > 0LL ? one_way_delay : 0LL; + } + + /** + * @brief Gets the link delay information. + * @param [in] delay Pointer to the delay information + * @return True if valid, false if invalid + */ + bool getLinkDelay( uint64_t *delay ) + { + if(delay == NULL) { + return false; + } + *delay = getLinkDelay(); + return *delay < INVALID_LINKDELAY; + } + + /** + * @brief Sets link delay information. + * Signed value allows this to be negative result because + * of inaccurate timestamps. + * @param delay Link delay + * @return True if one_way_delay is lower or equal than neighbor + * propagation delay threshold False otherwise + */ + bool setLinkDelay( int64_t delay ) + { + one_way_delay = delay; + int64_t abs_delay = (one_way_delay < 0 ? + -one_way_delay : one_way_delay); + + if (testMode) { + GPTP_LOG_STATUS("Link delay: %d", delay); + } + + return (abs_delay <= neighbor_prop_delay_thresh); + } + + /** + * @brief Gets a pointer to IEEE1588Clock + * @return Pointer to clock + */ + IEEE1588Clock *getClock( void ) + { + return clock; + } + + /** + * @brief Gets the local_addr + * @return LinkLayerAddress + */ + LinkLayerAddress *getLocalAddr( void ) + { + return &local_addr; + } + + /** + * @brief Gets the testMode + * @return bool of the test mode value + */ + bool getTestMode( void ) + { + return testMode; + } + + /** + * @brief Sets the testMode + * @param testMode changes testMode to this value + */ + void setTestMode( bool testMode ) + { + this->testMode = testMode; + } + + /** + * @brief Serializes (i.e. copy over buf pointer) the information from + * the variables (in that order): + * - asCapable; + * - Port Sate; + * - Link Delay; + * - Neighbor Rate Ratio + * @param buf [out] Buffer where to put the results. + * @param count [inout] Length of buffer. It contains maximum length + * to be written + * when the function is called, and the value is decremented by the + * same amount the + * buf size increases. + * @return TRUE if it has successfully written to buf all the values + * or if buf is NULL. + * FALSE if count should be updated with the right size. + */ + bool serializeState( void *buf, long *count ); + + /** + * @brief Restores the serialized state from the buffer. Copies the + * information from buffer + * to the variables (in that order): + * - asCapable; + * - Port State; + * - Link Delay; + * - Neighbor Rate Ratio + * @param buf Buffer containing the serialized state. + * @param count Buffer lenght. It is decremented by the same size of + * the variables that are + * being copied. + * @return TRUE if everything was copied successfully, FALSE otherwise. + */ + bool restoreSerializedState( void *buf, long *count ); + + /** + * @brief Sets the internal variabl sync_receipt_thresh, which is the + * flag that monitors the amount of wrong syncs enabled before + * switching + * the ptp to master. + * @param th Threshold to be set + * @return void + */ + void setSyncReceiptThresh(unsigned int th) + { + sync_receipt_thresh = th; + } + + /** + * @brief Gets the internal variabl sync_receipt_thresh, which is the + * flag that monitors the amount of wrong syncs enabled before + * switching + * the ptp to master. + * @return sync_receipt_thresh value + */ + unsigned int getSyncReceiptThresh( void ) + { + return sync_receipt_thresh; + } + + /** + * @brief Sets the wrongSeqIDCounter variable + * @param cnt Value to be set + * @return void + */ + void setWrongSeqIDCounter(unsigned int cnt) + { + wrongSeqIDCounter = cnt; + } + + /** + * @brief Gets the wrongSeqIDCounter value + * @param [out] cnt Pointer to the counter value. It must be valid + * @return TRUE if ok and lower than the syncReceiptThreshold value. + * FALSE otherwise + */ + bool getWrongSeqIDCounter(unsigned int *cnt) + { + if( cnt == NULL ) + { + return false; + } + *cnt = wrongSeqIDCounter; + + return( *cnt < getSyncReceiptThresh() ); + } + + /** + * @brief Increments the wrongSeqIDCounter value + * @param [out] cnt Pointer to the counter value. Must be valid + * @return TRUE if incremented value is lower than the + * syncReceiptThreshold. FALSE otherwise. + */ + bool incWrongSeqIDCounter(unsigned int *cnt) + { + if( getAsCapable() ) + { + wrongSeqIDCounter++; + } + bool ret = wrongSeqIDCounter < getSyncReceiptThresh(); + + if( cnt != NULL) + { + *cnt = wrongSeqIDCounter; + } + + return ret; + } + + /** + * @brief Gets the hardware timestamper version + * @return HW timestamper version + */ + int getTimestampVersion() { + return _hw_timestamper->getVersion(); + } + + /** + * @brief Adjusts the clock frequency. + * @param freq_offset Frequency offset + * @return TRUE if adjusted. FALSE otherwise. + */ + bool _adjustClockRate( FrequencyRatio freq_offset ) { + if( _hw_timestamper ) { + return _hw_timestamper->HWTimestamper_adjclockrate + ((float) freq_offset ); + } + return false; + } + + /** + * @brief Adjusts the clock frequency. + * @param freq_offset Frequency offset + * @return TRUE if adjusted. FALSE otherwise. + */ + bool adjustClockRate( FrequencyRatio freq_offset ) { + return _adjustClockRate( freq_offset ); + } + + /** + * @brief Gets extended error message from hardware timestamper + * @param msg [out] Extended error message + * @return void + */ + void getExtendedError(char *msg) { + if (_hw_timestamper) { + _hw_timestamper->HWTimestamper_get_extderror(msg); + } else { + *msg = '\0'; + } + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxSyncCount + * @return void + */ + void incCounter_ieee8021AsPortStatRxSyncCount( void ) + { + counters.ieee8021AsPortStatRxSyncCount++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxFollowUpCount + * @return void + */ + void incCounter_ieee8021AsPortStatRxFollowUpCount( void ) + { + counters.ieee8021AsPortStatRxFollowUpCount++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxPdelayRequest + * @return void + */ + void incCounter_ieee8021AsPortStatRxPdelayRequest( void ) + { + counters.ieee8021AsPortStatRxPdelayRequest++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxPdelayResponse + * @return void + */ + void incCounter_ieee8021AsPortStatRxPdelayResponse( void ) + { + counters.ieee8021AsPortStatRxPdelayResponse++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxPdelayResponseFollowUp + * @return void + */ + void incCounter_ieee8021AsPortStatRxPdelayResponseFollowUp( void ) + { + counters.ieee8021AsPortStatRxPdelayResponseFollowUp++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxAnnounce + * @return void + */ + void incCounter_ieee8021AsPortStatRxAnnounce( void ) + { + counters.ieee8021AsPortStatRxAnnounce++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxPTPPacketDiscard + * @return void + */ + void incCounter_ieee8021AsPortStatRxPTPPacketDiscard( void ) + { + counters.ieee8021AsPortStatRxPTPPacketDiscard++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatRxSyncReceiptTimeouts + * @return void + */ + void incCounter_ieee8021AsPortStatRxSyncReceiptTimeouts( void ) + { + counters.ieee8021AsPortStatRxSyncReceiptTimeouts++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatAnnounceReceiptTimeouts + * @return void + */ + void incCounter_ieee8021AsPortStatAnnounceReceiptTimeouts( void ) + { + counters.ieee8021AsPortStatAnnounceReceiptTimeouts++; + } + + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatPdelayAllowedLostResponsesExceeded + * @return void + */ + // TODO: Not called + void incCounter_ieee8021AsPortStatPdelayAllowedLostResponsesExceeded + ( void ) + { + counters. + ieee8021AsPortStatPdelayAllowedLostResponsesExceeded++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxSyncCount + * @return void + */ + void incCounter_ieee8021AsPortStatTxSyncCount( void ) + { + counters.ieee8021AsPortStatTxSyncCount++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxFollowUpCount + * @return void + */ + void incCounter_ieee8021AsPortStatTxFollowUpCount( void ) + { + counters.ieee8021AsPortStatTxFollowUpCount++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxPdelayRequest + * @return void + */ + void incCounter_ieee8021AsPortStatTxPdelayRequest( void ) + { + counters.ieee8021AsPortStatTxPdelayRequest++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxPdelayResponse + * @return void + */ + void incCounter_ieee8021AsPortStatTxPdelayResponse( void ) + { + counters.ieee8021AsPortStatTxPdelayResponse++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxPdelayResponseFollowUp + * @return void + */ + void incCounter_ieee8021AsPortStatTxPdelayResponseFollowUp( void ) + { + counters.ieee8021AsPortStatTxPdelayResponseFollowUp++; + } + + /** + * @brief Increment IEEE Port counter: + * ieee8021AsPortStatTxAnnounce + * @return void + */ + void incCounter_ieee8021AsPortStatTxAnnounce( void ) + { + counters.ieee8021AsPortStatTxAnnounce++; + } + + /** + * @brief Logs port counters + * @return void + */ + void logIEEEPortCounters( void ) + { + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxSyncCount : %u", + counters.ieee8021AsPortStatRxSyncCount ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxFollowUpCount : %u", + counters.ieee8021AsPortStatRxFollowUpCount ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxPdelayRequest : %u", + counters.ieee8021AsPortStatRxPdelayRequest ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxPdelayResponse : %u", + counters.ieee8021AsPortStatRxPdelayResponse ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxPdelayResponseFollowUp " + ": %u", counters. + ieee8021AsPortStatRxPdelayResponseFollowUp ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxAnnounce : %u", + counters.ieee8021AsPortStatRxAnnounce ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxPTPPacketDiscard : %u", + counters. + ieee8021AsPortStatRxPTPPacketDiscard ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatRxSyncReceiptTimeouts " + ": %u", counters. + ieee8021AsPortStatRxSyncReceiptTimeouts ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatAnnounceReceiptTimeouts " + ": %u", counters. + ieee8021AsPortStatAnnounceReceiptTimeouts ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatPdelayAllowed" + "LostResponsesExceeded : %u", counters. + ieee8021AsPortStatPdelayAllowedLostResponsesExceeded + ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxSyncCount : %u", + counters.ieee8021AsPortStatTxSyncCount ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxFollowUpCount : %u", counters. + ieee8021AsPortStatTxFollowUpCount); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxPdelayRequest : %u", + counters.ieee8021AsPortStatTxPdelayRequest); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxPdelayResponse : %u", counters. + ieee8021AsPortStatTxPdelayResponse); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxPdelayResponseFollowUp : %u", + counters.ieee8021AsPortStatTxPdelayResponseFollowUp + ); + GPTP_LOG_STATUS + ( "IEEE Port Counter " + "ieee8021AsPortStatTxAnnounce : %u", + counters.ieee8021AsPortStatTxAnnounce); + } + + /** + * @brief Get the cross timestamping information. + * The gPTP subsystem uses these samples to calculate + * ratios which can be used to translate or extrapolate + * one clock into another clock reference. The gPTP service + * uses these supplied cross timestamps to perform internal + * rate estimation and conversion functions. + * @param system_time [out] System time + * @param device_time [out] Device time + * @param local_clock [out] Local clock + * @param nominal_clock_rate [out] Nominal clock rate + * @return True in case of success. FALSE in case of error + */ + void getDeviceTime + ( Timestamp &system_time, Timestamp &device_time, + uint32_t &local_clock, uint32_t & nominal_clock_rate ); + + /** + * @brief Sets asCapable flag + * @param ascap flag to be set. If FALSE, marks peer_offset_init as + * false. + * @return void + */ + void setAsCapable(bool ascap) + { + if ( ascap != asCapable ) { + GPTP_LOG_STATUS + ("AsCapable: %s", ascap == true + ? "Enabled" : "Disabled"); + } + if( !ascap ) + { + _peer_offset_init = false; + } + asCapable = ascap; + } + + /** + * @brief Gets the asCapable flag + * @return asCapable flag. + */ + bool getAsCapable() + { + return( asCapable ); + } + + /** + * @brief Gets the Peer rate offset. Used to calculate neighbor + * rate ratio. + * @return FrequencyRatio peer rate offset + */ + FrequencyRatio getPeerRateOffset( void ) + { + return _peer_rate_offset; + } + + /** + * @brief Sets the peer rate offset. Used to calculate neighbor rate + * ratio. + * @param offset Offset to be set + * @return void + */ + void setPeerRateOffset( FrequencyRatio offset ) { + _peer_rate_offset = offset; + } + + /** + * @brief Sets peer offset timestamps + * @param mine Local timestamps + * @param theirs Remote timestamps + * @return void + */ + void setPeerOffset(Timestamp mine, Timestamp theirs) { + _peer_offset_ts_mine = mine; + _peer_offset_ts_theirs = theirs; + _peer_offset_init = true; + } + + /** + * @brief Gets peer offset timestamps + * @param mine [out] Reference to local timestamps + * @param theirs [out] Reference to remote timestamps + * @return TRUE if peer offset has already been initialized. FALSE + * otherwise. + */ + bool getPeerOffset(Timestamp & mine, Timestamp & theirs) { + mine = _peer_offset_ts_mine; + theirs = _peer_offset_ts_theirs; + return _peer_offset_init; + } + + /** + * @brief Sets the neighbor propagation delay threshold + * @param delay Delay in nanoseconds + * @return void + */ + void setNeighPropDelayThresh(int64_t delay) { + neighbor_prop_delay_thresh = delay; + } + + /** + * @brief Restart PDelay + * @return void + */ + void restartPDelay() { + _peer_offset_init = false; + } + + /** + * @brief Gets a pointer to timer_factory object + * @return timer_factory pointer + */ + const OSTimerFactory *getTimerFactory() { + return timer_factory; + } + + /** + * @brief Watch for link up and down events. + * @return Its an infinite loop. Returns NULL in case of error. + */ + void *watchNetLink( void ) + { + // Should never return + net_iface->watchNetLink(this); + + return NULL; + } + + /** + * @brief Receive frame + */ + net_result recv( LinkLayerAddress *addr, uint8_t *payload, + size_t &length, struct phy_delay *delay ) + { + return net_iface->nrecv( addr, payload, length, delay ); + } + + /** + * @brief Send frame + */ + net_result send( LinkLayerAddress *addr, uint16_t etherType, + uint8_t *payload, size_t length, bool timestamp ) + { + return net_iface->send + ( addr, etherType, payload, length, timestamp ); + } + + /** + * @brief Get the payload offset inside a packet + * @return 0 + */ + unsigned getPayloadOffset() + { + return net_iface->getPayloadOffset(); + } + + bool linkWatch( OSThreadFunction func, OSThreadFunctionArg arg ) + { + return link_thread->start( func, arg ); + } + + bool linkOpen( OSThreadFunction func, OSThreadFunctionArg arg ) + { + return listening_thread->start( func, arg ); + } + + /** + * @brief Gets the portState information + * @return PortState + */ + PortState getPortState( void ) { + return port_state; + } + + /** + * @brief Sets the PortState + * @param state value to be set + * @return void + */ + void setPortState( PortState state ) { + port_state = state; + } + + /** + * @brief Gets port identity + * @param identity [out] Reference to PortIdentity + * @return void + */ + void getPortIdentity(PortIdentity & identity) { + identity = this->port_identity; + } + + /** + * @brief Gets the "best" announce + * @return Pointer to PTPMessageAnnounce + */ + PTPMessageAnnounce *calculateERBest( void ); + + /** + * @brief Changes the port state + * @param state Current state + * @param changed_external_master TRUE if external master has + * changed, FALSE otherwise + * @return void + */ + void recommendState(PortState state, bool changed_external_master); + + /** + * @brief Locks the TX port + * @return TRUE if success. FALSE otherwise. + */ + virtual bool getTxLock() + { + return true; + } + + /** + * @brief Unlocks the port TX. + * @return TRUE if success. FALSE otherwise. + */ + virtual bool putTxLock() + { + return false; + } + + /** + * @brief Adds a new qualified announce the port. IEEE 802.1AS + * Clause 10.3.10.2 + * @param annc PTP announce message + * @return void + */ + void setQualifiedAnnounce( PTPMessageAnnounce *annc ) + { + delete qualified_announce; + qualified_announce = annc; + } + + /** + * @brief Switches port to a gPTP master + * @param annc If TRUE, starts announce event timer. + * @return void + */ + virtual void becomeMaster( bool annc ) = 0; + + /** + * @brief Switches port to a gPTP slave. + * @param restart_syntonization if TRUE, restarts the syntonization + * @return void + */ + virtual void becomeSlave( bool restart_syntonization ) = 0; + + /** + * @brief Sets current sync count value. + * @param cnt [in] sync count value + * @return void + */ + void setSyncCount(unsigned int cnt) + { + sync_count = cnt; + } + + /** + * @brief Increments sync count + * @return void + */ + void incSyncCount() { + ++sync_count; + } + + /** + * @brief Gets current sync count value. It is set to zero + * when master and incremented at each sync received for slave. + * @return sync count + */ + unsigned getSyncCount() + { + return sync_count; + } + + /** + * @brief Sets current pdelay count value. + * @param cnt [in] pdelay count value + * @return void + */ + void setPdelayCount(unsigned int cnt) { + pdelay_count = cnt; + } + + /** + * @brief Increments Pdelay count + * @return void + */ + void incPdelayCount() + { + ++pdelay_count; + } + + /** + * @brief Gets current pdelay count value. It is set to zero + * when asCapable is false. + * @return pdelay count + */ + unsigned getPdelayCount() + { + return pdelay_count; + } + + /** + * @brief Increments announce sequence id and returns + * @return Next announce sequence id. + */ + uint16_t getNextAnnounceSequenceId( void ) + { + return announce_sequence_id++; + } + + /** + * @brief Increments signal sequence id and returns + * @return Next signal sequence id. + */ + uint16_t getNextSignalSequenceId( void ) + { + return signal_sequence_id++; + } + + /** + * @brief Increments sync sequence ID and returns + * @return Next synce sequence id. + */ + uint16_t getNextSyncSequenceId( void ) + { + return sync_sequence_id++; + } + + /** + * @brief Gets the lastGmTimeBaseIndicator + * @return uint16 of the lastGmTimeBaseIndicator + */ + uint16_t getLastGmTimeBaseIndicator( void ) { + return lastGmTimeBaseIndicator; + } + + /** + * @brief Sets the lastGmTimeBaseIndicator + * @param gmTimeBaseIndicator from last Follow up message + * @return void + */ + void setLastGmTimeBaseIndicator(uint16_t gmTimeBaseIndicator) + { + lastGmTimeBaseIndicator = gmTimeBaseIndicator; + } + + /** + * @brief Gets the sync interval value + * @return Sync Interval + */ + char getSyncInterval( void ) + { + return log_mean_sync_interval; + } + + /** + * @brief Sets the sync interval value + * @param val time interval + * @return none + */ + void setSyncInterval( char val ) + { + log_mean_sync_interval = val; + } + + /** + * @brief Sets the sync interval back to initial value + * @return none + */ + void resetInitSyncInterval( void ) + { + log_mean_sync_interval = initialLogSyncInterval;; + } + + /** + * @brief Sets the sync interval + * @return none + */ + void setInitSyncInterval( char interval ) + { + initialLogSyncInterval = interval; + } + + /** + * @brief Gets the sync interval + * @return sync interval + */ + char getInitSyncInterval( void ) + { + return initialLogSyncInterval; + } + + /** + * @brief Gets the announce interval + * @return Announce interval + */ + char getAnnounceInterval( void ) { + return log_mean_announce_interval; + } + + /** + * @brief Sets the announce interval + * @param val time interval + * @return none + */ + void setAnnounceInterval(char val) { + log_mean_announce_interval = val; + } + /** + * @brief Start sync receipt timer + * @param waitTime time interval + * @return none + */ + void startSyncReceiptTimer(long long unsigned int waitTime); + + /** + * @brief Stop sync receipt timer + * @return none + */ + void stopSyncReceiptTimer( void ); + + /** + * @brief Start sync interval timer + * @param waitTime time interval in nanoseconds + * @return none + */ + void startSyncIntervalTimer(long long unsigned int waitTime); + + /** + * @brief Start announce interval timer + * @param waitTime time interval + * @return none + */ + void startAnnounceIntervalTimer(long long unsigned int waitTime); + + /** + * @brief Starts announce event timer + * @return void + */ + void startAnnounce(); + + /** + * @brief Process default state change event + * @return true if event is handled without errors + */ + bool processStateChange( Event e ); + + /** + * @brief Default sync/announce timeout handler + * @return true if event is handled without errors + */ + bool processSyncAnnounceTimeout( Event e ); + + + /** + * @brief Perform default event action, can be overridden by media + * specific actions in _processEvent + * @return true if event is handled without errors + */ + bool processEvent( Event e ); + + /** + * @brief Perform media specific event handling action + * @return true if event is handled without errors + */ + virtual bool _processEvent( Event e ) = 0; + + virtual void syncDone() = 0; + + /** + * @brief Sends a general message to a port. No timestamps + * @param buf [in] Pointer to the data buffer + * @param len Size of the message + * @param mcast_type Enumeration + * MulticastType (pdelay, none or other). Depracated. + * @param destIdentity Destination port identity + * @return void + */ + virtual void sendGeneralPort + (uint16_t etherType, uint8_t * buf, int len, MulticastType mcast_type, + PortIdentity * destIdentity) = 0; +}; + +#endif/*COMMON_PORT_HPP*/ diff --git a/daemons/gptp/common/ether_port.cpp b/daemons/gptp/common/ether_port.cpp new file mode 100644 index 00000000..83400285 --- /dev/null +++ b/daemons/gptp/common/ether_port.cpp @@ -0,0 +1,908 @@ +/****************************************************************************** + + 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 <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::openPort( EtherPort *port ) +{ + port_ready_condition->signal(); + struct phy_delay get_delay = { 0, 0, 0, 0 }; + if(port->_hw_timestamper) + port->_hw_timestamper->get_phy_delay(&get_delay); + + while (1) { + PTPMessageCommon *msg; + uint8_t buf[128]; + LinkLayerAddress remote; + net_result rrecv; + size_t length = sizeof(buf); + + if ((rrecv = recv(&remote, buf, length,&get_delay)) + == net_succeed) + { + GPTP_LOG_VERBOSE("Processing network buffer"); + msg = buildPTPMessage((char *)buf, (int)length, &remote, + this); + if (msg != NULL) { + GPTP_LOG_VERBOSE("Processing message"); + msg->processMessage(this); + if (msg->garbage()) { + delete msg; + } + } else { + GPTP_LOG_ERROR("Discarding invalid message"); + } + } 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) +{ + net_result rtx = port_send(etherType, buf, size, mcast_type, destIdentity, true); + if (rtx != net_succeed) { + GPTP_LOG_ERROR("sendEventPort(): failure"); + } + + 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 (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"); + { + int ts_good; + Timestamp req_timestamp; + int iter = TX_TIMEOUT_ITER; + long req = TX_TIMEOUT_BASE; + unsigned req_timestamp_counter_value; + long long wait_time = 0; + + 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"); + + OSTimer *timer = timer_factory->createTimer(); + + ts_good = getTxTimestamp + (pdelay_req, req_timestamp, req_timestamp_counter_value, false); + while (ts_good != GPTP_EC_SUCCESS && iter-- != 0) { + timer->sleep(req); + wait_time += req; + if (ts_good != GPTP_EC_EAGAIN && iter < 1) + GPTP_LOG_ERROR( + "Error (TX) timestamping PDelay request " + "(Retrying-%d), error=%d", iter, ts_good); + ts_good = + getTxTimestamp + (pdelay_req, req_timestamp, + req_timestamp_counter_value, iter == 0); + req *= 2; + } + delete timer; + putTxLock(); + + if (ts_good == GPTP_EC_SUCCESS) { + pdelay_req->setTimestamp(req_timestamp); + GPTP_LOG_DEBUG( + "PDelay Request message, Timestamp %u (sec) %u (ns), seqID %u", + req_timestamp.seconds_ls, req_timestamp.nanoseconds, + pdelay_req->getSequenceId()); + } else { + Timestamp failed = INVALID_TIMESTAMP; + pdelay_req->setTimestamp(failed); + GPTP_LOG_ERROR( "Invalid TX" ); + } + + if (ts_good != GPTP_EC_SUCCESS) { + char msg + [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE]; + getExtendedError(msg); + GPTP_LOG_ERROR( + "Error (TX) timestamping PDelay request, error=%d\t%s", + ts_good, msg); + } + + { + long long timeout; + long long interval; + + timeout = PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER * + ((long long) + (pow((double)2,getPDelayInterval())*1000000000.0)) - + wait_time*1000; + 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, wait_time %lld, timeout %lld", + getPDelayInterval(), wait_time, timeout); + + interval = + ((long long) + (pow((double)2,getPDelayInterval())*1000000000.0)) - + wait_time*1000; + 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; + getPortIdentity(dest_id); + sync->setPortIdentity(&dest_id); + getTxLock(); + 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; + } + } + } + } + } + + int ts_good; + Timestamp sync_timestamp; + unsigned sync_timestamp_counter_value; + int iter = TX_TIMEOUT_ITER; + long req = TX_TIMEOUT_BASE; + + OSTimer *timer = timer_factory->createTimer(); + + ts_good = getTxTimestamp( sync, sync_timestamp, + sync_timestamp_counter_value, + false ); + while (ts_good != GPTP_EC_SUCCESS && iter-- != 0) { + timer->sleep(req); + + if (ts_good != GPTP_EC_EAGAIN && iter < 1) + GPTP_LOG_ERROR( + "Error (TX) timestamping Sync (Retrying), " + "error=%d", ts_good); + ts_good = + getTxTimestamp + (sync, sync_timestamp, + sync_timestamp_counter_value, iter == 0); + req *= 2; + } + delete timer; + putTxLock(); + + if (ts_good != GPTP_EC_SUCCESS) { + char msg [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE]; + getExtendedError(msg); + GPTP_LOG_ERROR( + "Error (TX) timestamping Sync, error=" + "%d\n%s", + ts_good, msg ); + } + + if (ts_good == GPTP_EC_SUCCESS) { + GPTP_LOG_VERBOSE("Successful Sync timestamp"); + GPTP_LOG_VERBOSE("Seconds: %u", + sync_timestamp.seconds_ls); + GPTP_LOG_VERBOSE("Nanoseconds: %u", + sync_timestamp.nanoseconds); + } else { + GPTP_LOG_ERROR + ("*** Unsuccessful Sync timestamp"); + } + + PTPMessageFollowUp *follow_up; + if (ts_good == GPTP_EC_SUCCESS) { + + 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 { + } + 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 ) +{ + if (_hw_timestamper) { + return _hw_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 ) +{ + if (_hw_timestamper) { + return _hw_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(); + } +} diff --git a/daemons/gptp/common/ether_port.hpp b/daemons/gptp/common/ether_port.hpp new file mode 100644 index 00000000..6028ca75 --- /dev/null +++ b/daemons/gptp/common/ether_port.hpp @@ -0,0 +1,624 @@ +/****************************************************************************** + + 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. + +******************************************************************************/ + +#ifndef ETHER_PORT_HPP +#define ETHER_PORT_HPP + +#include <ieee1588.hpp> +#include <avbap_message.hpp> + +#include <avbts_ostimer.hpp> +#include <avbts_oslock.hpp> +#include <avbts_osnet.hpp> +#include <avbts_osthread.hpp> +#include <avbts_oscondition.hpp> +#include <ipcdef.hpp> +#include <gptp_log.hpp> + +#include <stdint.h> + +#include <map> +#include <list> + +#include <common_port.hpp> + +/**@file*/ + +#define GPTP_MULTICAST 0x0180C200000EULL /*!< GPTP multicast adddress */ +#define PDELAY_MULTICAST GPTP_MULTICAST /*!< PDELAY Multicast value */ +#define OTHER_MULTICAST GPTP_MULTICAST /*!< OTHER multicast value */ +#define TEST_STATUS_MULTICAST 0x011BC50AC000ULL /*!< AVnu Automotive profile test status msg Multicast value */ + +#define PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< PDelay timeout multiplier*/ +#define SYNC_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< Sync receipt timeout multiplier*/ +#define ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER 3 /*!< Announce receipt timeout multiplier*/ + +#define LOG2_INTERVAL_INVALID -127 /* Simple out of range Log base 2 value used for Sync and PDelay msg internvals */ + +/** + * @brief PortType enumeration. Selects between delay request-response (E2E) mechanism + * or PTPV1 or PTPV2 P2P (peer delay) mechanism. + */ +typedef enum { + V1, + V2_E2E, + V2_P2P +} PortType; + +/** + * @brief Provides a map for the identityMap member of EtherPort + * class + */ +typedef std::map < PortIdentity, LinkLayerAddress > IdentityMap_t; + + +/** + * @brief Ethernet specific port functions + */ +class EtherPort : public CommonPort +{ + static LinkLayerAddress other_multicast; + static LinkLayerAddress pdelay_multicast; + static LinkLayerAddress test_status_multicast; + + /* Port Status */ + // set to 0 when asCapable is false, increment for each pdelay recvd + bool linkUp; + + /* Port Configuration */ + char log_mean_unicast_sync_interval; + char log_min_mean_delay_req_interval; + char log_min_mean_pdelay_req_interval; + + unsigned int duplicate_resp_counter; + uint16_t last_invalid_seqid; + + /* Automotive Profile : Static variables */ + // port_state : already defined as port_state + bool isGM; + // asCapable : already defined as asCapable + char operLogPdelayReqInterval; + char operLogSyncInterval; + char initialLogPdelayReqInterval; + bool automotive_profile; + + // Test Status variables + uint32_t linkUpCount; + uint32_t linkDownCount; + StationState_t stationState; + + + /* Automotive Profile : Persistant variables */ + // neighborPropDelay : defined as one_way_delay ?? + // rateRatio : Optional and didn't fine this variable. Will proceed without writing it. + // neighborRateRatio : defined as _peer_rate_offset ?? + + // Automotive Profile AVB SYNC state indicator. > 0 will inditate valid AVB SYNC state + uint32_t avbSyncState; + + uint16_t pdelay_sequence_id; + PTPMessagePathDelayReq *last_pdelay_req; + PTPMessagePathDelayResp *last_pdelay_resp; + PTPMessagePathDelayRespFollowUp *last_pdelay_resp_fwup; + + IdentityMap_t identity_map; + + PTPMessageSync *last_sync; + + OSCondition *port_ready_condition; + + OSLock *pdelay_rx_lock; + OSLock *port_tx_lock; + + OSLock *pDelayIntervalTimerLock; + + net_result port_send + (uint16_t etherType, uint8_t * buf, int size, MulticastType mcast_type, + PortIdentity * destIdentity, bool timestamp); + + bool pdelay_started; + bool pdelay_halted; + bool sync_rate_interval_timer_started; + +protected: + static const unsigned int DUPLICATE_RESP_THRESH = 3; + + public: + void becomeMaster( bool annc ); + void becomeSlave( bool restart_syntonization ); + + /** + * @brief Starts pDelay event timer. + * @return void + */ + void startPDelay(); + + /** + * @brief Stops PDelay event timer + * @return void + */ + void stopPDelay(); + + /** + * @brief Enable/Disable PDelay Request messages + * @param hlt True to HALT (stop sending), False to resume (start sending). + */ + void haltPdelay(bool hlt) + { + pdelay_halted = hlt; + } + + /** + * @brief Get the status of pdelayHalted condition. + * @return True PdelayRequest halted. False when PDelay Request is running + */ + bool pdelayHalted(void) + { + return pdelay_halted; + } + + /** + * @brief Starts Sync Rate Interval event timer. Used for the + * Automotive Profile. + * @return void + */ + void startSyncRateIntervalTimer(); + + /** + * @brief Starts pDelay event timer if not yet started. + * @return void + */ + void syncDone(); + + /** + * @brief Gets the AVnu automotive profile flag + * @return automotive_profile flag + */ + bool getAutomotiveProfile() { return( automotive_profile ); } + + /** + * @brief Destroys a EtherPort + */ + ~EtherPort(); + + /** + * @brief Creates the EtherPort interface. + * @param init PortInit initialization parameters + */ + EtherPort( PortInit_t *portInit ); + + /** + * @brief Initializes the port. Creates network interface, initializes + * hardware timestamper and create OS locks conditions + * @return FALSE if error during building the interface. TRUE if success + */ + bool _init_port( void ); + + /** + * @brief Currently doesnt do anything. Just returns. + * @return void + */ + void recoverPort(void); + + /** + * @brief Receives messages from the network interface + * @return Its an infinite loop. Returns NULL in case of error. + */ + void *openPort( EtherPort *port ); + + /** + * @brief Sends and event to a IEEE1588 port. It includes timestamp + * @param buf [in] Pointer to the data buffer + * @param len Size of the message + * @param mcast_type Enumeration MulticastType (pdlay, none or other). Depracated. + * @param destIdentity Destination port identity + * @return void + */ + void sendEventPort + (uint16_t etherType, uint8_t * buf, int len, MulticastType mcast_type, + PortIdentity * destIdentity); + + /** + * @brief Sends a general message to a port. No timestamps + * @param buf [in] Pointer to the data buffer + * @param len Size of the message + * @param mcast_type Enumeration MulticastType (pdelay, none or other). Depracated. + * @param destIdentity Destination port identity + * @return void + */ + void sendGeneralPort + (uint16_t etherType, uint8_t * buf, int len, MulticastType mcast_type, + PortIdentity * destIdentity); + + /** + * @brief Process all events for a EtherPort + * @param e Event to be processed + * @return true if event is handled, false otherwise + */ + bool _processEvent(Event e); + + /** + * @brief Adds a foreign master. + * @param msg [in] PTP announce message + * @return void + * @todo Currently not implemented + */ + void addForeignMaster(PTPMessageAnnounce * msg); + + /** + * @brief Remove a foreign master. + * @param msg [in] PTP announce message + * @return void + * @todo Currently not implemented + */ + void removeForeignMaster(PTPMessageAnnounce * msg); + + /** + * @brief Remove all foreign masters. + * @return void + * @todo Currently not implemented + */ + void removeForeignMasterAll(void); + + /** + * @brief Gets the pDelay minimum interval + * @return PDelay interval + */ + char getPDelayInterval(void) { + return log_min_mean_pdelay_req_interval; + } + + /** + * @brief Sets the pDelay minimum interval + * @param val time interval + * @return none + */ + void setPDelayInterval(char val) { + log_min_mean_pdelay_req_interval = val; + } + + /** + * @brief Sets the pDelay minimum interval back to initial + * value + * @return none */ + void setInitPDelayInterval(void) { + log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; + } + + /** + * @brief Start pDelay interval timer + * @param waitTime time interval + * @return none + */ + void startPDelayIntervalTimer(long long unsigned int waitTime); + + /** + * @brief Increments PDelay sequence ID and returns. + * @return Next PDelay sequence id. + */ + uint16_t getNextPDelaySequenceId(void) { + return pdelay_sequence_id++; + } + + /** + * @brief Gets last sync sequence number from parent + * @return Parent last sync sequence number + * @todo Not currently implemented. + */ + uint16_t getParentLastSyncSequenceNumber(void); + + /** + * @brief Sets last sync sequence number from parent + * @param num Sequence number + * @return void + * @todo Currently not implemented. + */ + void setParentLastSyncSequenceNumber(uint16_t num); + + /** + * @brief Sets last sync ptp message + * @param msg [in] PTP sync message + * @return void + */ + void setLastSync(PTPMessageSync * msg) { + last_sync = msg; + } + + /** + * @brief Gets last sync message + * @return PTPMessageSync last sync + */ + PTPMessageSync *getLastSync(void) { + return last_sync; + } + + /** + * @brief Locks PDelay RX + * @return TRUE if acquired the lock. FALSE otherwise + */ + bool getPDelayRxLock() { + return pdelay_rx_lock->lock() == oslock_ok ? true : false; + } + + /** + * @brief Do a trylock on the PDelay RX + * @return TRUE if acquired the lock. FALSE otherwise. + */ + bool tryPDelayRxLock() { + return pdelay_rx_lock->trylock() == oslock_ok ? true : false; + } + + /** + * @brief Unlocks PDelay RX. + * @return TRUE if success. FALSE otherwise + */ + bool putPDelayRxLock() { + return pdelay_rx_lock->unlock() == oslock_ok ? true : false; + } + + bool getTxLock() { + return port_tx_lock->lock() == oslock_ok ? true : false; + } + + bool putTxLock() { + return port_tx_lock->unlock() == oslock_ok ? true : false; + } + + /** + * @brief Sets the last_pdelay_req message + * @param msg [in] PTPMessagePathDelayReq message to set + * @return void + */ + void setLastPDelayReq(PTPMessagePathDelayReq * msg) { + last_pdelay_req = msg; + } + + /** + * @brief Gets the last PTPMessagePathDelayReq message + * @return Last pdelay request + */ + PTPMessagePathDelayReq *getLastPDelayReq(void) { + return last_pdelay_req; + } + + /** + * @brief Sets the last PTPMessagePathDelayResp message + * @param msg [in] Last pdelay response + * @return void + */ + void setLastPDelayResp(PTPMessagePathDelayResp * msg) { + last_pdelay_resp = msg; + } + + /** + * @brief Gets the last PTPMessagePathDelayResp message + * @return Last pdelay response + */ + PTPMessagePathDelayResp *getLastPDelayResp(void) { + return last_pdelay_resp; + } + + /** + * @brief Sets the last PTPMessagePathDelayRespFollowUp message + * @param msg [in] last pdelay response follow up + * @return void + */ + void setLastPDelayRespFollowUp(PTPMessagePathDelayRespFollowUp * msg) { + last_pdelay_resp_fwup = msg; + } + + /** + * @brief Gets the last PTPMessagePathDelayRespFollowUp message + * @return last pdelay response follow up + */ + PTPMessagePathDelayRespFollowUp *getLastPDelayRespFollowUp(void) { + return last_pdelay_resp_fwup; + } + + /** + * @brief Gets RX timestamp based on port identity + * @param sourcePortIdentity [in] Source port identity + * @param sequenceId Sequence ID + * @param timestamp [out] RX timestamp + * @param counter_value [out] timestamp count value + * @param last If true, removes the rx lock. + * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. + */ + int getRxTimestamp + (PortIdentity * sourcePortIdentity, PTPMessageId messageId, + Timestamp & timestamp, unsigned &counter_value, bool last); + + /** + * @brief Gets TX timestamp based on port identity + * @param sourcePortIdentity [in] Source port identity + * @param sequenceId Sequence ID + * @param timestamp [out] TX timestamp + * @param counter_value [out] timestamp count value + * @param last If true, removes the TX lock + * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. + */ + int getTxTimestamp + (PortIdentity * sourcePortIdentity, PTPMessageId messageId, + Timestamp & timestamp, unsigned &counter_value, bool last); + + /** + * @brief Gets TX timestamp based on PTP message + * @param msg PTPMessageCommon message + * @param timestamp [out] TX timestamp + * @param counter_value [out] timestamp count value + * @param last If true, removes the TX lock + * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. + */ + int getTxTimestamp + (PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, + bool last); + + /** + * @brief Gets RX timestamp based on PTP message + * @param msg PTPMessageCommon message + * @param timestamp [out] RX timestamp + * @param counter_value [out] timestamp count value + * @param last If true, removes the RX lock + * @return GPTP_EC_SUCCESS if no error, GPTP_EC_FAILURE if error and GPTP_EC_EAGAIN to try again. + */ + int getRxTimestamp + (PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, + bool last); + + /** + * @brief Sets the value of last duplicated SeqID + * @param seqid Value to set + * @return void + */ + void setLastInvalidSeqID(uint16_t seqid) + { + last_invalid_seqid = seqid; + } + + /** + * @brief Get the value of last invalid seqID + * @return Last invalid seq id + */ + uint16_t getLastInvalidSeqID(void) + { + return last_invalid_seqid; + } + + /** + * @brief Sets the duplicate pdelay_resp counter. + * @param cnt Value to be set + */ + void setDuplicateRespCounter(unsigned int cnt) + { + duplicate_resp_counter = cnt; + } + + /** + * @brief Gets the current value of pdelay_resp duplicate messages counter + * @return Counter value + */ + unsigned int getDuplicateRespCounter(void) + { + return duplicate_resp_counter; + } + + /** + * @brief Increment the duplicate PDelayResp message counter + * @return True if it equals the threshold, False otherwise + */ + bool incrementDuplicateRespCounter(void) + { + return ++duplicate_resp_counter == DUPLICATE_RESP_THRESH; + } + + /** + * @brief Maps socket addr to the remote link layer address + * @param destIdentity [in] PortIdentity remote + * @param remote [in] remote link layer address + * @return void + */ + void mapSocketAddr + (PortIdentity * destIdentity, LinkLayerAddress * remote); + + /** + * @brief Adds New sock addr map + * @param destIdentity [in] PortIdentity remote + * @param remote [in] remote link layer address + * @return void + */ + void addSockAddrMap + (PortIdentity * destIdentity, LinkLayerAddress * remote); + + /** + * @brief Gets link up count + * @return Link up count + */ + uint32_t getLinkUpCount() { + return linkUpCount; + } + + /** + * @brief Gets link down count + * @return Link down count + */ + uint32_t getLinkDownCount() { + return linkDownCount; + } + + /** + * @brief Sets the Station State for the Test Status message + * @param StationState_t [in] The station state + * @return none + */ + void setStationState(StationState_t _stationState) { + stationState = _stationState; + if (stationState == STATION_STATE_ETHERNET_READY) { + GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_ETHERNET_READY"); + } + else if (stationState == STATION_STATE_AVB_SYNC) { + GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_AVB_SYNC"); + } + else if (stationState == STATION_STATE_AVB_MEDIA_READY) { + GPTP_LOG_STATUS("AVnu AP Status : STATION_STATE_AVB_MEDIA_READY"); + } + } + + /** + * @brief Gets the Station State for the Test Status + * message + * @return station state + */ + StationState_t getStationState() { + return stationState; + } + + + /** + * @brief Sets the linkUp status + * @param bool of the linkUp status + * @return void + */ + void setLinkUpState(bool state) { + linkUp = state; + } + + /** + * @brief Gets the linkUp status + * @return bool of the linkUp status + */ + bool getLinkUpState(void) { + return linkUp; + } +}; + +#endif/*ETHER_PORT_HPP*/ diff --git a/daemons/gptp/common/ieee1588.hpp b/daemons/gptp/common/ieee1588.hpp index 3d89a158..80242f6b 100644 --- a/daemons/gptp/common/ieee1588.hpp +++ b/daemons/gptp/common/ieee1588.hpp @@ -49,7 +49,8 @@ #include <gptp_log.hpp> -#define MAX_PORTS 32 /*!< Maximum number of IEEE1588Port instances */ +#define MAX_PORTS 32 /*!< Maximum number of EtherPort + * instances */ #define PTP_CLOCK_IDENTITY_LENGTH 8 /*!< Size of a clock identifier stored in the ClockIndentity class, described at IEEE 802.1AS Clause 8.5.2.4*/ @@ -72,7 +73,8 @@ class PTPMessageAnnounce; class PTPMessagePathDelayReq; class PTPMessagePathDelayResp; class PTPMessagePathDelayRespFollowUp; -class IEEE1588Port; +class EtherPort; +class CommonPort; class IEEE1588Clock; class OSNetworkInterface; @@ -105,7 +107,7 @@ typedef enum { * @brief Defines an event descriptor type */ typedef struct { - IEEE1588Port *port; //!< IEEE 1588 Port + CommonPort *port; //!< Media Dependent Ether Port Event event; //!< Event enumeration } event_descriptor_t; @@ -499,7 +501,8 @@ public: * @param frequency_offset Frequency offset * @return false */ - virtual bool HWTimestamper_adjclockrate( float frequency_offset ) + virtual bool HWTimestamper_adjclockrate + ( float frequency_offset ) const { return false; } /** @@ -526,7 +529,7 @@ public: virtual bool HWTimestamper_gettime(Timestamp * system_time, Timestamp * device_time, uint32_t * local_clock, - uint32_t * nominal_clock_rate) = 0; + uint32_t * nominal_clock_rate) const = 0; /** * @brief Gets the tx timestamp from hardware @@ -580,7 +583,8 @@ public: * @return void * @todo There is no current implementation for this method. */ - virtual void HWTimestamper_get_extderror(char *msg) { + virtual void HWTimestamper_get_extderror(char *msg) const + { *msg = '\0'; } @@ -600,7 +604,8 @@ public: * @brief Gets the HWTimestamper version * @return version (signed integer) */ - int getVersion() { + int getVersion() const + { return version; } /** @@ -626,7 +631,7 @@ public: * @return 0 **/ - int get_phy_delay (struct phy_delay *get_delay) + int get_phy_delay (struct phy_delay *get_delay) const { get_delay->mb_tx_phy_delay = delay.mb_tx_phy_delay; get_delay->mb_rx_phy_delay = delay.mb_rx_phy_delay; @@ -671,8 +676,8 @@ public: * @param port [in] IEEE1588 port * @return PTP message instance of PTPMessageCommon */ -PTPMessageCommon *buildPTPMessage(char *buf, int size, - LinkLayerAddress * remote, - IEEE1588Port * port); +PTPMessageCommon *buildPTPMessage +( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ); #endif diff --git a/daemons/gptp/common/ieee1588clock.cpp b/daemons/gptp/common/ieee1588clock.cpp index ac9b1aea..aae42dd1 100644 --- a/daemons/gptp/common/ieee1588clock.cpp +++ b/daemons/gptp/common/ieee1588clock.cpp @@ -233,7 +233,7 @@ void timerq_handler(void *arg) } void IEEE1588Clock::addEventTimer -( IEEE1588Port * target, Event e, unsigned long long time_ns ) +( CommonPort *target, Event e, unsigned long long time_ns ) { event_descriptor_t *event_descriptor = new event_descriptor_t(); event_descriptor->event = e; @@ -244,7 +244,7 @@ void IEEE1588Clock::addEventTimer } void IEEE1588Clock::addEventTimerLocked -( IEEE1588Port * target, Event e, unsigned long long time_ns ) +( CommonPort *target, Event e, unsigned long long time_ns ) { if( getTimerQLock() == oslock_fail ) return; addEventTimer( target, e, time_ns ); @@ -253,12 +253,14 @@ void IEEE1588Clock::addEventTimerLocked -void IEEE1588Clock::deleteEventTimer(IEEE1588Port * target, Event event) +void IEEE1588Clock::deleteEventTimer +( CommonPort *target, Event event ) { timerq->cancelEvent((int)event, NULL); } -void IEEE1588Clock::deleteEventTimerLocked(IEEE1588Port * target, Event event) +void IEEE1588Clock::deleteEventTimerLocked +( CommonPort *target, Event event ) { if( getTimerQLock() == oslock_fail ) return; @@ -336,10 +338,11 @@ FrequencyRatio IEEE1588Clock::calcMasterLocalClockRateDifference( Timestamp mast } void IEEE1588Clock::setMasterOffset -( IEEE1588Port * port, int64_t master_local_offset, Timestamp local_time, - FrequencyRatio master_local_freq_offset, int64_t local_system_offset, - Timestamp system_time, FrequencyRatio local_system_freq_offset, - unsigned sync_count, unsigned pdelay_count, PortState port_state, bool asCapable ) +( CommonPort *port, int64_t master_local_offset, + Timestamp local_time, FrequencyRatio master_local_freq_offset, + int64_t local_system_offset, Timestamp system_time, + FrequencyRatio local_system_freq_offset, unsigned sync_count, + unsigned pdelay_count, PortState port_state, bool asCapable ) { _master_local_freq_offset = master_local_freq_offset; _local_system_freq_offset = local_system_freq_offset; diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp deleted file mode 100644 index 441ebbd6..00000000 --- a/daemons/gptp/common/ieee1588port.cpp +++ /dev/null @@ -1,1422 +0,0 @@ -/****************************************************************************** - - 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 <avbts_port.hpp> -#include <avbts_message.hpp> -#include <avbts_clock.hpp> - -#include <avbts_oslock.hpp> -#include <avbts_osnet.hpp> -#include <avbts_oscondition.hpp> - -#include <gptp_log.hpp> - -#include <stdio.h> - -#include <math.h> - -#include <stdlib.h> - -LinkLayerAddress IEEE1588Port::other_multicast(OTHER_MULTICAST); -LinkLayerAddress IEEE1588Port::pdelay_multicast(PDELAY_MULTICAST); -LinkLayerAddress IEEE1588Port::test_status_multicast(TEST_STATUS_MULTICAST); - -OSThreadExitCode watchNetLinkWrapper(void *arg) -{ - IEEE1588Port *port; - - port = (IEEE1588Port *) arg; - if (port->watchNetLink() == NULL) - return osthread_ok; - else - return osthread_error; -} - -OSThreadExitCode openPortWrapper(void *arg) -{ - IEEE1588Port *port; - - port = (IEEE1588Port *) arg; - if (port->openPort(port) == NULL) - return osthread_ok; - else - return osthread_error; -} - -IEEE1588Port::~IEEE1588Port() -{ - delete port_ready_condition; - delete [] rate_offset_array; - if( qualified_announce != NULL ) delete qualified_announce; -} - -IEEE1588Port::IEEE1588Port(IEEE1588PortInit_t *portInit) -{ - sync_sequence_id = 0; - - clock = portInit->clock; - ifindex = portInit->index; - clock->registerPort(this, ifindex); - - forceSlave = portInit->forceSlave; - port_state = PTP_INITIALIZING; - - automotive_profile = portInit->automotive_profile; - isGM = portInit->isGM; - testMode = portInit->testMode; - linkUp = portInit->linkUp; - initialLogSyncInterval = portInit->initialLogSyncInterval; - initialLogPdelayReqInterval = portInit->initialLogPdelayReqInterval; - operLogPdelayReqInterval = portInit->operLogPdelayReqInterval; - operLogSyncInterval = portInit->operLogSyncInterval; - - if (automotive_profile) { - asCapable = true; - - if (initialLogSyncInterval == LOG2_INTERVAL_INVALID) - initialLogSyncInterval = -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 { - asCapable = false; - - if (initialLogSyncInterval == LOG2_INTERVAL_INVALID) - initialLogSyncInterval = -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 - } - - announce_sequence_id = 0; - signal_sequence_id = 0; - sync_sequence_id = 0; - pdelay_sequence_id = 0; - - pdelay_started = false; - pdelay_halted = false; - sync_rate_interval_timer_started = false; - - duplicate_resp_counter = 0; - last_invalid_seqid = 0; - - /*TODO: Add intervals below to a config interface*/ - log_mean_sync_interval = initialLogSyncInterval; - log_mean_announce_interval = 0; - log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; - - _current_clock_offset = _initial_clock_offset = portInit->offset; - - rate_offset_array = NULL; - - _hw_timestamper = portInit->timestamper; - - one_way_delay = ONE_WAY_DELAY_DEFAULT; - neighbor_prop_delay_thresh = NEIGHBOR_PROP_DELAY_THRESH; - sync_receipt_thresh = DEFAULT_SYNC_RECEIPT_THRESH; - wrongSeqIDCounter = 0; - - _peer_rate_offset = 1.0; - - last_sync = NULL; - last_pdelay_req = NULL; - last_pdelay_resp = NULL; - last_pdelay_resp_fwup = NULL; - - qualified_announce = NULL; - - this->net_label = portInit->net_label; - - this->timer_factory = portInit->timer_factory; - this->thread_factory = portInit->thread_factory; - - this->condition_factory = portInit->condition_factory; - this->lock_factory = portInit->lock_factory; - - setPdelayCount(0); - setSyncCount(0); - memset(link_delay, 0, sizeof(link_delay)); - - _peer_offset_init = false; - - if (automotive_profile) { - if (isGM) { - avbSyncState = 1; - } - else { - avbSyncState = 2; - } - if (testMode) { - 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); - } -} - -void IEEE1588Port::timestamper_init(void) -{ - if( _hw_timestamper != NULL ) { - _hw_timestamper->init_phy_delay(this->link_delay); - if( !_hw_timestamper->HWTimestamper_init( net_label, net_iface )) { - GPTP_LOG_ERROR - ( "Failed to initialize hardware timestamper, " - "falling back to software timestamping" ); - _hw_timestamper = NULL; - return; - } - } -} - -void IEEE1588Port::timestamper_reset(void) -{ - if( _hw_timestamper != NULL ) { - _hw_timestamper->init_phy_delay(this->link_delay); - _hw_timestamper->HWTimestamper_reset(); - } -} - -bool IEEE1588Port::init_port(int delay[4]) -{ - if (!OSNetworkInterfaceFactory::buildInterface - (&net_iface, factory_name_t("default"), net_label, _hw_timestamper)) - return false; - - this->net_iface = net_iface; - this->net_iface->getLinkLayerAddress(&local_addr); - clock->setClockIdentity(&local_addr); - memcpy(this->link_delay, delay, sizeof(this->link_delay)); - - this->timestamper_init(); - - pdelay_rx_lock = lock_factory->createLock(oslock_recursive); - port_tx_lock = lock_factory->createLock(oslock_recursive); - - syncReceiptTimerLock = lock_factory->createLock(oslock_recursive); - syncIntervalTimerLock = lock_factory->createLock(oslock_recursive); - announceIntervalTimerLock = lock_factory->createLock(oslock_recursive); - pDelayIntervalTimerLock = lock_factory->createLock(oslock_recursive); - - port_identity.setClockIdentity(clock->getClockIdentity()); - port_identity.setPortNumber(&ifindex); - - port_ready_condition = condition_factory->createCondition(); - - return true; -} - -void IEEE1588Port::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 IEEE1588Port::stopPDelay() { - haltPdelay(true); - pdelay_started = false; - clock->deleteEventTimerLocked( this, PDELAY_INTERVAL_TIMEOUT_EXPIRES); -} - -void IEEE1588Port::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 IEEE1588Port::startAnnounce() { - if (!automotive_profile) { - startAnnounceIntervalTimer(16000000); - } -} - -bool IEEE1588Port::serializeState( void *buf, off_t *count ) { - bool ret = true; - - if( buf == NULL ) { - *count = sizeof(port_state)+sizeof(_peer_rate_offset)+ - sizeof(asCapable)+sizeof(one_way_delay); - return true; - } - - if( port_state != PTP_MASTER && port_state != PTP_SLAVE ) { - *count = 0; - ret = false; - goto bail; - } - - /* asCapable */ - if( ret && *count >= (off_t) sizeof( asCapable )) { - memcpy( buf, &asCapable, sizeof( asCapable )); - *count -= sizeof( asCapable ); - buf = ((char *)buf) + sizeof( asCapable ); - } else if( ret == false ) { - *count += sizeof( asCapable ); - } else { - *count = sizeof( asCapable )-*count; - ret = false; - } - - /* Port State */ - if( ret && *count >= (off_t) sizeof( port_state )) { - memcpy( buf, &port_state, sizeof( port_state )); - *count -= sizeof( port_state ); - buf = ((char *)buf) + sizeof( port_state ); - } else if( ret == false ) { - *count += sizeof( port_state ); - } else { - *count = sizeof( port_state )-*count; - ret = false; - } - - /* Link Delay */ - if( ret && *count >= (off_t) sizeof( one_way_delay )) { - memcpy( buf, &one_way_delay, sizeof( one_way_delay )); - *count -= sizeof( one_way_delay ); - buf = ((char *)buf) + sizeof( one_way_delay ); - } else if( ret == false ) { - *count += sizeof( one_way_delay ); - } else { - *count = sizeof( one_way_delay )-*count; - ret = false; - } - - /* Neighbor Rate Ratio */ - if( ret && *count >= (off_t) sizeof( _peer_rate_offset )) { - memcpy( buf, &_peer_rate_offset, sizeof( _peer_rate_offset )); - *count -= sizeof( _peer_rate_offset ); - buf = ((char *)buf) + sizeof( _peer_rate_offset ); - } else if( ret == false ) { - *count += sizeof( _peer_rate_offset ); - } else { - *count = sizeof( _peer_rate_offset )-*count; - ret = false; - } - - bail: - return ret; -} - -bool IEEE1588Port::restoreSerializedState( void *buf, off_t *count ) { - bool ret = true; - - /* asCapable */ - if( ret && *count >= (off_t) sizeof( asCapable )) { - memcpy( &asCapable, buf, sizeof( asCapable )); - *count -= sizeof( asCapable ); - buf = ((char *)buf) + sizeof( asCapable ); - } else if( ret == false ) { - *count += sizeof( asCapable ); - } else { - *count = sizeof( asCapable )-*count; - ret = false; - } - - /* Port State */ - if( ret && *count >= (off_t) sizeof( port_state )) { - memcpy( &port_state, buf, sizeof( port_state )); - *count -= sizeof( port_state ); - buf = ((char *)buf) + sizeof( port_state ); - } else if( ret == false ) { - *count += sizeof( port_state ); - } else { - *count = sizeof( port_state )-*count; - ret = false; - } - - /* Link Delay */ - if( ret && *count >= (off_t) sizeof( one_way_delay )) { - memcpy( &one_way_delay, buf, sizeof( one_way_delay )); - *count -= sizeof( one_way_delay ); - buf = ((char *)buf) + sizeof( one_way_delay ); - } else if( ret == false ) { - *count += sizeof( one_way_delay ); - } else { - *count = sizeof( one_way_delay )-*count; - ret = false; - } - - /* Neighbor Rate Ratio */ - if( ret && *count >= (off_t) sizeof( _peer_rate_offset )) { - memcpy( &_peer_rate_offset, buf, sizeof( _peer_rate_offset )); - *count -= sizeof( _peer_rate_offset ); - buf = ((char *)buf) + sizeof( _peer_rate_offset ); - } else if( ret == false ) { - *count += sizeof( _peer_rate_offset ); - } else { - *count = sizeof( _peer_rate_offset )-*count; - ret = false; - } - - return ret; -} - -void *IEEE1588Port::watchNetLink(void) -{ - // Should never return - net_iface->watchNetLink(this); - - return NULL; -} - -void *IEEE1588Port::openPort(IEEE1588Port *port) -{ - port_ready_condition->signal(); - struct phy_delay get_delay = { 0, 0, 0, 0 }; - if(port->_hw_timestamper) - port->_hw_timestamper->get_phy_delay(&get_delay); - - while (1) { - PTPMessageCommon *msg; - uint8_t buf[128]; - LinkLayerAddress remote; - net_result rrecv; - size_t length = sizeof(buf); - - if ((rrecv = net_iface->nrecv(&remote, buf, length,&get_delay)) == net_succeed) { - GPTP_LOG_VERBOSE("Processing network buffer"); - msg = buildPTPMessage((char *)buf, (int)length, &remote, - this); - if (msg != NULL) { - GPTP_LOG_VERBOSE("Processing message"); - msg->processMessage(this); - if (msg->garbage()) { - delete msg; - } - } else { - GPTP_LOG_ERROR("Discarding invalid message"); - } - } else if (rrecv == net_fatal) { - GPTP_LOG_ERROR("read from network interface failed"); - this->processEvent(FAULT_DETECTED); - break; - } - } - - return NULL; -} - -net_result IEEE1588Port::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 net_iface->send(&dest, etherType, (uint8_t *) buf, size, timestamp); -} - -unsigned IEEE1588Port::getPayloadOffset() -{ - return net_iface->getPayloadOffset(); -} - -void IEEE1588Port::sendEventPort(uint16_t etherType, uint8_t * buf, int size, - MulticastType mcast_type, - PortIdentity * destIdentity) -{ - net_result rtx = port_send(etherType, buf, size, mcast_type, destIdentity, true); - if (rtx != net_succeed) { - GPTP_LOG_ERROR("sendEventPort(): failure"); - } - - return; -} - -void IEEE1588Port::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; -} - -void IEEE1588Port::processEvent(Event e) -{ - bool changed_external_master; - - switch (e) { - case POWERUP: - case INITIALIZE: - GPTP_LOG_DEBUG("Received POWERUP/INITIALIZE event"); - - { - unsigned long long interval3; - unsigned long long interval4; - Event e3 = NULL_EVENT; - Event e4 = NULL_EVENT; - - if (!automotive_profile) { - if (port_state != PTP_SLAVE && port_state != PTP_MASTER) { - GPTP_LOG_STATUS("Starting PDelay"); - startPDelay(); - } - } - else { - startPDelay(); - } - - if( clock->getPriority1() == 255 || port_state == PTP_SLAVE ) { - becomeSlave( true ); - } else if( port_state == PTP_MASTER ) { - becomeMaster( true ); - } else { - /*TODO: Should I remove the commented code below ?*/ - //e3 = SYNC_RECEIPT_TIMEOUT_EXPIRES; - e4 = ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; - interval3 = (unsigned long long) - (SYNC_RECEIPT_TIMEOUT_MULTIPLIER* - pow((double)2,getSyncInterval())*1000000000.0); - interval4 = (unsigned long long) - (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER* - pow((double)2,getAnnounceInterval())*1000000000.0); - } - - port_ready_condition->wait_prelock(); - - link_thread = thread_factory->createThread(); - if(!link_thread->start(watchNetLinkWrapper, (void *)this)) - { - GPTP_LOG_ERROR("Error creating port link thread"); - return; - } - - listening_thread = thread_factory->createThread(); - if (!listening_thread-> - start (openPortWrapper, (void *)this)) - { - GPTP_LOG_ERROR("Error creating port thread"); - return; - } - port_ready_condition->wait(); - - if (e3 != NULL_EVENT) - clock->addEventTimerLocked(this, e3, interval3); - if (e4 != NULL_EVENT) - clock->addEventTimerLocked(this, e4, interval4); - } - - if (automotive_profile) { - setStationState(STATION_STATE_ETHERNET_READY); - if (testMode) { - 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, log_mean_sync_interval, PTPMessageSignalling::sigMsgInterval_NoSend); - sigMsg->sendPort(this, NULL); - delete sigMsg; - } - - startSyncReceiptTimer((unsigned long long) - (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * - ((double) pow((double)2, getSyncInterval()) * - 1000000000.0))); - } - } - - break; - - case STATE_CHANGE_EVENT: - if (!automotive_profile) { // BMCA is not active with Automotive Profile - if ( clock->getPriority1() != 255 ) { - int number_ports, j; - PTPMessageAnnounce *EBest = NULL; - char EBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; - - IEEE1588Port **ports; - clock->getPortList(number_ports, ports); - - /* Find EBest for all ports */ - j = 0; - for (int i = 0; i < number_ports; ++i) { - while (ports[j] == NULL) - ++j; - if (ports[j]->port_state == PTP_DISABLED - || ports[j]->port_state == PTP_FAULTY) { - continue; - } - if (EBest == NULL) { - EBest = ports[j]->calculateERBest(); - } else if (ports[j]->calculateERBest()) { - if (ports[j]->calculateERBest()->isBetterThan(EBest)) { - EBest = ports[j]->calculateERBest(); - } - } - } - - if (EBest == NULL) { - break; - } - - /* Check if we've changed */ - { - - uint8_t LastEBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; - clock->getLastEBestIdentity(). - getIdentityString( LastEBestClockIdentity ); - EBest->getGrandmasterIdentity( EBestClockIdentity ); - if( memcmp( EBestClockIdentity, LastEBestClockIdentity, - PTP_CLOCK_IDENTITY_LENGTH ) != 0 ) - { - ClockIdentity newGM; - changed_external_master = true; - newGM.set((uint8_t *) EBestClockIdentity ); - clock->setLastEBestIdentity( newGM ); - } else { - changed_external_master = false; - } - } - - if( clock->isBetterThan( EBest )) { - // We're Grandmaster, set grandmaster info to me - ClockIdentity clock_identity; - unsigned char priority1; - unsigned char priority2; - ClockQuality clock_quality; - - clock_identity = getClock()->getClockIdentity(); - getClock()->setGrandmasterClockIdentity( clock_identity ); - priority1 = getClock()->getPriority1(); - getClock()->setGrandmasterPriority1( priority1 ); - priority2 = getClock()->getPriority2(); - getClock()->setGrandmasterPriority2( priority2 ); - clock_quality = getClock()->getClockQuality(); - getClock()->setGrandmasterClockQuality( clock_quality ); - } - - j = 0; - for (int i = 0; i < number_ports; ++i) { - while (ports[j] == NULL) - ++j; - if (ports[j]->port_state == PTP_DISABLED - || ports[j]->port_state == PTP_FAULTY) { - continue; - } - if (clock->isBetterThan(EBest)) { - // We are the GrandMaster, all ports are master - EBest = NULL; // EBest == NULL : we were grandmaster - ports[j]->recommendState(PTP_MASTER, - changed_external_master); - } else { - if( EBest == ports[j]->calculateERBest() ) { - // The "best" Announce was recieved on this port - ClockIdentity clock_identity; - unsigned char priority1; - unsigned char priority2; - ClockQuality *clock_quality; - - ports[j]->recommendState - ( PTP_SLAVE, changed_external_master ); - - clock_identity = EBest->getGrandmasterClockIdentity(); - getClock()->setGrandmasterClockIdentity(clock_identity); - priority1 = EBest->getGrandmasterPriority1(); - getClock()->setGrandmasterPriority1( priority1 ); - priority2 = EBest->getGrandmasterPriority2(); - getClock()->setGrandmasterPriority2( priority2 ); - clock_quality = EBest->getGrandmasterClockQuality(); - getClock()->setGrandmasterClockQuality(*clock_quality); - } else { - /* Otherwise we are the master because we have - sync'd to a better clock */ - ports[j]->recommendState - (PTP_MASTER, changed_external_master); - } - } - } - } - } - break; - - case LINKUP: - haltPdelay(false); - startPDelay(); - if (automotive_profile) { - GPTP_LOG_EXCEPTION("LINKUP"); - } - else { - GPTP_LOG_STATUS("LINKUP"); - } - - if (automotive_profile) { - asCapable = true; - - setStationState(STATION_STATE_ETHERNET_READY); - if (testMode) { - APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); - if (testStatusMsg) { - testStatusMsg->sendPort(this); - delete testStatusMsg; - } - } - - log_mean_sync_interval = initialLogSyncInterval; - log_mean_announce_interval = 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, log_mean_sync_interval, 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 (testMode) { - linkUpCount++; - } - } - this->timestamper_reset(); - break; - - case LINKDOWN: - stopPDelay(); - if (automotive_profile) { - GPTP_LOG_EXCEPTION("LINK DOWN"); - } - else { - setAsCapable(false); - GPTP_LOG_STATUS("LINK DOWN"); - } - if (testMode) { - linkDownCount++; - } - break; - - case ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES: - case SYNC_RECEIPT_TIMEOUT_EXPIRES: - { - if (e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES) { - incCounter_ieee8021AsPortStatAnnounceReceiptTimeouts(); - } - else if (e == SYNC_RECEIPT_TIMEOUT_EXPIRES) { - incCounter_ieee8021AsPortStatRxSyncReceiptTimeouts(); - } - if (!automotive_profile) { - - if( clock->getPriority1() == 255 ) { - // Restart timer - if( e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES ) { - clock->addEventTimerLocked - (this, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES, - (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER* - (unsigned long long) - (pow((double)2,getAnnounceInterval())* - 1000000000.0))); - } else { - startSyncReceiptTimer((unsigned long long) - (SYNC_RECEIPT_TIMEOUT_MULTIPLIER * - ((double) pow((double)2, getSyncInterval()) * - 1000000000.0))); - } - } - - if (port_state == PTP_INITIALIZING - || port_state == PTP_UNCALIBRATED - || port_state == PTP_SLAVE - || port_state == PTP_PRE_MASTER) { - GPTP_LOG_STATUS( - "*** %s Timeout Expired - Becoming Master", - e == ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES ? "Announce" : - "Sync" ); - { - // We're Grandmaster, set grandmaster info to me - ClockIdentity clock_identity; - unsigned char priority1; - unsigned char priority2; - ClockQuality clock_quality; - - clock_identity = getClock()->getClockIdentity(); - getClock()->setGrandmasterClockIdentity( clock_identity ); - priority1 = getClock()->getPriority1(); - getClock()->setGrandmasterPriority1( priority1 ); - priority2 = getClock()->getPriority2(); - getClock()->setGrandmasterPriority2( priority2 ); - clock_quality = getClock()->getClockQuality(); - getClock()->setGrandmasterClockQuality( clock_quality ); - } - port_state = PTP_MASTER; - Timestamp system_time; - Timestamp device_time; - - uint32_t local_clock, nominal_clock_rate; - - getDeviceTime(system_time, device_time, - local_clock, nominal_clock_rate); - - (void) clock->calcLocalSystemClockRateDifference - ( device_time, system_time ); - - delete qualified_announce; - qualified_announce = NULL; - - // Add timers for Announce and Sync, this is as close to immediately as we get - if( clock->getPriority1() != 255) { - clock->addEventTimerLocked - ( this, SYNC_INTERVAL_TIMEOUT_EXPIRES, 16000000 ); - } - startAnnounce(); - } - - } - else { - // Automotive Profile - 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))); - } - } - - } - - break; - case PDELAY_INTERVAL_TIMEOUT_EXPIRES: - GPTP_LOG_DEBUG("PDELAY_INTERVAL_TIMEOUT_EXPIRES occured"); - { - int ts_good; - Timestamp req_timestamp; - int iter = TX_TIMEOUT_ITER; - long req = TX_TIMEOUT_BASE; - unsigned req_timestamp_counter_value; - long long wait_time = 0; - - 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"); - - OSTimer *timer = timer_factory->createTimer(); - - ts_good = getTxTimestamp - (pdelay_req, req_timestamp, req_timestamp_counter_value, false); - while (ts_good != GPTP_EC_SUCCESS && iter-- != 0) { - timer->sleep(req); - wait_time += req; - if (ts_good != GPTP_EC_EAGAIN && iter < 1) - GPTP_LOG_ERROR( - "Error (TX) timestamping PDelay request " - "(Retrying-%d), error=%d", iter, ts_good); - ts_good = - getTxTimestamp - (pdelay_req, req_timestamp, - req_timestamp_counter_value, iter == 0); - req *= 2; - } - delete timer; - putTxLock(); - - if (ts_good == GPTP_EC_SUCCESS) { - pdelay_req->setTimestamp(req_timestamp); - GPTP_LOG_DEBUG( - "PDelay Request message, Timestamp %u (sec) %u (ns), seqID %u", - req_timestamp.seconds_ls, req_timestamp.nanoseconds, - pdelay_req->getSequenceId()); - } else { - Timestamp failed = INVALID_TIMESTAMP; - pdelay_req->setTimestamp(failed); - GPTP_LOG_ERROR( "Invalid TX" ); - } - - if (ts_good != GPTP_EC_SUCCESS) { - char msg - [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE]; - getExtendedError(msg); - GPTP_LOG_ERROR( - "Error (TX) timestamping PDelay request, error=%d\t%s", - ts_good, msg); - } - - { - long long timeout; - long long interval; - - timeout = PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER * - ((long long) - (pow((double)2,getPDelayInterval())*1000000000.0)) - - wait_time*1000; - 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, wait_time %lld, timeout %lld", - getPDelayInterval(), wait_time, timeout); - - interval = - ((long long) - (pow((double)2,getPDelayInterval())*1000000000.0)) - - wait_time*1000; - interval = interval > EVENT_TIMER_GRANULARITY ? - interval : EVENT_TIMER_GRANULARITY; - startPDelayIntervalTimer(interval); - } - } - break; - case SYNC_INTERVAL_TIMEOUT_EXPIRES: - GPTP_LOG_DEBUG("SYNC_INTERVAL_TIMEOUT_EXPIRES occured"); - { - /* Set offset from master to zero, update device vs - system time offset */ - Timestamp system_time; - Timestamp device_time; - FrequencyRatio local_system_freq_offset; - int64_t local_system_offset; - long long wait_time = 0; - - uint32_t local_clock, nominal_clock_rate; - - // Send a sync message and then a followup to broadcast - if (asCapable) { - PTPMessageSync *sync = new PTPMessageSync(this); - PortIdentity dest_id; - getPortIdentity(dest_id); - sync->setPortIdentity(&dest_id); - getTxLock(); - sync->sendPort(this, NULL); - GPTP_LOG_DEBUG("Sent SYNC message"); - - if (automotive_profile && port_state == PTP_MASTER) { - if (avbSyncState > 0) { - avbSyncState--; - if (avbSyncState == 0) { - // Send Avnu Automotive Profile status message - setStationState(STATION_STATE_AVB_SYNC); - if (testMode) { - APMessageTestStatus *testStatusMsg = new APMessageTestStatus(this); - if (testStatusMsg) { - testStatusMsg->sendPort(this); - delete testStatusMsg; - } - } - } - } - } - - int ts_good; - Timestamp sync_timestamp; - unsigned sync_timestamp_counter_value; - int iter = TX_TIMEOUT_ITER; - long req = TX_TIMEOUT_BASE; - - OSTimer *timer = timer_factory->createTimer(); - - ts_good = - getTxTimestamp(sync, sync_timestamp, - sync_timestamp_counter_value, - false); - while (ts_good != GPTP_EC_SUCCESS && iter-- != 0) { - timer->sleep(req); - wait_time += req; - - if (ts_good != GPTP_EC_EAGAIN && iter < 1) - GPTP_LOG_ERROR( - "Error (TX) timestamping Sync (Retrying), " - "error=%d", ts_good); - ts_good = - getTxTimestamp - (sync, sync_timestamp, - sync_timestamp_counter_value, iter == 0); - req *= 2; - } - delete timer; - putTxLock(); - - if (ts_good != GPTP_EC_SUCCESS) { - char msg [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE]; - getExtendedError(msg); - GPTP_LOG_ERROR( - "Error (TX) timestamping Sync, error=" - "%d\n%s", - ts_good, msg ); - } - - if (ts_good == GPTP_EC_SUCCESS) { - GPTP_LOG_VERBOSE("Successful Sync timestamp"); - GPTP_LOG_VERBOSE("Seconds: %u", - sync_timestamp.seconds_ls); - GPTP_LOG_VERBOSE("Nanoseconds: %u", - sync_timestamp.nanoseconds); - } else { - GPTP_LOG_ERROR - ("*** Unsuccessful Sync timestamp"); - } - - PTPMessageFollowUp *follow_up; - if (ts_good == GPTP_EC_SUCCESS) { - - 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 { - } - delete sync; - } - /* Do getDeviceTime() after transmitting sync frame - causing an update to local/system timestamp */ - getDeviceTime - (system_time, device_time, local_clock, nominal_clock_rate); - - GPTP_LOG_VERBOSE - ("port::processEvent(): System time: %u,%u Device Time: %u,%u", - system_time.seconds_ls, system_time.nanoseconds, - device_time.seconds_ls, device_time.nanoseconds); - - local_system_offset = - TIMESTAMP_TO_NS(system_time) - - TIMESTAMP_TO_NS(device_time); - local_system_freq_offset = - clock->calcLocalSystemClockRateDifference - ( device_time, system_time ); - clock->setMasterOffset - (this, 0, device_time, 1.0, local_system_offset, - system_time, local_system_freq_offset, sync_count, - pdelay_count, port_state, asCapable ); - - syncDone(); - - wait_time = ((long long) (pow((double)2, getSyncInterval()) * 1000000000.0)); - wait_time = wait_time > EVENT_TIMER_GRANULARITY ? wait_time : EVENT_TIMER_GRANULARITY; - startSyncIntervalTimer(wait_time); - - } - break; - case ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES: - GPTP_LOG_DEBUG("ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES occured"); - if (asCapable) { - // Send an announce message - PTPMessageAnnounce *annc = new PTPMessageAnnounce(this); - PortIdentity dest_id; - PortIdentity gmId; - ClockIdentity clock_id = clock->getClockIdentity(); - gmId.setClockIdentity(clock_id); - getPortIdentity(dest_id); - annc->setPortIdentity(&dest_id); - annc->sendPort(this, NULL); - delete annc; - } - startAnnounceIntervalTimer((uint64_t)(pow((double)2, getAnnounceInterval()) * 1000000000.0)); - 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); - } - pdelay_count = 0; - break; - - case PDELAY_RESP_PEER_MISBEHAVING_TIMEOUT_EXPIRES: - GPTP_LOG_EXCEPTION("PDelay Resp Peer Misbehaving timeout expired! Restarting PDelay"); - - haltPdelay(false); - if( port_state != PTP_SLAVE && port_state != 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 (log_mean_sync_interval != operLogSyncInterval) { - log_mean_sync_interval = 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, log_mean_sync_interval, PTPMessageSignalling::sigMsgInterval_NoChange); - else - sigMsg->setintervals(log_min_mean_pdelay_req_interval, log_mean_sync_interval, 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 IEEE1588Port::processEvent(), %d", - e); - break; - } - - return; -} - -PTPMessageAnnounce *IEEE1588Port::calculateERBest(void) -{ - return qualified_announce; -} - -void IEEE1588Port::recoverPort(void) -{ - return; -} - -IEEE1588Clock *IEEE1588Port::getClock(void) -{ - return clock; -} - -void IEEE1588Port::getDeviceTime -(Timestamp & system_time, Timestamp & device_time, - uint32_t & local_clock, uint32_t & nominal_clock_rate) -{ - if (_hw_timestamper) { - _hw_timestamper->HWTimestamper_gettime - (&system_time, &device_time, &local_clock, &nominal_clock_rate); - } else { - device_time = system_time = clock->getSystemTime(); - local_clock = nominal_clock_rate = 0; - } - return; -} - -void IEEE1588Port::becomeMaster( bool annc ) { - port_state = 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 IEEE1588Port::becomeSlave( bool restart_syntonization ) { - clock->deleteEventTimerLocked( this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES ); - clock->deleteEventTimerLocked( this, SYNC_INTERVAL_TIMEOUT_EXPIRES ); - - port_state = 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 IEEE1588Port::recommendState -( PortState state, bool changed_external_master ) -{ - bool reset_sync = false; - switch (state) { - case PTP_MASTER: - if (port_state != PTP_MASTER) { - port_state = PTP_MASTER; - // Start announce receipt timeout timer - // Start sync receipt timeout timer - becomeMaster( true ); - reset_sync = true; - } - break; - case PTP_SLAVE: - if (port_state != PTP_SLAVE) { - becomeSlave( true ); - reset_sync = true; - } else { - if( changed_external_master ) { - GPTP_LOG_STATUS("Changed master!" ); - clock->newSyntonizationSetPoint(); - getClock()->updateFUPInfo(); - reset_sync = true; - } - } - break; - default: - GPTP_LOG_ERROR - ("Invalid state change requested by call to " - "1588Port::recommendState()"); - break; - } - if( reset_sync ) sync_count = 0; - return; - } - -void IEEE1588Port::mapSocketAddr -(PortIdentity * destIdentity, LinkLayerAddress * remote) -{ - *remote = identity_map[*destIdentity]; - return; -} - -void IEEE1588Port::addSockAddrMap -(PortIdentity * destIdentity, LinkLayerAddress * remote) -{ - identity_map[*destIdentity] = *remote; - return; -} - -int IEEE1588Port::getTxTimestamp -(PTPMessageCommon * msg, Timestamp & timestamp, unsigned &counter_value, - bool last) -{ - PortIdentity identity; - msg->getPortIdentity(&identity); - return getTxTimestamp - (&identity, msg->getMessageId(), timestamp, counter_value, last); -} - -int IEEE1588Port::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 IEEE1588Port::getTxTimestamp(PortIdentity * sourcePortIdentity, - PTPMessageId messageId, Timestamp & timestamp, - unsigned &counter_value, bool last) -{ - if (_hw_timestamper) { - return _hw_timestamper->HWTimestamper_txtimestamp - (sourcePortIdentity, messageId, timestamp, counter_value, - last); - } - timestamp = clock->getSystemTime(); - return 0; -} - -int IEEE1588Port::getRxTimestamp(PortIdentity * sourcePortIdentity, - PTPMessageId messageId, Timestamp & timestamp, - unsigned &counter_value, bool last) -{ - if (_hw_timestamper) { - return _hw_timestamper->HWTimestamper_rxtimestamp - (sourcePortIdentity, messageId, timestamp, counter_value, - last); - } - timestamp = clock->getSystemTime(); - return 0; -} - -void IEEE1588Port::startSyncReceiptTimer(long long unsigned int waitTime) { - syncReceiptTimerLock->lock(); - clock->deleteEventTimerLocked(this, SYNC_RECEIPT_TIMEOUT_EXPIRES); - clock->addEventTimerLocked(this, SYNC_RECEIPT_TIMEOUT_EXPIRES, waitTime); - syncReceiptTimerLock->unlock(); -} - -void IEEE1588Port::stopSyncReceiptTimer(void) -{ - syncReceiptTimerLock->lock(); - clock->deleteEventTimerLocked(this, SYNC_RECEIPT_TIMEOUT_EXPIRES); - syncReceiptTimerLock->unlock(); -} - -void IEEE1588Port::startSyncIntervalTimer(long long unsigned int waitTime) -{ - syncIntervalTimerLock->lock(); - clock->deleteEventTimerLocked(this, SYNC_INTERVAL_TIMEOUT_EXPIRES); - clock->addEventTimerLocked(this, SYNC_INTERVAL_TIMEOUT_EXPIRES, waitTime); - syncIntervalTimerLock->unlock(); -} - -void IEEE1588Port::startAnnounceIntervalTimer(long long unsigned int waitTime) -{ - announceIntervalTimerLock->lock(); - clock->deleteEventTimerLocked(this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES); - clock->addEventTimerLocked(this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES, waitTime); - announceIntervalTimerLock->unlock(); -} - -void IEEE1588Port::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(); -} - diff --git a/daemons/gptp/common/ptp_message.cpp b/daemons/gptp/common/ptp_message.cpp index 309b5486..a5f3aadc 100644 --- a/daemons/gptp/common/ptp_message.cpp +++ b/daemons/gptp/common/ptp_message.cpp @@ -34,14 +34,14 @@ #include <ieee1588.hpp> #include <avbts_clock.hpp> #include <avbts_message.hpp> -#include <avbts_port.hpp> +#include <ether_port.hpp> #include <avbts_ostimer.hpp> #include <stdio.h> #include <string.h> #include <math.h> -PTPMessageCommon::PTPMessageCommon(IEEE1588Port * port) +PTPMessageCommon::PTPMessageCommon( CommonPort *port ) { // Fill in fields using port/clock dataset as a template versionPTP = GPTP_VERSION; @@ -65,7 +65,8 @@ bool PTPMessageCommon::isSenderEqual(PortIdentity portIdentity) } PTPMessageCommon *buildPTPMessage -(char *buf, int size, LinkLayerAddress * remote, IEEE1588Port * port) +( char *buf, int size, LinkLayerAddress *remote, + EtherPort *port ) { OSTimer *timer = port->getTimerFactory()->createTimer(); PTPMessageCommon *msg = NULL; @@ -541,7 +542,7 @@ abort: return NULL; } -void PTPMessageCommon::processMessage(IEEE1588Port * port) +void PTPMessageCommon::processMessage( EtherPort *port ) { _gc = true; return; @@ -665,7 +666,8 @@ PTPMessageSync::PTPMessageSync() { PTPMessageSync::~PTPMessageSync() { } -PTPMessageSync::PTPMessageSync(IEEE1588Port * port) : PTPMessageCommon(port) +PTPMessageSync::PTPMessageSync( EtherPort *port ) : + PTPMessageCommon( port ) { messageType = SYNC_MESSAGE; // This is an event message sequenceId = port->getNextSyncSequenceId(); @@ -679,7 +681,8 @@ PTPMessageSync::PTPMessageSync(IEEE1588Port * port) : PTPMessageCommon(port) return; } -void PTPMessageSync::sendPort(IEEE1588Port * port, PortIdentity * destIdentity) +void PTPMessageSync::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -714,8 +717,8 @@ void PTPMessageSync::sendPort(IEEE1588Port * port, PortIdentity * destIdentity) return; } - PTPMessageAnnounce::PTPMessageAnnounce(IEEE1588Port * port) : PTPMessageCommon - (port) +PTPMessageAnnounce::PTPMessageAnnounce( CommonPort *port ) : + PTPMessageCommon( port ) { messageType = ANNOUNCE_MESSAGE; // This is an event message sequenceId = port->getNextAnnounceSequenceId(); @@ -740,8 +743,8 @@ void PTPMessageSync::sendPort(IEEE1588Port * port, PortIdentity * destIdentity) return; } -void PTPMessageAnnounce::sendPort(IEEE1588Port * port, - PortIdentity * destIdentity) +void PTPMessageAnnounce::sendPort +( CommonPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -786,7 +789,7 @@ void PTPMessageAnnounce::sendPort(IEEE1588Port * port, return; } -void PTPMessageAnnounce::processMessage(IEEE1588Port * port) +void PTPMessageAnnounce::processMessage( EtherPort *port ) { ClockIdentity my_clock_identity; @@ -809,7 +812,7 @@ void PTPMessageAnnounce::processMessage(IEEE1588Port * port) } // Add message to the list - port->addQualifiedAnnounce(this); + port->setQualifiedAnnounce( this ); port->getClock()->addEventTimerLocked(port, STATE_CHANGE_EVENT, 16000000); bail: @@ -823,7 +826,7 @@ void PTPMessageAnnounce::processMessage(IEEE1588Port * port) 1000000000.0))); } -void PTPMessageSync::processMessage(IEEE1588Port * port) +void PTPMessageSync::processMessage( EtherPort *port ) { if (port->getPortState() == PTP_DISABLED ) { // Do nothing Sync messages should be ignored when in this state @@ -856,8 +859,8 @@ void PTPMessageSync::processMessage(IEEE1588Port * port) return; } - PTPMessageFollowUp::PTPMessageFollowUp(IEEE1588Port * port):PTPMessageCommon - (port) +PTPMessageFollowUp::PTPMessageFollowUp( EtherPort *port ) : + PTPMessageCommon( port ) { messageType = FOLLOWUP_MESSAGE; /* This is an event message */ control = FOLLOWUP; @@ -867,8 +870,8 @@ void PTPMessageSync::processMessage(IEEE1588Port * port) return; } -void PTPMessageFollowUp::sendPort(IEEE1588Port * port, - PortIdentity * destIdentity) +void PTPMessageFollowUp::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -927,7 +930,7 @@ void PTPMessageFollowUp::sendPort(IEEE1588Port * port, return; } -void PTPMessageFollowUp::processMessage(IEEE1588Port * port) +void PTPMessageFollowUp::processMessage( EtherPort *port ) { uint64_t delay; Timestamp sync_arrival; @@ -1096,8 +1099,8 @@ done: return; } - PTPMessagePathDelayReq::PTPMessagePathDelayReq(IEEE1588Port * port): - PTPMessageCommon (port) +PTPMessagePathDelayReq::PTPMessagePathDelayReq +( EtherPort *port ) : PTPMessageCommon( port ) { logMeanMessageInterval = 0; control = MESSAGE_OTHER; @@ -1106,7 +1109,7 @@ done: return; } -void PTPMessagePathDelayReq::processMessage(IEEE1588Port * port) +void PTPMessagePathDelayReq::processMessage( EtherPort *port ) { OSTimer *timer = port->getTimerFactory()->createTimer(); PortIdentity resp_fwup_id; @@ -1228,8 +1231,8 @@ done: return; } -void PTPMessagePathDelayReq::sendPort(IEEE1588Port * port, - PortIdentity * destIdentity) +void PTPMessagePathDelayReq::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { if(port->pdelayHalted()) return; @@ -1248,8 +1251,8 @@ void PTPMessagePathDelayReq::sendPort(IEEE1588Port * port, return; } - PTPMessagePathDelayResp::PTPMessagePathDelayResp(IEEE1588Port * port) : - PTPMessageCommon(port) +PTPMessagePathDelayResp::PTPMessagePathDelayResp +( EtherPort *port ) : PTPMessageCommon( port ) { /*TODO: Why 0x7F?*/ logMeanMessageInterval = 0x7F; @@ -1268,7 +1271,7 @@ PTPMessagePathDelayResp::~PTPMessagePathDelayResp() delete requestingPortIdentity; } -void PTPMessagePathDelayResp::processMessage(IEEE1588Port * port) +void PTPMessagePathDelayResp::processMessage( EtherPort *port ) { if (port->getPortState() == PTP_DISABLED) { // Do nothing all messages should be ignored when in this state @@ -1346,8 +1349,8 @@ bypass_verify_duplicate: return; } -void PTPMessagePathDelayResp::sendPort(IEEE1588Port * port, - PortIdentity * destIdentity) +void PTPMessagePathDelayResp::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -1406,7 +1409,7 @@ void PTPMessagePathDelayResp::getRequestingPortIdentity } PTPMessagePathDelayRespFollowUp::PTPMessagePathDelayRespFollowUp -(IEEE1588Port * port) : PTPMessageCommon (port) +( EtherPort *port ) : PTPMessageCommon( port ) { logMeanMessageInterval = 0x7F; control = MESSAGE_OTHER; @@ -1423,7 +1426,8 @@ PTPMessagePathDelayRespFollowUp::~PTPMessagePathDelayRespFollowUp() } #define US_PER_SEC 1000000 -void PTPMessagePathDelayRespFollowUp::processMessage(IEEE1588Port * port) +void PTPMessagePathDelayRespFollowUp::processMessage +( EtherPort *port ) { Timestamp remote_resp_tx_timestamp(0, 0, 0); Timestamp request_tx_timestamp(0, 0, 0); @@ -1666,8 +1670,8 @@ void PTPMessagePathDelayRespFollowUp::processMessage(IEEE1588Port * port) return; } -void PTPMessagePathDelayRespFollowUp::sendPort(IEEE1588Port * port, - PortIdentity * destIdentity) +void PTPMessagePathDelayRespFollowUp::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -1727,7 +1731,8 @@ void PTPMessagePathDelayRespFollowUp::setRequestingPortIdentity { } - PTPMessageSignalling::PTPMessageSignalling(IEEE1588Port * port) : PTPMessageCommon(port) +PTPMessageSignalling::PTPMessageSignalling +( EtherPort *port ) : PTPMessageCommon( port ) { messageType = SIGNALLING_MESSAGE; sequenceId = port->getNextSignalSequenceId(); @@ -1750,7 +1755,8 @@ void PTPMessageSignalling::setintervals(int8_t linkDelayInterval, int8_t timeSyn tlv.setAnnounceInterval(announceInterval); } -void PTPMessageSignalling::sendPort(IEEE1588Port * port, PortIdentity * destIdentity) +void PTPMessageSignalling::sendPort +( EtherPort *port, PortIdentity *destIdentity ) { uint8_t buf_t[256]; uint8_t *buf_ptr = buf_t + port->getPayloadOffset(); @@ -1771,7 +1777,7 @@ void PTPMessageSignalling::sendPort(IEEE1588Port * port, PortIdentity * destIden port->sendGeneralPort(PTP_ETHERTYPE, buf_t, messageLength, MCAST_OTHER, destIdentity); } -void PTPMessageSignalling::processMessage(IEEE1588Port * port) +void PTPMessageSignalling::processMessage( EtherPort *port ) { long long unsigned int waitTime; @@ -1806,7 +1812,7 @@ void PTPMessageSignalling::processMessage(IEEE1588Port * port) } if (timeSyncInterval == PTPMessageSignalling::sigMsgInterval_Initial) { - port->setInitSyncInterval(); + port->resetInitSyncInterval(); waitTime = ((long long) (pow((double)2, port->getSyncInterval()) * 1000000000.0)); waitTime = waitTime > EVENT_TIMER_GRANULARITY ? waitTime : EVENT_TIMER_GRANULARITY; diff --git a/daemons/gptp/linux/build/Makefile b/daemons/gptp/linux/build/Makefile index 4ab409be..1e00b1a5 100644 --- a/daemons/gptp/linux/build/Makefile +++ b/daemons/gptp/linux/build/Makefile @@ -56,7 +56,8 @@ OBJ_DIR = obj OBJ_FILES = $(OBJ_DIR)/ptp_message.o\ $(OBJ_DIR)/ap_message.o\ $(OBJ_DIR)/avbts_osnet.o\ - $(OBJ_DIR)/ieee1588port.o\ + $(OBJ_DIR)/ether_port.o\ + $(OBJ_DIR)/common_port.o\ $(OBJ_DIR)/ieee1588clock.o \ $(OBJ_DIR)/linux_hal_common.o\ $(OBJ_DIR)/linux_hal_persist_file.o\ @@ -65,7 +66,8 @@ OBJ_FILES = $(OBJ_DIR)/ptp_message.o\ $(OBJ_DIR)/ini.o \ $(OBJ_DIR)/gptp_cfg.o -HEADER_FILES = $(COMMON_DIR)/avbts_port.hpp\ +HEADER_FILES = $(COMMON_DIR)/ether_port.hpp\ + $(COMMON_DIR)/common_port.hpp\ $(COMMON_DIR)/avbts_ostimerq.hpp\ $(COMMON_DIR)/avbts_ostimer.hpp\ $(COMMON_DIR)/avbts_osthread.hpp\ @@ -156,8 +158,11 @@ $(OBJ_DIR)/linux_hal_i210.o: $(SRC_DIR)/linux_hal_i210.cpp $(HEADER_FILES) $(OBJ_DIR)/linux_hal_intelce.o: $(SRC_DIR)/linux_hal_intelce.cpp $(HEADER_FILES) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SRC_DIR)/linux_hal_intelce.cpp -o $(OBJ_DIR)/linux_hal_intelce.o -$(OBJ_DIR)/ieee1588port.o: $(COMMON_DIR)/ieee1588port.cpp $(HEADER_FILES) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/ieee1588port.cpp -o $(OBJ_DIR)/ieee1588port.o +$(OBJ_DIR)/ether_port.o: $(COMMON_DIR)/ether_port.cpp $(HEADER_FILES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ + +$(OBJ_DIR)/common_port.o: $(COMMON_DIR)/common_port.cpp $(HEADER_FILES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ $(OBJ_DIR)/ieee1588clock.o: $(COMMON_DIR)/ieee1588clock.cpp $(HEADER_FILES) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/ieee1588clock.cpp -o $(OBJ_DIR)/ieee1588clock.o diff --git a/daemons/gptp/linux/src/daemon_cl.cpp b/daemons/gptp/linux/src/daemon_cl.cpp index d6a74cee..129fbd6b 100644 --- a/daemons/gptp/linux/src/daemon_cl.cpp +++ b/daemons/gptp/linux/src/daemon_cl.cpp @@ -125,11 +125,11 @@ int watchdog_setup(OSThreadFactory *thread_factory) } static IEEE1588Clock *pClock = NULL; -static IEEE1588Port *pPort = NULL; +static EtherPort *pPort = NULL; int main(int argc, char **argv) { - IEEE1588PortInit_t portInit; + PortInit_t portInit; sigset_t set; InterfaceName *ifname; @@ -176,9 +176,7 @@ int main(int argc, char **argv) portInit.clock = NULL; portInit.index = 0; - portInit.forceSlave = false; portInit.timestamper = NULL; - portInit.offset = 0; portInit.net_label = NULL; portInit.automotive_profile = false; portInit.isGM = false; @@ -380,16 +378,14 @@ int main(int argc, char **argv) // just set directly into the portInit struct. portInit.clock = pClock; portInit.index = 1; - portInit.forceSlave = false; portInit.timestamper = timestamper; - portInit.offset = 0; portInit.net_label = ifname; portInit.condition_factory = condition_factory; portInit.thread_factory = thread_factory; portInit.timer_factory = timer_factory; portInit.lock_factory = lock_factory; - pPort = new IEEE1588Port(&portInit); + pPort = new EtherPort(&portInit); if(use_config_file) { diff --git a/daemons/gptp/linux/src/linux_hal_common.cpp b/daemons/gptp/linux/src/linux_hal_common.cpp index d63f1096..1db97012 100644 --- a/daemons/gptp/linux/src/linux_hal_common.cpp +++ b/daemons/gptp/linux/src/linux_hal_common.cpp @@ -34,7 +34,7 @@ #include <linux_hal_common.hpp> #include <sys/types.h> #include <avbts_clock.hpp> -#include <avbts_port.hpp> +#include <ether_port.hpp> #include <pthread.h> #include <linux_ipc.hpp> @@ -168,7 +168,8 @@ void LinuxNetworkInterface::clear_reenable_rx_queue() { } } -static void x_readEvent(int sockint, IEEE1588Port *pPort, int ifindex) +static void x_readEvent +( int sockint, EtherPort *pPort, int ifindex ) { int status; char buf[4096]; @@ -223,7 +224,7 @@ static void x_readEvent(int sockint, IEEE1588Port *pPort, int ifindex) return; } -static void x_initLinkUpStatus(IEEE1588Port *pPort, int ifindex) +static void x_initLinkUpStatus( EtherPort *pPort, int ifindex ) { struct ifreq device; memset(&device, 0, sizeof(device)); @@ -254,12 +255,20 @@ static void x_initLinkUpStatus(IEEE1588Port *pPort, int ifindex) close(inetSocket); } -void LinuxNetworkInterface::watchNetLink(IEEE1588Port *pPort) +void LinuxNetworkInterface::watchNetLink( CommonPort *iPort ) { fd_set netLinkFD; int netLinkSocket; struct sockaddr_nl addr; + EtherPort *pPort = + dynamic_cast<EtherPort *>(iPort); + if( pPort == NULL ) + { + GPTP_LOG_ERROR("NETLINK socket open error"); + return; + } + netLinkSocket = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (netLinkSocket < 0) { GPTP_LOG_ERROR("NETLINK socket open error"); diff --git a/daemons/gptp/linux/src/linux_hal_common.hpp b/daemons/gptp/linux/src/linux_hal_common.hpp index 732dfc13..5ea3ff0a 100644 --- a/daemons/gptp/linux/src/linux_hal_common.hpp +++ b/daemons/gptp/linux/src/linux_hal_common.hpp @@ -203,7 +203,7 @@ public: /** * @brief Watch for net link changes. */ - virtual void watchNetLink(IEEE1588Port *pPort); + virtual void watchNetLink( CommonPort *pPort ); /** * @brief Gets the payload offset @@ -292,7 +292,8 @@ public: * @param type OSLockType enumeration * @return Pointer to OSLock object */ - OSLock * createLock(OSLockType type) { + OSLock * createLock( OSLockType type ) const + { LinuxLock *lock = new LinuxLock(); if (lock->initialize(type) != oslock_ok) { delete lock; @@ -365,7 +366,8 @@ public: * @brief Creates LinuxCondition objects * @return Pointer to the OSCondition object in case of success. NULL otherwise */ - OSCondition * createCondition() { + OSCondition *createCondition() const + { LinuxCondition *result = new LinuxCondition(); return result->initialize() ? result : NULL; } @@ -487,7 +489,8 @@ class LinuxTimerFactory : public OSTimerFactory { * @brief Creates the linux timer * @return Pointer to OSTimer object */ - virtual OSTimer * createTimer() { + virtual OSTimer *createTimer() const + { return new LinuxTimer(); } }; @@ -551,7 +554,7 @@ class LinuxThreadFactory:public OSThreadFactory { * @brief Creates a new LinuxThread * @return Pointer to LinuxThread object */ - OSThread * createThread() { + OSThread *createThread() const { return new LinuxThread(); } }; diff --git a/daemons/gptp/linux/src/linux_hal_generic.cpp b/daemons/gptp/linux/src/linux_hal_generic.cpp index beb22024..4a3d187f 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.cpp +++ b/daemons/gptp/linux/src/linux_hal_generic.cpp @@ -433,7 +433,8 @@ static inline Timestamp pctTimestamp( struct ptp_clock_time *t ) { // Use HW cross-timestamp if available bool LinuxTimestamperGeneric::HWTimestamper_gettime ( Timestamp *system_time, Timestamp *device_time, uint32_t *local_clock, - uint32_t *nominal_clock_rate ) { + uint32_t *nominal_clock_rate ) const +{ if( phc_fd == -1 ) return false; diff --git a/daemons/gptp/linux/src/linux_hal_generic.hpp b/daemons/gptp/linux/src/linux_hal_generic.hpp index da33efbf..2257bf55 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.hpp +++ b/daemons/gptp/linux/src/linux_hal_generic.hpp @@ -137,8 +137,8 @@ public: * @return TRUE if got the time successfully, FALSE otherwise */ virtual bool HWTimestamper_gettime - ( Timestamp *system_time, Timestamp *device_time, uint32_t *local_clock, - uint32_t *nominal_clock_rate ); + ( Timestamp *system_time, Timestamp *device_time, + uint32_t *local_clock, uint32_t *nominal_clock_rate ) const; /** * @brief Gets the TX timestamp from hardware interface diff --git a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp index 19f15e73..5e164b0d 100644 --- a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp +++ b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp @@ -80,13 +80,11 @@ int parseMacAddr( _TCHAR *macstr, uint8_t *octet_string ) { int _tmain(int argc, _TCHAR* argv[]) { - IEEE1588PortInit_t portInit; + PortInit_t portInit; portInit.clock = NULL; portInit.index = 1; - portInit.forceSlave = false; portInit.timestamper = NULL; - portInit.offset = 0; portInit.net_label = NULL; portInit.automotive_profile = false; portInit.isGM = false; @@ -166,7 +164,7 @@ int _tmain(int argc, _TCHAR* argv[]) // Create Clock object portInit.clock = new IEEE1588Clock( false, false, priority1, portInit.timestamper, timerq_factory, ipc, portInit.lock_factory ); // Do not force slave // Create Port Object linked to clock and low level - IEEE1588Port *port = new IEEE1588Port( &portInit ); + EtherPort *port = new EtherPort( &portInit ); if (!port->init_port(phy_delays)) { printf( "Failed to initialize port\n" ); return -1; diff --git a/daemons/gptp/windows/daemon_cl/windows_hal.cpp b/daemons/gptp/windows/daemon_cl/windows_hal.cpp index ede0fdb2..1911b278 100644 --- a/daemons/gptp/windows/daemon_cl/windows_hal.cpp +++ b/daemons/gptp/windows/daemon_cl/windows_hal.cpp @@ -192,7 +192,7 @@ bool WindowsNamedPipeIPC::update(int64_t ml_phoffset, int64_t ls_phoffset, Frequ } -void WindowsPCAPNetworkInterface::watchNetLink(IEEE1588Port *pPort) +void WindowsPCAPNetworkInterface::watchNetLink( CommonPort *pPort) { /* ToDo add link up/down detection, Google MIB_IPADDR_DISCONNECTED */ } diff --git a/daemons/gptp/windows/daemon_cl/windows_hal.hpp b/daemons/gptp/windows/daemon_cl/windows_hal.hpp index f3f4eaca..03fdfb8a 100644 --- a/daemons/gptp/windows/daemon_cl/windows_hal.hpp +++ b/daemons/gptp/windows/daemon_cl/windows_hal.hpp @@ -110,7 +110,7 @@ public: /** * @brief Watch for netlink changes. */ - virtual void watchNetLink(IEEE1588Port *pPort); + virtual void watchNetLink( CommonPort *pPort ); /** * @brief Gets the offset to the start of data in the Layer 2 Frame @@ -258,7 +258,7 @@ public: * @param type Lock type - OSLockType * @return New lock on OSLock format */ - OSLock *createLock( OSLockType type ) { + OSLock *createLock( OSLockType type ) const { WindowsLock *lock = new WindowsLock(); if( !lock->initialize( type )) { delete lock; @@ -327,7 +327,7 @@ public: */ class WindowsConditionFactory : public OSConditionFactory { public: - OSCondition *createCondition() { + OSCondition *createCondition() const { WindowsCondition *result = new WindowsCondition(); return result->initialize() ? result : NULL; } @@ -514,7 +514,7 @@ public: * @brief Creates a new timer * @return New windows OSTimer */ - virtual OSTimer *createTimer() { + virtual OSTimer *createTimer() const { return new WindowsTimer(); } }; @@ -583,7 +583,7 @@ public: * @brief Creates a new windows thread * @return New thread of type OSThread */ - OSThread *createThread() { + OSThread *createThread() const { return new WindowsThread(); } }; @@ -633,7 +633,7 @@ private: HANDLE miniport; LARGE_INTEGER tsc_hz; LARGE_INTEGER netclock_hz; - DWORD readOID( NDIS_OID oid, void *output_buffer, DWORD size, DWORD *size_returned ) { + DWORD readOID( NDIS_OID oid, void *output_buffer, DWORD size, DWORD *size_returned ) const { NDIS_OID oid_l = oid; DWORD rc = DeviceIoControl( miniport, @@ -647,19 +647,19 @@ private: if( rc == 0 ) return GetLastError(); return ERROR_SUCCESS; } - Timestamp nanoseconds64ToTimestamp( uint64_t time ) { + Timestamp nanoseconds64ToTimestamp( uint64_t time ) const { Timestamp timestamp; timestamp.nanoseconds = time % 1000000000; timestamp.seconds_ls = (time / 1000000000) & 0xFFFFFFFF; timestamp.seconds_ms = (uint16_t)((time / 1000000000) >> 32); return timestamp; } - uint64_t scaleNativeClockToNanoseconds( uint64_t time ) { + uint64_t scaleNativeClockToNanoseconds( uint64_t time ) const { long double scaled_output = ((long double)netclock_hz.QuadPart)/1000000000; scaled_output = ((long double) time)/scaled_output; return (uint64_t) scaled_output; } - uint64_t scaleTSCClockToNanoseconds( uint64_t time ) { + uint64_t scaleTSCClockToNanoseconds( uint64_t time ) const { long double scaled_output = ((long double)tsc_hz.QuadPart)/1000000000; scaled_output = ((long double) time)/scaled_output; return (uint64_t) scaled_output; @@ -686,7 +686,7 @@ public: * @return True in case of success. FALSE in case of error */ virtual bool HWTimestamper_gettime( Timestamp *system_time, Timestamp *device_time, uint32_t *local_clock, - uint32_t *nominal_clock_rate ) { + uint32_t *nominal_clock_rate ) const { DWORD buf[6]; DWORD returned; uint64_t now_net, now_tsc; |