From 8524f0f779858cf53ee621635e28edfbcae7c0ba Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 8 Feb 2022 15:03:40 +0100 Subject: [PATCH] MINOR: quic: use a global dghlrs for each thread Move the QUIC datagram handlers oustide of the receivers. Use a global handler per-thread which is allocated on post-config. Implement a free function on process deinit to avoid a memory leak. --- include/haproxy/proto_quic.h | 2 + include/haproxy/receiver-t.h | 1 - src/proto_quic.c | 104 +++++++++++++++++------------------ src/xprt_quic.c | 17 +++--- 4 files changed, 61 insertions(+), 63 deletions(-) diff --git a/include/haproxy/proto_quic.h b/include/haproxy/proto_quic.h index e703f4314..d015886ef 100644 --- a/include/haproxy/proto_quic.h +++ b/include/haproxy/proto_quic.h @@ -24,4 +24,6 @@ extern struct protocol proto_quic4; extern struct protocol proto_quic6; +extern struct quic_dghdlr *quic_dghdlrs; + #endif /* _HAPROXY_PROTO_QUIC_H */ diff --git a/include/haproxy/receiver-t.h b/include/haproxy/receiver-t.h index d0dddb984..274339d40 100644 --- a/include/haproxy/receiver-t.h +++ b/include/haproxy/receiver-t.h @@ -68,7 +68,6 @@ struct receiver { struct qring **tx_qrings; /* Array of rings (one by thread) */ struct mt_list tx_qring_list; /* The same as ->tx_qrings but arranged in a list */ - struct quic_dghdlr **dghdlrs; /* Datagram handlers (one by thread) */ struct rxbuf **rxbufs; /* Array of buffers for RX (one by thread) */ struct mt_list rxbuf_list; /* The same as ->rxbufs but arranged in a list */ #endif diff --git a/src/proto_quic.c b/src/proto_quic.c index 3862e31dd..5296721c1 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -47,6 +47,8 @@ #include #include +/* per-thread quic datagram handlers */ +struct quic_dghdlr *quic_dghdlrs; static void quic_add_listener(struct protocol *proto, struct listener *listener); static int quic_bind_listener(struct listener *listener, char *errmsg, int errlen); @@ -619,56 +621,6 @@ static int quic_alloc_rxbufs_listener(struct listener *l) return 0; } -/* Allocate QUIC listener datagram handlers, one by thread. - * Returns 1 if succeeded, 0 if not. - */ -static int quic_alloc_dghdlrs_listener(struct listener *l) -{ - int i; - - l->rx.dghdlrs = calloc(global.nbthread, sizeof *l->rx.dghdlrs); - if (!l->rx.dghdlrs) - return 0; - - for (i = 0; i < global.nbthread; i++) { - struct quic_dghdlr *dghdlr; - - dghdlr = calloc(1, sizeof *dghdlr); - if (!dghdlr) - goto err; - - dghdlr->task = tasklet_new(); - if (!dghdlr->task) { - free(dghdlr); - goto err; - } - - dghdlr->task->tid = i; - dghdlr->task->context = dghdlr; - dghdlr->task->process = quic_lstnr_dghdlr; - dghdlr->odcids = EB_ROOT_UNIQUE; - dghdlr->cids = EB_ROOT_UNIQUE; - MT_LIST_INIT(&dghdlr->dgrams); - l->rx.dghdlrs[i] = dghdlr; - } - - return 1; - - err: - for (i = 0; i < global.nbthread; i++) { - struct quic_dghdlr *dghdlr = l->rx.dghdlrs[i]; - - if (!dghdlr) - break; - - tasklet_free(dghdlr->task); - free(dghdlr); - } - free(l->rx.dghdlrs); - - return 0; -} - /* This function tries to bind a QUIC4/6 listener. It may return a warning or * an error message in if the message is at most bytes long * (including '\0'). Note that may be NULL if is also zero. @@ -700,9 +652,8 @@ static int quic_bind_listener(struct listener *listener, char *errmsg, int errle } if (!quic_alloc_tx_rings_listener(listener) || - !quic_alloc_rxbufs_listener(listener) || - !quic_alloc_dghdlrs_listener(listener)) { - msg = "could not initialize tx/rx rings or dgram handlers"; + !quic_alloc_rxbufs_listener(listener)) { + msg = "could not initialize tx/rx rings"; err |= ERR_WARN; goto udp_return; } @@ -745,6 +696,53 @@ static void quic_disable_listener(struct listener *l) fd_stop_recv(l->rx.fd); } +static int quic_alloc_dghdlrs(void) +{ + int i; + + quic_dghdlrs = calloc(global.nbthread, sizeof(struct quic_dghdlr)); + if (!quic_dghdlrs) { + ha_alert("Failed to allocate the quic datagram handlers.\n"); + return 0; + } + + for (i = 0; i < global.nbthread; i++) { + struct quic_dghdlr *dghdlr = &quic_dghdlrs[i]; + + dghdlr->task = tasklet_new(); + if (!dghdlr->task) { + ha_alert("Failed to allocate the quic datagram handler on thread %d.\n", i); + return 0; + } + + tasklet_set_tid(dghdlr->task, i); + dghdlr->task->context = dghdlr; + dghdlr->task->process = quic_lstnr_dghdlr; + + dghdlr->odcids = EB_ROOT_UNIQUE; + dghdlr->cids = EB_ROOT_UNIQUE; + + MT_LIST_INIT(&dghdlr->dgrams); + } + + return 1; +} +REGISTER_POST_CHECK(quic_alloc_dghdlrs); + +static int quic_deallocate_dghdlrs(void) +{ + int i; + + if (quic_dghdlrs) { + for (i = 0; i < global.nbthread; ++i) + tasklet_free(quic_dghdlrs[i].task); + free(quic_dghdlrs); + } + + return 1; +} +REGISTER_POST_DEINIT(quic_deallocate_dghdlrs); + /* * Local variables: * c-indent-level: 8 diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 5aa1893d1..bff17805c 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -2803,7 +2804,6 @@ static int quic_build_post_handshake_frames(struct quic_conn *qc) for (i = 1; i < qc->tx.params.active_connection_id_limit; i++) { struct quic_connection_id *cid; - struct listener *l = qc->li; frm = pool_alloc(pool_head_quic_frame); if (!frm) @@ -2814,7 +2814,7 @@ static int quic_build_post_handshake_frames(struct quic_conn *qc) goto err; /* insert the allocated CID in the receiver datagram handler tree */ - ebmb_insert(&l->rx.dghdlrs[tid]->cids, &cid->node, cid->cid.len); + ebmb_insert(&quic_dghdlrs[tid].cids, &cid->node, cid->cid.len); quic_connection_id_to_frm_cpy(frm, cid); LIST_APPEND(&qel->pktns->tx.frms, &frm->list); @@ -3617,7 +3617,7 @@ static struct quic_conn *qc_new_conn(unsigned int version, int ipv4, /* insert the allocated CID in the receiver datagram handler tree */ if (server) - ebmb_insert(&l->rx.dghdlrs[tid]->cids, &icid->node, icid->cid.len); + ebmb_insert(&quic_dghdlrs[tid].cids, &icid->node, icid->cid.len); /* Select our SCID which is the first CID with 0 as sequence number. */ qc->scid = icid->cid; @@ -4025,7 +4025,7 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, * socket addresses. */ quic_cid_saddr_cat(&pkt->dcid, saddr); - node = ebmb_lookup(&l->rx.dghdlrs[tid]->odcids, pkt->dcid.data, + node = ebmb_lookup(&quic_dghdlrs[tid].odcids, pkt->dcid.data, pkt->dcid.len + pkt->dcid.addrlen); if (node) { qc = ebmb_entry(node, struct quic_conn, odcid_node); @@ -4037,7 +4037,7 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, * also for INITIAL/0-RTT non-first packets with the final DCID in * used. */ - node = ebmb_lookup(&l->rx.dghdlrs[tid]->cids, pkt->dcid.data, pkt->dcid.len); + node = ebmb_lookup(&quic_dghdlrs[tid].cids, pkt->dcid.data, pkt->dcid.len); if (!node) goto end; @@ -4377,7 +4377,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end, } /* Insert the DCID the QUIC client has chosen (only for listeners) */ - n = ebmb_insert(&l->rx.dghdlrs[tid]->odcids, &qc->odcid_node, + n = ebmb_insert(&quic_dghdlrs[tid].odcids, &qc->odcid_node, qc->odcid.len + qc->odcid.addrlen); /* If the insertion failed, it means that another @@ -5336,7 +5336,6 @@ int quic_lstnr_dgram_dispatch(unsigned char *buf, size_t len, void *owner, unsigned char *dcid; size_t dcid_len; int cid_tid; - struct listener *l = owner; if (!len || !quic_get_dgram_dcid(buf, buf + len, &dcid, &dcid_len)) goto err; @@ -5356,9 +5355,9 @@ int quic_lstnr_dgram_dispatch(unsigned char *buf, size_t len, void *owner, dgram->saddr = *saddr; dgram->qc = NULL; LIST_APPEND(dgrams, &dgram->list); - MT_LIST_APPEND(&l->rx.dghdlrs[cid_tid]->dgrams, &dgram->mt_list); + MT_LIST_APPEND(&quic_dghdlrs[cid_tid].dgrams, &dgram->mt_list); - tasklet_wakeup(l->rx.dghdlrs[cid_tid]->task); + tasklet_wakeup(quic_dghdlrs[cid_tid].task); return 1;