tcp: rfc 6582: implemented NewReno modification
|Reported by:||a-star||Owned by:||axeld|
|Component:||Network & Internet/TCP||Version:||R1/Development|
|Keywords:||NewReno, TCP, network||Cc:|
|Has a Patch:||yes||Platform:||All|
The NewReno modification to TCP augments the fast recovery algorithm to accommodate for multiple packet loss in a single window of data.
Motivation: A single retransmit timeout might result in retransmissions of several data packets, but each invocation of the fast retransmit algorithm leads to retransmission of only a single data packet.
Partial Acknowledgment: if the ACK for the retransmitted packet acknowledges some but not all of the packets transmitted before fast retransmit.
As per RFC 6582:
New sender-side state variable called "recover" to record the send sequence number that must be acknowledged before the fast recovery is declared to be over.
On receipt of 3rd dup ack : If ack - 1 > recover, set recover = highest sequence number transmited and enter fast retransmit.
On receipt of an ACK that acknowledges in-flight data:
Full Acknowledgment: ack > recover
: two choices to deflate cwnd
1.cwnd = min(ssthresh, max(FlightSize, SMSS) + SMSS)
2.cwnd = ssthresh where ssthresh is the value set when fast retransmit was entered
[Based on the discussion in the rfc, if the second method was chosen more precautions will have to be taken so I went forth with the first]
: exit the fast recovery procedure
Partial Acknowledgment : retransmit the first unacknowledged packet after considering this ACK
: partially deflate cwnd by the amount of new data acknowledged
: If the ACK acknowledges alteast one SMSS of new data, set cwnd += SMSS
: Send a new segment if permitted by the new value of cwnd
: Do not exit fast recovery procedure
: For the first partial ACK during fast recovery, reset the retransmission timer
Upon retransmission timeout, record the highest seq number transmitted in the variable recover and exit the fast recovery procedure if applicable.
There are 2 ways to handle dup ACKs after RTO. Both of them uses heursitics. The first one is an ACK based heurisitc while the other is a timestamp based heurisitc. I chose to implement the ACK based one since the other one had some tricky failing cases and to avoid those failures other algorithms such as Eifel detection algorithm would have to be implemented (which are part of some other rfc altogether).
ACK based heurisitc:
In case of no real congestion, after a spurious retransmission, if the segments were already buffered by the receiver, the three dup acks that may be received by the sender will be accompanied by the ACK field advancing by at least 4 segments.
Therefore whenever the cumulative acknowledged field is advanced
store the value of previous cumulative ack as prev_highest_ack store the latest cumulative ack as highest_ack
Now when entering fast retransmit if ack - 1 is not greater than recover, also check if congestion window > SMSS && (highest_ack - prev_highest_ack) <= 4*SMSS. If so, enter fast retransmit.
May want to use a separate flag to record whether or not it is presently in the fast recovery procedure. The use of the value of the duplicate ACK count is not reliable since it can be reset upon window updates and out-of-order acknowledgments.
When updating cumulative ACK field outside of fast recovery, recover may also need to be updated in order to continue check permit into fast recovery. This issue arises when an update to the cumulative ACK field results in sequence wraparound that affects the ordering between the cumulative field and the state variable recover since entry into fast recovery is only permitted if the ACK covers more than recover.