diff options
author | Christopher S. Hall <christopher.s.hall@intel.com> | 2018-06-04 13:43:52 -0400 |
---|---|---|
committer | Christopher S. Hall <christopher.s.hall@intel.com> | 2018-06-12 10:54:27 -0400 |
commit | 87acb2c7a6423db8df70acdcd2404785b3198a74 (patch) | |
tree | dafacce2d09cc3369d2b62f0dc9475b1ee7cdfd7 | |
parent | 247413605cc4cda855ea89cc6b5c4168a247a91a (diff) | |
download | Open-AVB-87acb2c7a6423db8df70acdcd2404785b3198a74.tar.gz |
gptp: Add monotonic raw clock option
Timestamp clocks that implement the PTP_SYS_OFFSET_PRECISE ioctl return
cross-timestamps with respect to monotonic raw and realtime
Add configuration file option allowing clock selection for system/local
clock relation
The default clock type is Realtime which is equivalent to the
CLOCK_REALTIME option to clock_gettime
Optionally, MonotonicRaw (equivalent to CLOCK_MONOTONIC_RAW) can be
specified in the gPTP daemon configuration file:
[clock]
SystemClock = MonotonicRaw
Fixed Makefile issue where some shell configurations use built-in 'echo'
and others don't
Forces all to use /bin/echo
-rw-r--r-- | daemons/gptp/common/common_tstamper.hpp | 9 | ||||
-rw-r--r-- | daemons/gptp/common/gptp_cfg.cpp | 11 | ||||
-rw-r--r-- | daemons/gptp/common/gptp_cfg.hpp | 13 | ||||
-rw-r--r-- | daemons/gptp/gptp_cfg.ini | 8 | ||||
-rw-r--r-- | daemons/gptp/linux/build/Makefile | 4 | ||||
-rw-r--r-- | daemons/gptp/linux/src/daemon_cl.cpp | 14 | ||||
-rw-r--r-- | daemons/gptp/linux/src/linux_hal_generic.cpp | 103 | ||||
-rw-r--r-- | daemons/gptp/linux/src/linux_hal_generic.hpp | 14 |
8 files changed, 168 insertions, 8 deletions
diff --git a/daemons/gptp/common/common_tstamper.hpp b/daemons/gptp/common/common_tstamper.hpp index cfaf3abd..557ac184 100644 --- a/daemons/gptp/common/common_tstamper.hpp +++ b/daemons/gptp/common/common_tstamper.hpp @@ -73,6 +73,15 @@ public: } /** + * @brief Sets system clock descriptor + * @param system_clock_desc name of local clock + * @return false if unimplemented + */ + virtual bool HWTimestamper_setsystemclock + ( const char *system_clock_desc ) + { return false; } + + /** * @brief Adjusts the hardware clock frequency * @param frequency_offset Frequency offset * @return false diff --git a/daemons/gptp/common/gptp_cfg.cpp b/daemons/gptp/common/gptp_cfg.cpp index 8b9db0dc..943c639a 100644 --- a/daemons/gptp/common/gptp_cfg.cpp +++ b/daemons/gptp/common/gptp_cfg.cpp @@ -52,6 +52,7 @@ uint32_t findSpeedByName( const char *name, const char **end ); GptpIniParser::GptpIniParser(std::string filename) { + _config.systemClockDesc[0] = '\0'; _error = ini_parse(filename.c_str(), iniCallBack, this); } @@ -86,6 +87,16 @@ int GptpIniParser::iniCallBack(void *user, const char *section, const char *name } } } + else if( parseMatch(section, "clock") ) + { + if( parseMatch(name, "SystemClock") ) + { + valOK = true; + strncpy( parser->_config.systemClockDesc, value, + MAX_CLOCK_DESC_LEN ); + parser->_config.systemClockDesc[MAX_CLOCK_DESC_LEN] = '\0'; + } + } else if( parseMatch(section, "port") ) { if( parseMatch(name, "announceReceiptTimeout") ) diff --git a/daemons/gptp/common/gptp_cfg.hpp b/daemons/gptp/common/gptp_cfg.hpp index f283a4db..e8801daf 100644 --- a/daemons/gptp/common/gptp_cfg.hpp +++ b/daemons/gptp/common/gptp_cfg.hpp @@ -45,6 +45,7 @@ const uint32_t LINKSPEED_2_5G = 2500000; const uint32_t LINKSPEED_1G = 1000000; const uint32_t LINKSPEED_100MB = 100000; const uint32_t INVALID_LINKSPEED = UINT_MAX; +const uint8_t MAX_CLOCK_DESC_LEN = 64; /** * @brief Returns name given numeric link speed @@ -68,6 +69,9 @@ class GptpIniParser /*ptp data set*/ unsigned char priority1; + /* Clock data set */ + char systemClockDesc[MAX_CLOCK_DESC_LEN+1]; + /*port data set*/ unsigned int announceReceiptTimeout; unsigned int syncReceiptTimeout; @@ -93,6 +97,15 @@ class GptpIniParser */ int parserError(void); + /** + * @brief Read SystemClock description + * @return pointer to c-string representing system clock + */ + const char *getSystemClockDesc(void) + { + return _config.systemClockDesc; + } + /** * @brief Reads priority1 config value * @param void diff --git a/daemons/gptp/gptp_cfg.ini b/daemons/gptp/gptp_cfg.ini index ee593e9e..83387606 100644 --- a/daemons/gptp/gptp_cfg.ini +++ b/daemons/gptp/gptp_cfg.ini @@ -6,6 +6,14 @@ # The lower the number, the higher the priority for the BMCA. priority1 = 248 +# Clock option to specify system clock type +# Currently, Linux only. Options are MonotonicRaw and Realtime. +# Realtime works on all network interfaces. MonotonicRaw is available on +# interfaces that support it. + +#[clock] +#SystemClock = MonotonicRaw + [port] # TODO diff --git a/daemons/gptp/linux/build/Makefile b/daemons/gptp/linux/build/Makefile index 1e00b1a5..fa9441d7 100644 --- a/daemons/gptp/linux/build/Makefile +++ b/daemons/gptp/linux/build/Makefile @@ -39,8 +39,8 @@ CFLAGS_G = -Wall -g -I. -I../../common -I../src \ PRECISE_TIME_TEST = "\#include <linux/ptp_clock.h>\\n\ \#ifdef PTP_SYS_OFFSET_PRECISE\\nint main(){return 0;}\\n\#endif" -HAS_PRECISE_TIME = $(shell echo $(PRECISE_TIME_TEST) | $(CC) -xc - \ --I$(ALTERNATE_LINUX_INCPATH) -o /dev/null > /dev/null 2>&1 ; echo $$?) +HAS_PRECISE_TIME = $(shell /bin/echo -e $(PRECISE_TIME_TEST) | $(CC) -xc - \ +-I$(ALTERNATE_LINUX_INCPATH); echo $$?) ifeq ($(HAS_PRECISE_TIME),0) CFLAGS_G += -DPTP_HW_CROSSTSTAMP diff --git a/daemons/gptp/linux/src/daemon_cl.cpp b/daemons/gptp/linux/src/daemon_cl.cpp index 3a6d95e5..53a8f9a4 100644 --- a/daemons/gptp/linux/src/daemon_cl.cpp +++ b/daemons/gptp/linux/src/daemon_cl.cpp @@ -150,6 +150,7 @@ int main(int argc, char **argv) LinuxIPCArg *ipc_arg = NULL; bool use_config_file = false; char config_file_path[512]; + const char *systemClockDesc = NULL; memset(config_file_path, 0, 512); GPTPPersist *pGPTPPersist = NULL; @@ -424,6 +425,11 @@ int main(int argc, char **argv) portInit.syncReceiptThreshold = iniParser.getSyncReceiptThresh(); + if( strnlen( iniParser.getSystemClockDesc(), + MAX_CLOCK_DESC_LEN ) != 0 ) + systemClockDesc = + iniParser.getSystemClockDesc(); + /*Only overwrites phy_delay default values if not input_delay switch enabled*/ if(!input_delay) { @@ -433,6 +439,14 @@ int main(int argc, char **argv) } + if( systemClockDesc != NULL ) + { + if( timestamper->HWTimestamper_setsystemclock + ( systemClockDesc )) + GPTP_LOG_INFO + ( "Using system Clock: %s", systemClockDesc ); + } + pPort = new EtherPort(&portInit); if (!pPort->init_port()) { diff --git a/daemons/gptp/linux/src/linux_hal_generic.cpp b/daemons/gptp/linux/src/linux_hal_generic.cpp index 9eeba46f..2a462696 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.cpp +++ b/daemons/gptp/linux/src/linux_hal_generic.cpp @@ -34,6 +34,8 @@ #include <linux_hal_generic_tsprivate.hpp> #include <platform.hpp> #include <avbts_message.hpp> +#include <gptp_cfg.hpp> + #include <sys/select.h> #include <sys/socket.h> #include <netpacket/packet.h> @@ -194,6 +196,13 @@ int findPhcIndex( InterfaceLabel *iface_label ) { return info.phc_index; } +LinuxTimestamperGeneric::clock_map_t +LinuxTimestamperGeneric::system_clock_map[] = +{ + { CLOCK_REALTIME, "Realtime" }, + { CLOCK_MONOTONIC_RAW, "MonotonicRaw" } +}; + LinuxTimestamperGeneric::~LinuxTimestamperGeneric() { if( _private != NULL ) delete _private; #ifdef WITH_IGBLIB @@ -207,6 +216,22 @@ LinuxTimestamperGeneric::LinuxTimestamperGeneric() { igb_private = NULL; #endif sd = -1; + system_clockid = CLOCK_REALTIME; +} + +const char *LinuxTimestamperGeneric::getClockNameFromId( clockid_t clockid ) + const +{ + unsigned i; + + for( i = 0; i < sizeof(system_clock_map)/sizeof(system_clock_map[0]); + ++i ) + { + if( system_clock_map[i].clockid == clockid ) + return system_clock_map[i].clock_name; + } + + return NULL; } bool LinuxTimestamperGeneric::Adjust( void *tmx ) const { @@ -276,6 +301,32 @@ void LinuxTimestamperGeneric::HWTimestamper_reset() } } +bool LinuxTimestamperGeneric::HWTimestamper_setsystemclock +( const char *system_clock_desc ) +{ + unsigned i; + + if( system_clock_desc == NULL ) + return false; + + for( i = 0; i < sizeof(system_clock_map)/sizeof(system_clock_map[0]); + ++i ) + { + if( strncmp( system_clock_desc, system_clock_map[i].clock_name, + MAX_CLOCK_DESC_LEN ) == 0 ) + { + system_clockid = system_clock_map[i].clockid; + + return true; + } + } + + GPTP_LOG_ERROR + ( "Requested clock type: '%s' not found", system_clock_desc ); + + return false; +} + int LinuxTimestamperGeneric::HWTimestamper_txtimestamp ( PortIdentity *identity, PTPMessageId messageId, Timestamp ×tamp, unsigned &clock_value, bool last ) @@ -454,13 +505,33 @@ bool LinuxTimestamperGeneric::HWTimestamper_gettime { struct ptp_sys_offset_precise offset; memset( &offset, 0, sizeof(offset)); - if( ioctl( phc_fd, PTP_SYS_OFFSET_PRECISE, &offset ) == 0 ) + if( ioctl( phc_fd, PTP_SYS_OFFSET_PRECISE, &offset ) != 0 ) { - *device_time = pctTimestamp( &offset.device ); + GPTP_LOG_ERROR( "Read PHC Crosstime IOCTL failed" ); + + return false; + } + + *device_time = pctTimestamp( &offset.device ); + + if( system_clockid == CLOCK_REALTIME ) *system_time = pctTimestamp( &offset.sys_realtime ); + else if( system_clockid == CLOCK_MONOTONIC_RAW ) + *system_time = pctTimestamp( &offset.sys_monoraw ); - return true; + else + { + const char * clock_name = + getClockNameFromId( system_clockid ); + GPTP_LOG_ERROR( + "Requested clock type: '%s' not supported", + clock_name != NULL ? clock_name : "Unknown" + ); + + return false; } + + return true; } #endif @@ -474,7 +545,11 @@ bool LinuxTimestamperGeneric::HWTimestamper_gettime memset( &offset, 0, sizeof(offset)); offset.n_samples = PTP_MAX_SAMPLES; if( ioctl( phc_fd, PTP_SYS_OFFSET, &offset ) == -1 ) + { + GPTP_LOG_ERROR( "Read PHC Crosstime IOCTL failed" ); + return false; + } pct = &offset.ts[0]; for( i = 0; i < offset.n_samples; ++i ) { @@ -487,10 +562,26 @@ bool LinuxTimestamperGeneric::HWTimestamper_gettime } } - if (device_time_l) - *device_time = pctTimestamp( device_time_l ); - if (system_time_l) + if( !device_time_l || !system_time_l ) + { + GPTP_LOG_ERROR( "PHC Crosstime result is empty" ); + + return false; + } + + *device_time = pctTimestamp( device_time_l ); + + if( system_clockid == CLOCK_REALTIME ) *system_time = pctTimestamp( system_time_l ); + else + { + const char *clock_name = + getClockNameFromId( system_clockid ); + GPTP_LOG_ERROR( + "Requested clock type: '%s' not supported", + clock_name != NULL ? clock_name : "Unknown" + ); + } } return true; diff --git a/daemons/gptp/linux/src/linux_hal_generic.hpp b/daemons/gptp/linux/src/linux_hal_generic.hpp index 943294f4..76b09015 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.hpp +++ b/daemons/gptp/linux/src/linux_hal_generic.hpp @@ -67,11 +67,22 @@ private: #endif TicketingLock *net_lock; + clockid_t system_clockid; #ifdef WITH_IGBLIB LinuxTimestamperIGBPrivate_t igb_private; #endif + struct clock_map_t + { + clockid_t clockid; + const char *clock_name; + }; + + static clock_map_t system_clock_map[]; + + const char *getClockNameFromId( clockid_t clockid ) const; + public: /** * @brief Default constructor. Initializes internal variables @@ -108,6 +119,9 @@ public: */ virtual void HWTimestamper_reset(); + virtual bool HWTimestamper_setsystemclock + ( const char *system_clock_desc ); + /** * @brief Inserts a new timestamp to the beginning of the * RX timestamp list. |