]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Dynamic Retry implementation
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 20 May 2022 14:37:36 +0000 (16:37 +0200)
committerFrédéric Lécaille <flecaille@haproxy.com>
Fri, 20 May 2022 15:11:13 +0000 (17:11 +0200)
We rely on <conn_opening> stats counter and tune.quic.retry_threshold
setting to dynamically start sending Retry packets. We continue to send such packets
when "quic-force-retry" setting is set. The difference is when we receive tokens.
We check them regardless of this setting because the Retry could have been
dynamically started. We must also send Retry packets when we receive Initial
packets without token if the dynamic Retry threshold was reached but only for connection
which are not currently opening or in others words for Initial packets without
connection already instantiated. Indeed, we must not send Retry packets for all
Initial packets without token. For instance a client may have already sent an
Initial packet without receiving Retry packet because the Retry feature was not
started, then the Retry starts on exeeding the threshold value due to others
connections, then finally our client decide to send another Initial packet
(to ACK Initial CRYPTO data for instance). It does this without token. So, for
this already existing connection we must not send a Retry packet.

src/xprt_quic.c

index f73c51ae735e9012fe6cf9a45326c4d9ea015772..f3bdddc565129fd2d2156288b3da74116b019ff6 100644 (file)
@@ -5315,16 +5315,18 @@ static void qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
                        /* TODO Retry should be automatically activated if
                         * suspect network usage is detected.
                         */
-                       if (l->bind_conf->quic_force_retry && global.cluster_secret) {
+                       if (global.cluster_secret) {
                                if (!token_len) {
-                                       TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
-                                       if (send_retry(l->rx.fd, &dgram->saddr, pkt)) {
-                                               TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
+                                       if (l->bind_conf->quic_force_retry) {
+                                               TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
+                                               if (send_retry(l->rx.fd, &dgram->saddr, pkt)) {
+                                                       TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
+                                                       goto err;
+                                               }
+
+                                               HA_ATOMIC_INC(&prx_counters->retry_sent);
                                                goto err;
                                        }
-
-                                       HA_ATOMIC_INC(&prx_counters->retry_sent);
-                                       goto err;
                                }
                                else {
                                        if (*buf == QUIC_TOKEN_FMT_RETRY) {
@@ -5380,6 +5382,18 @@ static void qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
                                goto drop;
                        }
 
+                       if (global.cluster_secret && !pkt->token_len && !l->bind_conf->quic_force_retry &&
+                           HA_ATOMIC_LOAD(&prx_counters->conn_opening) >= global.tune.quic_retry_threshold) {
+                               TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
+                               if (send_retry(l->rx.fd, &dgram->saddr, pkt)) {
+                                       TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
+                                       goto err;
+                               }
+
+                               HA_ATOMIC_INC(&prx_counters->retry_sent);
+                               goto err;
+                       }
+
                        /* RFC 9000 7.2. Negotiating Connection IDs:
                         * When an Initial packet is sent by a client that has not previously
                         * received an Initial or Retry packet from the server, the client