]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Re-arm the PTO timer upon datagram receipt
authorFrédéric Lécaille <flecaille@haproxy.com>
Tue, 4 Jan 2022 16:03:11 +0000 (17:03 +0100)
committerFrédéric Lécaille <flecaille@haproxy.com>
Tue, 4 Jan 2022 16:30:00 +0000 (17:30 +0100)
When block by the anti-amplification limit, this is the responsability of the
client to unblock it sending new datagrams. On the server side, even if not
well parsed, such datagrams must trigger the PTO timer arming.

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

index 8005b9b8355a73615b45d066d709a994caa0a4d6..c6e4354edc669acb97004a7db49b8bb780ba4798 100644 (file)
@@ -615,8 +615,14 @@ struct rxbuf {
 #define QUIC_FL_PKTNS_ACK_REQUIRED  (1UL << QUIC_FL_PKTNS_ACK_REQUIRED_BIT)
 
 /* Flags at connection level */
-#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0)
-#define QUIC_FL_POST_HANDSHAKE_FRAMES_BUILT     (1U << 1)
+#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT 0
+#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED \
+       (1U << QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT)
+
+#define QUIC_FL_CONN_IO_CB_WAKEUP_BIT               1
+#define QUIC_FL_CONN_IO_CB_WAKEUP (1U << QUIC_FL_CONN_IO_CB_WAKEUP_BIT)
+
+#define QUIC_FL_POST_HANDSHAKE_FRAMES_BUILT     (1U << 2)
 #define QUIC_FL_CONN_IMMEDIATE_CLOSE            (1U << 31)
 struct quic_conn {
        /* The quic_conn instance is refcounted as it can be used by threads
index b4dca7533bf4a58d5737fa4d51ac28866de1d30c..93a24f089e1724a605f2020b1779e257d37b5a8a 100644 (file)
@@ -3097,6 +3097,15 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
        qr = NULL;
        st = HA_ATOMIC_LOAD(&qc->state);
        TRACE_ENTER(QUIC_EV_CONN_HDSHK, qc, &st);
+       if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IO_CB_WAKEUP) {
+               HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
+               /* The I/O handler has been woken up by the dgram listener
+                * after the anti-amplification was reached.
+                */
+               qc_set_timer(qc);
+               if (tick_isset(qc->timer) && tick_is_lt(qc->timer, now_ms))
+                       task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
+       }
        ssl_err = SSL_ERROR_NONE;
        zero_rtt = st < QUIC_HS_ST_COMPLETE &&
                (!MT_LIST_ISEMPTY(&qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA].rx.pqpkts) ||
@@ -4013,7 +4022,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
        struct quic_conn *qc, *qc_to_purge = NULL;
        struct listener *l;
        struct ssl_sock_ctx *conn_ctx;
-       int long_header = 0;
+       int long_header = 0, io_cb_wakeup = 0;
        size_t b_cspace;
        struct quic_enc_level *qel;
 
@@ -4218,6 +4227,17 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
         */
        if (!dgram_ctx->dcid.len) {
                memcpy(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len);
+               if (!quic_peer_validated_addr(qc) &&
+                   HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
+                       TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
+                                   QUIC_EV_CONN_LPKT, qc);
+                       /* Reset the anti-amplification bit. It will be set again
+                        * when sending the next packet if reached again.
+                        */
+                       HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT);
+                       HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
+                       io_cb_wakeup = 1;
+               }
        }
        else if (memcmp(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len)) {
                TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc);
@@ -4279,6 +4299,14 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
        return pkt->len;
 
  err:
+       /* Wakeup the I/O handler callback if the PTO timer must be armed.
+        * This cannot be done by this thread.
+        */
+       if (io_cb_wakeup) {
+               conn_ctx = HA_ATOMIC_LOAD(&qc->xprt_ctx);
+               if (conn_ctx && conn_ctx->wait_event.tasklet)
+                       tasklet_wakeup(conn_ctx->wait_event.tasklet);
+       }
        /* If length not found, consume the entire datagram */
        if (!pkt->len)
                pkt->len = end - beg;