TCP ACKs can be used to measure the round-trip time to a TCP receiver, and they can do so very accurately: since ACKs are generated in the ISR (interrupt service routine), they involve only the lowest level of software and directly reflect the hardware path across the network and into the server NIC.
However it is far from trivial to use TCP ACKs to make a clean RTT measurement. First of all, TCP ACKs are invisible to the application layer, and so network capture must be used to timestamp the ACKs. Once a network capture point is chosen, the round-trip time can be measured by comparing the timestamp of when data is sent to the receiver to when an ACK matching that data is received. These raw measurements are not always reflective of the round-trip time:
- The receiver may have delayed the acknowledgement, as per RFC 1122, 188.8.131.52, in the hope that the application will respond to the received data by sending a response, onto which it can piggy-back the ACK. The RFC allows the stack to delay the ACK by up to 500ms, but a more typical timeout is the Linux default of 50ms. RTT measured from a delayed ACK will be inflated by the length of the timeout.
- TCP's cumulative ACK model allows a single ACK to acknowledge more than one received segment. In this case, the apparent RTT from an earlier segment to the ACK is inflated by the time difference between this earlier segment and the final one that triggers the ACK.
- When a segment is retransmitted, the resulting RTT is ambiguous:
- if the first transmission was actually dropped, then the ACK was generated in response to the retransmission, and measuring the RTT from the first transmission inflates the RTT;
- if the first transmission was successful, and the ACK was simply delayed, then measuring the RTT from the second segment underestimates the true round-trip time.
Careful filtering of the raw RTT measurements is required to derive reliable RTT measurements. Corvil invented a method for doing this, which was granted patent protection under U.S. patent number US8493875B2 and European patent number EP2234333.