[Winpcap-users] Packet timestamp strangeness

Richard Hansen pcap-ri at scientician.org
Fri Jun 30 22:11:03 GMT 2006


Gianluca Varenni <gianluca.varenni at cacetech.com> wrote:
> Second, the problem of the "delay" of 7-15ms is perfectly normal.  15ms is
> the scheduling time slice on NT SMP.  The timestamp that you obtain from
> GetSystemTime or GetSystemTimeAsFileTime is updated every time slice, so
> every 10 or 15ms (depending on the kernel you are using).

Ah ha!  That's why it's happening.  Thanks for the info!

Ioan Popescu <ipopescu at dataq.com> wrote:
> Gianluca Varenni wrote:
>> WinPcap instead uses KeQueryPerformanceCounter to obtain the timestamps
>> (usually).   <snip>
> 
> "Ke" prefixed APIs are only callable from drivers.  You can, however, use
> the "user mode" equivalent of those calls.  There are two APIs you'll 
> need to use in order to make use of the high resolution time.

I found QueryPerformanceCounter and QueryPerformanceFrequency (which, when combined, seem to do exactly what KeQueryPerformanceCounter does).  These are what you are referring to, correct?

Gianluca Varenni <gianluca.varenni at cacetech.com> wrote:
> Moreover, consider that there's a delay between when we timetag the 
> packets and put in the buffer, and when the app receives them.  This 
> behavior is controlled by the timeout you set in pcap_open_live and by 
> the mintocopy parameter that you can set with pcap_setmintocopy().  
> Please be careful modifying these parameters, as they can affect a 
> lot the CPU load.  I suggest you to search through the winpcap-users 
> archives for more details on mintocopy.

Thank you for the information.  I think I'll start out by setting to_ms to -1 and mintocopy to 0 to aid in understanding and debugging.  I'll adjust up as I learn more about the effect of these settings.

Ioan Popescu <ipopescu at dataq.com> wrote:
> Use "-1" as the timeout to return immediately.

That's very good to know.  I don't recall the documentation mentioning that fact.  Does it work on all the platforms supported by libpcap?  If so, that would be great.


So here is my current understanding:

KeQueryPerformanceCounter is not related to the current date and time (wall-clock time), so I believe WinPcap performs the following algorithm:

1.  When the interface is opened:
  a.  get and save the current wall-clock time (using KeGetSystemTime)
  b.  get and save the current counter value (using 
      KeQueryPerformanceCounter)

2.  When a packet comes in:
  a.  grab the current counter value and counter frequency (using 
      KeQueryPerformanceCounter)
  b.  subtract the initial counter value from the current counter value
  c.  divide that result by the counter frequency  (btw, what happens when 
      the CPU frequency changes, such as on a laptop?)
  d.  add that result to the wall-clock time saved when the interface was 
      opened
  e.  use that result as the timestamp value

Is this correct?

If it is correct, I can use QueryPerformanceCounter to get precise time differences.  However, I would have to somehow sync up with WinPcap's time to get accurate differences.  Regarding this, I have a few questions:

1.  How can I get the wall time and starting counter time used by WinPcap to calculate the timestamps?

2.  Do QueryPerformanceCounter and KeQueryPerformanceCounter use the same underlying counter (such that one returns the same value as if the other was called instead)?  The docs for QueryPerformanceCounter suggest that the value is possibly CPU-dependent on multi-CPU systems.  How do I know which CPU is the right CPU to query?

If it's not possible to easily grab the time and counter values used by WinPcap, I should be able to do a fairly accurate time synchronization by doing the following:

1.  When the interface is opened:
  a.  get and save the current wall time (using GetSystemTimeAsFileTime)
  b.  get and save the current counter value (using 
      QueryPerformanceCounter)
  c.  initialize a boolean value "myClockIsBehind" to false

2.  When a packet comes in:
  a.  grab the current counter value (using QueryPerformanceCounter)
  b.  grab the current counter frequency (using QueryPerformanceFrequency)
  c.  subtract the initial counter value from the current counter value
  d.  divide that result by the counter frequency
  e.  add that result to the wall time I saved when the interface was 
      opened
  f.  if my time is less than the time stamp, set "myClockIsBehind" to 
      true and add the difference to the wall time I saved when the 
      interface was opened
  g.  otherwise, if "myClockIsBehind" is false and my time is greater 
      than the timestamp, subtract the difference from the wall time I 
      saved when the interface was opened

Over time, this would sync my clock to within the shortest amount of time between timestamping the packet and calling the packet handler callback.

What do you think?  Is this a good approach?

Thank you all very much for your information and help!

Richard




More information about the Winpcap-users mailing list