]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Add a lock for RX packets
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 4 Jun 2021 08:33:32 +0000 (10:33 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Sep 2021 13:27:25 +0000 (15:27 +0200)
We must protect from concurrent the tree which stores the QUIC packets received
by the dgram I/O handler, these packets being also parsed by the xprt task.

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

index b9625354dd152696c6e6b78d91459422e2514216..97470dd65ab36874bfe59e32a3e50999f1f51936 100644 (file)
@@ -413,6 +413,7 @@ enum lock_label {
        SSL_SERVER_LOCK,
        SFT_LOCK, /* sink forward target */
        IDLE_CONNS_LOCK,
+       QUIC_LOCK,
        OTHER_LOCK,
        /* WT: make sure never to use these ones outside of development,
         * we need them for lock profiling!
@@ -466,6 +467,7 @@ static inline const char *lock_label(enum lock_label label)
        case SSL_SERVER_LOCK:      return "SSL_SERVER";
        case SFT_LOCK:             return "SFT";
        case IDLE_CONNS_LOCK:      return "IDLE_CONNS";
+       case QUIC_LOCK:            return "QUIC";
        case OTHER_LOCK:           return "OTHER";
        case DEBUG1_LOCK:          return "DEBUG1";
        case DEBUG2_LOCK:          return "DEBUG2";
index bf4f5f504f7f3db7bd779e603634ac2e726d3160..6c6a206caedfc174074e28a0eb8daefc5fae6da6 100644 (file)
@@ -530,6 +530,8 @@ struct quic_enc_level {
                /* The packets received by the listener I/O handler
                   with header protection removed. */
                struct eb_root pkts;
+               /* <pkts> must be protected from concurrent accesses */
+               __decl_thread(HA_RWLOCK_T rwlock);
                /* Liste of QUIC packets with protected header. */
                struct list pqpkts;
                /* Crypto frames */
index f4b95e79248b0909c619aeb11adfbb15f975a576..b7a191831a91f309817a849e815b96248bd48aec 100644 (file)
@@ -2403,7 +2403,9 @@ static inline void qc_rm_hp_pkts(struct quic_enc_level *el, struct quic_conn_ctx
                        pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
                        /* Store the packet into the tree of packets to decrypt. */
                        pqpkt->pn_node.key = pqpkt->pn;
+                       HA_RWLOCK_WRLOCK(QUIC_LOCK, &el->rx.rwlock);
                        quic_rx_packet_eb64_insert(&el->rx.pkts, &pqpkt->pn_node);
+                       HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &el->rx.rwlock);
                        TRACE_PROTO("hp removed", QUIC_EV_CONN_ELRMHP, ctx->conn, pqpkt);
                }
                quic_rx_packet_list_del(pqpkt);
@@ -2457,6 +2459,7 @@ int qc_treat_rx_pkts(struct quic_enc_level *el, struct quic_conn_ctx *ctx)
 
        TRACE_ENTER(QUIC_EV_CONN_ELRXPKTS, ctx->conn);
        tls_ctx = &el->tls_ctx;
+       HA_RWLOCK_WRLOCK(QUIC_LOCK, &el->rx.rwlock);
        node = eb64_first(&el->rx.pkts);
        while (node) {
                struct quic_rx_packet *pkt;
@@ -2495,6 +2498,7 @@ int qc_treat_rx_pkts(struct quic_enc_level *el, struct quic_conn_ctx *ctx)
                node = eb64_next(node);
                quic_rx_packet_eb64_delete(&pkt->pn_node);
        }
+       HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &el->rx.rwlock);
 
        if (!qc_treat_rx_crypto_frms(el, ctx))
                goto err;
@@ -2624,6 +2628,7 @@ static int quic_conn_enc_level_init(struct quic_conn *qc,
        qel->tls_ctx.tx.flags = 0;
 
        qel->rx.pkts = EB_ROOT;
+       HA_RWLOCK_INIT(&qel->rx.rwlock);
        LIST_INIT(&qel->rx.pqpkts);
 
        /* Allocate only one buffer. */
@@ -3002,7 +3007,9 @@ static inline int qc_try_rm_hp(struct quic_rx_packet *pkt,
                qpkt_trace = pkt;
                /* Store the packet */
                pkt->pn_node.key = pkt->pn;
+               HA_RWLOCK_WRLOCK(QUIC_LOCK, &qel->rx.rwlock);
                quic_rx_packet_eb64_insert(&qel->rx.pkts, &pkt->pn_node);
+               HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &qel->rx.rwlock);
        }
        else if (qel) {
                TRACE_PROTO("hp not removed", QUIC_EV_CONN_TRMHP, ctx ? ctx->conn : NULL, pkt);