]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Persistent congestion detection outside of controllers
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 2 Mar 2022 13:52:56 +0000 (14:52 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 4 Mar 2022 16:47:32 +0000 (17:47 +0100)
We establish the persistent congestion out of any congestion controller
to improve the algorithms genericity. This path characteristic detection may
be implemented regarless of the underlying congestion control algorithm.

Send congestion (loss) event using directly quic_cc_event(), so without
qc_cc_loss_event() wrapper function around quic_cc_event().

Take the opportunity of this patch to shorten "newest_time_sent" member field
of quic_cc_event to "time_sent".

include/haproxy/quic_cc-t.h
include/haproxy/quic_cc.h
src/quic_cc_newreno.c
src/xprt_quic.c

index e66fc726c3c560db2bce4649ddd63693df3f447a..f869dda0b1ab7c8bece033e005040e935ea6d859 100644 (file)
@@ -63,7 +63,7 @@ struct quic_cc_event {
                        unsigned int now_ms;
                        unsigned int max_ack_delay;
                        size_t lost_bytes;
-                       unsigned int newest_time_sent;
+                       unsigned int time_sent;
                        unsigned int period;
                } loss;
        };
index dbf0284ea0d22aaec395f608587bcb79ea9d0320..048a03a62a6e7710ac287787b11560031eee02cb 100644 (file)
@@ -61,7 +61,7 @@ static inline void quic_cc_event_trace(struct buffer *buf, const struct quic_cc_
                              " 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");
index 6ed5f06fb7bb17cb6fa05c6f8cf5ef921b122b35..e15b302b2b55cf17ed5981537605a96ea3ff11ca 100644 (file)
@@ -108,20 +108,13 @@ static void quic_cc_nr_ca_cb(struct quic_cc *cc, struct quic_cc_event *ev)
                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;
 
index 555041089b153731cdc7e835105f8a2664918b64..7973240459c8ee545b20802687f5498c4928ea19 100644 (file)
@@ -1575,7 +1575,7 @@ static inline void qc_cc_loss_event(struct quic_conn *qc,
                .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,
        };
 
@@ -1658,10 +1658,30 @@ static inline void qc_release_lost_pkts(struct quic_conn *qc,
                }
        }
 
+       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);