From 47bb15ca84d09a56f596114591457af24ea3a626 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Tue, 9 Sep 2025 11:49:33 +0200 Subject: [PATCH] MINOR: quic: get rid of ->target quic_conn struct member The ->li (struct listener *) member of quic_conn struct was replaced by a ->target (struct obj_type *) member by this commit: MINOR: quic-be: get rid of ->li quic_conn member to abstract the connection type (front or back) when implementing QUIC for the backends. In these cases, ->target was a pointer to the ojb_type of a server struct. This could not work with the dynamic servers contrary to the listeners which are not dynamic. This patch almost reverts the one mentioned above. ->target pointer to obj_type member is replaced by ->li pointer to listener struct member. As the listener are not dynamic, this is easy to do this. All one has to do is to replace the objt_listener(qc->target) statement by qc->li where applicable. For the backend connection, when needed, this is always qc->conn->target which is used only when qc->conn is initialized. The only "problematic" case is for quic_dgram_parse() which takes a pointer to an obj_type as third argument. But this obj_type is only used to call quic_rx_pkt_parse(). Inside this function it is used to access the proxy counters of the connection thanks to qc_counters(). So, this obj_type argument may be null for now on with this patch. This is the reason why qc_counters() is modified to take this into consideration. --- include/haproxy/quic_conn-t.h | 2 +- include/haproxy/quic_conn.h | 9 +++++++-- include/haproxy/quic_sock.h | 4 ++-- src/cli.c | 4 ++-- src/quic_cli.c | 5 +++-- src/quic_conn.c | 18 +++++++++--------- src/quic_rx.c | 10 ++++++++-- src/quic_sock.c | 13 +++++++------ src/quic_ssl.c | 6 +++--- src/quic_tx.c | 2 +- src/ssl_clienthello.c | 2 +- src/ssl_ocsp.c | 2 +- src/ssl_sock.c | 4 ++-- 13 files changed, 47 insertions(+), 34 deletions(-) diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 75493915d..890c06641 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -322,7 +322,7 @@ struct qcc_app_ops; * with a connection \ */ \ struct eb_root *cids; \ - enum obj_type *target; \ + struct listener *li; \ /* Idle timer task */ \ struct task *idle_timer_task; \ unsigned int idle_expire; \ diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 37050f865..78517753d 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -173,9 +173,14 @@ static inline void quic_free_ncbuf(struct ncbuf *ncbuf) static inline void *qc_counters(enum obj_type *o, const struct stats_module *m) { struct proxy *p; - struct listener *l = objt_listener(o); - struct server *s = objt_server(o); + struct listener *l; + struct server *s; + if (!o) + return NULL; + + l = objt_listener(o); + s = objt_server(o); p = l ? l->bind_conf->frontend : s ? s->proxy : NULL; diff --git a/include/haproxy/quic_sock.h b/include/haproxy/quic_sock.h index d8b45ec32..5753ddf61 100644 --- a/include/haproxy/quic_sock.h +++ b/include/haproxy/quic_sock.h @@ -79,8 +79,8 @@ static inline char qc_test_fd(struct quic_conn *qc) */ static inline int qc_fd(struct quic_conn *qc) { - /* TODO: check this: For backends, qc->fd is always initialized */ - return qc_test_fd(qc) ? qc->fd : __objt_listener(qc->target)->rx.fd; + /* For backends, qc->fd is always initialized */ + return qc_test_fd(qc) ? qc->fd : qc->li->rx.fd; } /* Try to increment handshake current counter. If listener limit is diff --git a/src/cli.c b/src/cli.c index ba0b3ab7b..dd81c5e0e 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1425,8 +1425,8 @@ static int cli_io_handler_show_fd(struct appctx *appctx) #if defined(USE_QUIC) else if (fdt.iocb == quic_conn_sock_fd_iocb) { qc = fdtab[fd].owner; - li = qc ? objt_listener(qc->target) : NULL; - sv = qc ? objt_server(qc->target) : NULL; + li = qc ? qc->li : NULL; + sv = qc ? (qc->conn ? objt_server(qc->conn->target) : NULL) : NULL; xprt_ctx = qc ? qc->xprt_ctx : NULL; conn = qc ? qc->conn : NULL; xprt = conn ? conn->xprt : NULL; // in fact it's &ssl_quic diff --git a/src/quic_cli.c b/src/quic_cli.c index d0300f847..1f22f8d05 100644 --- a/src/quic_cli.c +++ b/src/quic_cli.c @@ -181,10 +181,11 @@ static void dump_quic_oneline(struct show_quic_ctx *ctx, struct quic_conn *qc) char bufaddr[INET6_ADDRSTRLEN], bufport[6]; int ret; unsigned char cid_len; - struct listener *l = objt_listener(qc->target); + struct listener *l = qc->li; ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr, - l ? l->bind_conf->frontend->id : __objt_server(qc->target)->id); + l ? l->bind_conf->frontend->id : + qc->conn ? __objt_server(qc->conn->target)->id : "UNKNOWN"); chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */ diff --git a/src/quic_conn.c b/src/quic_conn.c index d55be2b41..95f8216d5 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -749,7 +749,7 @@ static struct quic_conn_closed *qc_new_cc_conn(struct quic_conn *qc) cc_qc->dcid = qc->dcid; cc_qc->scid = qc->scid; - cc_qc->target = qc->target; + cc_qc->li = qc->li; cc_qc->cids = qc->cids; cc_qc->idle_timer_task = qc->idle_timer_task; @@ -1113,7 +1113,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, goto err; } - qc->target = target; + qc->li = l; /* Now that quic_conn instance is allocated, quic_conn_release() will * ensure global accounting is decremented. */ @@ -1418,7 +1418,7 @@ int qc_handle_conn_migration(struct quic_conn *qc, * used during the handshake, unless the endpoint has acted on a * preferred_address transport parameter from the peer. */ - if (__objt_listener(qc->target)->bind_conf->quic_params.disable_active_migration) { + if (qc->li->bind_conf->quic_params.disable_active_migration) { TRACE_ERROR("Active migration was disabled, datagram dropped", QUIC_EV_CONN_LPKT, qc); goto err; } @@ -1548,8 +1548,8 @@ int quic_conn_release(struct quic_conn *qc) */ if (MT_LIST_INLIST(&qc->accept_list)) { MT_LIST_DELETE(&qc->accept_list); - BUG_ON(__objt_listener(qc->target)->rx.quic_curr_accept == 0); - HA_ATOMIC_DEC(&__objt_listener(qc->target)->rx.quic_curr_accept); + BUG_ON(qc->li->rx.quic_curr_accept == 0); + HA_ATOMIC_DEC(&qc->li->rx.quic_curr_accept); } /* Subtract last congestion window from global memory counter. */ @@ -1622,8 +1622,8 @@ int quic_conn_release(struct quic_conn *qc) /* Connection released before handshake completion. */ if (unlikely(qc->state < QUIC_HS_ST_COMPLETE)) { if (!qc_is_back(qc)) { - BUG_ON(__objt_listener(qc->target)->rx.quic_curr_handshake == 0); - HA_ATOMIC_DEC(&__objt_listener(qc->target)->rx.quic_curr_handshake); + BUG_ON(qc->li->rx.quic_curr_handshake == 0); + HA_ATOMIC_DEC(&qc->li->rx.quic_curr_handshake); } } @@ -2031,8 +2031,8 @@ void qc_bind_tid_commit(struct quic_conn *qc, struct listener *new_li) /* At this point no connection was accounted for yet on this * listener so it's OK to just swap the pointer. */ - if (new_li && new_li != __objt_listener(qc->target)) { - qc->target = &new_li->obj_type; + if (new_li && new_li != qc->li) { + qc->li = new_li; /* Update GSO conn support based on new listener status. */ if (HA_ATOMIC_LOAD(&new_li->flags) & LI_F_UDP_GSO_NOTSUPP) diff --git a/src/quic_rx.c b/src/quic_rx.c index 57cd7abbf..07a0481e7 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -1674,7 +1674,9 @@ static inline int quic_token_validate(struct quic_rx_packet *pkt, goto leave; } -/* Find the associated connection to the packet or create a new one if +/* Listener only function. + * + * Find the associated connection to the packet or create a new one if * this is an Initial packet. is the datagram containing the packet and * is the listener instance on which it was received. * @@ -2112,7 +2114,8 @@ static int quic_rx_pkt_parse(struct quic_conn *qc, struct quic_rx_packet *pkt, return 0; drop: - HA_ATOMIC_INC(&prx_counters->dropped_pkt); + if (prx_counters) + HA_ATOMIC_INC(&prx_counters->dropped_pkt); drop_silent: if (!pkt->len) pkt->len = end - beg; @@ -2308,6 +2311,9 @@ static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt, * function will thus retrieve the connection from the CID tree or allocate a * new one if possible.
  • is the listener attached to the receiver. * + * Note that for a QUIC backend, is never NULL. is never NULL + * for a QUIC frontend. + * * Returns 0 on success else non-zero. If an error happens, some packets from * the datagram may not have been parsed. */ diff --git a/src/quic_sock.c b/src/quic_sock.c index bcef80a2f..6ec8e520f 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -87,7 +87,7 @@ int quic_sock_get_dst(struct connection *conn, struct sockaddr *addr, socklen_t memcpy(addr, &qc->peer_addr, len); } else { struct sockaddr_storage *from; - struct listener *l = objt_listener(qc->target); + struct listener *l = qc->li; /* Return listener address if IP_PKTINFO or friends are not * supported by the socket. @@ -701,7 +701,7 @@ static int qc_may_use_saddr(struct quic_conn *qc) * possible. This is not useful if the listening socket is bound to * a specific address. It is even prohibited on FreeBSD. */ - return (!is_addr(&__objt_listener(qc->target)->rx.addr) && + return (!is_addr(&qc->li->rx.addr) && is_addr(&qc->local_addr)); } @@ -839,7 +839,7 @@ int qc_rcv_buf(struct quic_conn *qc) struct buffer buf = BUF_NULL; unsigned char *dgram_buf; ssize_t ret = 0; - struct listener *l = objt_listener(qc->target); + struct listener *l = qc->li; /* Do not call this if quic-conn FD is uninitialized. */ BUG_ON(qc->fd < 0); @@ -948,7 +948,8 @@ int qc_rcv_buf(struct quic_conn *qc) continue; } - quic_dgram_parse(new_dgram, qc, qc->target); + quic_dgram_parse(new_dgram, qc, l ? &l->obj_type : + (qc->conn ? &__objt_server(qc->conn->target)->obj_type : NULL)); /* A datagram must always be consumed after quic_parse_dgram(). */ BUG_ON(new_dgram->buf); } while (ret > 0); @@ -975,7 +976,7 @@ int qc_rcv_buf(struct quic_conn *qc) void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src, const struct sockaddr_storage *dst) { - struct listener *l = __objt_listener(qc->target); + struct listener *l = qc->li; struct bind_conf *bc = l->bind_conf; struct proxy *p = bc->frontend; int fd = -1; @@ -1083,7 +1084,7 @@ struct quic_accept_queue *quic_accept_queues; void quic_accept_push_qc(struct quic_conn *qc) { struct quic_accept_queue *queue = &quic_accept_queues[tid]; - struct listener *l = __objt_listener(qc->target); + struct listener *l = qc->li; struct li_per_thread *lthr = &l->per_thr[ti->ltid]; /* A connection must only be accepted once per instance. */ diff --git a/src/quic_ssl.c b/src/quic_ssl.c index e892e6159..7e20a906b 100644 --- a/src/quic_ssl.c +++ b/src/quic_ssl.c @@ -938,7 +938,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx) * handshake level CRYPTO data which are validated by the TLS stack. */ if (!qc_is_back(qc)) { - if (__objt_listener(qc->target)->bind_conf->ssl_conf.early_data && + if (qc->li->bind_conf->ssl_conf.early_data && (!qc->ael || !qc->ael->tls_ctx.rx.secret)) { TRACE_PROTO("SSL handshake in progress", QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err); @@ -982,7 +982,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx) qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; if (!qc_is_back(qc)) { - struct listener *l = __objt_listener(qc->target); + struct listener *l = qc->li; /* I/O callback switch */ qc->wait_event.tasklet->process = quic_conn_app_io_cb; qc->state = QUIC_HS_ST_CONFIRMED; @@ -1268,7 +1268,7 @@ int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn) ctx->qc = qc; if (!qc_is_back(qc)) { - struct bind_conf *bc = __objt_listener(qc->target)->bind_conf; + struct bind_conf *bc = qc->li->bind_conf; if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl, NULL, 1) == -1) goto err; diff --git a/src/quic_tx.c b/src/quic_tx.c index 6c5631651..304ab6892 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -333,7 +333,7 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx) /* Permanently disable UDP GSO for future conns which use current listener/server instance. */ if (!qc_is_back(qc)) { - struct listener *l = __objt_listener(qc->target); + struct listener *l = qc->li; TRACE_ERROR("mark listener UDP GSO as unsupported", QUIC_EV_CONN_SPPKTS, qc, first_pkt); HA_ATOMIC_OR(&l->flags, LI_F_UDP_GSO_NOTSUPP); } diff --git a/src/ssl_clienthello.c b/src/ssl_clienthello.c index 2befabd73..1129f0c4e 100644 --- a/src/ssl_clienthello.c +++ b/src/ssl_clienthello.c @@ -174,7 +174,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) s = __objt_listener(conn->target)->bind_conf; #ifdef USE_QUIC else if (qc) - s = __objt_listener(qc->target)->bind_conf; + s = qc->li->bind_conf; #endif /* USE_QUIC */ if (!s) { diff --git a/src/ssl_ocsp.c b/src/ssl_ocsp.c index 6d1a2178f..e650a3ce3 100644 --- a/src/ssl_ocsp.c +++ b/src/ssl_ocsp.c @@ -132,7 +132,7 @@ int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg) struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); /* null if not a listener */ - li = objt_listener(qc->target); + li = qc->li; } #endif diff --git a/src/ssl_sock.c b/src/ssl_sock.c index d47ce1f26..e1aa2936d 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1135,7 +1135,7 @@ static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned ref = __objt_listener(conn->target)->bind_conf->keys_ref; #ifdef USE_QUIC else if (qc) - ref = __objt_listener(qc->target)->bind_conf->keys_ref; + ref = qc->li->bind_conf->keys_ref; #endif if (!ref) { @@ -1691,7 +1691,7 @@ int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store) else { qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); BUG_ON(!qc); /* Must never happen */ - bind_conf = __objt_listener(qc->target)->bind_conf; + bind_conf = qc->li->bind_conf; ctx = qc->xprt_ctx; } #endif