-INTRODUCTION
+Open AVB
+========
+maintainer: eric.mann AT intel.com
+
+Intel created the Open AVB repository to encourage collaborative source code
+development for AVB technology enabling. By publishing the source code, our
+intent is to encourage standardization, stability and inter-operability between
+multiple vendors. This repository - created by the Intel LAN Access Division -
+is open for contributions from other vendors. The repository contains primarily
+network building block components - drivers, libraries, example applications
+and daemon source code - required to build an AVB system. It is planned to
+eventually include the various packet encapsulation types, protocol discovery
+daemons, libraries to convert media clocks to AVB clocks (and vice
+versa), and drivers.
+
+This repository does not include all components required to build a full
+production AVB system (e.g. a turnkey solution to stream stored or live audio
+or video content). Some simple example applications are provided which
+illustrate the flow - but a professional AVB system requires a full media stack
+- including audio and video inputs and outputs, media processing elements, and
+various graphical user interfaces. Various companies provide such integrated
+solutions.
+
+LICENSING AND CONTRIBUTION GUIDELINES
+======================================
+To the extent possible, content is licensed under BSD licensing terms. Linux
+kernel mode components are provided under a GPLv2 license. The specific license
+information is included in the various directories to eliminate confusion. We
+encourage you to review the ‘LICENSE’ file included in the head of the
+various subdirectories for details.
+
+Third party submissions are welcomed. Our intent for third party content
+contributions is to enable derivative products with minimal licensing
+entanglements. Practically speaking, this means we would enforce (a) an
+original-source attestation for any contributed content, and (b) rejecting
+patches with GPL content into existing “BSD” licensed components. Third
+party copyrights can be included provided they do not narrow the licensing
+terms of an existing component.
+
+Prior to accepting a commit, Intel may perform scans using third-party tools
+to identify suspected hits of GPL code. Intel may also perform vulnerability
+scans of patches in an attempt to find various coding errors such as memory
+leaks, buffer overflows and usage of uninitialized variables. The submitter
+will be asked to correct any detected issues prior to a commit. Owners
+of submitted third-party content are free to apply changes without supervision
+by Intel.
+
+RELATED OPEN SOURCE PROJECTS
+============================
+
+AVDECC
+------
+Jeff Koftinoff maintains a repository of AVDECC example open
+source code. AVDECC is a management layer, similar to SNMP MIB formats,
+which enables remote devices to detect, enumerate and configure AVB-related
+devices based on their standardized management properties.
+
++ https://github.com/jdkoftinoff/avdecc
++ https://github.com/jdkoftinoff/avdecc-examples
+
+XMOS
+----
+XMOS is a semiconductor company providing a reference design for AVB
+endpoints in pro audio and automotive. Our source code is open source
+and available on Github - https://github.com/xcore/sw_avb
-This component demonstrates various features of the Intel I210 Ethernet controller.
-These features can be used for developing Audio/Video Bridging applications,
-Industrial Ethernet applications which require precise timing control over frame
-transmission, or test harnesses for measuring system latencies and sampling events.
-
-This component - igb_avb - is limited to the Intel I210 Ethernet controller. The kernel
-module can be loaded in parallel to existing in-kernel igb modules which may be
-used on other supported Intel LAN controllers. Modifications are required to
-the in-kernel drivers if the existing in-kernel igb driver has support for the Intel I210.
-
-BUILDING
-
-There are four primary components - kmod (for the kernel-mode igb_avb driver),
-lib (for the user-mode driver library), examples (for test applications), and
-daemons (at present an MRP daemon required for establishing AVB streams).
-
-To build, 'cd' into each of the respective directories, and execute 'make'.
-
-The kernel igb module can be built which supports the latest Linux kernel
-3.x PTP clock support - to enable, modify kmod/Makefile and enable -DCONFIG_PTP
-as a build option (e.g. EXTRA_CFLAGS += -DCONFIG_PTP).
-
-The example application uses the pciutils library - the latest version
-can be downloaded from < ftp://ftp.kernel.org/pub/software/utils/pciutils/ >.
-Download and extract the library, and run 'make;make install;make install-lib'.
-
-RUNNING
-
-To install the kernel mode driver, you must have root permissions. Typically,
-the driver is loaded by:
- <optional> sudo modprobe dca
- <optional> sudo modprobe ptp
- sudo insmod ./igb_avb.ko
-
-As 3.4 and later kernels include support for the I210, you may need to 'rmmod igb'
-before loading the igb_avb module.
-
-Note that packets generated from the 'user-mode' libraries are not counted in
-ifconfig output, and likewise, if generating multicast traffic, the receiving
-node must be registered to receive the traffic (or run the interface in promiscious
-mode).
-
-TIME SYNC
-
-This package relies on using the linuxptp daemon to establish time
-synchronization. The latest source for this is available here:
-
- git clone git://git.code.sf.net/p/linuxptp/code linuxptp-code
-
-Type 'make' to build. This version has been tested with kernel 3.5.1.
-Assuming kernel support is enabled, simply 'modprobe ptp' to load the
-required kernel mode components. Example command line to the daemon is:
-
- ptp4l -f gPTP.cfg -2 -P -i p11p1
-
-Note the default gPTP.cfg file queries and times out relatively fast while
-awaiting the transmit timestamps to complete. To adjust this, modify the
-'tx_timestamp_retries' parameter to 400 (which roughly corresponds to 400 usec).
-
-EXAMPLE APPLICATIONS
-
-The test application - which simply streams timed packets - requires root permissions
-as well to execute and attach to the driver.
- sudo ./test
-
-To exit the test app, hit Ctrl-C. The application gracefully tears down
-the connection to the driver. If the application unexpectedly aborts the
-kernel-mode driver also reclaims the various buffers and attempts to clean up.
-The application should be able to re-initialize and use the transmit queues
-without restarting the driver.
-
-The 'simple_talker' application illustrates the various steps to publish a stream
-and being streaming after a listener connects.
-
-MRPD DAEMON
-
-The MRP daemon is required to establish stream reservations with compatible AVB
-infrastructure devices. The command line selectively enables MMRP (via the -m option),
-MVRP (via the -v option), and MSRP (via the -s option). You must also specify the
-interface on which you want to bind the daemon to (e.g. -i eth2). The full command line
-typically appears as follows:
- sudo ./mrpd -mvs -i eth2
-
-Sample client applications - mrpctl, mrpq, mrpl - illustrates how to connect, query
-and add attributes to the MRP daemon.
--- /dev/null
+/avbts_clock.hpp/1.1/Fri Sep 21 15:48:06 2012//
+/avbts_message.hpp/1.1/Fri Sep 7 19:02:51 2012//
+/avbts_oscondition.hpp/1.1/Fri Sep 21 20:14:21 2012//
+/avbts_osipc.hpp/1.1/Fri Sep 7 19:03:47 2012//
+/avbts_oslock.hpp/1.1/Fri Sep 7 19:03:59 2012//
+/avbts_osnet.cpp/1.1/Fri Sep 7 19:02:51 2012//
+/avbts_osnet.hpp/1.1/Fri Sep 21 20:12:53 2012//
+/avbts_osthread.hpp/1.1/Fri Sep 7 19:04:20 2012//
+/avbts_ostimer.hpp/1.1/Fri Sep 7 19:04:50 2012//
+/avbts_ostimerq.hpp/1.1/Fri Sep 7 19:02:51 2012//
+/avbts_port.hpp/1.1/Fri Sep 21 20:11:27 2012//
+/ieee1588.hpp/1.1/Fri Sep 21 15:56:15 2012//
+/ieee1588clock.cpp/1.1/Fri Sep 21 15:57:08 2012//
+/ieee1588port.cpp/1.1/Fri Sep 21 20:05:48 2012//
+/ptp_message.cpp/1.1/Fri Sep 21 18:27:54 2012//
+D
--- /dev/null
+linux_igb_avb/daemons/gptp/common
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+/******************************************************************************
+
+ 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_CLOCK_HPP
+#define AVBTS_CLOCK_HPP
+
+#include <stdint.h>
+#include <ieee1588.hpp>
+#include <avbts_port.hpp>
+#include <avbts_ostimerq.hpp>
+#include <avbts_osipc.hpp>
+
+#define EVENT_TIMER_GRANULARITY 5000000
+
+struct ClockQuality {
+ unsigned char cq_class;
+ unsigned char clockAccuracy;
+ int16_t offsetScaledLogVariance;
+};
+
+class IEEE1588Clock {
+ private:
+ ClockIdentity clock_identity;
+ ClockQuality clock_quality;
+ unsigned char priority1;
+ unsigned char priority2;
+ bool initializable;
+ bool is_boundary_clock;
+ bool two_step_clock;
+ unsigned char domain_number;
+ uint16_t number_ports;
+ uint16_t number_foreign_records;
+ bool slave_only;
+ int16_t current_utc_offset;
+ bool leap_59;
+ bool leap_61;
+ uint16_t epoch_number;
+ uint16_t steps_removed;
+ int64_t offset_from_master;
+ Timestamp one_way_delay;
+ PortIdentity parent_identity;
+ PortIdentity grandmaster_port_identity;
+ ClockQuality grandmaster_clock_quality;
+ unsigned char grandmaster_priority1;
+ unsigned char grandmaster_priority2;
+ bool grandmaster_is_boundary_clock;
+ uint8_t time_source;
+
+ int32_t master_local_offset_125us_offset;
+ uint64_t master_local_offset_nrst125us_initial;
+ bool master_local_offset_nrst125us_initialized;
+
+ ClockIdentity LastEBestIdentity;
+
+ IEEE1588Port *port_list[MAX_PORTS];
+
+ static Timestamp start_time;
+ Timestamp last_sync_time;
+
+ OS_IPC *ipc;
+
+ OSTimerQueue *timerq;
+
+ bool forceOrdinarySlave;
+ public:
+ IEEE1588Clock(bool forceOrdinarySlave,
+ OSTimerQueueFactory * timerq_factory, OS_IPC * ipc);
+ ~IEEE1588Clock(void);
+
+ Timestamp getTime(void);
+ Timestamp getPreciseTime(void);
+
+ bool isBetterThan(PTPMessageAnnounce * msg);
+
+ ClockIdentity getLastEBestIdentity( void ) {
+ return LastEBestIdentity;
+ }
+ void setLastEBestIdentity( ClockIdentity id ) {
+ LastEBestIdentity = id;
+ return;
+ }
+
+ void setClockIdentity(char *id) {
+ clock_identity.set((uint8_t *) id);
+ }
+ void setClockIdentity(LinkLayerAddress * addr) {
+ clock_identity.set(addr);
+ }
+
+ unsigned char getDomain(void) {
+ return domain_number;
+ }
+
+ PortIdentity getGrandmasterPortIdentity(void) {
+ return grandmaster_port_identity;
+ }
+ void setGrandmasterPortIdentity(PortIdentity id) {
+ grandmaster_port_identity = id;
+ }
+
+ ClockQuality getGrandmasterClockQuality(void) {
+ return grandmaster_clock_quality;
+ }
+
+ ClockQuality getClockQuality(void) {
+ return clock_quality;
+ }
+
+ unsigned char getGrandmasterPriority1(void) {
+ return grandmaster_priority1;
+ }
+
+ unsigned char getGrandmasterPriority2(void) {
+ return grandmaster_priority2;
+ }
+
+ uint16_t getMasterStepsRemoved(void) {
+ return steps_removed;
+ }
+
+ uint16_t getCurrentUtcOffset(void) {
+ return current_utc_offset;
+ }
+
+ uint8_t getTimeSource(void) {
+ return time_source;
+ }
+
+ void getGrandmasterIdentity(char *id);
+
+ unsigned char getPriority1(void) {
+ return priority1;
+ }
+
+ unsigned char getPriority2(void) {
+ return priority2;
+ }
+ uint16_t getNextPortId(void) {
+ return (number_ports++ % (MAX_PORTS + 1)) + 1;
+ }
+ void registerPort(IEEE1588Port * port, uint16_t index) {
+ if (index < MAX_PORTS) {
+ port_list[index - 1] = port;
+ }
+ ++number_ports;
+ }
+ void getPortList(int &count, IEEE1588Port ** &ports) {
+ ports = this->port_list;
+ count = number_ports;
+ return;
+ }
+
+ static Timestamp getSystemTime(void);
+
+ void addEventTimer(IEEE1588Port * target, Event e,
+ unsigned long long time_ns);
+ void deleteEventTimer(IEEE1588Port * target, Event e);
+
+#define SHM_SIZE 2*sizeof( int64_t ) \
+ + 2*(sizeof( last_sync_time.seconds_ms ) + sizeof( last_sync_time.seconds_ls ) + sizeof( last_sync_time.nanoseconds )) \
+ + 4*sizeof(uint32_t) + sizeof( uint16_t )
+
+ void setMasterOffset(int64_t master_local_offset, Timestamp local_time,
+ int32_t master_local_freq_offset,
+ int64_t local_system_offset, Timestamp system_time,
+ int32_t local_system_freq_offset,
+ uint32_t nominal_clock_rate, uint32_t local_clock);
+
+ ClockIdentity getClockIdentity() {
+ return clock_identity;
+ }
+
+ friend void tick_handler(int sig);
+};
+
+void tick_handler(int sig);
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_MESSAGE_HPP
+#define AVBTS_MESSAGE_HPP
+
+#include <stdint.h>
+#include <avbts_osnet.hpp>
+#include <ieee1588.hpp>
+
+#define PTP_CODE_STRING_LENGTH 4
+#define PTP_SUBDOMAIN_NAME_LENGTH 16
+#define PTP_FLAGS_LENGTH 2
+
+#define GPTP_VERSION 2
+#define PTP_NETWORK_VERSION 1
+
+#define PTP_ETHER 1
+#define PTP_DEFAULT 255
+
+#define PTP_COMMON_HDR_OFFSET 0
+#define PTP_COMMON_HDR_LENGTH 34
+#define PTP_COMMON_HDR_TRANSSPEC_MSGTYPE(x) x
+#define PTP_COMMON_HDR_PTP_VERSION(x) x+1
+#define PTP_COMMON_HDR_MSG_LENGTH(x) x+2
+#define PTP_COMMON_HDR_DOMAIN_NUMBER(x) x+4
+#define PTP_COMMON_HDR_FLAGS(x) x+6
+#define PTP_COMMON_HDR_CORRECTION(x) x+8
+#define PTP_COMMON_HDR_SOURCE_CLOCK_ID(x) x+20
+#define PTP_COMMON_HDR_SOURCE_PORT_ID(x) x+28
+#define PTP_COMMON_HDR_SEQUENCE_ID(x) x+30
+#define PTP_COMMON_HDR_CONTROL(x) x+32
+#define PTP_COMMON_HDR_LOG_MSG_INTRVL(x) x+33
+
+#define PTP_ANNOUNCE_OFFSET 34
+#define PTP_ANNOUNCE_LENGTH 30
+#define PTP_ANNOUNCE_CURRENT_UTC_OFFSET(x) x+10
+#define PTP_ANNOUNCE_GRANDMASTER_PRIORITY1(x) x+13
+#define PTP_ANNOUNCE_GRANDMASTER_CLOCK_QUALITY(x) x+14
+#define PTP_ANNOUNCE_GRANDMASTER_PRIORITY2(x) x+18
+#define PTP_ANNOUNCE_GRANDMASTER_IDENTITY(x) x+19
+#define PTP_ANNOUNCE_STEPS_REMOVED(x) x+27
+#define PTP_ANNOUNCE_TIME_SOURCE(x) x+29
+
+#define PTP_SYNC_OFFSET 34
+#define PTP_SYNC_LENGTH 10
+#define PTP_SYNC_SEC_MS(x) x
+#define PTP_SYNC_SEC_LS(x) x+2
+#define PTP_SYNC_NSEC(x) x+6
+
+#define PTP_FOLLOWUP_OFFSET 34
+#define PTP_FOLLOWUP_LENGTH 10
+#define PTP_FOLLOWUP_SEC_MS(x) x
+#define PTP_FOLLOWUP_SEC_LS(x) x+2
+#define PTP_FOLLOWUP_NSEC(x) x+6
+
+#define PTP_PDELAY_REQ_OFFSET 34
+#define PTP_PDELAY_REQ_LENGTH 20
+#define PTP_PDELAY_REQ_SEC_MS(x) x
+#define PTP_PDELAY_REQ_SEC_LS(x) x+2
+#define PTP_PDELAY_REQ_NSEC(x) x+6
+
+#define PTP_PDELAY_RESP_OFFSET 34
+#define PTP_PDELAY_RESP_LENGTH 20
+#define PTP_PDELAY_RESP_SEC_MS(x) x
+#define PTP_PDELAY_RESP_SEC_LS(x) x+2
+#define PTP_PDELAY_RESP_NSEC(x) x+6
+#define PTP_PDELAY_RESP_REQ_CLOCK_ID(x) x+10
+#define PTP_PDELAY_RESP_REQ_PORT_ID(x) x+18
+
+#define PTP_PDELAY_FOLLOWUP_OFFSET 34
+#define PTP_PDELAY_FOLLOWUP_LENGTH 20
+#define PTP_PDELAY_FOLLOWUP_SEC_MS(x) x
+#define PTP_PDELAY_FOLLOWUP_SEC_LS(x) x+2
+#define PTP_PDELAY_FOLLOWUP_NSEC(x) x+6
+#define PTP_PDELAY_FOLLOWUP_REQ_CLOCK_ID(x) x+10
+#define PTP_PDELAY_FOLLOWUP_REQ_PORT_ID(x) x+18
+
+#define PTP_LI_61_BYTE 0
+#define PTP_LI_61_BIT 0
+#define PTP_LI_59_BYTE 0
+#define PTP_LI_59_BIT 1
+#define PTP_ASSIST_BYTE 0
+#define PTP_ASSIST_BIT 1
+
+enum MessageType {
+ SYNC_MESSAGE = 0,
+ DELAY_REQ_MESSAGE = 1,
+ PATH_DELAY_REQ_MESSAGE = 2,
+ PATH_DELAY_RESP_MESSAGE = 3,
+ FOLLOWUP_MESSAGE = 8,
+ DELAY_RESP_MESSAGE = 9,
+ PATH_DELAY_FOLLOWUP_MESSAGE = 0xA,
+ ANNOUNCE_MESSAGE = 0xB,
+ SIGNALLING_MESSAGE = 0xC,
+ MANAGEMENT_MESSAGE = 0xD,
+};
+
+enum LegacyMessageType {
+ SYNC,
+ DELAY_REQ,
+ FOLLOWUP,
+ DELAY_RESP,
+ MANAGEMENT,
+ MESSAGE_OTHER
+};
+
+enum MulticastType {
+ MCAST_NONE,
+ MCAST_PDELAY,
+ MCAST_OTHER
+};
+
+class PTPMessageCommon {
+ protected:
+ unsigned char versionPTP;
+ uint16_t versionNetwork;
+ MessageType messageType;
+
+ PortIdentity *sourcePortIdentity;
+
+ uint16_t sequenceId;
+ LegacyMessageType control;
+ unsigned char flags[2];
+
+ uint16_t messageLength;
+ char logMeanMessageInterval;
+ long long correctionField;
+ unsigned char domainNumber;
+
+ Timestamp _timestamp;
+ unsigned _timestamp_counter_value;
+ bool _gc;
+
+ PTPMessageCommon(void) {
+ };
+ public:
+ PTPMessageCommon(IEEE1588Port * port);
+ virtual ~ PTPMessageCommon(void);
+
+ unsigned char *getFlags(void) {
+ return flags;
+ }
+
+ uint16_t getSequenceId(void) {
+ return sequenceId;
+ }
+ void setSequenceId(uint16_t seq) {
+ sequenceId = seq;
+ }
+
+ MessageType getMessageType(void) {
+ return messageType;
+ }
+
+ long long getCorrectionField(void) {
+ return correctionField;
+ }
+ void setCorrectionField(long long correctionAmount) {
+ correctionField = correctionAmount;
+ }
+
+ void getPortIdentity(PortIdentity * identity);
+ void setPortIdentity(PortIdentity * identity);
+
+ Timestamp getTimestamp(void) {
+ return _timestamp;
+ }
+ uint32_t getTimestampCounterValue(void) {
+ return _timestamp_counter_value;;
+ }
+ void setTimestamp(Timestamp & timestamp) {
+ _timestamp = timestamp;
+ }
+
+ bool garbage() {
+ return _gc;
+ }
+
+ bool isSenderEqual(PortIdentity portIdentity);
+
+ virtual void processMessage(IEEE1588Port * port);
+
+ void buildCommonHeader(uint8_t * buf);
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+#pragma pack(push,1)
+
+class PathTraceTLV {
+ private:
+ uint16_t tlvType;
+ uint16_t lengthField;
+ ClockIdentity identity;
+ public:
+ PathTraceTLV() {
+ tlvType = PLAT_htons(0x8);
+ lengthField = PLAT_htons(sizeof(identity));
+ }
+ void setClockIdentity(ClockIdentity * id) {
+ identity = *id;
+ }
+ void toByteString(uint8_t * byte_str) {
+ memcpy(byte_str, this, sizeof(*this));
+ }
+};
+
+#pragma pack(pop)
+
+class PTPMessageAnnounce:public PTPMessageCommon {
+ private:
+ char grandmasterIdentity[PTP_CLOCK_IDENTITY_LENGTH];
+
+ PathTraceTLV tlv;
+
+ uint16_t currentUtcOffset;
+ unsigned char grandmasterPriority1;
+ unsigned char grandmasterPriority2;
+ ClockQuality *clockQuality;
+ uint16_t stepsRemoved;
+ unsigned char timeSource;
+
+ PTPMessageAnnounce(void);
+ public:
+ PTPMessageAnnounce(IEEE1588Port * port);
+ ~PTPMessageAnnounce();
+
+ bool isBetterThan(PTPMessageAnnounce * msg);
+
+ unsigned char getGrandmasterPriority1(void) {
+ return grandmasterPriority1;
+ }
+ unsigned char getGrandmasterPriority2(void) {
+ return grandmasterPriority2;
+ }
+
+ ClockQuality *getGrandmasterClockQuality(void) {
+ return clockQuality;
+ }
+
+ uint16_t getStepsRemoved(void) {
+ return stepsRemoved;
+ }
+
+ void getGrandmasterIdentity(char *identity) {
+ memcpy(identity, grandmasterIdentity,
+ PTP_CLOCK_IDENTITY_LENGTH);
+ }
+
+ void processMessage(IEEE1588Port * port);
+
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+class PTPMessageSync:public PTPMessageCommon {
+ private:
+ Timestamp originTimestamp;
+
+ PTPMessageSync() {
+ return;
+ }
+ public:
+ PTPMessageSync(IEEE1588Port * port);
+ void processMessage(IEEE1588Port * port);
+
+ Timestamp getOriginTimestamp(void) {
+ return originTimestamp;
+ }
+
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+#pragma pack(push,1)
+
+class scaledNs {
+ private:
+ int32_t ms;
+ uint64_t ls;
+ public:
+ scaledNs() {
+ ms = 0;
+ ls = 0;
+ } void toByteString(uint8_t * byte_str) {
+ memcpy(byte_str, this, sizeof(*this));
+ }
+};
+
+class FollowUpTLV {
+ private:
+ uint16_t tlvType;
+ uint16_t lengthField;
+ uint8_t organizationId[3];
+ uint8_t organizationSubType_ms;
+ uint16_t organizationSubType_ls;
+ int32_t cumulativeScaledRateOffset;
+ uint16_t gmTimeBaseIndicator;
+ scaledNs scaledLastGmPhaseChange;
+ int32_t scaledLastGmFreqChange;
+ public:
+ FollowUpTLV() {
+ tlvType = PLAT_htons(0x3);
+ lengthField = PLAT_htons(28);
+ organizationId[0] = '\x00';
+ organizationId[1] = '\x80';
+ organizationId[2] = '\xC2';
+ organizationSubType_ms = 0;
+ organizationSubType_ls = PLAT_htons(1);
+ cumulativeScaledRateOffset = PLAT_htonl(0);
+ gmTimeBaseIndicator = PLAT_htons(0);
+ scaledLastGmFreqChange = PLAT_htonl(0);
+ }
+ void toByteString(uint8_t * byte_str) {
+ memcpy(byte_str, this, sizeof(*this));
+ }
+};
+
+#pragma pack(pop)
+
+class PTPMessageFollowUp:public PTPMessageCommon {
+ private:
+ Timestamp preciseOriginTimestamp;
+
+ FollowUpTLV tlv;
+
+ PTPMessageFollowUp(void) {
+ } public:
+ PTPMessageFollowUp(IEEE1588Port * port);
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+ void processMessage(IEEE1588Port * port);
+
+ Timestamp getPreciseOriginTimestamp(void) {
+ return preciseOriginTimestamp;
+ }
+ void setPreciseOriginTimestamp(Timestamp & timestamp) {
+ preciseOriginTimestamp = timestamp;
+ }
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+class PTPMessagePathDelayReq:public PTPMessageCommon {
+ private:
+ Timestamp originTimestamp;
+
+ PTPMessagePathDelayReq() {
+ return;
+ }
+ public:
+ PTPMessagePathDelayReq(IEEE1588Port * port);
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+ void processMessage(IEEE1588Port * port);
+
+ Timestamp getOriginTimestamp(void) {
+ return originTimestamp;
+ }
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+class PTPMessagePathDelayResp:public PTPMessageCommon {
+ private:
+ PortIdentity * requestingPortIdentity;
+ Timestamp requestReceiptTimestamp;
+
+ PTPMessagePathDelayResp(void) {
+ } public:
+ ~PTPMessagePathDelayResp();
+ PTPMessagePathDelayResp(IEEE1588Port * port);
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+ void processMessage(IEEE1588Port * port);
+
+ void setRequestReceiptTimestamp(Timestamp timestamp) {
+ requestReceiptTimestamp = timestamp;
+ }
+
+ void setRequestingPortIdentity(PortIdentity * identity);
+ void getRequestingPortIdentity(PortIdentity * identity);
+
+ Timestamp getRequestReceiptTimestamp(void) {
+ return requestReceiptTimestamp;
+ }
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+class PTPMessagePathDelayRespFollowUp:public PTPMessageCommon {
+ private:
+ Timestamp responseOriginTimestamp;
+ PortIdentity *requestingPortIdentity;
+
+ PTPMessagePathDelayRespFollowUp(void) {
+ } public:
+ PTPMessagePathDelayRespFollowUp(IEEE1588Port * port);
+ ~PTPMessagePathDelayRespFollowUp();
+ void sendPort(IEEE1588Port * port, PortIdentity * destIdentity);
+ void processMessage(IEEE1588Port * port);
+
+ void setResponseOriginTimestamp(Timestamp timestamp) {
+ responseOriginTimestamp = timestamp;
+ }
+ void setRequestingPortIdentity(PortIdentity * identity);
+
+ Timestamp getResponseOriginTimestamp(void) {
+ return responseOriginTimestamp;
+ }
+ PortIdentity *getRequestingPortIdentity(void) {
+ return requestingPortIdentity;
+ }
+
+ friend PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+};
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_OSSIGNAL_HPP
+#define AVBTS_OSSIGNAL_HPP
+ class OSCondition {
+private:
+ int wait_count;
+public:
+ virtual bool wait() = 0;
+ virtual bool wait_prelock() = 0;
+ virtual bool signal() = 0;
+protected:
+ OSCondition() {
+ wait_count = 0;
+ };
+ void up() {
+ ++wait_count;
+ }
+ void down() {
+ --wait_count;
+ }
+ bool waiting() {
+ return wait_count > 0;
+ }
+};
+
+ class OSConditionFactory {
+ public:virtual OSCondition * createCondition() = 0;
+};
+
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_OSIPC_HPP
+#define AVBTS_OSIPC_HPP
+ class OS_IPC {
+ public:virtual bool init() = 0;
+ virtual bool update(int64_t ml_phoffset, int64_t ls_phoffset,
+ int32_t ml_freqoffset, int32_t ls_freq_offset,
+ uint64_t local_time) = 0;
+};
+
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ Copyright (c) 2001-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_OSLOCK_HPP
+#define AVBTS_OSLOCK_HPP
+ typedef enum { oslock_recursive, oslock_nonrecursive } OSLockType;
+typedef enum { oslock_ok, oslock_self, oslock_held, oslock_fail } OSLockResult;
+ class OSLock {
+ public:virtual OSLockResult lock() = 0;
+ virtual OSLockResult unlock() = 0;
+ virtual OSLockResult trylock() = 0;
+ protected:OSLock() {
+ };
+ bool initialize(OSLockType type) {
+ return false;
+ };
+};
+
+ class OSLockFactory {
+ public:virtual OSLock * createLock(OSLockType type) = 0;
+};
+
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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 <avbts_osnet.hpp>
+
+std::map < factory_name_t,
+ OSNetworkInterfaceFactory * >OSNetworkInterfaceFactory::factoryMap;
--- /dev/null
+/******************************************************************************
+
+ 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_OSNET_HPP
+#define AVBTS_OSNET_HPP
+
+#include <stdint.h>
+#include <string.h>
+#include <map>
+#include <ieee1588.hpp>
+
+#define FACTORY_NAME_LENGTH 48
+#define ETHER_ADDR_OCTETS 6
+#define PTP_ETHERTYPE 0x88F7
+#define DEFAULT_TIMEOUT 1 // milliseconds
+
+class LinkLayerAddress:public InterfaceLabel {
+ private:
+ uint8_t addr[ETHER_ADDR_OCTETS];
+ public:
+ LinkLayerAddress() {
+ };
+ LinkLayerAddress(uint64_t address_scalar) {
+ uint8_t *ptr;
+ address_scalar <<= 16;
+ for (ptr = addr; ptr < addr + ETHER_ADDR_OCTETS; ++ptr) {
+ *ptr = (address_scalar & 0xFF00000000000000ULL) >> 56;
+ address_scalar <<= 8;
+ }
+ }
+ LinkLayerAddress(uint8_t * address_octet_array) {
+ uint8_t *ptr;
+ for (ptr = addr; ptr < addr + ETHER_ADDR_OCTETS;
+ ++ptr, ++address_octet_array) {
+ *ptr = *address_octet_array;
+ }
+ }
+ bool operator==(const LinkLayerAddress & cmp) const {
+ return memcmp(this->addr, cmp.addr,
+ ETHER_ADDR_OCTETS) == 0 ? true : false;
+ }
+ bool operator<(const LinkLayerAddress & cmp)const {
+ return memcmp(this->addr, cmp.addr,
+ ETHER_ADDR_OCTETS) < 0 ? true : false;
+ }
+ bool operator>(const LinkLayerAddress & cmp)const {
+ return memcmp(this->addr, cmp.addr,
+ ETHER_ADDR_OCTETS) < 0 ? true : false;
+ }
+ void toOctetArray(uint8_t * address_octet_array) {
+ uint8_t *ptr;
+ for (ptr = addr; ptr < addr + ETHER_ADDR_OCTETS;
+ ++ptr, ++address_octet_array) {
+ *address_octet_array = *ptr;
+ }
+ }
+};
+
+class InterfaceName:public InterfaceLabel {
+ private:
+ char *name;
+ public:
+ InterfaceName() {
+ };
+ InterfaceName(char *name, int length) {
+ this->name = new char[length + 1];
+ PLAT_strncpy(this->name, name, length);
+ }
+ bool operator==(const InterfaceName & cmp) const {
+ return strcmp(name, cmp.name) == 0 ? true : false;
+ }
+ bool operator<(const InterfaceName & cmp)const {
+ return strcmp(name, cmp.name) < 0 ? true : false;
+ }
+ bool operator>(const InterfaceName & cmp)const {
+ return strcmp(name, cmp.name) < 0 ? true : false;
+ }
+ bool toString(char *string, size_t length) {
+ if (length >= strlen(name) + 1) {
+ PLAT_strncpy(string, name, length);
+ return true;
+ }
+ return false;
+ }
+};
+
+class factory_name_t {
+ private:
+ char name[FACTORY_NAME_LENGTH];
+ factory_name_t();
+ public:
+ factory_name_t(const char *name_a) {
+ PLAT_strncpy(name, name_a, FACTORY_NAME_LENGTH - 1);
+ }
+ bool operator==(const factory_name_t & cmp) {
+ return strcmp(cmp.name, this->name) == 0 ? true : false;
+ }
+ bool operator<(const factory_name_t & cmp)const {
+ return strcmp(cmp.name, this->name) < 0 ? true : false;
+ }
+ bool operator>(const factory_name_t & cmp)const {
+ return strcmp(cmp.name, this->name) > 0 ? true : false;
+ }
+};
+
+typedef enum { net_trfail, net_fatal, net_succeed } net_result;
+
+class OSNetworkInterface {
+ public:
+ virtual net_result send(LinkLayerAddress * addr, uint8_t * payload,
+ size_t length, bool timestamp) = 0;
+ virtual net_result recv(LinkLayerAddress * addr, uint8_t * payload,
+ size_t & length) = 0;
+ virtual void getLinkLayerAddress(LinkLayerAddress * addr) = 0;
+ virtual unsigned getPayloadOffset() = 0;
+};
+
+class OSNetworkInterfaceFactory;
+
+typedef std::map < factory_name_t, OSNetworkInterfaceFactory * >FactoryMap_t;
+
+class OSNetworkInterfaceFactory {
+ public:
+ static bool registerFactory(factory_name_t id,
+ OSNetworkInterfaceFactory * factory) {
+ FactoryMap_t::iterator iter = factoryMap.find(id);
+ if (iter != factoryMap.end())
+ return false;
+ factoryMap[id] = factory;
+ return true;
+ }
+ static bool buildInterface(OSNetworkInterface ** iface,
+ factory_name_t id,
+ InterfaceLabel * iflabel,
+ HWTimestamper * timestamper) {
+ return factoryMap[id]->createInterface(iface, iflabel,
+ timestamper);
+ }
+ private:
+ virtual bool createInterface(OSNetworkInterface ** iface,
+ InterfaceLabel * iflabel,
+ HWTimestamper * timestamper) = 0;
+ static FactoryMap_t factoryMap;
+};
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_OSTHREAD_HPP
+#define AVBTS_OSTHREAD_HPP
+ typedef enum { osthread_ok, osthread_error } OSThreadExitCode;
+typedef OSThreadExitCode(*OSThreadFunction) (void *);
+ class OSThread {
+ public:virtual bool start(OSThreadFunction function, void *arg) = 0;
+ virtual bool join(OSThreadExitCode & exit_code) = 0;
+};
+
+ class OSThreadFactory {
+ public:virtual OSThread * createThread() = 0;
+};
+
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_OSTIMER_HPP
+#define AVBTS_OSTIMER_HPP
+
+class OSTimer {
+ public:virtual unsigned long sleep(unsigned long micro) = 0;
+};
+
+class OSTimerFactory {
+ public:virtual OSTimer * createTimer() = 0;
+};
+
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_OSTIMERQ_HPP
+#define AVBTS_OSTIMERQ_HPP
+
+typedef void (*ostimerq_handler) (void *);
+
+class OSTimerQueue {
+ public:
+ virtual bool addEvent(unsigned long micros, int type,
+ ostimerq_handler func, event_descriptor_t * arg,
+ bool dynamic, unsigned *event) = 0;
+ virtual bool cancelEvent(int type, unsigned *event) = 0;
+};
+
+class OSTimerQueueFactory {
+ public:
+ virtual OSTimerQueue * createOSTimerQueue() = 0;
+};
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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 <avbts_ostimer.hpp>
+#include <avbts_oslock.hpp>
+#include <avbts_osnet.hpp>
+#include <avbts_osthread.hpp>
+#include <avbts_oscondition.hpp>
+
+#include <stdint.h>
+
+#include <map>
+#include <list>
+
+#define GPTP_MULTICAST 0x0180C200000EULL
+#define PDELAY_MULTICAST GPTP_MULTICAST
+#define OTHER_MULTICAST GPTP_MULTICAST
+
+#define PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER 3
+#define SYNC_RECEIPT_TIMEOUT_MULTIPLIER 10
+#define ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER 10
+
+typedef enum {
+ PTP_MASTER,
+ PTP_PRE_MASTER,
+ PTP_SLAVE,
+ PTP_UNCALIBRATED,
+ PTP_DISABLED,
+ PTP_FAULTY,
+ PTP_INITIALIZING,
+ PTP_LISTENING
+} PortState;
+
+typedef enum {
+ V1,
+ V2_E2E,
+ V2_P2P
+} PortType;
+
+class PortIdentity {
+ private:
+ ClockIdentity clock_id;
+ uint16_t portNumber;
+ public:
+ PortIdentity() {
+ };
+ PortIdentity(uint8_t * clock_id, uint16_t * portNumber) {
+ this->portNumber = *portNumber;
+ this->portNumber = PLAT_ntohs(this->portNumber);
+ this->clock_id.set(clock_id);
+ }
+ bool operator!=(const PortIdentity & cmp) const {
+ return !(this->clock_id == cmp.clock_id)
+ || this->portNumber != cmp.portNumber ? true : false;
+ }
+ bool operator==(const PortIdentity & cmp)const {
+ return this->clock_id == cmp.clock_id
+ && this->portNumber == cmp.portNumber ? true : false;
+ }
+ 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;
+ }
+ 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;
+ }
+ void getClockIdentityString(char *id) {
+ clock_id.getIdentityString(id);
+ }
+ void setClockIdentity(ClockIdentity clock_id) {
+ this->clock_id = clock_id;
+ }
+ ClockIdentity getClockIdentity( void ) {
+ return this->clock_id;
+ }
+ void getPortNumberNO(uint16_t * id) { // Network byte order
+ uint16_t portNumberNO = PLAT_htons(portNumber);
+ *id = portNumberNO;
+ }
+ void getPortNumber(uint16_t * id) { // Host byte order
+ *id = portNumber;
+ }
+ void setPortNumber(uint16_t * id) {
+ portNumber = *id;
+ }
+};
+
+typedef std::map < PortIdentity, LinkLayerAddress > IdentityMap_t;
+
+typedef std::list < PTPMessageAnnounce * >AnnounceList_t;
+
+class IEEE1588Port {
+ static LinkLayerAddress other_multicast;
+ static LinkLayerAddress pdelay_multicast;
+
+ PortIdentity port_identity;
+ // directly connected node
+ PortIdentity peer_identity;
+
+ OSNetworkInterface *net_iface;
+ LinkLayerAddress local_addr;
+
+ // 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;
+ int64_t one_way_delay; // Allow this to be negative result of a large clock skew
+ // Implementation Specific data/methods
+ IEEE1588Clock *clock; // Pointer to clock object with which the port is associated
+
+ bool _syntonize;
+
+ bool asCapable;
+
+ int32_t *rate_offset_array;
+ uint32_t rate_offset_array_size;
+ uint32_t rate_offset_count;
+ uint32_t rate_offset_index;
+
+ int32_t _peer_rate_offset;
+ Timestamp _peer_offset_ts_theirs;
+ Timestamp _peer_offset_ts_mine;
+ bool _peer_offset_init;
+
+ int32_t _master_rate_offset;
+
+ int32_t _initial_clock_offset;
+ int32_t _current_clock_offset;
+
+ bool _master_local_freq_offset_init;
+ int64_t _prev_master_local_offset;
+ Timestamp _prev_sync_time;
+
+ bool _local_system_freq_offset_init;
+ int64_t _prev_local_system_offset;
+ Timestamp _prev_system_time;
+
+ AnnounceList_t qualified_announce;
+
+ uint16_t announce_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
+ uint16_t ifindex; // physical interface number that object represents
+
+ IdentityMap_t identity_map;
+
+ PTPMessageSync *last_sync;
+
+ OSThread *listening_thread;
+
+ OSCondition *port_ready_condition;
+
+ OSLock *pdelay_rx_lock;
+ OSLock *port_tx_lock;
+
+ OSThreadFactory *thread_factory;
+ OSTimerFactory *timer_factory;
+
+ HWTimestamper *_hw_timestamper;
+
+ net_result port_send(uint8_t * buf, int size, MulticastType mcast_type,
+ PortIdentity * destIdentity, bool timestamp);
+
+ InterfaceLabel *net_label;
+
+ OSLockFactory *lock_factory;
+ OSConditionFactory *condition_factory;
+ public:
+ // Added for testing
+ bool forceSlave;
+
+ OSTimerFactory *getTimerFactory() {
+ return timer_factory;
+ }
+ void setAsCapable(bool ascap) {
+ if (ascap != asCapable) {
+ fprintf(stderr, "AsCapable: %s\n",
+ ascap == true ? "Enabled" : "Disabled");
+ }
+ asCapable = ascap;
+ }
+
+ ~IEEE1588Port();
+ IEEE1588Port(IEEE1588Clock * clock, uint16_t index, bool forceSlave,
+ HWTimestamper * timestamper, bool syntonize,
+ int32_t offset, InterfaceLabel * net_label,
+ OSConditionFactory * condition_factory,
+ OSThreadFactory * thread_factory,
+ OSTimerFactory * timer_factory,
+ OSLockFactory * lock_factory);
+ bool init_port();
+
+ void recoverPort(void);
+ void *openPort(void);
+ unsigned getPayloadOffset();
+ void sendEventPort(uint8_t * buf, int len, MulticastType mcast_type,
+ PortIdentity * destIdentity);
+ void sendGeneralPort(uint8_t * buf, int len, MulticastType mcast_type,
+ PortIdentity * destIdentity);
+ void processEvent(Event e);
+
+ PTPMessageAnnounce *calculateERBest(void);
+
+ void addForeignMaster(PTPMessageAnnounce * msg);
+ void removeForeignMaster(PTPMessageAnnounce * msg);
+ void removeForeignMasterAll(void);
+
+ void addQualifiedAnnounce(PTPMessageAnnounce * msg) {
+ qualified_announce.push_front(msg);
+ }
+
+ void removeQualifiedAnnounce(PTPMessageAnnounce * msg) {
+ qualified_announce.remove(msg);
+ }
+
+ char getSyncInterval(void) {
+ return log_mean_sync_interval;
+ }
+ char getAnnounceInterval(void) {
+ return log_mean_announce_interval;
+ }
+ char getPDelayInterval(void) {
+ return log_min_mean_pdelay_req_interval;
+ }
+ PortState getPortState(void) {
+ return port_state;
+ }
+ void getPortIdentity(PortIdentity & identity) {
+ identity = this->port_identity;
+ }
+ bool burstEnabled(void) {
+ return burst_enabled;
+ }
+ uint16_t getNextAnnounceSequenceId(void) {
+ return announce_sequence_id++;
+ }
+ uint16_t getNextSyncSequenceId(void) {
+ return sync_sequence_id++;
+ }
+ uint16_t getNextPDelaySequenceId(void) {
+ return pdelay_sequence_id++;
+ }
+
+ uint16_t getParentLastSyncSequenceNumber(void);
+ void setParentLastSyncSequenceNumber(uint16_t num);
+
+ IEEE1588Clock *getClock(void);
+
+ void setLastSync(PTPMessageSync * msg) {
+ last_sync = msg;
+ }
+ PTPMessageSync *getLastSync(void) {
+ return last_sync;
+ }
+
+ bool getPDelayRxLock() {
+ return pdelay_rx_lock->lock() == oslock_ok ? true : false;
+ }
+
+ bool tryPDelayRxLock() {
+ return pdelay_rx_lock->trylock() == oslock_ok ? true : false;
+ }
+
+ bool putPDelayRxLock() {
+ return pdelay_rx_lock->unlock() == oslock_ok ? true : false;
+ }
+
+ int getTxLock() {
+ return port_tx_lock->lock() == oslock_ok ? true : false;
+ }
+ int putTxLock() {
+ return port_tx_lock->unlock() == oslock_ok ? true : false;
+ }
+
+ void setLastPDelayReq(PTPMessagePathDelayReq * msg) {
+ last_pdelay_req = msg;
+ }
+ PTPMessagePathDelayReq *getLastPDelayReq(void) {
+ return last_pdelay_req;
+ }
+
+ void setLastPDelayResp(PTPMessagePathDelayResp * msg) {
+ last_pdelay_resp = msg;
+ }
+ PTPMessagePathDelayResp *getLastPDelayResp(void) {
+ return last_pdelay_resp;
+ }
+
+ void setLastPDelayRespFollowUp(PTPMessagePathDelayRespFollowUp * msg) {
+ last_pdelay_resp_fwup = msg;
+ }
+ PTPMessagePathDelayRespFollowUp *getLastPDelayRespFollowUp(void) {
+ return last_pdelay_resp_fwup;
+ }
+
+ int calcMasterLocalClockRateDifference(signed long long offset,
+ Timestamp sync_time);
+ int calcLocalSystemClockRateDifference(signed long long offset,
+ Timestamp sync_time);
+
+ int32_t getMasterRateOffset(void) {
+ return _master_rate_offset;
+ }
+ void setMasterRateOffset(int32_t offset
+ /* parts-per-trillion frequency offset */ ) {
+ _master_rate_offset = offset;
+ }
+ int32_t getPeerRateOffset(void) {
+ return _peer_rate_offset;
+ }
+ void setPeerRateOffset(int32_t offset
+ /* parts-per-trillion frequency offset */ ) {
+ _peer_rate_offset = offset;
+ }
+ void setPeerOffset(Timestamp mine, Timestamp theirs) {
+ _peer_offset_ts_mine = mine;
+ _peer_offset_ts_theirs = theirs;
+ _peer_offset_init = true;
+ }
+ bool getPeerOffset(Timestamp & mine, Timestamp & theirs) {
+ mine = _peer_offset_ts_mine;
+ theirs = _peer_offset_ts_theirs;
+ return _peer_offset_init;
+ }
+
+ bool _adjustClockRate(int32_t freq_offset, unsigned counter_value,
+ Timestamp master_timestamp, int64_t offset,
+ bool change_master) {
+ if (_hw_timestamper) {
+ return
+ _hw_timestamper->HWTimestamper_adjclockrate
+ (freq_offset, counter_value, master_timestamp,
+ offset, change_master);
+ }
+ return false;
+ }
+ bool adjustClockRate(int32_t freq_offset, unsigned counter_value,
+ Timestamp master_timestamp, int64_t offset,
+ bool change_master) {
+ return _adjustClockRate(freq_offset, counter_value,
+ master_timestamp, offset,
+ change_master);
+ }
+
+ bool doSyntonization(void) {
+ return _syntonize;
+ }
+
+ void getExtendedError(char *msg) {
+ if (_hw_timestamper) {
+ _hw_timestamper->HWTimestamper_get_extderror(msg);
+ } else {
+ *msg = '\0';
+ }
+ }
+
+ bool getExternalClockRate(Timestamp & local_time,
+ int64_t & external_local_offset,
+ int32_t & external_local_freq_offset) {
+ bool s = false;
+ if (_hw_timestamper) {
+ s = _hw_timestamper->HWTimestamper_get_extclk_offset
+ (&local_time, &external_local_offset,
+ &external_local_freq_offset);
+ }
+ return s;
+ }
+
+ int getRxTimestamp(PortIdentity * sourcePortIdentity,
+ uint16_t sequenceId, Timestamp & timestamp,
+ unsigned &counter_value, bool last);
+ int getTxTimestamp(PortIdentity * sourcePortIdentity,
+ uint16_t sequenceId, Timestamp & timestamp,
+ unsigned &counter_value, bool last);
+
+ int getTxTimestamp(PTPMessageCommon * msg, Timestamp & timestamp,
+ unsigned &counter_value, bool last);
+ int getRxTimestamp(PTPMessageCommon * msg, Timestamp & timestamp,
+ unsigned &counter_value, bool last);
+
+ void getDeviceTime(Timestamp & system_time, Timestamp & device_time,
+ uint32_t & local_clock,
+ uint32_t & nominal_clock_rate);
+
+ int64_t getLinkDelay(void) {
+ return one_way_delay;
+ }
+ void setLinkDelay(int64_t delay) {
+ one_way_delay = delay;
+ }
+
+ void recommendState(PortState state, bool changed_master);
+
+ void mapSocketAddr(PortIdentity * destIdentity,
+ LinkLayerAddress * remote);
+ void addSockAddrMap(PortIdentity * destIdentity,
+ LinkLayerAddress * remote);
+};
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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 IEEE1588_HPP
+#define IEEE1588_HPP
+
+#include <stdint.h>
+
+#include <string.h>
+
+#include <signal.h>
+
+#include <stdio.h>
+
+#include <platform.hpp>
+
+#define MAX_PORTS 32
+
+#define PTP_CLOCK_IDENTITY_LENGTH 8
+
+class LinkLayerAddress;
+struct ClockQuality;
+class PortIdentity;
+class IEEE1588Clock;
+class PTPMessageCommon;
+class PTPMessageSync;
+class PTPMessageAnnounce;
+class PTPMessagePathDelayReq;
+class PTPMessagePathDelayResp;
+class PTPMessagePathDelayRespFollowUp;
+class IEEE1588Port;
+
+typedef enum {
+ NULL_EVENT = 0,
+ POWERUP = 5,
+ INITIALIZE,
+ STATE_CHANGE_EVENT,
+ SYNC_INTERVAL_TIMEOUT_EXPIRES,
+ PDELAY_INTERVAL_TIMEOUT_EXPIRES,
+ SYNC_RECEIPT_TIMEOUT_EXPIRES,
+ QUALIFICATION_TIMEOUT_EXPIRES,
+ ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES,
+ ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES,
+ FAULT_DETECTED,
+ PDELAY_DEFERRED_PROCESSING,
+ PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES,
+} Event;
+
+typedef struct {
+ IEEE1588Port *port;
+ Event event;
+} event_descriptor_t;
+
+class InterfaceLabel {
+ public:
+ virtual ~ InterfaceLabel() {
+ };
+};
+
+class ClockIdentity {
+ private:
+ uint8_t id[PTP_CLOCK_IDENTITY_LENGTH];
+ public:
+ bool operator==(const ClockIdentity & cmp) const {
+ return memcmp(this->id, cmp.id,
+ PTP_CLOCK_IDENTITY_LENGTH) == 0 ? true : false;
+ }
+ bool operator!=( const ClockIdentity &cmp ) const {
+ return memcmp( this->id, cmp.id, PTP_CLOCK_IDENTITY_LENGTH ) != 0 ? true : false;
+ }
+ bool operator<(const ClockIdentity & cmp)const {
+ return memcmp(this->id, cmp.id,
+ PTP_CLOCK_IDENTITY_LENGTH) < 0 ? true : false;
+ }
+ bool operator>(const ClockIdentity & cmp)const {
+ return memcmp(this->id, cmp.id,
+ PTP_CLOCK_IDENTITY_LENGTH) < 0 ? true : false;
+ }
+ void getIdentityString(char *id) {
+ memcpy(id, this->id, PTP_CLOCK_IDENTITY_LENGTH);
+ }
+ void set(uint8_t * id) {
+ memcpy(this->id, id, PTP_CLOCK_IDENTITY_LENGTH);
+ }
+ void set(LinkLayerAddress * address);
+};
+
+class Timestamp {
+ public:
+ Timestamp(uint32_t ns, uint32_t s_l, uint16_t s_m) {
+ nanoseconds = ns;
+ seconds_ls = s_l;
+ seconds_ms = s_m;
+ }
+ Timestamp() {
+ };
+ uint32_t nanoseconds;
+ uint32_t seconds_ls;
+ uint16_t seconds_ms;
+};
+
+#define INVALID_TIMESTAMP (Timestamp( 0xC0000000, 0, 0 ))
+#define PDELAY_PENDING_TIMESTAMP (Timestamp( 0xC0000001, 0, 0 ))
+
+#define TIMESTAMP_TO_NS(ts) (((static_cast<long long int>(ts.seconds_ms) << sizeof(ts.seconds_ls)*8) + ts.seconds_ls)*1000000000LL + \
+ ts.nanoseconds)
+
+static inline uint64_t bswap_64(uint64_t in)
+{
+ uint8_t *s = (uint8_t *) & in;
+ uint8_t *e = s + 7;
+ while (e > s) {
+ uint8_t t;
+ t = *s;
+ *s = *e;
+ *e = t;
+ ++s;
+ --e;
+ }
+ return in;
+}
+
+static inline void TIMESTAMP_SUB_NS(Timestamp & ts, uint64_t ns)
+{
+ while (ns >= 1000000000) {
+ if (ts.seconds_ls != 0) {
+ --ts.seconds_ls;
+ } else {
+ --ts.seconds_ms;
+ ts.seconds_ls = 0xFFFFFFFF;
+ }
+ ns -= 1000000000;
+ }
+ ts.nanoseconds -= (uint32_t) ns;
+}
+
+#define XPTPD_ERROR(fmt,...) fprintf( stderr, "ERROR at %u in %s: " fmt "\n", __LINE__, __FILE__ ,## __VA_ARGS__)
+#ifdef PTP_DEBUG
+#define XPTPD_INFO(fmt,...) fprintf( stderr, "DEBUG at %u in %s: " fmt "\n", __LINE__, __FILE__ ,## __VA_ARGS__)
+#else
+#define XPTPD_INFO(fmt,...)
+#endif
+
+#define HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE 4096
+
+class HWTimestamper {
+ public:
+ virtual bool HWTimestamper_init(InterfaceLabel * iface_label) {
+ return true;
+ }
+ virtual void HWTimestamper_final(void) {
+ }
+
+ virtual bool HWTimestamper_adjclockrate(int32_t frequency_offset,
+ unsigned counter_value,
+ Timestamp master_timestamp,
+ int64_t offset,
+ bool changed_master) {
+ return false;
+ }
+ virtual bool HWTimestamper_adjclockrate2(int32_t ppt_adjustment) {
+ return false;
+ }
+
+ virtual bool HWTimestamper_gettime(Timestamp * system_time,
+ Timestamp * device_time,
+ uint32_t * local_clock,
+ uint32_t * nominal_clock_rate) = 0;
+
+ virtual int HWTimestamper_txtimestamp(PortIdentity * identity,
+ uint16_t sequenceId,
+ Timestamp & timestamp,
+ unsigned &clock_value,
+ bool last) = 0;
+
+ virtual int HWTimestamper_rxtimestamp(PortIdentity * identity,
+ uint16_t sequenceId,
+ Timestamp & timestamp,
+ unsigned &clock_value,
+ bool last) = 0;
+
+ virtual bool HWTimestamper_get_extclk_offset(Timestamp * local_time,
+ int64_t * clk_offset,
+ int32_t *
+ ppt_freq_offset) {
+ return false;
+ }
+
+ virtual void HWTimestamper_get_extderror(char *msg) {
+ *msg = '\0';
+ }
+
+ virtual ~ HWTimestamper() {
+ }
+};
+
+PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port);
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ 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_clock.hpp>
+#include <avbts_oslock.hpp>
+#include <avbts_ostimerq.hpp>
+
+#include <stdio.h>
+
+#include <string.h>
+
+#include <stdlib.h>
+
+#include <string.h>
+
+void ClockIdentity::set(LinkLayerAddress * addr)
+{
+ uint64_t tmp1 = 0;
+ uint32_t tmp2;
+ addr->toOctetArray((uint8_t *) & tmp1);
+ tmp2 = tmp1 & 0xFFFFFF;
+ tmp1 >>= 24;
+ tmp1 <<= 16;
+ tmp1 |= 0xFEFF;
+ tmp1 <<= 24;
+ tmp1 |= tmp2;
+ memcpy(id, &tmp1, PTP_CLOCK_IDENTITY_LENGTH);
+}
+
+IEEE1588Clock::IEEE1588Clock(bool forceOrdinarySlave,
+ OSTimerQueueFactory * timerq_factory, OS_IPC * ipc)
+{
+ timerq = timerq_factory->createOSTimerQueue();
+
+ priority1 = 248;
+ priority2 = 248;
+
+ master_local_offset_nrst125us_initialized = false;
+
+ number_ports = 0;
+
+ this->forceOrdinarySlave = forceOrdinarySlave;
+
+ clock_quality.clockAccuracy = 0xfe;
+ clock_quality.cq_class = 248;
+ clock_quality.offsetScaledLogVariance = 16640;
+
+ time_source = 160;
+
+ domain_number = 0;
+
+ this->ipc = ipc;
+
+ memset( &LastEBestIdentity, 0xFF, sizeof( LastEBestIdentity ));
+ return;
+}
+
+Timestamp IEEE1588Clock::getSystemTime(void)
+{
+ return (Timestamp(0, 0, 0));
+}
+
+void timerq_handler(void *arg)
+{
+ event_descriptor_t *event_descriptor = (event_descriptor_t *) arg;
+ event_descriptor->port->processEvent(event_descriptor->event);
+}
+
+void IEEE1588Clock::addEventTimer(IEEE1588Port * target, Event e,
+ unsigned long long time_ns)
+{
+ event_descriptor_t *event_descriptor = new event_descriptor_t();
+ event_descriptor->event = e;
+ event_descriptor->port = target;
+ timerq->addEvent((unsigned)time_ns / 1000, (int)e, timerq_handler,
+ event_descriptor, true, NULL);
+}
+
+void IEEE1588Clock::deleteEventTimer(IEEE1588Port * target, Event event)
+{
+ timerq->cancelEvent((int)event, NULL);
+}
+
+// Sync clock to argument time
+void IEEE1588Clock::setMasterOffset(int64_t master_local_offset,
+ Timestamp local_time,
+ int32_t master_local_freq_offset,
+ int64_t local_system_offset,
+ Timestamp system_time,
+ int32_t local_system_freq_offset,
+ uint32_t nominal_clock_rate,
+ uint32_t local_clock)
+{
+
+ if (ipc != NULL)
+ ipc->update(master_local_offset, local_system_offset,
+ master_local_freq_offset, local_system_freq_offset,
+ TIMESTAMP_TO_NS(local_time));
+ return;
+}
+
+void IEEE1588Clock::getGrandmasterIdentity(char *id)
+{
+ grandmaster_port_identity.getClockIdentityString(id);
+}
+
+// Get current time from system clock
+Timestamp IEEE1588Clock::getTime(void)
+{
+ return getSystemTime();
+}
+
+// Get timestamp from hardware
+Timestamp IEEE1588Clock::getPreciseTime(void)
+{
+ return getSystemTime();
+}
+
+bool IEEE1588Clock::isBetterThan(PTPMessageAnnounce * msg)
+{
+ unsigned char this1[14];
+ unsigned char that1[14];
+ uint16_t tmp;
+
+ this1[0] = priority1;
+ that1[0] = msg->getGrandmasterPriority1();
+
+ this1[1] = clock_quality.cq_class;
+ that1[1] = msg->getGrandmasterClockQuality()->cq_class;
+
+ this1[2] = clock_quality.clockAccuracy;
+ that1[2] = msg->getGrandmasterClockQuality()->clockAccuracy;
+
+ tmp = clock_quality.offsetScaledLogVariance;
+ tmp = PLAT_htons(tmp);
+ memcpy(this1 + 3, &tmp, sizeof(tmp));
+ tmp = msg->getGrandmasterClockQuality()->offsetScaledLogVariance;
+ tmp = PLAT_htons(tmp);
+ memcpy(that1 + 3, &tmp, sizeof(tmp));
+
+ this1[5] = priority2;
+ that1[5] = msg->getGrandmasterPriority2();
+
+ clock_identity.getIdentityString((char *)this1 + 6);
+ //memcpy( this1+6, clock_identity, PTP_CLOCK_IDENTITY_LENGTH );
+ msg->getGrandmasterIdentity((char *)that1 + 6);
+
+#if 0
+ fprintf(stderr, "(Clk)Us: ");
+ for (int i = 0; i < 14; ++i)
+ fprintf(stderr, "%hhx ", this1[i]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "(Clk)Them: ");
+ for (int i = 0; i < 14; ++i)
+ fprintf(stderr, "%hhx ", that1[i]);
+ fprintf(stderr, "\n");
+#endif
+
+ return (memcmp(this1, that1, 14) < 0) ? true : false;
+}
+
+IEEE1588Clock::~IEEE1588Clock(void)
+{
+ // Unmap shared memory
+}
--- /dev/null
+/******************************************************************************
+
+ 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 <stdio.h>
+
+#include <math.h>
+
+#include <stdlib.h>
+
+LinkLayerAddress IEEE1588Port::other_multicast(OTHER_MULTICAST);
+LinkLayerAddress IEEE1588Port::pdelay_multicast(PDELAY_MULTICAST);
+
+OSThreadExitCode openPortWrapper(void *arg)
+{
+ IEEE1588Port *port;
+
+ port = (IEEE1588Port *) arg;
+ if (port->openPort() == NULL)
+ return osthread_ok;
+ else
+ return osthread_error;
+}
+
+IEEE1588Port::~IEEE1588Port()
+{
+ delete port_ready_condition;
+ delete [] rate_offset_array;
+}
+
+IEEE1588Port::IEEE1588Port(IEEE1588Clock * clock, uint16_t index,
+ bool forceSlave, HWTimestamper * timestamper,
+ bool syntonize, int32_t offset,
+ InterfaceLabel * net_label,
+ OSConditionFactory * condition_factory,
+ OSThreadFactory * thread_factory,
+ OSTimerFactory * timer_factory,
+ OSLockFactory * lock_factory)
+{
+ sync_sequence_id = 0;
+ last_pdelay_req = NULL;
+
+ clock->registerPort(this, index);
+ this->clock = clock;
+ ifindex = index;
+
+ this->forceSlave = forceSlave;
+
+ asCapable = false;
+
+ announce_sequence_id = 0;
+ sync_sequence_id = 0;
+ pdelay_sequence_id = 0;
+
+ sync_sequence_id = 0;
+
+ log_mean_sync_interval = -3;
+ log_mean_announce_interval = 0;
+ log_min_mean_pdelay_req_interval = 0;
+
+ _current_clock_offset = _initial_clock_offset = offset;
+
+ rate_offset_array = NULL;
+
+ _hw_timestamper = timestamper;
+
+ if (_hw_timestamper != NULL) {
+ if (!_hw_timestamper->HWTimestamper_init(net_label)) {
+ XPTPD_ERROR
+ ("Failed to initialize hardware timestamper, falling back to software timestamping");
+ _hw_timestamper = NULL;
+ }
+ }
+
+ _syntonize = syntonize;
+ _master_local_freq_offset_init = false;
+ _local_system_freq_offset_init = false;
+
+ one_way_delay = 3600000000000;
+
+ _peer_rate_offset = 0;
+ _master_rate_offset = 0;
+
+ last_sync = NULL;
+ last_pdelay_req = NULL;
+ last_pdelay_resp = NULL;
+ last_pdelay_resp_fwup = NULL;
+
+ this->net_label = net_label;
+
+ this->timer_factory = timer_factory;
+ this->thread_factory = thread_factory;
+
+ this->condition_factory = condition_factory;
+ this->lock_factory = lock_factory;
+}
+
+bool IEEE1588Port::init_port()
+{
+ 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);
+
+ pdelay_rx_lock = lock_factory->createLock(oslock_recursive);
+ port_tx_lock = lock_factory->createLock(oslock_recursive);
+
+ port_identity.setClockIdentity(clock->getClockIdentity());
+ port_identity.setPortNumber(&ifindex);
+
+ port_ready_condition = condition_factory->createCondition();
+
+ return true;
+}
+
+void *IEEE1588Port::openPort(void)
+{
+ fprintf(stderr, "openPort: thread started\n");
+
+ port_ready_condition->signal();
+
+ while (1) {
+ PTPMessageCommon *msg;
+ uint8_t buf[128];
+ LinkLayerAddress remote;
+ net_result rrecv;
+ size_t length = sizeof(buf);
+
+ if ((rrecv = net_iface->recv(&remote, buf, length)) == net_succeed) {
+ XPTPD_INFO("Processing network buffer");
+ msg = buildPTPMessage((char *)buf, (int)length, &remote,
+ this);
+ if (msg != NULL) {
+ XPTPD_INFO("Processing message");
+ msg->processMessage(this);
+ if (msg->garbage()) {
+ delete msg;
+ }
+ } else {
+ XPTPD_ERROR("Discarding invalid message");
+ }
+ } else if (rrecv == net_fatal) {
+ XPTPD_ERROR("read from network interface failed");
+ this->processEvent(FAULT_DETECTED);
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+net_result IEEE1588Port::port_send(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 {
+ dest = other_multicast;
+ }
+ } else {
+ mapSocketAddr(destIdentity, &dest);
+ }
+
+ return net_iface->send(&dest, (uint8_t *) buf, size, timestamp);
+}
+
+unsigned IEEE1588Port::getPayloadOffset()
+{
+ return net_iface->getPayloadOffset();
+}
+
+void IEEE1588Port::sendEventPort(uint8_t * buf, int size,
+ MulticastType mcast_type,
+ PortIdentity * destIdentity)
+{
+ net_result rtx = port_send(buf, size, mcast_type, destIdentity, true);
+ if (rtx != net_succeed) {
+ XPTPD_ERROR("sendEventPort(): failure");
+ }
+
+ return;
+}
+
+void IEEE1588Port::sendGeneralPort(uint8_t * buf, int size,
+ MulticastType mcast_type,
+ PortIdentity * destIdentity)
+{
+ net_result rtx = port_send(buf, size, mcast_type, destIdentity, false);
+ if (rtx != net_succeed) {
+ XPTPD_ERROR("sendEventPort(): failure");
+ }
+
+ return;
+}
+
+void IEEE1588Port::processEvent(Event e)
+{
+ bool changed_master;
+ OSTimer *timer = timer_factory->createTimer();
+
+ switch (e) {
+ case POWERUP:
+ case INITIALIZE:
+ XPTPD_INFO("Received POWERUP/INITIALIZE event");
+ {
+ unsigned long long interval1;
+ unsigned long long interval3;
+ unsigned long long interval4;
+ Event e1 = NULL_EVENT;
+ Event e3 = NULL_EVENT;
+ Event e4 = NULL_EVENT;
+
+ if (forceSlave) {
+ port_state = PTP_SLAVE;
+ e1 = PDELAY_INTERVAL_TIMEOUT_EXPIRES;
+ interval1 =
+ (unsigned long
+ long)(pow((double)2,
+ getPDelayInterval()) *
+ 1000000000.0);
+ } else {
+ port_state = PTP_LISTENING;
+ e1 = PDELAY_INTERVAL_TIMEOUT_EXPIRES;
+ e3 = SYNC_RECEIPT_TIMEOUT_EXPIRES;
+ e4 = ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
+ interval1 =
+ (unsigned long
+ long)(pow((double)2,
+ getPDelayInterval()) *
+ 1000000000.0);
+ 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);
+ }
+
+ fprintf(stderr, "Starting port thread\n");
+ port_ready_condition->wait_prelock();
+ listening_thread = thread_factory->createThread();
+ if (!listening_thread->start
+ (openPortWrapper, (void *)this)) {
+ XPTPD_ERROR("Error creating port thread\n");
+ return;
+ }
+ port_ready_condition->wait();
+
+ if (e1 != NULL_EVENT)
+ clock->addEventTimer(this, e1, interval1);
+ if (e3 != NULL_EVENT)
+ clock->addEventTimer(this, e3, interval3);
+ if (e4 != NULL_EVENT)
+ clock->addEventTimer(this, e4, interval4);
+ }
+ break;
+ case STATE_CHANGE_EVENT:
+ if (!forceSlave) {
+ int number_ports, j;
+ PTPMessageAnnounce *EBest = NULL;
+ PortIdentity EBestPortIdentity;
+
+ IEEE1588Port **ports;
+ clock->getPortList(number_ports, ports);
+ // If ANY ports are in PTP_INTIALIZING state, STATE_CHANGE_EVENT cannot be processed
+#if 0
+ for (int i = 0; i < number_ports; ++i) {
+ if (ports[i]->port_state == PTP_INITIALIZING) {
+ break;
+ }
+ }
+#endif
+ //fprintf( stderr, "State Change Event\n" );
+
+ // 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()->isBetterThan(EBest)) {
+ EBest = ports[j]->calculateERBest();
+ }
+ }
+ }
+
+ // Check if we've changed
+ EBest->getPortIdentity( &EBestPortIdentity );
+ if( EBestPortIdentity.getClockIdentity() != clock->getLastEBestIdentity() ) {
+ fprintf( stderr, "Changed master!\n" );
+ changed_master = true;
+ } else {
+ changed_master = false;
+ }
+
+ 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
+ fprintf(stderr, "\n");
+ EBest = NULL; // EBest == NULL : we were grandmaster
+ ports[j]->recommendState(PTP_MASTER,
+ changed_master);
+ } else {
+ if (EBest == calculateERBest()) {
+ // The "best" sync was recieved on this port
+ ports[j]->recommendState
+ (PTP_SLAVE, changed_master);
+ } else {
+ // Otherwise we are the master because we have sync'd to a better clock
+ ports[j]->recommendState
+ (PTP_MASTER,
+ changed_master);
+ }
+ }
+ }
+ clock->setLastEBestIdentity( EBestPortIdentity.getClockIdentity() );
+ }
+ break;
+ case ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES:
+ case SYNC_RECEIPT_TIMEOUT_EXPIRES:
+ {
+ if (forceSlave) {
+ break;
+ }
+ if (port_state == PTP_LISTENING
+ || port_state == PTP_UNCALIBRATED
+ || port_state == PTP_SLAVE
+ || port_state == PTP_PRE_MASTER) {
+ fprintf(stderr,
+ "***Sync Timeout Expired - Becoming Master: %d\n",
+ e);
+ port_state = PTP_MASTER;
+ Timestamp system_time;
+ Timestamp device_time;
+ int64_t local_system_offset;
+
+#if 0
+ Timestamp crstamp_device_time;
+ int64_t external_local_offset;
+ int32_t external_local_freq_offset;
+#endif
+ uint32_t local_clock, nominal_clock_rate;
+
+ getDeviceTime(system_time, device_time,
+ local_clock, nominal_clock_rate);
+
+ local_system_offset =
+ TIMESTAMP_TO_NS(system_time) -
+ TIMESTAMP_TO_NS(device_time);
+#if 0
+ local_system_offset = device_time.nanoseconds +
+ (((unsigned long long)device_time.seconds_ms
+ << sizeof(device_time.seconds_ls) * 8) +
+ device_time.seconds_ls) * 1000000000LL;
+ local_system_offset -=
+ system_time.nanoseconds +
+ (((unsigned long long)system_time.seconds_ms
+ << sizeof(system_time.seconds_ls) * 8) +
+ system_time.seconds_ls) * 1000000000LL;
+#endif
+
+ (void)
+ calcLocalSystemClockRateDifference
+ (local_system_offset, system_time);
+
+ //getExternalClockRate( crstamp_device_time, external_local_offset, external_local_freq_offset );
+
+#if 0
+ clock->setMasterOffset(0, device_time, 0,
+ local_system_offset,
+ system_time,
+ local_system_freq_offset,
+ nominal_clock_rate,
+ local_clock);
+#endif
+ if (this->doSyntonization()) {
+ this->adjustClockRate(0, local_clock,
+ device_time, 0,
+ false);
+ }
+ // "Expire" all previously received announce messages on this port
+ while (!qualified_announce.empty()) {
+ delete qualified_announce.back();
+ qualified_announce.pop_back();
+ }
+
+ // Add timers for Announce and Sync, this is as close to immediately as we get
+ clock->addEventTimer(this,
+ ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES,
+ 8000000);
+ clock->addEventTimer(this,
+ SYNC_INTERVAL_TIMEOUT_EXPIRES,
+ 8000000);
+ }
+ break;
+ case PDELAY_INTERVAL_TIMEOUT_EXPIRES:
+ XPTPD_INFO("PDELAY_INTERVAL_TIMEOUT_EXPIRES occured");
+ {
+ int ts_good;
+ int iter = 2;
+ Timestamp req_timestamp;
+ long req = 1000; // = 1 ms
+ unsigned req_timestamp_counter_value;
+
+ 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);
+
+ XPTPD_INFO("Preparing to send PDelay Request");
+ getTxLock();
+ pdelay_req->sendPort(this, NULL);
+ XPTPD_INFO("Sent PDelay Request");
+
+ ts_good =
+ getTxTimestamp(pdelay_req, req_timestamp,
+ req_timestamp_counter_value,
+ false);
+ while (ts_good != 0 && iter-- != 0) {
+ timer->sleep(req);
+ if (ts_good != -72 && iter < 1)
+ fprintf(stderr,
+ "Error (TX) timestamping PDelay request (Retrying-%d), error=%d\n",
+ iter, ts_good);
+ ts_good =
+ getTxTimestamp(pdelay_req,
+ req_timestamp,
+ req_timestamp_counter_value,
+ iter == 0);
+ req *= 2;
+ }
+ putTxLock();
+
+ //fprintf( stderr, "Sequence = %hu\n", pdelay_req->getSequenceId() );
+
+ if (pdelay_req == NULL) {
+ fprintf(stderr,
+ "PDelay request is NULL!\n");
+ abort();
+ }
+
+ if (ts_good == 0) {
+ pdelay_req->setTimestamp(req_timestamp);
+ } else {
+ Timestamp failed = INVALID_TIMESTAMP;
+ pdelay_req->setTimestamp(failed);
+ }
+
+ if (ts_good != 0) {
+ char msg
+ [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE];
+ getExtendedError(msg);
+ fprintf(stderr,
+ "Error (TX) timestamping PDelay request, error=%d\n%s",
+ ts_good, msg);
+ //_exit(-1);
+ }
+#ifdef DEBUG
+ if (ts_good == 0) {
+ XPTPD_INFO
+ ("Successful PDelay Req timestamp, %u,%u",
+ req_timestamp.seconds_ls,
+ req_timestamp.nanoseconds);
+ } else {
+ XPTPD_INFO
+ ("*** Unsuccessful PDelay Req timestamp");
+ }
+#endif
+
+ }
+ clock->addEventTimer(this,
+ PDELAY_INTERVAL_TIMEOUT_EXPIRES,
+ (unsigned long
+ long)(pow((double)2,
+ getPDelayInterval()) *
+ 1000000000.0));
+ break;
+ case SYNC_INTERVAL_TIMEOUT_EXPIRES:
+ XPTPD_INFO("SYNC_INTERVAL_TIMEOUT_EXPIRES occured");
+ // Set offset from master to zero, update device vs system time offset
+ Timestamp system_time;
+ Timestamp device_time;
+ int32_t local_system_freq_offset;
+ int64_t local_system_offset;
+ static bool adj_up = true;
+
+#if 0
+ Timestamp crstamp_device_time;
+ int64_t external_local_offset;
+ int32_t external_local_freq_offset;
+#endif
+ uint32_t local_clock, nominal_clock_rate;
+
+ getDeviceTime(system_time, device_time, local_clock,
+ nominal_clock_rate);
+ //fprintf( stderr, "Device Time = %llu,System Time = %llu\n", TIMESTAMP_TO_NS(device_time), TIMESTAMP_TO_NS(system_time));
+
+ XPTPD_INFO
+ ("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);
+#if 0
+ local_system_offset = device_time.nanoseconds +
+ (((unsigned long long)device_time.seconds_ms <<
+ sizeof(device_time.seconds_ls) * 8) +
+ device_time.seconds_ls) * 1000000000LL;
+ local_system_offset -=
+ system_time.nanoseconds +
+ (((unsigned long long)system_time.seconds_ms <<
+ sizeof(system_time.seconds_ls) * 8) +
+ system_time.seconds_ls) * 1000000000LL;
+#endif
+
+ local_system_freq_offset =
+ calcLocalSystemClockRateDifference
+ (local_system_offset, system_time);
+
+ //getExternalClockRate( crstamp_device_time, external_local_offset, external_local_freq_offset );
+
+ clock->setMasterOffset(0, device_time, 0,
+ local_system_offset, system_time,
+ local_system_freq_offset,
+ nominal_clock_rate, local_clock);
+ if (this->doSyntonization()) {
+ this->adjustClockRate(0, local_clock,
+ device_time, 0, false);
+ }
+
+ if (_hw_timestamper != NULL
+ && _initial_clock_offset != 0) {
+ if (adj_up) {
+ _hw_timestamper->HWTimestamper_adjclockrate2
+ (_current_clock_offset += 2500);
+ } else {
+ _hw_timestamper->HWTimestamper_adjclockrate2
+ (_current_clock_offset -= 2500);
+ }
+ XPTPD_INFO("Adjust clock rate current: %d",
+ _current_clock_offset);
+ }
+ if (_current_clock_offset >
+ _initial_clock_offset + 5000000
+ || _current_clock_offset <
+ _initial_clock_offset - 5000000) {
+ adj_up = !adj_up;
+ }
+ // 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);
+ XPTPD_INFO("Sent SYNC message");
+
+ int ts_good;
+ int iter = 2;
+ Timestamp sync_timestamp;
+ unsigned sync_timestamp_counter_value;
+ long req = 1000; // = 1 ms
+ XPTPD_INFO("Start TS Read");
+ ts_good =
+ getTxTimestamp(sync, sync_timestamp,
+ sync_timestamp_counter_value,
+ false);
+ XPTPD_INFO("Done TS Read");
+ while (ts_good != 0 && iter-- != 0) {
+ timer->sleep(req);
+ if (ts_good != -72 && iter < 1)
+ fprintf(stderr,
+ "Error (TX) timestamping Sync (Retrying), error=%d\n",
+ ts_good);
+ ts_good =
+ getTxTimestamp(sync, sync_timestamp,
+ sync_timestamp_counter_value,
+ iter == 0);
+ req *= 2;
+ }
+ putTxLock();
+
+ if (ts_good != 0) {
+ char msg
+ [HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE];
+ getExtendedError(msg);
+ fprintf(stderr,
+ "Error (TX) timestamping Sync, error=%d\n%s",
+ ts_good, msg);
+ //_exit(-1);
+ }
+
+ if (ts_good == 0) {
+ XPTPD_INFO("Successful Sync timestamp");
+ XPTPD_INFO("Seconds: %u",
+ sync_timestamp.seconds_ls);
+ XPTPD_INFO("Nanoseconds: %u",
+ sync_timestamp.nanoseconds);
+ } else {
+ XPTPD_INFO
+ ("*** Unsuccessful Sync timestamp");
+ }
+
+ PTPMessageFollowUp *follow_up;
+ if (ts_good == 0) {
+ follow_up =
+ new PTPMessageFollowUp(this);
+ PortIdentity dest_id;
+ getPortIdentity(dest_id);
+ follow_up->setPortIdentity(&dest_id);
+ follow_up->setSequenceId(sync->getSequenceId());
+ follow_up->setPreciseOriginTimestamp(sync_timestamp);
+ follow_up->sendPort(this, NULL);
+ delete follow_up;
+ } else {
+ // Re-add the timer, since we failed re-send sooner?
+ //clock->addEventTimer( this, SYNC_INTERVAL_TIMEOUT_EXPIRES, (unsigned long long) (pow(2,getSyncInterval())*1000000000.0));
+ }
+ delete sync;
+ }
+ }
+ clock->addEventTimer(this, SYNC_INTERVAL_TIMEOUT_EXPIRES,
+ (unsigned long
+ long)(pow((double)2,
+ getSyncInterval()) *
+ 1000000000.0));
+ break;
+ case ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES:
+ 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);
+ clock->setGrandmasterPortIdentity(gmId);
+ getPortIdentity(dest_id);
+ annc->setPortIdentity(&dest_id);
+ annc->sendPort(this, NULL);
+ delete annc;
+ }
+ clock->addEventTimer(this, ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES,
+ (unsigned)(pow
+ ((double)2,
+ getAnnounceInterval()) *
+ 1000000000.0));
+ break;
+ case FAULT_DETECTED:
+ XPTPD_INFO("Received FAULT_DETECTED event");
+ break;
+ case PDELAY_DEFERRED_PROCESSING:
+ pdelay_rx_lock->lock();
+ if (last_pdelay_resp_fwup == NULL) {
+ fprintf(stderr, "PDelay Response Followup is NULL!\n");
+ 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:
+ setAsCapable(false);
+ break;
+ default:
+ XPTPD_INFO
+ ("Unhandled event type in IEEE1588Port::processEvent(), %d",
+ e);
+ break;
+ }
+ return;
+}
+
+PTPMessageAnnounce *IEEE1588Port::calculateERBest(void)
+{
+ if (qualified_announce.empty()) {
+ return NULL;
+ }
+ if (qualified_announce.size() == 1) {
+ return qualified_announce.front();
+ }
+
+ AnnounceList_t::iterator iter_l = qualified_announce.begin();
+ PTPMessageAnnounce *best = *iter_l;
+ ++iter_l;
+ while (iter_l != qualified_announce.end()) {
+ if ((*iter_l)->isBetterThan(best))
+ best = *iter_l;
+ iter_l = qualified_announce.erase(iter_l);
+ }
+
+ return best;
+}
+
+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::recommendState(PortState state, bool changed_master)
+{
+ switch (state) {
+ case PTP_MASTER:
+ if (port_state != PTP_MASTER) {
+ port_state = PTP_MASTER;
+ // Start announce receipt timeout timer
+ // Start sync receipt timeout timer
+ clock->addEventTimer(this,
+ ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES,
+ 8000000);
+ clock->addEventTimer(this,
+ SYNC_INTERVAL_TIMEOUT_EXPIRES,
+ 8000000);
+ fprintf(stderr, "Switching to Master\n");
+ } else {
+ port_state = PTP_MASTER;
+ }
+ break;
+ case PTP_SLAVE:
+ // Stop sending announce messages
+ // Stop sending sync messages
+ if (port_state != PTP_SLAVE) {
+ port_state = PTP_SLAVE;
+ clock->deleteEventTimer(this,
+ ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES);
+ clock->deleteEventTimer(this,
+ SYNC_INTERVAL_TIMEOUT_EXPIRES);
+ clock->addEventTimer(this, SYNC_RECEIPT_TIMEOUT_EXPIRES,
+ (SYNC_RECEIPT_TIMEOUT_MULTIPLIER *
+ (unsigned long
+ long)(pow((double)2,
+ getSyncInterval()) *
+ 1000000000.0)));
+ clock->addEventTimer(this,
+ ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES,
+ (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER
+ *
+ (unsigned long
+ long)(pow((double)2,
+ getAnnounceInterval())
+ * 1000000000.0)));
+ fprintf(stderr, "Switching to Slave\n");
+ } else {
+ if (changed_master) {
+ port_state = PTP_SLAVE;
+ } else {
+ port_state = PTP_SLAVE;
+ }
+ }
+ break;
+ default:
+ XPTPD_INFO
+ ("Invalid state change requested by call to 1588Port::recommendState()");
+ break;
+ }
+ return;
+}
+
+#define FIR_SAMPLE_TIME 1 // Seconds
+
+int IEEE1588Port::calcMasterLocalClockRateDifference(signed long long offset,
+ Timestamp sync_time)
+{
+ long long inter_sync_time;
+ signed long long offset_delta;
+ int ppt_offset;
+
+ XPTPD_INFO("Calculated master to local PTP clock rate difference");
+
+ if (!_master_local_freq_offset_init) {
+ _prev_sync_time = sync_time;
+ _prev_master_local_offset = offset;
+
+ _master_local_freq_offset_init = true;
+
+ return 0;
+ }
+
+ inter_sync_time =
+ TIMESTAMP_TO_NS(sync_time) - TIMESTAMP_TO_NS(_prev_sync_time);
+ offset_delta = offset - _prev_master_local_offset;
+
+ if (rate_offset_array == NULL) {
+ rate_offset_array_size = 4;
+ ++rate_offset_array_size;
+ rate_offset_array = new int32_t[rate_offset_array_size];
+ rate_offset_count = 0;
+ rate_offset_index = 0;
+ }
+ //fprintf( stderr, "Calculated master to local PTP clock rate difference, offset=%lld,sync_time = %lld\n", offset_delta, inter_sync_time );
+
+ if (inter_sync_time != 0) {
+ //fprintf( stderr, "Offset Delta: %lld, IST: %llu(%llu,%llu)\n", offset_delta, inter_sync_time, TIMESTAMP_TO_NS(sync_time),TIMESTAMP_TO_NS(_prev_sync_time) );
+ ppt_offset =
+ int (((offset_delta * 1000000000000LL) / inter_sync_time));
+ } else {
+ ppt_offset = 0;
+ }
+
+ _prev_sync_time = sync_time;
+ _prev_master_local_offset = offset;
+
+ return ppt_offset;
+}
+
+int IEEE1588Port::calcLocalSystemClockRateDifference(signed long long offset,
+ Timestamp system_time)
+{
+ unsigned long long inter_system_time;
+ signed long long offset_delta;
+ int ppt_offset;
+
+ XPTPD_INFO("Calculated local to system clock rate difference");
+
+ if (!_local_system_freq_offset_init) {
+ _prev_system_time = system_time;
+ _prev_local_system_offset = offset;
+
+ _local_system_freq_offset_init = true;
+
+ return 0;
+ }
+
+ inter_system_time =
+ TIMESTAMP_TO_NS(system_time) - TIMESTAMP_TO_NS(_prev_system_time);
+ offset_delta = offset - _prev_local_system_offset;
+
+ if (inter_system_time != 0) {
+ ppt_offset =
+ int (((offset_delta * 1000000000000LL) /
+ (int64_t) inter_system_time));
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() offset delta: %Ld",
+ offset_delta);
+ } else {
+ ppt_offset = 0;
+ offset_delta = 0;
+ }
+
+ if (inter_system_time != 0) {
+ XPTPD_INFO("Calculation Step: %Ld",
+ ((offset_delta * 1000000000000LL) /
+ (int64_t) inter_system_time));
+ }
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() offset: %Ld",
+ offset);
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() prev offset: %ld",
+ _prev_local_system_offset);
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() system time: %u,%u",
+ system_time.seconds_ls, system_time.nanoseconds);
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() prev system time: %u,%u",
+ _prev_system_time.seconds_ls, _prev_system_time.nanoseconds);
+ XPTPD_INFO
+ ("IEEE1588Port::calcLocalSystemClockRateDifference() inter-system time: %Lu",
+ inter_system_time);
+ XPTPD_INFO("IEEE1588Port::calcLocalSystemClockRateDifference() PPT: %d",
+ ppt_offset);
+
+ _prev_system_time = system_time;
+ _prev_local_system_offset = offset;
+
+ return ppt_offset;
+}
+
+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->getSequenceId(), 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->getSequenceId(), timestamp,
+ counter_value, last);
+}
+
+int IEEE1588Port::getTxTimestamp(PortIdentity * sourcePortIdentity,
+ uint16_t sequenceId, Timestamp & timestamp,
+ unsigned &counter_value, bool last)
+{
+ if (_hw_timestamper) {
+ return
+ _hw_timestamper->HWTimestamper_txtimestamp
+ (sourcePortIdentity, sequenceId, timestamp, counter_value,
+ last);
+ }
+ timestamp = clock->getSystemTime();
+ return true;
+}
+
+int IEEE1588Port::getRxTimestamp(PortIdentity * sourcePortIdentity,
+ uint16_t sequenceId, Timestamp & timestamp,
+ unsigned &counter_value, bool last)
+{
+ if (_hw_timestamper) {
+ return
+ _hw_timestamper->HWTimestamper_rxtimestamp
+ (sourcePortIdentity, sequenceId, timestamp, counter_value,
+ last);
+ }
+ timestamp = clock->getSystemTime();
+ return true;
+}
--- /dev/null
+/******************************************************************************
+
+ 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_clock.hpp>
+#include <avbts_message.hpp>
+#include <avbts_port.hpp>
+#include <avbts_ostimer.hpp>
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <time.h>
+
+PTPMessageCommon::PTPMessageCommon(IEEE1588Port * port)
+{
+ // Fill in fields using port/clock dataset as a template
+ versionPTP = GPTP_VERSION;
+ versionNetwork = PTP_NETWORK_VERSION;
+ domainNumber = port->getClock()->getDomain();
+ // Set flags as necessary
+ memset(flags, 0, PTP_FLAGS_LENGTH);
+ correctionField = 0;
+ _gc = false;
+ sourcePortIdentity = new PortIdentity();
+
+ return;
+}
+
+// Determine whether the message was sent by given communication technology, uuid, and port id fields
+bool PTPMessageCommon::isSenderEqual(PortIdentity portIdentity)
+{
+ return portIdentity == *sourcePortIdentity;
+}
+
+PTPMessageCommon *buildPTPMessage(char *buf, int size,
+ LinkLayerAddress * remote,
+ IEEE1588Port * port)
+{
+ OSTimer *timer = port->getTimerFactory()->createTimer();
+ PTPMessageCommon *msg = NULL;
+ MessageType messageType;
+ unsigned char tspec_msg_t = 0;
+
+ uint16_t sequenceId;
+ PortIdentity *sourcePortIdentity;
+ Timestamp timestamp(0, 0, 0);
+ unsigned counter_value = 0;
+
+#if PTP_DEBUG
+ {
+ int i;
+ XPTPD_INFO("Packet Dump:\n");
+ for (i = 0; i < size; ++i) {
+ fprintf(stderr, "%hhx\t", buf[i]);
+ if (i % 8 == 7)
+ fprintf(stderr, "\n");
+ }
+ if (i % 8 != 0)
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ memcpy(&tspec_msg_t,
+ buf + PTP_COMMON_HDR_TRANSSPEC_MSGTYPE(PTP_COMMON_HDR_OFFSET),
+ sizeof(tspec_msg_t));
+ messageType = (MessageType) (tspec_msg_t & 0xF);
+
+ sourcePortIdentity = new PortIdentity((uint8_t *) (buf +
+ PTP_COMMON_HDR_SOURCE_CLOCK_ID
+ (PTP_COMMON_HDR_OFFSET)),
+ (uint16_t *) (buf +
+ PTP_COMMON_HDR_SOURCE_PORT_ID
+ (PTP_COMMON_HDR_OFFSET)));
+
+ memcpy(&(sequenceId),
+ buf + PTP_COMMON_HDR_SEQUENCE_ID(PTP_COMMON_HDR_OFFSET),
+ sizeof(sequenceId));
+ sequenceId = PLAT_ntohs(sequenceId);
+
+ //fprintf( stderr, "Captured Sequence Id: %u\n", sequenceId );
+ XPTPD_INFO("Captured Sequence Id: %u", sequenceId);
+
+ if (!(messageType >> 3)) {
+ int iter = 2;
+ long req = 1000; // = 1 ms
+ int ts_good =
+ port->getRxTimestamp(sourcePortIdentity, sequenceId,
+ timestamp, counter_value, false);
+ while (ts_good != 0 && iter-- != 0) {
+ // Waits at least 1 time slice regardless of size of 'req'
+ timer->sleep(req);
+ if (ts_good != 72)
+ fprintf(stderr,
+ "Error (RX) timestamping RX event packet (Retrying), error=%d\n",
+ ts_good);
+ ts_good =
+ port->getRxTimestamp(sourcePortIdentity, sequenceId,
+ timestamp, counter_value,
+ iter == 0);
+ req *= 2;
+ }
+ if (ts_good != 0) {
+ char msg[HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE];
+ port->getExtendedError(msg);
+ XPTPD_ERROR
+ ("*** Received an event packet but cannot retrieve timestamp, discarding. messageType=%u,error=%d\n%s",
+ messageType, ts_good, msg);
+ //_exit(-1);
+ return NULL;
+ }
+
+ else {
+ XPTPD_INFO("Timestamping event packet");
+ }
+
+ }
+
+ switch (messageType) {
+ case SYNC_MESSAGE:
+
+ //fprintf( stderr, "*** Received Sync message\n" );
+ //printf( "Sync RX timestamp = %hu,%u,%u\n", timestamp.seconds_ms, timestamp.seconds_ls, timestamp.nanoseconds );
+ XPTPD_INFO("*** Received Sync message");
+
+ // Be sure buffer is the correction size
+ if (size < PTP_COMMON_HDR_LENGTH + PTP_SYNC_LENGTH) {
+ goto done;
+ }
+ {
+ PTPMessageSync *sync_msg = new PTPMessageSync();
+ sync_msg->messageType = messageType;
+ // Copy in v2 sync specific fields
+ memcpy(&(sync_msg->originTimestamp.seconds_ms),
+ buf + PTP_SYNC_SEC_MS(PTP_SYNC_OFFSET),
+ sizeof(sync_msg->originTimestamp.seconds_ms));
+ memcpy(&(sync_msg->originTimestamp.seconds_ls),
+ buf + PTP_SYNC_SEC_LS(PTP_SYNC_OFFSET),
+ sizeof(sync_msg->originTimestamp.seconds_ls));
+ memcpy(&(sync_msg->originTimestamp.nanoseconds),
+ buf + PTP_SYNC_NSEC(PTP_SYNC_OFFSET),
+ sizeof(sync_msg->originTimestamp.nanoseconds));
+ msg = sync_msg;
+ }
+ break;
+ case FOLLOWUP_MESSAGE:
+
+ XPTPD_INFO("*** Received Follow Up message");
+
+ // Be sure buffer is the correction size
+ if (size < PTP_COMMON_HDR_LENGTH + PTP_FOLLOWUP_LENGTH) {
+ goto done;
+ }
+ {
+ PTPMessageFollowUp *followup_msg =
+ new PTPMessageFollowUp();
+ followup_msg->messageType = messageType;
+ // Copy in v2 sync specific fields
+ memcpy(&
+ (followup_msg->
+ preciseOriginTimestamp.seconds_ms),
+ buf + PTP_FOLLOWUP_SEC_MS(PTP_FOLLOWUP_OFFSET),
+ sizeof(followup_msg->
+ preciseOriginTimestamp.seconds_ms));
+ memcpy(&
+ (followup_msg->
+ preciseOriginTimestamp.seconds_ls),
+ buf + PTP_FOLLOWUP_SEC_LS(PTP_FOLLOWUP_OFFSET),
+ sizeof(followup_msg->
+ preciseOriginTimestamp.seconds_ls));
+ memcpy(&
+ (followup_msg->
+ preciseOriginTimestamp.nanoseconds),
+ buf + PTP_FOLLOWUP_NSEC(PTP_FOLLOWUP_OFFSET),
+ sizeof(followup_msg->
+ preciseOriginTimestamp.nanoseconds));
+
+ followup_msg->preciseOriginTimestamp.seconds_ms =
+ PLAT_ntohs(followup_msg->
+ preciseOriginTimestamp.seconds_ms);
+ followup_msg->preciseOriginTimestamp.seconds_ls =
+ PLAT_ntohl(followup_msg->
+ preciseOriginTimestamp.seconds_ls);
+ followup_msg->preciseOriginTimestamp.nanoseconds =
+ PLAT_ntohl(followup_msg->
+ preciseOriginTimestamp.nanoseconds);
+
+ msg = followup_msg;
+ }
+ break;
+ case PATH_DELAY_REQ_MESSAGE:
+
+ XPTPD_INFO("*** Received PDelay Request message");
+
+ // Be sure buffer is the correction size
+ if (size < PTP_COMMON_HDR_LENGTH + PTP_PDELAY_REQ_LENGTH
+ && /* For Broadcom compatibility */ size != 46) {
+ goto done;
+ }
+ {
+ PTPMessagePathDelayReq *pdelay_req_msg =
+ new PTPMessagePathDelayReq();
+ pdelay_req_msg->messageType = messageType;
+
+#if 0
+ // The origin timestamp for PDelay Request packets has been eliminated since it is unused
+ // Copy in v2 PDelay Request specific fields
+ memcpy(&(pdelay_req_msg->originTimestamp.seconds_ms),
+ buf +
+ PTP_PDELAY_REQ_SEC_MS(PTP_PDELAY_REQ_OFFSET),
+ sizeof(pdelay_req_msg->
+ originTimestamp.seconds_ms));
+ memcpy(&(pdelay_req_msg->originTimestamp.seconds_ls),
+ buf +
+ PTP_PDELAY_REQ_SEC_LS(PTP_PDELAY_REQ_OFFSET),
+ sizeof(pdelay_req_msg->
+ originTimestamp.seconds_ls));
+ memcpy(&(pdelay_req_msg->originTimestamp.nanoseconds),
+ buf + PTP_PDELAY_REQ_NSEC(PTP_PDELAY_REQ_OFFSET),
+ sizeof(pdelay_req_msg->
+ originTimestamp.nanoseconds));
+
+ pdelay_req_msg->originTimestamp.seconds_ms =
+ PLAT_ntohs(pdelay_req_msg->
+ originTimestamp.seconds_ms);
+ pdelay_req_msg->originTimestamp.seconds_ls =
+ PLAT_ntohl(pdelay_req_msg->
+ originTimestamp.seconds_ls);
+ pdelay_req_msg->originTimestamp.nanoseconds =
+ PLAT_ntohl(pdelay_req_msg->
+ originTimestamp.nanoseconds);
+#endif
+
+ msg = pdelay_req_msg;
+ }
+ break;
+ case PATH_DELAY_RESP_MESSAGE:
+
+ XPTPD_INFO("*** Received PDelay Response message, %u, %u, %u",
+ timestamp.seconds_ls, timestamp.nanoseconds,
+ sequenceId);
+
+ // Be sure buffer is the correction size
+ if (size < PTP_COMMON_HDR_LENGTH + PTP_PDELAY_RESP_LENGTH) {
+ goto done;
+ }
+ {
+ PTPMessagePathDelayResp *pdelay_resp_msg =
+ new PTPMessagePathDelayResp();
+ pdelay_resp_msg->messageType = messageType;
+ // Copy in v2 PDelay Response specific fields
+ pdelay_resp_msg->requestingPortIdentity =
+ new PortIdentity((uint8_t *) buf +
+ PTP_PDELAY_RESP_REQ_CLOCK_ID
+ (PTP_PDELAY_RESP_OFFSET),
+ (uint16_t *) (buf +
+ PTP_PDELAY_RESP_REQ_PORT_ID
+ (PTP_PDELAY_RESP_OFFSET)));
+
+#ifdef DEBUG
+ for (int n = 0; n < PTP_CLOCK_IDENTITY_LENGTH; ++n) { // MMM
+ fprintf(stderr, "%c",
+ pdelay_resp_msg->
+ requestingPortIdentity.clockIdentity
+ [n]);
+ }
+#endif
+
+ memcpy(&
+ (pdelay_resp_msg->
+ requestReceiptTimestamp.seconds_ms),
+ buf +
+ PTP_PDELAY_RESP_SEC_MS(PTP_PDELAY_RESP_OFFSET),
+ sizeof(pdelay_resp_msg->
+ requestReceiptTimestamp.seconds_ms));
+ memcpy(&
+ (pdelay_resp_msg->
+ requestReceiptTimestamp.seconds_ls),
+ buf +
+ PTP_PDELAY_RESP_SEC_LS(PTP_PDELAY_RESP_OFFSET),
+ sizeof(pdelay_resp_msg->
+ requestReceiptTimestamp.seconds_ls));
+ memcpy(&
+ (pdelay_resp_msg->
+ requestReceiptTimestamp.nanoseconds),
+ buf +
+ PTP_PDELAY_RESP_NSEC(PTP_PDELAY_RESP_OFFSET),
+ sizeof(pdelay_resp_msg->
+ requestReceiptTimestamp.nanoseconds));
+
+ pdelay_resp_msg->requestReceiptTimestamp.seconds_ms =
+ PLAT_ntohs(pdelay_resp_msg->requestReceiptTimestamp.seconds_ms);
+ pdelay_resp_msg->requestReceiptTimestamp.seconds_ls =
+ PLAT_ntohl(pdelay_resp_msg->requestReceiptTimestamp.seconds_ls);
+ pdelay_resp_msg->requestReceiptTimestamp.nanoseconds =
+ PLAT_ntohl(pdelay_resp_msg->requestReceiptTimestamp.nanoseconds);
+
+ msg = pdelay_resp_msg;
+ }
+ break;
+ case PATH_DELAY_FOLLOWUP_MESSAGE:
+
+ XPTPD_INFO("*** Received PDelay Response FollowUp message");
+
+ // Be sure buffer is the correction size
+// if( size < PTP_COMMON_HDR_LENGTH + PTP_PDELAY_FOLLOWUP_LENGTH ) {
+// goto done;
+// }
+ {
+ PTPMessagePathDelayRespFollowUp *pdelay_resp_fwup_msg =
+ new PTPMessagePathDelayRespFollowUp();
+ pdelay_resp_fwup_msg->messageType = messageType;
+ // Copy in v2 PDelay Response specific fields
+ pdelay_resp_fwup_msg->requestingPortIdentity =
+ new PortIdentity((uint8_t *) buf +
+ PTP_PDELAY_FOLLOWUP_REQ_CLOCK_ID
+ (PTP_PDELAY_RESP_OFFSET),
+ (uint16_t *) (buf +
+ PTP_PDELAY_FOLLOWUP_REQ_PORT_ID
+ (PTP_PDELAY_FOLLOWUP_OFFSET)));
+
+ memcpy(&
+ (pdelay_resp_fwup_msg->
+ responseOriginTimestamp.seconds_ms),
+ buf +
+ PTP_PDELAY_FOLLOWUP_SEC_MS
+ (PTP_PDELAY_FOLLOWUP_OFFSET),
+ sizeof
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ seconds_ms));
+ memcpy(&
+ (pdelay_resp_fwup_msg->
+ responseOriginTimestamp.seconds_ls),
+ buf +
+ PTP_PDELAY_FOLLOWUP_SEC_LS
+ (PTP_PDELAY_FOLLOWUP_OFFSET),
+ sizeof
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ seconds_ls));
+ memcpy(&
+ (pdelay_resp_fwup_msg->
+ responseOriginTimestamp.nanoseconds),
+ buf +
+ PTP_PDELAY_FOLLOWUP_NSEC
+ (PTP_PDELAY_FOLLOWUP_OFFSET),
+ sizeof
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ nanoseconds));
+
+ pdelay_resp_fwup_msg->
+ responseOriginTimestamp.seconds_ms =
+ PLAT_ntohs
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ seconds_ms);
+ pdelay_resp_fwup_msg->
+ responseOriginTimestamp.seconds_ls =
+ PLAT_ntohl
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ seconds_ls);
+ pdelay_resp_fwup_msg->
+ responseOriginTimestamp.nanoseconds =
+ PLAT_ntohl
+ (pdelay_resp_fwup_msg->responseOriginTimestamp.
+ nanoseconds);
+
+ msg = pdelay_resp_fwup_msg;
+ }
+ break;
+ case ANNOUNCE_MESSAGE:
+ {
+ PTPMessageAnnounce *annc = new PTPMessageAnnounce();
+ annc->messageType = messageType;
+
+ memcpy(&(annc->currentUtcOffset),
+ buf +
+ PTP_ANNOUNCE_CURRENT_UTC_OFFSET
+ (PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->currentUtcOffset));
+ annc->currentUtcOffset =
+ PLAT_ntohs(annc->currentUtcOffset);
+ memcpy(&(annc->grandmasterPriority1),
+ buf +
+ PTP_ANNOUNCE_GRANDMASTER_PRIORITY1
+ (PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->grandmasterPriority1));
+ memcpy(annc->clockQuality,
+ buf +
+ PTP_ANNOUNCE_GRANDMASTER_CLOCK_QUALITY
+ (PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->clockQuality));
+ annc->clockQuality->offsetScaledLogVariance =
+ PLAT_ntohs(annc->
+ clockQuality->offsetScaledLogVariance);
+ memcpy(&(annc->grandmasterPriority2),
+ buf +
+ PTP_ANNOUNCE_GRANDMASTER_PRIORITY2
+ (PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->grandmasterPriority2));
+ memcpy(&(annc->grandmasterIdentity),
+ buf +
+ PTP_ANNOUNCE_GRANDMASTER_IDENTITY
+ (PTP_ANNOUNCE_OFFSET),
+ PTP_CLOCK_IDENTITY_LENGTH);
+ memcpy(&(annc->stepsRemoved),
+ buf +
+ PTP_ANNOUNCE_STEPS_REMOVED(PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->stepsRemoved));
+ annc->stepsRemoved = PLAT_ntohs(annc->stepsRemoved);
+ memcpy(&(annc->timeSource),
+ buf +
+ PTP_ANNOUNCE_TIME_SOURCE(PTP_ANNOUNCE_OFFSET),
+ sizeof(annc->timeSource));
+
+ msg = annc;
+ }
+ break;
+ default:
+
+ XPTPD_ERROR("Received unsupported message type, %d",
+ (int)messageType);
+
+ goto done;
+ }
+
+ msg->_gc = false;
+
+ // Copy in common header fields
+ memcpy(&(msg->versionPTP),
+ buf + PTP_COMMON_HDR_PTP_VERSION(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->versionPTP));
+ memcpy(&(msg->messageLength),
+ buf + PTP_COMMON_HDR_MSG_LENGTH(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->messageLength));
+ msg->messageLength = PLAT_ntohs(msg->messageLength);
+ memcpy(&(msg->domainNumber),
+ buf + PTP_COMMON_HDR_DOMAIN_NUMBER(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->domainNumber));
+ memcpy(&(msg->flags), buf + PTP_COMMON_HDR_FLAGS(PTP_COMMON_HDR_OFFSET),
+ PTP_FLAGS_LENGTH);
+ memcpy(&(msg->correctionField),
+ buf + PTP_COMMON_HDR_CORRECTION(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->correctionField));
+ msg->correctionField = bswap_64(msg->correctionField); // Assume LE machine
+ msg->sourcePortIdentity = sourcePortIdentity;
+ msg->sequenceId = sequenceId;
+ memcpy(&(msg->control),
+ buf + PTP_COMMON_HDR_CONTROL(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->control));
+ memcpy(&(msg->logMeanMessageInterval),
+ buf + PTP_COMMON_HDR_LOG_MSG_INTRVL(PTP_COMMON_HDR_OFFSET),
+ sizeof(msg->logMeanMessageInterval));
+
+ port->addSockAddrMap(msg->sourcePortIdentity, remote);
+
+ msg->_timestamp = timestamp;
+ msg->_timestamp_counter_value = counter_value;
+
+ done:
+ return msg;
+}
+
+void PTPMessageCommon::processMessage(IEEE1588Port * port)
+{
+ _gc = true;
+ return;
+}
+
+void PTPMessageCommon::buildCommonHeader(uint8_t * buf)
+{
+ unsigned char tspec_msg_t;
+ tspec_msg_t = messageType | 0x10;
+ //tspec_msg_t = messageType;
+ long long correctionField_BE = bswap_64(correctionField); // Assume LE machine
+ uint16_t messageLength_NO = PLAT_htons(messageLength);
+
+ memcpy(buf + PTP_COMMON_HDR_TRANSSPEC_MSGTYPE(PTP_COMMON_HDR_OFFSET),
+ &tspec_msg_t, sizeof(tspec_msg_t));
+ memcpy(buf + PTP_COMMON_HDR_PTP_VERSION(PTP_COMMON_HDR_OFFSET),
+ &versionPTP, sizeof(versionPTP));
+ memcpy(buf + PTP_COMMON_HDR_MSG_LENGTH(PTP_COMMON_HDR_OFFSET),
+ &messageLength_NO, sizeof(messageLength_NO));
+ memcpy(buf + PTP_COMMON_HDR_DOMAIN_NUMBER(PTP_COMMON_HDR_OFFSET),
+ &domainNumber, sizeof(domainNumber));
+ memcpy(buf + PTP_COMMON_HDR_FLAGS(PTP_COMMON_HDR_OFFSET), &flags,
+ PTP_FLAGS_LENGTH);
+ memcpy(buf + PTP_COMMON_HDR_CORRECTION(PTP_COMMON_HDR_OFFSET),
+ &correctionField_BE, sizeof(correctionField));
+
+ sourcePortIdentity->getClockIdentityString((char *)buf +
+ PTP_COMMON_HDR_SOURCE_CLOCK_ID
+ (PTP_COMMON_HDR_OFFSET));
+ sourcePortIdentity->getPortNumberNO((uint16_t *) (buf +
+ PTP_COMMON_HDR_SOURCE_PORT_ID
+ (PTP_COMMON_HDR_OFFSET)));
+
+ XPTPD_INFO("Sending Sequence Id: %u", sequenceId);
+ sequenceId = PLAT_htons(sequenceId);
+ memcpy(buf + PTP_COMMON_HDR_SEQUENCE_ID(PTP_COMMON_HDR_OFFSET),
+ &sequenceId, sizeof(sequenceId));
+ sequenceId = PLAT_ntohs(sequenceId);
+ memcpy(buf + PTP_COMMON_HDR_CONTROL(PTP_COMMON_HDR_OFFSET), &control,
+ sizeof(control));
+ memcpy(buf + PTP_COMMON_HDR_LOG_MSG_INTRVL(PTP_COMMON_HDR_OFFSET),
+ &logMeanMessageInterval, sizeof(logMeanMessageInterval));
+
+ return;
+}
+
+void PTPMessageCommon::getPortIdentity(PortIdentity * identity)
+{
+ *identity = *sourcePortIdentity;
+}
+
+void PTPMessageCommon::setPortIdentity(PortIdentity * identity)
+{
+ *sourcePortIdentity = *identity;
+}
+
+PTPMessageCommon::~PTPMessageCommon(void)
+{
+ delete sourcePortIdentity;
+ return;
+}
+
+PTPMessageAnnounce::PTPMessageAnnounce(void)
+{
+ clockQuality = new ClockQuality();
+}
+
+PTPMessageAnnounce::~PTPMessageAnnounce(void)
+{
+ delete clockQuality;
+}
+
+bool PTPMessageAnnounce::isBetterThan(PTPMessageAnnounce * msg)
+{
+ unsigned char this1[14];
+ unsigned char that1[14];
+ uint16_t tmp;
+
+ this1[0] = grandmasterPriority1;
+ that1[0] = msg->getGrandmasterPriority1();
+
+ this1[1] = clockQuality->cq_class;
+ that1[1] = msg->getGrandmasterClockQuality()->cq_class;
+
+ this1[2] = clockQuality->clockAccuracy;
+ that1[2] = msg->getGrandmasterClockQuality()->clockAccuracy;
+
+ tmp = clockQuality->offsetScaledLogVariance;
+ tmp = PLAT_htons(tmp);
+ memcpy(this1 + 3, &tmp, sizeof(tmp));
+ tmp = msg->getGrandmasterClockQuality()->offsetScaledLogVariance;
+ tmp = PLAT_htons(tmp);
+ memcpy(that1 + 3, &tmp, sizeof(tmp));
+
+ this1[5] = grandmasterPriority2;
+ that1[5] = msg->getGrandmasterPriority2();
+
+ this->getGrandmasterIdentity((char *)this1 + 6);
+ msg->getGrandmasterIdentity((char *)that1 + 6);
+
+#if 0
+ fprintf(stderr, "Us: ");
+ for (int i = 0; i < 14; ++i)
+ fprintf(stderr, "%hhx", this1[i]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Them: ");
+ for (int i = 0; i < 14; ++i)
+ fprintf(stderr, "%hhx", that1[i]);
+ fprintf(stderr, "\n");
+#endif
+
+ return (memcmp(this1, that1, 14) < 0) ? true : false;
+}
+
+ PTPMessageSync::PTPMessageSync(IEEE1588Port * port):PTPMessageCommon(port)
+{
+ messageType = SYNC_MESSAGE; // This is an event message
+ sequenceId = port->getNextSyncSequenceId();
+ control = SYNC;
+
+ flags[PTP_ASSIST_BYTE] |= (0x1 << PTP_ASSIST_BIT);
+
+ originTimestamp = port->getClock()->getTime();
+
+ logMeanMessageInterval = port->getSyncInterval();
+ return;
+}
+
+void PTPMessageSync::sendPort(IEEE1588Port * port, PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0x0;
+ Timestamp originTimestamp_BE;
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength = PTP_COMMON_HDR_LENGTH + PTP_SYNC_LENGTH;
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ // Get timestamp
+ originTimestamp = port->getClock()->getTime();
+ originTimestamp_BE.seconds_ms = PLAT_htons(originTimestamp.seconds_ms);
+ originTimestamp_BE.seconds_ls = PLAT_htonl(originTimestamp.seconds_ls);
+ originTimestamp_BE.nanoseconds =
+ PLAT_htonl(originTimestamp.nanoseconds);
+ // Copy in v2 sync specific fields
+ memcpy(buf_ptr + PTP_SYNC_SEC_MS(PTP_SYNC_OFFSET),
+ &(originTimestamp_BE.seconds_ms),
+ sizeof(originTimestamp.seconds_ms));
+ memcpy(buf_ptr + PTP_SYNC_SEC_LS(PTP_SYNC_OFFSET),
+ &(originTimestamp_BE.seconds_ls),
+ sizeof(originTimestamp.seconds_ls));
+ memcpy(buf_ptr + PTP_SYNC_NSEC(PTP_SYNC_OFFSET),
+ &(originTimestamp_BE.nanoseconds),
+ sizeof(originTimestamp.nanoseconds));
+
+ port->sendEventPort(buf_t, messageLength, MCAST_OTHER, destIdentity);
+
+ return;
+}
+
+ PTPMessageAnnounce::PTPMessageAnnounce(IEEE1588Port * port):PTPMessageCommon
+ (port)
+{
+ messageType = ANNOUNCE_MESSAGE; // This is an event message
+ sequenceId = port->getNextAnnounceSequenceId();
+ ClockIdentity id;
+ control = MESSAGE_OTHER;
+
+ id = port->getClock()->getClockIdentity();
+ tlv.setClockIdentity(&id);
+
+ currentUtcOffset = port->getClock()->getCurrentUtcOffset();
+ grandmasterPriority1 = port->getClock()->getPriority1();
+ grandmasterPriority2 = port->getClock()->getPriority2();
+ clockQuality = new ClockQuality();
+ *clockQuality = port->getClock()->getClockQuality();
+ stepsRemoved = 0;
+ timeSource = port->getClock()->getTimeSource();
+ ClockIdentity clock_identity;
+ clock_identity = port->getClock()->getClockIdentity();
+ clock_identity.getIdentityString(grandmasterIdentity);
+
+ logMeanMessageInterval = port->getAnnounceInterval();
+ return;
+}
+
+void PTPMessageAnnounce::sendPort(IEEE1588Port * port,
+ PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0x0;
+
+ uint16_t currentUtcOffset_l = PLAT_htons(currentUtcOffset);
+ uint16_t stepsRemoved_l = PLAT_htons(stepsRemoved);
+ ClockQuality clockQuality_l = *clockQuality;
+ clockQuality_l.offsetScaledLogVariance =
+ PLAT_htons(clockQuality_l.offsetScaledLogVariance);
+
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength =
+ PTP_COMMON_HDR_LENGTH + PTP_ANNOUNCE_LENGTH + sizeof(tlv);
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ memcpy(buf_ptr + PTP_ANNOUNCE_CURRENT_UTC_OFFSET(PTP_ANNOUNCE_OFFSET),
+ ¤tUtcOffset_l, sizeof(currentUtcOffset));
+ memcpy(buf_ptr +
+ PTP_ANNOUNCE_GRANDMASTER_PRIORITY1(PTP_ANNOUNCE_OFFSET),
+ &grandmasterPriority1, sizeof(grandmasterPriority1));
+ memcpy(buf_ptr +
+ PTP_ANNOUNCE_GRANDMASTER_CLOCK_QUALITY(PTP_ANNOUNCE_OFFSET),
+ &clockQuality_l, sizeof(clockQuality));
+ memcpy(buf_ptr +
+ PTP_ANNOUNCE_GRANDMASTER_PRIORITY2(PTP_ANNOUNCE_OFFSET),
+ &grandmasterPriority2, sizeof(grandmasterPriority2));
+ port->getClock()->getGrandmasterIdentity((char *)buf_ptr +
+ PTP_ANNOUNCE_GRANDMASTER_IDENTITY
+ (PTP_ANNOUNCE_OFFSET));
+ memcpy(buf_ptr + PTP_ANNOUNCE_STEPS_REMOVED(PTP_ANNOUNCE_OFFSET),
+ &stepsRemoved_l, sizeof(stepsRemoved));
+ memcpy(buf_ptr + PTP_ANNOUNCE_TIME_SOURCE(PTP_ANNOUNCE_OFFSET),
+ &timeSource, sizeof(timeSource));
+ tlv.toByteString(buf_ptr + PTP_COMMON_HDR_LENGTH + PTP_ANNOUNCE_LENGTH);
+
+ port->sendGeneralPort(buf_t, messageLength, MCAST_OTHER, destIdentity);
+
+ return;
+}
+
+void PTPMessageAnnounce::processMessage(IEEE1588Port * port)
+{
+ // Delete announce receipt timeout
+ port->getClock()->deleteEventTimer(port,
+ ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES);
+
+ // Add message to the list
+ port->addQualifiedAnnounce(this);
+
+ port->getClock()->addEventTimer(port, ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES,
+ (unsigned long long)
+ (ANNOUNCE_RECEIPT_TIMEOUT_MULTIPLIER *
+ (pow
+ ((double)2,
+ port->getAnnounceInterval()) *
+ 1000000000.0)));
+ port->getClock()->addEventTimer(port, STATE_CHANGE_EVENT, 16000000);
+}
+
+void PTPMessageSync::processMessage(IEEE1588Port * port)
+{
+ Timestamp system_time;
+ Timestamp device_time;
+ int64_t delay;
+
+ signed long long local_system_offset;
+ signed long long scalar_offset;
+
+ int32_t local_clock_adjustment;
+ int32_t local_system_freq_offset;
+
+ // Expire any SYNC_RECEIPT timers that exist
+ port->getClock()->deleteEventTimer(port, SYNC_RECEIPT_TIMEOUT_EXPIRES);
+ if (port->getPortState() == PTP_INITIALIZING
+ || port->getPortState() == PTP_DISABLED) {
+ // Do nothing Sync messages should be ignored when in this state
+ return;
+ }
+ if (port->getPortState() == PTP_FAULTY) {
+ // According to spec recovery is implementation specific
+ port->recoverPort();
+ return;
+ }
+
+ XPTPD_INFO("PTP assist flag is not set, FLAGS[0,1] = %u,%u", flags[0],
+ flags[1]);
+
+// if( flags[PTP_ASSIST_BYTE] & (0x1<<PTP_ASSIST_BIT)) {
+ if (true) {
+ // If PTP_ASSIST flag is set, expect a follow-up message and do nothing
+ PTPMessageSync *old_sync = port->getLastSync();
+ if (old_sync != NULL) {
+ delete old_sync;
+ }
+ port->setLastSync(this);
+ _gc = false;
+ goto done;
+ } else {
+ _gc = true;
+ }
+
+ // Indicates invalid link delay, wait until link delay had been calculated
+ if ((delay = port->getLinkDelay()) == 3600000000000) {
+ printf
+ ("Got Sync/Follow-Up but Link Delay has not been computed\n");
+ goto done;
+ }
+#if 0
+ scalar_offset = _timestamp.nanoseconds +
+ (((unsigned long long)_timestamp.seconds_ms <<
+ sizeof(_timestamp.seconds_ls) * 8) +
+ _timestamp.seconds_ls) * 1000000000LL;
+ scalar_offset -=
+ originTimestamp.nanoseconds +
+ (((unsigned long long)originTimestamp.seconds_ms <<
+ sizeof(originTimestamp.seconds_ls) * 8) +
+ originTimestamp.seconds_ls) * 1000000000LL;
+#endif
+ scalar_offset =
+ TIMESTAMP_TO_NS(_timestamp) - TIMESTAMP_TO_NS(originTimestamp);
+ scalar_offset -= delay;
+#if 0
+ scalar_offset -= delay.nanoseconds +
+ (((unsigned long long)delay.seconds_ms << sizeof(delay.seconds_ls) *
+ 8) + delay.seconds_ls) * 1000000000LL;
+#endif
+ scalar_offset -= correctionField >> 16; // Fractional nanoseconds are dropped
+
+ // Otherwise synchronize clock with approximate time from Sync message
+ uint32_t local_clock;
+ uint32_t nominal_clock_rate;
+ uint32_t device_sync_time_offset;
+
+#if 0
+ Timestamp crstamp_device_time;
+ int64_t external_local_offset;
+ int32_t external_local_freq_offset;
+#endif
+
+ port->getDeviceTime(system_time, device_time, local_clock,
+ nominal_clock_rate);
+
+ // Adjust local_clock to correspond to _timestamp
+ device_sync_time_offset =
+ TIMESTAMP_TO_NS(device_time) - TIMESTAMP_TO_NS(_timestamp);
+ local_clock -=
+ device_sync_time_offset / (1000000000 / nominal_clock_rate);
+
+ XPTPD_INFO
+ ("ptp_message::sync::processMessage System time: %u,%u Device Time: %u,%u",
+ system_time.seconds_ls, system_time.nanoseconds,
+ device_time.seconds_ls, device_time.nanoseconds);
+
+ local_clock_adjustment =
+ port->calcMasterLocalClockRateDifference(scalar_offset, _timestamp);
+ port->setMasterRateOffset(local_clock_adjustment);
+
+ local_system_offset =
+ TIMESTAMP_TO_NS(system_time) - TIMESTAMP_TO_NS(device_time);
+#if 0
+ local_system_offset = system_time.nanoseconds +
+ (((unsigned long long)system_time.seconds_ms <<
+ sizeof(system_time.seconds_ls) * 8) +
+ system_time.seconds_ls) * 1000000000LL;
+ local_system_offset -=
+ device_time.nanoseconds +
+ (((unsigned long long)device_time.seconds_ms <<
+ sizeof(device_time.seconds_ls) * 8) +
+ device_time.seconds_ls) * 1000000000LL;
+#endif
+
+ local_system_freq_offset =
+ port->calcLocalSystemClockRateDifference(local_system_offset,
+ system_time);
+
+ TIMESTAMP_SUB_NS(system_time,
+ (device_sync_time_offset *
+ (1000000000000ULL +
+ local_system_freq_offset)) / 1000000000000ULL);
+
+ //port->getExternalClockRate( crstamp_device_time, external_local_offset, external_local_freq_offset );
+
+#if 0
+ port->getClock()->setMasterOffset(scalar_offset, _timestamp,
+ local_clock_adjustment,
+ local_system_offset, system_time,
+ local_system_freq_offset,
+ external_local_offset,
+ crstamp_device_time,
+ external_local_freq_offset);
+#endif
+ port->getClock()->setMasterOffset(scalar_offset, _timestamp,
+ local_clock_adjustment,
+ local_system_offset, system_time,
+ local_system_freq_offset,
+ nominal_clock_rate, local_clock);
+ //fprintf( stderr, "Master-Local Offset=%d\n", local_clock_adjustment );
+
+ if (port->doSyntonization()) {
+ port->adjustClockRate(local_clock_adjustment,
+ _timestamp_counter_value, originTimestamp,
+ scalar_offset, false);
+ }
+
+ done:
+ // Restart the SYNC_RECEIPT timer
+ port->getClock()->addEventTimer(port, SYNC_RECEIPT_TIMEOUT_EXPIRES,
+ (unsigned long long)
+ (SYNC_RECEIPT_TIMEOUT_MULTIPLIER *
+ ((double)
+ pow((double)2,
+ port->getSyncInterval()) *
+ 1000000000.0)));
+
+ return;
+}
+
+ PTPMessageFollowUp::PTPMessageFollowUp(IEEE1588Port * port):PTPMessageCommon
+ (port)
+{
+ messageType = FOLLOWUP_MESSAGE; // This is an event message
+ control = FOLLOWUP;
+
+ logMeanMessageInterval = port->getSyncInterval();
+
+ return;
+}
+
+void PTPMessageFollowUp::sendPort(IEEE1588Port * port,
+ PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0x0;
+ Timestamp preciseOriginTimestamp_BE;
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength =
+ PTP_COMMON_HDR_LENGTH + PTP_FOLLOWUP_LENGTH + sizeof(tlv);
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ preciseOriginTimestamp_BE.seconds_ms =
+ PLAT_htons(preciseOriginTimestamp.seconds_ms);
+ preciseOriginTimestamp_BE.seconds_ls =
+ PLAT_htonl(preciseOriginTimestamp.seconds_ls);
+ preciseOriginTimestamp_BE.nanoseconds =
+ PLAT_htonl(preciseOriginTimestamp.nanoseconds);
+ // Copy in v2 sync specific fields
+ memcpy(buf_ptr + PTP_FOLLOWUP_SEC_MS(PTP_FOLLOWUP_OFFSET),
+ &(preciseOriginTimestamp_BE.seconds_ms),
+ sizeof(preciseOriginTimestamp.seconds_ms));
+ memcpy(buf_ptr + PTP_FOLLOWUP_SEC_LS(PTP_FOLLOWUP_OFFSET),
+ &(preciseOriginTimestamp_BE.seconds_ls),
+ sizeof(preciseOriginTimestamp.seconds_ls));
+ memcpy(buf_ptr + PTP_FOLLOWUP_NSEC(PTP_FOLLOWUP_OFFSET),
+ &(preciseOriginTimestamp_BE.nanoseconds),
+ sizeof(preciseOriginTimestamp.nanoseconds));
+ tlv.toByteString(buf_ptr + PTP_COMMON_HDR_LENGTH + PTP_FOLLOWUP_LENGTH);
+
+ XPTPD_INFO("Follow-Up Time: %u seconds(hi)",
+ preciseOriginTimestamp.seconds_ms);
+ XPTPD_INFO("Follow-Up Time: %u seconds",
+ preciseOriginTimestamp.seconds_ls);
+ XPTPD_INFO("F-UP Time: %u nanoseconds",
+ preciseOriginTimestamp.nanoseconds);
+ XPTPD_INFO("F-UP Time: %x seconds", preciseOriginTimestamp.seconds_ls);
+ XPTPD_INFO("F-UP Time: %x nanoseconds",
+ preciseOriginTimestamp.nanoseconds);
+#if 0
+ XPTPD_INFO("Follow-up Dump:\n");
+#ifdef DEBUG
+ for (int i = 0; i < messageLength; ++i) {
+ fprintf(stderr, "%d:%02x ", i, (unsigned char)buf[i]);
+ }
+ fprintf(stderr, "\n");
+#endif
+#endif
+
+ port->sendGeneralPort(buf_t, messageLength, MCAST_OTHER, destIdentity);
+
+ return;
+}
+
+void PTPMessageFollowUp::processMessage(IEEE1588Port * port)
+{
+ int64_t delay;
+ Timestamp sync_arrival;
+ Timestamp system_time(0, 0, 0);
+ Timestamp device_time(0, 0, 0);
+
+ signed long long local_system_offset;
+ signed long long scalar_offset;
+
+ int32_t local_clock_adjustment;
+ int32_t local_system_freq_offset;
+
+ XPTPD_INFO("Processing a follow-up message");
+
+ if (port->getPortState() == PTP_INITIALIZING
+ || port->getPortState() == PTP_DISABLED) {
+ // Do nothing Sync messages should be ignored when in this state
+ return;
+ }
+ if (port->getPortState() == PTP_FAULTY) {
+ // According to spec recovery is implementation specific
+ port->recoverPort();
+ return;
+ }
+
+ PortIdentity sync_id;
+ PTPMessageSync *sync = port->getLastSync();
+ if (sync == NULL) {
+
+ XPTPD_ERROR("Received Follow Up but there is no sync message");
+
+ return;
+ }
+ sync->getPortIdentity(&sync_id);
+
+ if (sync->getSequenceId() != sequenceId
+ || sync_id != *sourcePortIdentity) {
+
+ XPTPD_ERROR
+ ("Received Follow Up but cannot find corresponding Sync");
+
+ goto done;
+ }
+
+ sync_arrival = sync->getTimestamp();
+
+ XPTPD_INFO("Sync Arrival: %u seconds", sync_arrival.seconds_ls);
+ XPTPD_INFO("Sync Arrival: %u nanoseconds", sync_arrival.nanoseconds);
+ XPTPD_INFO("Sync Depart: %u seconds",
+ preciseOriginTimestamp.seconds_ls);
+ XPTPD_INFO("Sync Depart: %u nanoseconds",
+ preciseOriginTimestamp.nanoseconds);
+ XPTPD_INFO("Sync Depart: %x seconds",
+ preciseOriginTimestamp.seconds_ls);
+ XPTPD_INFO("Sync Depart: %x nanoseconds",
+ preciseOriginTimestamp.nanoseconds);
+
+ delay = port->getLinkDelay();
+ if ((delay = port->getLinkDelay()) == 3600000000000) {
+ goto done;
+ }
+ //fprintf( stderr, "Local Time = %llu,Master Time = %llu\n", TIMESTAMP_TO_NS(sync_arrival)-delay, TIMESTAMP_TO_NS( preciseOriginTimestamp));
+
+ scalar_offset =
+ TIMESTAMP_TO_NS(sync_arrival) -
+ TIMESTAMP_TO_NS(preciseOriginTimestamp);
+
+ //printf( "Followup timestamp: %u,%u,%u\n", preciseOriginTimestamp.seconds_ms, preciseOriginTimestamp.seconds_ls, preciseOriginTimestamp.nanoseconds );
+ //printf( "Sync Arrival timestamp: %u,%u,%u\n", sync_arrival.seconds_ms, sync_arrival.seconds_ls, sync_arrival.nanoseconds );
+ //printf( "FollowUp Scalar = %Ld\n", scalar_offset );
+
+ scalar_offset -= delay;
+ scalar_offset -= correctionField >> 16; // Fractional nanoseconds are dropped
+ //fprintf( stderr, "Scalar offset = %lld\n", scalar_offset );
+ //scalar_offset -= sync->getCorrectionField() >> 16; // Fractional nanoseconds are dropped
+ //fprintf( stderr, "Correction Field (ns): %lld\n", correctionField >> 16 );
+ //fprintf( stderr, "Link Delay (ns): %lld(%llu,%llu)\n", delay, TIMESTAMP_TO_NS( sync_arrival), TIMESTAMP_TO_NS(preciseOriginTimestamp) );
+
+ XPTPD_INFO("Followup Correction Field: %Ld,%lu", correctionField >> 16,
+ delay);
+ XPTPD_INFO("FollowUp Scalar = %lld", scalar_offset);
+
+ // Otherwise synchronize clock with approximate time from Sync message
+ uint32_t local_clock, nominal_clock_rate;
+ uint32_t device_sync_time_offset;
+
+#if 0
+ Timestamp crstamp_device_time;
+ int64_t external_local_offset;
+ int32_t external_local_freq_offset;
+#endif
+
+ port->getDeviceTime(system_time, device_time, local_clock,
+ nominal_clock_rate);
+ //fprintf( stderr, "Device Time = %llu,System Time = %llu\n", TIMESTAMP_TO_NS(device_time), TIMESTAMP_TO_NS(system_time));
+
+ // Adjust local_clock to correspond to sync_arrival
+ device_sync_time_offset =
+ TIMESTAMP_TO_NS(device_time) - TIMESTAMP_TO_NS(sync_arrival);
+ //local_clock -= device_sync_time_offset/(1000000000/nominal_clock_rate);
+
+ XPTPD_INFO
+ ("ptp_message::FollowUp::processMessage 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);
+
+#if 0
+ local_system_offset = system_time.nanoseconds +
+ (((unsigned long long)system_time.seconds_ms <<
+ sizeof(system_time.seconds_ls) * 8) +
+ system_time.seconds_ls) * 1000000000LL;
+ local_system_offset -=
+ device_time.nanoseconds +
+ (((unsigned long long)device_time.seconds_ms <<
+ sizeof(device_time.seconds_ls) * 8) +
+ device_time.seconds_ls) * 1000000000LL;
+#endif
+
+ local_clock_adjustment =
+ port->calcMasterLocalClockRateDifference(scalar_offset,
+ sync_arrival);
+ port->setMasterRateOffset(local_clock_adjustment);
+
+ local_system_freq_offset =
+ port->calcLocalSystemClockRateDifference(local_system_offset,
+ system_time);
+ //fprintf( stderr, "Master-Local Freq Offset = %d\n", local_clock_adjustment );
+ //fprintf( stderr, "Local-System Freq Offset = %d\n", local_system_freq_offset );
+
+ TIMESTAMP_SUB_NS(system_time,
+ (device_sync_time_offset *
+ (1000000000000ULL +
+ local_system_freq_offset)) / 1000000000000ULL);
+
+ //port->getExternalClockRate( crstamp_device_time, external_local_offset, external_local_freq_offset );
+
+#if 0
+ port->getClock()->setMasterOffset(scalar_offset, sync_arrival,
+ local_clock_adjustment,
+ local_system_offset, system_time,
+ local_system_freq_offset,
+ external_local_offset,
+ crstamp_device_time,
+ external_local_freq_offset);
+#endif
+ port->getClock()->setMasterOffset(scalar_offset, sync_arrival,
+ local_clock_adjustment,
+ local_system_offset, system_time,
+ local_system_freq_offset,
+ nominal_clock_rate, local_clock);
+ //fprintf( stderr, "Master-Local Offset=%lld,%d,%llu\n", scalar_offset, local_clock_adjustment, TIMESTAMP_TO_NS(sync_arrival) );
+
+ if (port->doSyntonization()) {
+ port->adjustClockRate(local_clock_adjustment,
+ sync->getTimestampCounterValue(),
+ preciseOriginTimestamp, scalar_offset,
+ false);
+ }
+
+ done:
+ _gc = true;
+ delete sync;
+ port->setLastSync(NULL);
+
+ return;
+}
+
+ PTPMessagePathDelayReq::PTPMessagePathDelayReq(IEEE1588Port * port):PTPMessageCommon
+ (port)
+{
+ logMeanMessageInterval = 0;
+ control = MESSAGE_OTHER;
+ messageType = PATH_DELAY_REQ_MESSAGE;
+ sequenceId = port->getNextPDelaySequenceId();
+ return;
+}
+
+void PTPMessagePathDelayReq::processMessage(IEEE1588Port * port)
+{
+ OSTimer *timer = port->getTimerFactory()->createTimer();
+
+ if (port->getPortState() == PTP_INITIALIZING
+ || port->getPortState() == PTP_DISABLED) {
+ // Do nothing all messages should be ignored when in this state
+ return;
+ }
+
+ if (port->getPortState() == PTP_FAULTY) {
+ // According to spec recovery is implementation specific
+ port->recoverPort();
+ return;
+ }
+
+ port->getClock()->deleteEventTimer(port,
+ PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES);
+ port->getClock()->addEventTimer(port,
+ PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES,
+ (unsigned long long)
+ (PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER
+ *
+ (pow
+ ((double)2,
+ port->getPDelayInterval()) *
+ 1000000000.0)));
+ // Generate and send message
+ PTPMessagePathDelayResp *resp = new PTPMessagePathDelayResp(port);
+ PortIdentity resp_id;
+ port->getPortIdentity(resp_id);
+ resp->setPortIdentity(&resp_id);
+ resp->setSequenceId(sequenceId);
+
+ XPTPD_INFO("Process PDelay Request SeqId: %u\t", sequenceId);
+ //XPTPD_INFO( "Process PDelay Request Port: %u\t", );
+ //XPTPD_INFO( "Process PDelay Request Identity: \"" );
+
+#ifdef DEBUG
+ for (int n = 0; n < PTP_CLOCK_IDENTITY_LENGTH; ++n) {
+ fprintf(stderr, "%c", resp_id.clockIdentity[n]);
+ }
+ fprintf(stderr, "\"\n");
+#endif
+
+ PortIdentity requestingPortIdentity_p;
+ this->getPortIdentity(&requestingPortIdentity_p);
+ resp->setRequestingPortIdentity(&requestingPortIdentity_p);
+ resp->setRequestReceiptTimestamp(_timestamp);
+ port->getTxLock();
+ resp->sendPort(port, sourcePortIdentity);
+
+ XPTPD_INFO("Sent path delay response");
+
+ int ts_good;
+ int iter = 2;
+ Timestamp resp_timestamp;
+ unsigned resp_timestamp_counter_value;
+ unsigned req = 1000; // = 1 ms
+
+ XPTPD_INFO("Start TS Read");
+ ts_good =
+ port->getTxTimestamp(resp, resp_timestamp,
+ resp_timestamp_counter_value, false);
+
+ XPTPD_INFO("Done TS Read");
+
+ while (ts_good != 0 && iter-- != 0) {
+ timer->sleep(req);
+ if (ts_good == -72 && iter < 1)
+ fprintf(stderr,
+ "Error (TX) timestamping PDelay Response (Retrying-%d), error=%d\n",
+ iter, ts_good);
+ ts_good =
+ port->getTxTimestamp(resp, resp_timestamp,
+ resp_timestamp_counter_value,
+ iter == 0);
+ req *= 2;
+ }
+ port->putTxLock();
+
+ if (ts_good != 0) {
+ char msg[HWTIMESTAMPER_EXTENDED_MESSAGE_SIZE];
+ port->getExtendedError(msg);
+ fprintf(stderr,
+ "Error (TX) timestamping PDelay Response, error=%d\n%s",
+ ts_good, msg);
+ delete resp;
+ return;
+ }
+
+ PTPMessagePathDelayRespFollowUp *resp_fwup =
+ new PTPMessagePathDelayRespFollowUp(port);
+ PortIdentity resp_fwup_id;
+ port->getPortIdentity(resp_fwup_id);
+ resp_fwup->setPortIdentity(&resp_fwup_id);
+ resp_fwup->setSequenceId(sequenceId);
+ resp_fwup->setRequestingPortIdentity(sourcePortIdentity);
+ resp_fwup->setResponseOriginTimestamp(resp_timestamp);
+ long long turnaround;
+ turnaround =
+ (resp_timestamp.seconds_ls - _timestamp.seconds_ls) * 1000000000LL;
+
+ XPTPD_INFO("Response Depart(sec): %u", resp_timestamp.seconds_ls);
+ XPTPD_INFO("Request Arrival(sec): %u", _timestamp.seconds_ls);
+ XPTPD_INFO("#1 Correction Field: %Ld", turnaround);
+
+ turnaround += resp_timestamp.nanoseconds;
+
+ XPTPD_INFO("#2 Correction Field: %Ld", turnaround);
+
+ turnaround -= _timestamp.nanoseconds;
+
+ XPTPD_INFO("#3 Correction Field: %Ld", turnaround);
+
+ //resp_fwup->setCorrectionField( turnaround << 16 );
+ resp_fwup->setCorrectionField(0); // MMM
+ resp_fwup->sendPort(port, sourcePortIdentity);
+
+ XPTPD_INFO("Sent path delay response fwup");
+
+ delete resp;
+ delete resp_fwup;
+
+ _gc = true;
+}
+
+void PTPMessagePathDelayReq::sendPort(IEEE1588Port * port,
+ PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0;
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength = PTP_COMMON_HDR_LENGTH + PTP_PDELAY_REQ_LENGTH;
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ // Get timestamp
+ //originTimestamp = port->getClock()->getTime();
+ // These fields are not used
+// memcpy( buf+PTP_PDELAY_REQ_SEC_MS(PTP_PDELAY_REQ_OFFSET), &(originTimestamp.seconds_ms), sizeof(originTimestamp.seconds_ms));
+// memcpy( buf+PTP_PDELAY_REQ_SEC_LS(PTP_PDELAY_REQ_OFFSET), &(originTimestamp.seconds_ls), sizeof(originTimestamp.seconds_ls));
+// memcpy( buf+PTP_PDELAY_REQ_NSEC(PTP_PDELAY_REQ_OFFSET), &(originTimestamp.nanoseconds), sizeof(originTimestamp.nanoseconds));
+// memcpy( buf+PTP_PDELAY_REQ_TS_OFFSET(PTP_PDELAY_REQ_OFFSET), &(originTimestamp.timescaleOffset), sizeof(originTimestamp.timescaleOffset));
+
+ port->sendEventPort(buf_t, messageLength, MCAST_PDELAY, destIdentity);
+ return;
+}
+
+ PTPMessagePathDelayResp::PTPMessagePathDelayResp(IEEE1588Port * port):
+PTPMessageCommon(port)
+{
+ logMeanMessageInterval = 0;
+ control = MESSAGE_OTHER;
+ messageType = PATH_DELAY_RESP_MESSAGE;
+ versionPTP = GPTP_VERSION;
+ requestingPortIdentity = new PortIdentity();
+
+ flags[PTP_ASSIST_BYTE] |= (0x1 << PTP_ASSIST_BIT);
+
+ return;
+}
+
+PTPMessagePathDelayResp::~PTPMessagePathDelayResp()
+{
+ delete requestingPortIdentity;
+}
+
+void PTPMessagePathDelayResp::processMessage(IEEE1588Port * port)
+{
+ if (port->getPortState() == PTP_INITIALIZING
+ || port->getPortState() == PTP_DISABLED) {
+ // Do nothing all messages should be ignored when in this state
+ return;
+ }
+ if (port->getPortState() == PTP_FAULTY) {
+ // According to spec recovery is implementation specific
+ port->recoverPort();
+ return;
+ }
+
+ if (port->tryPDelayRxLock() != true) {
+ fprintf(stderr, "Failed to get PDelay RX Lock\n");
+ return;
+ }
+
+ port->getClock()->deleteEventTimer(port,
+ PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES);
+ port->getClock()->addEventTimer(port,
+ PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES,
+ (unsigned long long)
+ (PDELAY_RESP_RECEIPT_TIMEOUT_MULTIPLIER
+ *
+ (pow
+ ((double)2,
+ port->getPDelayInterval()) *
+ 1000000000.0)));
+ PTPMessagePathDelayResp *old_pdelay_resp = port->getLastPDelayResp();
+ if (old_pdelay_resp != NULL) {
+ delete old_pdelay_resp;
+ }
+ port->setLastPDelayResp(this);
+
+ port->putPDelayRxLock();
+ _gc = false;
+
+ return;
+}
+
+void PTPMessagePathDelayResp::sendPort(IEEE1588Port * port,
+ PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0;
+ Timestamp requestReceiptTimestamp_BE;
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength = PTP_COMMON_HDR_LENGTH + PTP_PDELAY_RESP_LENGTH;
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ requestReceiptTimestamp_BE.seconds_ms =
+ PLAT_htons(requestReceiptTimestamp.seconds_ms);
+ requestReceiptTimestamp_BE.seconds_ls =
+ PLAT_htonl(requestReceiptTimestamp.seconds_ls);
+ requestReceiptTimestamp_BE.nanoseconds =
+ PLAT_htonl(requestReceiptTimestamp.nanoseconds);
+
+ // Copy in v2 PDelay_Req specific fields
+ requestingPortIdentity->getClockIdentityString((char *)buf_ptr +
+ PTP_PDELAY_RESP_REQ_CLOCK_ID
+ (PTP_PDELAY_RESP_OFFSET));
+ requestingPortIdentity->getPortNumberNO((uint16_t *) (buf_ptr +
+ PTP_PDELAY_RESP_REQ_PORT_ID
+ (PTP_PDELAY_RESP_OFFSET)));
+ memcpy(buf_ptr + PTP_PDELAY_RESP_SEC_MS(PTP_PDELAY_RESP_OFFSET),
+ &(requestReceiptTimestamp_BE.seconds_ms),
+ sizeof(requestReceiptTimestamp.seconds_ms));
+ memcpy(buf_ptr + PTP_PDELAY_RESP_SEC_LS(PTP_PDELAY_RESP_OFFSET),
+ &(requestReceiptTimestamp_BE.seconds_ls),
+ sizeof(requestReceiptTimestamp.seconds_ls));
+ memcpy(buf_ptr + PTP_PDELAY_RESP_NSEC(PTP_PDELAY_RESP_OFFSET),
+ &(requestReceiptTimestamp_BE.nanoseconds),
+ sizeof(requestReceiptTimestamp.nanoseconds));
+
+ XPTPD_INFO("PDelay Resp Timestamp: %u,%u",
+ requestReceiptTimestamp.seconds_ls,
+ requestReceiptTimestamp.nanoseconds);
+
+ port->sendEventPort(buf_t, messageLength, MCAST_PDELAY, destIdentity);
+ return;
+}
+
+void PTPMessagePathDelayResp::setRequestingPortIdentity(PortIdentity * identity)
+{
+ *requestingPortIdentity = *identity;
+}
+
+void PTPMessagePathDelayResp::getRequestingPortIdentity(PortIdentity * identity)
+{
+ *identity = *requestingPortIdentity;
+}
+
+ PTPMessagePathDelayRespFollowUp::PTPMessagePathDelayRespFollowUp(IEEE1588Port * port):
+PTPMessageCommon
+ (port)
+{
+ logMeanMessageInterval = 0;
+ control = MESSAGE_OTHER;
+ messageType = PATH_DELAY_FOLLOWUP_MESSAGE;
+ versionPTP = GPTP_VERSION;
+ requestingPortIdentity = new PortIdentity();
+
+ return;
+}
+
+PTPMessagePathDelayRespFollowUp::~PTPMessagePathDelayRespFollowUp()
+{
+ delete requestingPortIdentity;
+}
+
+void PTPMessagePathDelayRespFollowUp::processMessage(IEEE1588Port * port)
+{
+ Timestamp remote_resp_tx_timestamp(0, 0, 0);
+ Timestamp request_tx_timestamp(0, 0, 0);
+ Timestamp remote_req_rx_timestamp(0, 0, 0);
+ Timestamp response_rx_timestamp(0, 0, 0);
+
+ if (port->getPortState() == PTP_INITIALIZING
+ || port->getPortState() == PTP_DISABLED) {
+ // Do nothing all messages should be ignored when in this state
+ return;
+ }
+ if (port->getPortState() == PTP_FAULTY) {
+ // According to spec recovery is implementation specific
+ port->recoverPort();
+ return;
+ }
+
+ if (port->tryPDelayRxLock() != true)
+ return;
+
+ PTPMessagePathDelayReq *req = port->getLastPDelayReq();
+ PTPMessagePathDelayResp *resp = port->getLastPDelayResp();
+
+ PortIdentity req_id;
+ PortIdentity resp_id;
+
+ if (req == NULL) {
+ // Shouldn't happen
+ XPTPD_ERROR
+ (">>> Received PDelay followup but no REQUEST exists");
+ goto abort;
+ }
+
+ if (resp == NULL) {
+ // Probably shouldn't happen either
+ XPTPD_ERROR
+ (">>> Received PDelay followup but no RESPONSE exists");
+ goto abort;
+ }
+
+ req->getPortIdentity(&req_id);
+ resp->getRequestingPortIdentity(&resp_id);
+
+ // Check if we have sent a request
+// if( req->getSequenceId() != sequenceId || req_id.portNumber != requestingPortIdentity.portNumber ||
+// memcmp( req_id.clockIdentity, requestingPortIdentity.clockIdentity, PTP_CLOCK_IDENTITY_LENGTH ) != 0 ) {
+ if (req->getSequenceId() != sequenceId) {
+
+ XPTPD_ERROR
+ ("Received PDelay Response Follow Up but cannot find corresponding request");
+ // XPTPD_INFO( "Requesting SeqId: %u ", req->getSequenceId() );
+ // XPTPD_INFO( "Requesting SeqId: %u ", sequenceId );
+ XPTPD_ERROR("My SeqId: %u ", req->getSequenceId());
+ XPTPD_ERROR("Their SeqId: %u ", sequenceId);
+ //XPTPD_INFO( "Requesting Port: %u ", requestingPortIdentity.portNumber );
+ XPTPD_INFO("Requesting Identity: \"");
+
+#ifdef DEBUG
+ for (int n = 0; n < PTP_CLOCK_IDENTITY_LENGTH; ++n) {
+ fprintf(stderr, "%u: %x ", n,
+ requestingPortIdentity.clockIdentity[n]);
+ }
+ fprintf(stderr, " \"\n");
+#endif
+
+ //XPTPD_INFO( "Requesting SeqId: %u ", req->getSequenceId() );
+ //XPTPD_INFO( "Requesting Port: %u ", req_id.portNumber );
+ XPTPD_INFO("Requesting Identity: \"");
+
+#ifdef DEBUG
+ for (int n = 0; n < PTP_CLOCK_IDENTITY_LENGTH; ++n) {
+ fprintf(stderr, "%u:%x ", n, req_id.clockIdentity[n]);
+ }
+ fprintf(stderr, " \"\n");
+#endif
+
+ goto abort;
+ }
+ //fprintf( stderr, "PDelay Follow-Up OK\n" );
+
+ // Check if we have received a response
+ if (resp->getSequenceId() != sequenceId
+ || resp_id != *requestingPortIdentity) {
+ uint16_t resp_port_number;
+ uint16_t req_port_number;
+ resp_id.getPortNumber(&resp_port_number);
+ requestingPortIdentity->getPortNumber(&req_port_number);
+ XPTPD_ERROR
+ ("Received PDelay Response Follow Up but cannot find corresponding response");
+ XPTPD_ERROR("%hu, %hu, %hu, %hu", resp->getSequenceId(),
+ sequenceId, resp_port_number, req_port_number);
+
+ goto abort;
+ }
+
+ XPTPD_INFO("Request Sequence Id: %u", req->getSequenceId());
+ XPTPD_INFO("Response Sequence Id: %u", resp->getSequenceId());
+ XPTPD_INFO("Follow-Up Sequence Id: %u", req->getSequenceId());
+
+ port->setAsCapable(true);
+
+ int64_t link_delay;
+ unsigned long long turn_around;
+
+ // Assume that we are a two step clock, otherwise originTimestamp may be used
+ request_tx_timestamp = req->getTimestamp();
+ if (request_tx_timestamp.nanoseconds ==
+ PDELAY_PENDING_TIMESTAMP.nanoseconds) {
+ // Defer processing
+ if (port->getLastPDelayRespFollowUp() != NULL) {
+ delete port->getLastPDelayRespFollowUp();
+ }
+ port->setLastPDelayRespFollowUp(this);
+ port->getClock()->addEventTimer(port,
+ PDELAY_DEFERRED_PROCESSING,
+ 1000000);
+ goto defer;
+ }
+ if (request_tx_timestamp.nanoseconds == INVALID_TIMESTAMP.nanoseconds) {
+ // Stop processing the packet
+ goto abort;
+ }
+ remote_req_rx_timestamp = resp->getRequestReceiptTimestamp();
+ response_rx_timestamp = resp->getTimestamp();
+ remote_resp_tx_timestamp = responseOriginTimestamp;
+
+#if 0
+ fprintf(stderr, "@REQT,%u,%u,%u,%hu\n", request_tx_timestamp.seconds_ms,
+ request_tx_timestamp.seconds_ls,
+ request_tx_timestamp.nanoseconds, req->getSequenceId());
+ fprintf(stderr, "@REQR,%u,%u,%u,%hu\n",
+ remote_req_rx_timestamp.seconds_ms,
+ remote_req_rx_timestamp.seconds_ls,
+ remote_req_rx_timestamp.nanoseconds, resp->getSequenceId());
+ fprintf(stderr, "@RESR,%u,%u,%u,%hu\n",
+ response_rx_timestamp.seconds_ms,
+ response_rx_timestamp.seconds_ls,
+ response_rx_timestamp.nanoseconds, resp->getSequenceId());
+ fprintf(stderr, "@REST,%u,%u,%u,%hu\n",
+ remote_resp_tx_timestamp.seconds_ms,
+ remote_resp_tx_timestamp.seconds_ls,
+ remote_resp_tx_timestamp.nanoseconds, sequenceId);
+#endif
+
+ link_delay =
+ ((response_rx_timestamp.seconds_ms * 1LL -
+ request_tx_timestamp.seconds_ms) << 32) * 1000000000;
+ link_delay +=
+ (response_rx_timestamp.seconds_ls * 1LL -
+ request_tx_timestamp.seconds_ls) * 1000000000;
+ link_delay +=
+ (response_rx_timestamp.nanoseconds * 1LL -
+ request_tx_timestamp.nanoseconds);
+ //fprintf( stderr, "Send/Recv Delay is %lld\n", link_delay );
+
+ turn_around =
+ ((remote_resp_tx_timestamp.seconds_ms * 1LL -
+ remote_req_rx_timestamp.seconds_ms) << 32) * 1000000000;
+ turn_around +=
+ (remote_resp_tx_timestamp.seconds_ls * 1LL -
+ remote_req_rx_timestamp.seconds_ls) * 1000000000;
+ turn_around +=
+ (remote_resp_tx_timestamp.nanoseconds * 1LL -
+ remote_req_rx_timestamp.nanoseconds);
+ //fprintf( stderr, "Unadjusted Turn Around is %llu\n", turn_around );
+ //fprintf( stderr, "Unadjusted Link Delay *2 %lld\n", link_delay - turn_around );
+
+ //fprintf( stderr, "Peer Rate Offset: %d", port->getPeerRateOffset() );
+
+ // Adjust turn-around time for peer to local clock rate difference
+ turn_around +=
+ (((long long)turn_around) * port->getPeerRateOffset()) /
+ 1000000000000LL;
+
+ XPTPD_INFO("Turn Around Adjustment %Ld",
+ ((long long)turn_around * port->getPeerRateOffset()) /
+ 1000000000000LL);
+ XPTPD_INFO("Step #1: Turn Around Adjustment %Ld",
+ ((long long)turn_around * port->getPeerRateOffset()));
+ XPTPD_INFO("Adjusted Peer turn around is %Lu", turn_around);
+
+ // Subtract turn-around time from link delay after rate adjustment
+ link_delay -= turn_around;
+
+ link_delay /= 2;
+
+ {
+ uint64_t mine_elapsed;
+ uint64_t theirs_elapsed;
+ Timestamp prev_peer_ts_mine;
+ Timestamp prev_peer_ts_theirs;
+ int32_t rate_offset;
+ if (port->getPeerOffset(prev_peer_ts_mine, prev_peer_ts_theirs)) {
+ mine_elapsed =
+ TIMESTAMP_TO_NS(request_tx_timestamp) -
+ TIMESTAMP_TO_NS(prev_peer_ts_mine);
+ theirs_elapsed =
+ TIMESTAMP_TO_NS(remote_req_rx_timestamp) -
+ TIMESTAMP_TO_NS(prev_peer_ts_theirs);
+#if 0
+ rate_offset =
+ (int32_t) ((mine_elapsed * 1000000000ULL) /
+ theirs_elapsed);
+ rate_offset -= 1000000000;
+#endif
+ theirs_elapsed -= port->getLinkDelay() - link_delay;
+ rate_offset =
+ (int32_t) ((mine_elapsed * 1000000000ULL) /
+ theirs_elapsed);
+ rate_offset -= 1000000000;
+ rate_offset *= 1000;
+ port->setPeerRateOffset(rate_offset);
+ //fprintf( stderr, "(2)PDelay rate offset: %d\n", rate_offset );
+ }
+ }
+ port->setLinkDelay(link_delay);
+ port->setPeerOffset(request_tx_timestamp, remote_req_rx_timestamp);
+
+ abort:
+ delete req;
+ port->setLastPDelayReq(NULL);
+ delete resp;
+ port->setLastPDelayResp(NULL);
+
+ _gc = true;
+
+ defer:
+ port->putPDelayRxLock();
+
+ return;
+}
+
+void PTPMessagePathDelayRespFollowUp::sendPort(IEEE1588Port * port,
+ PortIdentity * destIdentity)
+{
+ uint8_t buf_t[256];
+ uint8_t *buf_ptr = buf_t + port->getPayloadOffset();
+ unsigned char tspec_msg_t = 0;
+ Timestamp responseOriginTimestamp_BE;
+ memset(buf_t, 0, 256);
+ // Create packet in buf
+ // Copy in common header
+ messageLength = PTP_COMMON_HDR_LENGTH + PTP_PDELAY_RESP_LENGTH;
+ tspec_msg_t |= messageType & 0xF;
+ buildCommonHeader(buf_ptr);
+ responseOriginTimestamp_BE.seconds_ms =
+ PLAT_htons(responseOriginTimestamp.seconds_ms);
+ responseOriginTimestamp_BE.seconds_ls =
+ PLAT_htonl(responseOriginTimestamp.seconds_ls);
+ responseOriginTimestamp_BE.nanoseconds =
+ PLAT_htonl(responseOriginTimestamp.nanoseconds);
+
+ // Copy in v2 PDelay_Req specific fields
+ requestingPortIdentity->getClockIdentityString((char *)buf_ptr +
+ PTP_PDELAY_FOLLOWUP_REQ_CLOCK_ID
+ (PTP_PDELAY_FOLLOWUP_OFFSET));
+ requestingPortIdentity->getPortNumberNO((uint16_t *) (buf_ptr +
+ PTP_PDELAY_FOLLOWUP_REQ_PORT_ID
+ (PTP_PDELAY_FOLLOWUP_OFFSET)));
+ memcpy(buf_ptr + PTP_PDELAY_FOLLOWUP_SEC_MS(PTP_PDELAY_FOLLOWUP_OFFSET),
+ &(responseOriginTimestamp_BE.seconds_ms),
+ sizeof(responseOriginTimestamp.seconds_ms));
+ memcpy(buf_ptr + PTP_PDELAY_FOLLOWUP_SEC_LS(PTP_PDELAY_FOLLOWUP_OFFSET),
+ &(responseOriginTimestamp_BE.seconds_ls),
+ sizeof(responseOriginTimestamp.seconds_ls));
+ memcpy(buf_ptr + PTP_PDELAY_FOLLOWUP_NSEC(PTP_PDELAY_FOLLOWUP_OFFSET),
+ &(responseOriginTimestamp_BE.nanoseconds),
+ sizeof(responseOriginTimestamp.nanoseconds));
+
+ XPTPD_INFO("PDelay Resp Timestamp: %u,%u",
+ responseOriginTimestamp.seconds_ls,
+ responseOriginTimestamp.nanoseconds);
+
+ port->sendGeneralPort(buf_t, messageLength, MCAST_PDELAY, destIdentity);
+ return;
+}
+
+void PTPMessagePathDelayRespFollowUp::setRequestingPortIdentity(PortIdentity *
+ identity)
+{
+ *requestingPortIdentity = *identity;
+}
--- /dev/null
+D/src////
+D/build////
--- /dev/null
+linux_igb_avb/daemons/gptp/linux
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+D/obj////
+/Makefile/1.1/Fri Sep 7 18:53:45 2012//
--- /dev/null
+linux_igb_avb/daemons/gptp/linux/build
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+#
+# Copyright (c) 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.
+
+CXX = g++
+
+CFLAGS_G = -Wall -g -I. -I../../common -I../src
+LDFLAGS_G = -lpthread -lrt
+
+CFLAGS = $(CFLAGS_G)
+LDFLAGS = $(LDFLAGS_G)
+
+CXXFLAGS =
+COMMON_DIR = ../../common
+SRC_DIR = ../src
+OBJ_DIR = obj
+
+OBJ_FILES = $(OBJ_DIR)/ptp_message.o\
+ $(OBJ_DIR)/avbts_osnet.o\
+ $(OBJ_DIR)/ieee1588port.o\
+ $(OBJ_DIR)/ieee1588clock.o
+
+HEADER_FILES = $(COMMON_DIR)/avbts_port.hpp\
+ $(COMMON_DIR)/avbts_ostimerq.hpp\
+ $(COMMON_DIR)/avbts_ostimer.hpp\
+ $(COMMON_DIR)/avbts_osthread.hpp\
+ $(COMMON_DIR)/avbts_osnet.hpp\
+ $(COMMON_DIR)/avbts_oslock.hpp\
+ $(COMMON_DIR)/avbts_osipc.hpp\
+ $(COMMON_DIR)/avbts_oscondition.hpp\
+ $(COMMON_DIR)/avbts_message.hpp\
+ $(COMMON_DIR)/avbts_clock.hpp\
+ $(COMMON_DIR)/ieee1588.hpp\
+ $(SRC_DIR)/linux_hal.hpp\
+ $(SRC_DIR)/platform.hpp
+
+all: daemon_cl
+
+rebuild: clean all
+
+daemon_cl: $(SRC_DIR)/daemon_cl.cpp $(OBJ_FILES)
+ $(CXX) $(CFLAGS) $(CXXFLAGS) $(OBJ_FILES) $(SRC_DIR)/daemon_cl.cpp -o $(OBJ_DIR)/daemon_cl $(LDFLAGS)
+
+$(OBJ_DIR)/ieee1588port.o: $(COMMON_DIR)/ieee1588port.cpp $(HEADER_FILES)
+ $(CXX) $(CFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/ieee1588port.cpp -o $(OBJ_DIR)/ieee1588port.o
+
+$(OBJ_DIR)/ieee1588clock.o: $(COMMON_DIR)/ieee1588clock.cpp $(HEADER_FILES)
+ $(CXX) $(CFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/ieee1588clock.cpp -o $(OBJ_DIR)/ieee1588clock.o
+
+$(OBJ_DIR)/ptp_message.o: $(COMMON_DIR)/ptp_message.cpp $(HEADER_FILES)
+ $(CXX) $(CFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/ptp_message.cpp -o $(OBJ_DIR)/ptp_message.o
+
+$(OBJ_DIR)/avbts_osnet.o: $(COMMON_DIR)/avbts_osnet.cpp $(HEADER_FILES)
+ $(CXX) $(CFLAGS) $(CXXFLAGS) -c $(COMMON_DIR)/avbts_osnet.cpp -o $(OBJ_DIR)/avbts_osnet.o
+
+clean:
+ /bin/rm -f *~ $(OBJ_DIR)/*.o $(OBJ_DIR)/daemon_cl
+
--- /dev/null
+/.dir/1.1/Fri Sep 21 21:13:03 2012//
+D
--- /dev/null
+linux_igb_avb/daemons/gptp/linux/build/obj
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+/daemon_cl.cpp/1.1/Fri Sep 7 18:52:56 2012//
+/linux_hal.hpp/1.1/Fri Sep 21 17:52:55 2012//
+/platform.hpp/1.1/Fri Sep 7 18:52:41 2012//
+D
--- /dev/null
+linux_igb_avb/daemons/gptp/linux/src
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+/******************************************************************************
+
+ Copyright (c) 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_clock.hpp"
+#include "avbts_osnet.hpp"
+#include "avbts_oslock.hpp"
+#include "linux_hal.hpp"
+
+int main(int argc, char **argv)
+{
+ sigset_t set;
+ InterfaceName *ifname;
+ int sig;
+
+ LinuxPCAPNetworkInterfaceFactory *default_factory =
+ new LinuxPCAPNetworkInterfaceFactory;
+ OSNetworkInterfaceFactory::registerFactory(factory_name_t("default"),
+ default_factory);
+ LinuxThreadFactory *thread_factory = new LinuxThreadFactory();
+ LinuxTimerQueueFactory *timerq_factory = new LinuxTimerQueueFactory();
+ LinuxLockFactory *lock_factory = new LinuxLockFactory();
+ LinuxTimerFactory *timer_factory = new LinuxTimerFactory();
+ LinuxConditionFactory *condition_factory = new LinuxConditionFactory();
+ LinuxSimpleIPC *ipc = new LinuxSimpleIPC();
+
+ if (argc < 2)
+ return -1;
+ ifname = new InterfaceName(argv[1], strlen(argv[1]));
+
+ IEEE1588Clock *clock = new IEEE1588Clock(false, timerq_factory, ipc);
+ HWTimestamper *timestamper = new LinuxTimestamper();
+ IEEE1588Port *port =
+ new IEEE1588Port(clock, 1, false, timestamper, false, 0, ifname,
+ condition_factory, thread_factory, timer_factory,
+ lock_factory);
+
+ if (!port->init_port()) {
+ printf("failed to initialize port \n");
+ return -1;
+ }
+ port->processEvent(POWERUP);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
+ perror("pthread_sigmask()");
+ return -1;
+ }
+
+ if (sigwait(&set, &sig) != 0) {
+ perror("sigwait()");
+ return -1;
+ }
+
+ fprintf(stderr, "Exiting on %d\n", sig);
+
+ return 0;
+}
--- /dev/null
+/******************************************************************************
+
+ Copyright (c) 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 LINUX_HAL_HPP
+#define LINUX_HAL_HPP
+
+#include "avbts_osnet.hpp"
+#include "avbts_oslock.hpp"
+#include "avbts_oscondition.hpp"
+#include "avbts_ostimerq.hpp"
+#include "avbts_ostimer.hpp"
+#include "ieee1588.hpp"
+
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <string.h>
+#include <errno.h>
+
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <sys/prctl.h>
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <sys/select.h>
+#include <linux/net_tstamp.h>
+#include <linux/sockios.h>
+
+#define ONE_WAY_PHY_DELAY 400
+#define P8021AS_MULTICAST "\x01\x80\xC2\x00\x00\x0E"
+
+static inline Timestamp tsToTimestamp(struct timespec *ts)
+{
+ Timestamp ret;
+ if (sizeof(ts->tv_sec) > sizeof(ret.seconds_ls)) {
+ ret.seconds_ms = ts->tv_sec >> (sizeof(ret.seconds_ls) * 8);
+ ret.seconds_ls = ts->tv_sec & 0xFFFFFFFF;
+ ret.nanoseconds = ts->tv_nsec;
+ } else {
+ ret.seconds_ms = 0;
+ ret.seconds_ls = ts->tv_sec;
+ ret.nanoseconds = ts->tv_nsec;
+ }
+ return ret;
+}
+
+class LinuxTimestamper:public HWTimestamper {
+ private:
+ int sd;
+ Timestamp crstamp_system;
+ Timestamp crstamp_device;
+ pthread_mutex_t cross_stamp_lock;
+ bool cross_stamp_good;
+ std::list < Timestamp > rxTimestampList;
+ public:
+ virtual bool HWTimestamper_init(InterfaceLabel * iface_label) {
+ pthread_mutex_init(&cross_stamp_lock, NULL);
+ sd = -1;
+ cross_stamp_good = false;
+ return true;
+ }
+ void setSocketDescriptor(int sd) {
+ this->sd = sd;
+ };
+ void updateCrossStamp(Timestamp * system_time, Timestamp * device_time) {
+ pthread_mutex_lock(&cross_stamp_lock);
+ crstamp_system = *system_time;
+ crstamp_device = *device_time;
+ cross_stamp_good = true;
+ pthread_mutex_unlock(&cross_stamp_lock);
+ }
+ void pushRXTimestamp(Timestamp * tstamp) {
+ rxTimestampList.push_front(*tstamp);
+ }
+ bool post_init(int ifindex) {
+ int timestamp_flags = 0;
+ struct ifreq device;
+ struct hwtstamp_config hwconfig;
+ int err;
+
+ memset(&device, 0, sizeof(device));
+ device.ifr_ifindex = ifindex;
+ err = ioctl(sd, SIOCGIFNAME, &device);
+ if (err == -1) {
+ XPTPD_ERROR("Failed to get interface name: %s",
+ strerror(errno));
+ return false;
+ }
+
+ device.ifr_data = (char *)&hwconfig;
+ memset(&hwconfig, 0, sizeof(hwconfig));
+ hwconfig.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ hwconfig.tx_type = HWTSTAMP_TX_ON;
+ printf("TX type = %u\n", hwconfig.tx_type);
+ printf("RX filter = %u\n", hwconfig.rx_filter);
+ err = ioctl(sd, SIOCSHWTSTAMP, &device);
+ if (err == -1) {
+ XPTPD_ERROR("Failed to configure timestamping: %s",
+ strerror(errno));
+ return false;
+ }
+
+ timestamp_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
+ timestamp_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
+ timestamp_flags |= SOF_TIMESTAMPING_SYS_HARDWARE;
+ timestamp_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
+ err =
+ setsockopt(sd, SOL_SOCKET, SO_TIMESTAMPING,
+ ×tamp_flags, sizeof(timestamp_flags));
+ if (err == -1) {
+ XPTPD_ERROR
+ ("Failed to configure timestamping on socket: %s",
+ strerror(errno));
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual bool HWTimestamper_gettime(Timestamp * system_time,
+ Timestamp * device_time,
+ uint32_t * local_clock,
+ uint32_t * nominal_clock_rate) {
+ bool ret = false;
+ pthread_mutex_lock(&cross_stamp_lock);
+ if (cross_stamp_good) {
+ *system_time = crstamp_system;
+ *device_time = crstamp_device;
+ ret = true;
+ }
+ pthread_mutex_unlock(&cross_stamp_lock);
+ return ret;
+ }
+
+ virtual int HWTimestamper_txtimestamp(PortIdentity * identity,
+ uint16_t sequenceId,
+ Timestamp & timestamp,
+ unsigned &clock_value,
+ bool last) {
+ int err;
+ int ret = -72;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct sockaddr_ll remote;
+ struct iovec sgentry;
+ struct {
+ struct cmsghdr cm;
+ char control[256];
+ } control;
+
+ if (sd == -1)
+ return -1;
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_iov = &sgentry;
+ msg.msg_iovlen = 1;
+
+ sgentry.iov_base = NULL;
+ sgentry.iov_len = 0;
+
+ memset(&remote, 0, sizeof(remote));
+ msg.msg_name = (caddr_t) & remote;
+ msg.msg_namelen = sizeof(remote);
+ msg.msg_control = &control;
+ msg.msg_controllen = sizeof(control);
+
+ err = recvmsg(sd, &msg, MSG_ERRQUEUE);
+ if (err == -1) {
+ if (errno == EAGAIN)
+ return -72;
+ else
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SO_TIMESTAMPING) {
+ struct timespec *ts_device, *ts_system;
+ Timestamp device, system;
+ ts_system =
+ ((struct timespec *)CMSG_DATA(cmsg)) + 1;
+ system = tsToTimestamp(ts_system);
+ ts_device = ts_system + 1;
+ device = tsToTimestamp(ts_device);
+ updateCrossStamp(&system, &device);
+ timestamp = device;
+ ret = 0;
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+
+ return ret;
+ }
+
+ virtual int HWTimestamper_rxtimestamp(PortIdentity * identity,
+ uint16_t sequenceId,
+ Timestamp & timestamp,
+ unsigned &clock_value,
+ bool last) {
+ if (rxTimestampList.empty())
+ return -72;
+ timestamp = rxTimestampList.back();
+ rxTimestampList.pop_back();
+
+ return 0;
+ }
+};
+
+class LinuxLock:public OSLock {
+ friend class LinuxLockFactory;
+ private:
+ OSLockType type;
+ pthread_t thread_id;
+ int lock_c;
+ pthread_mutexattr_t mta;
+ pthread_mutex_t mutex;
+ pthread_cond_t port_ready_signal;
+ protected:
+ LinuxLock() {
+ lock_c = NULL;
+ }
+ bool initialize(OSLockType type) {
+ pthread_mutexattr_init(&mta);
+ if (type == oslock_recursive)
+ pthread_mutexattr_settype(&mta,
+ PTHREAD_MUTEX_RECURSIVE);
+ lock_c = pthread_mutex_init(&mutex, &mta);
+ if (lock_c != 0) {
+ XPTPD_ERROR("Mutex initialization faile - %s\n",
+ strerror(errno));
+ return oslock_fail;
+ }
+ return oslock_ok;
+
+ }
+ OSLockResult lock() {
+ lock_c = pthread_mutex_lock(&mutex);
+ if (lock_c != 0)
+ return oslock_fail;
+ return oslock_ok;
+ }
+ OSLockResult trylock() {
+ lock_c = pthread_mutex_trylock(&mutex);
+ if (lock_c != 0)
+ return oslock_fail;
+ return oslock_ok;
+ }
+ OSLockResult unlock() {
+ lock_c = pthread_mutex_unlock(&mutex);
+ if (lock_c != 0)
+ return oslock_fail;
+ return oslock_ok;
+ }
+};
+
+class LinuxLockFactory:public OSLockFactory {
+ public:
+ OSLock * createLock(OSLockType type) {
+ LinuxLock *lock = new LinuxLock();
+ if (lock->initialize(type) != oslock_ok) {
+ delete lock;
+ lock = NULL;
+ }
+ return lock;
+ }
+};
+
+class LinuxCondition:public OSCondition {
+ friend class LinuxConditionFactory;
+ private:
+ pthread_cond_t port_ready_signal;
+ pthread_mutex_t port_lock;
+ protected:
+ bool initialize() {
+ int lock_c;
+ pthread_cond_init(&port_ready_signal, NULL);
+ lock_c = pthread_mutex_init(&port_lock, NULL);
+ if (lock_c != 0)
+ return false;
+ return true;
+ }
+public:
+ bool wait_prelock() {
+ pthread_mutex_lock(&port_lock);
+ up();
+ return true;
+ }
+ bool wait() {
+ pthread_cond_wait(&port_ready_signal, &port_lock);
+ down();
+ pthread_mutex_unlock(&port_lock);
+ return true;
+ }
+ bool signal() {
+ pthread_mutex_lock(&port_lock);
+ if (waiting())
+ pthread_cond_broadcast(&port_ready_signal);
+ pthread_mutex_unlock(&port_lock);
+ return true;
+ }
+};
+
+class LinuxConditionFactory:public OSConditionFactory {
+ public:
+ OSCondition * createCondition() {
+ LinuxCondition *result = new LinuxCondition();
+ return result->initialize() ? result : NULL;
+ }
+};
+
+class LinuxTimerQueue;
+
+struct TimerQueue_t;
+
+struct LinuxTimerQueueHandlerArg {
+ timer_t timer_handle;
+ struct sigevent sevp;
+ event_descriptor_t *inner_arg;
+ ostimerq_handler func;
+ int type;
+ bool rm;
+ TimerQueue_t *timer_queue;
+};
+
+typedef std::list < LinuxTimerQueueHandlerArg * >TimerArgList_t;
+
+struct TimerQueue_t {
+ TimerArgList_t arg_list;
+ pthread_mutex_t lock;
+};
+
+typedef std::map < int, TimerQueue_t > TimerQueueMap_t;
+
+void LinuxTimerQueueHandler(union sigval arg_in);
+
+class LinuxTimerQueue:public OSTimerQueue {
+ friend class LinuxTimerQueueFactory;
+ friend void LinuxTimerQueueHandler(union sigval arg_in);
+ private:
+ TimerQueueMap_t timerQueueMap;
+ TimerArgList_t retiredTimers;
+ bool in_callback;
+ protected:
+ LinuxTimerQueue() {
+ int err;
+ pthread_mutex_t retiredTimersLock;
+ pthread_mutexattr_t retiredTimersLockAttr;
+ err = pthread_mutexattr_init(&retiredTimersLockAttr);
+ if (err != 0) {
+ XPTPD_ERROR("mutexattr_init()");
+ exit(0);
+ }
+ err =
+ pthread_mutexattr_settype(&retiredTimersLockAttr,
+ PTHREAD_MUTEX_NORMAL);
+ if (err != 0) {
+ XPTPD_ERROR("mutexattr_settype()");
+ exit(0);
+ }
+ err =
+ pthread_mutex_init(&retiredTimersLock,
+ &retiredTimersLockAttr);
+ if (err != 0) {
+ XPTPD_ERROR("mutex_init()");
+ exit(0);
+ }
+ };
+ public:
+ bool addEvent(unsigned long micros, int type, ostimerq_handler func,
+ event_descriptor_t * arg, bool rm, unsigned *event) {
+ LinuxTimerQueueHandlerArg *outer_arg =
+ new LinuxTimerQueueHandlerArg();
+ if (timerQueueMap.find(type) == timerQueueMap.end()) {
+ pthread_mutex_init(&timerQueueMap[type].lock, NULL);
+ }
+ outer_arg->inner_arg = arg;
+ outer_arg->func = func;
+ outer_arg->type = type;
+ outer_arg->timer_queue = &timerQueueMap[type];
+ sigset_t set;
+ sigset_t oset;
+ int err;
+ timer_t timerhandle;
+ struct sigevent ev;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ err = pthread_sigmask(SIG_BLOCK, &set, &oset);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_BLOCK ... )");
+ exit(0);
+ }
+ pthread_mutex_lock(&timerQueueMap[type].lock);
+ {
+ struct itimerspec its;
+ memset(&ev, 0, sizeof(ev));
+ ev.sigev_notify = SIGEV_THREAD;
+ ev.sigev_value.sival_ptr = outer_arg;
+ ev.sigev_notify_function = LinuxTimerQueueHandler;
+ ev.sigev_notify_attributes = new pthread_attr_t;
+ pthread_attr_init((pthread_attr_t *) ev.sigev_notify_attributes);
+ pthread_attr_setdetachstate((pthread_attr_t *) ev.sigev_notify_attributes,
+ PTHREAD_CREATE_DETACHED);
+ if (timer_create(CLOCK_MONOTONIC, &ev, &timerhandle) == -1) {
+ XPTPD_ERROR("timer_create failed - %s\n",
+ strerror(errno));
+ exit(0);
+ }
+ outer_arg->timer_handle = timerhandle;
+ outer_arg->sevp = ev;
+
+ memset(&its, 0, sizeof(its));
+ its.it_value.tv_sec = micros / 1000000;
+ its.it_value.tv_nsec = (micros % 1000000) * 1000;
+ timer_settime(outer_arg->timer_handle, 0, &its, NULL);
+ }
+ timerQueueMap[type].arg_list.push_front(outer_arg);
+
+ pthread_mutex_unlock(&timerQueueMap[type].lock);
+
+ err = pthread_sigmask(SIG_SETMASK, &oset, NULL);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_SETMASK ... )");
+ exit(0);
+ }
+ return true;
+ }
+ bool cancelEvent(int type, unsigned *event) {
+ TimerQueueMap_t::iterator iter = timerQueueMap.find(type);
+ if (iter == timerQueueMap.end())
+ return false;
+ sigset_t set;
+ sigset_t oset;
+ int err;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ err = pthread_sigmask(SIG_BLOCK, &set, &oset);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_BLOCK ... )");
+ exit(0);
+ }
+ pthread_mutex_lock(&timerQueueMap[type].lock);
+ while (!timerQueueMap[type].arg_list.empty()) {
+ LinuxTimerQueueHandlerArg *del_arg =
+ timerQueueMap[type].arg_list.front();
+ timerQueueMap[type].arg_list.pop_front();
+ timer_delete(del_arg->timer_handle);
+ delete(pthread_attr_t *) del_arg->sevp.
+ sigev_notify_attributes;
+ if (del_arg->rm)
+ delete del_arg->inner_arg;
+ delete del_arg;
+ }
+ pthread_mutex_unlock(&timerQueueMap[type].lock);
+ err = pthread_sigmask(SIG_SETMASK, &oset, NULL);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_SETMASK ... )");
+ exit(0);
+ }
+ return true;
+ }
+};
+
+void LinuxTimerQueueHandler(union sigval arg_in)
+{
+ LinuxTimerQueueHandlerArg *arg =
+ (LinuxTimerQueueHandlerArg *) arg_in.sival_ptr;
+ bool runnable = false;
+ unsigned size;
+
+ pthread_mutex_lock(&arg->timer_queue->lock);
+ size = arg->timer_queue->arg_list.size();
+ arg->timer_queue->arg_list.remove(arg);
+ if (arg->timer_queue->arg_list.size() < size) {
+ runnable = true;
+ }
+ pthread_mutex_unlock(&arg->timer_queue->lock);
+
+ if (runnable) {
+ arg->func(arg->inner_arg);
+ if (arg->rm)
+ delete arg->inner_arg;
+ delete(pthread_attr_t *) arg->sevp.sigev_notify_attributes;
+ }
+}
+
+class LinuxTimerQueueFactory:public OSTimerQueueFactory {
+ public:
+ virtual OSTimerQueue * createOSTimerQueue() {
+ LinuxTimerQueue *timerq = new LinuxTimerQueue();
+ return timerq;
+ };
+};
+
+class LinuxTimer:public OSTimer {
+ friend class LinuxTimerFactory;
+ public:
+ virtual unsigned long sleep(unsigned long micros) {
+ struct timespec req = { 0, micros }; /* Should be micros*1000 -Chris */
+ nanosleep(&req, NULL);
+ return micros;
+ }
+ protected:
+ LinuxTimer() {};
+};
+
+class LinuxTimerFactory:public OSTimerFactory {
+ public:
+ virtual OSTimer * createTimer() {
+ return new LinuxTimer();
+ }
+};
+
+struct OSThreadArg {
+ OSThreadFunction func;
+ void *arg;
+ OSThreadExitCode ret;
+};
+
+void *OSThreadCallback(void *input)
+{
+ OSThreadArg *arg = (OSThreadArg *) input;
+ arg->ret = arg->func(arg->arg);
+ return 0;
+}
+
+class LinuxThread:public OSThread {
+ friend class LinuxThreadFactory;
+ private:
+
+ pthread_t thread_id;
+ OSThreadArg *arg_inner;
+ public:
+ virtual bool start(OSThreadFunction function, void *arg) {
+ sigset_t set;
+ sigset_t oset;
+ int err;
+ arg_inner = new OSThreadArg();
+ arg_inner->func = function;
+ arg_inner->arg = arg;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ err = pthread_sigmask(SIG_BLOCK, &set, &oset);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_BLOCK ... )");
+ return false;
+ }
+ err = pthread_create(&thread_id, NULL, OSThreadCallback,
+ arg_inner);
+ if (err != 0)
+ return false;
+ sigdelset(&oset, SIGALRM);
+ err = pthread_sigmask(SIG_SETMASK, &oset, NULL);
+ if (err != 0) {
+ XPTPD_ERROR
+ ("Add timer pthread_sigmask( SIG_SETMASK ... )");
+ return false;
+ }
+
+ return true;
+ }
+ virtual bool join(OSThreadExitCode & exit_code) {
+ int err;
+ err = pthread_join(thread_id, NULL);
+ if (err != 0)
+ return false;
+ exit_code = arg_inner->ret;
+ delete arg_inner;
+ return true;
+ }
+ protected:
+ LinuxThread() {};
+};
+
+class LinuxThreadFactory:public OSThreadFactory {
+ public:
+ OSThread * createThread() {
+ return new LinuxThread();
+ }
+};
+
+class LinuxPCAPNetworkInterface:public OSNetworkInterface {
+ friend class LinuxPCAPNetworkInterfaceFactory;
+ private:
+ LinkLayerAddress local_addr;
+ int sd_event;
+ int sd_general;
+ LinuxTimestamper *timestamper;
+ int ifindex;
+ public:
+ virtual net_result send(LinkLayerAddress * addr, uint8_t * payload,
+ size_t length, bool timestamp) {
+ sockaddr_ll *remote = NULL;
+ int err;
+ remote = new struct sockaddr_ll;
+ memset(remote, 0, sizeof(*remote));
+ remote->sll_family = AF_PACKET;
+ remote->sll_protocol = htons(PTP_ETHERTYPE);
+ remote->sll_ifindex = ifindex;
+ remote->sll_halen = ETH_ALEN;
+ addr->toOctetArray(remote->sll_addr);
+ if (timestamp) {
+ err = sendto(sd_event, payload, length, 0,
+ (sockaddr *) remote, sizeof(*remote));
+ } else {
+ err = sendto(sd_general, payload, length, 0,
+ (sockaddr *) remote, sizeof(*remote));
+ }
+ delete remote;
+ if (err == -1) {
+ XPTPD_ERROR("Failed to send: %s(%d)", strerror(errno),
+ errno);
+ return net_fatal;
+ }
+ return net_succeed;
+ }
+
+ virtual net_result recv(LinkLayerAddress * addr, uint8_t * payload,
+ size_t & length) {
+ fd_set readfds;
+ int err;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct {
+ struct cmsghdr cm;
+ char control[256];
+ } control;
+ struct sockaddr_ll remote;
+ struct iovec sgentry;
+
+ struct timeval timeout = { 0, 100000 };
+
+ FD_ZERO(&readfds);
+ FD_SET(sd_event, &readfds);
+
+ err = select(sd_event + 1, &readfds, NULL, NULL, &timeout);
+ if (err == 0) {
+ return net_trfail;
+ } else if (err == -1) {
+ if (err == EINTR) {
+ XPTPD_ERROR("select() recv signal");
+ } else {
+ XPTPD_ERROR("select() failed");
+ return net_fatal;
+ }
+ }
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_iov = &sgentry;
+ msg.msg_iovlen = 1;
+
+ sgentry.iov_base = payload;
+ sgentry.iov_len = length;
+
+ memset(&remote, 0, sizeof(remote));
+ msg.msg_name = (caddr_t) & remote;
+ msg.msg_namelen = sizeof(remote);
+ msg.msg_control = &control;
+ msg.msg_controllen = sizeof(control);
+
+ err = recvmsg(sd_event, &msg, 0);
+ if (err < 0)
+ return net_fatal;
+ *addr = LinkLayerAddress(remote.sll_addr);
+
+ if (err > 0 && !(payload[0] & 0x8)) {
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SO_TIMESTAMPING) {
+ struct timespec *ts_device, *ts_system;
+ Timestamp device, system;
+ ts_system =
+ ((struct timespec *)CMSG_DATA(cmsg))
+ + 1;
+ system = tsToTimestamp(ts_system);
+ ts_device = ts_system + 1;
+ device = tsToTimestamp(ts_device);
+ timestamper->updateCrossStamp(&system,
+ &device);
+ timestamper->pushRXTimestamp(&device);
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+ }
+
+ length = err;
+ return net_succeed;
+ }
+
+ virtual void getLinkLayerAddress(LinkLayerAddress * addr) {
+ *addr = local_addr;
+ }
+
+ virtual unsigned getPayloadOffset() {
+ return 0;
+ }
+
+ virtual ~ LinuxPCAPNetworkInterface() {
+ close(sd_event);
+ close(sd_general);
+ }
+
+ protected:
+ LinuxPCAPNetworkInterface() {};
+};
+
+class LinuxPCAPNetworkInterfaceFactory:public OSNetworkInterfaceFactory {
+ public:
+ virtual bool createInterface(OSNetworkInterface ** net_iface,
+ InterfaceLabel * label,
+ HWTimestamper * timestamper) {
+ struct ifreq device;
+ int err;
+ struct sockaddr_ll ifsock_addr;
+ struct packet_mreq mr_8021as;
+ LinkLayerAddress addr;
+ int ifindex;
+
+ LinuxPCAPNetworkInterface *net_iface_l =
+ new LinuxPCAPNetworkInterface();
+ InterfaceName *ifname = dynamic_cast < InterfaceName * >(label);
+ if (ifname == NULL) {
+ XPTPD_ERROR("ifame == NULL \n");
+ return false;
+ }
+
+ net_iface_l->sd_general =
+ socket(PF_PACKET, SOCK_DGRAM, htons(PTP_ETHERTYPE));
+ if (net_iface_l->sd_general == -1) {
+ XPTPD_ERROR("failed to open general socket: %s \n",
+ strerror(errno));
+ return false;
+ }
+ net_iface_l->sd_event =
+ socket(PF_PACKET, SOCK_DGRAM, htons(PTP_ETHERTYPE));
+ if (net_iface_l->sd_event == -1) {
+ XPTPD_ERROR("failed to open event socket: %s \n",
+ strerror(errno));
+ return false;
+ }
+
+ memset(&device, 0, sizeof(device));
+ ifname->toString(device.ifr_name, IFNAMSIZ);
+ err = ioctl(net_iface_l->sd_event, SIOCGIFHWADDR, &device);
+ if (err == -1) {
+ XPTPD_ERROR("Failed to get interface address: %s",
+ strerror(errno));
+ return false;
+ }
+ addr = LinkLayerAddress(((struct sockaddr_ll *)&device.ifr_hwaddr)->sll_addr);
+ net_iface_l->local_addr = addr;
+
+ err = ioctl(net_iface_l->sd_event, SIOCGIFINDEX, &device);
+ if (err == -1) {
+ XPTPD_ERROR("Failed to get interface index: %s",
+ strerror(errno));
+ return false;
+ }
+ ifindex = device.ifr_ifindex;
+ net_iface_l->ifindex = ifindex;
+ memset(&mr_8021as, 0, sizeof(mr_8021as));
+ mr_8021as.mr_ifindex = ifindex;
+ mr_8021as.mr_type = PACKET_MR_MULTICAST;
+ mr_8021as.mr_alen = 6;
+ memcpy(mr_8021as.mr_address, P8021AS_MULTICAST,
+ mr_8021as.mr_alen);
+ err = setsockopt(net_iface_l->sd_event, SOL_PACKET,
+ PACKET_ADD_MEMBERSHIP, &mr_8021as,
+ sizeof(mr_8021as));
+ if (err == -1) {
+ XPTPD_ERROR
+ ("Unable to add PTP multicast addresses to port id: %u",
+ ifindex);
+ return false;
+ }
+
+ memset(&ifsock_addr, 0, sizeof(ifsock_addr));
+ ifsock_addr.sll_family = AF_PACKET;
+ ifsock_addr.sll_ifindex = ifindex;
+ ifsock_addr.sll_protocol = htons(PTP_ETHERTYPE);
+ err = bind(net_iface_l->sd_event, (sockaddr *) & ifsock_addr,
+ sizeof(ifsock_addr));
+ if (err == -1) {
+ XPTPD_ERROR("Call to bind() failed: %s",
+ strerror(errno));
+ return false;
+ }
+
+ net_iface_l->timestamper = dynamic_cast < LinuxTimestamper * >(timestamper);
+ if (net_iface_l->timestamper == NULL) {
+ XPTPD_ERROR("timestamper == NULL\n");
+ return false;
+ }
+ net_iface_l->timestamper->setSocketDescriptor(net_iface_l->sd_event);
+ if (!net_iface_l->timestamper->post_init(ifindex)) {
+ XPTPD_ERROR("post_init failed\n");
+ return false;
+ }
+ *net_iface = net_iface_l;
+
+ return true;
+ }
+};
+
+class LinuxSimpleIPC:public OS_IPC {
+ public:
+ LinuxSimpleIPC() {};
+ ~LinuxSimpleIPC() {}
+ virtual bool init() {
+ return true;
+ }
+ virtual bool update(int64_t ml_phoffset, int64_t ls_phoffset,
+ int32_t ml_freqoffset, int32_t ls_freqoffset,
+ uint64_t local_time) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "Master-Local Phase Offset: %ld\n"
+ "Master-Local Frequency Offset: %d\n"
+ "Local-System Phase Offset: %ld\n"
+ "Local-System Frequency Offset: %d\n"
+ "Local Time: %lu\n", ml_phoffset, ml_freqoffset,
+ ls_phoffset, ls_freqoffset, local_time);
+#endif
+ return true;
+ }
+};
+
+#endif
--- /dev/null
+/******************************************************************************
+
+ Copyright (c) 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 PLATFORM_HPP
+#define PLATFORM_HPP
+
+#include <arpa/inet.h>
+
+#define PLAT_strncpy( dest, src, max ) strncpy( dest, src, max+1 );
+
+#define PLAT_htons( s ) htons( s )
+#define PLAT_htonl( l ) htonl( l )
+#define PLAT_ntohs( s ) ntohs( s )
+#define PLAT_ntohl( l ) ntohl( l )
+
+#endif
--- /dev/null
+D/daemon_cl////
+D/x64////
+D/named_pipe_test////
+/gptp.sln/1.1/Fri Sep 21 16:52:20 2012/-kb/
--- /dev/null
+linux_igb_avb/daemons/gptp/windows
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+D/x64////
+/ReadMe.txt/1.1/Fri Sep 21 20:19:03 2012//
+/daemon_cl.cpp/1.1/Fri Sep 7 19:10:38 2012//
+/daemon_cl.vcxproj/1.1/Fri Sep 21 16:50:01 2012//
+/daemon_cl.vcxproj.filters/1.1/Fri Sep 21 16:50:23 2012//
+/daemon_cl.vcxproj.user/1.1/Fri Sep 7 18:39:51 2012//
+/ipcdef.hpp/1.1/Fri Sep 7 19:11:15 2012//
+/packet.cpp/1.1/Fri Sep 7 19:10:51 2012//
+/packet.hpp/1.1/Fri Sep 7 19:11:26 2012//
+/platform.hpp/1.1/Fri Sep 7 19:11:37 2012//
+/stdafx.cpp/1.1/Fri Sep 7 18:39:51 2012//
+/stdafx.h/1.1/Fri Sep 7 18:39:51 2012//
+/targetver.h/1.1/Fri Sep 7 18:39:51 2012//
+/tsc.hpp/1.1/Fri Sep 21 16:58:33 2012//
+/windows_hal.hpp/1.1/Fri Sep 21 16:53:58 2012//
--- /dev/null
+linux_igb_avb/daemons/gptp/windows/daemon_cl
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+========================================================================\r
+(C) Copyright 2009-2012 Intel Corporation, All Rights Reserved\r
+Author: Christopher Hall <christopher.s.hall@intel.com>\r
+========================================================================\r
+\r
+========================================================================\r
+ CONSOLE APPLICATION : daemon_cl Project Overview\r
+========================================================================\r
+\r
+* Dependencies\r
+\r
+ WinPCAP Developer's Pack is required for linking (WpdPack_*.zip)\r
+ WinPCAP must also be installed on any machine where the daemon runs (WinPcap_*.exe installer for windows)\r
+\r
+To run from the command line:\r
+\r
+daemon_cl.exe xx-xx-xx-xx-xx-xx\r
+\r
+ where xx-xx-xx-xx-xx-xx is the mac address of the local interface\r
+\r
+* Terminology\r
+\r
+ master - 802.1AS Grandmaster Clock\r
+ local - local network device clock (802.1AS timestamp source)\r
+ system - clock use elsewhere on a PC-like device, e.g. TSC or HPET timer\r
+\r
+* Interprocess Communication:\r
+\r
+The daemon communicates with other user processes through a named pipe. The pipe name and message format is defined in ipcdef.hpp.\r
+\r
+The pipe name is "gptp-update". An example is in the project named_pipe_test.\r
+\r
+The message format is:\r
+\r
+ Integer64 <master-local phase offset>\r
+ Integer64 <local-system phase offset>\r
+ Integer32 <master-local frequency offset>\r
+ Integer32 <local-system frequency offset>\r
+ UInteger64 <local time of last update>\r
+\r
+* Meaning of IPC provided values:\r
+\r
+ master ~= local - <master-local phase offset>\r
+ local ~= system - <local-system phase offset>\r
+ Dmaster ~= Dlocal * (1-<master-local phase offset>/1e12)\r
+ (where D denotes a delta rather than a specific value)\r
+ Dlocal ~= Dsystem * (1-<local-system freq offset>/1e12)\r
+ (where D denotes a delta rather than a specific value)\r
+\r
+* Known Limitations:\r
+\r
+ * There are problems with timestamp accuracy create problems using switches that impose limits on the peer rate offset\r
+ * The current driver version does not allow timestamping between the system clock (e.g. TCS) and the network device clock;\r
+ systems offsets are not valid\r
+\r
+\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+\r
+#include "ieee1588.hpp"\r
+#include "avbts_clock.hpp"\r
+#include "avbts_osnet.hpp"\r
+#include "avbts_oslock.hpp"\r
+#include "windows_hal.hpp"\r
+#include <tchar.h>\r
+\r
+#define MACSTR_LENGTH 17\r
+\r
+static bool exit_flag;\r
+\r
+BOOL WINAPI ctrl_handler( DWORD ctrl_type ) {\r
+ bool ret;\r
+ if( ctrl_type == CTRL_C_EVENT ) {\r
+ exit_flag = true;\r
+ ret = true;\r
+ } else {\r
+ ret = false;\r
+ }\r
+ return ret;\r
+}\r
+\r
+int parseMacAddr( _TCHAR *macstr, uint8_t *octet_string ) {\r
+ int i;\r
+ _TCHAR *cur = macstr;\r
+\r
+ if( strnlen_s( macstr, MACSTR_LENGTH ) != 17 ) return -1;\r
+\r
+ for( i = 0; i < ETHER_ADDR_OCTETS; ++i ) {\r
+ octet_string[i] = strtol( cur, &cur, 16 ) & 0xFF;\r
+ ++cur;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int _tmain(int argc, _TCHAR* argv[])\r
+{\r
+ bool force_slave = false;\r
+ int32_t offset = 0;\r
+ bool syntonize = false;\r
+\r
+ // Register default network interface\r
+ WindowsPCAPNetworkInterfaceFactory *default_factory = new WindowsPCAPNetworkInterfaceFactory();\r
+ OSNetworkInterfaceFactory::registerFactory( factory_name_t( "default" ), default_factory );\r
+\r
+ // Create thread, lock, timer, timerq factories\r
+ WindowsThreadFactory *thread_factory = new WindowsThreadFactory();\r
+ WindowsTimerQueueFactory *timerq_factory = new WindowsTimerQueueFactory();\r
+ WindowsLockFactory *lock_factory = new WindowsLockFactory();\r
+ WindowsTimerFactory *timer_factory = new WindowsTimerFactory();\r
+ WindowsConditionFactory *condition_factory = new WindowsConditionFactory();\r
+ WindowsNamedPipeIPC *ipc = new WindowsNamedPipeIPC();\r
+ if( !ipc->init() ) {\r
+ delete ipc;\r
+ ipc = NULL;\r
+ }\r
+\r
+ // Create Low level network interface object\r
+ uint8_t local_addr_ostr[ETHER_ADDR_OCTETS];\r
+ if( argc < 2 ) return -1;\r
+ parseMacAddr( argv[1], local_addr_ostr );\r
+ LinkLayerAddress local_addr(local_addr_ostr);\r
+ \r
+ // Create Clock object\r
+ IEEE1588Clock *clock = new IEEE1588Clock( false, timerq_factory, ipc ); // Do not force slave\r
+ // Create HWTimestamper object\r
+ HWTimestamper *timestamper = new WindowsTimestamper();\r
+ // Create Port Object linked to clock and low level\r
+ IEEE1588Port *port = new IEEE1588Port( clock, 1, false, timestamper, false, 0, &local_addr,\r
+ condition_factory, thread_factory, timer_factory, lock_factory );\r
+ if( !port->init_port() ) {\r
+ printf( "Failed to initialize port\n" );\r
+ return -1;\r
+ }\r
+ port->processEvent( POWERUP );\r
+\r
+ // Wait for Ctrl-C\r
+ if( !SetConsoleCtrlHandler( ctrl_handler, true )) {\r
+ printf( "Unable to register Ctrl-C handler\n" );\r
+ return -1;\r
+ }\r
+\r
+ while( !exit_flag ) Sleep( 1200 );\r
+\r
+ delete( ipc );\r
+\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup Label="ProjectConfigurations">\r
+ <ProjectConfiguration Include="Debug|Win32">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|x64">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|Win32">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|x64">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ </ItemGroup>\r
+ <PropertyGroup Label="Globals">\r
+ <ProjectGuid>{590D3055-A068-4B31-B4F9-B2ACC5F93663}</ProjectGuid>\r
+ <Keyword>Win32Proj</Keyword>\r
+ <RootNamespace>daemon_cl</RootNamespace>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+ <ImportGroup Label="ExtensionSettings">\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <PropertyGroup Label="UserMacros" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ </PropertyGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <ClCompile>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WPCAP;HAVE_REMOTE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\pcap\Include;C:\Users\John\src\gptp\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <AdditionalDependencies>wpcap.lib;Iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalLibraryDirectories>C:\Users\John\src\pcap\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <ClCompile>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WPCAP;HAVE_REMOTE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\pcap\Include;C:\Users\John\src\gptp\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <AdditionalDependencies>wpcap.lib;Iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <AdditionalLibraryDirectories>C:\Users\John\src\pcap\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WPCAP;HAVE_REMOTE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\pcap\Include;C:\Users\John\src\gptp\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ <AdditionalLibraryDirectories>C:\Users\John\src\pcap\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+ <AdditionalDependencies>wpcap.lib;Iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <GenerateMapFile>true</GenerateMapFile>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WPCAP;HAVE_REMOTE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\pcap\Include;$(SolutionDir)\daemon_cl\;..\..\..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ <AdditionalLibraryDirectories>C:\Users\John\src\pcap\Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+ <AdditionalDependencies>wpcap.lib;Iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <GenerateMapFile>true</GenerateMapFile>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemGroup>\r
+ <None Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="..\..\..\common\avbts_clock.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_message.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_oscondition.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_osipc.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_oslock.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_osnet.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_osthread.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_ostimer.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_ostimerq.hpp" />\r
+ <ClInclude Include="..\..\..\common\avbts_port.hpp" />\r
+ <ClInclude Include="..\..\..\common\ieee1588.hpp" />\r
+ <ClInclude Include="ipcdef.hpp" />\r
+ <ClInclude Include="packet.hpp" />\r
+ <ClInclude Include="platform.hpp" />\r
+ <ClInclude Include="stdafx.h" />\r
+ <ClInclude Include="targetver.h" />\r
+ <ClInclude Include="tsc.hpp" />\r
+ <ClInclude Include="windows_hal.hpp" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="..\..\..\common\avbts_osnet.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ieee1588clock.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ieee1588port.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ptp_message.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="daemon_cl.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="packet.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="stdafx.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>\r
+ </ClCompile>\r
+ </ItemGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <ImportGroup Label="ExtensionTargets">\r
+ </ImportGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup>\r
+ <Filter Include="Source Files">\r
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r
+ </Filter>\r
+ <Filter Include="Header Files">\r
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\r
+ </Filter>\r
+ <Filter Include="Resource Files">\r
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r
+ </Filter>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="stdafx.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="targetver.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\ieee1588.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_clock.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_message.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_osnet.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_port.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_oslock.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_ostimer.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="windows_hal.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_osthread.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="packet.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_oscondition.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_ostimerq.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\..\..\common\avbts_osipc.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="ipcdef.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="platform.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="tsc.hpp">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="stdafx.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="daemon_cl.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ieee1588port.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ieee1588clock.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\ptp_message.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\..\..\common\avbts_osnet.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="packet.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ </ItemGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LocalDebuggerCommandArguments>88-88-88-88-87-88</LocalDebuggerCommandArguments>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LocalDebuggerCommandArguments>00-13-20-F8-84-41</LocalDebuggerCommandArguments>\r
+ <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\r
+ </PropertyGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+\r
+#ifndef IPCDEF_HPP\r
+#define IPCDEF_HPP\r
+\r
+#include <stdint.h>\r
+\r
+#define PIPE_PREFIX "\\\\.\\pipe\\"\r
+#define P802_1AS_PIPENAME "gptp-update"\r
+#define OUTSTANDING_MESSAGES 10\r
+\r
+#pragma pack(push,1)\r
+\r
+class WindowsNPipeMessage {\r
+private:\r
+ int64_t ml_phoffset;\r
+ int64_t ls_phoffset;\r
+ int32_t ml_freqoffset;\r
+ int32_t ls_freq_offset;\r
+ uint64_t local_time;\r
+public:\r
+ WindowsNPipeMessage() {};\r
+ WindowsNPipeMessage( int64_t ml_phoffset, int64_t ls_phoffset, int32_t ml_freqoffset, int32_t ls_freq_offset, uint64_t local_time ) {\r
+ this->ml_phoffset = ml_phoffset;\r
+ this->ls_phoffset = ls_phoffset;\r
+ this->ml_freqoffset = ml_freqoffset;\r
+ this->ls_freq_offset = ls_freq_offset;\r
+ this->local_time = local_time;\r
+\r
+ }\r
+ bool write( HANDLE pipe ) {\r
+ DWORD bytes_written;\r
+ DWORD last_error = ERROR_SUCCESS;\r
+ if( WriteFile( pipe, this, sizeof(*this), &bytes_written, NULL ) == 0 ) {\r
+ last_error = GetLastError();\r
+ }\r
+ if( last_error == ERROR_SUCCESS || last_error == ERROR_PIPE_LISTENING ) {\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ bool read( HANDLE pipe ) {\r
+ DWORD bytes_written;\r
+ if( ReadFile( pipe, this, sizeof(*this), &bytes_written, NULL ) == 0 ) return false;\r
+ return true;\r
+ }\r
+ int64_t getMasterLocalOffset() { return ml_phoffset; }\r
+ int32_t getMasterLocalFreqOffset() { return ml_freqoffset; }\r
+ int64_t getLocalSystemOffset() { return ls_phoffset; }\r
+ int32_t getLocalSystemFreqOffset() { return ls_freq_offset; }\r
+ uint64_t getLocalTime() { return local_time; }\r
+};\r
+\r
+#pragma pack(pop)\r
+\r
+#endif\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+\r
+#include "packet.hpp"\r
+#include "platform.hpp"\r
+\r
+#include <pcap.h>\r
+#include "iphlpapi.h"\r
+\r
+#define MAX_FRAME_SIZE 96\r
+\r
+#define WINPCAP_INTERFACENAMEPREFIX "rpcap://\\Device\\NPF_"\r
+#define WINPCAP_INTERFACENAMEPREFIX_LENGTH 20\r
+#define WINPCAP_INTERFACENAMESUFFIX_LENGTH 38\r
+#define WINPCAP_INTERFACENAME_LENGTH WINPCAP_INTERFACENAMEPREFIX_LENGTH+WINPCAP_INTERFACENAMESUFFIX_LENGTH\r
+\r
+struct packet_handle {\r
+ pcap_t *iface;\r
+ char errbuf[PCAP_ERRBUF_SIZE];\r
+ packet_addr_t iface_addr;\r
+ HANDLE capture_lock;\r
+ uint16_t ethertype;\r
+ struct bpf_program filter;\r
+};\r
+\r
+\r
+packet_error_t mallocPacketHandle( struct packet_handle **phandle ) {\r
+ packet_error_t ret = PACKET_NO_ERROR;\r
+\r
+ packet_handle *handle = (struct packet_handle *) malloc((size_t) sizeof( *handle ));\r
+ if( handle == NULL ) {\r
+ ret = PACKET_NOMEMORY_ERROR;\r
+ goto fnexit;\r
+ }\r
+ *phandle = handle;\r
+\r
+ if(( handle->capture_lock = CreateMutex( NULL, FALSE, NULL )) == NULL ) {\r
+ ret = PACKET_CREATEMUTEX_ERROR;\r
+ goto fnexit;\r
+ }\r
+ handle->iface = NULL;\r
+\r
+fnexit:\r
+ return ret;\r
+}\r
+\r
+void freePacketHandle( struct packet_handle *handle ) {\r
+ CloseHandle( handle->capture_lock );\r
+ free((void *) handle );\r
+}\r
+\r
+packet_error_t openInterfaceByAddr( struct packet_handle *handle, packet_addr_t *addr, int timeout ) {\r
+ packet_error_t ret = PACKET_NO_ERROR;\r
+ char name[WINPCAP_INTERFACENAME_LENGTH+1] = "\0";\r
+\r
+ PIP_ADAPTER_ADDRESSES pAdapterAddress;\r
+ IP_ADAPTER_ADDRESSES AdapterAddress[32]; // Allocate information for up to 32 NICs\r
+ DWORD dwBufLen = sizeof(AdapterAddress); // Save memory size of buffer\r
+\r
+ DWORD dwStatus = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, AdapterAddress, &dwBufLen);\r
+\r
+ if( dwStatus != ERROR_SUCCESS ) {\r
+ ret = PACKET_IFLOOKUP_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+ for( pAdapterAddress = AdapterAddress; pAdapterAddress != NULL; pAdapterAddress = pAdapterAddress->Next ) {\r
+ if( pAdapterAddress->PhysicalAddressLength == ETHER_ADDR_OCTETS &&\r
+ memcmp( pAdapterAddress->PhysicalAddress, addr->addr, ETHER_ADDR_OCTETS ) == 0 ) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( pAdapterAddress != NULL ) {\r
+ strcpy_s( name, WINPCAP_INTERFACENAMEPREFIX );\r
+ strncpy_s( name+WINPCAP_INTERFACENAMEPREFIX_LENGTH, WINPCAP_INTERFACENAMESUFFIX_LENGTH+1, pAdapterAddress->AdapterName, WINPCAP_INTERFACENAMESUFFIX_LENGTH );\r
+ printf( "Opening: %s\n", name );\r
+ handle->iface = pcap_open( name, MAX_FRAME_SIZE, PCAP_OPENFLAG_MAX_RESPONSIVENESS | PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_LOCAL,\r
+ timeout, NULL, handle->errbuf );\r
+ if( handle->iface == NULL ) {\r
+ ret = PACKET_IFLOOKUP_ERROR;\r
+ goto fnexit;\r
+ }\r
+ handle->iface_addr = *addr;\r
+ } else {\r
+ ret = PACKET_IFNOTFOUND_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+fnexit:\r
+ return ret;\r
+}\r
+\r
+void closeInterface( struct packet_handle *pfhandle ) {\r
+ if( pfhandle->iface != NULL ) pcap_close( pfhandle->iface );\r
+}\r
+\r
+\r
+packet_error_t sendFrame( struct packet_handle *handle, packet_addr_t *addr, uint16_t ethertype, uint8_t *payload, size_t length ) {\r
+ packet_error_t ret = PACKET_NO_ERROR;\r
+ uint16_t ethertype_no = PLAT_htons( ethertype );\r
+ uint8_t *payload_ptr = payload;\r
+\r
+ if( length < PACKET_HDR_LENGTH ) {\r
+ ret = PACKET_BADBUFFER_ERROR;\r
+ }\r
+\r
+ // Build Header\r
+ memcpy( payload_ptr, addr->addr, ETHER_ADDR_OCTETS ); payload_ptr+= ETHER_ADDR_OCTETS;\r
+ memcpy( payload_ptr, handle->iface_addr.addr, ETHER_ADDR_OCTETS ); payload_ptr+= ETHER_ADDR_OCTETS;\r
+ memcpy( payload_ptr, ðertype_no, sizeof( ethertype_no ));\r
+\r
+ if( pcap_sendpacket( handle->iface, payload, (int) length+PACKET_HDR_LENGTH ) != 0 ) {\r
+ ret = PACKET_XMIT_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+fnexit:\r
+ return ret;\r
+}\r
+\r
+packet_error_t packetBind( struct packet_handle *handle, uint16_t ethertype ) {\r
+ packet_error_t ret = PACKET_NO_ERROR;\r
+ char filter_expression[32] = "ether proto 0x";\r
+\r
+ sprintf_s( filter_expression+strlen(filter_expression), 31-strlen(filter_expression), "%hx", ethertype );\r
+ if( pcap_compile( handle->iface, &handle->filter, filter_expression, 1, 0 ) == -1 ) {\r
+ ret = PACKET_BIND_ERROR;\r
+ goto fnexit;\r
+ }\r
+ if( pcap_setfilter( handle->iface, &handle->filter ) == -1 ) {\r
+ ret = PACKET_BIND_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+ handle->ethertype = ethertype;\r
+\r
+fnexit:\r
+ return ret;\r
+}\r
+\r
+// Call to recvFrame must be thread-safe. However call to pcap_next_ex() isn't because of somewhat undefined memory management semantics.\r
+// Wrap call to pcap library with mutex\r
+packet_error_t recvFrame( struct packet_handle *handle, packet_addr_t *addr, uint8_t *payload, size_t &length ) {\r
+ packet_error_t ret = PACKET_NO_ERROR;\r
+ struct pcap_pkthdr *hdr_r;\r
+ u_char *data;\r
+\r
+ int pcap_result;\r
+ DWORD wait_result;\r
+\r
+ wait_result = WaitForSingleObject( handle->capture_lock, 1000 );\r
+ if( wait_result != WAIT_OBJECT_0 ) {\r
+ ret = PACKET_GETMUTEX_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+ pcap_result = pcap_next_ex( handle->iface, &hdr_r, (const u_char **) &data );\r
+ if( pcap_result == 0 ) {\r
+ ret = PACKET_RECVTIMEOUT_ERROR;\r
+ } else if( pcap_result < 0 ) {\r
+ ret = PACKET_RECVFAILED_ERROR;\r
+ } else {\r
+ length = hdr_r->len-PACKET_HDR_LENGTH >= length ? length : hdr_r->len-PACKET_HDR_LENGTH;\r
+ memcpy( payload, data+PACKET_HDR_LENGTH, length );\r
+ memcpy( addr->addr, data+ETHER_ADDR_OCTETS, ETHER_ADDR_OCTETS );\r
+ }\r
+ \r
+ if( !ReleaseMutex( handle->capture_lock )) {\r
+ ret = PACKET_RLSMUTEX_ERROR;\r
+ goto fnexit;\r
+ }\r
+\r
+fnexit:\r
+ return ret;\r
+}\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+\r
+#ifndef PACKET_H\r
+#define PACKET_H\r
+\r
+#include "stdint.h"\r
+\r
+#define ETHER_ADDR_OCTETS 6\r
+#define PACKET_HDR_LENGTH 14\r
+\r
+typedef enum {\r
+ PACKET_NO_ERROR = 0, PACKET_NOMEMORY_ERROR, PACKET_BADBUFFER_ERROR, PACKET_XMIT_ERROR, PACKET_IFLOOKUP_ERROR, PACKET_IFNOTFOUND_ERROR,\r
+ PACKET_CREATEMUTEX_ERROR, PACKET_GETMUTEX_ERROR, PACKET_RLSMUTEX_ERROR, PACKET_RECVTIMEOUT_ERROR, PACKET_RECVFAILED_ERROR,\r
+ PACKET_BIND_ERROR\r
+} packet_error_t; \r
+\r
+typedef struct { uint8_t addr[ETHER_ADDR_OCTETS]; } packet_addr_t;\r
+typedef struct packet_handle * pfhandle_t;\r
+\r
+packet_error_t mallocPacketHandle( pfhandle_t *pfhandle_r );\r
+void freePacketHandle( pfhandle_t pfhandle );\r
+\r
+packet_error_t openInterfaceByAddr( pfhandle_t pfhandle, packet_addr_t *addr, int timeout );\r
+void closeInterface( pfhandle_t pfhandle );\r
+packet_error_t sendFrame( pfhandle_t pfhandle, packet_addr_t *addr, uint16_t ethertype, uint8_t *payload, size_t length );\r
+packet_error_t recvFrame( pfhandle_t pfhandle, packet_addr_t *addr, uint8_t *payload, size_t &length );\r
+\r
+packet_error_t packetBind( struct packet_handle *handle, uint16_t ethertype );\r
+\r
+#endif /* PACKET_H */\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+#ifndef PLATFORM_HPP\r
+#define PLATFORM_HPP\r
+\r
+#include <Winsock2.h>\r
+\r
+#define PLAT_strncpy( dest, src, max ) strncpy_s( dest, max+1, src, _TRUNCATE );\r
+\r
+#define PLAT_htons( s ) htons( s )\r
+#define PLAT_htonl( l ) htonl( l )\r
+#define PLAT_ntohs( s ) ntohs( s )\r
+#define PLAT_ntohl( l ) ntohl( l )\r
+\r
+#endif\r
--- /dev/null
+// stdafx.cpp : source file that includes just the standard includes\r
+// daemon_cl.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
--- /dev/null
+// stdafx.h : include file for standard system include files,\r
+// or project specific include files that are used frequently, but\r
+// are changed infrequently\r
+//\r
+\r
+#pragma once\r
+\r
+#include "targetver.h"\r
+\r
+#include <stdio.h>\r
+#include <tchar.h>\r
+\r
+\r
+\r
+// TODO: reference additional headers your program requires here\r
--- /dev/null
+#pragma once\r
+\r
+// Including SDKDDKVer.h defines the highest available Windows platform.\r
+\r
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and\r
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.\r
+\r
+#include <SDKDDKVer.h>\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+#ifndef TSC_HPP\r
+#define TSC_HPP\r
+\r
+#include <intrin.h>\r
+#include <stdint.h>\r
+\r
+#define CPUFREQ_BASE 133\r
+\r
+inline unsigned __int64 PLAT_rdtsc()\r
+{\r
+ return __rdtsc();\r
+}\r
+\r
+// 'millis' argument specifies time to measure TSC over. A longer time is generally more reliable\r
+// Returns TSC frequency\r
+inline uint64_t getTSCFrequency( unsigned millis ) {\r
+ uint64_t tsc1, tsc2, multiplier;\r
+ unsigned msig, lsig;\r
+\r
+ tsc1 = PLAT_rdtsc();\r
+ Sleep( millis );\r
+ tsc2 = PLAT_rdtsc();\r
+ multiplier = (unsigned) (tsc2 - tsc1)/133;\r
+ lsig = multiplier % 1000000;\r
+ msig = (unsigned) multiplier / 1000000;\r
+ if( lsig >= 750000 ) multiplier = (msig+1)*1000000;\r
+ else if( lsig < 250000 ) multiplier = msig*1000000;\r
+ else multiplier = msig*1000000 + 500000;\r
+ return multiplier*CPUFREQ_BASE;\r
+}\r
+\r
+#endif/*TSC_HPP*/\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+#ifndef WINDOWS_HAL_HPP\r
+#define WINDOWS_HAL_HPP\r
+\r
+#include "avbts_osnet.hpp"\r
+#include "avbts_oslock.hpp"\r
+#include "avbts_oscondition.hpp"\r
+#include "avbts_ostimerq.hpp"\r
+#include "avbts_ostimer.hpp"\r
+#include "packet.hpp"\r
+#include "ieee1588.hpp"\r
+#include "iphlpapi.h"\r
+#include "ipcdef.hpp"\r
+#include "tsc.hpp"\r
+\r
+#include "avbts_osipc.hpp"\r
+\r
+#include <ntddndis.h>\r
+\r
+#include <map>\r
+\r
+class WindowsPCAPNetworkInterface : public OSNetworkInterface {\r
+ friend class WindowsPCAPNetworkInterfaceFactory;\r
+private:\r
+ pfhandle_t handle;\r
+ LinkLayerAddress local_addr;\r
+public:\r
+ virtual net_result send( LinkLayerAddress *addr, uint8_t *payload, size_t length, bool timestamp ) {\r
+ packet_addr_t dest;\r
+ addr->toOctetArray( dest.addr );\r
+ if( sendFrame( handle, &dest, PTP_ETHERTYPE, payload, length ) != PACKET_NO_ERROR ) return net_fatal;\r
+ return net_succeed;\r
+ }\r
+ virtual net_result recv( LinkLayerAddress *addr, uint8_t *payload, size_t &length ) {\r
+ packet_addr_t dest;\r
+ packet_error_t pferror = recvFrame( handle, &dest, payload, length );\r
+ if( pferror != PACKET_NO_ERROR && pferror != PACKET_RECVTIMEOUT_ERROR ) return net_fatal;\r
+ if( pferror == PACKET_RECVTIMEOUT_ERROR ) return net_trfail;\r
+ *addr = LinkLayerAddress( dest.addr );\r
+ return net_succeed;\r
+ }\r
+ virtual void getLinkLayerAddress( LinkLayerAddress *addr ) {\r
+ *addr = local_addr;\r
+ }\r
+ virtual unsigned getPayloadOffset() {\r
+ return PACKET_HDR_LENGTH;\r
+ }\r
+ virtual ~WindowsPCAPNetworkInterface() {\r
+ closeInterface( handle );\r
+ if( handle != NULL ) freePacketHandle( handle );\r
+ }\r
+protected:\r
+ WindowsPCAPNetworkInterface() { handle = NULL; };\r
+};\r
+\r
+class WindowsPCAPNetworkInterfaceFactory : public OSNetworkInterfaceFactory {\r
+public:\r
+ virtual bool createInterface( OSNetworkInterface **net_iface, InterfaceLabel *label, HWTimestamper *timestamper ) {\r
+ WindowsPCAPNetworkInterface *net_iface_l = new WindowsPCAPNetworkInterface();\r
+ LinkLayerAddress *addr = dynamic_cast<LinkLayerAddress *>(label);\r
+ if( addr == NULL ) goto error_nofree;\r
+ net_iface_l->local_addr = *addr;\r
+ packet_addr_t pfaddr;\r
+ addr->toOctetArray( pfaddr.addr );\r
+ if( mallocPacketHandle( &net_iface_l->handle ) != PACKET_NO_ERROR ) goto error_nofree;\r
+ if( openInterfaceByAddr( net_iface_l->handle, &pfaddr, 1 ) != PACKET_NO_ERROR ) goto error_free_handle;\r
+ if( packetBind( net_iface_l->handle, PTP_ETHERTYPE ) != PACKET_NO_ERROR ) goto error_free_handle;\r
+ *net_iface = net_iface_l;\r
+\r
+ return true;\r
+\r
+error_free_handle:\r
+error_nofree:\r
+ delete net_iface_l;\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+class WindowsLock : public OSLock {\r
+ friend class WindowsLockFactory;\r
+private:\r
+ OSLockType type;\r
+ DWORD thread_id;\r
+ HANDLE lock_c;\r
+ OSLockResult lock_l( DWORD timeout ) {\r
+ DWORD wait_result = WaitForSingleObject( lock_c, timeout );\r
+ if( wait_result == WAIT_TIMEOUT ) return oslock_held;\r
+ else if( wait_result == WAIT_OBJECT_0 ) return oslock_ok;\r
+ else return oslock_fail;\r
+\r
+ }\r
+ OSLockResult nonreentrant_lock_l( DWORD timeout ) {\r
+ OSLockResult result;\r
+ DWORD wait_result;\r
+ wait_result = WaitForSingleObject( lock_c, timeout );\r
+ if( wait_result == WAIT_OBJECT_0 ) {\r
+ if( thread_id == GetCurrentThreadId() ) {\r
+ result = oslock_self;\r
+ ReleaseMutex( lock_c );\r
+ } else {\r
+ result = oslock_ok;\r
+ thread_id = GetCurrentThreadId();\r
+ }\r
+ } else if( wait_result == WAIT_TIMEOUT ) result = oslock_held;\r
+ else result = oslock_fail;\r
+ \r
+ return result;\r
+ }\r
+protected:\r
+ WindowsLock() {\r
+ lock_c = NULL;\r
+ }\r
+ bool initialize( OSLockType type ) {\r
+ lock_c = CreateMutex( NULL, false, NULL );\r
+ if( lock_c == NULL ) return false;\r
+ this->type = type;\r
+ return true;\r
+ }\r
+ OSLockResult lock() {\r
+ if( type == oslock_recursive ) {\r
+ return lock_l( INFINITE );\r
+ }\r
+ return nonreentrant_lock_l( INFINITE );\r
+ }\r
+ OSLockResult trylock() {\r
+ if( type == oslock_recursive ) {\r
+ return lock_l( 0 );\r
+ }\r
+ return nonreentrant_lock_l( 0 );\r
+ }\r
+ OSLockResult unlock() {\r
+ ReleaseMutex( lock_c );\r
+ return oslock_ok;\r
+ }\r
+};\r
+\r
+class WindowsLockFactory : public OSLockFactory {\r
+public:\r
+ OSLock *createLock( OSLockType type ) {\r
+ WindowsLock *lock = new WindowsLock();\r
+ if( !lock->initialize( type )) {\r
+ delete lock;\r
+ lock = NULL;\r
+ }\r
+ return lock;\r
+ }\r
+};\r
+\r
+class WindowsCondition : public OSCondition {\r
+ friend class WindowsConditionFactory;\r
+private:\r
+ SRWLOCK lock;\r
+ CONDITION_VARIABLE condition;\r
+protected:\r
+ bool initialize() {\r
+ InitializeSRWLock( &lock );\r
+ InitializeConditionVariable( &condition );\r
+ return true;\r
+ }\r
+public:\r
+ bool wait_prelock() {\r
+ AcquireSRWLockExclusive( &lock );\r
+ up();\r
+ return true;\r
+ }\r
+ bool wait() {\r
+ BOOL result = SleepConditionVariableSRW( &condition, &lock, INFINITE, 0 );\r
+ bool ret = false;\r
+ if( result == TRUE ) {\r
+ down();\r
+ ReleaseSRWLockExclusive( &lock );\r
+ ret = true;\r
+ }\r
+ return ret;\r
+ }\r
+ bool signal() {\r
+ AcquireSRWLockExclusive( &lock );\r
+ if( waiting() ) WakeAllConditionVariable( &condition );\r
+ ReleaseSRWLockExclusive( &lock );\r
+ return true;\r
+ }\r
+};\r
+\r
+class WindowsConditionFactory : public OSConditionFactory {\r
+public:\r
+ OSCondition *createCondition() {\r
+ WindowsCondition *result = new WindowsCondition();\r
+ return result->initialize() ? result : NULL;\r
+ }\r
+};\r
+\r
+class WindowsTimerQueue;\r
+\r
+struct TimerQueue_t;\r
+\r
+struct WindowsTimerQueueHandlerArg {\r
+ HANDLE timer_handle;\r
+ HANDLE queue_handle;\r
+ event_descriptor_t *inner_arg;\r
+ ostimerq_handler func;\r
+ int type;\r
+ bool rm;\r
+ WindowsTimerQueue *queue;\r
+ TimerQueue_t *timer_queue;\r
+};\r
+\r
+typedef std::list<WindowsTimerQueueHandlerArg *> TimerArgList_t;\r
+\r
+struct TimerQueue_t {\r
+ TimerArgList_t arg_list;\r
+ HANDLE queue_handle;\r
+ SRWLOCK lock;\r
+};\r
+\r
+\r
+VOID CALLBACK WindowsTimerQueueHandler( PVOID arg_in, BOOLEAN ignore );\r
+\r
+typedef std::map<int,TimerQueue_t> TimerQueueMap_t;\r
+\r
+class WindowsTimerQueue : public OSTimerQueue {\r
+ friend class WindowsTimerQueueFactory;\r
+ friend VOID CALLBACK WindowsTimerQueueHandler( PVOID arg_in, BOOLEAN ignore );\r
+private:\r
+ TimerQueueMap_t timerQueueMap;\r
+ TimerArgList_t retiredTimers;\r
+ SRWLOCK retiredTimersLock;\r
+ void cleanupRetiredTimers() {\r
+ AcquireSRWLockExclusive( &retiredTimersLock );\r
+ while( !retiredTimers.empty() ) {\r
+ WindowsTimerQueueHandlerArg *retired_arg = retiredTimers.front();\r
+ retiredTimers.pop_front();\r
+ ReleaseSRWLockExclusive( &retiredTimersLock );\r
+ DeleteTimerQueueTimer( retired_arg->queue_handle, retired_arg->timer_handle, INVALID_HANDLE_VALUE );\r
+ if( retired_arg->rm ) delete retired_arg->inner_arg;\r
+ delete retired_arg;\r
+ AcquireSRWLockExclusive( &retiredTimersLock );\r
+ }\r
+ ReleaseSRWLockExclusive( &retiredTimersLock );\r
+\r
+ }\r
+protected:\r
+ WindowsTimerQueue() {\r
+ InitializeSRWLock( &retiredTimersLock );\r
+ };\r
+public:\r
+ bool addEvent( unsigned long micros, int type, ostimerq_handler func, event_descriptor_t *arg, bool rm, unsigned *event ) {\r
+ WindowsTimerQueueHandlerArg *outer_arg = new WindowsTimerQueueHandlerArg();\r
+ cleanupRetiredTimers();\r
+ if( timerQueueMap.find(type) == timerQueueMap.end() ) {\r
+ timerQueueMap[type].queue_handle = CreateTimerQueue();\r
+ InitializeSRWLock( &timerQueueMap[type].lock );\r
+ }\r
+ outer_arg->queue_handle = timerQueueMap[type].queue_handle;\r
+ outer_arg->inner_arg = arg;\r
+ outer_arg->func = func;\r
+ outer_arg->queue = this;\r
+ outer_arg->type = type;\r
+ outer_arg->timer_queue = &timerQueueMap[type];\r
+ AcquireSRWLockExclusive( &timerQueueMap[type].lock );\r
+ CreateTimerQueueTimer( &outer_arg->timer_handle, timerQueueMap[type].queue_handle, WindowsTimerQueueHandler, (void *) outer_arg, micros/1000, 0, 0 );\r
+ timerQueueMap[type].arg_list.push_front(outer_arg);\r
+ ReleaseSRWLockExclusive( &timerQueueMap[type].lock );\r
+ return true;\r
+ }\r
+ bool cancelEvent( int type, unsigned *event ) {\r
+ TimerQueueMap_t::iterator iter = timerQueueMap.find( type );\r
+ if( iter == timerQueueMap.end() ) return false;\r
+ AcquireSRWLockExclusive( &timerQueueMap[type].lock );\r
+ while( ! timerQueueMap[type].arg_list.empty() ) {\r
+ WindowsTimerQueueHandlerArg *del_arg = timerQueueMap[type].arg_list.front();\r
+ timerQueueMap[type].arg_list.pop_front();\r
+ ReleaseSRWLockExclusive( &timerQueueMap[type].lock );\r
+ DeleteTimerQueueTimer( del_arg->queue_handle, del_arg->timer_handle, INVALID_HANDLE_VALUE );\r
+ if( del_arg->rm ) delete del_arg->inner_arg;\r
+ delete del_arg;\r
+ AcquireSRWLockExclusive( &timerQueueMap[type].lock );\r
+ }\r
+ ReleaseSRWLockExclusive( &timerQueueMap[type].lock );\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+VOID CALLBACK WindowsTimerQueueHandler( PVOID arg_in, BOOLEAN ignore ) {\r
+ WindowsTimerQueueHandlerArg *arg = (WindowsTimerQueueHandlerArg *) arg_in;\r
+ arg->func( arg->inner_arg );\r
+\r
+ // Remove myself from unexpired timer queue\r
+ AcquireSRWLockExclusive( &arg->timer_queue->lock );\r
+ arg->timer_queue->arg_list.remove( arg );\r
+ ReleaseSRWLockExclusive( &arg->timer_queue->lock );\r
+\r
+ // Add myself to the expired timer queue\r
+ AcquireSRWLockExclusive( &arg->queue->retiredTimersLock );\r
+ arg->queue->retiredTimers.push_front( arg );\r
+ ReleaseSRWLockExclusive( &arg->queue->retiredTimersLock );\r
+}\r
+\r
+class WindowsTimerQueueFactory : public OSTimerQueueFactory {\r
+public:\r
+ virtual OSTimerQueue *createOSTimerQueue() {\r
+ WindowsTimerQueue *timerq = new WindowsTimerQueue();\r
+ return timerq;\r
+ };\r
+};\r
+\r
+class WindowsTimer : public OSTimer {\r
+ friend class WindowsTimerFactory;\r
+public:\r
+ virtual unsigned long sleep( unsigned long micros ) {\r
+ Sleep( micros/1000 );\r
+ return micros;\r
+ }\r
+protected:\r
+ WindowsTimer() {};\r
+};\r
+\r
+class WindowsTimerFactory : public OSTimerFactory {\r
+public:\r
+ virtual OSTimer *createTimer() {\r
+ return new WindowsTimer();\r
+ }\r
+};\r
+\r
+struct OSThreadArg {\r
+ OSThreadFunction func;\r
+ void *arg;\r
+ OSThreadExitCode ret;\r
+};\r
+\r
+DWORD WINAPI OSThreadCallback( LPVOID input ) {\r
+ OSThreadArg *arg = (OSThreadArg*) input;\r
+ arg->ret = arg->func( arg->arg );\r
+ return 0;\r
+}\r
+\r
+class WindowsThread : public OSThread {\r
+ friend class WindowsThreadFactory;\r
+private:\r
+ HANDLE thread_id;\r
+ OSThreadArg *arg_inner;\r
+public:\r
+ virtual bool start( OSThreadFunction function, void *arg ) {\r
+ arg_inner = new OSThreadArg();\r
+ arg_inner->func = function;\r
+ arg_inner->arg = arg;\r
+ thread_id = CreateThread( NULL, 0, OSThreadCallback, arg_inner, 0, NULL );\r
+ if( thread_id == NULL ) return false;\r
+ else return true;\r
+ }\r
+ virtual bool join( OSThreadExitCode &exit_code ) {\r
+ if( WaitForSingleObject( thread_id, INFINITE ) != WAIT_OBJECT_0 ) return false;\r
+ exit_code = arg_inner->ret;\r
+ delete arg_inner;\r
+ return true;\r
+ }\r
+protected:\r
+ WindowsThread() {};\r
+};\r
+\r
+class WindowsThreadFactory : public OSThreadFactory {\r
+public:\r
+ OSThread *createThread() {\r
+ return new WindowsThread();\r
+ }\r
+};\r
+\r
+#define NETCLOCK_HZ 1056000000\r
+#define ONE_WAY_PHY_DELAY 8000\r
+\r
+#define NETWORK_CARD_ID_PREFIX "\\\\.\\"\r
+#define OID_INTEL_GET_RXSTAMP 0xFF020264\r
+#define OID_INTEL_GET_TXSTAMP 0xFF020263\r
+#define OID_INTEL_GET_SYSTIM 0xFF020262\r
+#define OID_INTEL_SET_SYSTIM 0xFF020261\r
+\r
+class WindowsTimestamper : public HWTimestamper {\r
+private:\r
+ // No idea whether the underlying implementation is thread safe\r
+ HANDLE miniport;\r
+ LARGE_INTEGER tsc_hz;\r
+ DWORD readOID( NDIS_OID oid, void *output_buffer, DWORD size, DWORD *size_returned ) {\r
+ NDIS_OID oid_l = oid;\r
+ DWORD rc = DeviceIoControl(\r
+ miniport,\r
+ IOCTL_NDIS_QUERY_GLOBAL_STATS,\r
+ &oid_l,\r
+ sizeof(oid_l),\r
+ output_buffer,\r
+ size,\r
+ size_returned,\r
+ NULL );\r
+ if( rc == 0 ) return GetLastError();\r
+ return ERROR_SUCCESS;\r
+ }\r
+ Timestamp nanoseconds64ToTimestamp( uint64_t time ) {\r
+ Timestamp timestamp;\r
+ timestamp.nanoseconds = time % 1000000000;\r
+ timestamp.seconds_ls = (time / 1000000000) & 0xFFFFFFFF;\r
+ timestamp.seconds_ms = (uint16_t)((time / 1000000000) >> 32);\r
+ return timestamp;\r
+ }\r
+ uint64_t scaleNativeClockToNanoseconds( uint64_t time ) {\r
+ long double scaled_output = ((long double)NETCLOCK_HZ)/1000000000;\r
+ scaled_output = ((long double) time)/scaled_output;\r
+ return (uint64_t) scaled_output;\r
+ }\r
+ uint64_t scaleTSCClockToNanoseconds( uint64_t time ) {\r
+ long double scaled_output = ((long double)tsc_hz.QuadPart)/1000000000;\r
+ scaled_output = ((long double) time)/scaled_output;\r
+ return (uint64_t) scaled_output;\r
+ }\r
+public:\r
+ virtual bool HWTimestamper_init( InterfaceLabel *iface_label ) {\r
+ char network_card_id[64];\r
+ LinkLayerAddress *addr = dynamic_cast<LinkLayerAddress *>(iface_label);\r
+ if( addr == NULL ) return false;\r
+ PIP_ADAPTER_ADDRESSES pAdapterAddress;\r
+ IP_ADAPTER_ADDRESSES AdapterAddress[32]; // Allocate information for up to 32 NICs\r
+ DWORD dwBufLen = sizeof(AdapterAddress); // Save memory size of buffer\r
+\r
+ DWORD dwStatus = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, AdapterAddress, &dwBufLen);\r
+ if( dwStatus != ERROR_SUCCESS ) return false;\r
+\r
+ for( pAdapterAddress = AdapterAddress; pAdapterAddress != NULL; pAdapterAddress = pAdapterAddress->Next ) {\r
+ if( pAdapterAddress->PhysicalAddressLength == ETHER_ADDR_OCTETS && *addr == LinkLayerAddress( pAdapterAddress->PhysicalAddress )) { \r
+ break;\r
+ }\r
+ }\r
+\r
+ if( pAdapterAddress == NULL ) return false;\r
+\r
+ PLAT_strncpy( network_card_id, NETWORK_CARD_ID_PREFIX, 63 );\r
+ PLAT_strncpy( network_card_id+strlen(network_card_id), pAdapterAddress->AdapterName, 63-strlen(network_card_id) );\r
+\r
+ miniport = CreateFile( network_card_id,\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+ NULL, OPEN_EXISTING, 0, NULL );\r
+ if( miniport == INVALID_HANDLE_VALUE ) return false;\r
+\r
+ tsc_hz.QuadPart = getTSCFrequency( 1000 );\r
+\r
+ return true;\r
+ }\r
+ virtual bool HWTimestamper_gettime( Timestamp *system_time, Timestamp *device_time, uint32_t *local_clock, uint32_t *nominal_clock_rate )\r
+ {\r
+ DWORD buf[6];\r
+ DWORD returned;\r
+ uint64_t now_net, now_tsc;\r
+ DWORD result;\r
+\r
+ memset( buf, 0xFF, sizeof( buf ));\r
+ if(( result = readOID( OID_INTEL_GET_SYSTIM, buf, sizeof(buf), &returned )) != ERROR_SUCCESS ) return false;\r
+\r
+ now_net = (((uint64_t)buf[1]) << 32) | buf[0];\r
+ now_net = scaleNativeClockToNanoseconds( now_net );\r
+ *device_time = nanoseconds64ToTimestamp( now_net );\r
+\r
+ now_tsc = (((uint64_t)buf[3]) << 32) | buf[2];\r
+ now_tsc = scaleTSCClockToNanoseconds( now_tsc );\r
+ *system_time = nanoseconds64ToTimestamp( now_tsc );\r
+\r
+ return true;\r
+ }\r
+\r
+ virtual int HWTimestamper_txtimestamp( PortIdentity *identity, uint16_t sequenceId, Timestamp ×tamp, unsigned &clock_value, bool last )\r
+ {\r
+ DWORD buf[8], buf_tmp[8];\r
+ DWORD returned = 0;\r
+ uint64_t tx_r,tx_s;\r
+ DWORD result;\r
+ while(( result = readOID( OID_INTEL_GET_TXSTAMP, buf_tmp, sizeof(buf_tmp), &returned )) == ERROR_SUCCESS ) {\r
+ memcpy( buf, buf_tmp, sizeof( buf ));\r
+ }\r
+ if( result != ERROR_GEN_FAILURE ) return -1;\r
+ if( returned == 0 ) return -72;\r
+ tx_r = (((uint64_t)buf[1]) << 32) | buf[0];\r
+ tx_s = scaleNativeClockToNanoseconds( tx_r );\r
+ tx_s += ONE_WAY_PHY_DELAY;\r
+ timestamp = nanoseconds64ToTimestamp( tx_s );\r
+ //fprintf( stderr, "@@@SI,%hu,%u\n", sequenceId, buf[3] );\r
+ //fprintf( stderr, "@@TXR,%u,%u,%u,%hu,%llu,%hu,%hu\n", timestamp.seconds_ms, timestamp.seconds_ls,\r
+ // timestamp.nanoseconds, 0, tx_r, sequenceId, buf[3] );\r
+\r
+ return 0;\r
+ }\r
+\r
+ virtual int HWTimestamper_rxtimestamp( PortIdentity *identity, uint16_t sequenceId, Timestamp ×tamp, unsigned &clock_value, bool last )\r
+ {\r
+ DWORD buf[4], buf_tmp[4];\r
+ DWORD returned;\r
+ uint64_t rx_r,rx_s;\r
+ DWORD result;\r
+ uint16_t packet_sequence_id;\r
+ while(( result = readOID( OID_INTEL_GET_RXSTAMP, buf_tmp, sizeof(buf_tmp), &returned )) == ERROR_SUCCESS ) {\r
+ memcpy( buf, buf_tmp, sizeof( buf ));\r
+ }\r
+ if( result != ERROR_GEN_FAILURE ) return -1;\r
+ if( returned == 0 ) return -72;\r
+ packet_sequence_id = *((uint32_t *) buf+3) >> 16;\r
+ if( PLAT_ntohs( packet_sequence_id ) != sequenceId ) return -72;\r
+ rx_r = (((uint64_t)buf[1]) << 32) | buf[0];\r
+ rx_s = scaleNativeClockToNanoseconds( rx_r );\r
+ rx_s -= ONE_WAY_PHY_DELAY;\r
+ timestamp = nanoseconds64ToTimestamp( rx_s );\r
+ //fprintf( stderr, "@@RXR,%u,%u,%u,%hu,%llu\n", timestamp.seconds_ms, timestamp.seconds_ls,\r
+ // timestamp.nanoseconds, PLAT_ntohs(packet_sequence_id), rx_r );\r
+\r
+ return 0;\r
+ }\r
+};\r
+\r
+\r
+\r
+class WindowsNamedPipeIPC : public OS_IPC {\r
+private:\r
+ HANDLE pipe;\r
+public:\r
+ WindowsNamedPipeIPC() { };\r
+ ~WindowsNamedPipeIPC() {\r
+ CloseHandle( pipe );\r
+ }\r
+ virtual bool init() {\r
+ char pipename[64];\r
+ PLAT_strncpy( pipename, PIPE_PREFIX, 63 );\r
+ PLAT_strncpy( pipename+strlen(pipename), P802_1AS_PIPENAME, 63-strlen(pipename) );\r
+ pipe = CreateNamedPipe( pipename, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES,\r
+ OUTSTANDING_MESSAGES*sizeof( WindowsNPipeMessage ), 0, 0, NULL );\r
+ if( pipe == INVALID_HANDLE_VALUE ) return false;\r
+ return true;\r
+ }\r
+ virtual bool update( int64_t ml_phoffset, int64_t ls_phoffset, int32_t ml_freqoffset, int32_t ls_freq_offset, uint64_t local_time ) {\r
+ WindowsNPipeMessage msg( ml_phoffset, ls_phoffset, ml_freqoffset, ls_freq_offset, local_time );\r
+ if( !msg.write( pipe )) {\r
+ CloseHandle(pipe);\r
+ return init();\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+#endif\r
--- /dev/null
+linux_igb_avb/daemons/gptp/windows/daemon_cl/x64
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 2012\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "daemon_cl", "daemon_cl\daemon_cl.vcxproj", "{590D3055-A068-4B31-B4F9-B2ACC5F93663}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_pipe_test", "named_pipe_test\named_pipe_test.vcxproj", "{303FACBB-2A44-4511-A855-2B5B2C0E3A89}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Release|x64 = Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {590D3055-A068-4B31-B4F9-B2ACC5F93663}.Release|x64.ActiveCfg = Release|x64\r
+ {590D3055-A068-4B31-B4F9-B2ACC5F93663}.Release|x64.Build.0 = Release|x64\r
+ {303FACBB-2A44-4511-A855-2B5B2C0E3A89}.Release|x64.ActiveCfg = Release|x64\r
+ {303FACBB-2A44-4511-A855-2B5B2C0E3A89}.Release|x64.Build.0 = Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+/ReadMe.txt/1.1/Fri Sep 21 20:20:49 2012//
+/named_pipe_test.cpp/1.1/Fri Sep 21 20:21:47 2012//
+/named_pipe_test.vcxproj/1.1/Fri Sep 21 16:52:35 2012//
+/named_pipe_test.vcxproj.filters/1.1/Fri Sep 7 18:39:51 2012//
+/named_pipe_test.vcxproj.user/1.1/Fri Sep 7 18:39:51 2012//
+/stdafx.cpp/1.1/Fri Sep 7 18:39:51 2012//
+/stdafx.h/1.1/Fri Sep 7 18:39:51 2012//
+/targetver.h/1.1/Fri Sep 7 18:39:51 2012//
+D
--- /dev/null
+linux_igb_avb/daemons/gptp/windows/named_pipe_test
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+========================================================================\r
+(C) Copyright 2009-2012 Intel Corporation, All Rights Reserved\r
+Author: Christopher Hall <christopher.s.hall@intel.com>\r
+========================================================================\r
+\r
+========================================================================\r
+ CONSOLE APPLICATION : named_pipe_test Project Overview\r
+========================================================================\r
+\r
+An example application to interface with gptp/daemon_cl. See ipcdef.hpp for message details.\r
--- /dev/null
+/******************************************************************************\r
+\r
+ Copyright (c) 2009-2012, Intel Corporation \r
+ All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without \r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ 1. Redistributions of source code must retain the above copyright notice, \r
+ this list of conditions and the following disclaimer.\r
+ \r
+ 2. Redistributions in binary form must reproduce the above copyright \r
+ notice, this list of conditions and the following disclaimer in the \r
+ documentation and/or other materials provided with the distribution.\r
+ \r
+ 3. Neither the name of the Intel Corporation nor the names of its \r
+ contributors may be used to endorse or promote products derived from \r
+ this software without specific prior written permission.\r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+\r
+******************************************************************************/\r
+\r
+#include "stdafx.h"\r
+#include "ipcdef.hpp"\r
+#include "tsc.hpp"\r
+\r
+#define PIPE_PREFIX "\\\\.\\pipe\\"\r
+#define P802_1AS_PIPENAME "gptp-update"\r
+#define OUTSTANDING_MESSAGES 10\r
+\r
+static bool exit_flag;\r
+\r
+BOOL WINAPI ctrl_handler( DWORD ctrl_type ) {\r
+ bool ret;\r
+ if( ctrl_type == CTRL_C_EVENT ) {\r
+ exit_flag = true;\r
+ ret = true;\r
+ } else {\r
+ ret = false;\r
+ }\r
+ return ret;\r
+}\r
+\r
+uint64_t scaleTSCClockToNanoseconds( uint64_t tsc_value, uint64_t tsc_frequency ) {\r
+ long double scaled_output = ((long double)tsc_frequency)/1000000000;\r
+ scaled_output = ((long double) tsc_value)/scaled_output;\r
+ return (uint64_t) scaled_output;\r
+}\r
+int _tmain(int argc, _TCHAR* argv[])\r
+{\r
+ char pipename[64];\r
+ strcpy_s( pipename, 64, PIPE_PREFIX );\r
+ strcat_s( pipename, 64-strlen(pipename), P802_1AS_PIPENAME );\r
+ WindowsNPipeMessage msg;\r
+ HANDLE pipe;\r
+ uint64_t tsc_frequency = getTSCFrequency( 1000 );\r
+\r
+ pipe = CreateFile( pipename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if( pipe == INVALID_HANDLE_VALUE ) {\r
+ printf( "Failed to open gptp handle, %d\n", GetLastError() );\r
+ }\r
+\r
+ \r
+ // Wait for Ctrl-C\r
+ if( !SetConsoleCtrlHandler( ctrl_handler, true )) {\r
+ printf( "Unable to register Ctrl-C handler\n" );\r
+ return -1;\r
+ }\r
+\r
+ printf( "TSC Frequency: %llu\n", tsc_frequency );\r
+ while( msg.read( pipe ) == true && !exit_flag ) {\r
+ uint64_t now_tscns, now_8021as;\r
+ uint64_t update_tscns, update_8021as;\r
+ unsigned delta_tscns, delta_8021as;\r
+ long double ml_ratio, ls_ratio;\r
+#if 0\r
+ printf( "Master-Local Offset = %lld\n", msg.getMasterLocalOffset() );\r
+ printf( "Master-Local Frequency Offset = %d\n", msg.getMasterLocalFreqOffset() );\r
+ printf( "Local-System Offset = %lld\n", msg.getLocalSystemOffset() );\r
+ printf( "Local-System Frequency Offset = %d\n", msg.getLocalSystemFreqOffset() );\r
+ printf( "Local Time = %llu\n", msg.getLocalTime() );\r
+#endif\r
+ now_tscns = scaleTSCClockToNanoseconds( PLAT_rdtsc(), tsc_frequency );\r
+ update_tscns = msg.getLocalTime() + msg.getLocalSystemOffset();\r
+ update_8021as = msg.getLocalTime() - msg.getMasterLocalOffset();\r
+ delta_tscns = (unsigned)(now_tscns - update_tscns);\r
+ ml_ratio = -1*(((long double)msg.getMasterLocalFreqOffset())/1000000000000)+1;\r
+ ls_ratio = -1*(((long double)msg.getLocalSystemFreqOffset())/1000000000000)+1;\r
+ delta_8021as = (unsigned)(ml_ratio*ls_ratio*delta_tscns);\r
+ now_8021as = update_8021as + delta_8021as;\r
+ printf( "Time now in terms of TSC scaled to nanoseconds time: %llu\n", now_tscns );\r
+ printf( "Last update time in terms of 802.1AS time: %llu\n", update_8021as );\r
+ printf( "TSC delta scaled to ns: %u\n", delta_tscns );\r
+ printf( "8021as delta scaled: %u\n", delta_8021as );\r
+ printf( "Time now in terms of 802.1AS time: %llu\n", now_8021as );\r
+ }\r
+\r
+ printf( "Closing pipe\n" );\r
+ CloseHandle( pipe );\r
+\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup Label="ProjectConfigurations">\r
+ <ProjectConfiguration Include="Debug|Win32">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|x64">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|Win32">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|x64">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ </ItemGroup>\r
+ <PropertyGroup Label="Globals">\r
+ <ProjectGuid>{303FACBB-2A44-4511-A855-2B5B2C0E3A89}</ProjectGuid>\r
+ <Keyword>Win32Proj</Keyword>\r
+ <RootNamespace>named_pipe_test</RootNamespace>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <CharacterSet>Unicode</CharacterSet>\r
+ <PlatformToolset>v110</PlatformToolset>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+ <ImportGroup Label="ExtensionSettings">\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <PropertyGroup Label="UserMacros" />\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <LinkIncremental>true</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <LinkIncremental>false</LinkIncremental>\r
+ </PropertyGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <ClCompile>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <PreprocessorDefinitions>\r
+ </PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\gptp\windows\gptp\daemon_cl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <ClCompile>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <Optimization>Disabled</Optimization>\r
+ <PreprocessorDefinitions>\r
+ </PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\gptp\windows\gptp\daemon_cl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>C:\Users\John\src\gptp\windows\gptp\daemon_cl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <ClCompile>\r
+ <WarningLevel>Level3</WarningLevel>\r
+ <PrecompiledHeader>Use</PrecompiledHeader>\r
+ <Optimization>MaxSpeed</Optimization>\r
+ <FunctionLevelLinking>true</FunctionLevelLinking>\r
+ <IntrinsicFunctions>true</IntrinsicFunctions>\r
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE</PreprocessorDefinitions>\r
+ <AdditionalIncludeDirectories>..\daemon_cl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ </ClCompile>\r
+ <Link>\r
+ <SubSystem>Console</SubSystem>\r
+ <GenerateDebugInformation>true</GenerateDebugInformation>\r
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
+ <OptimizeReferences>true</OptimizeReferences>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemGroup>\r
+ <None Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="stdafx.h" />\r
+ <ClInclude Include="targetver.h" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="named_pipe_test.cpp" />\r
+ <ClCompile Include="stdafx.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>\r
+ </ClCompile>\r
+ </ItemGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <ImportGroup Label="ExtensionTargets">\r
+ </ImportGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup>\r
+ <Filter Include="Source Files">\r
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r
+ </Filter>\r
+ <Filter Include="Header Files">\r
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\r
+ </Filter>\r
+ <Filter Include="Resource Files">\r
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r
+ </Filter>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="stdafx.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="targetver.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="stdafx.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="named_pipe_test.cpp">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ </ItemGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+</Project>
\ No newline at end of file
--- /dev/null
+// stdafx.cpp : source file that includes just the standard includes\r
+// named_pipe_test.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
--- /dev/null
+// stdafx.h : include file for standard system include files,\r
+// or project specific include files that are used frequently, but\r
+// are changed infrequently\r
+//\r
+\r
+#pragma once\r
+\r
+#include "targetver.h"\r
+\r
+#include <stdio.h>\r
+#include <tchar.h>\r
+#include <Windows.h>\r
+\r
+\r
+\r
+// TODO: reference additional headers your program requires here\r
--- /dev/null
+#pragma once\r
+\r
+// Including SDKDDKVer.h defines the highest available Windows platform.\r
+\r
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and\r
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.\r
+\r
+#include <SDKDDKVer.h>\r
--- /dev/null
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\cl.command.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\CL.read.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\CL.write.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\link.command.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\link.read.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\link.write.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\mt.command.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\mt.read.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\mt.write.1.tlog\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\named_pipe_test.exe.intermediate.manifest\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\named_pipe_test.obj\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\named_pipe_test.pch\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\x64\Release\stdafx.obj\r
+\\DATAGROVEJF\STG\USERS\CHRISH\GPTP_BZR\MAIN\WINDOWS\GPTP\NAMED_PIPE_TEST\X64\RELEASE\VC100.PDB\r
+\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\x64\Release\named_pipe_test.exe\r
+\\DATAGROVEJF\STG\USERS\CHRISH\GPTP_BZR\MAIN\WINDOWS\GPTP\X64\RELEASE\NAMED_PIPE_TEST.PDB\r
--- /dev/null
+Build started 9/5/2012 6:17:28 PM.\r
+ 1>Project "\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\named_pipe_test.vcxproj" on node 2 (clean target(s)).\r
+ 1>_PrepareForClean:\r
+ Deleting file "x64\Release\named_pipe_test.lastbuildstate".\r
+ 1>Done Building Project "\\datagrovejf\STG\USERS\Chrish\gptp_bzr\main\windows\gptp\named_pipe_test\named_pipe_test.vcxproj" (clean target(s)).\r
+\r
+Build succeeded.\r
+\r
+Time Elapsed 00:00:00.30\r
--- /dev/null
+linux_igb_avb/daemons/gptp/windows/x64
--- /dev/null
+:pserver:ekmann@azusa.jf.intel.com:/home/cvsroot/ladsw
--- /dev/null
+ daemon_cl\r
+\r
+ Timestamp is 5047f856 (Wed Sep 05 18:11:50 2012)\r
+\r
+ Preferred load address is 0000000140000000\r
+\r
+ Start Length Name Class\r
+ 0001:00000000 00009f5eH .text CODE\r
+ 0001:00009f60 0000040cH .text$x CODE\r
+ 0001:0000a370 000000b2H .text$yc CODE\r
+ 0001:0000a430 0000005fH .text$yd CODE\r
+ 0002:00000000 00000328H .idata$5 DATA\r
+ 0002:00000328 00000008H .CRT$XCA DATA\r
+ 0002:00000330 00000008H .CRT$XCAA DATA\r
+ 0002:00000338 00000018H .CRT$XCU DATA\r
+ 0002:00000350 00000008H .CRT$XCZ DATA\r
+ 0002:00000358 00000008H .CRT$XIA DATA\r
+ 0002:00000360 00000008H .CRT$XIAA DATA\r
+ 0002:00000368 00000008H .CRT$XIY DATA\r
+ 0002:00000370 00000008H .CRT$XIZ DATA\r
+ 0002:00000380 00001020H .rdata DATA\r
+ 0002:000013a0 0000006cH .rdata$debug DATA\r
+ 0002:00001410 0000113cH .rdata$r DATA\r
+ 0002:00002550 00000008H .rtc$IAA DATA\r
+ 0002:00002558 00000008H .rtc$IZZ DATA\r
+ 0002:00002560 00000008H .rtc$TAA DATA\r
+ 0002:00002568 00000008H .rtc$TZZ DATA\r
+ 0002:00002570 000011e0H .xdata DATA\r
+ 0002:00003750 00000084H .xdata$x DATA\r
+ 0002:000037d4 00000078H .idata$2 DATA\r
+ 0002:0000384c 00000014H .idata$3 DATA\r
+ 0002:00003860 00000328H .idata$4 DATA\r
+ 0002:00003b88 000006daH .idata$6 DATA\r
+ 0002:00004262 00000000H .edata DATA\r
+ 0003:00000000 00000714H .data DATA\r
+ 0003:00000720 00000600H .bss DATA\r
+ 0004:00000000 000009e4H .pdata DATA\r
+\r
+ Address Publics by Value Rva+Base Lib:Object\r
+\r
+ 0000:00000000 ___safe_se_handler_count 0000000000000000 <absolute>\r
+ 0000:00000000 ___safe_se_handler_table 0000000000000000 <absolute>\r
+ 0000:00000000 __ImageBase 0000000140000000 <linker-defined>\r
+ 0001:00000000 ??1bad_alloc@std@@UEAA@XZ 0000000140001000 f i avbts_osnet.obj\r
+ 0001:00000020 ??_Gbad_alloc@std@@UEAAPEAXI@Z 0000000140001020 f i avbts_osnet.obj\r
+ 0001:00000020 ??_Ebad_alloc@std@@UEAAPEAXI@Z 0000000140001020 f i CIL library: CIL module\r
+ 0001:00000060 ??0?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA@AEBU?$less@Vfactory_name_t@@@1@AEBV?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@1@@Z 0000000140001060 f i avbts_osnet.obj\r
+ 0001:00000100 ??1?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA@XZ 0000000140001100 f i avbts_osnet.obj\r
+ 0001:00000110 ?erase@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@0@Z 0000000140001110 f i avbts_osnet.obj\r
+ 0001:000001d0 ?erase@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@@Z 00000001400011d0 f i avbts_osnet.obj\r
+ 0001:00000520 ?clear@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAAXXZ 0000000140001520 f i avbts_osnet.obj\r
+ 0001:000005a0 ?_Erase@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@@Z 00000001400015a0 f i avbts_osnet.obj\r
+ 0001:00000600 ?_Lrotate@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@@Z 0000000140001600 f i avbts_osnet.obj\r
+ 0001:00000660 ?_Rrotate@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@@Z 0000000140001660 f i avbts_osnet.obj\r
+ 0001:000006c0 ??0bad_alloc@std@@QEAA@AEBV01@@Z 00000001400016c0 f i avbts_osnet.obj\r
+ 0001:000006f0 ?timerq_handler@@YAXPEAX@Z 00000001400016f0 f ieee1588clock.obj\r
+ 0001:00000700 ?addEventTimer@IEEE1588Clock@@QEAAXPEAVIEEE1588Port@@W4Event@@_K@Z 0000000140001700 f ieee1588clock.obj\r
+ 0001:000007a0 ?isBetterThan@IEEE1588Clock@@QEAA_NPEAVPTPMessageAnnounce@@@Z 00000001400017a0 f ieee1588clock.obj\r
+ 0001:00000870 ??_EInterfaceLabel@@UEAAPEAXI@Z 0000000140001870 f i CIL library: CIL module\r
+ 0001:00000870 ??_GLinkLayerAddress@@UEAAPEAXI@Z 0000000140001870 f i ieee1588port.obj\r
+ 0001:00000870 ??_ELinkLayerAddress@@UEAAPEAXI@Z 0000000140001870 f i CIL library: CIL module\r
+ 0001:00000870 ??_GInterfaceLabel@@UEAAPEAXI@Z 0000000140001870 f i ieee1588port.obj\r
+ 0001:000008a0 ?pow@@YANNH@Z 00000001400018a0 f i ieee1588port.obj\r
+ 0001:000008e0 ??1LinkLayerAddress@@UEAA@XZ 00000001400018e0 f i ieee1588port.obj\r
+ 0001:000008f0 ?openPortWrapper@@YA?AW4OSThreadExitCode@@PEAX@Z 00000001400018f0 f ieee1588port.obj\r
+ 0001:00000910 ??1?$map@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@@std@@QEAA@XZ 0000000140001910 f i ieee1588port.obj\r
+ 0001:00000950 ??0IEEE1588Port@@QEAA@PEAVIEEE1588Clock@@G_NPEAVHWTimestamper@@1HPEAVInterfaceLabel@@PEAVOSConditionFactory@@PEAVOSThreadFactory@@PEAVOSTimerFactory@@PEAVOSLockFactory@@@Z 0000000140001950 f ieee1588port.obj\r
+ 0001:00000b40 ?init_port@IEEE1588Port@@QEAA_NXZ 0000000140001b40 f ieee1588port.obj\r
+ 0001:00000cc0 ?openPort@IEEE1588Port@@QEAAPEAXXZ 0000000140001cc0 f ieee1588port.obj\r
+ 0001:00000e20 ?processEvent@IEEE1588Port@@QEAAXW4Event@@@Z 0000000140001e20 f ieee1588port.obj\r
+ 0001:00001cc0 ?calculateERBest@IEEE1588Port@@QEAAPEAVPTPMessageAnnounce@@XZ 0000000140002cc0 f ieee1588port.obj\r
+ 0001:00001d90 ?recommendState@IEEE1588Port@@QEAAXW4PortState@@_N@Z 0000000140002d90 f ieee1588port.obj\r
+ 0001:00001fa0 ?calcMasterLocalClockRateDifference@IEEE1588Port@@QEAAH_JVTimestamp@@@Z 0000000140002fa0 f ieee1588port.obj\r
+ 0001:000020e0 ?calcLocalSystemClockRateDifference@IEEE1588Port@@QEAAH_JVTimestamp@@@Z 00000001400030e0 f ieee1588port.obj\r
+ 0001:000021b0 ??A?$map@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@@std@@QEAAAEAPEAVOSNetworkInterfaceFactory@@AEBVfactory_name_t@@@Z 00000001400031b0 f i ieee1588port.obj\r
+ 0001:000022b0 ??A?$map@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@@std@@QEAAAEAVLinkLayerAddress@@AEBVPortIdentity@@@Z 00000001400032b0 f i ieee1588port.obj\r
+ 0001:000023a0 ??1?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@QEAA@XZ 00000001400033a0 f i ieee1588port.obj\r
+ 0001:000023b0 ??0?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA@AEBU?$less@VPortIdentity@@@1@AEBV?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@1@@Z 00000001400033b0 f i ieee1588port.obj\r
+ 0001:00002440 ??1?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA@XZ 0000000140003440 f i ieee1588port.obj\r
+ 0001:00002440 ??1?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA@XZ 0000000140003440 f i daemon_cl.obj\r
+ 0001:00002450 ??R?$less@VPortIdentity@@@std@@QEBA_NAEBVPortIdentity@@0@Z 0000000140003450 f i ieee1588port.obj\r
+ 0001:000024a0 ?erase@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@0@Z 00000001400034a0 f i ieee1588port.obj\r
+ 0001:00002580 ?_Lbound@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@IEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@AEBVPortIdentity@@@Z 0000000140003580 f i ieee1588port.obj\r
+ 0001:00002610 ?erase@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@@Z 0000000140003610 f i ieee1588port.obj\r
+ 0001:00002980 ?clear@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAAXXZ 0000000140003980 f i ieee1588port.obj\r
+ 0001:00002a10 ?_Erase@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@@Z 0000000140003a10 f i ieee1588port.obj\r
+ 0001:00002a80 ?_Lrotate@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@@Z 0000000140003a80 f i ieee1588port.obj\r
+ 0001:00002ae0 ?_Rrotate@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@@Z 0000000140003ae0 f i ieee1588port.obj\r
+ 0001:00002b40 ?_Insert@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@@Z 0000000140003b40 f i ieee1588port.obj\r
+ 0001:00002de0 ?_Insert@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@@Z 0000000140003de0 f i ieee1588port.obj\r
+ 0001:00003050 ?_Linsert@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAA?AU?$pair@V?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@std@@_N@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@_N@Z 0000000140004050 f i ieee1588port.obj\r
+ 0001:000031b0 ?_Insert@?$_Tree@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@IEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@@2@_NPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@1@Z 00000001400041b0 f i ieee1588port.obj\r
+ 0001:00003460 ?_Linsert@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAA?AU?$pair@V?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@std@@_N@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@_N@Z 0000000140004460 f i ieee1588port.obj\r
+ 0001:00003610 ?_Insert@?$_Tree@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@IEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@@2@_NPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@1@Z 0000000140004610 f i ieee1588port.obj\r
+ 0001:000038c0 ??$_Buynode@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@1@@Z 00000001400048c0 f i ieee1588port.obj\r
+ 0001:00003930 ??$_Buynode@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@1@@Z 0000000140004930 f i ieee1588port.obj\r
+ 0001:00003990 ?_Buynode@?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@2@XZ 0000000140004990 f i ieee1588port.obj\r
+ 0001:00003a10 ?_Buynode@?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@2@XZ 0000000140004a10 f i ieee1588port.obj\r
+ 0001:00003a90 ??_EPTPMessagePathDelayReq@@UEAAPEAXI@Z 0000000140004a90 f i CIL library: CIL module\r
+ 0001:00003a90 ??_GPTPMessageCommon@@UEAAPEAXI@Z 0000000140004a90 f i ptp_message.obj\r
+ 0001:00003a90 ??_GPTPMessageSync@@UEAAPEAXI@Z 0000000140004a90 f i ptp_message.obj\r
+ 0001:00003a90 ??_EPTPMessageSync@@UEAAPEAXI@Z 0000000140004a90 f i CIL library: CIL module\r
+ 0001:00003a90 ??_EPTPMessageFollowUp@@UEAAPEAXI@Z 0000000140004a90 f i CIL library: CIL module\r
+ 0001:00003a90 ??_GPTPMessagePathDelayReq@@UEAAPEAXI@Z 0000000140004a90 f i ptp_message.obj\r
+ 0001:00003a90 ??_GPTPMessageFollowUp@@UEAAPEAXI@Z 0000000140004a90 f i ptp_message.obj\r
+ 0001:00003a90 ??_EPTPMessageCommon@@UEAAPEAXI@Z 0000000140004a90 f i CIL library: CIL module\r
+ 0001:00003ad0 ??_GPTPMessagePathDelayResp@@UEAAPEAXI@Z 0000000140004ad0 f i ptp_message.obj\r
+ 0001:00003ad0 ??_EPTPMessagePathDelayResp@@UEAAPEAXI@Z 0000000140004ad0 f i CIL library: CIL module\r
+ 0001:00003b30 ??_GPTPMessagePathDelayRespFollowUp@@UEAAPEAXI@Z 0000000140004b30 f i ptp_message.obj\r
+ 0001:00003b30 ??_EPTPMessagePathDelayRespFollowUp@@UEAAPEAXI@Z 0000000140004b30 f i CIL library: CIL module\r
+ 0001:00003b90 ??0PortIdentity@@QEAA@PEAEPEAG@Z 0000000140004b90 f i ptp_message.obj\r
+ 0001:00003bd0 ?addQualifiedAnnounce@IEEE1588Port@@QEAAXPEAVPTPMessageAnnounce@@@Z 0000000140004bd0 f i ptp_message.obj\r
+ 0001:00003c50 ?buildPTPMessage@@YAPEAVPTPMessageCommon@@PEADHPEAVLinkLayerAddress@@PEAVIEEE1588Port@@@Z 0000000140004c50 f ptp_message.obj\r
+ 0001:00004370 ?processMessage@PTPMessageCommon@@UEAAXPEAVIEEE1588Port@@@Z 0000000140005370 f ptp_message.obj\r
+ 0001:00004380 ?buildCommonHeader@PTPMessageCommon@@QEAAXPEAE@Z 0000000140005380 f ptp_message.obj\r
+ 0001:00004460 ??1PTPMessageCommon@@UEAA@XZ 0000000140005460 f ptp_message.obj\r
+ 0001:00004480 ??_EPTPMessageAnnounce@@UEAAPEAXI@Z 0000000140005480 f i CIL library: CIL module\r
+ 0001:00004480 ??_GPTPMessageAnnounce@@UEAAPEAXI@Z 0000000140005480 f i ptp_message.obj\r
+ 0001:000044e0 ?isBetterThan@PTPMessageAnnounce@@QEAA_NPEAV1@@Z 00000001400054e0 f ptp_message.obj\r
+ 0001:000045b0 ??0PTPMessageSync@@QEAA@PEAVIEEE1588Port@@@Z 00000001400055b0 f ptp_message.obj\r
+ 0001:00004660 ?sendPort@PTPMessageSync@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 0000000140005660 f ptp_message.obj\r
+ 0001:000047a0 ??0PTPMessageAnnounce@@QEAA@PEAVIEEE1588Port@@@Z 00000001400057a0 f ptp_message.obj\r
+ 0001:000048e0 ?sendPort@PTPMessageAnnounce@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 00000001400058e0 f ptp_message.obj\r
+ 0001:00004a60 ?processMessage@PTPMessageAnnounce@@UEAAXPEAVIEEE1588Port@@@Z 0000000140005a60 f ptp_message.obj\r
+ 0001:00004b50 ?processMessage@PTPMessageSync@@UEAAXPEAVIEEE1588Port@@@Z 0000000140005b50 f ptp_message.obj\r
+ 0001:00004c60 ??0PTPMessageFollowUp@@QEAA@PEAVIEEE1588Port@@@Z 0000000140005c60 f ptp_message.obj\r
+ 0001:00004d50 ?sendPort@PTPMessageFollowUp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 0000000140005d50 f ptp_message.obj\r
+ 0001:00004ea0 ?processMessage@PTPMessageFollowUp@@UEAAXPEAVIEEE1588Port@@@Z 0000000140005ea0 f ptp_message.obj\r
+ 0001:00005290 ?processMessage@PTPMessagePathDelayReq@@UEAAXPEAVIEEE1588Port@@@Z 0000000140006290 f ptp_message.obj\r
+ 0001:000056b0 ?sendPort@PTPMessagePathDelayReq@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 00000001400066b0 f ptp_message.obj\r
+ 0001:000057b0 ??0PTPMessagePathDelayResp@@QEAA@PEAVIEEE1588Port@@@Z 00000001400067b0 f ptp_message.obj\r
+ 0001:00005840 ?processMessage@PTPMessagePathDelayResp@@UEAAXPEAVIEEE1588Port@@@Z 0000000140006840 f ptp_message.obj\r
+ 0001:00005990 ?sendPort@PTPMessagePathDelayResp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 0000000140006990 f ptp_message.obj\r
+ 0001:00005ae0 ??0PTPMessagePathDelayRespFollowUp@@QEAA@PEAVIEEE1588Port@@@Z 0000000140006ae0 f ptp_message.obj\r
+ 0001:00005b70 ?processMessage@PTPMessagePathDelayRespFollowUp@@UEAAXPEAVIEEE1588Port@@@Z 0000000140006b70 f ptp_message.obj\r
+ 0001:00006070 ?sendPort@PTPMessagePathDelayRespFollowUp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z 0000000140007070 f ptp_message.obj\r
+ 0001:000061c0 ?_Buynode@?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@2@PEAU342@0AEBQEAUWindowsTimerQueueHandlerArg@@@Z 00000001400071c0 f i daemon_cl.obj\r
+ 0001:000061c0 ?_Buynode@?$_List_val@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@2@PEAU342@0AEBQEAVPTPMessageAnnounce@@@Z 00000001400071c0 f i ptp_message.obj\r
+ 0001:00006260 ?HWTimestamper_init@HWTimestamper@@UEAA_NPEAVInterfaceLabel@@@Z 0000000140007260 f i daemon_cl.obj\r
+ 0001:00006270 ??3@YAXPEAX0@Z 0000000140007270 f i ieee1588port.obj\r
+ 0001:00006270 ?HWTimestamper_final@HWTimestamper@@UEAAXXZ 0000000140007270 f i daemon_cl.obj\r
+ 0001:00006280 ?HWTimestamper_adjclockrate@HWTimestamper@@UEAA_NHIVTimestamp@@_J_N@Z 0000000140007280 f i daemon_cl.obj\r
+ 0001:00006280 ?HWTimestamper_adjclockrate2@HWTimestamper@@UEAA_NH@Z 0000000140007280 f i daemon_cl.obj\r
+ 0001:00006280 ?HWTimestamper_get_extclk_offset@HWTimestamper@@UEAA_NPEAVTimestamp@@PEA_JPEAH@Z 0000000140007280 f i daemon_cl.obj\r
+ 0001:00006290 ?HWTimestamper_get_extderror@HWTimestamper@@UEAAXPEAD@Z 0000000140007290 f i daemon_cl.obj\r
+ 0001:000062a0 ??_GHWTimestamper@@UEAAPEAXI@Z 00000001400072a0 f i daemon_cl.obj\r
+ 0001:000062a0 ??_GWindowsTimestamper@@UEAAPEAXI@Z 00000001400072a0 f i daemon_cl.obj\r
+ 0001:000062a0 ??_EHWTimestamper@@UEAAPEAXI@Z 00000001400072a0 f i CIL library: CIL module\r
+ 0001:000062a0 ??_EWindowsTimestamper@@UEAAPEAXI@Z 00000001400072a0 f i CIL library: CIL module\r
+ 0001:000062d0 ?send@WindowsPCAPNetworkInterface@@UEAA?AW4net_result@@PEAVLinkLayerAddress@@PEAE_K_N@Z 00000001400072d0 f i daemon_cl.obj\r
+ 0001:000063a0 ?recv@WindowsPCAPNetworkInterface@@UEAA?AW4net_result@@PEAVLinkLayerAddress@@PEAEAEA_K@Z 00000001400073a0 f i daemon_cl.obj\r
+ 0001:000064d0 ?getLinkLayerAddress@WindowsPCAPNetworkInterface@@UEAAXPEAVLinkLayerAddress@@@Z 00000001400074d0 f i daemon_cl.obj\r
+ 0001:00006500 ?getPayloadOffset@WindowsPCAPNetworkInterface@@UEAAIXZ 0000000140007500 f i daemon_cl.obj\r
+ 0001:00006510 ??_GWindowsPCAPNetworkInterface@@UEAAPEAXI@Z 0000000140007510 f i daemon_cl.obj\r
+ 0001:00006510 ??_EWindowsPCAPNetworkInterface@@UEAAPEAXI@Z 0000000140007510 f i CIL library: CIL module\r
+ 0001:00006590 ?createInterface@WindowsPCAPNetworkInterfaceFactory@@UEAA_NPEAPEAVOSNetworkInterface@@PEAVInterfaceLabel@@PEAVHWTimestamper@@@Z 0000000140007590 f i daemon_cl.obj\r
+ 0001:000066f0 ?lock@WindowsLock@@MEAA?AW4OSLockResult@@XZ 00000001400076f0 f i daemon_cl.obj\r
+ 0001:000067a0 ?trylock@WindowsLock@@MEAA?AW4OSLockResult@@XZ 00000001400077a0 f i daemon_cl.obj\r
+ 0001:00006850 ?unlock@WindowsLock@@MEAA?AW4OSLockResult@@XZ 0000000140007850 f i daemon_cl.obj\r
+ 0001:00006870 ?createLock@WindowsLockFactory@@UEAAPEAVOSLock@@W4OSLockType@@@Z 0000000140007870 f i daemon_cl.obj\r
+ 0001:000068f0 ?wait_prelock@WindowsCondition@@UEAA_NXZ 00000001400078f0 f i daemon_cl.obj\r
+ 0001:00006910 ?wait@WindowsCondition@@UEAA_NXZ 0000000140007910 f i daemon_cl.obj\r
+ 0001:00006960 ?signal@WindowsCondition@@UEAA_NXZ 0000000140007960 f i daemon_cl.obj\r
+ 0001:000069a0 ?createCondition@WindowsConditionFactory@@UEAAPEAVOSCondition@@XZ 00000001400079a0 f i daemon_cl.obj\r
+ 0001:000069f0 ?cleanupRetiredTimers@WindowsTimerQueue@@AEAAXXZ 00000001400079f0 f i daemon_cl.obj\r
+ 0001:00006ac0 ??0WindowsTimerQueue@@IEAA@XZ 0000000140007ac0 f i daemon_cl.obj\r
+ 0001:00006b60 ?addEvent@WindowsTimerQueue@@UEAA_NKHP6AXPEAX@ZPEAUevent_descriptor_t@@_NPEAI@Z 0000000140007b60 f i daemon_cl.obj\r
+ 0001:00006da0 ?cancelEvent@WindowsTimerQueue@@UEAA_NHPEAI@Z 0000000140007da0 f i daemon_cl.obj\r
+ 0001:00006f40 ??1?$map@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@@std@@QEAA@XZ 0000000140007f40 f i daemon_cl.obj\r
+ 0001:00006f80 ?WindowsTimerQueueHandler@@YAXPEAXE@Z 0000000140007f80 f daemon_cl.obj\r
+ 0001:00007090 ?createOSTimerQueue@WindowsTimerQueueFactory@@UEAAPEAVOSTimerQueue@@XZ 0000000140008090 f i daemon_cl.obj\r
+ 0001:000070d0 ?sleep@WindowsTimer@@UEAAKK@Z 00000001400080d0 f i daemon_cl.obj\r
+ 0001:00007100 ?createTimer@WindowsTimerFactory@@UEAAPEAVOSTimer@@XZ 0000000140008100 f i daemon_cl.obj\r
+ 0001:00007130 ?OSThreadCallback@@YAKPEAX@Z 0000000140008130 f daemon_cl.obj\r
+ 0001:00007150 ?start@WindowsThread@@UEAA_NP6A?AW4OSThreadExitCode@@PEAX@Z0@Z 0000000140008150 f i daemon_cl.obj\r
+ 0001:000071e0 ?join@WindowsThread@@UEAA_NAEAW4OSThreadExitCode@@@Z 00000001400081e0 f i daemon_cl.obj\r
+ 0001:00007230 ?createThread@WindowsThreadFactory@@UEAAPEAVOSThread@@XZ 0000000140008230 f i daemon_cl.obj\r
+ 0001:00007260 ?HWTimestamper_init@WindowsTimestamper@@UEAA_NPEAVInterfaceLabel@@@Z 0000000140008260 f i daemon_cl.obj\r
+ 0001:00007550 ?HWTimestamper_gettime@WindowsTimestamper@@UEAA_NPEAVTimestamp@@0PEAI1@Z 0000000140008550 f i daemon_cl.obj\r
+ 0001:00007730 ?HWTimestamper_txtimestamp@WindowsTimestamper@@UEAAHPEAVPortIdentity@@GAEAVTimestamp@@AEAI_N@Z 0000000140008730 f i daemon_cl.obj\r
+ 0001:000078d0 ?HWTimestamper_rxtimestamp@WindowsTimestamper@@UEAAHPEAVPortIdentity@@GAEAVTimestamp@@AEAI_N@Z 00000001400088d0 f i daemon_cl.obj\r
+ 0001:00007a60 ?init@WindowsNamedPipeIPC@@UEAA_NXZ 0000000140008a60 f i daemon_cl.obj\r
+ 0001:00007b40 ?update@WindowsNamedPipeIPC@@UEAA_N_J0HH_K@Z 0000000140008b40 f i daemon_cl.obj\r
+ 0001:00007bd0 ?ctrl_handler@@YAHK@Z 0000000140008bd0 f daemon_cl.obj\r
+ 0001:00007bf0 main 0000000140008bf0 f daemon_cl.obj\r
+ 0001:00008020 ??A?$map@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@@std@@QEAAAEAUTimerQueue_t@@AEBH@Z 0000000140009020 f i daemon_cl.obj\r
+ 0001:000081e0 ??1TimerQueue_t@@QEAA@XZ 00000001400091e0 f i daemon_cl.obj\r
+ 0001:000081e0 ??1?$list@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@std@@QEAA@XZ 00000001400091e0 f i ieee1588port.obj\r
+ 0001:00008240 ??1?$pair@$$CBHUTimerQueue_t@@@std@@QEAA@XZ 0000000140009240 f i daemon_cl.obj\r
+ 0001:00008240 ??$_Dest_val@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@std@@U?$pair@$$CBHUTimerQueue_t@@@2@@std@@YAXAEAV?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@0@PEAU?$pair@$$CBHUTimerQueue_t@@@0@@Z 0000000140009240 f i daemon_cl.obj\r
+ 0001:000082a0 ?_Tidy@?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAXXZ 00000001400092a0 f i daemon_cl.obj\r
+ 0001:000082f0 ??1?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAA@XZ 00000001400092f0 f i daemon_cl.obj\r
+ 0001:00008300 ??0?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA@AEBU?$less@H@1@AEBV?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@1@@Z 0000000140009300 f i daemon_cl.obj\r
+ 0001:00008390 ?erase@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@0@Z 0000000140009390 f i daemon_cl.obj\r
+ 0001:00008490 ??0?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAA@AEBV01@@Z 0000000140009490 f i daemon_cl.obj\r
+ 0001:00008540 ?erase@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@@Z 0000000140009540 f i daemon_cl.obj\r
+ 0001:000088d0 ?_Erase@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@@Z 00000001400098d0 f i daemon_cl.obj\r
+ 0001:00008970 ?_Lrotate@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@@Z 0000000140009970 f i daemon_cl.obj\r
+ 0001:000089d0 ?_Rrotate@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@IEAAXPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@@Z 00000001400099d0 f i daemon_cl.obj\r
+ 0001:00008a30 ?_Insert@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@V?$_Tree_const_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@@Z 0000000140009a30 f i daemon_cl.obj\r
+ 0001:00008c40 ?_Linsert@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAA?AU?$pair@V?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@std@@_N@2@PEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@_N@Z 0000000140009c40 f i daemon_cl.obj\r
+ 0001:00008d70 ?_Insert@?$_Tree@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@IEAA?AV?$_Tree_iterator@V?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@@2@_NPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@1@Z 0000000140009d70 f i daemon_cl.obj\r
+ 0001:00009060 ??$_Buynode@U?$pair@$$CBHUTimerQueue_t@@@std@@@?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@1@$$QEAU?$pair@$$CBHUTimerQueue_t@@@1@@Z 000000014000a060 f i daemon_cl.obj\r
+ 0001:000090e0 ??$_Insert@V?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@std@@@?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAXV?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@1@00Uforward_iterator_tag@1@@Z 000000014000a0e0 f i daemon_cl.obj\r
+ 0001:00009190 ?_Buynode@?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@2@XZ 000000014000a190 f i daemon_cl.obj\r
+ 0001:00009210 ?openInterfaceByAddr@@YA?AW4packet_error_t@@PEAUpacket_handle@@PEAUpacket_addr_t@@H@Z 000000014000a210 f packet.obj\r
+ 0001:000093d0 ?packetBind@@YA?AW4packet_error_t@@PEAUpacket_handle@@G@Z 000000014000a3d0 f packet.obj\r
+ 0001:000094d0 ??_U@YAPEAX_K@Z 000000014000a4d0 f msvcprt:newaop_s.obj\r
+ 0001:000094f0 __security_check_cookie 000000014000a4f0 f MSVCRT:amdsecgs.obj\r
+ 0001:00009510 ?what@exception@std@@UEBAPEBDXZ 000000014000a510 f MSVCRT:MSVCR100.dll\r
+ 0001:00009516 ??0exception@std@@QEAA@AEBV01@@Z 000000014000a516 f MSVCRT:MSVCR100.dll\r
+ 0001:0000951c _onexit 000000014000a51c f MSVCRT:atonexit.obj\r
+ 0001:000095cc atexit 000000014000a5cc f MSVCRT:atonexit.obj\r
+ 0001:000095e4 ??3@YAXPEAX@Z 000000014000a5e4 f MSVCRT:MSVCR100.dll\r
+ 0001:000095ec ??_Etype_info@@UEAAPEAXI@Z 000000014000a5ec f i MSVCRT:ti_inst.obj\r
+ 0001:00009656 ??2@YAPEAX_K@Z 000000014000a656 f MSVCRT:MSVCR100.dll\r
+ 0001:0000965c _purecall 000000014000a65c f MSVCRT:MSVCR100.dll\r
+ 0001:0000991c mainCRTStartup 000000014000a91c f MSVCRT:crtexe.obj\r
+ 0001:00009930 __report_gsfailure 000000014000a930 f MSVCRT:gs_report.obj\r
+ 0001:00009a7a __C_specific_handler 000000014000aa7a f MSVCRT:MSVCR100.dll\r
+ 0001:00009a80 _unlock 000000014000aa80 f MSVCRT:MSVCR100.dll\r
+ 0001:00009a86 __dllonexit 000000014000aa86 f MSVCRT:MSVCR100.dll\r
+ 0001:00009a8c _lock 000000014000aa8c f MSVCRT:MSVCR100.dll\r
+ 0001:00009a94 ?__ArrayUnwind@@YAXPEAX_KHP6AX0@Z@Z 000000014000aa94 f MSVCRT:ehvecdtr.obj\r
+ 0001:00009ae0 ??_M@YAXPEAX_KHP6AX0@Z@Z 000000014000aae0 f MSVCRT:ehvecdtr.obj\r
+ 0001:00009b40 ?__CxxUnhandledExceptionFilter@@YAJPEAU_EXCEPTION_POINTERS@@@Z 000000014000ab40 f MSVCRT:unhandld.obj\r
+ 0001:00009b84 __CxxSetUnhandledExceptionFilter 000000014000ab84 f MSVCRT:unhandld.obj\r
+ 0001:00009b9c _amsg_exit 000000014000ab9c f MSVCRT:MSVCR100.dll\r
+ 0001:00009ba4 _RTC_Initialize 000000014000aba4 f MSVCRT:_initsect_.obj\r
+ 0001:00009bdc _RTC_Terminate 000000014000abdc f MSVCRT:_initsect_.obj\r
+ 0001:00009c14 _XcptFilter 000000014000ac14 f MSVCRT:MSVCR100.dll\r
+ 0001:00009c20 _ValidateImageBase 000000014000ac20 f MSVCRT:pesect.obj\r
+ 0001:00009c50 _FindPESection 000000014000ac50 f MSVCRT:pesect.obj\r
+ 0001:00009ca0 _IsNonwritableInCurrentImage 000000014000aca0 f MSVCRT:pesect.obj\r
+ 0001:00009ce2 _initterm 000000014000ace2 f MSVCRT:MSVCR100.dll\r
+ 0001:00009ce8 _initterm_e 000000014000ace8 f MSVCRT:MSVCR100.dll\r
+ 0001:00009cf0 _matherr 000000014000acf0 f MSVCRT:merr.obj\r
+ 0001:00009cf0 _setargv 000000014000acf0 f MSVCRT:dllargv.obj\r
+ 0001:00009cf4 __security_init_cookie 000000014000acf4 f MSVCRT:gs_support.obj\r
+ 0001:00009da8 __crt_debugger_hook 000000014000ada8 f MSVCRT:MSVCR100.dll\r
+ 0001:00009dae ?terminate@@YAXXZ 000000014000adae f MSVCRT:MSVCR100.dll\r
+ 0001:00009db4 ??1type_info@@UEAA@XZ 000000014000adb4 f MSVCRT:MSVCR100.dll\r
+ 0001:00009db4 ?_type_info_dtor_internal_method@type_info@@QEAAXXZ 000000014000adb4 f MSVCRT:MSVCR100.dll\r
+ 0001:00009dba RtlVirtualUnwind 000000014000adba f kernel32:KERNEL32.dll\r
+ 0001:00009dc0 RtlLookupFunctionEntry 000000014000adc0 f kernel32:KERNEL32.dll\r
+ 0001:00009dc6 memcpy 000000014000adc6 f MSVCRT:MSVCR100.dll\r
+ 0001:00009dcc __GSHandlerCheckCommon 000000014000adcc f MSVCRT:gshandler.obj\r
+ 0001:00009e30 __GSHandlerCheck 000000014000ae30 f MSVCRT:gshandler.obj\r
+ 0001:00009e60 __chkstk 000000014000ae60 f MSVCRT:chkstk.obj\r
+ 0001:00009e60 _alloca_probe 000000014000ae60 MSVCRT:chkstk.obj\r
+ 0001:00009eae memcmp 000000014000aeae f MSVCRT:MSVCR100.dll\r
+ 0001:00009eb4 _CxxThrowException 000000014000aeb4 f MSVCRT:MSVCR100.dll\r
+ 0001:00009eba __CxxFrameHandler3 000000014000aeba f MSVCRT:MSVCR100.dll\r
+ 0001:00009ec0 __RTDynamicCast 000000014000aec0 f MSVCRT:MSVCR100.dll\r
+ 0001:00009ec8 __GSHandlerCheck_EH 000000014000aec8 f MSVCRT:gshandlereh.obj\r
+ 0001:00009f58 memset 000000014000af58 f MSVCRT:MSVCR100.dll\r
+ 0002:00000000 __imp_GetAdaptersAddresses 000000014000c000 Iphlpapi:IPHLPAPI.DLL\r
+ 0002:00000008 \177IPHLPAPI_NULL_THUNK_DATA 000000014000c008 Iphlpapi:IPHLPAPI.DLL\r
+ 0002:00000010 __imp_GetCurrentProcess 000000014000c010 kernel32:KERNEL32.dll\r
+ 0002:00000018 __imp_TerminateProcess 000000014000c018 kernel32:KERNEL32.dll\r
+ 0002:00000020 __imp_DecodePointer 000000014000c020 kernel32:KERNEL32.dll\r
+ 0002:00000028 __imp_GetSystemTimeAsFileTime 000000014000c028 kernel32:KERNEL32.dll\r
+ 0002:00000030 __imp_UnhandledExceptionFilter 000000014000c030 kernel32:KERNEL32.dll\r
+ 0002:00000038 __imp_SetUnhandledExceptionFilter 000000014000c038 kernel32:KERNEL32.dll\r
+ 0002:00000040 __imp_RtlVirtualUnwind 000000014000c040 kernel32:KERNEL32.dll\r
+ 0002:00000048 __imp_GetCurrentProcessId 000000014000c048 kernel32:KERNEL32.dll\r
+ 0002:00000050 __imp_GetTickCount 000000014000c050 kernel32:KERNEL32.dll\r
+ 0002:00000058 __imp_QueryPerformanceCounter 000000014000c058 kernel32:KERNEL32.dll\r
+ 0002:00000060 __imp_RtlCaptureContext 000000014000c060 kernel32:KERNEL32.dll\r
+ 0002:00000068 __imp_RtlLookupFunctionEntry 000000014000c068 kernel32:KERNEL32.dll\r
+ 0002:00000070 __imp_CreateFileA 000000014000c070 kernel32:KERNEL32.dll\r
+ 0002:00000078 __imp_CreateTimerQueue 000000014000c078 kernel32:KERNEL32.dll\r
+ 0002:00000080 __imp_WaitForSingleObject 000000014000c080 kernel32:KERNEL32.dll\r
+ 0002:00000088 __imp_ReleaseSRWLockExclusive 000000014000c088 kernel32:KERNEL32.dll\r
+ 0002:00000090 __imp_WriteFile 000000014000c090 kernel32:KERNEL32.dll\r
+ 0002:00000098 __imp_AcquireSRWLockExclusive 000000014000c098 kernel32:KERNEL32.dll\r
+ 0002:000000a0 __imp_Sleep 000000014000c0a0 kernel32:KERNEL32.dll\r
+ 0002:000000a8 __imp_InitializeConditionVariable 000000014000c0a8 kernel32:KERNEL32.dll\r
+ 0002:000000b0 __imp_GetLastError 000000014000c0b0 kernel32:KERNEL32.dll\r
+ 0002:000000b8 __imp_SleepConditionVariableSRW 000000014000c0b8 kernel32:KERNEL32.dll\r
+ 0002:000000c0 __imp_CreateNamedPipeA 000000014000c0c0 kernel32:KERNEL32.dll\r
+ 0002:000000c8 __imp_CreateTimerQueueTimer 000000014000c0c8 kernel32:KERNEL32.dll\r
+ 0002:000000d0 __imp_InitializeSRWLock 000000014000c0d0 kernel32:KERNEL32.dll\r
+ 0002:000000d8 __imp_SetConsoleCtrlHandler 000000014000c0d8 kernel32:KERNEL32.dll\r
+ 0002:000000e0 __imp_DeviceIoControl 000000014000c0e0 kernel32:KERNEL32.dll\r
+ 0002:000000e8 __imp_WakeAllConditionVariable 000000014000c0e8 kernel32:KERNEL32.dll\r
+ 0002:000000f0 __imp_CreateMutexA 000000014000c0f0 kernel32:KERNEL32.dll\r
+ 0002:000000f8 __imp_GetCurrentThreadId 000000014000c0f8 kernel32:KERNEL32.dll\r
+ 0002:00000100 __imp_ReleaseMutex 000000014000c100 kernel32:KERNEL32.dll\r
+ 0002:00000108 __imp_CloseHandle 000000014000c108 kernel32:KERNEL32.dll\r
+ 0002:00000110 __imp_DeleteTimerQueueTimer 000000014000c110 kernel32:KERNEL32.dll\r
+ 0002:00000118 __imp_CreateThread 000000014000c118 kernel32:KERNEL32.dll\r
+ 0002:00000120 __imp_EncodePointer 000000014000c120 kernel32:KERNEL32.dll\r
+ 0002:00000128 __imp_IsDebuggerPresent 000000014000c128 kernel32:KERNEL32.dll\r
+ 0002:00000130 \177KERNEL32_NULL_THUNK_DATA 000000014000c130 kernel32:KERNEL32.dll\r
+ 0002:00000138 __imp_?_Xout_of_range@std@@YAXPEBD@Z 000000014000c138 msvcprt:MSVCP100.dll\r
+ 0002:00000140 __imp_?_Xlength_error@std@@YAXPEBD@Z 000000014000c140 msvcprt:MSVCP100.dll\r
+ 0002:00000148 \177MSVCP100_NULL_THUNK_DATA 000000014000c148 msvcprt:MSVCP100.dll\r
+ 0002:00000150 __imp_??0exception@std@@QEAA@AEBQEBD@Z 000000014000c150 MSVCRT:MSVCR100.dll\r
+ 0002:00000158 __imp_??0exception@std@@QEAA@AEBV01@@Z 000000014000c158 MSVCRT:MSVCR100.dll\r
+ 0002:00000160 __imp_??1exception@std@@UEAA@XZ 000000014000c160 MSVCRT:MSVCR100.dll\r
+ 0002:00000168 __imp_??2@YAPEAX_K@Z 000000014000c168 MSVCRT:MSVCR100.dll\r
+ 0002:00000170 __imp_abort 000000014000c170 MSVCRT:MSVCR100.dll\r
+ 0002:00000178 __imp___iob_func 000000014000c178 MSVCRT:MSVCR100.dll\r
+ 0002:00000180 __imp_fprintf 000000014000c180 MSVCRT:MSVCR100.dll\r
+ 0002:00000188 __imp_strncpy_s 000000014000c188 MSVCRT:MSVCR100.dll\r
+ 0002:00000190 __imp_memset 000000014000c190 MSVCRT:MSVCR100.dll\r
+ 0002:00000198 __imp_strtol 000000014000c198 MSVCRT:MSVCR100.dll\r
+ 0002:000001a0 __imp_strnlen 000000014000c1a0 MSVCRT:MSVCR100.dll\r
+ 0002:000001a8 __imp__purecall 000000014000c1a8 MSVCRT:MSVCR100.dll\r
+ 0002:000001b0 __imp_sprintf_s 000000014000c1b0 MSVCRT:MSVCR100.dll\r
+ 0002:000001b8 __imp_free 000000014000c1b8 MSVCRT:MSVCR100.dll\r
+ 0002:000001c0 __imp_malloc 000000014000c1c0 MSVCRT:MSVCR100.dll\r
+ 0002:000001c8 __imp_strcpy_s 000000014000c1c8 MSVCRT:MSVCR100.dll\r
+ 0002:000001d0 __imp___C_specific_handler 000000014000c1d0 MSVCRT:MSVCR100.dll\r
+ 0002:000001d8 __imp__unlock 000000014000c1d8 MSVCRT:MSVCR100.dll\r
+ 0002:000001e0 __imp_?what@exception@std@@UEBAPEBDXZ 000000014000c1e0 MSVCRT:MSVCR100.dll\r
+ 0002:000001e8 __imp__lock 000000014000c1e8 MSVCRT:MSVCR100.dll\r
+ 0002:000001f0 __imp__onexit 000000014000c1f0 MSVCRT:MSVCR100.dll\r
+ 0002:000001f8 __imp__amsg_exit 000000014000c1f8 MSVCRT:MSVCR100.dll\r
+ 0002:00000200 __imp___getmainargs 000000014000c200 MSVCRT:MSVCR100.dll\r
+ 0002:00000208 __imp__XcptFilter 000000014000c208 MSVCRT:MSVCR100.dll\r
+ 0002:00000210 __imp__exit 000000014000c210 MSVCRT:MSVCR100.dll\r
+ 0002:00000218 __imp__cexit 000000014000c218 MSVCRT:MSVCR100.dll\r
+ 0002:00000220 __imp_exit 000000014000c220 MSVCRT:MSVCR100.dll\r
+ 0002:00000228 __imp___initenv 000000014000c228 MSVCRT:MSVCR100.dll\r
+ 0002:00000230 __imp__initterm 000000014000c230 MSVCRT:MSVCR100.dll\r
+ 0002:00000238 __imp__initterm_e 000000014000c238 MSVCRT:MSVCR100.dll\r
+ 0002:00000240 __imp__configthreadlocale 000000014000c240 MSVCRT:MSVCR100.dll\r
+ 0002:00000248 __imp___setusermatherr 000000014000c248 MSVCRT:MSVCR100.dll\r
+ 0002:00000250 __imp__commode 000000014000c250 MSVCRT:MSVCR100.dll\r
+ 0002:00000258 __imp__fmode 000000014000c258 MSVCRT:MSVCR100.dll\r
+ 0002:00000260 __imp___set_app_type 000000014000c260 MSVCRT:MSVCR100.dll\r
+ 0002:00000268 __imp___crt_debugger_hook 000000014000c268 MSVCRT:MSVCR100.dll\r
+ 0002:00000270 __imp_?terminate@@YAXXZ 000000014000c270 MSVCRT:MSVCR100.dll\r
+ 0002:00000278 __imp_?_type_info_dtor_internal_method@type_info@@QEAAXXZ 000000014000c278 MSVCRT:MSVCR100.dll\r
+ 0002:00000280 __imp___dllonexit 000000014000c280 MSVCRT:MSVCR100.dll\r
+ 0002:00000288 __imp_memcpy 000000014000c288 MSVCRT:MSVCR100.dll\r
+ 0002:00000290 __imp_memcmp 000000014000c290 MSVCRT:MSVCR100.dll\r
+ 0002:00000298 __imp__CxxThrowException 000000014000c298 MSVCRT:MSVCR100.dll\r
+ 0002:000002a0 __imp___CxxFrameHandler3 000000014000c2a0 MSVCRT:MSVCR100.dll\r
+ 0002:000002a8 __imp___RTDynamicCast 000000014000c2a8 MSVCRT:MSVCR100.dll\r
+ 0002:000002b0 __imp_??3@YAXPEAX@Z 000000014000c2b0 MSVCRT:MSVCR100.dll\r
+ 0002:000002b8 __imp_printf 000000014000c2b8 MSVCRT:MSVCR100.dll\r
+ 0002:000002c0 \177MSVCR100_NULL_THUNK_DATA 000000014000c2c0 MSVCRT:MSVCR100.dll\r
+ 0002:000002c8 __imp_ntohl 000000014000c2c8 ws2_32:WS2_32.dll\r
+ 0002:000002d0 __imp_htonl 000000014000c2d0 ws2_32:WS2_32.dll\r
+ 0002:000002d8 __imp_ntohs 000000014000c2d8 ws2_32:WS2_32.dll\r
+ 0002:000002e0 __imp_htons 000000014000c2e0 ws2_32:WS2_32.dll\r
+ 0002:000002e8 \177WS2_32_NULL_THUNK_DATA 000000014000c2e8 ws2_32:WS2_32.dll\r
+ 0002:000002f0 __imp_pcap_close 000000014000c2f0 wpcap:wpcap.dll\r
+ 0002:000002f8 __imp_pcap_setfilter 000000014000c2f8 wpcap:wpcap.dll\r
+ 0002:00000300 __imp_pcap_next_ex 000000014000c300 wpcap:wpcap.dll\r
+ 0002:00000308 __imp_pcap_sendpacket 000000014000c308 wpcap:wpcap.dll\r
+ 0002:00000310 __imp_pcap_compile 000000014000c310 wpcap:wpcap.dll\r
+ 0002:00000318 __imp_pcap_open 000000014000c318 wpcap:wpcap.dll\r
+ 0002:00000320 \177wpcap_NULL_THUNK_DATA 000000014000c320 wpcap:wpcap.dll\r
+ 0002:00000328 __xc_a 000000014000c328 MSVCRT:cinitexe.obj\r
+ 0002:00000350 __xc_z 000000014000c350 MSVCRT:cinitexe.obj\r
+ 0002:00000358 __xi_a 000000014000c358 MSVCRT:cinitexe.obj\r
+ 0002:00000370 __xi_z 000000014000c370 MSVCRT:cinitexe.obj\r
+ 0002:000003a8 ??_7type_info@@6B@ 000000014000c3a8 MSVCRT:ti_inst.obj\r
+ 0002:000003c0 ??_C@_0BM@PAPJHAGI@invalid?5map?1set?$DMT?$DO?5iterator?$AA@ 000000014000c3c0 avbts_osnet.obj\r
+ 0002:000003e8 ??_7bad_alloc@std@@6B@ 000000014000c3e8 avbts_osnet.obj\r
+ 0002:000003f8 ??_C@_07DOAOMMKG@Enabled?$AA@ 000000014000c3f8 ieee1588port.obj\r
+ 0002:00000400 ??_C@_08JGILNPHN@Disabled?$AA@ 000000014000c400 ieee1588port.obj\r
+ 0002:00000410 ??_C@_0P@MNFODPHI@AsCapable?3?5?$CFs?6?$AA@ 000000014000c410 ieee1588port.obj\r
+ 0002:00000420 ??_C@_0CB@NKHFMBCL@?4?4?2?4?4?2?4?4?2common?2ieee1588port?4cpp@ 000000014000c420 ieee1588port.obj\r
+ 0002:00000450 ??_C@_0GF@MDOAJEFI@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Failed?5to?5ini@ 000000014000c450 ieee1588port.obj\r
+ 0002:000004b8 ??_C@_07DLHCIBDH@default?$AA@ 000000014000c4b8 ieee1588port.obj\r
+ 0002:000004c0 ??_C@_0BK@DFGFBKIK@openPort?3?5thread?5started?6?$AA@ 000000014000c4c0 ieee1588port.obj\r
+ 0002:000004e0 ??_C@_0CP@OBBALOF@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Discarding?5in@ 000000014000c4e0 ieee1588port.obj\r
+ 0002:00000510 ??_C@_0DH@EKGLNKDB@ERROR?5at?5?$CFu?5in?5?$CFs?3?5read?5from?5net@ 000000014000c510 ieee1588port.obj\r
+ 0002:00000548 ??_C@_0CN@JABMLKGN@ERROR?5at?5?$CFu?5in?5?$CFs?3?5sendEventPort@ 000000014000c548 ieee1588port.obj\r
+ 0002:00000578 ??_C@_0BG@CGMOFACK@Starting?5port?5thread?6?$AA@ 000000014000c578 ieee1588port.obj\r
+ 0002:00000590 ??_C@_0DA@JEOMFCHP@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Error?5creatin@ 000000014000c590 ieee1588port.obj\r
+ 0002:000005c0 ??_C@_01EEMJAFIK@?6?$AA@ 000000014000c5c0 ieee1588port.obj\r
+ 0002:000005c8 ??_C@_0CP@NPGACHBF@?$CK?$CK?$CKSync?5Timeout?5Expired?5?9?5Becomi@ 000000014000c5c8 ieee1588port.obj\r
+ 0002:00000600 ??_C@_0EA@FIDILCHK@Error?5?$CITX?$CJ?5timestamping?5PDelay?5r@ 000000014000c600 ieee1588port.obj\r
+ 0002:00000640 ??_C@_0DE@BANOKGOL@Error?5?$CITX?$CJ?5timestamping?5PDelay?5r@ 000000014000c640 ieee1588port.obj\r
+ 0002:00000678 ??_C@_0DD@OGAMEIIA@Error?5?$CITX?$CJ?5timestamping?5Sync?5?$CIRe@ 000000014000c678 ieee1588port.obj\r
+ 0002:000006b0 ??_C@_0CK@JAJCOOCC@Error?5?$CITX?$CJ?5timestamping?5Sync?0?5er@ 000000014000c6b0 ieee1588port.obj\r
+ 0002:000006e0 ??_C@_0CD@KBDOGJHF@PDelay?5Response?5Followup?5is?5NULL@ 000000014000c6e0 ieee1588port.obj\r
+ 0002:00000708 ??_C@_0BF@CMGMJLA@Switching?5to?5Master?6?$AA@ 000000014000c708 ieee1588port.obj\r
+ 0002:00000720 ??_C@_0BE@JHDPFIAH@Switching?5to?5Slave?6?$AA@ 000000014000c720 ieee1588port.obj\r
+ 0002:00000738 ??_C@_0BE@JONHPENG@map?1set?$DMT?$DO?5too?5long?$AA@ 000000014000c738 ieee1588port.obj\r
+ 0002:00000758 ??_7LinkLayerAddress@@6B@ 000000014000c758 ieee1588port.obj\r
+ 0002:00000768 ??_7InterfaceLabel@@6B@ 000000014000c768 ieee1588port.obj\r
+ 0002:00000770 ??_C@_0DO@EBENJJMN@Error?5?$CIRX?$CJ?5timestamping?5RX?5event@ 000000014000c770 ptp_message.obj\r
+ 0002:000007b0 ??_C@_0CA@LPEMILMO@?4?4?2?4?4?2?4?4?2common?2ptp_message?4cpp?$AA@ 000000014000c7b0 ptp_message.obj\r
+ 0002:000007d0 ??_C@_0HH@MLCBNOMP@ERROR?5at?5?$CFu?5in?5?$CFs?3?5?$CK?$CK?$CK?5Received?5@ 000000014000c7d0 ptp_message.obj\r
+ 0002:00000848 ??_C@_0DK@JNCBBDII@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Received?5unsu@ 000000014000c848 ptp_message.obj\r
+ 0002:00000890 ??_C@_0EE@GKDAOEGN@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Received?5Foll@ 000000014000c890 ptp_message.obj\r
+ 0002:000008e0 ??_C@_0EK@GKBMCKE@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Received?5Foll@ 000000014000c8e0 ptp_message.obj\r
+ 0002:00000930 ??_C@_0EB@NKLDNAPB@Error?5?$CITX?$CJ?5timestamping?5PDelay?5R@ 000000014000c930 ptp_message.obj\r
+ 0002:00000978 ??_C@_0DF@LCPJCKOO@Error?5?$CITX?$CJ?5timestamping?5PDelay?5R@ 000000014000c978 ptp_message.obj\r
+ 0002:000009b0 ??_C@_0BO@DLMECCKO@Failed?5to?5get?5PDelay?5RX?5Lock?6?$AA@ 000000014000c9b0 ptp_message.obj\r
+ 0002:000009d0 ??_C@_0EH@DDBECIOJ@ERROR?5at?5?$CFu?5in?5?$CFs?3?5?$DO?$DO?$DO?5Received?5@ 000000014000c9d0 ptp_message.obj\r
+ 0002:00000a20 ??_C@_0EI@NNLKEKEC@ERROR?5at?5?$CFu?5in?5?$CFs?3?5?$DO?$DO?$DO?5Received?5@ 000000014000ca20 ptp_message.obj\r
+ 0002:00000a70 ??_C@_0FN@HBGJNHBE@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Received?5PDel@ 000000014000ca70 ptp_message.obj\r
+ 0002:00000ad0 ??_C@_0CC@DILPCBD@ERROR?5at?5?$CFu?5in?5?$CFs?3?5My?5SeqId?3?5?$CFu?5@ 000000014000cad0 ptp_message.obj\r
+ 0002:00000af8 ??_C@_0CF@BHKGMNAC@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Their?5SeqId?3?5@ 000000014000caf8 ptp_message.obj\r
+ 0002:00000b20 ??_C@_0FO@BHOOLJAL@ERROR?5at?5?$CFu?5in?5?$CFs?3?5Received?5PDel@ 000000014000cb20 ptp_message.obj\r
+ 0002:00000b80 ??_C@_0CH@FHAMNBPF@ERROR?5at?5?$CFu?5in?5?$CFs?3?5?$CFhu?0?5?$CFhu?0?5?$CFhu@ 000000014000cb80 ptp_message.obj\r
+ 0002:00000ba8 ??_C@_0BB@MOGOBHAF@list?$DMT?$DO?5too?5long?$AA@ 000000014000cba8 ptp_message.obj\r
+ 0002:00000bc8 ??_7PTPMessageCommon@@6B@ 000000014000cbc8 ptp_message.obj\r
+ 0002:00000be0 ??_7PTPMessageSync@@6B@ 000000014000cbe0 ptp_message.obj\r
+ 0002:00000bf8 ??_7PTPMessageAnnounce@@6B@ 000000014000cbf8 ptp_message.obj\r
+ 0002:00000c10 ??_7PTPMessagePathDelayReq@@6B@ 000000014000cc10 ptp_message.obj\r
+ 0002:00000c28 ??_7PTPMessagePathDelayResp@@6B@ 000000014000cc28 ptp_message.obj\r
+ 0002:00000c40 ??_7PTPMessagePathDelayRespFollowUp@@6B@ 000000014000cc40 ptp_message.obj\r
+ 0002:00000c58 ??_7PTPMessageFollowUp@@6B@ 000000014000cc58 ptp_message.obj\r
+ 0002:00000c68 ??_C@_04GBDIODIA@?2?2?4?2?$AA@ 000000014000cc68 daemon_cl.obj\r
+ 0002:00000c70 ??_C@_09IPJPBDHI@?2?2?4?2pipe?2?$AA@ 000000014000cc70 daemon_cl.obj\r
+ 0002:00000c80 ??_C@_0M@FKJIJDJM@gptp?9update?$AA@ 000000014000cc80 daemon_cl.obj\r
+ 0002:00000c90 ??_C@_0BL@JMMFGJEE@Failed?5to?5initialize?5port?6?$AA@ 000000014000cc90 daemon_cl.obj\r
+ 0002:00000cb0 ??_C@_0CD@KNEPODGG@Unable?5to?5register?5Ctrl?9C?5handle@ 000000014000ccb0 daemon_cl.obj\r
+ 0002:00000ce8 ??_7HWTimestamper@@6B@ 000000014000cce8 daemon_cl.obj\r
+ 0002:00000d40 ??_7WindowsPCAPNetworkInterface@@6B@ 000000014000cd40 daemon_cl.obj\r
+ 0002:00000d70 ??_7WindowsPCAPNetworkInterfaceFactory@@6B@ 000000014000cd70 daemon_cl.obj\r
+ 0002:00000d80 ??_7WindowsLock@@6B@ 000000014000cd80 daemon_cl.obj\r
+ 0002:00000da0 ??_7WindowsLockFactory@@6B@ 000000014000cda0 daemon_cl.obj\r
+ 0002:00000db0 ??_7WindowsCondition@@6B@ 000000014000cdb0 daemon_cl.obj\r
+ 0002:00000dd0 ??_7WindowsConditionFactory@@6B@ 000000014000cdd0 daemon_cl.obj\r
+ 0002:00000de0 ??_7WindowsTimerQueue@@6B@ 000000014000cde0 daemon_cl.obj\r
+ 0002:00000df8 ??_7WindowsTimerQueueFactory@@6B@ 000000014000cdf8 daemon_cl.obj\r
+ 0002:00000e08 ??_7WindowsTimer@@6B@ 000000014000ce08 daemon_cl.obj\r
+ 0002:00000e18 ??_7WindowsTimerFactory@@6B@ 000000014000ce18 daemon_cl.obj\r
+ 0002:00000e28 ??_7WindowsThread@@6B@ 000000014000ce28 daemon_cl.obj\r
+ 0002:00000e40 ??_7WindowsThreadFactory@@6B@ 000000014000ce40 daemon_cl.obj\r
+ 0002:00000e58 ??_7WindowsTimestamper@@6B@ 000000014000ce58 daemon_cl.obj\r
+ 0002:00000eb0 ??_7WindowsNamedPipeIPC@@6B@ 000000014000ceb0 daemon_cl.obj\r
+ 0002:00000ec0 ??_C@_0BF@EIMMNHOL@rpcap?3?1?1?2Device?2NPF_?$AA@ 000000014000cec0 packet.obj\r
+ 0002:00000ed8 ??_C@_0N@IELFOPPD@Opening?3?5?$CFs?6?$AA@ 000000014000ced8 packet.obj\r
+ 0002:00000ee8 ??_C@_0P@CMACLOMI@ether?5proto?50x?$AA@ 000000014000cee8 packet.obj\r
+ 0002:00000ef8 ??_C@_03OIHFBGIJ@?$CFhx?$AA@ 000000014000cef8 packet.obj\r
+ 0002:00000f00 __real@43e0000000000000 000000014000cf00 CIL library: CIL module\r
+ 0002:00000f08 __real@41cdcd6500000000 000000014000cf08 CIL library: CIL module\r
+ 0002:00000f10 __real@43f0000000000000 000000014000cf10 CIL library: CIL module\r
+ 0002:00000f18 __real@3ff0e5604189374c 000000014000cf18 CIL library: CIL module\r
+ 0002:00000f20 __real@3ff0000000000000 000000014000cf20 CIL library: CIL module\r
+ 0002:00000fc8 __real@4008000000000000 000000014000cfc8 CIL library: CIL module\r
+ 0002:00000fd0 __real@4000000000000000 000000014000cfd0 CIL library: CIL module\r
+ 0002:00001050 __real@4024000000000000 000000014000d050 CIL library: CIL module\r
+ 0002:00001410 ??_R4type_info@@6B@ 000000014000d410 MSVCRT:ti_inst.obj\r
+ 0002:00001438 ??_R3type_info@@8 000000014000d438 MSVCRT:ti_inst.obj\r
+ 0002:00001450 ??_R2type_info@@8 000000014000d450 MSVCRT:ti_inst.obj\r
+ 0002:00001460 ??_R1A@?0A@EA@type_info@@8 000000014000d460 MSVCRT:ti_inst.obj\r
+ 0002:00001488 ??_R4bad_alloc@std@@6B@ 000000014000d488 avbts_osnet.obj\r
+ 0002:000014b0 ??_R3bad_alloc@std@@8 000000014000d4b0 avbts_osnet.obj\r
+ 0002:000014c8 ??_R2bad_alloc@std@@8 000000014000d4c8 avbts_osnet.obj\r
+ 0002:000014e0 ??_R1A@?0A@EA@exception@std@@8 000000014000d4e0 avbts_osnet.obj\r
+ 0002:00001508 ??_R3exception@std@@8 000000014000d508 avbts_osnet.obj\r
+ 0002:00001520 ??_R2exception@std@@8 000000014000d520 avbts_osnet.obj\r
+ 0002:00001530 ??_R1A@?0A@EA@bad_alloc@std@@8 000000014000d530 avbts_osnet.obj\r
+ 0002:00001558 ??_R4InterfaceLabel@@6B@ 000000014000d558 ieee1588port.obj\r
+ 0002:00001580 ??_R4LinkLayerAddress@@6B@ 000000014000d580 ieee1588port.obj\r
+ 0002:000015a8 ??_R3LinkLayerAddress@@8 000000014000d5a8 ieee1588port.obj\r
+ 0002:000015c0 ??_R2LinkLayerAddress@@8 000000014000d5c0 ieee1588port.obj\r
+ 0002:000015d8 ??_R1A@?0A@EA@InterfaceLabel@@8 000000014000d5d8 ieee1588port.obj\r
+ 0002:00001600 ??_R3InterfaceLabel@@8 000000014000d600 ieee1588port.obj\r
+ 0002:00001618 ??_R2InterfaceLabel@@8 000000014000d618 ieee1588port.obj\r
+ 0002:00001628 ??_R1A@?0A@EA@LinkLayerAddress@@8 000000014000d628 ieee1588port.obj\r
+ 0002:00001650 ??_R4PTPMessageFollowUp@@6B@ 000000014000d650 ptp_message.obj\r
+ 0002:00001678 ??_R3PTPMessageFollowUp@@8 000000014000d678 ptp_message.obj\r
+ 0002:00001690 ??_R2PTPMessageFollowUp@@8 000000014000d690 ptp_message.obj\r
+ 0002:000016a8 ??_R1A@?0A@EA@PTPMessageFollowUp@@8 000000014000d6a8 ptp_message.obj\r
+ 0002:000016d0 ??_R4PTPMessagePathDelayRespFollowUp@@6B@ 000000014000d6d0 ptp_message.obj\r
+ 0002:000016f8 ??_R3PTPMessagePathDelayRespFollowUp@@8 000000014000d6f8 ptp_message.obj\r
+ 0002:00001710 ??_R2PTPMessagePathDelayRespFollowUp@@8 000000014000d710 ptp_message.obj\r
+ 0002:00001728 ??_R1A@?0A@EA@PTPMessagePathDelayRespFollowUp@@8 000000014000d728 ptp_message.obj\r
+ 0002:00001750 ??_R4PTPMessagePathDelayResp@@6B@ 000000014000d750 ptp_message.obj\r
+ 0002:00001778 ??_R3PTPMessagePathDelayResp@@8 000000014000d778 ptp_message.obj\r
+ 0002:00001790 ??_R2PTPMessagePathDelayResp@@8 000000014000d790 ptp_message.obj\r
+ 0002:000017a8 ??_R1A@?0A@EA@PTPMessagePathDelayResp@@8 000000014000d7a8 ptp_message.obj\r
+ 0002:000017d0 ??_R4PTPMessagePathDelayReq@@6B@ 000000014000d7d0 ptp_message.obj\r
+ 0002:000017f8 ??_R3PTPMessagePathDelayReq@@8 000000014000d7f8 ptp_message.obj\r
+ 0002:00001810 ??_R2PTPMessagePathDelayReq@@8 000000014000d810 ptp_message.obj\r
+ 0002:00001828 ??_R1A@?0A@EA@PTPMessagePathDelayReq@@8 000000014000d828 ptp_message.obj\r
+ 0002:00001850 ??_R4PTPMessageAnnounce@@6B@ 000000014000d850 ptp_message.obj\r
+ 0002:00001878 ??_R3PTPMessageAnnounce@@8 000000014000d878 ptp_message.obj\r
+ 0002:00001890 ??_R2PTPMessageAnnounce@@8 000000014000d890 ptp_message.obj\r
+ 0002:000018a8 ??_R1A@?0A@EA@PTPMessageAnnounce@@8 000000014000d8a8 ptp_message.obj\r
+ 0002:000018d0 ??_R4PTPMessageSync@@6B@ 000000014000d8d0 ptp_message.obj\r
+ 0002:000018f8 ??_R3PTPMessageSync@@8 000000014000d8f8 ptp_message.obj\r
+ 0002:00001910 ??_R2PTPMessageSync@@8 000000014000d910 ptp_message.obj\r
+ 0002:00001928 ??_R1A@?0A@EA@PTPMessageSync@@8 000000014000d928 ptp_message.obj\r
+ 0002:00001950 ??_R4PTPMessageCommon@@6B@ 000000014000d950 ptp_message.obj\r
+ 0002:00001978 ??_R3PTPMessageCommon@@8 000000014000d978 ptp_message.obj\r
+ 0002:00001990 ??_R2PTPMessageCommon@@8 000000014000d990 ptp_message.obj\r
+ 0002:000019a0 ??_R1A@?0A@EA@PTPMessageCommon@@8 000000014000d9a0 ptp_message.obj\r
+ 0002:000019c8 ??_R4WindowsNamedPipeIPC@@6B@ 000000014000d9c8 daemon_cl.obj\r
+ 0002:000019f0 ??_R3WindowsNamedPipeIPC@@8 000000014000d9f0 daemon_cl.obj\r
+ 0002:00001a08 ??_R2WindowsNamedPipeIPC@@8 000000014000da08 daemon_cl.obj\r
+ 0002:00001a20 ??_R1A@?0A@EA@WindowsNamedPipeIPC@@8 000000014000da20 daemon_cl.obj\r
+ 0002:00001a48 ??_R4WindowsTimestamper@@6B@ 000000014000da48 daemon_cl.obj\r
+ 0002:00001a70 ??_R3WindowsTimestamper@@8 000000014000da70 daemon_cl.obj\r
+ 0002:00001a88 ??_R2WindowsTimestamper@@8 000000014000da88 daemon_cl.obj\r
+ 0002:00001aa0 ??_R1A@?0A@EA@WindowsTimestamper@@8 000000014000daa0 daemon_cl.obj\r
+ 0002:00001ac8 ??_R4WindowsThreadFactory@@6B@ 000000014000dac8 daemon_cl.obj\r
+ 0002:00001af0 ??_R3WindowsThreadFactory@@8 000000014000daf0 daemon_cl.obj\r
+ 0002:00001b08 ??_R2WindowsThreadFactory@@8 000000014000db08 daemon_cl.obj\r
+ 0002:00001b20 ??_R1A@?0A@EA@WindowsThreadFactory@@8 000000014000db20 daemon_cl.obj\r
+ 0002:00001b48 ??_R4WindowsThread@@6B@ 000000014000db48 daemon_cl.obj\r
+ 0002:00001b70 ??_R3WindowsThread@@8 000000014000db70 daemon_cl.obj\r
+ 0002:00001b88 ??_R2WindowsThread@@8 000000014000db88 daemon_cl.obj\r
+ 0002:00001ba0 ??_R1A@?0A@EA@WindowsThread@@8 000000014000dba0 daemon_cl.obj\r
+ 0002:00001bc8 ??_R4WindowsTimerFactory@@6B@ 000000014000dbc8 daemon_cl.obj\r
+ 0002:00001bf0 ??_R3WindowsTimerFactory@@8 000000014000dbf0 daemon_cl.obj\r
+ 0002:00001c08 ??_R2WindowsTimerFactory@@8 000000014000dc08 daemon_cl.obj\r
+ 0002:00001c20 ??_R1A@?0A@EA@WindowsTimerFactory@@8 000000014000dc20 daemon_cl.obj\r
+ 0002:00001c48 ??_R4WindowsTimer@@6B@ 000000014000dc48 daemon_cl.obj\r
+ 0002:00001c70 ??_R3WindowsTimer@@8 000000014000dc70 daemon_cl.obj\r
+ 0002:00001c88 ??_R2WindowsTimer@@8 000000014000dc88 daemon_cl.obj\r
+ 0002:00001ca0 ??_R1A@?0A@EA@WindowsTimer@@8 000000014000dca0 daemon_cl.obj\r
+ 0002:00001cc8 ??_R4WindowsTimerQueueFactory@@6B@ 000000014000dcc8 daemon_cl.obj\r
+ 0002:00001cf0 ??_R3WindowsTimerQueueFactory@@8 000000014000dcf0 daemon_cl.obj\r
+ 0002:00001d08 ??_R2WindowsTimerQueueFactory@@8 000000014000dd08 daemon_cl.obj\r
+ 0002:00001d20 ??_R1A@?0A@EA@WindowsTimerQueueFactory@@8 000000014000dd20 daemon_cl.obj\r
+ 0002:00001d48 ??_R4WindowsTimerQueue@@6B@ 000000014000dd48 daemon_cl.obj\r
+ 0002:00001d70 ??_R3WindowsTimerQueue@@8 000000014000dd70 daemon_cl.obj\r
+ 0002:00001d88 ??_R2WindowsTimerQueue@@8 000000014000dd88 daemon_cl.obj\r
+ 0002:00001da0 ??_R1A@?0A@EA@WindowsTimerQueue@@8 000000014000dda0 daemon_cl.obj\r
+ 0002:00001dc8 ??_R4WindowsConditionFactory@@6B@ 000000014000ddc8 daemon_cl.obj\r
+ 0002:00001df0 ??_R3WindowsConditionFactory@@8 000000014000ddf0 daemon_cl.obj\r
+ 0002:00001e08 ??_R2WindowsConditionFactory@@8 000000014000de08 daemon_cl.obj\r
+ 0002:00001e20 ??_R1A@?0A@EA@WindowsConditionFactory@@8 000000014000de20 daemon_cl.obj\r
+ 0002:00001e48 ??_R4WindowsCondition@@6B@ 000000014000de48 daemon_cl.obj\r
+ 0002:00001e70 ??_R3WindowsCondition@@8 000000014000de70 daemon_cl.obj\r
+ 0002:00001e88 ??_R2WindowsCondition@@8 000000014000de88 daemon_cl.obj\r
+ 0002:00001ea0 ??_R1A@?0A@EA@WindowsCondition@@8 000000014000dea0 daemon_cl.obj\r
+ 0002:00001ec8 ??_R4WindowsLockFactory@@6B@ 000000014000dec8 daemon_cl.obj\r
+ 0002:00001ef0 ??_R3WindowsLockFactory@@8 000000014000def0 daemon_cl.obj\r
+ 0002:00001f08 ??_R2WindowsLockFactory@@8 000000014000df08 daemon_cl.obj\r
+ 0002:00001f20 ??_R1A@?0A@EA@WindowsLockFactory@@8 000000014000df20 daemon_cl.obj\r
+ 0002:00001f48 ??_R4WindowsLock@@6B@ 000000014000df48 daemon_cl.obj\r
+ 0002:00001f70 ??_R3WindowsLock@@8 000000014000df70 daemon_cl.obj\r
+ 0002:00001f88 ??_R2WindowsLock@@8 000000014000df88 daemon_cl.obj\r
+ 0002:00001fa0 ??_R1A@?0A@EA@WindowsLock@@8 000000014000dfa0 daemon_cl.obj\r
+ 0002:00001fc8 ??_R4WindowsPCAPNetworkInterfaceFactory@@6B@ 000000014000dfc8 daemon_cl.obj\r
+ 0002:00001ff0 ??_R3WindowsPCAPNetworkInterfaceFactory@@8 000000014000dff0 daemon_cl.obj\r
+ 0002:00002008 ??_R2WindowsPCAPNetworkInterfaceFactory@@8 000000014000e008 daemon_cl.obj\r
+ 0002:00002020 ??_R1A@?0A@EA@WindowsPCAPNetworkInterfaceFactory@@8 000000014000e020 daemon_cl.obj\r
+ 0002:00002048 ??_R4WindowsPCAPNetworkInterface@@6B@ 000000014000e048 daemon_cl.obj\r
+ 0002:00002070 ??_R3WindowsPCAPNetworkInterface@@8 000000014000e070 daemon_cl.obj\r
+ 0002:00002088 ??_R2WindowsPCAPNetworkInterface@@8 000000014000e088 daemon_cl.obj\r
+ 0002:000020a0 ??_R1A@?0A@EA@WindowsPCAPNetworkInterface@@8 000000014000e0a0 daemon_cl.obj\r
+ 0002:000020c8 ??_R3OS_IPC@@8 000000014000e0c8 daemon_cl.obj\r
+ 0002:000020e0 ??_R2OS_IPC@@8 000000014000e0e0 daemon_cl.obj\r
+ 0002:000020f0 ??_R1A@?0A@EA@OS_IPC@@8 000000014000e0f0 daemon_cl.obj\r
+ 0002:00002118 ??_R3OSTimerQueueFactory@@8 000000014000e118 daemon_cl.obj\r
+ 0002:00002130 ??_R2OSTimerQueueFactory@@8 000000014000e130 daemon_cl.obj\r
+ 0002:00002140 ??_R1A@?0A@EA@OSTimerQueueFactory@@8 000000014000e140 daemon_cl.obj\r
+ 0002:00002168 ??_R3OSTimerQueue@@8 000000014000e168 daemon_cl.obj\r
+ 0002:00002180 ??_R2OSTimerQueue@@8 000000014000e180 daemon_cl.obj\r
+ 0002:00002190 ??_R1A@?0A@EA@OSTimerQueue@@8 000000014000e190 daemon_cl.obj\r
+ 0002:000021b8 ??_R3OSConditionFactory@@8 000000014000e1b8 daemon_cl.obj\r
+ 0002:000021d0 ??_R2OSConditionFactory@@8 000000014000e1d0 daemon_cl.obj\r
+ 0002:000021e0 ??_R1A@?0A@EA@OSConditionFactory@@8 000000014000e1e0 daemon_cl.obj\r
+ 0002:00002208 ??_R3OSCondition@@8 000000014000e208 daemon_cl.obj\r
+ 0002:00002220 ??_R2OSCondition@@8 000000014000e220 daemon_cl.obj\r
+ 0002:00002230 ??_R1A@?0A@EA@OSCondition@@8 000000014000e230 daemon_cl.obj\r
+ 0002:00002258 ??_R3OSThreadFactory@@8 000000014000e258 daemon_cl.obj\r
+ 0002:00002270 ??_R2OSThreadFactory@@8 000000014000e270 daemon_cl.obj\r
+ 0002:00002280 ??_R1A@?0A@EA@OSThreadFactory@@8 000000014000e280 daemon_cl.obj\r
+ 0002:000022a8 ??_R3OSThread@@8 000000014000e2a8 daemon_cl.obj\r
+ 0002:000022c0 ??_R2OSThread@@8 000000014000e2c0 daemon_cl.obj\r
+ 0002:000022d0 ??_R1A@?0A@EA@OSThread@@8 000000014000e2d0 daemon_cl.obj\r
+ 0002:000022f8 ??_R3OSLockFactory@@8 000000014000e2f8 daemon_cl.obj\r
+ 0002:00002310 ??_R2OSLockFactory@@8 000000014000e310 daemon_cl.obj\r
+ 0002:00002320 ??_R1A@?0A@EA@OSLockFactory@@8 000000014000e320 daemon_cl.obj\r
+ 0002:00002348 ??_R3OSLock@@8 000000014000e348 daemon_cl.obj\r
+ 0002:00002360 ??_R2OSLock@@8 000000014000e360 daemon_cl.obj\r
+ 0002:00002370 ??_R1A@?0A@EA@OSLock@@8 000000014000e370 daemon_cl.obj\r
+ 0002:00002398 ??_R3OSTimerFactory@@8 000000014000e398 daemon_cl.obj\r
+ 0002:000023b0 ??_R2OSTimerFactory@@8 000000014000e3b0 daemon_cl.obj\r
+ 0002:000023c0 ??_R1A@?0A@EA@OSTimerFactory@@8 000000014000e3c0 daemon_cl.obj\r
+ 0002:000023e8 ??_R3OSTimer@@8 000000014000e3e8 daemon_cl.obj\r
+ 0002:00002400 ??_R2OSTimer@@8 000000014000e400 daemon_cl.obj\r
+ 0002:00002410 ??_R1A@?0A@EA@OSTimer@@8 000000014000e410 daemon_cl.obj\r
+ 0002:00002438 ??_R3OSNetworkInterfaceFactory@@8 000000014000e438 daemon_cl.obj\r
+ 0002:00002450 ??_R2OSNetworkInterfaceFactory@@8 000000014000e450 daemon_cl.obj\r
+ 0002:00002460 ??_R1A@?0A@EA@OSNetworkInterfaceFactory@@8 000000014000e460 daemon_cl.obj\r
+ 0002:00002488 ??_R3OSNetworkInterface@@8 000000014000e488 daemon_cl.obj\r
+ 0002:000024a0 ??_R2OSNetworkInterface@@8 000000014000e4a0 daemon_cl.obj\r
+ 0002:000024b0 ??_R1A@?0A@EA@OSNetworkInterface@@8 000000014000e4b0 daemon_cl.obj\r
+ 0002:000024d8 ??_R4HWTimestamper@@6B@ 000000014000e4d8 daemon_cl.obj\r
+ 0002:00002500 ??_R3HWTimestamper@@8 000000014000e500 daemon_cl.obj\r
+ 0002:00002518 ??_R2HWTimestamper@@8 000000014000e518 daemon_cl.obj\r
+ 0002:00002528 ??_R1A@?0A@EA@HWTimestamper@@8 000000014000e528 daemon_cl.obj\r
+ 0002:00002550 __rtc_iaa 000000014000e550 MSVCRT:_initsect_.obj\r
+ 0002:00002558 __rtc_izz 000000014000e558 MSVCRT:_initsect_.obj\r
+ 0002:00002560 __rtc_taa 000000014000e560 MSVCRT:_initsect_.obj\r
+ 0002:00002568 __rtc_tzz 000000014000e568 MSVCRT:_initsect_.obj\r
+ 0002:00003750 _CT??_R0?AVbad_alloc@std@@@8??0bad_alloc@std@@QEAA@AEBV01@@Z24 000000014000f750 avbts_osnet.obj\r
+ 0002:00003778 _CT??_R0?AVexception@std@@@8??0exception@std@@QEAA@AEBV01@@Z24 000000014000f778 avbts_osnet.obj\r
+ 0002:000037a0 _CTA2?AVbad_alloc@std@@ 000000014000f7a0 avbts_osnet.obj\r
+ 0002:000037b8 _TI2?AVbad_alloc@std@@ 000000014000f7b8 avbts_osnet.obj\r
+ 0002:000037d4 __IMPORT_DESCRIPTOR_wpcap 000000014000f7d4 wpcap:wpcap.dll\r
+ 0002:000037e8 __IMPORT_DESCRIPTOR_IPHLPAPI 000000014000f7e8 Iphlpapi:IPHLPAPI.DLL\r
+ 0002:000037fc __IMPORT_DESCRIPTOR_WS2_32 000000014000f7fc ws2_32:WS2_32.dll\r
+ 0002:00003810 __IMPORT_DESCRIPTOR_KERNEL32 000000014000f810 kernel32:KERNEL32.dll\r
+ 0002:00003824 __IMPORT_DESCRIPTOR_MSVCP100 000000014000f824 msvcprt:MSVCP100.dll\r
+ 0002:00003838 __IMPORT_DESCRIPTOR_MSVCR100 000000014000f838 MSVCRT:MSVCR100.dll\r
+ 0002:0000384c __NULL_IMPORT_DESCRIPTOR 000000014000f84c wpcap:wpcap.dll\r
+ 0003:00000000 ??_R0?AVtype_info@@@8 0000000140011000 MSVCRT:ti_inst.obj\r
+ 0003:00000020 __security_cookie 0000000140011020 MSVCRT:gs_cookie.obj\r
+ 0003:00000028 __security_cookie_complement 0000000140011028 MSVCRT:gs_cookie.obj\r
+ 0003:00000030 __native_dllmain_reason 0000000140011030 MSVCRT:natstart.obj\r
+ 0003:00000034 __native_vcclrit_reason 0000000140011034 MSVCRT:natstart.obj\r
+ 0003:00000038 __globallocalestatus 0000000140011038 MSVCRT:xthdloc.obj\r
+ 0003:0000003c __defaultmatherr 000000014001103c MSVCRT:merr.obj\r
+ 0003:00000040 ??_R0?AVbad_alloc@std@@@8 0000000140011040 avbts_osnet.obj\r
+ 0003:00000068 ??_R0?AVexception@std@@@8 0000000140011068 avbts_osnet.obj\r
+ 0003:00000090 ??_R0?AVInterfaceLabel@@@8 0000000140011090 ieee1588port.obj\r
+ 0003:000000b8 ??_R0?AVLinkLayerAddress@@@8 00000001400110b8 ieee1588port.obj\r
+ 0003:000000e0 ??_R0?AVPTPMessageFollowUp@@@8 00000001400110e0 ptp_message.obj\r
+ 0003:00000110 ??_R0?AVPTPMessagePathDelayRespFollowUp@@@8 0000000140011110 ptp_message.obj\r
+ 0003:00000148 ??_R0?AVPTPMessagePathDelayResp@@@8 0000000140011148 ptp_message.obj\r
+ 0003:00000178 ??_R0?AVPTPMessagePathDelayReq@@@8 0000000140011178 ptp_message.obj\r
+ 0003:000001a8 ??_R0?AVPTPMessageAnnounce@@@8 00000001400111a8 ptp_message.obj\r
+ 0003:000001d8 ??_R0?AVPTPMessageSync@@@8 00000001400111d8 ptp_message.obj\r
+ 0003:00000200 ??_R0?AVPTPMessageCommon@@@8 0000000140011200 ptp_message.obj\r
+ 0003:00000228 ??_R0?AVWindowsNamedPipeIPC@@@8 0000000140011228 daemon_cl.obj\r
+ 0003:00000258 ??_R0?AVWindowsTimestamper@@@8 0000000140011258 daemon_cl.obj\r
+ 0003:00000288 ??_R0?AVWindowsThreadFactory@@@8 0000000140011288 daemon_cl.obj\r
+ 0003:000002b8 ??_R0?AVWindowsThread@@@8 00000001400112b8 daemon_cl.obj\r
+ 0003:000002e0 ??_R0?AVWindowsTimerFactory@@@8 00000001400112e0 daemon_cl.obj\r
+ 0003:00000310 ??_R0?AVWindowsTimer@@@8 0000000140011310 daemon_cl.obj\r
+ 0003:00000338 ??_R0?AVWindowsTimerQueueFactory@@@8 0000000140011338 daemon_cl.obj\r
+ 0003:00000368 ??_R0?AVWindowsTimerQueue@@@8 0000000140011368 daemon_cl.obj\r
+ 0003:00000390 ??_R0?AVWindowsConditionFactory@@@8 0000000140011390 daemon_cl.obj\r
+ 0003:000003c0 ??_R0?AVWindowsCondition@@@8 00000001400113c0 daemon_cl.obj\r
+ 0003:000003e8 ??_R0?AVWindowsLockFactory@@@8 00000001400113e8 daemon_cl.obj\r
+ 0003:00000418 ??_R0?AVWindowsLock@@@8 0000000140011418 daemon_cl.obj\r
+ 0003:00000440 ??_R0?AVWindowsPCAPNetworkInterfaceFactory@@@8 0000000140011440 daemon_cl.obj\r
+ 0003:00000480 ??_R0?AVWindowsPCAPNetworkInterface@@@8 0000000140011480 daemon_cl.obj\r
+ 0003:000004b8 ??_R0?AVOS_IPC@@@8 00000001400114b8 daemon_cl.obj\r
+ 0003:000004d8 ??_R0?AVOSTimerQueueFactory@@@8 00000001400114d8 daemon_cl.obj\r
+ 0003:00000508 ??_R0?AVOSTimerQueue@@@8 0000000140011508 daemon_cl.obj\r
+ 0003:00000530 ??_R0?AVOSConditionFactory@@@8 0000000140011530 daemon_cl.obj\r
+ 0003:00000560 ??_R0?AVOSCondition@@@8 0000000140011560 daemon_cl.obj\r
+ 0003:00000588 ??_R0?AVOSThreadFactory@@@8 0000000140011588 daemon_cl.obj\r
+ 0003:000005b0 ??_R0?AVOSThread@@@8 00000001400115b0 daemon_cl.obj\r
+ 0003:000005d0 ??_R0?AVOSLockFactory@@@8 00000001400115d0 daemon_cl.obj\r
+ 0003:000005f8 ??_R0?AVOSLock@@@8 00000001400115f8 daemon_cl.obj\r
+ 0003:00000618 ??_R0?AVOSTimerFactory@@@8 0000000140011618 daemon_cl.obj\r
+ 0003:00000640 ??_R0?AVOSTimer@@@8 0000000140011640 daemon_cl.obj\r
+ 0003:00000660 ??_R0?AVOSNetworkInterfaceFactory@@@8 0000000140011660 daemon_cl.obj\r
+ 0003:00000690 ??_R0?AVOSNetworkInterface@@@8 0000000140011690 daemon_cl.obj\r
+ 0003:000006c0 ??_R0?AVHWTimestamper@@@8 00000001400116c0 daemon_cl.obj\r
+ 0003:000006e8 ?other_multicast@IEEE1588Port@@0VLinkLayerAddress@@A 00000001400116e8 ieee1588port.obj\r
+ 0003:000006f8 ?pdelay_multicast@IEEE1588Port@@0VLinkLayerAddress@@A 00000001400116f8 ieee1588port.obj\r
+ 0003:00000710 _fltused 0000000140011710 MSVCRT:dllsupp.obj\r
+ 0003:00000cc0 _dowildcard 0000000140011cc0 MSVCRT:wildcard.obj\r
+ 0003:00000cc4 _newmode 0000000140011cc4 MSVCRT:_newmode.obj\r
+ 0003:00000cc8 _commode 0000000140011cc8 MSVCRT:xncommod.obj\r
+ 0003:00000ccc _fmode 0000000140011ccc MSVCRT:xtxtmode.obj\r
+ 0003:00000cd8 ?factoryMap@OSNetworkInterfaceFactory@@0V?$map@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@@std@@A 0000000140011cd8 avbts_osnet.obj\r
+ 0003:00000cf8 __native_startup_state 0000000140011cf8 <common>\r
+ 0003:00000d00 __native_startup_lock 0000000140011d00 <common>\r
+ 0003:00000d08 __dyn_tls_init_callback 0000000140011d08 <common>\r
+ 0003:00000d10 __onexitend 0000000140011d10 <common>\r
+ 0003:00000d18 __onexitbegin 0000000140011d18 <common>\r
+\r
+ entry point at 0001:0000991c\r
+\r
+ Static symbols\r
+\r
+ 0001:00009664 pre_cpp_init 000000014000a664 f MSVCRT:crtexe.obj\r
+ 0001:000096cc __tmainCRTStartup 000000014000a6cc f MSVCRT:crtexe.obj\r
+ 0001:0000984c pre_c_init 000000014000a84c f MSVCRT:crtexe.obj\r
+ 0001:00009f60 _onexit$fin$0 000000014000af60 f MSVCRT:atonexit.obj\r
+ 0001:00009f7b __tmainCRTStartup$filt$0 000000014000af7b f MSVCRT:crtexe.obj\r
+ 0001:00009f99 ?filt$0@?0??__ArrayUnwind@@YAXPEAX_KHP6AX0@Z@Z@4HA 000000014000af99 f MSVCRT:ehvecdtr.obj\r
+ 0001:00009fda ?fin$0@?0???_M@YAXPEAX_KHP6AX0@Z@Z@4HA 000000014000afda f MSVCRT:ehvecdtr.obj\r
+ 0001:0000a010 _IsNonwritableInCurrentImage$filt$0 000000014000b010 f MSVCRT:pesect.obj\r
+ 0001:0000a040 ?catch$0@?0???$_Insert@V?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@std@@@?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAXV?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@1@00Uforward_iterator_tag@1@@Z@4HA 000000014000b040 f CIL library: CIL module\r
+ 0001:0000a04f __catch$??$_Insert@V?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@std@@@?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAXV?$_List_const_iterator@V?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@@1@00Uforward_iterator_tag@1@@Z$0 000000014000b04f f CIL library: CIL module\r
+ 0001:0000a0b0 ?dtor$0@?0???0?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAA@AEBV01@@Z@4HA 000000014000b0b0 f CIL library: CIL module\r
+ 0001:0000a0c0 ?catch$0@?0???0?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAA@AEBV01@@Z@4HA 000000014000b0c0 f CIL library: CIL module\r
+ 0001:0000a0cd __catch$??0?$list@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAA@AEBV01@@Z$0 000000014000b0cd f CIL library: CIL module\r
+ 0001:0000a0e0 ?catch$0@?0??_Buynode@?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@2@PEAU342@0AEBQEAUWindowsTimerQueueHandlerArg@@@Z@4HA 000000014000b0e0 f CIL library: CIL module\r
+ 0001:0000a0e0 ?catch$0@?0??_Buynode@?$_List_val@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@2@PEAU342@0AEBQEAVPTPMessageAnnounce@@@Z@4HA 000000014000b0e0 f CIL library: CIL module\r
+ 0001:0000a0ed __catch$?_Buynode@?$_List_val@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAVPTPMessageAnnounce@@V?$allocator@PEAVPTPMessageAnnounce@@@std@@@2@PEAU342@0AEBQEAVPTPMessageAnnounce@@@Z$0 000000014000b0ed f CIL library: CIL module\r
+ 0001:0000a0ed __catch$?_Buynode@?$_List_val@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@std@@QEAAPEAU_Node@?$_List_nod@PEAUWindowsTimerQueueHandlerArg@@V?$allocator@PEAUWindowsTimerQueueHandlerArg@@@std@@@2@PEAU342@0AEBQEAUWindowsTimerQueueHandlerArg@@@Z$0 000000014000b0ed f CIL library: CIL module\r
+ 0001:0000a110 ?dtor$0@?0???0PTPMessagePathDelayResp@@QEAA@PEAVIEEE1588Port@@@Z@4HA 000000014000b110 f CIL library: CIL module\r
+ 0001:0000a110 ?dtor$0@?0???0PTPMessageAnnounce@@QEAA@PEAVIEEE1588Port@@@Z@4HA 000000014000b110 f CIL library: CIL module\r
+ 0001:0000a110 ?dtor$0@?0???0PTPMessagePathDelayRespFollowUp@@QEAA@PEAVIEEE1588Port@@@Z@4HA 000000014000b110 f CIL library: CIL module\r
+ 0001:0000a120 ?catch$0@?0???$_Buynode@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@1@@Z@4HA 000000014000b120 f CIL library: CIL module\r
+ 0001:0000a12d __catch$??$_Buynode@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@?$_Tree_val@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@1@@Z$0 000000014000b12d f CIL library: CIL module\r
+ 0001:0000a150 ?catch$0@?0???$_Buynode@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@1@@Z@4HA 000000014000b150 f CIL library: CIL module\r
+ 0001:0000a15d __catch$??$_Buynode@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@?$_Tree_val@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@$0A@@std@@@1@$$QEAU?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@1@@Z$0 000000014000b15d f CIL library: CIL module\r
+ 0001:0000a180 ?dtor$0@?0???$_Buynode@U?$pair@$$CBHUTimerQueue_t@@@std@@@?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@1@$$QEAU?$pair@$$CBHUTimerQueue_t@@@1@@Z@4HA 000000014000b180 f CIL library: CIL module\r
+ 0001:0000a1a0 ?catch$0@?0???$_Buynode@U?$pair@$$CBHUTimerQueue_t@@@std@@@?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@1@$$QEAU?$pair@$$CBHUTimerQueue_t@@@1@@Z@4HA 000000014000b1a0 f CIL library: CIL module\r
+ 0001:0000a1ad __catch$??$_Buynode@U?$pair@$$CBHUTimerQueue_t@@@std@@@?$_Tree_val@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@std@@QEAAPEAU_Node@?$_Tree_nod@V?$_Tmap_traits@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@$0A@@std@@@1@$$QEAU?$pair@$$CBHUTimerQueue_t@@@1@@Z$0 000000014000b1ad f CIL library: CIL module\r
+ 0001:0000a1d0 ?dtor$1@?0???1?$map@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@@std@@QEAA@XZ@4HA 000000014000b1d0 f CIL library: CIL module\r
+ 0001:0000a1d0 ?dtor$1@?0???1?$map@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@@std@@QEAA@XZ@4HA 000000014000b1d0 f CIL library: CIL module\r
+ 0001:0000a1e0 ?dtor$0@?0???0WindowsTimerQueue@@IEAA@XZ@4HA 000000014000b1e0 f CIL library: CIL module\r
+ 0001:0000a1f0 ?dtor$0@?0???A?$map@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@@std@@QEAAAEAVLinkLayerAddress@@AEBVPortIdentity@@@Z@4HA 000000014000b1f0 f CIL library: CIL module\r
+ 0001:0000a200 ?dtor$1@?0???A?$map@VPortIdentity@@VLinkLayerAddress@@U?$less@VPortIdentity@@@std@@V?$allocator@U?$pair@$$CBVPortIdentity@@VLinkLayerAddress@@@std@@@4@@std@@QEAAAEAVLinkLayerAddress@@AEBVPortIdentity@@@Z@4HA 000000014000b200 f CIL library: CIL module\r
+ 0001:0000a210 ?dtor$0@?0???0IEEE1588Port@@QEAA@PEAVIEEE1588Clock@@G_NPEAVHWTimestamper@@1HPEAVInterfaceLabel@@PEAVOSConditionFactory@@PEAVOSThreadFactory@@PEAVOSTimerFactory@@PEAVOSLockFactory@@@Z@4HA 000000014000b210 f CIL library: CIL module\r
+ 0001:0000a220 ?dtor$1@?0???0IEEE1588Port@@QEAA@PEAVIEEE1588Clock@@G_NPEAVHWTimestamper@@1HPEAVInterfaceLabel@@PEAVOSConditionFactory@@PEAVOSThreadFactory@@PEAVOSTimerFactory@@PEAVOSLockFactory@@@Z@4HA 000000014000b220 f CIL library: CIL module\r
+ 0001:0000a240 ?dtor$2@?0???0IEEE1588Port@@QEAA@PEAVIEEE1588Clock@@G_NPEAVHWTimestamper@@1HPEAVInterfaceLabel@@PEAVOSConditionFactory@@PEAVOSThreadFactory@@PEAVOSTimerFactory@@PEAVOSLockFactory@@@Z@4HA 000000014000b240 f CIL library: CIL module\r
+ 0001:0000a260 ?dtor$0@?0???A?$map@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@@std@@QEAAAEAUTimerQueue_t@@AEBH@Z@4HA 000000014000b260 f CIL library: CIL module\r
+ 0001:0000a270 ?dtor$1@?0???A?$map@HUTimerQueue_t@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHUTimerQueue_t@@@std@@@3@@std@@QEAAAEAUTimerQueue_t@@AEBH@Z@4HA 000000014000b270 f CIL library: CIL module\r
+ 0001:0000a280 ?dtor$0@?0??createOSTimerQueue@WindowsTimerQueueFactory@@UEAAPEAVOSTimerQueue@@XZ@4HA 000000014000b280 f CIL library: CIL module\r
+ 0001:0000a290 ?dtor$8@?0??buildPTPMessage@@YAPEAVPTPMessageCommon@@PEADHPEAVLinkLayerAddress@@PEAVIEEE1588Port@@@Z@4HA 000000014000b290 f CIL library: CIL module\r
+ 0001:0000a2a0 ?dtor$10@?0??buildPTPMessage@@YAPEAVPTPMessageCommon@@PEADHPEAVLinkLayerAddress@@PEAVIEEE1588Port@@@Z@4HA 000000014000b2a0 f CIL library: CIL module\r
+ 0001:0000a2b0 ?dtor$0@?0??openPort@IEEE1588Port@@QEAAPEAXXZ@4HA 000000014000b2b0 f CIL library: CIL module\r
+ 0001:0000a2c0 ?dtor$0@?0??processMessage@PTPMessagePathDelayReq@@UEAAXPEAVIEEE1588Port@@@Z@4HA 000000014000b2c0 f CIL library: CIL module\r
+ 0001:0000a2d0 ?dtor$1@?0??processMessage@PTPMessagePathDelayReq@@UEAAXPEAVIEEE1588Port@@@Z@4HA 000000014000b2d0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessagePathDelayReq@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessagePathDelayResp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessagePathDelayRespFollowUp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessageAnnounce@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessageFollowUp@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2e0 ?dtor$0@?0??sendPort@PTPMessageSync@@QEAAXPEAVIEEE1588Port@@PEAVPortIdentity@@@Z@4HA 000000014000b2e0 f CIL library: CIL module\r
+ 0001:0000a2f0 ?dtor$0@?0??processEvent@IEEE1588Port@@QEAAXW4Event@@@Z@4HA 000000014000b2f0 f CIL library: CIL module\r
+ 0001:0000a300 ?dtor$1@?0??processEvent@IEEE1588Port@@QEAAXW4Event@@@Z@4HA 000000014000b300 f CIL library: CIL module\r
+ 0001:0000a310 ?dtor$2@?0??processEvent@IEEE1588Port@@QEAAXW4Event@@@Z@4HA 000000014000b310 f CIL library: CIL module\r
+ 0001:0000a320 ?dtor$3@?0??processEvent@IEEE1588Port@@QEAAXW4Event@@@Z@4HA 000000014000b320 f CIL library: CIL module\r
+ 0001:0000a330 main$dtor$1 000000014000b330 f CIL library: CIL module\r
+ 0001:0000a340 main$dtor$2 000000014000b340 f CIL library: CIL module\r
+ 0001:0000a350 main$dtor$3 000000014000b350 f CIL library: CIL module\r
+ 0001:0000a360 ?dtor$1@?0???__F?factoryMap@OSNetworkInterfaceFactory@@0V?$map@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@@std@@A@@YAXXZ@4HA 000000014000b360 f CIL library: CIL module\r
+ 0001:0000a370 ??__E?factoryMap@OSNetworkInterfaceFactory@@0V?$map@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@@std@@A@@YAXXZ 000000014000b370 f CIL library: CIL module\r
+ 0001:0000a390 ??__E?other_multicast@IEEE1588Port@@0VLinkLayerAddress@@A@@YAXXZ 000000014000b390 f CIL library: CIL module\r
+ 0001:0000a3e0 ??__E?pdelay_multicast@IEEE1588Port@@0VLinkLayerAddress@@A@@YAXXZ 000000014000b3e0 f CIL library: CIL module\r
+ 0001:0000a430 ??__F?factoryMap@OSNetworkInterfaceFactory@@0V?$map@Vfactory_name_t@@PEAVOSNetworkInterfaceFactory@@U?$less@Vfactory_name_t@@@std@@V?$allocator@U?$pair@$$CBVfactory_name_t@@PEAVOSNetworkInterfaceFactory@@@std@@@4@@std@@A@@YAXXZ 000000014000b430 f CIL library: CIL module\r
+ 0001:0000a470 ??__F?other_multicast@IEEE1588Port@@0VLinkLayerAddress@@A@@YAXXZ 000000014000b470 f CIL library: CIL module\r
+ 0001:0000a480 ??__F?pdelay_multicast@IEEE1588Port@@0VLinkLayerAddress@@A@@YAXXZ 000000014000b480 f CIL library: CIL module\r
--- /dev/null
+INTRODUCTION
+
+The MRP daemon is required to establish stream reservations with compatible AVB
+infrastructure devices. The command line selectively enables MMRP (via the
+-m option), MVRP (via the -v option), and MSRP (via the -s option). You must
+also specify the interface on which you want to bind the daemon to
+(e.g. -i eth2). The full command line typically appears as follows:
+ sudo ./mrpd -mvs -i eth2
+
+Sample client applications - mrpctl, mrpq, mrpl - illustrate how to connect,
+query and add attributes to the MRP daemon.
+++ /dev/null
-OPT=-O2
-#CFLAGS=$(OPT) -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -ggdb
-CFLAGS=$(OPT) -Wall -W -Wno-parentheses -ggdb
-
-CC=gcc
-INCFLAGS=-I../lib
-LDLIBS=-ligb -lpci -lz -pthread
-LDFLAGS=-L../lib
-
-all: test latency_test simple_talker mrpq mrpl
-
-test: test.o
-
-simple_talker: simple_talker.o
-
-mrpl: mrpl.o
-
-mrpq: mrpq.o
-
-latency_test: latency_test.o
-
-latency_test.o: latency_test.c
- gcc -c $(INCFLAGS) $(CFLAGS) latency_test.c
-
-test.o: test.c
- gcc -c $(INCFLAGS) $(CFLAGS) test.c
-
-simple_talker.o: simple_talker.c
- gcc -c $(INCFLAGS) -I../daemons/mrpd $(CFLAGS) simple_talker.c
-
-mrpl.o: mrpl.c
- gcc -c $(INCFLAGS) -I../daemons/mrpd $(CFLAGS) mrpl.c
-
-mrpq.o: mrpq.c
- gcc -c $(INCFLAGS) -I../daemons/mrpd $(CFLAGS) mrpq.c
-
-%: %.o
- $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
-
-clean:
- rm -f `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"`
-
+++ /dev/null
-/******************************************************************************
-
- Copyright (c) 2001-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 <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <signal.h>
-#include <errno.h>
-
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-
-#include <sys/un.h>
-
-#include <pci/pci.h>
-
-#include "igb.h"
-
-#define IGB_BIND_NAMESZ 24
-
-device_t igb_dev;
-volatile int halt_tx;
-
-void
-sigint_handler (int signum)
-{
- printf("halting ...\n");
- halt_tx = signum;
-}
-
-int
-connect()
-{
- struct pci_access *pacc;
- struct pci_dev *dev;
- int err;
- char devpath[IGB_BIND_NAMESZ];
-
- memset(&igb_dev, 0, sizeof(device_t));
-
- pacc = pci_alloc();
- pci_init(pacc);
- pci_scan_bus(pacc);
- for (dev=pacc->devices; dev; dev=dev->next)
- {
- pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);
-
- igb_dev.pci_vendor_id = dev->vendor_id;
- igb_dev.pci_device_id = dev->device_id;
- igb_dev.domain = dev->domain;
- igb_dev.bus = dev->bus;
- igb_dev.dev = dev->dev;
- igb_dev.func = dev->func;
-
- snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d", \
- dev->domain, dev->bus, dev->dev, dev->func );
- printf("probing %s\n", devpath);
-
- err = igb_probe(&igb_dev);
-
- if (err) {
- continue;
- }
-
- printf ("attaching to %s\n", devpath);
- err = igb_attach(devpath, &igb_dev);
-
- if (err) {
- printf ("attach failed! (%s)\n", strerror(errno));
- continue;
- }
- printf("attach successful to %s\n", devpath);
- goto out;
- }
-
- pci_cleanup(pacc);
- return ENXIO;
-
-out:
- pci_cleanup(pacc);
- return 0;
-
-}
-
-#define VERSION_STR "1.0"
-
-static const char *version_str =
-"latency test v" VERSION_STR "\n"
-"Copyright (c) 2012, Intel Corporation\n";
-
-
-static void
-usage( void ) {
- fprintf(stderr,
- "\n"
- "usage: latency_test [-hr] [-d <obs>]"
- "\n"
- "options:\n"
- " -h show this message\n"
- " -d observation window (seconds)\n"
- " -p delay from sw schedule to hw transmit in usec (defaults to 20 msec)\n"
- "\n"
- "%s"
- "\n", version_str);
- exit(1);
-}
-
-#define PACKET_IPG (20000000) /* 20 msec */
-
-int
-main(int argc, char *argv[]) {
- int c;
- unsigned i;
- unsigned tqavctl;
- int err;
- struct igb_dma_alloc a_page;
- struct igb_packet a_packet;
- struct igb_packet *tmp_packet;
- struct igb_packet *cleaned_packets;
- struct igb_packet *free_packets;
- u_int64_t last_time;
- u_int64_t rdtsc0;
- unsigned int captured_latency;
- int obs_window = 1;
- int obs_window_count;
- int ipg = PACKET_IPG / 1000;
-
- unsigned int min = 0xFFFFFFFF;
- unsigned int max = 0;
- float avg = 0.0;
-
- for (;;) {
- c = getopt(argc, argv, "hrp:d:");
-
- if (c < 0)
- break;
-
- switch (c) {
- default:
- case 'h':
- usage();
- break;
- case 'p':
- sscanf(optarg, "%d", &ipg);
- break;
- case 'd':
- sscanf(optarg, "%d", &obs_window);
- break;
- }
- }
- if (optind < argc)
- usage();
-
- ipg *= 1000; /* scale to nsec */
-
- if (ipg > 400000000) { printf("specified delay is too large \n"); return(-1); }
-
- err = connect();
-
- if (err) { printf("connect failed (%s)\n", strerror(errno)); return(errno); }
-
- err = igb_init(&igb_dev);
-
- if (err) { printf("init failed (%s)\n", strerror(errno)); return(errno); }
-
- err = igb_dma_malloc_page(&igb_dev, &a_page);
-
- if (err) { printf("malloc failed (%s)\n", strerror(errno)); return(errno); }
-
-#define PKT_SZ 200
- memset(&a_packet, 0, sizeof(a_packet));
-
- a_packet.dmatime = a_packet.attime = a_packet.flags = 0;
- a_packet.map.paddr = a_page.dma_paddr;
- a_packet.map.mmap_size = a_page.mmap_size;
-
- a_packet.offset = 0;
- a_packet.vaddr = a_page.dma_vaddr + a_packet.offset;
- a_packet.len = PKT_SZ;
-
- free_packets = NULL;
-
- /* divide the dma page into buffers for packets */
- for (i = 1; i < ((a_page.mmap_size) / PKT_SZ); i++) {
- tmp_packet = malloc(sizeof(struct igb_packet));
- if (NULL == tmp_packet) { printf("malloc failed (%s)\n", strerror(errno)); return(errno); }
- *tmp_packet = a_packet;
- tmp_packet->offset = (i * PKT_SZ);
- tmp_packet->vaddr += tmp_packet->offset;
- tmp_packet->next = free_packets;
- memset(tmp_packet->vaddr, 0xffffffff, PKT_SZ); /* MAC header at least */
- free_packets = tmp_packet;
- }
-
- igb_set_class_bandwidth(&igb_dev, 0, 0, 0); /* disable Qav */
- igb_readreg(&igb_dev, 0x3570, &tqavctl);
- tqavctl &= 0xFFFF; /* zero-out the prefetch delay */
- igb_writereg(&igb_dev, 0x3570, tqavctl);
-
- halt_tx = 0;
- signal(SIGINT, sigint_handler);
-
-
- igb_get_wallclock(&igb_dev, &last_time, &rdtsc0);
-
- obs_window_count = obs_window;
-
- while (!halt_tx) {
- tmp_packet = free_packets;
-
- if (NULL == tmp_packet) goto cleanup;
-
- free_packets = tmp_packet->next;
-
- igb_get_wallclock(&igb_dev, &last_time, &rdtsc0);
-
- tmp_packet->attime = last_time + ipg;
- *(u_int64_t *)(tmp_packet->vaddr + 32) = tmp_packet->attime;
-
- err = igb_xmit(&igb_dev, 0, tmp_packet);
-
- if (ENOSPC == err) {
- /* put back for now */
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
-
- sleep(1); /* sleep 1 sec */
-
-cleanup:
- igb_clean(&igb_dev, &cleaned_packets);
- i = 0;
- while (cleaned_packets) {
- i++;
- tmp_packet = cleaned_packets;
- cleaned_packets = cleaned_packets->next;
- /* remap attime to compare to dma time */
- while (tmp_packet->attime > 999999999) tmp_packet->attime -= 1000000000;
- if ((tmp_packet->attime > 999000000) && (tmp_packet->dmatime < 1000000))
- captured_latency = (unsigned int)(1000000000 - tmp_packet->attime + tmp_packet->dmatime);
- else
- captured_latency = (unsigned int)(tmp_packet->dmatime - tmp_packet->attime);
-
- if (captured_latency < min)
- min = captured_latency;
-
- if (captured_latency > max)
- max = captured_latency;
-
- avg += ((float)captured_latency / (float)obs_window);
-
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
- obs_window_count--;
- if (0 == obs_window_count) {
- obs_window_count = obs_window;
- printf("min = %d max = %d avg = %f\n", min, max, avg);
- min = 0xFFFFFFFF;
- max = 0;
- avg = 0.0;
- }
-
- }
-
- igb_dma_free_page(&igb_dev, &a_page);
- err = igb_detach(&igb_dev);
- return(0);
-}
-
--- /dev/null
+OPT=-O2
+CFLAGS=$(OPT) -Wall -W -Wno-parentheses -ggdb
+
+CC=gcc
+INCFLAGS=-I../../lib/igb
+LDLIBS=-ligb -lpci -lz -pthread
+LDFLAGS=-L../../lib/igb
+
+all: mrpq mrpl
+
+mrpl: mrpl.o
+
+mrpq: mrpq.o
+
+mrpl.o: mrpl.c
+ gcc -c $(INCFLAGS) -I../../daemons/mrpd $(CFLAGS) mrpl.c
+
+mrpq.o: mrpq.c
+ gcc -c $(INCFLAGS) -I../../daemons/mrpd $(CFLAGS) mrpq.c
+
+%: %.o
+ $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+clean:
+ rm -f `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` mrpl mrpq
+
+++ /dev/null
-/******************************************************************************
-
- Copyright (c) 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 <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#include <pci/pci.h>
-#include <sys/socket.h>
-#include <linux/if.h>
-#include <netpacket/packet.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/ethernet.h>
-#include <sys/un.h>
-#include <pthread.h>
-#include <poll.h>
-
-#include "igb.h"
-#include "mrpd.h"
-
-#define IGB_BIND_NAMESZ 24
-
-/* global variables */
-int control_socket = -1;
-device_t igb_dev;
-volatile int halt_tx = 0;
-volatile int listeners = 0;
-volatile int mrp_okay;
-volatile int mrp_error = 0;;
-volatile int domain_a_valid = 0;
-int domain_class_a_id;
-int domain_class_a_priority;
-int domain_class_a_vid;
-volatile int domain_b_valid = 0;
-int domain_class_b_id;
-int domain_class_b_priority;
-int domain_class_b_vid;
-
-#define VERSION_STR "1.0"
-
-static const char *version_str =
-"simple_talker v" VERSION_STR "\n"
-"Copyright (c) 2012, Intel Corporation\n";
-
-#define MRPD_PORT_DEFAULT 7500
-
-int mrp_join_listener(uint8_t *streamid);
-
-int
-send_mrp_msg( char *notify_data, int notify_len) {
- struct sockaddr_in addr;
- socklen_t addr_len;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(MRPD_PORT_DEFAULT);
- inet_aton("127.0.0.1", &addr.sin_addr);
- addr_len = sizeof(addr);
-
- if (control_socket != -1)
- return(sendto(control_socket, notify_data, notify_len, 0, (struct sockaddr *)&addr, addr_len));
- else
- return(0);
-}
-
-int
-mrp_connect() {
- struct sockaddr_in addr;
- int sock_fd = -1;
-
- sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock_fd < 0)
- goto out;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(MRPD_PORT_DEFAULT);
- inet_aton("127.0.0.1", &addr.sin_addr);
-
- memset(&addr, 0, sizeof(addr));
-
- control_socket = sock_fd;
-
- return(0);
-out:
- if (sock_fd != -1) close(sock_fd);
- sock_fd = -1;
- return(-1);
-}
-
-int
-mrp_disconnect() {
- char *msgbuf;
- int rc;
-
- msgbuf = malloc(64);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,64);
- sprintf(msgbuf,"BYE");
- mrp_okay = 0;
- rc = send_mrp_msg(msgbuf, 1500);
- /* rc = recv_mrp_okay(); */
- free(msgbuf);
- return rc;
-}
-
-
-int
-recv_mrp_okay() {
- while ((mrp_okay == 0) && (mrp_error == 0))
- usleep(20000);
- return 0;
-}
-
-int mrp_register_domain(int *class_id, int *priority, u_int16_t *vid) {
- char *msgbuf;
- int rc;
- msgbuf = malloc(64);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,64);
- sprintf(msgbuf,"S+D:C:%d:P:%d:V:%04x",
- *class_id,
- *priority,
- *vid);
-
- mrp_okay = 0;
- rc = send_mrp_msg(msgbuf, 1500);
- /* rc = recv_mrp_okay(); */
- free(msgbuf);
- return rc;
-
-}
-
-int mrp_get_domain(int *class_a_id, int *a_priority, u_int16_t *a_vid, \
- int *class_b_id, int *b_priority, u_int16_t *b_vid ) {
- char *msgbuf;
-
- /* we may not get a notification if we are joining late,
- * so query for what is already there ...
- */
- msgbuf = malloc(64);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,64);
- sprintf(msgbuf,"S??");
- send_mrp_msg(msgbuf, 64);
- free(msgbuf);
-
- while (!halt_tx && (domain_a_valid == 0) && (domain_b_valid == 0))
- usleep(20000);
-
- *class_a_id = 0;
- *a_priority = 0;
- *a_vid = 0;
- *class_b_id = 0;
- *b_priority = 0;
- *b_vid = 0;
-
- if (domain_a_valid) {
- *class_a_id = domain_class_a_id;
- *a_priority = domain_class_a_priority;
- *a_vid = domain_class_a_vid;
- }
- if (domain_b_valid) {
- *class_b_id = domain_class_b_id;
- *b_priority = domain_class_b_priority;
- *b_vid = domain_class_b_vid;
- }
-
- return(0);
-}
-
-unsigned char monitor_stream_id[] = {0,0,0,0,0,0,0,0};
-
-int
-mrp_await_listener(unsigned char *streamid) {
- char *msgbuf;
-
- memcpy(monitor_stream_id, streamid, sizeof(monitor_stream_id));
-
- msgbuf = malloc(64);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,64);
- sprintf(msgbuf,"S??");
- send_mrp_msg(msgbuf, 64);
- free(msgbuf);
-
- /* either already there ... or need to wait ... */
- while (!halt_tx && (listeners == 0))
- usleep(20000);
-
- return(0);
-}
-
-int
-process_mrp_msg(char *buf, int buflen) {
-
- /*
- * 1st character indicates application
- * [MVS] - MAC, VLAN or STREAM
- */
- unsigned int id;
- unsigned int priority;
- unsigned int vid;
- int i,j,k;
- unsigned int substate;
- unsigned char recovered_streamid[8];
- k = 0;
-
-next_line:
- if (k >= buflen)
- return(0);
-
- switch (buf[k]) {
- case 'E':
- printf("%s from mrpd\n", buf);
- fflush(stdout);
- mrp_error = 1;
- break;
- case 'O':
- mrp_okay = 1;
- break;
- case 'M':
- case 'V':
- printf("%s unhandled from mrpd\n", buf);
- fflush(stdout);
- /* unhandled for now */
- break;
- case 'L':
- /* parse a listener attribute - see if it matches our monitor_stream_id */
- i = k;
- while (buf[i] != 'D')
- i++;
- i+=2; /* skip the ':' */
- sscanf(&(buf[i]),"%d",&substate);
-
- while (buf[i] != 'S')
- i++;
- i+=2; /* skip the ':' */
-
- for (j = 0; j < 8; j++) {
- sscanf(&(buf[i+2*j]),"%02x",&id);
- recovered_streamid[j] = (unsigned char)id;
- }
-
- printf("FOUND STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
- recovered_streamid[0],
- recovered_streamid[1],
- recovered_streamid[2],
- recovered_streamid[3],
- recovered_streamid[4],
- recovered_streamid[5],
- recovered_streamid[6],
- recovered_streamid[7]);
-
- switch (substate) {
- case 0:
- printf("with state ignore\n");
- break;
- case 1:
- printf("with state askfailed\n");
- break;
- case 2:
- printf("with state ready\n");
- break;
- case 3:
- printf("with state readyfail\n");
- break;
- default:
- printf("with state UNKNOWN (%d)\n", substate);
- break;
- }
-
- if (substate > MSRP_LISTENER_ASKFAILED) {
- if (memcmp(recovered_streamid, monitor_stream_id, sizeof(recovered_streamid)) == 0) {
- mrp_join_listener(recovered_streamid);
- listeners = 1;
- printf("added listener\n");
- }
- }
- fflush(stdout);
-
- /* try to find a newline ... */
- while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
- i++;
-
- if (i == buflen)
- return(0);
- if (buf[i] == '\0')
- return(0);
-
- i++;
- k = i;
- goto next_line;
- break;
- case 'D':
- i = k+4;
- /* save the domain attribute */
- sscanf(&(buf[i]),"%d",&id);
- while (buf[i] != 'P')
- i++;
- i+=2; /* skip the ':' */
- sscanf(&(buf[i]),"%d",&priority);
- while (buf[i] != 'V')
- i++;
- i+=2; /* skip the ':' */
- sscanf(&(buf[i]),"%x",&vid);
- if (id == 6) {
- domain_class_a_id = id;
- domain_class_a_priority = priority;
- domain_class_a_vid = vid;
- domain_a_valid = 1;
- } else {
- domain_class_b_id = id;
- domain_class_b_priority = priority;
- domain_class_b_vid = vid;
- domain_b_valid = 1;
- }
- while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
- i++;
-
- if ((i == buflen) || (buf[i] == '\0'))
- return(0);
- i++;
- k = i;
- goto next_line;
- break;
- case 'T':
- /* as simple_talker we don't care about other talkers */
- i = k;
- while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
- i++;
- if (i == buflen)
- return(0);
- if (buf[i] == '\0')
- return(0);
-
- i++;
- k = i;
- goto next_line;
- break;
- case 'S':
- /* handle the leave/join events */
- switch (buf[k+4]) {
- case 'L':
- i = k+5;
- while (buf[i] != 'D')
- i++;
- i+=2; /* skip the ':' */
- sscanf(&(buf[i]),"%d",&substate);
-
- while (buf[i] != 'S')
- i++;
- i+=2; /* skip the ':' */
-
- for (j = 0; j < 8; j++) {
- sscanf(&(buf[i+2*j]),"%02x",&id);
- recovered_streamid[j] = (unsigned char)id;
- }
-
- printf("EVENT on STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
- recovered_streamid[0],
- recovered_streamid[1],
- recovered_streamid[2],
- recovered_streamid[3],
- recovered_streamid[4],
- recovered_streamid[5],
- recovered_streamid[6],
- recovered_streamid[7]);
-
- switch (substate) {
- case 0:
- printf("with state ignore\n");
- break;
- case 1:
- printf("with state askfailed\n");
- break;
- case 2:
- printf("with state ready\n");
- break;
- case 3:
- printf("with state readyfail\n");
- break;
- default:
- printf("with state UNKNOWN (%d)\n", substate);
- break;
- }
-
-
- switch (buf[k+1]) {
- case 'L':
- printf("got a leave indication\n");
- if (memcmp(recovered_streamid, monitor_stream_id, sizeof(recovered_streamid)) == 0) {
- listeners = 0;
- printf("listener left\n");
- }
- break;
- case 'J':
- case 'N':
- printf("got a new/join indication\n");
- if (substate > MSRP_LISTENER_ASKFAILED) {
- if (memcmp(recovered_streamid, monitor_stream_id, sizeof(recovered_streamid)) == 0)
- mrp_join_listener(recovered_streamid);
- listeners = 1;
- }
- break;
- }
- /* only care about listeners ... */
- default:
- return(0);
- break;
- }
- break;
- case '\0':
- break;
- }
- return(0);
-}
-
-
-void *
-mrp_monitor_thread(void *arg) {
- char *msgbuf;
- struct sockaddr_in client_addr;
- struct msghdr msg;
- struct iovec iov;
- int bytes = 0;
- struct pollfd fds;
- int rc;
-
- if (NULL == arg)
- rc = 0;
- else
- rc = 1;
-
- msgbuf = (char *)malloc (MAX_MRPD_CMDSZ);
- if (NULL == msgbuf)
- return NULL;
- while (!halt_tx) {
- fds.fd = control_socket;
- fds.events = POLLIN;
- fds.revents = 0;
- rc = poll(&fds, 1, 100);
- if (rc < 0) {
- free (msgbuf);
- pthread_exit(NULL);
- }
- if (rc == 0)
- continue;
- if ((fds.revents & POLLIN) == 0) {
- free (msgbuf);
- pthread_exit(NULL);
- }
-
- memset(&msg, 0, sizeof(msg));
- memset(&client_addr, 0, sizeof(client_addr));
- memset(msgbuf, 0, MAX_MRPD_CMDSZ);
-
- iov.iov_len = MAX_MRPD_CMDSZ;
- iov.iov_base = msgbuf;
- msg.msg_name = &client_addr;
- msg.msg_namelen = sizeof(client_addr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- bytes = recvmsg(control_socket, &msg, 0);
- if (bytes < 0)
- continue;
-
- process_mrp_msg(msgbuf, bytes);
- }
- free (msgbuf);
-
- pthread_exit(NULL);
-}
-
-pthread_t monitor_thread;
-pthread_attr_t monitor_attr;
-
-int
-mrp_monitor() {
- pthread_attr_init(&monitor_attr);
- pthread_create(&monitor_thread, NULL, mrp_monitor_thread, NULL);
-
- return(0);
-}
-
-int
-mrp_join_listener(uint8_t *streamid) {
- char *msgbuf;
- int rc;
-
- msgbuf = malloc(1500);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,1500);
- sprintf(msgbuf,"S+L:%02X%02X%02X%02X%02X%02X%02X%02X"
- ":D:2",
- streamid[0],
- streamid[1],
- streamid[2],
- streamid[3],
- streamid[4],
- streamid[5],
- streamid[6],
- streamid[7]);
-
- mrp_okay = 0;
- rc = send_mrp_msg(msgbuf, 1500);
- /* rc = recv_mrp_okay(); */
- free(msgbuf);
- return rc;
-}
-
-int
-mrp_advertise_stream(
- uint8_t *streamid,
- uint8_t *destaddr,
- u_int16_t vlan,
- int pktsz,
- int interval,
- int priority,
- int latency) {
- char *msgbuf;
- int rc;
-
- msgbuf = malloc(1500);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,1500);
- sprintf(msgbuf,"S++S:%02X%02X%02X%02X%02X%02X%02X%02X"
- ":A:%02X%02X%02X%02X%02X%02X"
- ":V:%04X"
- ":Z:%d"
- ":I:%d"
- ":P:%d"
- ":L:%d",
- streamid[0],
- streamid[1],
- streamid[2],
- streamid[3],
- streamid[4],
- streamid[5],
- streamid[6],
- streamid[7],
- destaddr[0],
- destaddr[1],
- destaddr[2],
- destaddr[3],
- destaddr[4],
- destaddr[5],
- vlan,
- pktsz,
- interval,
- priority << 5,
- latency);
-
- mrp_okay = 0;
- rc = send_mrp_msg(msgbuf, 1500);
- /* rc = recv_mrp_okay(); */
- free(msgbuf);
- return rc;
-}
-
-int
-mrp_unadvertise_stream(
- uint8_t *streamid,
- uint8_t *destaddr,
- u_int16_t vlan,
- int pktsz,
- int interval,
- int priority,
- int latency) {
- char *msgbuf;
- int rc;
-
- msgbuf = malloc(1500);
- if (NULL == msgbuf)
- return -1;
-
- memset(msgbuf,0,1500);
- sprintf(msgbuf,"S--S:%02X%02X%02X%02X%02X%02X%02X%02X"
- ":A:%02X%02X%02X%02X%02X%02X"
- ":V:%04X"
- ":Z:%d"
- ":I:%d"
- ":P:%d"
- ":L:%d",
- streamid[0],
- streamid[1],
- streamid[2],
- streamid[3],
- streamid[4],
- streamid[5],
- streamid[6],
- streamid[7],
- destaddr[0],
- destaddr[1],
- destaddr[2],
- destaddr[3],
- destaddr[4],
- destaddr[5],
- vlan,
- pktsz,
- interval,
- priority << 5,
- latency);
-
- mrp_okay = 0;
- rc = send_mrp_msg(msgbuf, 1500);
- /* rc = recv_mrp_okay(); */
- free(msgbuf);
- return rc;
-}
-
-void
-sigint_handler (int signum)
-{
- printf("got SIGINT\n");
- halt_tx = signum;
-}
-
-int
-pci_connect()
-{
- struct pci_access *pacc;
- struct pci_dev *dev;
- int err;
- char devpath[IGB_BIND_NAMESZ];
-
- memset(&igb_dev, 0, sizeof(device_t));
-
- pacc = pci_alloc();
- pci_init(pacc);
- pci_scan_bus(pacc);
- for (dev=pacc->devices; dev; dev=dev->next)
- {
- pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);
-
- igb_dev.pci_vendor_id = dev->vendor_id;
- igb_dev.pci_device_id = dev->device_id;
- igb_dev.domain = dev->domain;
- igb_dev.bus = dev->bus;
- igb_dev.dev = dev->dev;
- igb_dev.func = dev->func;
-
- snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d", \
- dev->domain, dev->bus, dev->dev, dev->func );
-
- err = igb_probe(&igb_dev);
-
- if (err) {
- continue;
- }
-
- printf ("attaching to %s\n", devpath);
- err = igb_attach(devpath, &igb_dev);
-
- if (err) {
- printf ("attach failed! (%s)\n", strerror(errno));
- continue;
- }
- goto out;
- }
-
- pci_cleanup(pacc);
- return ENXIO;
-
-out:
- pci_cleanup(pacc);
- return 0;
-
-}
-
-unsigned char STATION_ADDR[] = {0,0,0,0,0,0};
-unsigned char STREAM_ID[] = {0,0,0,0,0,0,0,0};
-unsigned char DEST_ADDR[] = {0x91, 0xE0, 0xF0, 0x00, 0x00, 0x00}; /* IEEE 1722 reserved address */
-
-int
-get_mac_address(char *interface) {
- struct ifreq if_request;
- int lsock;
- int rc;
-
- lsock = socket(PF_PACKET, SOCK_RAW, htons(0x800));
- if (lsock < 0)
- return -1;
-
- memset(&if_request, 0, sizeof(if_request));
-
- strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name));
-
- rc = ioctl(lsock, SIOCGIFHWADDR, &if_request);
- if (rc < 0) {
- close(lsock);
- return -1;
- }
-
- memcpy(STATION_ADDR, if_request.ifr_hwaddr.sa_data, sizeof(STATION_ADDR));
- close(lsock);
- return 0;
-}
-
-static void
-usage( void ) {
- fprintf(stderr,
- "\n"
- "usage: simple_talker [-h] -i interface-name"
- "\n"
- "options:\n"
- " -h show this message\n"
- " -i specify interface for AVB connection\n"
- "\n"
- "%s"
- "\n", version_str);
- exit(1);
-}
-
-#define PACKET_IPG (125000) /* (1) packet every 125 msec */
-
-int
-main(int argc, char *argv[]) {
- unsigned i;
- int err;
- struct igb_dma_alloc a_page;
- struct igb_packet a_packet;
- struct igb_packet *tmp_packet;
- struct igb_packet *cleaned_packets;
- struct igb_packet *free_packets;
- int c;
- u_int64_t last_time;
- u_int64_t rdtsc0;
- int rc = 0;
- char *interface = NULL;
- int class_a_id = 0;
- int a_priority = 0;
- u_int16_t a_vid = 0;
- int class_b_id = 0;
- int b_priority = 0;
- u_int16_t b_vid = 0;
-
- for (;;) {
- c = getopt(argc, argv, "hi:");
-
- if (c < 0)
- break;
-
- switch (c) {
- case 'h':
- usage();
- break;
- case 'i':
- if (interface) {
- printf("only one interface per daemon is supported\n");
- usage();
- }
- interface = strdup(optarg);
- break;
- }
- }
- if (optind < argc)
- usage();
-
- if (NULL == interface) {
- usage();
- }
-
- rc = mrp_connect();
- if (rc) {
- printf("socket creation failed\n");
- return(errno);
- }
-
- err = pci_connect();
-
- if (err) {
- printf("connect failed (%s) - are you running as root?\n", strerror(errno));
- return(errno);
- }
-
- err = igb_init(&igb_dev);
-
- if (err) {
- printf("init failed (%s) - is the driver really loaded?\n", strerror(errno));
- return(errno);
- }
-
- err = igb_dma_malloc_page(&igb_dev, &a_page);
-
- if (err) {
- printf("malloc failed (%s) - out of memory?\n", strerror(errno));
- return(errno);
- }
-
- signal(SIGINT, sigint_handler);
-
- rc = get_mac_address(interface);
- if (rc) {
- printf("failed to open interface\n");
- usage();
- }
-
- mrp_monitor();
- mrp_get_domain(&class_a_id, &a_priority, &a_vid, &class_b_id, &b_priority, &b_vid);
-
- printf("detected domain Class A PRIO=%d VID=%04x...\n", a_priority, a_vid);
-
- mrp_register_domain(&class_a_id, &a_priority, &a_vid);
- igb_set_class_bandwidth(&igb_dev, 0, 0, 0); /* xxx Qav */
-
- memset(STREAM_ID, 0, sizeof(STREAM_ID));
-
- memcpy(STREAM_ID, STATION_ADDR, sizeof(STATION_ADDR));
-
-#define PKT_SZ 200
- a_packet.dmatime = a_packet.attime = a_packet.flags = 0;
- a_packet.map.paddr = a_page.dma_paddr;
- a_packet.map.mmap_size = a_page.mmap_size;
-
- a_packet.offset = 0;
- a_packet.vaddr = a_page.dma_vaddr + a_packet.offset;
- a_packet.len = PKT_SZ;
-
- free_packets = NULL;
-
- /* divide the dma page into buffers for packets */
- for (i = 1; i < ((a_page.mmap_size) / PKT_SZ); i++) {
- tmp_packet = malloc(sizeof(struct igb_packet));
- if (NULL == tmp_packet) { printf("failed to allocate igb_packet memory!\n"); return(errno); }
-
- *tmp_packet = a_packet;
- tmp_packet->offset = (i * PKT_SZ);
- tmp_packet->vaddr += tmp_packet->offset;
- tmp_packet->next = free_packets;
- memset(tmp_packet->vaddr, 0, PKT_SZ); /* MAC header at least */
- memcpy(tmp_packet->vaddr, DEST_ADDR, sizeof(DEST_ADDR));
- memcpy(tmp_packet->vaddr+6, STATION_ADDR, sizeof(STATION_ADDR));
- /* Q-tag */
- ((char *)tmp_packet->vaddr)[12] = 0x81;
- ((char *)tmp_packet->vaddr)[13] = 0x00;
- ((char *)tmp_packet->vaddr)[14] = ((a_priority << 13 | a_vid) ) >> 8;
- ((char *)tmp_packet->vaddr)[15] = ((a_priority << 13 | a_vid) ) & 0xFF;
- ((char *)tmp_packet->vaddr)[16] = 0x88; /* experimental etype */
- ((char *)tmp_packet->vaddr)[17] = 0xB5;
- free_packets = tmp_packet;
- }
-
-
- /*
- * subtract 16 bytes for the MAC header/Q-tag - pktsz is limited to the
- * data payload of the ethernet frame .
- *
- * IPG is scaled to the Class (A) observation interval of packets per 125 usec
- */
- printf("advertising stream ...\n");
- mrp_advertise_stream( STREAM_ID, DEST_ADDR, a_vid, PKT_SZ - 16, PACKET_IPG / 125000, a_priority, 3900);
-
- printf("awaiting a listener ...\n");
-
- mrp_await_listener(STREAM_ID);
-
- printf("got a listener ...\n");
-
- halt_tx = 0;
-
- rc = nice(-20);
-
- igb_get_wallclock(&igb_dev, &last_time, &rdtsc0);
-
- while (listeners && !halt_tx) {
- tmp_packet = free_packets;
-
- if (NULL == tmp_packet)
- goto cleanup;
-
- free_packets = tmp_packet->next;
-
- /* unfortuntely unless this thread is at rtprio
- * you get pre-empted between fetching the time
- * and programming the packet and get a late packet
- */
- tmp_packet->attime = last_time + PACKET_IPG;
- *(u_int64_t *)(tmp_packet->vaddr + 32) = tmp_packet->attime;
- err = igb_xmit(&igb_dev, 0, tmp_packet);
-
- if (!err) {
- continue;
- }
-
- if (ENOSPC == err) {
- /* put back for now */
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
-cleanup:
- igb_clean(&igb_dev, &cleaned_packets);
- i = 0;
- while (cleaned_packets) {
- i++;
- tmp_packet = cleaned_packets;
- cleaned_packets = cleaned_packets->next;
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
- }
-
- rc = nice(0);
-
- if (halt_tx == 0)
- printf("listener left ...\n");
-
- halt_tx = 1;
- mrp_unadvertise_stream( STREAM_ID, DEST_ADDR, a_vid, PKT_SZ - 16, PACKET_IPG / 125000, a_priority, 3900);
-
- igb_set_class_bandwidth(&igb_dev, 0, 0, 0); /* disable Qav */
-
- rc = mrp_disconnect();
- igb_dma_free_page(&igb_dev, &a_page);
- err = igb_detach(&igb_dev);
- pthread_exit(NULL);
- return(0);
-}
-
--- /dev/null
+OPT=-O2
+CFLAGS=$(OPT) -Wall -W -Wno-parentheses
+
+CC=gcc
+INCFLAGS=-I../../lib/igb
+LDLIBS=-ligb -lpci -lz -lrt -lm -pthread
+LDFLAGS=-L../../lib/igb
+
+all: simple_talker
+
+simple_talker: simple_talker.o
+
+simple_talker.o: simple_talker.c
+ gcc -c $(INCFLAGS) -I../../daemons/mrpd $(CFLAGS) simple_talker.c
+
+%: %.o
+ $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+clean:
+ rm -f `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` simple_talker
+
--- /dev/null
+EXAMPLE APPLICATIONS
+
+The 'simple_talker' application illustrates the various steps to publish a stream
+and streaming 1722/61883 audio frames after a listener connects. The audio
+itself is a simple sine wave. It has been tested with other vendors listeners
+at AVNu plug-fests.
+
+The simple talker application requires root permissions to execute and
+attach to the driver.
+ sudo ./simple_talker
+
+To exit the app, hit Ctrl-C. The application gracefully tears down
+the connection to the driver. If the application unexpectedly aborts the
+kernel-mode driver also reclaims the various buffers and attempts to clean up.
+The application should be able to re-initialize and use the transmit queues
+without restarting the driver.
+
+Note this application requires using the provided gptp timesync daemon to
+provide the 802.1AS presentation times included in the 1722 frames. This
+application also requires the mrpd daemon to be running to detect and
+establish various stream reservation parameters.
+
--- /dev/null
+/******************************************************************************
+
+ Copyright (c) 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 <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <pci/pci.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <netpacket/packet.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <sys/un.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "igb.h"
+#include "mrpd.h"
+#include <math.h>
+#include <endian.h>
+#include <stdint.h>
+
+typedef struct {
+ int64_t ml_phoffset;
+ int64_t ls_phoffset;
+ int32_t ml_freqoffset;
+ int32_t ls_freqoffset;
+ int64_t local_time;
+} gPtpTimeData;
+
+
+#define SHM_SIZE 4*8 + sizeof(pthread_mutex_t) /* 3 - 64 bit and 2 - 32 bits */
+#define SHM_NAME "/ptp"
+
+#define MAX_SAMPLE_VALUE ((1U << ((sizeof(int32_t)*8)-1))-1)
+
+#define SRC_CHANNELS (2)
+#define SAMPLES_PER_SECOND (48000)
+#define FREQUENCY (480)
+#define SAMPLES_PER_CYCLE (SAMPLES_PER_SECOND/FREQUENCY)
+#define GAIN (.5)
+
+#define SYSTEM_FREQ_FILENAME "/sys/module/igb_avb/parameters/TEN_USEC_COUNT"
+
+//1722 header
+#define ETH_TYPE 0x22F0
+
+#define CD_SUBTYPE 0x02 /* for simple audio format */
+#define SV_VER_MR_RS_GV_TV 0x81
+#define RS_TU 0x00
+#define SAMPLE_FORMAT_NON_INTR_FLOAT 0x02
+#define NOMINAL_SAMPLE_RATE 0x09
+#define LINEAR_SAMPLE_MSB 0x20
+unsigned char GATEWAY_INFO[] =
+ { SAMPLE_FORMAT_NON_INTR_FLOAT, 0, NOMINAL_SAMPLE_RATE, LINEAR_SAMPLE_MSB };
+
+#define SAMPLE_SIZE 4 /* 4 bytes */
+#define SAMPLES_PER_FRAME 6
+#define CHANNELS 2
+#define PAYLOAD_SIZE SAMPLE_SIZE*SAMPLES_PER_FRAME*CHANNELS /* 6*4 * 2 channels = 48 bytes */
+
+#define IGB_BIND_NAMESZ 24
+
+#define XMIT_DELAY (200000000) /* us */
+#define RENDER_DELAY (XMIT_DELAY+2000000) /* us */
+typedef enum { false = 0, true = 1 } bool;
+typedef struct __attribute__ ((packed)) {
+ uint64_t subtype:7;
+ uint64_t cd_indicator:1;
+ uint64_t timestamp_valid:1;
+ uint64_t gateway_valid:1;
+ uint64_t reserved0:1;
+ uint64_t reset:1;
+ uint64_t version:3;
+ uint64_t sid_valid:1;
+ uint64_t seq_number:8;
+ uint64_t timestamp_uncertain:1;
+ uint64_t reserved1:7;
+ uint64_t stream_id;
+ uint64_t timestamp:32;
+ uint64_t gateway_info:32;
+ uint64_t length:16;
+} seventeen22_header;
+
+/* 61883 CIP with SYT Field */
+typedef struct {
+ uint16_t packet_channel:6;
+ uint16_t format_tag:2;
+ uint16_t app_control:4;
+ uint16_t packet_tcode:4;
+ uint16_t source_id:6;
+ uint16_t reserved0:2;
+ uint16_t data_block_size:8;
+ uint16_t reserved1:2;
+ uint16_t source_packet_header:1;
+ uint16_t quadlet_padding_count:3;
+ uint16_t fraction_number:2;
+ uint16_t data_block_continuity:8;
+ uint16_t format_id:6;
+ uint16_t eoh:2;
+ uint16_t format_dependent_field:8;
+ uint16_t syt;
+} six1883_header;
+
+typedef struct {
+ uint8_t label;
+ uint8_t value[3];
+} six1883_sample;
+
+/* global variables */
+int control_socket = -1;
+device_t igb_dev;
+volatile int halt_tx = 0;
+volatile int listeners = 0;
+volatile int mrp_okay;
+volatile int mrp_error = 0;;
+volatile int domain_a_valid = 0;
+int domain_class_a_id;
+int domain_class_a_priority;
+int domain_class_a_vid;
+volatile int domain_b_valid = 0;
+int domain_class_b_id;
+int domain_class_b_priority;
+int domain_class_b_vid;
+
+#define VERSION_STR "1.0"
+static const char *version_str = "simple_talker v" VERSION_STR "\n"
+ "Copyright (c) 2012, Intel Corporation\n";
+
+#define MRPD_PORT_DEFAULT 7500
+static inline uint64_t ST_rdtsc(void)
+{
+ uint64_t ret;
+ unsigned c, d;
+ asm volatile ("rdtsc":"=a" (c), "=d"(d));
+ ret = d;
+ ret <<= 32;
+ ret |= c;
+ return ret;
+}
+
+static int shm_fd = -1;
+static char *memory_offset_buffer = NULL;
+int gptpinit(void)
+{
+ shm_fd = shm_open(SHM_NAME, O_RDWR, 0);
+ if (shm_fd == -1) {
+ perror("shm_open()");
+ return false;
+ }
+ memory_offset_buffer =
+ (char *)mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+ shm_fd, 0);
+ if (memory_offset_buffer == (char *)-1) {
+ perror("mmap()");
+ memory_offset_buffer = NULL;
+ shm_unlink(SHM_NAME);
+ return false;
+ }
+ return true;
+}
+
+void gptpdeinit(void)
+{
+ if (memory_offset_buffer != NULL) {
+ munmap(memory_offset_buffer, SHM_SIZE);
+ }
+ if (shm_fd != -1) {
+ close(shm_fd);
+ }
+}
+
+int gptpscaling(gPtpTimeData * td)
+{
+ pthread_mutex_lock((pthread_mutex_t *) memory_offset_buffer);
+ memcpy(td, memory_offset_buffer + sizeof(pthread_mutex_t), sizeof(*td));
+ pthread_mutex_unlock((pthread_mutex_t *) memory_offset_buffer);
+
+ fprintf(stderr, "ml_phoffset = %lld, ls_phoffset = %lld\n",
+ td->ml_phoffset, td->ls_phoffset);
+ fprintf(stderr, "ml_freqffset = %d, ls_freqoffset = %d\n",
+ td->ml_freqoffset, td->ls_freqoffset);
+
+ return true;
+}
+
+void gensine32(int32_t * buf, unsigned count)
+{
+ long double interval = (2 * ((long double)M_PI)) / count;
+ unsigned i;
+ for (i = 0; i < count; ++i) {
+ buf[i] =
+ (int32_t) (MAX_SAMPLE_VALUE * sinl(i * interval) * GAIN);
+ }
+}
+
+int get_samples(unsigned count, int32_t * buffer)
+{
+ static int init = 0;
+ static int32_t samples_onechannel[100];
+ static unsigned index = 0;
+
+ if (init == 0) {
+ gensine32(samples_onechannel, 100);
+ init = 1;
+ }
+
+ while (count > 0) {
+ int i;
+ for (i = 0; i < SRC_CHANNELS; ++i) {
+ *(buffer++) = samples_onechannel[index];
+ }
+ index = (index + 1) % 100;
+ --count;
+ }
+
+ return 0;
+}
+
+int mrp_join_listener(uint8_t * streamid);
+int send_mrp_msg(char *notify_data, int notify_len)
+{
+ struct sockaddr_in addr;
+ socklen_t addr_len;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(MRPD_PORT_DEFAULT);
+ inet_aton("127.0.0.1", &addr.sin_addr);
+ addr_len = sizeof(addr);
+ if (control_socket != -1)
+ return (sendto
+ (control_socket, notify_data, notify_len, 0,
+ (struct sockaddr *)&addr, addr_len));
+
+ else
+ return (0);
+}
+
+int mrp_connect()
+{
+ struct sockaddr_in addr;
+ int sock_fd = -1;
+ sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock_fd < 0)
+ goto out;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(MRPD_PORT_DEFAULT);
+ inet_aton("127.0.0.1", &addr.sin_addr);
+ memset(&addr, 0, sizeof(addr));
+ control_socket = sock_fd;
+ return (0);
+ out: if (sock_fd != -1)
+ close(sock_fd);
+ sock_fd = -1;
+ return (-1);
+}
+
+int mrp_disconnect()
+{
+ char *msgbuf;
+ int rc;
+ msgbuf = malloc(64);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 64);
+ sprintf(msgbuf, "BYE");
+ mrp_okay = 0;
+ rc = send_mrp_msg(msgbuf, 1500);
+
+ /* rc = recv_mrp_okay(); */
+ free(msgbuf);
+ return rc;
+}
+
+int recv_mrp_okay()
+{
+ while ((mrp_okay == 0) && (mrp_error == 0))
+ usleep(20000);
+ return 0;
+}
+
+int mrp_register_domain(int *class_id, int *priority, u_int16_t * vid)
+{
+ char *msgbuf;
+ int rc;
+ msgbuf = malloc(64);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 64);
+ sprintf(msgbuf, "S+D:C:%d:P:%d:V:%04x", *class_id, *priority, *vid);
+ mrp_okay = 0;
+ rc = send_mrp_msg(msgbuf, 1500);
+
+ /* rc = recv_mrp_okay(); */
+ free(msgbuf);
+ return rc;
+}
+
+int mrp_get_domain(int *class_a_id, int *a_priority, u_int16_t * a_vid,
+ int *class_b_id, int *b_priority, u_int16_t * b_vid)
+{
+ char *msgbuf;
+
+ /* we may not get a notification if we are joining late,
+ * so query for what is already there ...
+ */
+ msgbuf = malloc(64);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 64);
+ sprintf(msgbuf, "S??");
+ send_mrp_msg(msgbuf, 64);
+ free(msgbuf);
+ while (!halt_tx && (domain_a_valid == 0) && (domain_b_valid == 0))
+ usleep(20000);
+ *class_a_id = 0;
+ *a_priority = 0;
+ *a_vid = 0;
+ *class_b_id = 0;
+ *b_priority = 0;
+ *b_vid = 0;
+ if (domain_a_valid) {
+ *class_a_id = domain_class_a_id;
+ *a_priority = domain_class_a_priority;
+ *a_vid = domain_class_a_vid;
+ }
+ if (domain_b_valid) {
+ *class_b_id = domain_class_b_id;
+ *b_priority = domain_class_b_priority;
+ *b_vid = domain_class_b_vid;
+ }
+ return (0);
+}
+unsigned char monitor_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+int mrp_await_listener(unsigned char *streamid)
+{
+ char *msgbuf;
+ memcpy(monitor_stream_id, streamid, sizeof(monitor_stream_id));
+ msgbuf = malloc(64);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 64);
+ sprintf(msgbuf, "S??");
+ send_mrp_msg(msgbuf, 64);
+ free(msgbuf);
+
+ /* either already there ... or need to wait ... */
+ while (!halt_tx && (listeners == 0))
+ usleep(20000);
+ return (0);
+}
+
+int process_mrp_msg(char *buf, int buflen)
+{
+
+ /*
+ * 1st character indicates application
+ * [MVS] - MAC, VLAN or STREAM
+ */
+ unsigned int id;
+ unsigned int priority;
+ unsigned int vid;
+ int i, j, k;
+ unsigned int substate;
+ unsigned char recovered_streamid[8];
+ k = 0;
+ next_line:if (k >= buflen)
+ return (0);
+ switch (buf[k]) {
+ case 'E':
+ printf("%s from mrpd\n", buf);
+ fflush(stdout);
+ mrp_error = 1;
+ break;
+ case 'O':
+ mrp_okay = 1;
+ break;
+ case 'M':
+ case 'V':
+ printf("%s unhandled from mrpd\n", buf);
+ fflush(stdout);
+
+ /* unhandled for now */
+ break;
+ case 'L':
+
+ /* parse a listener attribute - see if it matches our monitor_stream_id */
+ i = k;
+ while (buf[i] != 'D')
+ i++;
+ i += 2; /* skip the ':' */
+ sscanf(&(buf[i]), "%d", &substate);
+ while (buf[i] != 'S')
+ i++;
+ i += 2; /* skip the ':' */
+ for (j = 0; j < 8; j++) {
+ sscanf(&(buf[i + 2 * j]), "%02x", &id);
+ recovered_streamid[j] = (unsigned char)id;
+ } printf
+ ("FOUND STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
+ recovered_streamid[0], recovered_streamid[1],
+ recovered_streamid[2], recovered_streamid[3],
+ recovered_streamid[4], recovered_streamid[5],
+ recovered_streamid[6], recovered_streamid[7]);
+ switch (substate) {
+ case 0:
+ printf("with state ignore\n");
+ break;
+ case 1:
+ printf("with state askfailed\n");
+ break;
+ case 2:
+ printf("with state ready\n");
+ break;
+ case 3:
+ printf("with state readyfail\n");
+ break;
+ default:
+ printf("with state UNKNOWN (%d)\n", substate);
+ break;
+ }
+ if (substate > MSRP_LISTENER_ASKFAILED) {
+ if (memcmp
+ (recovered_streamid, monitor_stream_id,
+ sizeof(recovered_streamid)) == 0) {
+ mrp_join_listener(recovered_streamid);
+ listeners = 1;
+ printf("added listener\n");
+ }
+ }
+ fflush(stdout);
+
+ /* try to find a newline ... */
+ while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
+ i++;
+ if (i == buflen)
+ return (0);
+ if (buf[i] == '\0')
+ return (0);
+ i++;
+ k = i;
+ goto next_line;
+ break;
+ case 'D':
+ i = k + 4;
+
+ /* save the domain attribute */
+ sscanf(&(buf[i]), "%d", &id);
+ while (buf[i] != 'P')
+ i++;
+ i += 2; /* skip the ':' */
+ sscanf(&(buf[i]), "%d", &priority);
+ while (buf[i] != 'V')
+ i++;
+ i += 2; /* skip the ':' */
+ sscanf(&(buf[i]), "%x", &vid);
+ if (id == 6) {
+ domain_class_a_id = id;
+ domain_class_a_priority = priority;
+ domain_class_a_vid = vid;
+ domain_a_valid = 1;
+ } else {
+ domain_class_b_id = id;
+ domain_class_b_priority = priority;
+ domain_class_b_vid = vid;
+ domain_b_valid = 1;
+ }
+ while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
+ i++;
+ if ((i == buflen) || (buf[i] == '\0'))
+ return (0);
+ i++;
+ k = i;
+ goto next_line;
+ break;
+ case 'T':
+
+ /* as simple_talker we don't care about other talkers */
+ i = k;
+ while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
+ i++;
+ if (i == buflen)
+ return (0);
+ if (buf[i] == '\0')
+ return (0);
+ i++;
+ k = i;
+ goto next_line;
+ break;
+ case 'S':
+
+ /* handle the leave/join events */
+ switch (buf[k + 4]) {
+ case 'L':
+ i = k + 5;
+ while (buf[i] != 'D')
+ i++;
+ i += 2; /* skip the ':' */
+ sscanf(&(buf[i]), "%d", &substate);
+ while (buf[i] != 'S')
+ i++;
+ i += 2; /* skip the ':' */
+ for (j = 0; j < 8; j++) {
+ sscanf(&(buf[i + 2 * j]), "%02x", &id);
+ recovered_streamid[j] = (unsigned char)id;
+ } printf
+ ("EVENT on STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
+ recovered_streamid[0], recovered_streamid[1],
+ recovered_streamid[2], recovered_streamid[3],
+ recovered_streamid[4], recovered_streamid[5],
+ recovered_streamid[6], recovered_streamid[7]);
+ switch (substate) {
+ case 0:
+ printf("with state ignore\n");
+ break;
+ case 1:
+ printf("with state askfailed\n");
+ break;
+ case 2:
+ printf("with state ready\n");
+ break;
+ case 3:
+ printf("with state readyfail\n");
+ break;
+ default:
+ printf("with state UNKNOWN (%d)\n", substate);
+ break;
+ }
+ switch (buf[k + 1]) {
+ case 'L':
+ printf("got a leave indication\n");
+ if (memcmp
+ (recovered_streamid, monitor_stream_id,
+ sizeof(recovered_streamid)) == 0) {
+ listeners = 0;
+ printf("listener left\n");
+ }
+ break;
+ case 'J':
+ case 'N':
+ printf("got a new/join indication\n");
+ if (substate > MSRP_LISTENER_ASKFAILED) {
+ if (memcmp
+ (recovered_streamid,
+ monitor_stream_id,
+ sizeof(recovered_streamid)) == 0)
+ mrp_join_listener
+ (recovered_streamid);
+ listeners = 1;
+ }
+ break;
+ }
+
+ /* only care about listeners ... */
+ default:
+ return (0);
+ break;
+ }
+ break;
+ case '\0':
+ break;
+ }
+ return (0);
+}
+
+void *mrp_monitor_thread(void *arg)
+{
+ char *msgbuf;
+ struct sockaddr_in client_addr;
+ struct msghdr msg;
+ struct iovec iov;
+ int bytes = 0;
+ struct pollfd fds;
+ int rc;
+ if (NULL == arg)
+ rc = 0;
+
+ else
+ rc = 1;
+ msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
+ if (NULL == msgbuf)
+ return NULL;
+ while (!halt_tx) {
+ fds.fd = control_socket;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ rc = poll(&fds, 1, 100);
+ if (rc < 0) {
+ free(msgbuf);
+ pthread_exit(NULL);
+ }
+ if (rc == 0)
+ continue;
+ if ((fds.revents & POLLIN) == 0) {
+ free(msgbuf);
+ pthread_exit(NULL);
+ }
+ memset(&msg, 0, sizeof(msg));
+ memset(&client_addr, 0, sizeof(client_addr));
+ memset(msgbuf, 0, MAX_MRPD_CMDSZ);
+ iov.iov_len = MAX_MRPD_CMDSZ;
+ iov.iov_base = msgbuf;
+ msg.msg_name = &client_addr;
+ msg.msg_namelen = sizeof(client_addr);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ bytes = recvmsg(control_socket, &msg, 0);
+ if (bytes < 0)
+ continue;
+ process_mrp_msg(msgbuf, bytes);
+ }
+ free(msgbuf);
+ pthread_exit(NULL);
+}
+
+pthread_t monitor_thread;
+pthread_attr_t monitor_attr;
+int mrp_monitor()
+{
+ pthread_attr_init(&monitor_attr);
+ pthread_create(&monitor_thread, NULL, mrp_monitor_thread, NULL);
+ return (0);
+}
+
+int mrp_join_listener(uint8_t * streamid)
+{
+ char *msgbuf;
+ int rc;
+ msgbuf = malloc(1500);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 1500);
+ sprintf(msgbuf, "S+L:%02X%02X%02X%02X%02X%02X%02X%02X"
+ ":D:2", streamid[0], streamid[1], streamid[2], streamid[3],
+ streamid[4], streamid[5], streamid[6], streamid[7]);
+ mrp_okay = 0;
+ rc = send_mrp_msg(msgbuf, 1500);
+
+ /* rc = recv_mrp_okay(); */
+ free(msgbuf);
+ return rc;
+}
+
+int
+mrp_advertise_stream(uint8_t * streamid,
+ uint8_t * destaddr,
+ u_int16_t vlan,
+ int pktsz, int interval, int priority, int latency)
+{
+ char *msgbuf;
+ int rc;
+ msgbuf = malloc(1500);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 1500);
+ sprintf(msgbuf, "S++S:%02X%02X%02X%02X%02X%02X%02X%02X"
+ ":A:%02X%02X%02X%02X%02X%02X"
+ ":V:%04X"
+ ":Z:%d"
+ ":I:%d"
+ ":P:%d"
+ ":L:%d", streamid[0], streamid[1], streamid[2],
+ streamid[3], streamid[4], streamid[5], streamid[6],
+ streamid[7], destaddr[0], destaddr[1], destaddr[2],
+ destaddr[3], destaddr[4], destaddr[5], vlan, pktsz,
+ interval, priority << 5, latency);
+ mrp_okay = 0;
+ rc = send_mrp_msg(msgbuf, 1500);
+
+ /* rc = recv_mrp_okay(); */
+ free(msgbuf);
+ return rc;
+}
+
+int
+mrp_unadvertise_stream(uint8_t * streamid,
+ uint8_t * destaddr,
+ u_int16_t vlan,
+ int pktsz, int interval, int priority, int latency)
+{
+ char *msgbuf;
+ int rc;
+ msgbuf = malloc(1500);
+ if (NULL == msgbuf)
+ return -1;
+ memset(msgbuf, 0, 1500);
+ sprintf(msgbuf, "S--S:%02X%02X%02X%02X%02X%02X%02X%02X"
+ ":A:%02X%02X%02X%02X%02X%02X"
+ ":V:%04X"
+ ":Z:%d"
+ ":I:%d"
+ ":P:%d"
+ ":L:%d", streamid[0], streamid[1], streamid[2],
+ streamid[3], streamid[4], streamid[5], streamid[6],
+ streamid[7], destaddr[0], destaddr[1], destaddr[2],
+ destaddr[3], destaddr[4], destaddr[5], vlan, pktsz,
+ interval, priority << 5, latency);
+ mrp_okay = 0;
+ rc = send_mrp_msg(msgbuf, 1500);
+
+ /* rc = recv_mrp_okay(); */
+ free(msgbuf);
+ return rc;
+}
+
+void sigint_handler(int signum)
+{
+ printf("got SIGINT\n");
+ halt_tx = signum;
+}
+
+int pci_connect()
+{
+ struct pci_access *pacc;
+ struct pci_dev *dev;
+ int err;
+ char devpath[IGB_BIND_NAMESZ];
+ memset(&igb_dev, 0, sizeof(device_t));
+ pacc = pci_alloc();
+ pci_init(pacc);
+ pci_scan_bus(pacc);
+ for (dev = pacc->devices; dev; dev = dev->next) {
+ pci_fill_info(dev,
+ PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);
+ igb_dev.pci_vendor_id = dev->vendor_id;
+ igb_dev.pci_device_id = dev->device_id;
+ igb_dev.domain = dev->domain;
+ igb_dev.bus = dev->bus;
+ igb_dev.dev = dev->dev;
+ igb_dev.func = dev->func;
+ snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d",
+ dev->domain, dev->bus, dev->dev, dev->func);
+ err = igb_probe(&igb_dev);
+ if (err) {
+ continue;
+ }
+ printf("attaching to %s\n", devpath);
+ err = igb_attach(devpath, &igb_dev);
+ if (err) {
+ printf("attach failed! (%s)\n", strerror(errno));
+ continue;
+ }
+ goto out;
+ }
+ pci_cleanup(pacc);
+ return ENXIO;
+ out: pci_cleanup(pacc);
+ return 0;
+}
+
+unsigned char STATION_ADDR[] = { 0, 0, 0, 0, 0, 0 };
+unsigned char STREAM_ID[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* IEEE 1722 reserved address */
+unsigned char DEST_ADDR[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 };
+
+int get_mac_address(char *interface)
+{
+ struct ifreq if_request;
+ int lsock;
+ int rc;
+ lsock = socket(PF_PACKET, SOCK_RAW, htons(0x800));
+ if (lsock < 0)
+ return -1;
+ memset(&if_request, 0, sizeof(if_request));
+ strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name));
+ rc = ioctl(lsock, SIOCGIFHWADDR, &if_request);
+ if (rc < 0) {
+ close(lsock);
+ return -1;
+ }
+ memcpy(STATION_ADDR, if_request.ifr_hwaddr.sa_data,
+ sizeof(STATION_ADDR));
+ close(lsock);
+ return 0;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "\n"
+ "usage: simple_talker [-h] -i interface-name"
+ "\n"
+ "options:\n"
+ " -h show this message\n"
+ " -i specify interface for AVB connection\n"
+ "\n" "%s" "\n", version_str);
+ exit(1);
+}
+
+#define PACKET_IPG (125000) /* (1) packet every 125 usec */
+
+int main(int argc, char *argv[])
+{
+ unsigned i;
+ int err;
+ struct igb_dma_alloc a_page;
+ struct igb_packet a_packet;
+ struct igb_packet *tmp_packet;
+ struct igb_packet *cleaned_packets;
+ struct igb_packet *free_packets;
+ int c;
+ u_int64_t last_time;
+ int rc = 0;
+ char *interface = NULL;
+ int class_a_id = 0;
+ int a_priority = 0;
+ u_int16_t a_vid = 0;
+ int class_b_id = 0;
+ int b_priority = 0;
+ u_int16_t b_vid = 0;
+ int seqnum;
+ int time_stamp;
+ int16_t data_length;
+ unsigned total_samples = 0;
+ int TEN_USEC_COUNT;
+ gPtpTimeData td;
+ int32_t sample_buffer[SAMPLES_PER_FRAME * SRC_CHANNELS];
+ seventeen22_header *header0;
+ six1883_header *header1;
+ six1883_sample *sample;
+ FILE *freqfile;
+ char freqstring[8];
+ uint64_t now_tscns, now_8021as;
+ uint64_t update_tscns, update_8021as;
+ unsigned delta_tscns, delta_8021as, delta_local;
+ long double ml_ratio, ls_ratio;
+
+ for (;;) {
+ c = getopt(argc, argv, "hi:");
+ if (c < 0)
+ break;
+ switch (c) {
+ case 'h':
+ usage();
+ break;
+ case 'i':
+ if (interface) {
+ printf
+ ("only one interface per daemon is supported\n");
+ usage();
+ }
+ interface = strdup(optarg);
+ break;
+ }
+ }
+ if (optind < argc)
+ usage();
+ if (NULL == interface) {
+ usage();
+ }
+ rc = mrp_connect();
+ if (rc) {
+ printf("socket creation failed\n");
+ return (errno);
+ }
+ err = pci_connect();
+ if (err) {
+ printf("connect failed (%s) - are you running as root?\n",
+ strerror(errno));
+ return (errno);
+ }
+ err = igb_init(&igb_dev);
+ if (err) {
+ printf("init failed (%s) - is the driver really loaded?\n",
+ strerror(errno));
+ return (errno);
+ }
+ err = igb_dma_malloc_page(&igb_dev, &a_page);
+ if (err) {
+ printf("malloc failed (%s) - out of memory?\n",
+ strerror(errno));
+ return (errno);
+ }
+ signal(SIGINT, sigint_handler);
+ rc = get_mac_address(interface);
+ if (rc) {
+ printf("failed to open interface\n");
+ usage();
+ }
+
+ freqfile = fopen(SYSTEM_FREQ_FILENAME, "r");
+ if (freqfile == NULL) {
+ printf("Failed to open kernel module parameter: %s\n",
+ strerror(errno));
+ return errno;
+ }
+
+ if (fscanf(freqfile, "%7s", freqstring) != 1) {
+ printf("Failed to read kernel module parameter: %s\n",
+ strerror(errno));
+ return errno;
+ }
+
+ TEN_USEC_COUNT = atoi(freqstring);
+ /* fprintf(stderr, "TEN_USEC_COUNT = %d\n", TEN_USEC_COUNT); */
+
+ mrp_monitor();
+
+ /*
+ * should use mrp_get_domain() above but this is a simplification
+ */
+ domain_a_valid = 1;
+ class_a_id = MSRP_SR_CLASS_A;
+ a_priority = MSRP_SR_CLASS_A_PRIO;
+ a_vid = 2;
+ printf("detected domain Class A PRIO=%d VID=%04x...\n", a_priority,
+ a_vid);
+
+#define PKT_SZ 100
+
+ mrp_register_domain(&class_a_id, &a_priority, &a_vid);
+ igb_set_class_bandwidth(&igb_dev, PACKET_IPG / 125000, 0, PKT_SZ - 22,
+ 0);
+
+ memset(STREAM_ID, 0, sizeof(STREAM_ID));
+ memcpy(STREAM_ID, STATION_ADDR, sizeof(STATION_ADDR));
+
+ a_packet.dmatime = a_packet.attime = a_packet.flags = 0;
+ a_packet.map.paddr = a_page.dma_paddr;
+ a_packet.map.mmap_size = a_page.mmap_size;
+ a_packet.offset = 0;
+ a_packet.vaddr = a_page.dma_vaddr + a_packet.offset;
+ a_packet.len = PKT_SZ;
+ free_packets = NULL;
+ seqnum = 0;
+
+ /* divide the dma page into buffers for packets */
+ for (i = 1; i < ((a_page.mmap_size) / PKT_SZ); i++) {
+ tmp_packet = malloc(sizeof(struct igb_packet));
+ if (NULL == tmp_packet) {
+ printf("failed to allocate igb_packet memory!\n");
+ return (errno);
+ }
+ *tmp_packet = a_packet;
+ tmp_packet->offset = (i * PKT_SZ);
+ tmp_packet->vaddr += tmp_packet->offset;
+ tmp_packet->next = free_packets;
+ memset(tmp_packet->vaddr, 0, PKT_SZ); /* MAC header at least */
+ memcpy(tmp_packet->vaddr, DEST_ADDR, sizeof(DEST_ADDR));
+ memcpy(tmp_packet->vaddr + 6, STATION_ADDR,
+ sizeof(STATION_ADDR));
+
+ /* Q-tag */
+ ((char *)tmp_packet->vaddr)[12] = 0x81;
+ ((char *)tmp_packet->vaddr)[13] = 0x00;
+ ((char *)tmp_packet->vaddr)[14] =
+ ((a_priority << 13 | a_vid)) >> 8;
+ ((char *)tmp_packet->vaddr)[15] =
+ ((a_priority << 13 | a_vid)) & 0xFF;
+ ((char *)tmp_packet->vaddr)[16] = 0x22; /* 1722 eth type */
+ ((char *)tmp_packet->vaddr)[17] = 0xF0;
+
+ /* 1722 header update + payload */
+ header0 =
+ (seventeen22_header *) (((char *)tmp_packet->vaddr) + 18);
+ header0->cd_indicator = 0;
+ header0->subtype = 0;
+ header0->sid_valid = 1;
+ header0->version = 0;
+ header0->reset = 0;
+ header0->reserved0 = 0;
+ header0->gateway_valid = 0;
+ header0->reserved1 = 0;
+ header0->timestamp_uncertain = 0;
+ memset(&(header0->stream_id), 0, sizeof(header0->stream_id));
+ memcpy(&(header0->stream_id), STATION_ADDR,
+ sizeof(STATION_ADDR));
+ header0->length = htons(32);
+ header1 = (six1883_header *) (header0 + 1);
+ header1->format_tag = 1;
+ header1->packet_channel = 0x1F;
+ header1->packet_tcode = 0xA;
+ header1->app_control = 0x0;
+ header1->reserved0 = 0;
+ header1->source_id = 0x3F;
+ header1->data_block_size = CHANNELS;
+ header1->fraction_number = 0;
+ header1->quadlet_padding_count = 0;
+ header1->source_packet_header = 0;
+ header1->reserved1 = 0;
+ header1->eoh = 0x2;
+ header1->format_id = 0x10;
+ header1->format_dependent_field = 0x02;
+ header1->syt = 0xFFFF;
+ tmp_packet->len =
+ 18 + sizeof(seventeen22_header) + sizeof(six1883_header) +
+ (SAMPLES_PER_FRAME * CHANNELS * sizeof(six1883_sample));
+ free_packets = tmp_packet;
+ }
+
+ /*
+ * subtract 16 bytes for the MAC header/Q-tag - pktsz is limited to the
+ * data payload of the ethernet frame .
+ *
+ * IPG is scaled to the Class (A) observation interval of packets per 125 usec
+ */
+ fprintf(stderr, "advertising stream ...\n");
+ mrp_advertise_stream(STREAM_ID, DEST_ADDR, a_vid, PKT_SZ - 16,
+ PACKET_IPG / 125000, a_priority, 3900);
+ fprintf(stderr, "awaiting a listener ...\n");
+ mrp_await_listener(STREAM_ID);
+ printf("got a listener ...\n");
+ halt_tx = 0;
+
+ gptpinit();
+ gptpscaling(&td);
+
+ now_tscns = ST_rdtsc() * 10000 / TEN_USEC_COUNT;
+ update_tscns = td.local_time + td.ls_phoffset;
+ update_8021as = td.local_time - td.ml_phoffset;
+ delta_tscns = (unsigned)(now_tscns - update_tscns);
+ ml_ratio = -1 * (((long double)td.ml_freqoffset) / 1000000000000) + 1;
+ ls_ratio = -1 * (((long double)td.ls_freqoffset) / 1000000000000) + 1;
+ delta_local = (unsigned)(ls_ratio * delta_tscns);
+ delta_8021as = (unsigned)(ml_ratio * ls_ratio * delta_tscns);
+ now_8021as = update_8021as + delta_8021as;
+ last_time = td.local_time + delta_local + XMIT_DELAY;
+
+ time_stamp = now_8021as + RENDER_DELAY;
+
+ rc = nice(-20);
+
+ while (listeners && !halt_tx) {
+ tmp_packet = free_packets;
+ if (NULL == tmp_packet)
+ goto cleanup;
+ header0 =
+ (seventeen22_header *) (((char *)tmp_packet->vaddr) + 18);
+ header1 = (six1883_header *) (header0 + 1);
+ free_packets = tmp_packet->next;
+
+ /* unfortuntely unless this thread is at rtprio
+ * you get pre-empted between fetching the time
+ * and programming the packet and get a late packet
+ */
+ tmp_packet->attime = last_time + PACKET_IPG;
+ last_time += PACKET_IPG;
+
+ get_samples(SAMPLES_PER_FRAME, sample_buffer);
+ header0->seq_number = seqnum++;
+ if (seqnum % 4 == 0)
+ header0->timestamp_valid = 0;
+
+ else
+ header0->timestamp_valid = 1;
+
+ time_stamp = htonl(time_stamp);
+ header0->timestamp = time_stamp;
+ time_stamp = ntohl(time_stamp);
+ time_stamp += PACKET_IPG;
+ header1->data_block_continuity = total_samples;
+ total_samples += SAMPLES_PER_FRAME;
+ sample =
+ (six1883_sample *) (((char *)tmp_packet->vaddr) +
+ (18 + sizeof(seventeen22_header) +
+ sizeof(six1883_header)));
+
+ for (i = 0; i < SAMPLES_PER_FRAME * CHANNELS; ++i) {
+ uint32_t tmp = htonl(sample_buffer[i]);
+ sample[i].label = 0x40;
+ memcpy(&(sample[i].value), &(tmp),
+ sizeof(sample[i].value));
+ }
+
+ err = igb_xmit(&igb_dev, 0, tmp_packet);
+
+ if (!err) {
+ continue;
+ }
+
+ if (ENOSPC == err) {
+
+ /* put back for now */
+ tmp_packet->next = free_packets;
+ free_packets = tmp_packet;
+ }
+
+ cleanup: igb_clean(&igb_dev, &cleaned_packets);
+ i = 0;
+ while (cleaned_packets) {
+ i++;
+ tmp_packet = cleaned_packets;
+ cleaned_packets = cleaned_packets->next;
+ tmp_packet->next = free_packets;
+ free_packets = tmp_packet;
+ }
+ }
+ rc = nice(0);
+
+ if (halt_tx == 0)
+ printf("listener left ...\n");
+ halt_tx = 1;
+
+ mrp_unadvertise_stream(STREAM_ID, DEST_ADDR, a_vid, PKT_SZ - 16,
+ PACKET_IPG / 125000, a_priority, 3900);
+
+ igb_set_class_bandwidth(&igb_dev, 0, 0, 0, 0); /* disable Qav */
+
+ rc = mrp_disconnect();
+
+ igb_dma_free_page(&igb_dev, &a_page);
+
+ err = igb_detach(&igb_dev);
+
+ pthread_exit(NULL);
+
+ return (0);
+}
+++ /dev/null
-/******************************************************************************
-
- Copyright (c) 2001-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 <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <signal.h>
-#include <errno.h>
-
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-
-#include <stdio.h>
-
-#include <pci/pci.h>
-
-#include "igb.h"
-
-#define IGB_BIND_NAMESZ 24
-
-device_t igb_dev;
-volatile int halt_tx;
-
-void
-sigint_handler (int signum)
-{
- printf("got SIGINT\n");
- halt_tx = signum;
-}
-
-int
-connect()
-{
- struct pci_access *pacc;
- struct pci_dev *dev;
- int err;
- char devpath[IGB_BIND_NAMESZ];
-
- memset(&igb_dev, 0, sizeof(device_t));
-
- pacc = pci_alloc();
- pci_init(pacc);
- pci_scan_bus(pacc);
- for (dev=pacc->devices; dev; dev=dev->next)
- {
- pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);
-
- igb_dev.pci_vendor_id = dev->vendor_id;
- igb_dev.pci_device_id = dev->device_id;
- igb_dev.domain = dev->domain;
- igb_dev.bus = dev->bus;
- igb_dev.dev = dev->dev;
- igb_dev.func = dev->func;
-
- snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d", \
- dev->domain, dev->bus, dev->dev, dev->func );
- printf("probing %s\n", devpath);
-
- err = igb_probe(&igb_dev);
-
- if (err) {
- continue;
- }
-
- printf ("attaching to %s\n", devpath);
- err = igb_attach(devpath, &igb_dev);
-
- if (err) {
- printf ("attach failed! (%s)\n", strerror(errno));
- continue;
- }
- printf("attach successful to %s\n", devpath);
- goto out;
- }
-
- pci_cleanup(pacc);
- return ENXIO;
-
-out:
- pci_cleanup(pacc);
- return 0;
-
-}
-
-#define PACKET_IPG (20000000) /* 20 msec */
-
-int
-main()
-{
- unsigned i;
- int err;
- struct igb_dma_alloc a_page;
- struct igb_packet a_packet;
- struct igb_packet *tmp_packet;
- struct igb_packet *cleaned_packets;
- struct igb_packet *free_packets;
- u_int64_t last_time;
- u_int64_t rdtsc0;
-
- err = connect();
-
- if (err) { printf("connect failed (%s)\n", strerror(errno)); return(errno); }
-
- err = igb_init(&igb_dev);
-
- if (err) { printf("init failed (%s)\n", strerror(errno)); return(errno); }
-
- err = igb_dma_malloc_page(&igb_dev, &a_page);
-
- if (err) { printf("malloc failed (%s)\n", strerror(errno)); return(errno); }
-
-#define PKT_SZ 200
- a_packet.dmatime = a_packet.attime = a_packet.flags = 0;
- a_packet.map.paddr = a_page.dma_paddr;
- a_packet.map.mmap_size = a_page.mmap_size;
-
- a_packet.offset = 0;
- a_packet.vaddr = a_page.dma_vaddr + a_packet.offset;
- a_packet.len = PKT_SZ;
-
- free_packets = NULL;
-
- /* divide the dma page into buffers for packets */
- for (i = 1; i < ((a_page.mmap_size) / PKT_SZ); i++) {
- tmp_packet = malloc(sizeof(struct igb_packet));
- if (NULL == tmp_packet) { printf("failed to allocate igb_packet memory!\n"); return(errno); }
-
- *tmp_packet = a_packet;
- tmp_packet->offset = (i * PKT_SZ);
- tmp_packet->vaddr += tmp_packet->offset;
- tmp_packet->next = free_packets;
- memset(tmp_packet->vaddr, 0xffffffff, PKT_SZ); /* MAC header at least */
- free_packets = tmp_packet;
- }
-
- igb_set_class_bandwidth(&igb_dev, 0, 0, 0); /* disable Qav */
-
- halt_tx = 0;
- signal(SIGINT, sigint_handler);
-
-
- igb_get_wallclock(&igb_dev, &last_time, &rdtsc0);
-
- while (!halt_tx) {
- tmp_packet = free_packets;
-
- if (NULL == tmp_packet) goto cleanup;
-
- free_packets = tmp_packet->next;
-
- tmp_packet->attime = last_time + PACKET_IPG;
- *(u_int64_t *)(tmp_packet->vaddr + 32) = tmp_packet->attime;
-
- err = igb_xmit(&igb_dev, 0, tmp_packet);
-
- if (!err) { last_time += PACKET_IPG; continue; }
-
- if (ENOSPC == err) {
- /* put back for now */
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
-cleanup:
- igb_clean(&igb_dev, &cleaned_packets);
- i = 0;
- while (cleaned_packets) {
- i++;
- tmp_packet = cleaned_packets;
- cleaned_packets = cleaned_packets->next;
- /* remap attime to compare to dma time */
- while (tmp_packet->attime > 999999999) tmp_packet->attime -= 1000000000;
- /* doesn't handle wrap-around ! */
- printf("delta(attime-dmatime)=%d\n", (unsigned int)(tmp_packet->attime - tmp_packet->dmatime));
- tmp_packet->next = free_packets;
- free_packets = tmp_packet;
- }
-
- }
-
- igb_dma_free_page(&igb_dev, &a_page);
- err = igb_detach(&igb_dev);
- return(0);
-}
-
--- /dev/null
+INTRODUCTION
+
+This component demonstrates various features of the Intel I210 Ethernet
+controller. These features can be used for developing Audio/Video Bridging
+applications, Industrial Ethernet applications which require precise timing
+control over frame transmission, or test harnesses for measuring system
+latencies and sampling events.
+
+This component - igb_avb - is limited to the Intel I210 Ethernet controller.
+The kernel module can be loaded in parallel to existing in-kernel igb modules
+which may be used on other supported Intel LAN controllers. Modifications are
+required to the in-kernel drivers if the existing in-kernel igb driver has
+support for the Intel I210.
+
+BUILDING
+
+The kernel igb module can be built which supports the latest Linux kernel
+3.x PTP clock support - to enable, modify kmod/Makefile and enable -DCONFIG_PTP
+as a build option (e.g. EXTRA_CFLAGS += -DCONFIG_PTP).
+
+RUNNING
+
+To install the kernel mode driver, you must have root permissions. Typically,
+the driver is loaded by:
+ <optional> sudo modprobe dca
+ <optional> sudo modprobe ptp
+ sudo insmod ./igb_avb.ko
+
+As 3.4 and later kernels include support for the I210, you may need to 'rmmod
+igb' before loading the igb_avb module.
+
return(0);
}
int
-igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz)
+igb_set_class_bandwidth(device_t *dev,
+ u_int32_t class_a,
+ u_int32_t class_b,
+ u_int32_t tpktsz_a,
+ u_int32_t tpktsz_b)
{
u_int32_t tqavctrl;
u_int32_t tqavcc0, tqavcc1;
struct e1000_hw *hw;
struct igb_link_cmd link;
int err;
+ float class_a_percent, class_b_percent;
if (NULL == dev) return EINVAL;
adapter = (struct adapter *)dev->private_data;
if (link.duplex != FULL_DUPLEX ) return EINVAL;
- if ((class_a + class_b) > 75 ) return EINVAL;
+ if (tpktsz_a < 64)
+ tpktsz_a = 64; /* minimum ethernet frame size */
- if ((tpktsz < 64) || (tpktsz > 2000)) return EINVAL;
+ if (tpktsz_a > 1500)
+ return EINVAL;
+
+ if (tpktsz_b < 64)
+ tpktsz_b = 64; /* minimum ethernet frame size */
+
+ if (tpktsz_b > 1500)
+ return EINVAL;
tqavctrl = E1000_READ_REG(hw, E1000_TQAVCTRL);
else
linkrate = E1000_TQAVCC_LINKRATE;
- /* XXX convert to fixed point or floating point percents */
- class_a_idle = (class_a * 2 * linkrate / 100); /* 'class_a' is a percent */
- class_b_idle = (class_b * 2 * linkrate / 100);
+ /*
+ * class_a and class_b are the packets-per-(respective)observation
+ * interval (125 usec for class A, 250 usec for class B)
+ * these parameters are also used when establishing the MSRP
+ * talker advertise attribute (as well as the tpktsize)
+ *
+ * note that class_a and class_b are independent of the media
+ * rate. For our idle slope calculation, we need to scale the
+ * (tpktsz + (media overhead)) * rate -> percentage of media rate.
+ */
+
+ /* 12=Ethernet IPG, 8=Preamble+Start of Frame, 18=Mac Header with VLAN+Etype, 4=CRC */
+ class_a_percent = (float)((tpktsz_a + (12 + 8 + 18 + 4)) * class_a) ;
+ class_b_percent = (float)((tpktsz_b + (12 + 8 + 18 + 4)) * class_b) ;
+
+ class_a_percent /= 0.000125; /* class A observation window */
+ class_b_percent /= 0.000250; /* class B observation window */
+
+ if (link.speed == 100) {
+ class_a_percent /= (100000000.0 / 8); /* bytes-per-sec @ 100Mbps */
+ class_b_percent /= (100000000.0 / 8);
+ class_a_idle = (u_int32_t)(class_a_percent * 0.2 * (float)linkrate + 0.5);
+ class_b_idle = (u_int32_t)(class_b_percent * 0.2 * (float)linkrate + 0.5);
+ } else {
+ class_a_percent /= (1000000000.0 / 8); /* bytes-per-sec @ 1Gbps */
+ class_b_percent /= (1000000000.0 / 8);
+ class_a_idle = (u_int32_t)(class_a_percent * 2.0 * (float)linkrate + 0.5);
+ class_b_idle = (u_int32_t)(class_b_percent * 2.0 * (float)linkrate + 0.5);
+ }
+
+ if ((class_a_percent + class_b_percent) > 0.75)
+ return EINVAL;
tqavcc0 |= class_a_idle;
tqavcc1 |= class_b_idle;
/*
- * The datasheet lists a formula for configuring the high credit threshold,
- * however it is only relevant in the conditions the high priority SR queues
- * are internally pre-empted by manageability traffic or low power proxy modes -
- * and if the SR queues are pre-empted, they would burst more packets than expected.
- * So - if you enable manageability or proxy modes while running AVB traffic, you
- * should program the high credit thresholds to prevent non-compliant packet bursts.
- * But be aware the stream didn't stream as much bandwidth as it reserved,
- * and you may have had an underrun on the listener.
+ * hiCredit is the number of idleslope credits accumulated due to delay T
+ *
+ * we assume the maxInterferenceSize is 18 + 4 + 1500 (1522).
+ * Note: if EEE is enabled, we should use for maxInterferenceSize
+ * the overhead of link recovery (a media-specific quantity).
+ */
+ tqavhc0 = 0x80000000 + (class_a_idle * 1522 / linkrate ); /* L.10 */
+
+ /*
+ * Class B high credit is is the same, except the delay
+ * is the MaxBurstSize of Class A + maxInterferenceSize of non-SR traffic
+ *
+ * L.41
+ * max Class B delay = (1522 + tpktsz_a) / (linkrate - class_a_idle)
*/
- tqavhc0 = 0xFFFFFFFF;
- tqavhc1 = 0xFFFFFFFF;
+
+ tqavhc1 = 0x80000000 + (class_b_idle * ((1522 + tpktsz_a)/ (linkrate - class_a_idle)));
/* implicitly enable the Qav shaper */
tqavctrl |= E1000_TQAVCTRL_TX_ARB;
int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet);
void igb_clean(device_t *dev, struct igb_packet **cleaned_packets);
int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc);
-int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz);
+int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz_a, u_int32_t tpktsz_b);
void igb_trigger(device_t *dev, u_int32_t data);
void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data);