#define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED (1U << 11) /* The half-open connection counter was decremented */
#define QUIC_FL_CONN_HANDSHAKE_SPEED_UP (1U << 12) /* Handshake speeding up was done */
#define QUIC_FL_CONN_ACK_TIMER_FIRED (1U << 13) /* idle timer triggered for acknowledgements */
+#define QUIC_FL_CONN_IO_TO_REQUEUE (1U << 14) /* IO handler must be requeued on new thread after connection migration */
#define QUIC_FL_CONN_TO_KILL (1U << 24) /* Unusable connection, to be killed */
#define QUIC_FL_CONN_TX_TP_RECEIVED (1U << 25) /* Peer transport parameters have been received (used for the transmitting part) */
#define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */
void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src,
const struct sockaddr_storage *dst);
void qc_release_fd(struct quic_conn *qc, int reinit);
+void qc_want_recv(struct quic_conn *qc);
void quic_accept_push_qc(struct quic_conn *qc);
}
/* Reinit IO tasklet. */
+ if (qc->wait_event.tasklet->state & TASK_IN_LIST)
+ qc->flags |= QUIC_FL_CONN_IO_TO_REQUEUE;
tasklet_kill(qc->wait_event.tasklet);
/* In most cases quic_conn_app_io_cb is used but for 0-RTT quic_conn_io_cb can be still activated. */
t3->process = qc->wait_event.tasklet->process;
/* Rebind the connection FD. */
if (qc_test_fd(qc)) {
+ /* Reading is reactivated by the new thread. */
fd_migrate_on(qc->fd, new_tid);
- /* TODO need to reactivate reading on the new thread. */
}
/* Remove conn from per-thread list instance. */
return 1;
}
+/* Must be called after qc_set_tid_affinity() on the new thread. */
+void qc_finalize_affinity_rebind(struct quic_conn *qc)
+{
+ TRACE_ENTER(QUIC_EV_CONN_SET_AFFINITY, qc);
+
+ /* Reactivate FD polling if connection socket is active. */
+ qc_want_recv(qc);
+
+ /* Reactivate timer task if needed. */
+ qc_set_timer(qc);
+
+ /* Idle timer task is always active. */
+ task_queue(qc->idle_timer_task);
+
+ /* Reactivate IO tasklet if needed. */
+ if (qc->flags & QUIC_FL_CONN_IO_TO_REQUEUE) {
+ tasklet_wakeup(qc->wait_event.tasklet);
+ qc->flags &= ~QUIC_FL_CONN_IO_TO_REQUEUE;
+ }
+
+ TRACE_LEAVE(QUIC_EV_CONN_SET_AFFINITY, qc);
+}
+
/* appctx context used by "show quic" command */
struct show_quic_ctx {
unsigned int epoch;
}
}
+/* Wrapper for fd_want_recv(). Safe even if connection does not used its owned
+ * socket.
+ */
+void qc_want_recv(struct quic_conn *qc)
+{
+ if (qc_test_fd(qc))
+ fd_want_recv(qc->fd);
+}
+
/*********************** QUIC accept queue management ***********************/
/* per-thread accept queues */
struct quic_accept_queue *quic_accept_queues;