]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: listener: Add QUIC info to listeners and receivers.
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 23 Nov 2020 13:23:21 +0000 (14:23 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 23 Dec 2020 10:57:26 +0000 (11:57 +0100)
This patch adds a quic_transport_params struct to bind_conf struct
used for the listeners. This is to store the QUIC transport parameters
for the listeners. Also initializes them when calling str2listener().
Before str2sa_range() it's too early to figure we're going to speak QUIC,
and after it's too late as listeners are already created. So it seems that
doing it in str2listener() when the protocol is discovered is the best
place.

Also adds two ebtrees to the underlying receivers to store the connection
by connections IDs (one for the original connection IDs, and another
one for the definitive connection IDs which really identify the connections.

However it doesn't seem normal that it is stored in the receiver nor the
listener. There should be a private context in the listener so that
protocols can store internal information. This element should in
fact be the listener handle.

Something still feels wrong, and probably we'll have to make QUIC and
SSL co-exist: a proof of this is that there's some explicit code in
bind_parse_ssl() to prevent the "ssl" keyword from replacing the xprt.

include/haproxy/listener-t.h
include/haproxy/receiver-t.h
src/cfgparse.c
src/proto_quic.c

index ec57f8867afe2644b7501a2da2c6e22b916ca7fa..ce5ed408feeeb36fc7522f08c6020e6d3898705b 100644 (file)
@@ -36,6 +36,7 @@
 #ifdef USE_OPENSSL
 #include <haproxy/openssl-compat.h>
 #endif
+#include <haproxy/xprt_quic-t.h>
 
 /* Some pointer types reference below */
 struct task;
@@ -165,6 +166,9 @@ struct bind_conf {
        char *ca_sign_pass;        /* CAKey passphrase */
 
        struct cert_key_and_chain * ca_sign_ckch;       /* CA and possible certificate chain for ca generation */
+#endif
+#ifdef USE_QUIC
+       struct quic_transport_params quic_params; /* QUIC transport parameters. */
 #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) */
index 5b17211c4bc90e8a600c0fa7dc5b18fecc24f984..7284da3f681ca2adc5b0687857b86982ebbfa25b 100644 (file)
@@ -62,6 +62,11 @@ struct receiver {
        void (*iocb)(int fd);            /* generic I/O handler (typically accept callback) */
        struct rx_settings *settings;    /* points to the settings used by this receiver */
        struct list proto_list;          /* list in the protocol header */
+#ifdef USE_QUIC
+       struct list qpkts;               /* QUIC Initial packets to accept new connections */
+       struct eb_root odcids;           /* QUIC original destination connection IDs. */
+       struct eb_root cids;             /* QUIC connection IDs. */
+#endif
        /* warning: this struct is huge, keep it at the bottom */
        struct sockaddr_storage addr;    /* the address the socket is bound to */
 };
index 957ae9e616518dcf307c360f3eea7d5a47349120..4dd01bb6319b923412163494dbe92916f7817749 100644 (file)
@@ -78,6 +78,7 @@
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
 #include <haproxy/uri_auth-t.h>
+#include <haproxy/xprt_quic.h>
 
 
 /* Used to chain configuration sections definitions. This list
@@ -135,6 +136,17 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
                        goto fail;
 
                /* OK the address looks correct */
+
+#ifdef USE_QUIC
+               /* The transport layer automatically switches to QUIC when QUIC
+                * is selected, regardless of bind_conf settings. We then need
+                * to initialize QUIC params.
+                */
+               if (proto->sock_type == SOCK_DGRAM && proto->ctrl_type == SOCK_STREAM) {
+                       bind_conf->xprt = xprt_get(XPRT_QUIC);
+                       quic_transport_params_init(&bind_conf->quic_params, 1);
+               }
+#endif
                if (!create_listeners(bind_conf, ss2, port, end, fd, proto, err)) {
                        memprintf(err, "%s for address '%s'.\n", *err, str);
                        goto fail;
index 751fc49aac625c4ae6c0e1e763d60b2d042aaca4..8b3e91bb9f0a1f78d67569ac5dcb0235cfd3f703 100644 (file)
@@ -46,6 +46,7 @@
 #include <haproxy/tools.h>
 
 
+static void quic_add_listener(struct protocol *proto, struct listener *listener);
 static int quic_bind_listener(struct listener *listener, char *errmsg, int errlen);
 static int quic_connect_server(struct connection *conn, int flags);
 static void quic_enable_listener(struct listener *listener);
@@ -60,7 +61,7 @@ struct protocol proto_quic4 = {
        .listen         = quic_bind_listener,
        .enable         = quic_enable_listener,
        .disable        = quic_disable_listener,
-       .add            = default_add_listener,
+       .add            = quic_add_listener,
        .unbind         = default_unbind_listener,
        .suspend        = default_suspend_listener,
        .resume         = default_resume_listener,
@@ -97,7 +98,7 @@ struct protocol proto_quic6 = {
        .listen         = quic_bind_listener,
        .enable         = quic_enable_listener,
        .disable        = quic_disable_listener,
-       .add            = default_add_listener,
+       .add            = quic_add_listener,
        .unbind         = default_unbind_listener,
        .suspend        = default_suspend_listener,
        .resume         = default_resume_listener,
@@ -513,6 +514,18 @@ int quic_connect_server(struct connection *conn, int flags)
        return SF_ERR_NONE;  /* connection is OK */
 }
 
+/* Add listener <listener> to protocol <proto>. Technically speaking we just
+ * initialize a few entries which should be doable during quic_bind_listener().
+ * The end of the initialization goes on with the default function.
+ */
+static void quic_add_listener(struct protocol *proto, struct listener *listener)
+{
+       LIST_INIT(&listener->rx.qpkts);
+       listener->rx.odcids = EB_ROOT_UNIQUE;
+       listener->rx.cids = EB_ROOT_UNIQUE;
+       default_add_listener(proto, listener);
+}
+
 /* This function tries to bind a QUIC4/6 listener. It may return a warning or
  * an error message in <errmsg> if the message is at most <errlen> bytes long
  * (including '\0'). Note that <errmsg> may be NULL if <errlen> is also zero.