From: Frédéric Lécaille Date: Fri, 4 Jun 2021 08:33:32 +0000 (+0200) Subject: MINOR: quic: Add a lock for RX packets X-Git-Tag: v2.5-dev8~123 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9fccace8b0b88fba8d384f3cf61e1cc3eaa8d5eb;p=thirdparty%2Fhaproxy.git MINOR: quic: Add a lock for RX packets 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. --- diff --git a/include/haproxy/thread.h b/include/haproxy/thread.h index b9625354dd..97470dd65a 100644 --- a/include/haproxy/thread.h +++ b/include/haproxy/thread.h @@ -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"; diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index bf4f5f504f..6c6a206cae 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -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; + /* must be protected from concurrent accesses */ + __decl_thread(HA_RWLOCK_T rwlock); /* Liste of QUIC packets with protected header. */ struct list pqpkts; /* Crypto frames */ diff --git a/src/xprt_quic.c b/src/xprt_quic.c index f4b95e7924..b7a191831a 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -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);