summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher S. Hall <christopher.s.hall@intel.com>2018-06-04 13:43:52 -0400
committerChristopher S. Hall <christopher.s.hall@intel.com>2018-06-12 10:54:27 -0400
commit87acb2c7a6423db8df70acdcd2404785b3198a74 (patch)
treedafacce2d09cc3369d2b62f0dc9475b1ee7cdfd7
parent247413605cc4cda855ea89cc6b5c4168a247a91a (diff)
downloadOpen-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.hpp9
-rw-r--r--daemons/gptp/common/gptp_cfg.cpp11
-rw-r--r--daemons/gptp/common/gptp_cfg.hpp13
-rw-r--r--daemons/gptp/gptp_cfg.ini8
-rw-r--r--daemons/gptp/linux/build/Makefile4
-rw-r--r--daemons/gptp/linux/src/daemon_cl.cpp14
-rw-r--r--daemons/gptp/linux/src/linux_hal_generic.cpp103
-rw-r--r--daemons/gptp/linux/src/linux_hal_generic.hpp14
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 &timestamp,
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.