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

Can Npcap use KeQuerySystemTimePrecise() if running on Windows 8 or later? #1407

Open
guyharris opened this Issue Dec 8, 2018 · 0 comments

Comments

Projects
None yet
2 participants
@guyharris
Copy link

guyharris commented Dec 8, 2018

Somebody complained about packet time stamps drifting from system time with WinPcap on Windows 10.

WinPcap has, at least on 32-bit Windows, a registry parameter HKLM\System\CurrentControlSet\Services\NPF\TimestampMode that controls how time stamps are generated:

  • 0 (default) -> Timestamps generated through KeQueryPerformanceCounter, less reliable on SMP/HyperThreading machines, precision = some microseconds
  • 2 -> Timestamps generated through KeQuerySystemTime, more reliable on SMP/HyperThreading machines, precision = scheduling quantum (10/15 ms)
  • 3 -> Timestamps generated through the i386 instruction RDTSC, less reliable on SMP/HyperThreading/SpeedStep machines, precision = some microseconds

There also appears to be a setting of 1, the symbol for which in time_calls.h is TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP, and a setting of 99, the symbol for which is TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP.

It looks as if, on 64-bit Windows, the RDTSC version isn't supported.

From a quick look at the Npcap driver, it seems to behave similarly, although the NT GET_TIME() code went from

#ifdef _X86_
	if ( TimestampMode == TIMESTAMPMODE_RDTSC )
    	{
		GetTimeRDTSC(dst,data);
	}
	else
#endif // _X86_
	if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
	{
		GetTimeQST(dst,data);
	}
	else
	{
		GetTimeKQPC(dst,data);
	}

in WinPcap to

#ifdef _X86_
	if (g_TimestampMode == TIMESTAMPMODE_RDTSC)
	{
		GetTimeRDTSC(dst, data);
	}
	else
		#endif // _X86_
	if (g_TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME)
	{
		GetTimeQST(dst, data);
	}
	else
	{
		GetTimeKQPC(dst, data);
	}

on Npcap - the mis-indentation of the #endif makes it less clear that modes 0 and 2 are still supported.

If a mode were supported in which KeQuerySystemTimePrecise() were used, at least on Windows 8 (and its server variant) and later, that would provide a mode that 1) gives high-resolution time stamps and 2) doesn't drift from the system clock, although it might be more costly than using KeQueryPerformanceCounter(). (And if it's not more costly, it's probably the best mode on 64-bit Windows, given that RDTSC isn't being used.)

Furthermore, given that there's now a pcap_set_tstamp_type() in libpcap, having the time stamp type be per-pcap_t, rather than system-wide, might be useful. You'd offer a choice between:

  • PCAP_TSTAMP_HOST - this would use KeQuerySystemTime() prior to Windows 8 and KeQuerySystemTimePrecise() on Windows 8 and later, and would always be available (it's the default in libpcap);
  • PCAP_TSTAMP_HOST_LOWPREC - this would always use KeQuerySystemTime(), and would be always be available;
  • PCAP_TSTAMP_HOST_HIPREC - this would always use KeQuerySystemTimePrecise(), and would only be available on Windows 8 and later.

If the other time stamp types are useful, we could add new PCAP_TSTAMP_ types for them, and make them available only on Windows (the PCAP_TSTAMP_ADAPTER types are available only on Linux - and they have a number of problems, not the least of which is that they give time as seconds since January 1, 1970, 00:00:00 TAI with at least some adapters; don't get me started on UN*X time stamps and leap seconds...).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment