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
struct quic_accept_queue *quic_accept_queues;
/* Install <qc> on the queue ready to be accepted. The queue task is then woken
- * up. If <qc> accept is already scheduled or done, nothing is done.
+ * up.
*/
void quic_accept_push_qc(struct quic_conn *qc)
{
struct quic_accept_queue *queue = &quic_accept_queues[tid];
struct li_per_thread *lthr = &qc->li->per_thr[ti->ltid];
- /* early return if accept is already in progress/done for this
- * connection
- */
- if (qc->flags & QUIC_FL_CONN_ACCEPT_REGISTERED)
- return;
+ /* A connection must only be accepted once per instance. */
+ BUG_ON(qc->flags & QUIC_FL_CONN_ACCEPT_REGISTERED);
BUG_ON(MT_LIST_INLIST(&qc->accept_list));
HA_ATOMIC_INC(&qc->li->rx.quic_curr_accept);
if (qc_is_listener(ctx->qc)) {
qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
qc->state = QUIC_HS_ST_CONFIRMED;
- /* The connection is ready to be accepted. */
- quic_accept_push_qc(qc);
+
+ if (!(qc->flags & QUIC_FL_CONN_ACCEPT_REGISTERED)) {
+ quic_accept_push_qc(qc);
+ }
+ else {
+ /* Connection already accepted if 0-RTT used.
+ * In this case, schedule quic-conn to ensure
+ * post-handshake frames are emitted.
+ */
+ tasklet_wakeup(qc->wait_event.tasklet);
+ }
BUG_ON(qc->li->rx.quic_curr_handshake == 0);
HA_ATOMIC_DEC(&qc->li->rx.quic_curr_handshake);
/* mux-quic can now be considered ready. */
qc->mux_state = QC_MUX_READY;
+ /* Schedule quic-conn to ensure post handshake frames are emitted. This
+ * is not done for 0-RTT as xprt->start happens before handshake
+ * completion.
+ */
+ if (qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS)
+ tasklet_wakeup(qc->wait_event.tasklet);
+
ret = 1;
out:
TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);