See https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 for more
information about QUIC retry.
-tune.quic.socket-owner { listener | connection }
- Specifies how QUIC connections will use socket for receive/send operations.
- Connections can share listener socket or each connection can allocate its
- own socket.
+tune.quic.socket-owner { connection | listener }
+ Specifies globally how QUIC connections will use socket for receive/send
+ operations. Connections can share listener socket or each connection can
+ allocate its own socket.
When default "connection" value is set, a dedicated socket will be allocated
by every QUIC connections. This option is the preferred one to achieve the
a higher CPU usage if listeners are shared across a lot of threads or a
large number of QUIC connections can be used simultaneously.
+ This setting is applied in conjunction with each "quic-socket" bind options.
+ If "connection" mode is used on global tuning, it will be activated for each
+ listener, unless its bind option is set to "listener". However, if "listener"
+ is used globally, it will be forced on every listener instance, regardless of
+ their individual configuration.
+
tune.rcvbuf.client <number>
tune.rcvbuf.server <number>
Forces the kernel socket receive buffer size on the client or the server side
See https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 for more
information about QUIC retry.
+quic-socket [ connection | listener ]
+ This QUIC specific setting allows to define the socket allocation mode for
+ the specific listeners. See "tune.quic.socket-owner" for a full description
+ of its usage.
+
shards <number> | by-thread | by-group
In multi-threaded mode, on operating systems supporting multiple listeners on
the same IP:port, this will automatically create this number of multiple
#include <haproxy/api-t.h>
#include <haproxy/obj_type-t.h>
#include <haproxy/quic_cc-t.h>
+#include <haproxy/quic_sock-t.h>
#include <haproxy/quic_tp-t.h>
#include <haproxy/receiver-t.h>
#include <haproxy/stats-t.h>
#ifdef USE_QUIC
struct quic_transport_params quic_params; /* QUIC transport parameters. */
struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */
+ enum quic_sock_mode quic_mode; /* QUIC socket allocation strategy */
#endif
struct proxy *frontend; /* the frontend all these listeners belong to, or NULL */
const struct mux_proto_list *mux_proto; /* the mux to use for all incoming connections (specified by the "proto" keyword) */
#define _HAPROXY_QUIC_SOCK_T_H
#ifdef USE_QUIC
+/* QUIC socket allocation strategy. */
+enum quic_sock_mode {
+ QUIC_SOCK_MODE_CONN, /* Use a dedicated socket per connection. */
+ QUIC_SOCK_MODE_LSTNR, /* Multiplex connections over listener socket. */
+};
+
/* QUIC connection accept queue. One per thread. */
struct quic_accept_queue {
struct mt_list listeners; /* QUIC listeners with at least one connection ready to be accepted on this queue */
return 0;
}
+static int bind_parse_quic_socket(char **args, int cur_arg, struct proxy *px,
+ struct bind_conf *conf, char **err)
+{
+ char *arg;
+ if (!*args[cur_arg + 1]) {
+ memprintf(err, "'%s' : missing argument, use either connection or listener.", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ arg = args[cur_arg + 1];
+ if (strcmp(arg, "connection") == 0) {
+ conf->quic_mode = QUIC_SOCK_MODE_CONN;
+ }
+ else if (strcmp(arg, "listener") == 0) {
+ conf->quic_mode = QUIC_SOCK_MODE_LSTNR;
+ }
+ else {
+ memprintf(err, "'%s' : unknown argument, use either connection or listener.", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
static struct bind_kw_list bind_kws = { "QUIC", { }, {
{ "quic-force-retry", bind_parse_quic_force_retry, 0 },
{ "quic-cc-algo", bind_parse_quic_cc_algo, 1 },
+ { "quic-socket", bind_parse_quic_socket, 1 },
{ NULL, NULL, 0 },
}};
HA_RWLOCK_INIT(&bind_conf->sni_lock);
bind_conf->sni_ctx = EB_ROOT;
bind_conf->sni_w_ctx = EB_ROOT;
+#endif
+#ifdef USE_QUIC
+ /* Use connection socket for QUIC by default. */
+ bind_conf->quic_mode = QUIC_SOCK_MODE_CONN;
#endif
LIST_INIT(&bind_conf->listeners);
conn_id->qc = qc;
- if ((global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
+ if (l->bind_conf->quic_mode == QUIC_SOCK_MODE_CONN &&
+ (global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
is_addr(local_addr)) {
TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
qc_alloc_fd(qc, local_addr, peer_addr);