]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: QUIC conn initialization from I/O handler
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 31 May 2021 07:30:14 +0000 (09:30 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Sep 2021 13:27:25 +0000 (15:27 +0200)
Move the QUIC conn (struct quic_conn) initialization from quic_sock_accept_conn()
to qc_lstnr_pkt_rcv() as this is done for the server part.
Move the timer initialization to ->start xprt callback to ensure the connection
context is done : it is initialized by the ->accept callback which may be run
by another thread than the one for the I/O handler which also run ->start.

include/haproxy/xprt_quic.h
src/quic_sock.c
src/xprt_quic.c

index 1e4d684a148eac3f1b7d498891765fa84bc4df6b..65a2aa40ae1fda6e16c2c648aae7f148796e2d1c 100644 (file)
@@ -1135,11 +1135,6 @@ static inline void free_quic_rx_packet(struct quic_rx_packet *pkt)
        quic_rx_packet_refdec(pkt);
 }
 
-int qc_new_conn_init(struct quic_conn *conn, int ipv4,
-                     struct eb_root *quic_initial_clients,
-                     struct eb_root *quic_clients,
-                     unsigned char *dcid, size_t dcid_len,
-                     unsigned char *scid, size_t scid_len);
 ssize_t quic_lstnr_dgram_read(char *buf, size_t len, void *owner,
                               struct sockaddr_storage *saddr);
 ssize_t quic_srv_dgram_read(char *buf, size_t len, void *owner,
index aee5ce24b9b645067cc41fa825f7deb13b517194..042c35d97089f64310facb2b46848a9fc46b1818 100644 (file)
@@ -142,8 +142,7 @@ struct connection *quic_sock_accept_conn(struct listener *l, int *status)
 {
        struct quic_conn *qc;
        struct quic_rx_packet *pkt;
-       struct quic_cid *odcid;
-       int ret, ipv4;
+       int ret;
 
        qc = NULL;
        pkt = LIST_ELEM(l->rx.qpkts.n, struct quic_rx_packet *, rx_list);
@@ -156,27 +155,6 @@ struct connection *quic_sock_accept_conn(struct listener *l, int *status)
        if (!new_quic_cli_conn(qc, l, &pkt->saddr))
                goto err;
 
-       ipv4 = pkt->saddr.ss_family == AF_INET;
-       if (!qc_new_conn_init(qc, ipv4, &l->rx.odcids, &l->rx.cids,
-                             pkt->dcid.data, pkt->dcid.len,
-                             pkt->scid.data, pkt->scid.len))
-               goto err;
-
-       odcid = &qc->rx.params.original_destination_connection_id;
-       /* Copy the transport parameters. */
-       qc->rx.params = l->bind_conf->quic_params;
-       /* Copy original_destination_connection_id transport parameter. */
-       memcpy(odcid->data, &pkt->dcid, pkt->odcid_len);
-       odcid->len = pkt->odcid_len;
-       /* Copy the initial source connection ID. */
-       quic_cid_cpy(&qc->rx.params.initial_source_connection_id, &qc->scid);
-       qc->enc_params_len =
-               quic_transport_params_encode(qc->enc_params,
-                                            qc->enc_params + sizeof qc->enc_params,
-                                            &qc->rx.params, 1);
-       if (!qc->enc_params_len)
-               goto err;
-
        ret = CO_AC_DONE;
 
  done:
index 6e2fde9b58fa9b1fb15e7ea7f72aaf2611773312..9d36777b25e7564d7a3fcb49f63f12466d209880 100644 (file)
@@ -2796,20 +2796,20 @@ static struct task *process_timer(struct task *task, void *ctx, unsigned int sta
  * <scid> is the source connection ID with <scid_len> as length.
  * Returns 1 if succeeded, 0 if not.
  */
-int qc_new_conn_init(struct quic_conn *qc, int ipv4,
-                     struct eb_root *quic_initial_clients,
-                     struct eb_root *quic_clients,
-                     unsigned char *dcid, size_t dcid_len,
-                     unsigned char *scid, size_t scid_len)
+static int qc_new_conn_init(struct quic_conn *qc, int ipv4,
+                            struct eb_root *quic_initial_clients,
+                            struct eb_root *quic_clients,
+                            unsigned char *dcid, size_t dcid_len,
+                            unsigned char *scid, size_t scid_len, int server)
 {
        int i;
        /* Initial CID. */
        struct quic_connection_id *icid;
 
-       TRACE_ENTER(QUIC_EV_CONN_INIT, qc->conn);
+       TRACE_ENTER(QUIC_EV_CONN_INIT);
        qc->cids = EB_ROOT;
        /* QUIC Server (or listener). */
-       if (objt_listener(qc->conn->target)) {
+       if (server) {
                /* Copy the initial DCID. */
                qc->odcid.len = dcid_len;
                if (qc->odcid.len)
@@ -2838,7 +2838,7 @@ int qc_new_conn_init(struct quic_conn *qc, int ipv4,
        qc->scid = icid->cid;
 
        /* Insert the DCID the QUIC client has chosen (only for listeners) */
-       if (objt_listener(qc->conn->target))
+       if (server)
                ebmb_insert(quic_initial_clients, &qc->odcid_node, qc->odcid.len);
 
        /* Insert our SCID, the connection ID for the QUIC client. */
@@ -2872,12 +2872,12 @@ int qc_new_conn_init(struct quic_conn *qc, int ipv4,
        qc->path = &qc->paths[0];
        quic_path_init(qc->path, ipv4, default_quic_cc_algo, qc);
 
-       TRACE_LEAVE(QUIC_EV_CONN_INIT, qc->conn);
+       TRACE_LEAVE(QUIC_EV_CONN_INIT);
 
        return 1;
 
  err:
-       TRACE_DEVEL("leaving in error", QUIC_EV_CONN_INIT, qc->conn);
+       TRACE_DEVEL("leaving in error", QUIC_EV_CONN_INIT);
        quic_conn_free(qc);
        return 0;
 }
@@ -3246,6 +3246,9 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
                }
 
                if (!node) {
+                       int ipv4;
+                       struct quic_cid *odcid;
+
                        if (pkt->type != QUIC_PACKET_TYPE_INITIAL) {
                                TRACE_PROTO("Non Initiial packet", QUIC_EV_CONN_LPKT);
                                goto err;
@@ -3257,21 +3260,37 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
                                goto err;
                        }
 
-                       pkt->qc = qc;
                        pkt->saddr = *saddr;
                        /* Note that here, odcid_len equals to pkt->dcid.len minus the length
                         * of <saddr>.
                         */
                        pkt->odcid_len = dcid_len;
+                       ipv4 = saddr->ss_family == AF_INET;
+                       if (!qc_new_conn_init(qc, ipv4, &l->rx.odcids, &l->rx.cids,
+                                             pkt->dcid.data, pkt->dcid.len,
+                                             pkt->scid.data, pkt->scid.len, 1))
+                               goto err;
+
+                       odcid = &qc->rx.params.original_destination_connection_id;
+                       /* Copy the transport parameters. */
+                       qc->rx.params = l->bind_conf->quic_params;
+                       /* Copy original_destination_connection_id transport parameter. */
+                       memcpy(odcid->data, &pkt->dcid, pkt->odcid_len);
+                       odcid->len = pkt->odcid_len;
+                       /* Copy the initial source connection ID. */
+                       quic_cid_cpy(&qc->rx.params.initial_source_connection_id, &qc->scid);
+                       qc->enc_params_len =
+                               quic_transport_params_encode(qc->enc_params,
+                                                            qc->enc_params + sizeof qc->enc_params,
+                                                            &qc->rx.params, 1);
+                       if (!qc->enc_params_len)
+                               goto err;
+
+                       pkt->qc = qc;
                        /* Enqueue this packet. */
                        LIST_APPEND(&l->rx.qpkts, &pkt->rx_list);
                        /* Try to accept a new connection. */
                        listener_accept(l);
-                       if (!quic_conn_init_timer(qc)) {
-                               TRACE_PROTO("Non initialized timer", QUIC_EV_CONN_LPKT, qc->conn);
-                               goto err;
-                       }
-
                        /* This is the DCID node sent in this packet by the client. */
                        node = &qc->odcid_node;
                        conn_ctx = qc->conn->xprt_ctx;
@@ -4341,7 +4360,7 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
                quic_conn->conn = conn;
                ipv4 = conn->dst->ss_family == AF_INET;
                if (!qc_new_conn_init(quic_conn, ipv4, NULL, &srv->cids,
-                                     dcid, sizeof dcid, NULL, 0))
+                                     dcid, sizeof dcid, NULL, 0, 0))
                        goto err;
 
                if (!qc_new_isecs(conn, dcid, sizeof dcid, 0))
@@ -4397,8 +4416,6 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
 
        /* Leave init state and start handshake */
        conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
-       /* Start the handshake */
-       tasklet_wakeup(ctx->wait_event.tasklet);
 
  out:
        TRACE_LEAVE(QUIC_EV_CONN_NEW, conn);
@@ -4413,6 +4430,22 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
        return -1;
 }
 
+/* Start the QUIC transport layer */
+static int qc_xprt_start(struct connection *conn, void *ctx)
+{
+       struct quic_conn *qc;
+       struct quic_conn_ctx *qctx = ctx;
+
+       qc = conn->qc;
+       if (!quic_conn_init_timer(qc)) {
+               TRACE_PROTO("Non initialized timer", QUIC_EV_CONN_LPKT, conn);
+               return 0;
+       }
+
+       tasklet_wakeup(qctx->wait_event.tasklet);
+       return 1;
+}
+
 /* transport-layer operations for QUIC connections. */
 static struct xprt_ops ssl_quic = {
        .snd_buf  = quic_conn_from_buf,
@@ -4420,6 +4453,7 @@ static struct xprt_ops ssl_quic = {
        .subscribe = quic_conn_subscribe,
        .unsubscribe = quic_conn_unsubscribe,
        .init     = qc_conn_init,
+       .start    = qc_xprt_start,
        .prepare_bind_conf = ssl_sock_prepare_bind_conf,
        .destroy_bind_conf = ssl_sock_destroy_bind_conf,
        .name     = "QUIC",