" time_sent=%u period=%u",
ev->loss.now_ms, ev->loss.max_ack_delay,
(unsigned long long)ev->loss.lost_bytes,
- ev->loss.newest_time_sent, ev->loss.period);
+ ev->loss.time_sent, ev->loss.period);
break;
case QUIC_CC_EVT_ECN_CE:
chunk_appendf(buf, "ecn_ce");
break;
case QUIC_CC_EVT_LOSS:
- if (ev->loss.newest_time_sent > cc->algo_state.nr.recovery_start_time) {
- cc->algo_state.nr.recovery_start_time = ev->loss.now_ms;
- cc->algo_state.nr.cwnd = QUIC_MAX(cc->algo_state.nr.cwnd >> 1, path->min_cwnd);
- cc->algo_state.nr.ssthresh = cc->algo_state.nr.cwnd;
- }
- if (quic_loss_persistent_congestion(&path->loss,
- ev->loss.period,
- ev->loss.now_ms,
- ev->loss.max_ack_delay)) {
- cc->algo_state.nr.cwnd = path->min_cwnd;
- /* Re-entering slow start state. */
- cc->algo_state.nr.state = QUIC_CC_ST_SS;
- cc->algo_state.nr.recovery_start_time = 0;
- }
+ /* Do not decrease the congestion window when already in recovery period. */
+ if (ev->loss.time_sent <= cc->algo_state.nr.recovery_start_time)
+ goto out;
+
+ cc->algo_state.nr.recovery_start_time = now_ms;
+ cc->algo_state.nr.ssthresh = cc->algo_state.nr.cwnd;
+ cc->algo_state.nr.cwnd = QUIC_MAX(cc->algo_state.nr.cwnd >> 1, path->min_cwnd);
path->cwnd = cc->algo_state.nr.cwnd;
break;
.loss.now_ms = now_ms,
.loss.max_ack_delay = qc->max_ack_delay,
.loss.lost_bytes = lost_bytes,
- .loss.newest_time_sent = newest_time_sent,
+ .loss.time_sent = newest_time_sent,
.loss.period = period,
};
}
}
+ if (newest_lost) {
+ /* Sent a congestion event to the controller */
+ struct quic_cc_event ev = {
+ .type = QUIC_CC_EVT_LOSS,
+ .loss.time_sent = newest_lost->time_sent,
+ };
+
+ quic_cc_event(&qc->path->cc, &ev);
+ }
+
+ /* If an RTT have been already sampled, <rtt_min> has been set.
+ * We must check if we are experiencing a persistent congestion.
+ * If this is the case, the congestion controller must re-enter
+ * slow start state.
+ */
+ if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
+ unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
+
+ if (quic_loss_persistent_congestion(&qc->path->loss, period,
+ now_ms, qc->max_ack_delay))
+ qc->path->cc.algo->slow_start(&qc->path->cc);
+ }
+
if (lost_bytes) {
- /* Sent a packet loss event to the congestion controller. */
- qc_cc_loss_event(qc, lost_bytes, newest_lost->time_sent,
- newest_lost->time_sent - oldest_lost->time_sent, now_us);
quic_tx_packet_refdec(oldest_lost);
if (newest_lost != oldest_lost)
quic_tx_packet_refdec(newest_lost);