NewReno = AIMD, slow start, fast recovery, triple acknowledgement
if (seqno > _last_acked) { /* new data arrived */
if (! _in_fast_recovery) {
_last_acked = seqno;
_dupacks = 0;
inflate_window(); /* AI part of AIMD */
send_packets(now());
_last_sent_time = now();
} else if (seqno < _recover) {
uint32 new_data = seqno - _last_acked;
_last_acked = seqno;
if (new_data < _cwnd) {
_cwnd -= new_data;
} else {
_cwnd = 0;
};
_cwnd += _mss;
retransmit_packet(now());
send_packets(now());
} else {
uint32 flightsize = _highest_sent - seqno;
_cwnd = min(_ssthresh, flightsize + _mss);
_last_acked = seqno;
_dupacks = 0;
_in_fast_recovery = FALSE;
send_packets(now());
};
} else if (_in_fast_recovery) {
_cwnd += _mss; /* AI part of AIMD */
send_packets(now());
} else { /* old data duplicated */
_dupacks++;
if (_dupacks != 3) {
send_packets(now());
} else {
_ssthresh = max(_cwnd/2, (uint32)(2 * _mss));
/* MD part of AIMD */
retransmit_packet(now());
_cwnd = _ssthresh + 3*_mss;
_in_fast_recovery = TRUE;
_recover = _highest_sent;
};
}