From cff6d757e3ba609c08ef2aaa00f07e53551e5bf6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 3 Jun 2024 07:11:10 +0200 Subject: Adding upstream version 3.0.0. Signed-off-by: Daniel Baumann --- src/quic_conn.c | 63 +++++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 35 deletions(-) (limited to 'src/quic_conn.c') diff --git a/src/quic_conn.c b/src/quic_conn.c index 5233496..6cc1d38 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -355,7 +355,7 @@ int qc_h3_request_reject(struct quic_conn *qc, uint64_t id) int ret = 0; struct quic_frame *ss, *rs; struct quic_enc_level *qel = qc->ael; - const uint64_t app_error_code = H3_REQUEST_REJECTED; + const uint64_t app_error_code = H3_ERR_REQUEST_REJECTED; TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); @@ -544,10 +544,10 @@ int quic_build_post_handshake_frames(struct quic_conn *qc) goto leave; } - /* QUIC connection packet handler task (post handshake) */ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state) { + struct list send_list = LIST_HEAD_INIT(send_list); struct quic_conn *qc = context; struct quic_enc_level *qel; @@ -592,9 +592,13 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta goto out; } + if (!qel_need_sending(qel, qc)) + goto out; + /* XXX TODO: how to limit the list frames to send */ - if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) { - TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc); + qel_register_send(&send_list, qel, &qel->pktns->tx.frms); + if (!qc_send(qc, 0, &send_list)) { + TRACE_DEVEL("qc_send() failed", QUIC_EV_CONN_IO_CB, qc); goto out; } @@ -741,9 +745,9 @@ static struct quic_conn_closed *qc_new_cc_conn(struct quic_conn *qc) /* QUIC connection packet handler task. */ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) { - int ret; struct quic_conn *qc = context; - struct buffer *buf = NULL; + struct list send_list = LIST_HEAD_INIT(send_list); + struct quic_enc_level *qel; int st; struct tasklet *tl = (struct tasklet *)t; @@ -753,8 +757,8 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st); if (HA_ATOMIC_LOAD(&tl->state) & TASK_HEAVY) { - HA_ATOMIC_AND(&tl->state, ~TASK_HEAVY); qc_ssl_provide_all_quic_data(qc, qc->xprt_ctx); + HA_ATOMIC_AND(&tl->state, ~TASK_HEAVY); } /* Retranmissions */ @@ -771,11 +775,6 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) if (!qc_treat_rx_pkts(qc)) goto out; - if (HA_ATOMIC_LOAD(&tl->state) & TASK_HEAVY) { - tasklet_wakeup(tl); - goto out; - } - if (qc->flags & QUIC_FL_CONN_TO_KILL) { TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_PHPKTS, qc); goto out; @@ -797,34 +796,21 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) } } - buf = qc_get_txb(qc); - if (!buf) - goto out; - - if (b_data(buf) && !qc_purge_txbuf(qc, buf)) - goto out; - - /* Currently buf cannot be non-empty at this stage. Even if a previous - * sendto() has failed it is emptied to simulate packet emission and - * rely on QUIC lost detection to try to emit it. - */ - BUG_ON_HOT(b_data(buf)); - b_reset(buf); + /* Insert each QEL into sending list if needed. */ + list_for_each_entry(qel, &qc->qel_list, list) { + if (qel_need_sending(qel, qc)) + qel_register_send(&send_list, qel, &qel->pktns->tx.frms); + } - ret = qc_prep_hpkts(qc, buf, NULL); - if (ret == -1) { - qc_txb_release(qc); + /* Skip sending if no QEL with frames to sent. */ + if (LIST_ISEMPTY(&send_list)) goto out; - } - if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) { - if (qc->flags & QUIC_FL_CONN_TO_KILL) - qc_txb_release(qc); + if (!qc_send(qc, 0, &send_list)) { + TRACE_DEVEL("qc_send() failed", QUIC_EV_CONN_IO_CB, qc); goto out; } - qc_txb_release(qc); - out: /* Release the Handshake encryption level and packet number space if * the Handshake is confirmed and if there is no need to send @@ -1818,7 +1804,14 @@ int qc_set_tid_affinity(struct quic_conn *qc, uint new_tid, struct listener *new qc_detach_th_ctx_list(qc, 0); node = eb64_first(qc->cids); - BUG_ON(!node || eb64_next(node)); /* One and only one CID must be present before affinity rebind. */ + /* One and only one CID must be present before affinity rebind. + * + * This could be triggered fairly easily if tasklet is scheduled just + * before thread migration for post-handshake state to generate new + * CIDs. In this case, QUIC_FL_CONN_IO_TO_REQUEUE should be used + * instead of tasklet_wakeup(). + */ + BUG_ON(!node || eb64_next(node)); conn_id = eb64_entry(node, struct quic_connection_id, seq_num); /* At this point no connection was accounted for yet on this -- cgit v1.2.3