/** * @file ptpd.h * @mainpage Ptpd v2 Documentation * @authors Martin Burnicki, Alexandre van Kempen, Steven Kreuzer, * George Neville-Neil * @version 2.0 * @date Fri Aug 27 10:22:19 2010 * * @section implementation Implementation * PTTdV2 is not a full implementation of 1588 - 2008 standard. * It is implemented only with use of Transparent Clock and Peer delay * mechanism, according to 802.1AS requierements. * * This header file includes all others headers. * It defines functions which are not dependant of the operating system. */ /* modification history -------------------- 17oct23,rjq Fix Y2038 issue. 15aug16,xxy Add PTP features.(F6696) 06jun16,xxy Fix unstable error.(VXW7-3677) 02feb16,h_l Init version. */ #ifndef PTPD_H_ #define PTPD_H_ #define VXWORKS_OS #ifdef VXWORKS_OS #define HAVE_SYS_TIMEX_H #define _POSIX_TIMERS 200112L #define PACKAGE_VERSION "2.3.1" #define usleep(x) taskDelay(sysClkRateGet() * x / 1000000) #endif /*endif VXWORKS_OS*/ #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #ifdef HAVE_STRINGS_H #include #endif /* HAVE_STRINGS_H */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIMEX_H #ifndef VXWORKS_OS #include #else /*below parts copied from include/uapi/linux/timx.h*/ struct timex { int modes; /* mode selector */ long offset; /* time offset (usec) */ int freq; /* frequency offset (scaled ppm) */ long maxerror;/* maximum error (usec) */ long esterror;/* estimated error (usec) */ int status; /* clock command/status */ long constant;/* pll time constant */ long precision;/* clock precision (usec) (read only) */ long tolerance;/* clock frequency tolerance (ppm) * (read only) */ struct timeval time; /* (read only, except for ADJ_SETOFFSET) */ unsigned int tick; /* (modified) usecs between clock ticks */ int tai; /* TAI offset (ro) */ }; /* * Mode codes (timex.mode) */ #define ADJ_OFFSET 0x0001 /* time offset */ #define ADJ_FREQUENCY 0x0002 /* frequency offset */ #define ADJ_MAXERROR 0x0004 /* maximum time error */ #define ADJ_ESTERROR 0x0008 /* estimated time error */ #define ADJ_STATUS 0x0010 /* clock status */ #define ADJ_TIMECONST 0x0020 /* pll time constant */ #define ADJ_TAI 0x0080 /* set TAI offset */ #define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */ #define ADJ_MICRO 0x1000 /* select microsecond resolution */ #define ADJ_NANO 0x2000 /* select nanosecond resolution */ #define ADJ_TICK 0x4000 /* tick value */ /* NTP userland likes the MOD_ prefix better */ #define MOD_OFFSET ADJ_OFFSET #define MOD_FREQUENCY ADJ_FREQUENCY #define MOD_MAXERROR ADJ_MAXERROR #define MOD_ESTERROR ADJ_ESTERROR #define MOD_STATUS ADJ_STATUS #define MOD_TIMECONST ADJ_TIMECONST #define MOD_TAI ADJ_TAI #define MOD_MICRO ADJ_MICRO #define MOD_NANO ADJ_NANO /* * Status codes (timex.status) */ #define STA_PLL 0x0001 /* enable PLL updates (rw) */ #define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */ #define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */ #define STA_FLL 0x0008 /* select frequency-lock mode (rw) */ #define STA_INS 0x0010 /* insert leap (rw) */ #define STA_DEL 0x0020 /* delete leap (rw) */ #define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */ #define STA_FREQHOLD 0x0080 /* hold frequency (rw) */ #define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */ #define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */ #define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */ #define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ #define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ #define STA_NANO 0x2000 /* resolution (0 = us, 1 = ns) (ro) */ #define STA_MODE 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ #define STA_CLK 0x8000 /* clock source (0 = A, 1 = B) (ro) */ /* read-only bits */ #define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK) /* * Clock states (time_state) */ #define TIME_OK 0 /* clock synchronized, no leap second */ #define TIME_INS 1 /* insert leap second */ #define TIME_DEL 2 /* delete leap second */ #define TIME_OOP 3 /* leap second in progress */ #define TIME_WAIT 4 /* leap second has occurred */ #define TIME_ERROR 5 /* clock not synchronized */ #define TIME_BAD TIME_ERROR /* bw compat */ #endif #endif #include #include #ifdef VXWORKS_OS #include #else #include #endif #include #ifndef VXWORKS_OS #include #endif #include #include #include #include #ifdef VXWORKS_OS struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #else #include #endif #include #ifndef VXWORKS_OS #include #endif #include #include #ifdef HAVE_UTMPX_H #include #else #ifdef HAVE_UTMP_H #include #endif /* HAVE_UTMP_H */ #endif /* HAVE_UTMPX_H */ #ifdef HAVE_NET_ETHERNET_H #include #endif /* HAVE_NET_ETHERNET_H */ #include #ifdef HAVE_NETINET_IN_SYSTM_H #include #endif #include #include #ifdef HAVE_NETINET_ETHER_H #include #endif /* HAVE_NETINET_ETHER_H */ #ifdef HAVE_NET_IF_ARP_H #include #endif /* HAVE_NET_IF_ARP_H*/ #ifdef HAVE_NET_IF_H #include #endif /* HAVE_NET_IF_H*/ #ifdef HAVE_NETINET_IF_ETHER_H #include #endif /* HAVE_NETINET_IF_ETHER_H */ /* This macro is to remove sudden jitter which would cause PTP unstable */ #define huge_jitter_counts_max 3 #ifdef HAVE_SYS_CPUSET_H #include #endif /* HAVE_SYS_CPUSET_H */ #include "constants.h" #include "limits.h" #include "dep/ipv4_acl.h" #include "dep/constants_dep.h" #include "dep/datatypes_dep.h" #include "datatypes.h" #include "dep/ptpd_dep.h" #include "dep/daemonconfig.h" int64_t llabs(int64_t i); /* NOTE: this macro can be refactored into a function */ #define XMALLOC(ptr,size) \ if(!((ptr)=malloc(size))) { \ PERROR("failed to allocate memory"); \ return; \ } #define IS_SET(data, bitpos) \ ((data & ( 0x1 << bitpos )) == (0x1 << bitpos)) #define SET_FIELD(data, bitpos) \ data << bitpos /* #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) */ /** \name arith.c * -Timing management and arithmetic*/ /**\{*/ /* arith.c */ /** * \brief Convert Integer64 into TimeInternal structure */ void integer64_to_internalTime(Integer64,TimeInternal*); /** * \brief Convert TimeInternal structure to Integer64 */ void internalTime_to_integer64(TimeInternal, Integer64*); /** * \brief Convert TimeInternal into Timestamp structure (defined by the spec) */ void fromInternalTime(const TimeInternal*,Timestamp*); /** * \brief Convert Timestamp to TimeInternal structure (defined by the spec) */ void toInternalTime(TimeInternal*, const Timestamp*); void ts_to_InternalTime(const struct timespec *, TimeInternal *); void tv_to_InternalTime(const struct timeval *, TimeInternal *); /** * \brief Use to normalize a TimeInternal structure * * The nanosecondsField member must always be less than 10⁹ * This function is used after adding or substracting TimeInternal */ void normalizeTime(TimeInternal*); /** * \brief Add two InternalTime structure and normalize */ void addTime(TimeInternal*,const TimeInternal*,const TimeInternal*); /** * \brief Substract two InternalTime structure and normalize */ void subTime(TimeInternal*,const TimeInternal*,const TimeInternal*); /** \}*/ /** * \brief Divied an InternalTime by 2 */ void div2Time(TimeInternal *); /** \name bmc.c * -Best Master Clock Algorithm functions*/ /**\{*/ /* bmc.c */ /** * \brief Compare data set of foreign masters and local data set * \return The recommended state for the port */ UInteger8 bmc(ForeignMasterRecord*, const RunTimeOpts*,PtpClock*); /** * \brief When recommended state is Master, copy local data into parent and grandmaster dataset */ void m1(const RunTimeOpts *, PtpClock*); /** * \brief When recommended state is Slave, copy dataset of master into parent and grandmaster dataset */ void s1(MsgHeader*,MsgAnnounce*,PtpClock*, const RunTimeOpts *); void p1(PtpClock *ptpClock, const RunTimeOpts *rtOpts); /** * \brief Initialize datas */ void initData(RunTimeOpts*,PtpClock*); /** \}*/ /** \name protocol.c * -Execute the protocol engine*/ /**\{*/ /** * \brief Protocol engine */ /* protocol.c */ void protocol(RunTimeOpts*,PtpClock*); /** \}*/ /** \name management.c * -Management message support*/ /**\{*/ /* management.c */ /** * \brief Management message support */ void handleMMNullManagement(MsgManagement*, MsgManagement*, PtpClock*); void handleMMClockDescription(MsgManagement*, MsgManagement*, PtpClock*); void handleMMSlaveOnly(MsgManagement*, MsgManagement*, PtpClock*); void handleMMUserDescription(MsgManagement*, MsgManagement*, PtpClock*); void handleMMSaveInNonVolatileStorage(MsgManagement*, MsgManagement*, PtpClock*); void handleMMResetNonVolatileStorage(MsgManagement*, MsgManagement*, PtpClock*); void handleMMInitialize(MsgManagement*, MsgManagement*, PtpClock*); void handleMMDefaultDataSet(MsgManagement*, MsgManagement*, PtpClock*); void handleMMCurrentDataSet(MsgManagement*, MsgManagement*, PtpClock*); void handleMMParentDataSet(MsgManagement*, MsgManagement*, PtpClock*); void handleMMTimePropertiesDataSet(MsgManagement*, MsgManagement*, PtpClock*); void handleMMPortDataSet(MsgManagement*, MsgManagement*, PtpClock*); void handleMMPriority1(MsgManagement*, MsgManagement*, PtpClock*); void handleMMPriority2(MsgManagement*, MsgManagement*, PtpClock*); void handleMMDomain(MsgManagement*, MsgManagement*, PtpClock*); void handleMMLogAnnounceInterval(MsgManagement*, MsgManagement*, PtpClock*); void handleMMAnnounceReceiptTimeout(MsgManagement*, MsgManagement*, PtpClock*); void handleMMLogSyncInterval(MsgManagement*, MsgManagement*, PtpClock*); void handleMMVersionNumber(MsgManagement*, MsgManagement*, PtpClock*); void handleMMEnablePort(MsgManagement*, MsgManagement*, PtpClock*); void handleMMDisablePort(MsgManagement*, MsgManagement*, PtpClock*); void handleMMTime(MsgManagement*, MsgManagement*, PtpClock*, RunTimeOpts*); void handleMMClockAccuracy(MsgManagement*, MsgManagement*, PtpClock*); void handleMMUtcProperties(MsgManagement*, MsgManagement*, PtpClock*); void handleMMTraceabilityProperties(MsgManagement*, MsgManagement*, PtpClock*); void handleMMDelayMechanism(MsgManagement*, MsgManagement*, PtpClock*); void handleMMLogMinPdelayReqInterval(MsgManagement*, MsgManagement*, PtpClock*); void handleMMErrorStatus(MsgManagement*); void handleErrorManagementMessage(MsgManagement *incoming, MsgManagement *outgoing, PtpClock *ptpClock, Enumeration16 mgmtId, Enumeration16 errorId); /** \}*/ /* * \brief Packing and Unpacking macros */ #define DECLARE_PACK( type ) void pack##type( void*, void* ); DECLARE_PACK( NibbleUpper ) DECLARE_PACK( Enumeration4Lower ) DECLARE_PACK( UInteger4Lower ) DECLARE_PACK( UInteger16 ) DECLARE_PACK( UInteger8 ) DECLARE_PACK( Octet ) DECLARE_PACK( Integer8 ) DECLARE_PACK( UInteger48 ) DECLARE_PACK( Integer64 ) #define DECLARE_UNPACK( type ) void unpack##type( void*, void*, PtpClock *ptpClock ); DECLARE_UNPACK( Boolean ) DECLARE_UNPACK( Enumeration4Lower ) DECLARE_UNPACK( Octet ) DECLARE_UNPACK( UInteger48 ) DECLARE_UNPACK( Integer64 ) /*Diplay functions usefull to debug */ void displayRunTimeOpts(const RunTimeOpts*); void displayDefault (const PtpClock*); void displayCurrent (const PtpClock*); void displayParent (const PtpClock*); void displayGlobal (const PtpClock*); void displayPort (const PtpClock*); void displayForeignMaster (const PtpClock*); void displayOthers (const PtpClock*); void displayBuffer (const PtpClock*); void displayPtpClock (const PtpClock*); void timeInternal_display(const TimeInternal*); void clockIdentity_display(const ClockIdentity); void netPath_display(const NetPath*); void intervalTimer_display(const IntervalTimer*); void integer64_display (const Integer64*); void timeInterval_display(const TimeInterval*); void portIdentity_display(const PortIdentity*); void clockQuality_display (const ClockQuality*); void PTPText_display(const PTPText*, const PtpClock*); void unicast_display(const Octet*); const char *portState_getName(Enumeration8 portState); void timestamp_display(const Timestamp * timestamp); void displayCounters(const PtpClock*); void displayStatistics(const PtpClock*); void clearCounters(PtpClock *); void msgHeader_display(const MsgHeader*); void msgAnnounce_display(const MsgAnnounce*); void msgSync_display(const MsgSync *sync); void msgFollowUp_display(const MsgFollowUp*); void msgPDelayReq_display(const MsgPDelayReq*); void msgDelayReq_display(const MsgDelayReq * req); void msgDelayResp_display(const MsgDelayResp * resp); void msgPDelayResp_display(const MsgPDelayResp * presp); void msgPDelayRespFollowUp_display(const MsgPDelayRespFollowUp * prespfollow); void msgManagement_display(const MsgManagement * manage); void mMSlaveOnly_display(const MMSlaveOnly*, const PtpClock*); void mMClockDescription_display(const MMClockDescription*, const PtpClock*); void mMUserDescription_display(const MMUserDescription*, const PtpClock*); void mMInitialize_display(const MMInitialize*, const PtpClock*); void mMDefaultDataSet_display(const MMDefaultDataSet*, const PtpClock*); void mMCurrentDataSet_display(const MMCurrentDataSet*, const PtpClock*); void mMParentDataSet_display(const MMParentDataSet*, const PtpClock*); void mMTimePropertiesDataSet_display(const MMTimePropertiesDataSet*, const PtpClock*); void mMPortDataSet_display(const MMPortDataSet*, const PtpClock*); void mMPriority1_display(const MMPriority1*, const PtpClock*); void mMPriority2_display(const MMPriority2*, const PtpClock*); void mMDomain_display(const MMDomain*, const PtpClock*); void mMLogAnnounceInterval_display(const MMLogAnnounceInterval*, const PtpClock*); void mMAnnounceReceiptTimeout_display(const MMAnnounceReceiptTimeout*, const PtpClock*); void mMLogSyncInterval_display(const MMLogSyncInterval*, const PtpClock*); void mMVersionNumber_display(const MMVersionNumber*, const PtpClock*); void mMTime_display(const MMTime*, const PtpClock*); void mMClockAccuracy_display(const MMClockAccuracy*, const PtpClock*); void mMUtcProperties_display(const MMUtcProperties*, const PtpClock*); void mMTraceabilityProperties_display(const MMTraceabilityProperties*, const PtpClock*); void mMDelayMechanism_display(const MMDelayMechanism*, const PtpClock*); void mMLogMinPdelayReqInterval_display(const MMLogMinPdelayReqInterval*, const PtpClock*); void mMErrorStatus_display(const MMErrorStatus*, const PtpClock*); void clearTime(TimeInternal *time); char *dump_TimeInternal(const TimeInternal * p); char *dump_TimeInternal2(const char *st1, const TimeInternal * p1, const char *st2, const TimeInternal * p2); int snprint_TimeInternal(char *s, int max_len, const TimeInternal * p); void nano_to_Time(TimeInternal *time, int nano); int gtTime(const TimeInternal *x, const TimeInternal *b); void absTime(TimeInternal *time); int is_Time_close(const TimeInternal *x, const TimeInternal *b, int nanos); int isTimeInternalNegative(const TimeInternal * p); double timeInternalToDouble(const TimeInternal * p); TimeInternal doubleToTimeInternal(const double d); void toState(UInteger8,RunTimeOpts*,PtpClock*); /* helper functions for leap second handling */ float secondsToMidnight(RunTimeOpts*); float getPauseAfterMidnight(Integer8 announceInterval); Boolean respectUtcOffset(RunTimeOpts * rtOpts, PtpClock * ptpClock); void ptpdBondarySyncTime(int threadNum); #endif /*PTPD_H_*/