Based on their understanding of the Fast Retransmit algorithm, I believe the authors are giving you their real-world idea of what to expect. Understand, this is the authors' idea. Even your argument is made with some assumptions which may, or may not, be congruent with the authors' assumptions. You could contact the authors for clarification. A simple search turns up a verified e-mail address for Larry Peterson at the University of Arizona.
RFC 2581, TCP Congestion Control:
3.2 Fast Retransmit/Fast Recovery
A TCP receiver SHOULD send an immediate duplicate ACK when an out-
of-order segment arrives. The purpose of this ACK is to inform the
sender that a segment was received out-of-order and which sequence
number is expected. From the sender's perspective, duplicate ACKs
can be caused by a number of network problems. First, they can be
caused by dropped segments. In this case, all segments after the
dropped segment will trigger duplicate ACKs. Second, duplicate ACKs
can be caused by the re-ordering of data segments by the network (not
a rare event along some network paths [Pax97]). Finally, duplicate
ACKs can be caused by replication of ACK or data segments by the
network. In addition, a TCP receiver SHOULD send an immediate ACK
when the incoming segment fills in all or part of a gap in the
sequence space. This will generate more timely information for a
sender recovering from a loss through a retransmission timeout, a
fast retransmit, or an experimental loss recovery algorithm, such as
NewReno [FH98].
The TCP sender SHOULD use the "fast retransmit" algorithm to detect
and repair loss, based on incoming duplicate ACKs. The fast
retransmit algorithm uses the arrival of 3 duplicate ACKs (4
identical ACKs without the arrival of any other intervening packets)
as an indication that a segment has been lost. After receiving 3
duplicate ACKs, TCP performs a retransmission of what appears to be
the missing segment, without waiting for the retransmission timer to
expire.
After the fast retransmit algorithm sends what appears to be the
missing segment, the "fast recovery" algorithm governs the
transmission of new data until a non-duplicate ACK arrives. The
reason for not performing slow start is that the receipt of the
duplicate ACKs not only indicates that a segment has been lost, but
also that segments are most likely leaving the network (although a
massive segment duplication by the network can invalidate this
conclusion). In other words, since the receiver can only generate a
duplicate ACK when a segment has arrived, that segment has left the
network and is in the receiver's buffer, so we know it is no longer
consuming network resources. Furthermore, since the ACK "clock"
[Jac88] is preserved, the TCP sender can continue to transmit new
segments (although transmission must continue using a reduced cwnd).
The fast retransmit and fast recovery algorithms are usually
implemented together as follows.
When the third duplicate ACK is received, set ssthresh to no more
than the value given in equation 3.
Retransmit the lost segment and set cwnd to ssthresh plus 3*SMSS.
This artificially "inflates" the congestion window by the number
of segments (three) that have left the network and which the
receiver has buffered.
For each additional duplicate ACK received, increment cwnd by
SMSS. This artificially inflates the congestion window in order
to reflect the additional segment that has left the network.
Transmit a segment, if allowed by the new value of cwnd and the
receiver's advertised window.
When the next ACK arrives that acknowledges new data, set cwnd to
ssthresh (the value set in step 1). This is termed "deflating"
the window.
This ACK should be the acknowledgment elicited by the
retransmission from step 1, one RTT after the retransmission
(though it may arrive sooner in the presence of significant out-
of-order delivery of data segments at the receiver).
Additionally, this ACK should acknowledge all the intermediate
segments sent between the lost segment and the receipt of the
third duplicate ACK, if none of these were lost.
Note: This algorithm is known to generally not recover very
efficiently from multiple losses in a single flight of packets [FF96].
One proposed set of modifications to address this problem can be found
in [FH98].
To add to the previous answer:
A "Cumulative ACK" implies that all the bytes sent by the sender (so far) have been received correctly by the receiver. In order words, when the sender receives an ACK with sequence number n
, the receiver is telling the sender that it has received every byte up to and including n-1
and it is expecting byte n
next.
In "selective ACKs", the receiver sends ACKs for every packet that it has received, regardless of whether it was the packet that the receiver was expecting or not (i.e. whether the packet was out-of-order or not).
E.g. Let's assume that sender S sends 3 packets: pkt1
(seq # = 100), pkt2
(seq # = 200), and pkt3
(seq # = 300), but pkt2
gets lost in transmission.
With GBN: When the receiver R gets pkt1
: It sends ACK=200
, telling the sender that it has received all the bytes up to (but not including) 200 and is expecting byte 200 next. Now, pkt2
got lost, but pkt3
was received by the receiver. So, the receiver will send ACK=200 again and drop pkt3
because it is out-of-order. S will then have to re-transmit pkt2
AND pkt3
.
Once pkt2
is retransmitted and successfully received, R will send ACK=300 (i.e. it has received everything up to, but not including, byte 300 and is expecting byte 300, i.e. pkt3
). Once pkt3
is transmitted successfully, it will ACK that too.
With Selective Repeat (SR): Once R receives pkt1
, it will send an ACK for it. Once it receives pkt3
, it will send an ACK specifically for this packet too and will NOT drop the packet even though pkt3
is out-of-order (it will buffer it). Eventually, pkt2
will timeout on the sender's end, so the sender will retransmit pkt2
. If it's successful the receiver will send an ACK for it too.
Notice that, with SR, you didn't have to retransmit pkt3
even though pkt2
was lost. This is beneficial because it prevents the sender from having to retransmit the packets that had already been successfully received by the receiver (it's pointless, right? Why send pkt3
again when it was already delivered?). This helps avoid congestion in the network because you're not constantly retransmitting packets that DON'T need to be retransmitted.
In general, TCP's congestion control can be described as a combination/hybrid of GBN and Selective Repeat. Here's why:
TCP is similar to GBN because both protocols have a limit on the number of
unACK'd packets that the sender can send into the network. However, TCP is different from GBN because GBN requires the re-transmission of every unACK'd
packet when packets are lost, but TCP only retransmits the oldest unACK'd one.
TCP is similar to selective repeat because, when packets are lost due to congestion, the protocols do not require the sender to retransmit EVERY unACK'd packet sent by the sender. The sender just retransmits the oldest unACK'd packet. TCP is different from selective repeat because SR requires individual acknowledgement of each packet that was sent by the receiver; but rather than selectively ACKing every packet, TCP sends an ACK for the next packet that it is expecting (like GBN) and buffers the ones that it has received so far, even if they're out of order (like SR). That's why it can be considered a hybrid.
Hope this helps.
Best Answer
Your best way to understand TCP is to open up Wireshark, download a large file using HTTP, or any TCP protocol, and look for BLACK lines saying DUP ACK, Fast Retransmit, or Retransmit to scroll across your screen.
Generally you will see some packet loss over an internet connection, and you can dig into this further on your own to see your own client sending DUP ACK's for lost packets.
Or better yet, do an upload, and you can see your client doing a Fast Retransmit after it sees 3 identical ACK's.
You can also look closer at the TCP options and see the SACK's that manbearpig alluded to.
Another good source of info about fast-retransmits is the RFC. The second paragraph answers your comment about why 3 ACK's vs 1,2,4,5.
https://www.rfc-editor.org/rfc/rfc2001