Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken windows code #377

Merged
merged 7 commits into from
Apr 22, 2016
6 changes: 3 additions & 3 deletions daemons/gptp/common/avbts_message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ class PathTraceTLV {
IdentityList::iterator iter;
*((uint16_t *)byte_str) = tlvType; // tlvType already in network byte order
byte_str += sizeof(tlvType);
*((uint16_t *)byte_str) =
PLAT_htons(identityList.size()*PTP_CLOCK_IDENTITY_LENGTH);
*((uint16_t *)byte_str) = PLAT_htons
((uint16_t)identityList.size()*PTP_CLOCK_IDENTITY_LENGTH);
byte_str += sizeof(uint16_t);
for
(iter = identityList.begin();
Expand Down Expand Up @@ -414,7 +414,7 @@ class PathTraceTLV {
* @return Total length
*/
int length() {
return 2*sizeof(uint16_t) + PTP_CLOCK_IDENTITY_LENGTH*identityList.size();
return (int)(2*sizeof(uint16_t) + PTP_CLOCK_IDENTITY_LENGTH*identityList.size());
}
};

Expand Down
4 changes: 2 additions & 2 deletions daemons/gptp/common/gptp_cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ int GptpIniParser::iniCallBack(void *user, const char *section, const char *name
{
errno = 0;
char *pEnd;
unsigned char p1 = strtoul(value, &pEnd, 10);
unsigned char p1 = (unsigned char) strtoul(value, &pEnd, 10);
if( *pEnd == '\0' && errno == 0) {
valOK = true;
parser->_config.priority1 = p1;
Expand Down Expand Up @@ -140,7 +140,7 @@ int GptpIniParser::iniCallBack(void *user, const char *section, const char *name
{
errno = 0;
char *pEnd;
uint16_t lostpdelayth = strtoul(value, &pEnd, 10);
uint16_t lostpdelayth = (uint16_t) strtoul(value, &pEnd, 10);
if( *pEnd == '\0' && errno == 0 ) {
valOK = true;
parser->_config.lostPdelayRespThresh = lostpdelayth;
Expand Down
18 changes: 17 additions & 1 deletion daemons/gptp/common/ieee1588.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,23 @@ class HWTimestamper {
return 0;
}

/**
/**
* @brief Sets the the PHY delay for TX and RX
* @param [input] struct phy_delay pointer
* @return 0
**/

int set_phy_delay(struct phy_delay *set_delay)
{
delay.mb_tx_phy_delay = set_delay->mb_tx_phy_delay;
delay.mb_rx_phy_delay = set_delay->mb_rx_phy_delay;
delay.gb_tx_phy_delay = set_delay->gb_tx_phy_delay;
delay.gb_rx_phy_delay = set_delay->gb_rx_phy_delay;

return 0;
}

/**
* Default constructor. Sets version to zero.
*/
HWTimestamper() { version = 0; }
Expand Down
7 changes: 4 additions & 3 deletions daemons/gptp/common/ieee1588port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ IEEE1588Port::IEEE1588Port
void IEEE1588Port::timestamper_init(void)
{
if( _hw_timestamper != NULL ) {
_hw_timestamper->init_phy_delay(this->link_delay);
if( !_hw_timestamper->HWTimestamper_init( net_label, net_iface )) {
XPTPD_ERROR
( "Failed to initialize hardware timestamper, "
Expand All @@ -159,7 +160,6 @@ void IEEE1588Port::timestamper_init(void)
return;
}
}
_hw_timestamper->init_phy_delay(this->link_delay);
}

bool IEEE1588Port::init_port(int delay[4])
Expand Down Expand Up @@ -327,8 +327,9 @@ bool IEEE1588Port::restoreSerializedState( void *buf, off_t *count ) {
void *IEEE1588Port::openPort(IEEE1588Port *port)
{
port_ready_condition->signal();
struct phy_delay get_delay;
port->_hw_timestamper->get_phy_delay(&get_delay);
struct phy_delay get_delay = { 0, 0, 0, 0 };
if(port->_hw_timestamper)
port->_hw_timestamper->get_phy_delay(&get_delay);

while (1) {
PTPMessageCommon *msg;
Expand Down
2 changes: 1 addition & 1 deletion daemons/gptp/common/ptp_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ void PTPMessagePathDelayResp::processMessage(IEEE1588Port * port)
XPTPD_ERROR("Remote misbehaving. Stopping PDelay Requests for 5 minutes.");
port->stopPDelay();
port->getClock()->addEventTimerLocked
(port, PDELAY_RESP_PEER_MISBEHAVING_TIMEOUT_EXPIRES, 300 * 1000000000.0);
(port, PDELAY_RESP_PEER_MISBEHAVING_TIMEOUT_EXPIRES, (int64_t)(300 * 1000000000.0));
}
}
else {
Expand Down
13 changes: 1 addition & 12 deletions daemons/gptp/windows/daemon_cl/daemon_cl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ POSSIBILITY OF SUCH DAMAGE.

#define MACSTR_LENGTH 17

#define PHY_DELAY_GB_TX_I20 184 //1G delay in nanoseconds
#define PHY_DELAY_GB_RX_I20 382 //1G delay in nanoseconds
#define PHY_DELAY_MB_TX_I20 1044 //100M delay in nanoseconds
#define PHY_DELAY_MB_RX_I20 2133 //100M delay in nanoseconds

static bool exit_flag;

void print_usage( char *arg0 ) {
Expand Down Expand Up @@ -87,8 +82,8 @@ int _tmain(int argc, _TCHAR* argv[])
int32_t offset = 0;
bool syntonize = false;
uint8_t priority1 = 248;
int phy_delays[4] = { 0 };
int i;
int phy_delays[4] = { -1, -1, -1, -1 };

// Register default network interface
WindowsPCAPNetworkInterfaceFactory *default_factory = new WindowsPCAPNetworkInterfaceFactory();
Expand Down Expand Up @@ -139,12 +134,6 @@ int _tmain(int argc, _TCHAR* argv[])
parseMacAddr( argv[i], local_addr_ostr );
LinkLayerAddress local_addr(local_addr_ostr);

// Initialize default PHY delays
phy_delays[0] = PHY_DELAY_GB_TX_I20;
phy_delays[1] = PHY_DELAY_GB_RX_I20;
phy_delays[2] = PHY_DELAY_MB_TX_I20;
phy_delays[3] = PHY_DELAY_MB_RX_I20;

// Create HWTimestamper object
HWTimestamper *timestamper = new WindowsTimestamper();
// Create Clock object
Expand Down
89 changes: 72 additions & 17 deletions daemons/gptp/windows/daemon_cl/tsc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@

#include <intrin.h>
#include <stdint.h>

#define BASE_FREQUENCY 100000000 /*!< Base frequency in HZ */
#include <VersionHelpers.h>

/**
* @brief Gets the processor timestamp
Expand All @@ -50,30 +49,86 @@ inline unsigned __int64 PLAT_rdtsc()
return __rdtsc();
}

#define CLOCK_INFO_CPUID_LEAF (0x15)
#define SYSTEM_CLOCK_24MHZ (24000000)
#define MAX_MODEL_LIST_LEN (2)

typedef struct
{
short model_list[MAX_MODEL_LIST_LEN+1]; // Terminate model list with -1
uint32_t clock_rate; // clock_rate of 0 is invalid
}
ModelNumberSystemClockRateMapping;

static ModelNumberSystemClockRateMapping ModelNumberSystemClockRateMap[] =
{
{{ 0x5E, 0x4E, -1 }, SYSTEM_CLOCK_24MHZ },
{{ -1 }, 0 },
};

/**
* @brief Gets the system clock frequency using CPU model number
* @param model_query model number to look up
* @return System frequency, or 0 on error
*/
inline uint32_t FindFrequencyByModel(uint8_t model_query) {
ModelNumberSystemClockRateMapping *map = ModelNumberSystemClockRateMap;
uint32_t ret = 0;

while (map->clock_rate != 0)
{
short *model = map->model_list;

while (*model != -1)
{
if (*model == model_query) {
ret = map->clock_rate;
break;
}
++model;
}
++map;
}

return ret;
}


/**
* @brief Gets the TSC frequnecy
* @param millis time in miliseconds
* @return TSC frequency
* @return TSC frequency, or 0 on error
*/
inline uint64_t getTSCFrequency( unsigned millis ) {
UINT16 multiplierx2;
uint64_t frequency = 0;
DWORD mhz;
DWORD mhz_sz = sizeof(mhz);
int max_cpuid_level;
int tmp[4];

if( RegGetValue( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "~MHz", RRF_RT_REG_DWORD, NULL, &mhz, &mhz_sz ) != ERROR_SUCCESS ) {
goto done;
// Find the max cpuid level, and if possible find clock info
__cpuid(tmp, 0);
max_cpuid_level = tmp[0];
if (max_cpuid_level >= CLOCK_INFO_CPUID_LEAF)
__cpuid(tmp, CLOCK_INFO_CPUID_LEAF);

// For pre-Win10 on 6th Generation or greater Intel CPUs the raw hardware
// clock will be returned, *else* use QPC for everything else
//
// EAX (tmp[0]) must be >= 1, See Intel SDM 17.15.4 "Invariant Time-keeping"
if (!IsWindows10OrGreater() && max_cpuid_level >= CLOCK_INFO_CPUID_LEAF &&
tmp[0] >= 1) {
SYSTEM_INFO info;

GetSystemInfo(&info);

// Look at processor model (upper byte of revision) number to determine clock rate
return FindFrequencyByModel(info.wProcessorRevision >> 8);
}
fprintf( stderr, "mhz: %u\n", mhz );
multiplierx2 = (UINT16)((2*mhz*1000000ULL)/BASE_FREQUENCY);
if( multiplierx2 % 2 == 1 ) ++multiplierx2;
fprintf( stderr, "Multiplier: %hhu\n", multiplierx2/2 );

frequency = (((uint64_t)multiplierx2)*BASE_FREQUENCY)/2;
fprintf( stderr, "Frequency: %llu\n", frequency );
LARGE_INTEGER freq;

if (QueryPerformanceFrequency(&freq))
return freq.QuadPart;

done:
return frequency;
return 0;
}

#endif/*TSC_HPP*/
59 changes: 54 additions & 5 deletions daemons/gptp/windows/daemon_cl/windows_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ bool WindowsTimestamper::HWTimestamper_init( InterfaceLabel *iface_label, OSNetw
PIP_ADAPTER_INFO pAdapterInfo;
IP_ADAPTER_INFO AdapterInfo[32]; // Allocate information for up to 32 NICs
DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
struct phy_delay delay_val;

DWORD dwStatus = GetAdaptersInfo( AdapterInfo, &dwBufLen );
if( dwStatus != ERROR_SUCCESS ) return false;
Expand All @@ -87,12 +88,60 @@ bool WindowsTimestamper::HWTimestamper_init( InterfaceLabel *iface_label, OSNetw

if( pAdapterInfo == NULL ) return false;

if( strstr( pAdapterInfo->Description, NANOSECOND_CLOCK_PART_DESCRIPTION ) != NULL ) {
netclock_hz.QuadPart = NETCLOCK_HZ_NANO;
} else {
netclock_hz.QuadPart = NETCLOCK_HZ_OTHER;
get_phy_delay(&delay_val);

DeviceClockRateMapping *rate_map = DeviceClockRateMap;
while (rate_map->device_desc != NULL)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be rate_map != NULL here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps rate_map has a entry with device_desc == NULL to terminate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The expectation is that the array has at least one terminating entry where device_desc == NULL. This is for both the PHY delay and clock rate mapping.

{
if (strstr(pAdapterInfo->Description, rate_map->device_desc) != NULL)
break;
++rate_map;
}
if (rate_map->device_desc != NULL) {
netclock_hz.QuadPart = rate_map->clock_rate;
}
else {
XPTPD_ERROR("Unable to determine clock rate for interface %s", pAdapterInfo->Description);
return false;
}

DevicePhyDelayMapping *phy_map = DevicePhyDelayMap;
while (phy_map->device_desc != NULL)
{
if (strstr(pAdapterInfo->Description, phy_map->device_desc) != NULL)
break;
++phy_map;
}
if (phy_map->device_desc != NULL) {
if(delay_val.gb_rx_phy_delay == -1)
delay_val.gb_rx_phy_delay = phy_map->delay.gb_rx_phy_delay;
if (delay_val.gb_tx_phy_delay == -1)
delay_val.gb_tx_phy_delay = phy_map->delay.gb_tx_phy_delay;
if (delay_val.mb_rx_phy_delay == -1)
delay_val.mb_rx_phy_delay = phy_map->delay.mb_rx_phy_delay;
if (delay_val.mb_tx_phy_delay == -1)
delay_val.mb_tx_phy_delay = phy_map->delay.mb_tx_phy_delay;
set_phy_delay(&delay_val);
}

if (delay_val.gb_rx_phy_delay == -1) {
XPTPD_ERROR("Warning: Gbit receive PHY delay is unknown using 0");
delay_val.gb_rx_phy_delay = 0;
}
fprintf( stderr, "Adapter UID: %s\n", pAdapterInfo->AdapterName );
if (delay_val.gb_tx_phy_delay == -1) {
XPTPD_ERROR("Warning: Gbit transmit PHY delay is unknown using 0");
delay_val.gb_tx_phy_delay = 0;
}
if (delay_val.mb_rx_phy_delay == -1) {
XPTPD_ERROR("Warning: Mbit receive PHY delay is unknown using 0");
delay_val.mb_rx_phy_delay = 0;
}
if (delay_val.mb_tx_phy_delay == -1) {
XPTPD_ERROR("Warning: Mbit transmit PHY delay is unknown using 0");
delay_val.gb_tx_phy_delay = 0;
}

XPTPD_INFO( "Adapter UID: %s\n", pAdapterInfo->AdapterName );
PLAT_strncpy( network_card_id, NETWORK_CARD_ID_PREFIX, 63 );
PLAT_strncpy( network_card_id+strlen(network_card_id), pAdapterInfo->AdapterName, 63-strlen(network_card_id) );

Expand Down
Loading