MINOR: quic: get rid of ->target quic_conn struct member

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.
This commit is contained in:
Frederic Lecaille 2025-09-09 11:49:33 +02:00
parent 5354c24c76
commit 47bb15ca84
13 changed files with 47 additions and 34 deletions

View 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; \

View 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;

View 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

View File

@ -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

View 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 */

View 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)

View 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.
*/

View 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. */

View 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;

View 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);
}

View 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) {

View 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

View 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