A sender and receiver connected via DropTail queue with 100 packets queue limit, RTT 100ms, 5 Mbps bottleneck (tcl script attached). The sender runs TCP/Linux with "cubic" congestion avoidance algorithm (tcl script attached).
The TCP cubic flow starts around 0.5s and ramps up the cwnd to around 325 packets. Soon, the drop tail queue starts dropping packets. However, the TCP cwnd doesn't decrease between 2s and 10s even though the queue drops multiple packets every RTT (plot attached). Around 10s the TCP cwnd converges and starts oscillating around 150 packets for the rest of the simulation. The fact that the TCP sender didn't cut back cwnd even after multiple drops per RTT is non-standard TCP behavior.
Digging more, (thanks to Dr. Injong Rhee and Yaogong Wang from NCSU), when TCP enters recovery state due to 3 duplicate ACKs or ECN, it records the maximum sequence number we have sent in a variable called recover_ (line 484 in ns-2.35/tcp/tcp-linux.cc) and will not come out of recovery state until it receives an incoming cumulative ACK for a sequence number greater than recover_ (line 460 in ns-2.35/tcp/tcp-linux.cc). During this recovery period, cwnd is held constant and TCP tries to recover the lost packets with the help of SACK. In this setting, due to severe congestion, a number of retransmitted packets get lost again. According to RFC 5681, "the loss of a retransmission should be taken as two indications of congestion and, therefore, cwnd (and ssthresh) MUST be lowered twice in this case". But this is not done by the current tcp-linux implementation in ns-2. This behavior may be exhibited by "Reno" and other congestion avoidance flavors under TCP/Linux.
Appreciate any insights/fixes for this issue.