MINOR: quic-be: get rid of ->li quic_conn member

Replace ->li quic_conn pointer to struct listener member by  ->target which is
an object type enum and adapt the code.
Use __objt_(listener|server)() where the object type is known. Typically
this is were the code which is specific to one connection type (frontend/backend).
Remove <server> parameter passed to qc_new_conn(). It is redundant with the
<target> parameter.
GSO is not supported at this time for QUIC backend. qc_prep_pkts() is modified
to prevent it from building more than an MTU. This has as consequence to prevent
qc_send_ppkts() to use GSO.
ssl_clienthello.c code is run only by listeners. This is why __objt_listener()
is used in place of ->li.
This commit is contained in:
Frederic Lecaille 2025-06-06 15:20:00 +02:00
parent a80e93402e
commit 24b0109acb
14 changed files with 81 additions and 65 deletions

View File

@ -319,7 +319,7 @@ struct qcc_app_ops;
* with a connection \ * with a connection \
*/ \ */ \
struct eb_root *cids; \ struct eb_root *cids; \
struct listener *li; /* only valid for frontend connections */ \ enum obj_type *target; \
/* Idle timer task */ \ /* Idle timer task */ \
struct task *idle_timer_task; \ struct task *idle_timer_task; \
unsigned int idle_expire; \ unsigned int idle_expire; \

View File

@ -69,7 +69,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
struct quic_connection_id *conn_id, struct quic_connection_id *conn_id,
struct sockaddr_storage *local_addr, struct sockaddr_storage *local_addr,
struct sockaddr_storage *peer_addr, struct sockaddr_storage *peer_addr,
int server, int token, void *owner, int token, void *owner,
struct connection *conn); struct connection *conn);
int quic_build_post_handshake_frames(struct quic_conn *qc); int quic_build_post_handshake_frames(struct quic_conn *qc);
const struct quic_version *qc_supported_version(uint32_t version); const struct quic_version *qc_supported_version(uint32_t version);
@ -164,13 +164,6 @@ static inline void quic_free_ncbuf(struct ncbuf *ncbuf)
*ncbuf = NCBUF_NULL; *ncbuf = NCBUF_NULL;
} }
/* Return the address of the connection owner object type. */
static inline enum obj_type *qc_owner_obj_type(struct quic_conn *qc)
{
return qc_is_listener(qc) ? &qc->li->obj_type :
&objt_server(qc->conn->target)->obj_type;
}
/* Return the address of the QUIC counters attached to the proxy of /* Return the address of the QUIC counters attached to the proxy of
* the owner of the connection whose object type address is <o> for * the owner of the connection whose object type address is <o> for
* listener and servers, or NULL for others object type. * listener and servers, or NULL for others object type.

View File

@ -33,6 +33,7 @@
#include <haproxy/connection-t.h> #include <haproxy/connection-t.h>
#include <haproxy/fd-t.h> #include <haproxy/fd-t.h>
#include <haproxy/listener-t.h> #include <haproxy/listener-t.h>
#include <haproxy/obj_type.h>
#include <haproxy/quic_conn-t.h> #include <haproxy/quic_conn-t.h>
#include <haproxy/quic_sock-t.h> #include <haproxy/quic_sock-t.h>
@ -78,7 +79,8 @@ static inline char qc_test_fd(struct quic_conn *qc)
*/ */
static inline int qc_fd(struct quic_conn *qc) static inline int qc_fd(struct quic_conn *qc)
{ {
return qc_test_fd(qc) ? qc->fd : qc->li->rx.fd; /* TODO: check this: For backends, qc->fd is always initialized */
return qc_test_fd(qc) ? qc->fd : __objt_listener(qc->target)->rx.fd;
} }
/* Try to increment <l> handshake current counter. If listener limit is /* Try to increment <l> handshake current counter. If listener limit is

View File

@ -1423,7 +1423,8 @@ static int cli_io_handler_show_fd(struct appctx *appctx)
#if defined(USE_QUIC) #if defined(USE_QUIC)
else if (fdt.iocb == quic_conn_sock_fd_iocb) { else if (fdt.iocb == quic_conn_sock_fd_iocb) {
qc = fdtab[fd].owner; qc = fdtab[fd].owner;
li = qc ? qc->li : NULL; li = qc ? objt_listener(qc->target) : NULL;
sv = qc ? objt_server(qc->target) : NULL;
xprt_ctx = qc ? qc->xprt_ctx : NULL; xprt_ctx = qc ? qc->xprt_ctx : NULL;
conn = qc ? qc->conn : NULL; conn = qc ? qc->conn : NULL;
xprt = conn ? conn->xprt : NULL; // in fact it's &ssl_quic xprt = conn ? conn->xprt : NULL; // in fact it's &ssl_quic

View File

@ -4,7 +4,7 @@
#include <haproxy/cli.h> #include <haproxy/cli.h>
#include <haproxy/list.h> #include <haproxy/list.h>
#include <haproxy/mux_quic.h> #include <haproxy/mux_quic.h>
#include <haproxy/quic_conn-t.h> #include <haproxy/quic_conn.h>
#include <haproxy/quic_tp.h> #include <haproxy/quic_tp.h>
#include <haproxy/quic_utils.h> #include <haproxy/quic_utils.h>
#include <haproxy/tools.h> #include <haproxy/tools.h>
@ -181,9 +181,11 @@ static void dump_quic_oneline(struct show_quic_ctx *ctx, struct quic_conn *qc)
char bufaddr[INET6_ADDRSTRLEN], bufport[6]; char bufaddr[INET6_ADDRSTRLEN], bufport[6];
int ret; int ret;
unsigned char cid_len; unsigned char cid_len;
struct listener *l = objt_listener(qc->target);
ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr, ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr,
qc->li->bind_conf->frontend->id); l ? l->bind_conf->frontend->id : __objt_server(qc->target)->id);
chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */ chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */
/* State */ /* State */

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->dcid = qc->dcid;
cc_qc->scid = qc->scid; cc_qc->scid = qc->scid;
cc_qc->li = qc->li; cc_qc->target = qc->target;
cc_qc->cids = qc->cids; cc_qc->cids = qc->cids;
cc_qc->idle_timer_task = qc->idle_timer_task; cc_qc->idle_timer_task = qc->idle_timer_task;
@ -1067,13 +1067,13 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
struct quic_connection_id *conn_id, struct quic_connection_id *conn_id,
struct sockaddr_storage *local_addr, struct sockaddr_storage *local_addr,
struct sockaddr_storage *peer_addr, struct sockaddr_storage *peer_addr,
int server, int token, void *owner, int token, void *target,
struct connection *conn) struct connection *conn)
{ {
struct quic_conn *qc = NULL; struct quic_conn *qc = NULL;
struct listener *l = server ? owner : NULL; struct listener *l = objt_listener(target);
struct server *srv = server ? NULL : owner; struct server *srv = objt_server(target);
struct proxy *prx = l ? l->bind_conf->frontend : srv->proxy; struct proxy *prx = l ? l->bind_conf->frontend : __objt_server(target)->proxy;
struct quic_cc_algo *cc_algo = NULL; struct quic_cc_algo *cc_algo = NULL;
unsigned int next_actconn = 0, next_sslconn = 0, next_handshake = 0; unsigned int next_actconn = 0, next_sslconn = 0, next_handshake = 0;
@ -1092,7 +1092,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
goto err; goto err;
} }
if (server) { if (l) {
next_handshake = quic_increment_curr_handshake(l); next_handshake = quic_increment_curr_handshake(l);
if (!next_handshake) { if (!next_handshake) {
TRACE_STATE("max handshake reached", QUIC_EV_CONN_INIT); TRACE_STATE("max handshake reached", QUIC_EV_CONN_INIT);
@ -1112,6 +1112,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
goto err; goto err;
} }
qc->target = target;
*qc->cids = EB_ROOT; *qc->cids = EB_ROOT;
/* Now that quic_conn instance is allocated, quic_conn_release() will /* Now that quic_conn instance is allocated, quic_conn_release() will
* ensure global accounting is decremented. * ensure global accounting is decremented.
@ -1167,7 +1168,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
qc->prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module); qc->prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
/* QUIC Server (or listener). */ /* QUIC Server (or listener). */
if (server) { if (l) {
cc_algo = l->bind_conf->quic_cc_algo; cc_algo = l->bind_conf->quic_cc_algo;
qc->flags = QUIC_FL_CONN_LISTENER; qc->flags = QUIC_FL_CONN_LISTENER;
@ -1180,7 +1181,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
/* Copy the packet SCID to reuse it as DCID for sending */ /* Copy the packet SCID to reuse it as DCID for sending */
qc->dcid = *scid; qc->dcid = *scid;
qc->tx.buf = BUF_NULL; qc->tx.buf = BUF_NULL;
qc->li = l;
conn_id->qc = qc; conn_id->qc = qc;
} }
/* QUIC Client (outgoing connection to servers) */ /* QUIC Client (outgoing connection to servers) */
@ -1209,7 +1209,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
conn_id = conn_cid; conn_id = conn_cid;
qc->tx.buf = BUF_NULL; qc->tx.buf = BUF_NULL;
qc->li = NULL;
qc->next_cid_seq_num = 1; qc->next_cid_seq_num = 1;
conn->handle.qc = qc; conn->handle.qc = qc;
} }
@ -1219,7 +1218,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
/* Listener only: if connection is instantiated due to an INITIAL packet with an /* Listener only: if connection is instantiated due to an INITIAL packet with an
* already checked token, consider the peer address as validated. * already checked token, consider the peer address as validated.
*/ */
if (server) { if (l) {
if (token_odcid->len) { if (token_odcid->len) {
TRACE_STATE("validate peer address due to initial token", TRACE_STATE("validate peer address due to initial token",
QUIC_EV_CONN_INIT, qc); QUIC_EV_CONN_INIT, qc);
@ -1292,7 +1291,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
qc->max_ack_delay = 0; qc->max_ack_delay = 0;
/* Only one path at this time (multipath not supported) */ /* Only one path at this time (multipath not supported) */
qc->path = &qc->paths[0]; qc->path = &qc->paths[0];
quic_cc_path_init(qc->path, ipv4, server ? l->bind_conf->max_cwnd : 0, quic_cc_path_init(qc->path, ipv4, l ? l->bind_conf->max_cwnd : 0,
cc_algo ? cc_algo : default_quic_cc_algo, qc); cc_algo ? cc_algo : default_quic_cc_algo, qc);
if (local_addr) if (local_addr)
@ -1301,7 +1300,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
memset(&qc->local_addr, 0, sizeof(qc->local_addr)); memset(&qc->local_addr, 0, sizeof(qc->local_addr));
memcpy(&qc->peer_addr, peer_addr, sizeof qc->peer_addr); memcpy(&qc->peer_addr, peer_addr, sizeof qc->peer_addr);
if (server) { if (l) {
qc_lstnr_params_init(qc, &l->bind_conf->quic_params, qc_lstnr_params_init(qc, &l->bind_conf->quic_params,
conn_id->stateless_reset_token, conn_id->stateless_reset_token,
qc->dcid.data, qc->dcid.len, qc->dcid.data, qc->dcid.len,
@ -1335,7 +1334,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
!quic_conn_init_idle_timer_task(qc, prx)) !quic_conn_init_idle_timer_task(qc, prx))
goto err; goto err;
if (!qc_new_isecs(qc, &qc->iel->tls_ctx, qc->original_version, dcid->data, dcid->len, server)) if (!qc_new_isecs(qc, &qc->iel->tls_ctx, qc->original_version, dcid->data, dcid->len, !!l))
goto err; goto err;
/* Counters initialization */ /* Counters initialization */
@ -1386,7 +1385,7 @@ int qc_handle_conn_migration(struct quic_conn *qc,
* used during the handshake, unless the endpoint has acted on a * used during the handshake, unless the endpoint has acted on a
* preferred_address transport parameter from the peer. * preferred_address transport parameter from the peer.
*/ */
if (qc->li->bind_conf->quic_params.disable_active_migration) { if (__objt_listener(qc->target)->bind_conf->quic_params.disable_active_migration) {
TRACE_ERROR("Active migration was disabled, datagram dropped", QUIC_EV_CONN_LPKT, qc); TRACE_ERROR("Active migration was disabled, datagram dropped", QUIC_EV_CONN_LPKT, qc);
goto err; goto err;
} }
@ -1516,8 +1515,8 @@ int quic_conn_release(struct quic_conn *qc)
*/ */
if (MT_LIST_INLIST(&qc->accept_list)) { if (MT_LIST_INLIST(&qc->accept_list)) {
MT_LIST_DELETE(&qc->accept_list); MT_LIST_DELETE(&qc->accept_list);
BUG_ON(qc->li->rx.quic_curr_accept == 0); BUG_ON(__objt_listener(qc->target)->rx.quic_curr_accept == 0);
HA_ATOMIC_DEC(&qc->li->rx.quic_curr_accept); HA_ATOMIC_DEC(&__objt_listener(qc->target)->rx.quic_curr_accept);
} }
/* Substract last congestion window from global memory counter. */ /* Substract last congestion window from global memory counter. */
@ -1587,8 +1586,8 @@ int quic_conn_release(struct quic_conn *qc)
/* Connection released before handshake completion. */ /* Connection released before handshake completion. */
if (unlikely(qc->state < QUIC_HS_ST_COMPLETE)) { if (unlikely(qc->state < QUIC_HS_ST_COMPLETE)) {
if (qc_is_listener(qc)) { if (qc_is_listener(qc)) {
BUG_ON(qc->li->rx.quic_curr_handshake == 0); BUG_ON(__objt_listener(qc->target)->rx.quic_curr_handshake == 0);
HA_ATOMIC_DEC(&qc->li->rx.quic_curr_handshake); HA_ATOMIC_DEC(&__objt_listener(qc->target)->rx.quic_curr_handshake);
} }
} }
@ -1996,8 +1995,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 /* At this point no connection was accounted for yet on this
* listener so it's OK to just swap the pointer. * listener so it's OK to just swap the pointer.
*/ */
if (new_li && new_li != qc->li) if (new_li && new_li != __objt_listener(qc->target))
qc->li = new_li; qc->target = &new_li->obj_type;
/* Rebind the connection FD. */ /* Rebind the connection FD. */
if (qc_test_fd(qc)) { if (qc_test_fd(qc)) {

View File

@ -1819,7 +1819,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
goto err; goto err;
qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid, qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid,
conn_id, &dgram->daddr, &pkt->saddr, 1, conn_id, &dgram->daddr, &pkt->saddr,
!!pkt->token_len, l, NULL); !!pkt->token_len, l, NULL);
if (qc == NULL) { if (qc == NULL) {
pool_free(pool_head_quic_connection_id, conn_id); pool_free(pool_head_quic_connection_id, conn_id);

View File

@ -87,13 +87,13 @@ int quic_sock_get_dst(struct connection *conn, struct sockaddr *addr, socklen_t
memcpy(addr, &qc->peer_addr, len); memcpy(addr, &qc->peer_addr, len);
} else { } else {
struct sockaddr_storage *from; struct sockaddr_storage *from;
struct listener *l = objt_listener(qc->target);
/* Return listener address if IP_PKTINFO or friends are not /* Return listener address if IP_PKTINFO or friends are not
* supported by the socket. * supported by the socket.
*/ */
BUG_ON(!qc->li); BUG_ON(!l);
from = is_addr(&qc->local_addr) ? &qc->local_addr : from = is_addr(&qc->local_addr) ? &qc->local_addr : &l->rx.addr;
&qc->li->rx.addr;
if (len > sizeof(*from)) if (len > sizeof(*from))
len = sizeof(*from); len = sizeof(*from);
memcpy(addr, from, len); memcpy(addr, from, len);
@ -819,6 +819,7 @@ int qc_rcv_buf(struct quic_conn *qc)
struct buffer buf = BUF_NULL; struct buffer buf = BUF_NULL;
unsigned char *dgram_buf; unsigned char *dgram_buf;
ssize_t ret = 0; ssize_t ret = 0;
struct listener *l = objt_listener(qc->target);
/* Do not call this if quic-conn FD is uninitialized. */ /* Do not call this if quic-conn FD is uninitialized. */
BUG_ON(qc->fd < 0); BUG_ON(qc->fd < 0);
@ -869,7 +870,7 @@ int qc_rcv_buf(struct quic_conn *qc)
continue; continue;
} }
if (qc_is_listener(qc) && !qc_check_dcid(qc, new_dgram->dcid, new_dgram->dcid_len)) { if (l && !qc_check_dcid(qc, new_dgram->dcid, new_dgram->dcid_len)) {
/* Datagram received by error on the connection FD, dispatch it /* Datagram received by error on the connection FD, dispatch it
* to its associated quic-conn. * to its associated quic-conn.
* *
@ -879,7 +880,6 @@ int qc_rcv_buf(struct quic_conn *qc)
struct quic_dgram *tmp_dgram; struct quic_dgram *tmp_dgram;
unsigned char *rxbuf_tail; unsigned char *rxbuf_tail;
size_t cspace; size_t cspace;
struct listener *l = qc->li;
TRACE_STATE("datagram for other connection on quic-conn socket, requeue it", QUIC_EV_CONN_RCV, qc); TRACE_STATE("datagram for other connection on quic-conn socket, requeue it", QUIC_EV_CONN_RCV, qc);
@ -928,7 +928,7 @@ int qc_rcv_buf(struct quic_conn *qc)
continue; continue;
} }
quic_dgram_parse(new_dgram, qc, qc_owner_obj_type(qc)); quic_dgram_parse(new_dgram, qc, qc->target);
/* A datagram must always be consumed after quic_parse_dgram(). */ /* A datagram must always be consumed after quic_parse_dgram(). */
BUG_ON(new_dgram->buf); BUG_ON(new_dgram->buf);
} while (ret > 0); } while (ret > 0);
@ -950,11 +950,13 @@ int qc_rcv_buf(struct quic_conn *qc)
* *
* Return the socket FD or a negative error code. On error, socket is marked as * Return the socket FD or a negative error code. On error, socket is marked as
* uninitialized. * uninitialized.
* Note: This function must not be run for backends connection.
*/ */
void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src, void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src,
const struct sockaddr_storage *dst) const struct sockaddr_storage *dst)
{ {
struct bind_conf *bc = qc->li->bind_conf; struct listener *l = __objt_listener(qc->target);
struct bind_conf *bc = l->bind_conf;
struct proxy *p = bc->frontend; struct proxy *p = bc->frontend;
int fd = -1; int fd = -1;
int ret; int ret;
@ -1007,7 +1009,7 @@ void qc_alloc_fd(struct quic_conn *qc, const struct sockaddr_storage *src,
} }
/* Fallback to listener socket for this receiver instance. */ /* Fallback to listener socket for this receiver instance. */
HA_ATOMIC_STORE(&qc->li->rx.quic_mode, QUIC_SOCK_MODE_LSTNR); HA_ATOMIC_STORE(&l->rx.quic_mode, QUIC_SOCK_MODE_LSTNR);
} }
goto err; goto err;
} }
@ -1061,13 +1063,14 @@ struct quic_accept_queue *quic_accept_queues;
void quic_accept_push_qc(struct quic_conn *qc) void quic_accept_push_qc(struct quic_conn *qc)
{ {
struct quic_accept_queue *queue = &quic_accept_queues[tid]; struct quic_accept_queue *queue = &quic_accept_queues[tid];
struct li_per_thread *lthr = &qc->li->per_thr[ti->ltid]; struct listener *l = __objt_listener(qc->target);
struct li_per_thread *lthr = &l->per_thr[ti->ltid];
/* A connection must only be accepted once per instance. */ /* A connection must only be accepted once per instance. */
BUG_ON(qc->flags & QUIC_FL_CONN_ACCEPT_REGISTERED); BUG_ON(qc->flags & QUIC_FL_CONN_ACCEPT_REGISTERED);
BUG_ON(MT_LIST_INLIST(&qc->accept_list)); BUG_ON(MT_LIST_INLIST(&qc->accept_list));
HA_ATOMIC_INC(&qc->li->rx.quic_curr_accept); HA_ATOMIC_INC(&l->rx.quic_curr_accept);
qc->flags |= QUIC_FL_CONN_ACCEPT_REGISTERED; qc->flags |= QUIC_FL_CONN_ACCEPT_REGISTERED;
/* 1. insert the listener in the accept queue /* 1. insert the listener in the accept queue

View File

@ -937,14 +937,16 @@ static int qc_ssl_provide_quic_data(struct ncbuf *ncbuf,
* provided by the stack. This happens after having received the peer * provided by the stack. This happens after having received the peer
* handshake level CRYPTO data which are validated by the TLS stack. * handshake level CRYPTO data which are validated by the TLS stack.
*/ */
if (qc->li->bind_conf->ssl_conf.early_data && if (qc_is_listener(qc)) {
(!qc->ael || !qc->ael->tls_ctx.rx.secret)) { if (__objt_listener(qc->target)->bind_conf->ssl_conf.early_data &&
TRACE_PROTO("SSL handshake in progress", (!qc->ael || !qc->ael->tls_ctx.rx.secret)) {
QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err); TRACE_PROTO("SSL handshake in progress",
goto out; QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
} goto out;
else { }
TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state); else {
TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
}
} }
#endif #endif
@ -980,6 +982,7 @@ static int qc_ssl_provide_quic_data(struct ncbuf *ncbuf,
qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
if (qc_is_listener(ctx->qc)) { if (qc_is_listener(ctx->qc)) {
struct listener *l = __objt_listener(qc->target);
/* I/O callback switch */ /* I/O callback switch */
qc->wait_event.tasklet->process = quic_conn_app_io_cb; qc->wait_event.tasklet->process = quic_conn_app_io_cb;
qc->state = QUIC_HS_ST_CONFIRMED; qc->state = QUIC_HS_ST_CONFIRMED;
@ -995,8 +998,8 @@ static int qc_ssl_provide_quic_data(struct ncbuf *ncbuf,
tasklet_wakeup(qc->wait_event.tasklet); tasklet_wakeup(qc->wait_event.tasklet);
} }
BUG_ON(qc->li->rx.quic_curr_handshake == 0); BUG_ON(l->rx.quic_curr_handshake == 0);
HA_ATOMIC_DEC(&qc->li->rx.quic_curr_handshake); HA_ATOMIC_DEC(&l->rx.quic_curr_handshake);
} }
else { else {
qc->state = QUIC_HS_ST_COMPLETE; qc->state = QUIC_HS_ST_COMPLETE;
@ -1224,7 +1227,7 @@ int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn)
ctx->qc = qc; ctx->qc = qc;
if (qc_is_listener(qc)) { if (qc_is_listener(qc)) {
struct bind_conf *bc = qc->li->bind_conf; struct bind_conf *bc = __objt_listener(qc->target)->bind_conf;
if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl, NULL, 1) == -1) if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl, NULL, 1) == -1)
goto err; goto err;

View File

@ -288,8 +288,10 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
int ret = 0; int ret = 0;
struct quic_conn *qc; struct quic_conn *qc;
char skip_sendto = 0; char skip_sendto = 0;
struct listener *l;
qc = ctx->qc; qc = ctx->qc;
l = objt_listener(qc->target);
TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc); TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
while (b_contig_data(buf, 0)) { while (b_contig_data(buf, 0)) {
unsigned char *pos; unsigned char *pos;
@ -305,7 +307,11 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
/* If datagram bigger than MTU, several ones were encoded for GSO usage. */ /* If datagram bigger than MTU, several ones were encoded for GSO usage. */
if (dglen > qc->path->mtu) { if (dglen > qc->path->mtu) {
if (likely(!(HA_ATOMIC_LOAD(&qc->li->flags) & LI_F_UDP_GSO_NOTSUPP))) { /* TODO: note that at this time for connection to backends this
* part is not run because no more than an MTU has been prepared for
* such connections (dglen <= qc->path->mtu). So, here l is not NULL.
*/
if (likely(!(HA_ATOMIC_LOAD(&l->flags) & LI_F_UDP_GSO_NOTSUPP))) {
TRACE_PROTO("send multiple datagrams with GSO", QUIC_EV_CONN_SPPKTS, qc); TRACE_PROTO("send multiple datagrams with GSO", QUIC_EV_CONN_SPPKTS, qc);
gso = qc->path->mtu; gso = qc->path->mtu;
} }
@ -327,11 +333,15 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0, gso); int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0, gso);
if (ret < 0) { if (ret < 0) {
if (gso && ret == -EIO) { if (gso && ret == -EIO) {
/* TODO: note that at this time for connection to backends this
* part is not run because no more than an MTU has been
* prepared for such connections (l is not NULL).
*/
/* Disable permanently UDP GSO for this listener. /* Disable permanently UDP GSO for this listener.
* Retry standard emission. * Retry standard emission.
*/ */
TRACE_ERROR("mark listener UDP GSO as unsupported", QUIC_EV_CONN_SPPKTS, qc, first_pkt); TRACE_ERROR("mark listener UDP GSO as unsupported", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
HA_ATOMIC_OR(&qc->li->flags, LI_F_UDP_GSO_NOTSUPP); HA_ATOMIC_OR(&l->flags, LI_F_UDP_GSO_NOTSUPP);
continue; continue;
} }
@ -576,6 +586,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
int dgram_cnt = 0; int dgram_cnt = 0;
/* Restrict GSO emission to comply with sendmsg limitation. See QUIC_MAX_GSO_DGRAMS for more details. */ /* Restrict GSO emission to comply with sendmsg limitation. See QUIC_MAX_GSO_DGRAMS for more details. */
uchar gso_dgram_cnt = 0; uchar gso_dgram_cnt = 0;
struct listener *l = objt_listener(qc->target);
TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
/* Currently qc_prep_pkts() does not handle buffer wrapping so the /* Currently qc_prep_pkts() does not handle buffer wrapping so the
@ -765,11 +776,13 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
prv_pkt = cur_pkt; prv_pkt = cur_pkt;
} }
else if (!(quic_tune.options & QUIC_TUNE_NO_UDP_GSO) && else if (!(quic_tune.options & QUIC_TUNE_NO_UDP_GSO) &&
!(HA_ATOMIC_LOAD(&qc->li->flags) & LI_F_UDP_GSO_NOTSUPP) &&
dglen == qc->path->mtu && dglen == qc->path->mtu &&
(char *)end < b_wrap(buf) && (char *)end < b_wrap(buf) &&
++gso_dgram_cnt < QUIC_MAX_GSO_DGRAMS) { ++gso_dgram_cnt < QUIC_MAX_GSO_DGRAMS &&
l && !(HA_ATOMIC_LOAD(&l->flags) & LI_F_UDP_GSO_NOTSUPP)) {
/* TODO: note that for backends GSO is not used. No more than
* an MTU is prepared.
*/
/* A datagram covering the full MTU has been /* A datagram covering the full MTU has been
* built, use GSO to built next entry. Do not * built, use GSO to built next entry. Do not
* reserve extra space for datagram header. * reserve extra space for datagram header.

View File

@ -177,7 +177,7 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
s = __objt_listener(conn->target)->bind_conf; s = __objt_listener(conn->target)->bind_conf;
#ifdef USE_QUIC #ifdef USE_QUIC
else if (qc) else if (qc)
s = qc->li->bind_conf; s = __objt_listener(qc->target)->bind_conf;
#endif /* USE_QUIC */ #endif /* USE_QUIC */
if (!s) { if (!s) {

View File

@ -127,7 +127,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); struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
/* null if not a listener */ /* null if not a listener */
li = qc->li; li = objt_listener(qc->target);
} }
#endif #endif

View File

@ -926,7 +926,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; ref = __objt_listener(conn->target)->bind_conf->keys_ref;
#ifdef USE_QUIC #ifdef USE_QUIC
else if (qc) else if (qc)
ref = qc->li->bind_conf->keys_ref; ref = __objt_listener(qc->target)->bind_conf->keys_ref;
#endif #endif
if (!ref) { if (!ref) {
@ -1482,7 +1482,7 @@ int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
else { else {
qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
BUG_ON(!qc); /* Must never happen */ BUG_ON(!qc); /* Must never happen */
bind_conf = qc->li->bind_conf; bind_conf = __objt_listener(qc->target)->bind_conf;
ctx = qc->xprt_ctx; ctx = qc->xprt_ctx;
} }
#endif #endif

View File

@ -123,7 +123,7 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
int ipv4 = conn->dst->ss_family == AF_INET; int ipv4 = conn->dst->ss_family == AF_INET;
struct server *srv = objt_server(conn->target); struct server *srv = objt_server(conn->target);
qc = qc_new_conn(quic_version_1, ipv4, NULL, NULL, NULL, qc = qc_new_conn(quic_version_1, ipv4, NULL, NULL, NULL,
NULL, NULL, &srv->addr, 0, 0, srv, conn); NULL, NULL, &srv->addr, 0, srv, conn);
} }
if (!qc) if (!qc)