]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: get rid of ->target quic_conn struct member
authorFrederic Lecaille <flecaille@haproxy.com>
Tue, 9 Sep 2025 09:49:33 +0000 (11:49 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Thu, 11 Sep 2025 07:51:28 +0000 (09:51 +0200)
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.

13 files changed:
include/haproxy/quic_conn-t.h
include/haproxy/quic_conn.h
include/haproxy/quic_sock.h
src/cli.c
src/quic_cli.c
src/quic_conn.c
src/quic_rx.c
src/quic_sock.c
src/quic_ssl.c
src/quic_tx.c
src/ssl_clienthello.c
src/ssl_ocsp.c
src/ssl_sock.c

index 75493915d5345e6121aea0afd25a21f0ef031fe1..890c06641c03bfde465b94eafbea64ae709ce23b 100644 (file)
@@ -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;                                              \
index 37050f8651de2a4a71630b84af5ca9b3dd96c849..78517753de43998f94b96ee1b25beb4221626f05 100644 (file)
@@ -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;
 
index d8b45ec323f3897de87010fb94f0eec51554de74..5753ddf619e488cffbf6eb563b0520a88216b52d 100644 (file)
@@ -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 <l> handshake current counter. If listener limit is
index ba0b3ab7b4a3ac070df7181d1fa039892b938dec..dd81c5e0e988ca6cc94798b35f8f0f60b3e682da 100644 (file)
--- 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
index d0300f847b873b7d02e4fa327b89f3ca866397c0..1f22f8d0574c057f90d61bdc6757d342472723f2 100644 (file)
@@ -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 */
 
index d55be2b4141152e948fdb5a4b438aa4bca390a23..95f8216d50e1723b9e488e1116d026e73267e94e 100644 (file)
@@ -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)
index 57cd7abbf40ee5460d7bbf4be2898f87ab5a2dd7..07a0481e7403dd84be55cdfb5663e6df4d23a911 100644 (file)
@@ -1674,7 +1674,9 @@ static inline int quic_token_validate(struct quic_rx_packet *pkt,
        goto leave;
 }
 
-/* Find the associated connection to the packet <pkt> or create a new one if
+/* Listener only function.
+ *
+ * Find the associated connection to the packet <pkt> or create a new one if
  * this is an Initial packet. <dgram> is the datagram containing the packet and
  * <l> 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. <li> is the listener attached to the receiver.
  *
+ * Note that for a QUIC backend, <from_qc> is never NULL. <o> 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.
  */
index bcef80a2f6ced223dd1e92fb44d1fa4d570621e4..6ec8e520f25ecbe3b35c7e38a66ffb58f731269a 100644 (file)
@@ -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. */
index e892e6159f09e863918a0271b08cdbdaddf1755c..7e20a906b272e6dd81bea7c64f4384a505bc318e 100644 (file)
@@ -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;
index 6c5631651191c7508ac8b172a012c1203c44c226..304ab6892d8b1d1a6b812d39b8256c6cfd6ab0e0 100644 (file)
@@ -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);
                                        }
index 2befabd73b5ce7e104dcbedf062ed1797a909cd8..1129f0c4ebc4174a6982522e9d161588ad76c219 100644 (file)
@@ -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) {
index 6d1a2178fa70f4eac70e0cbfa128f6aa9366b883..e650a3ce3dfe5e014568442673d7b04d06ba160f 100644 (file)
@@ -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
 
index d47ce1f26b4c09ebb334e1c8392bd84206306ffb..e1aa2936db7287a629c2ea3857fcbae2def8bbf2 100644 (file)
@@ -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