If window scaling is in effect, then 16 bits may not be sufficient for the SACK option fields that define the origin and length of a block. There are two possible ways to handle this:
The first alternative would significantly reduce the number of blocks possible in a SACK option; therefore, we have chosen the second alternative, scaling the SACK information as well as the window.
Scaling the SACK information introduces some loss of precision, since a SACK option must report queued data blocks whose origins and lengths are multiples of the window scale factor rcv.scale. These reported blocks must be equal to or smaller than the actual blocks of queued data.
Specifically, suppose that the receiver has a contiguous block of queued data that occupies sequence numbers L, L+1, ... L+N-1, and that the window scale factor is S = rcv.scale. Then the corresponding block that will be reported in a SACK option will be:
Relative Origin = int((L+S-1)/S) Block Size = int((L+N)/S) - (Relative Origin)
where the function int(x) returns the greatest integer contained in x.
The resulting loss of precision is not a serious problem for the sender. If the data-sending TCP keeps track of the boundaries of all segments in its retransmission queue, it will generally be able to infer from the imprecise SACK data which full segments don't need to be retransmitted. This will fail only if S is larger than the maximum segment size, in which case some segments may be retransmitted unnecessarily. If the sending TCP does not keep track of transmitted segment boundaries, the imprecision of the scaled SACK quantities will only result in retransmitting a small amount of unneeded sequence space. On the average, the data sender will unnecessarily retransmit J*S bytes of the sequence space for each SACK received; here J is the number of blocks reported in the SACK, and S = snd.scale.