]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Export QUIC CLI code from quic_conn.c
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 24 Jul 2023 09:51:02 +0000 (11:51 +0200)
committerFrédéric Lécaille <flecaille@haproxy.com>
Thu, 27 Jul 2023 08:51:03 +0000 (10:51 +0200)
To accelerate the compilation of quic_conn.c file, export the code in relation
with the QUIC CLI from quic_conn.c to quic_cli.c.

Makefile
include/haproxy/quic_cli-t.h [new file with mode: 0644]
src/quic_cli.c [new file with mode: 0644]
src/quic_conn.c

index 26f995be5518928292be2209ef0dc82ab0d07e68..a8c5a53b4d2e078cbe11e00963c0f674c53be610 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -608,7 +608,7 @@ OPTIONS_OBJS += src/quic_conn.o src/mux_quic.o src/h3.o src/xprt_quic.o    \
                 src/qpack-dec.o src/hq_interop.o src/quic_stream.o         \
                 src/h3_stats.o src/qmux_http.o src/cfgparse-quic.o         \
                 src/cbuf.o src/quic_cc.o src/quic_cc_nocc.o                \
-                src/quic_trace.o
+                src/quic_trace.o src/quic_cli.o
 endif
 
 ifneq ($(USE_QUIC_OPENSSL_COMPAT),)
diff --git a/include/haproxy/quic_cli-t.h b/include/haproxy/quic_cli-t.h
new file mode 100644 (file)
index 0000000..6f95899
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/haproxy/quic_trace-t.h
+ * Definitions for QUIC CLI internal types, constants and flags.
+ *
+ * Copyright (C) 2023
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _HAPROXY_QUIC_CLI_T_H
+#define _HAPROXY_QUIC_CLI_T_H
+
+extern unsigned int qc_epoch;
+
+#endif /* _HAPROXY_QUIC_CLI_T_H */
diff --git a/src/quic_cli.c b/src/quic_cli.c
new file mode 100644 (file)
index 0000000..2b9ba64
--- /dev/null
@@ -0,0 +1,401 @@
+#include <import/eb64tree.h>
+
+#include <haproxy/applet-t.h>
+#include <haproxy/cli.h>
+#include <haproxy/list.h>
+#include <haproxy/tools.h>
+#include <haproxy/quic_conn-t.h>
+#include <haproxy/quic_tp.h>
+
+/* incremented by each "show quic". */
+unsigned int qc_epoch = 0;
+
+enum quic_dump_format {
+       QUIC_DUMP_FMT_ONELINE,
+       QUIC_DUMP_FMT_FULL,
+};
+
+/* appctx context used by "show quic" command */
+struct show_quic_ctx {
+       unsigned int epoch;
+       struct bref bref; /* back-reference to the quic-conn being dumped */
+       unsigned int thr;
+       int flags;
+       enum quic_dump_format format;
+};
+
+#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
+
+static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       struct show_quic_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+       int argc = 2;
+
+       if (!cli_has_level(appctx, ACCESS_LVL_OPER))
+               return 1;
+
+       ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
+       ctx->thr = 0;
+       ctx->flags = 0;
+       ctx->format = QUIC_DUMP_FMT_ONELINE;
+
+       if (strcmp(args[argc], "oneline") == 0) {
+               /* format already used as default value */
+               ++argc;
+       }
+       else if (strcmp(args[argc], "full") == 0) {
+               ctx->format = QUIC_DUMP_FMT_FULL;
+               ++argc;
+       }
+
+       while (*args[argc]) {
+               if (strcmp(args[argc], "all") == 0)
+                       ctx->flags |= QC_CLI_FL_SHOW_ALL;
+
+               ++argc;
+       }
+
+       LIST_INIT(&ctx->bref.users);
+
+       return 0;
+}
+
+/* Dump for "show quic" with "oneline" format. */
+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;
+
+       ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr,
+                           qc->li->bind_conf->frontend->id);
+       chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */
+
+       /* State */
+       if (qc->flags & QUIC_FL_CONN_CLOSING)
+               chunk_appendf(&trash, "CLOSE   ");
+       else if (qc->flags & QUIC_FL_CONN_DRAINING)
+               chunk_appendf(&trash, "DRAIN   ");
+       else if (qc->state < QUIC_HS_ST_COMPLETE)
+               chunk_appendf(&trash, "HDSHK   ");
+       else
+               chunk_appendf(&trash, "ESTAB   ");
+
+       /* Bytes in flight / Lost packets */
+       chunk_appendf(&trash, "%9llu %6llu %6llu   ",
+                     (ullong)qc->path->in_flight,
+                     (ullong)qc->path->ifae_pkts,
+                     (ullong)qc->path->loss.nb_lost_pkt);
+
+       /* Socket */
+       if (qc->local_addr.ss_family == AF_INET ||
+           qc->local_addr.ss_family == AF_INET6) {
+               addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->local_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, "%15s:%-5s   ", bufaddr, bufport);
+
+               addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, "%15s:%-5s ", bufaddr, bufport);
+
+       }
+
+       /* CIDs */
+       for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
+               chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
+
+       chunk_appendf(&trash, " ");
+       for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
+               chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
+
+       chunk_appendf(&trash, "\n");
+}
+
+/* Dump for "show quic" with "full" format. */
+static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
+{
+       struct quic_pktns *pktns;
+       struct eb64_node *node;
+       struct qc_stream_desc *stream;
+       char bufaddr[INET6_ADDRSTRLEN], bufport[6];
+       int expire, i, addnl;
+       unsigned char cid_len;
+
+       addnl = 0;
+       /* CIDs */
+       chunk_appendf(&trash, "* %p[%02u]: scid=", qc, ctx->thr);
+       for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
+               chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
+       while (cid_len++ < 20)
+               chunk_appendf(&trash, "..");
+
+       chunk_appendf(&trash, " dcid=");
+       for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
+               chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
+       while (cid_len++ < 20)
+               chunk_appendf(&trash, "..");
+
+       chunk_appendf(&trash, "\n");
+
+       chunk_appendf(&trash, "  loc. TPs:");
+       quic_transport_params_dump(&trash, qc, &qc->rx.params);
+       chunk_appendf(&trash, "\n");
+       chunk_appendf(&trash, "  rem. TPs:");
+       quic_transport_params_dump(&trash, qc, &qc->tx.params);
+       chunk_appendf(&trash, "\n");
+
+       /* Connection state */
+       if (qc->flags & QUIC_FL_CONN_CLOSING)
+               chunk_appendf(&trash, "  st=closing          ");
+       else if (qc->flags & QUIC_FL_CONN_DRAINING)
+               chunk_appendf(&trash, "  st=draining         ");
+       else if (qc->state < QUIC_HS_ST_CONFIRMED)
+               chunk_appendf(&trash, "  st=handshake        ");
+       else
+               chunk_appendf(&trash, "  st=opened           ");
+
+       if (qc->mux_state == QC_MUX_NULL)
+               chunk_appendf(&trash, "mux=null                                      ");
+       else if (qc->mux_state == QC_MUX_READY)
+               chunk_appendf(&trash, "mux=ready                                     ");
+       else
+               chunk_appendf(&trash, "mux=released                                  ");
+
+       expire = qc->idle_expire;
+       chunk_appendf(&trash, "expire=%02ds ",
+                     TICKS_TO_MS(tick_remain(now_ms, expire)) / 1000);
+
+       chunk_appendf(&trash, "\n");
+
+       /* Socket */
+       chunk_appendf(&trash, "  fd=%d", qc->fd);
+       if (qc->local_addr.ss_family == AF_INET ||
+           qc->local_addr.ss_family == AF_INET6) {
+               addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->local_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, "               local_addr=%s:%s", bufaddr, bufport);
+
+               addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, " foreign_addr=%s:%s", bufaddr, bufport);
+       }
+
+       chunk_appendf(&trash, "\n");
+
+       /* Packet number spaces information */
+       pktns = qc->ipktns;
+       if (pktns) {
+               chunk_appendf(&trash, "  [initl]             rx.ackrng=%-6zu tx.inflight=%-6zu",
+                             pktns->rx.arngs.sz, pktns->tx.in_flight);
+       }
+
+       pktns = qc->hpktns;
+       if (pktns) {
+               chunk_appendf(&trash, "           [hndshk] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
+                             pktns->rx.arngs.sz, pktns->tx.in_flight);
+       }
+
+       pktns = qc->apktns;
+       if (pktns) {
+               chunk_appendf(&trash, "  [01rtt]             rx.ackrng=%-6zu tx.inflight=%-6zu\n",
+                             pktns->rx.arngs.sz, pktns->tx.in_flight);
+       }
+
+       chunk_appendf(&trash, "  srtt=%-4u rttvar=%-4u rttmin=%-4u ptoc=%-4u cwnd=%-6llu"
+                             " mcwnd=%-6llu sentpkts=%-6llu lostpkts=%-6llu\n",
+                     qc->path->loss.srtt >> 3, qc->path->loss.rtt_var >> 2,
+                     qc->path->loss.rtt_min, qc->path->loss.pto_count, (ullong)qc->path->cwnd,
+                     (ullong)qc->path->mcwnd, (ullong)qc->cntrs.sent_pkt, (ullong)qc->path->loss.nb_lost_pkt);
+
+       if (qc->cntrs.dropped_pkt) {
+               chunk_appendf(&trash, " droppkts=%-6llu", qc->cntrs.dropped_pkt);
+               addnl = 1;
+       }
+       if (qc->cntrs.dropped_pkt_bufoverrun) {
+               chunk_appendf(&trash, " dropbuff=%-6llu", qc->cntrs.dropped_pkt_bufoverrun);
+               addnl = 1;
+       }
+       if (qc->cntrs.dropped_parsing) {
+               chunk_appendf(&trash, " droppars=%-6llu", qc->cntrs.dropped_parsing);
+               addnl = 1;
+       }
+       if (qc->cntrs.socket_full) {
+               chunk_appendf(&trash, " sockfull=%-6llu", qc->cntrs.socket_full);
+               addnl = 1;
+       }
+       if (qc->cntrs.sendto_err) {
+               chunk_appendf(&trash, " sendtoerr=%-6llu", qc->cntrs.sendto_err);
+               addnl = 1;
+       }
+       if (qc->cntrs.sendto_err_unknown) {
+               chunk_appendf(&trash, " sendtounknerr=%-6llu", qc->cntrs.sendto_err);
+               addnl = 1;
+       }
+       if (qc->cntrs.conn_migration_done) {
+               chunk_appendf(&trash, " migrdone=%-6llu", qc->cntrs.conn_migration_done);
+               addnl = 1;
+       }
+       if (qc->cntrs.data_blocked) {
+               chunk_appendf(&trash, " datablocked=%-6llu", qc->cntrs.data_blocked);
+               addnl = 1;
+       }
+       if (qc->cntrs.stream_data_blocked) {
+               chunk_appendf(&trash, " sdatablocked=%-6llu", qc->cntrs.stream_data_blocked);
+               addnl = 1;
+       }
+       if (qc->cntrs.streams_blocked_bidi) {
+               chunk_appendf(&trash, " sblockebidi=%-6llu", qc->cntrs.streams_blocked_bidi);
+               addnl = 1;
+       }
+       if (qc->cntrs.streams_blocked_uni) {
+               chunk_appendf(&trash, " sblockeduni=%-6llu", qc->cntrs.streams_blocked_uni);
+               addnl = 1;
+       }
+       if (addnl)
+               chunk_appendf(&trash, "\n");
+
+       /* Streams */
+       node = eb64_first(&qc->streams_by_id);
+       i = 0;
+       while (node) {
+               stream = eb64_entry(node, struct qc_stream_desc, by_id);
+               node = eb64_next(node);
+
+               chunk_appendf(&trash, "  | stream=%-8llu", (unsigned long long)stream->by_id.key);
+               chunk_appendf(&trash, " off=%-8llu ack=%-8llu",
+                             (unsigned long long)stream->buf_offset,
+                             (unsigned long long)stream->ack_offset);
+
+               if (!(++i % 3)) {
+                       chunk_appendf(&trash, "\n");
+                       i = 0;
+               }
+       }
+
+       chunk_appendf(&trash, "\n");
+}
+
+static int cli_io_handler_dump_quic(struct appctx *appctx)
+{
+       struct show_quic_ctx *ctx = appctx->svcctx;
+       struct stconn *sc = appctx_sc(appctx);
+       struct quic_conn *qc;
+
+       thread_isolate();
+
+       if (ctx->thr >= global.nbthread)
+               goto done;
+
+       /* FIXME: Don't watch the other side !*/
+       if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) {
+               /* If we're forced to shut down, we might have to remove our
+                * reference to the last stream being dumped.
+                */
+               if (!LIST_ISEMPTY(&ctx->bref.users))
+                       LIST_DEL_INIT(&ctx->bref.users);
+               goto done;
+       }
+
+       chunk_reset(&trash);
+
+       if (!LIST_ISEMPTY(&ctx->bref.users)) {
+               /* Remove show_quic_ctx from previous quic_conn instance. */
+               LIST_DEL_INIT(&ctx->bref.users);
+       }
+       else if (!ctx->bref.ref) {
+               /* First invocation. */
+               ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
+
+               /* Print legend for oneline format. */
+               if (ctx->format == QUIC_DUMP_FMT_ONELINE) {
+                       chunk_appendf(&trash, "# conn/frontend                     state   "
+                                     "in_flight infl_p lost_p         "
+                                     "Local Address           Foreign Address      "
+                                     "local & remote CIDs\n");
+                       applet_putchk(appctx, &trash);
+               }
+       }
+
+       while (1) {
+               int done = 0;
+
+               if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
+                       /* If closing connections requested through "all", move
+                        * to quic_conns_clo list after browsing quic_conns.
+                        * Else move directly to the next quic_conns thread.
+                        */
+                       if (ctx->flags & QC_CLI_FL_SHOW_ALL) {
+                               ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
+                               continue;
+                       }
+
+                       done = 1;
+               }
+               else if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns_clo) {
+                       /* Closing list entirely browsed, go to next quic_conns
+                        * thread.
+                        */
+                       done = 1;
+               }
+               else {
+                       /* Retrieve next element of the current list. */
+                       qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
+                       if ((int)(qc->qc_epoch - ctx->epoch) > 0)
+                               done = 1;
+               }
+
+               if (done) {
+                       ++ctx->thr;
+                       if (ctx->thr >= global.nbthread)
+                               break;
+                       /* Switch to next thread quic_conns list. */
+                       ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
+                       continue;
+               }
+
+               switch (ctx->format) {
+               case QUIC_DUMP_FMT_FULL:
+                       dump_quic_full(ctx, qc);
+                       break;
+               case QUIC_DUMP_FMT_ONELINE:
+                       dump_quic_oneline(ctx, qc);
+                       break;
+               }
+
+               if (applet_putchk(appctx, &trash) == -1) {
+                       /* Register show_quic_ctx to quic_conn instance. */
+                       LIST_APPEND(&qc->back_refs, &ctx->bref.users);
+                       goto full;
+               }
+
+               ctx->bref.ref = qc->el_th_ctx.n;
+       }
+
+ done:
+       thread_release();
+       return 1;
+
+ full:
+       thread_release();
+       return 0;
+}
+
+static void cli_release_show_quic(struct appctx *appctx)
+{
+       struct show_quic_ctx *ctx = appctx->svcctx;
+
+       if (ctx->thr < global.nbthread) {
+               thread_isolate();
+               if (!LIST_ISEMPTY(&ctx->bref.users))
+                       LIST_DEL_INIT(&ctx->bref.users);
+               thread_release();
+       }
+}
+
+static struct cli_kw_list cli_kws = {{ }, {
+       { { "show", "quic", NULL }, "show quic [oneline|full] [all]          : display quic connections status", cli_parse_show_quic, cli_io_handler_dump_quic, cli_release_show_quic },
+       {{},}
+}};
+
+INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
+
index 1a8ed164ea0dec7c7ad2accbf2a1751052373a6f..60374da97165a6ab48da109e24977f70235ad920 100644 (file)
@@ -34,8 +34,6 @@
 #include <haproxy/ticks.h>
 #include <haproxy/xxhash.h>
 
-#include <haproxy/applet-t.h>
-#include <haproxy/cli.h>
 #include <haproxy/connection.h>
 #include <haproxy/fd.h>
 #include <haproxy/freq_ctr.h>
@@ -48,6 +46,7 @@
 #include <haproxy/pipe.h>
 #include <haproxy/proxy.h>
 #include <haproxy/quic_cc.h>
+#include <haproxy/quic_cli-t.h>
 #include <haproxy/quic_frame.h>
 #include <haproxy/quic_enc.h>
 #include <haproxy/quic_loss.h>
@@ -64,9 +63,6 @@
 #include <haproxy/thread.h>
 #include <haproxy/trace.h>
 
-/* incremented by each "show quic". */
-static unsigned int qc_epoch = 0;
-
 /* list of supported QUIC versions by this implementation */
 const struct quic_version quic_versions[] = {
        {
@@ -8013,395 +8009,6 @@ void qc_finalize_affinity_rebind(struct quic_conn *qc)
        TRACE_LEAVE(QUIC_EV_CONN_SET_AFFINITY, qc);
 }
 
-enum quic_dump_format {
-       QUIC_DUMP_FMT_ONELINE,
-       QUIC_DUMP_FMT_FULL,
-};
-
-/* appctx context used by "show quic" command */
-struct show_quic_ctx {
-       unsigned int epoch;
-       struct bref bref; /* back-reference to the quic-conn being dumped */
-       unsigned int thr;
-       int flags;
-       enum quic_dump_format format;
-};
-
-#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
-
-static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx, void *private)
-{
-       struct show_quic_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
-       int argc = 2;
-
-       if (!cli_has_level(appctx, ACCESS_LVL_OPER))
-               return 1;
-
-       ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
-       ctx->thr = 0;
-       ctx->flags = 0;
-       ctx->format = QUIC_DUMP_FMT_ONELINE;
-
-       if (strcmp(args[argc], "oneline") == 0) {
-               /* format already used as default value */
-               ++argc;
-       }
-       else if (strcmp(args[argc], "full") == 0) {
-               ctx->format = QUIC_DUMP_FMT_FULL;
-               ++argc;
-       }
-
-       while (*args[argc]) {
-               if (strcmp(args[argc], "all") == 0)
-                       ctx->flags |= QC_CLI_FL_SHOW_ALL;
-
-               ++argc;
-       }
-
-       LIST_INIT(&ctx->bref.users);
-
-       return 0;
-}
-
-/* Dump for "show quic" with "oneline" format. */
-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;
-
-       ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr,
-                           qc->li->bind_conf->frontend->id);
-       chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */
-
-       /* State */
-       if (qc->flags & QUIC_FL_CONN_CLOSING)
-               chunk_appendf(&trash, "CLOSE   ");
-       else if (qc->flags & QUIC_FL_CONN_DRAINING)
-               chunk_appendf(&trash, "DRAIN   ");
-       else if (qc->state < QUIC_HS_ST_COMPLETE)
-               chunk_appendf(&trash, "HDSHK   ");
-       else
-               chunk_appendf(&trash, "ESTAB   ");
-
-       /* Bytes in flight / Lost packets */
-       chunk_appendf(&trash, "%9llu %6llu %6llu   ",
-                     (ullong)qc->path->in_flight,
-                     (ullong)qc->path->ifae_pkts,
-                     (ullong)qc->path->loss.nb_lost_pkt);
-
-       /* Socket */
-       if (qc->local_addr.ss_family == AF_INET ||
-           qc->local_addr.ss_family == AF_INET6) {
-               addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
-               port_to_str(&qc->local_addr, bufport, sizeof(bufport));
-               chunk_appendf(&trash, "%15s:%-5s   ", bufaddr, bufport);
-
-               addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
-               port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
-               chunk_appendf(&trash, "%15s:%-5s ", bufaddr, bufport);
-
-       }
-
-       /* CIDs */
-       for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
-               chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
-
-       chunk_appendf(&trash, " ");
-       for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
-               chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
-
-       chunk_appendf(&trash, "\n");
-}
-
-/* Dump for "show quic" with "full" format. */
-static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
-{
-       struct quic_pktns *pktns;
-       struct eb64_node *node;
-       struct qc_stream_desc *stream;
-       char bufaddr[INET6_ADDRSTRLEN], bufport[6];
-       int expire, i, addnl;
-       unsigned char cid_len;
-
-       addnl = 0;
-       /* CIDs */
-       chunk_appendf(&trash, "* %p[%02u]: scid=", qc, ctx->thr);
-       for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
-               chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
-       while (cid_len++ < 20)
-               chunk_appendf(&trash, "..");
-
-       chunk_appendf(&trash, " dcid=");
-       for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
-               chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
-       while (cid_len++ < 20)
-               chunk_appendf(&trash, "..");
-
-       chunk_appendf(&trash, "\n");
-
-       chunk_appendf(&trash, "  loc. TPs:");
-       quic_transport_params_dump(&trash, qc, &qc->rx.params);
-       chunk_appendf(&trash, "\n");
-       chunk_appendf(&trash, "  rem. TPs:");
-       quic_transport_params_dump(&trash, qc, &qc->tx.params);
-       chunk_appendf(&trash, "\n");
-
-       /* Connection state */
-       if (qc->flags & QUIC_FL_CONN_CLOSING)
-               chunk_appendf(&trash, "  st=closing          ");
-       else if (qc->flags & QUIC_FL_CONN_DRAINING)
-               chunk_appendf(&trash, "  st=draining         ");
-       else if (qc->state < QUIC_HS_ST_CONFIRMED)
-               chunk_appendf(&trash, "  st=handshake        ");
-       else
-               chunk_appendf(&trash, "  st=opened           ");
-
-       if (qc->mux_state == QC_MUX_NULL)
-               chunk_appendf(&trash, "mux=null                                      ");
-       else if (qc->mux_state == QC_MUX_READY)
-               chunk_appendf(&trash, "mux=ready                                     ");
-       else
-               chunk_appendf(&trash, "mux=released                                  ");
-
-       expire = qc->idle_expire;
-       chunk_appendf(&trash, "expire=%02ds ",
-                     TICKS_TO_MS(tick_remain(now_ms, expire)) / 1000);
-
-       chunk_appendf(&trash, "\n");
-
-       /* Socket */
-       chunk_appendf(&trash, "  fd=%d", qc->fd);
-       if (qc->local_addr.ss_family == AF_INET ||
-           qc->local_addr.ss_family == AF_INET6) {
-               addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
-               port_to_str(&qc->local_addr, bufport, sizeof(bufport));
-               chunk_appendf(&trash, "               local_addr=%s:%s", bufaddr, bufport);
-
-               addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
-               port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
-               chunk_appendf(&trash, " foreign_addr=%s:%s", bufaddr, bufport);
-       }
-
-       chunk_appendf(&trash, "\n");
-
-       /* Packet number spaces information */
-       pktns = qc->ipktns;
-       if (pktns) {
-               chunk_appendf(&trash, "  [initl]             rx.ackrng=%-6zu tx.inflight=%-6zu",
-                             pktns->rx.arngs.sz, pktns->tx.in_flight);
-       }
-
-       pktns = qc->hpktns;
-       if (pktns) {
-               chunk_appendf(&trash, "           [hndshk] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
-                             pktns->rx.arngs.sz, pktns->tx.in_flight);
-       }
-
-       pktns = qc->apktns;
-       if (pktns) {
-               chunk_appendf(&trash, "  [01rtt]             rx.ackrng=%-6zu tx.inflight=%-6zu\n",
-                             pktns->rx.arngs.sz, pktns->tx.in_flight);
-       }
-
-       chunk_appendf(&trash, "  srtt=%-4u rttvar=%-4u rttmin=%-4u ptoc=%-4u cwnd=%-6llu"
-                             " mcwnd=%-6llu sentpkts=%-6llu lostpkts=%-6llu\n",
-                     qc->path->loss.srtt >> 3, qc->path->loss.rtt_var >> 2,
-                     qc->path->loss.rtt_min, qc->path->loss.pto_count, (ullong)qc->path->cwnd,
-                     (ullong)qc->path->mcwnd, (ullong)qc->cntrs.sent_pkt, (ullong)qc->path->loss.nb_lost_pkt);
-
-       if (qc->cntrs.dropped_pkt) {
-               chunk_appendf(&trash, " droppkts=%-6llu", qc->cntrs.dropped_pkt);
-               addnl = 1;
-       }
-       if (qc->cntrs.dropped_pkt_bufoverrun) {
-               chunk_appendf(&trash, " dropbuff=%-6llu", qc->cntrs.dropped_pkt_bufoverrun);
-               addnl = 1;
-       }
-       if (qc->cntrs.dropped_parsing) {
-               chunk_appendf(&trash, " droppars=%-6llu", qc->cntrs.dropped_parsing);
-               addnl = 1;
-       }
-       if (qc->cntrs.socket_full) {
-               chunk_appendf(&trash, " sockfull=%-6llu", qc->cntrs.socket_full);
-               addnl = 1;
-       }
-       if (qc->cntrs.sendto_err) {
-               chunk_appendf(&trash, " sendtoerr=%-6llu", qc->cntrs.sendto_err);
-               addnl = 1;
-       }
-       if (qc->cntrs.sendto_err_unknown) {
-               chunk_appendf(&trash, " sendtounknerr=%-6llu", qc->cntrs.sendto_err);
-               addnl = 1;
-       }
-       if (qc->cntrs.conn_migration_done) {
-               chunk_appendf(&trash, " migrdone=%-6llu", qc->cntrs.conn_migration_done);
-               addnl = 1;
-       }
-       if (qc->cntrs.data_blocked) {
-               chunk_appendf(&trash, " datablocked=%-6llu", qc->cntrs.data_blocked);
-               addnl = 1;
-       }
-       if (qc->cntrs.stream_data_blocked) {
-               chunk_appendf(&trash, " sdatablocked=%-6llu", qc->cntrs.stream_data_blocked);
-               addnl = 1;
-       }
-       if (qc->cntrs.streams_blocked_bidi) {
-               chunk_appendf(&trash, " sblockebidi=%-6llu", qc->cntrs.streams_blocked_bidi);
-               addnl = 1;
-       }
-       if (qc->cntrs.streams_blocked_uni) {
-               chunk_appendf(&trash, " sblockeduni=%-6llu", qc->cntrs.streams_blocked_uni);
-               addnl = 1;
-       }
-       if (addnl)
-               chunk_appendf(&trash, "\n");
-
-       /* Streams */
-       node = eb64_first(&qc->streams_by_id);
-       i = 0;
-       while (node) {
-               stream = eb64_entry(node, struct qc_stream_desc, by_id);
-               node = eb64_next(node);
-
-               chunk_appendf(&trash, "  | stream=%-8llu", (unsigned long long)stream->by_id.key);
-               chunk_appendf(&trash, " off=%-8llu ack=%-8llu",
-                             (unsigned long long)stream->buf_offset,
-                             (unsigned long long)stream->ack_offset);
-
-               if (!(++i % 3)) {
-                       chunk_appendf(&trash, "\n");
-                       i = 0;
-               }
-       }
-
-       chunk_appendf(&trash, "\n");
-}
-
-static int cli_io_handler_dump_quic(struct appctx *appctx)
-{
-       struct show_quic_ctx *ctx = appctx->svcctx;
-       struct stconn *sc = appctx_sc(appctx);
-       struct quic_conn *qc;
-
-       thread_isolate();
-
-       if (ctx->thr >= global.nbthread)
-               goto done;
-
-       /* FIXME: Don't watch the other side !*/
-       if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) {
-               /* If we're forced to shut down, we might have to remove our
-                * reference to the last stream being dumped.
-                */
-               if (!LIST_ISEMPTY(&ctx->bref.users))
-                       LIST_DEL_INIT(&ctx->bref.users);
-               goto done;
-       }
-
-       chunk_reset(&trash);
-
-       if (!LIST_ISEMPTY(&ctx->bref.users)) {
-               /* Remove show_quic_ctx from previous quic_conn instance. */
-               LIST_DEL_INIT(&ctx->bref.users);
-       }
-       else if (!ctx->bref.ref) {
-               /* First invocation. */
-               ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
-
-               /* Print legend for oneline format. */
-               if (ctx->format == QUIC_DUMP_FMT_ONELINE) {
-                       chunk_appendf(&trash, "# conn/frontend                     state   "
-                                     "in_flight infl_p lost_p         "
-                                     "Local Address           Foreign Address      "
-                                     "local & remote CIDs\n");
-                       applet_putchk(appctx, &trash);
-               }
-       }
-
-       while (1) {
-               int done = 0;
-
-               if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
-                       /* If closing connections requested through "all", move
-                        * to quic_conns_clo list after browsing quic_conns.
-                        * Else move directly to the next quic_conns thread.
-                        */
-                       if (ctx->flags & QC_CLI_FL_SHOW_ALL) {
-                               ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
-                               continue;
-                       }
-
-                       done = 1;
-               }
-               else if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns_clo) {
-                       /* Closing list entirely browsed, go to next quic_conns
-                        * thread.
-                        */
-                       done = 1;
-               }
-               else {
-                       /* Retrieve next element of the current list. */
-                       qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
-                       if ((int)(qc->qc_epoch - ctx->epoch) > 0)
-                               done = 1;
-               }
-
-               if (done) {
-                       ++ctx->thr;
-                       if (ctx->thr >= global.nbthread)
-                               break;
-                       /* Switch to next thread quic_conns list. */
-                       ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
-                       continue;
-               }
-
-               switch (ctx->format) {
-               case QUIC_DUMP_FMT_FULL:
-                       dump_quic_full(ctx, qc);
-                       break;
-               case QUIC_DUMP_FMT_ONELINE:
-                       dump_quic_oneline(ctx, qc);
-                       break;
-               }
-
-               if (applet_putchk(appctx, &trash) == -1) {
-                       /* Register show_quic_ctx to quic_conn instance. */
-                       LIST_APPEND(&qc->back_refs, &ctx->bref.users);
-                       goto full;
-               }
-
-               ctx->bref.ref = qc->el_th_ctx.n;
-       }
-
- done:
-       thread_release();
-       return 1;
-
- full:
-       thread_release();
-       return 0;
-}
-
-static void cli_release_show_quic(struct appctx *appctx)
-{
-       struct show_quic_ctx *ctx = appctx->svcctx;
-
-       if (ctx->thr < global.nbthread) {
-               thread_isolate();
-               if (!LIST_ISEMPTY(&ctx->bref.users))
-                       LIST_DEL_INIT(&ctx->bref.users);
-               thread_release();
-       }
-}
-
-static struct cli_kw_list cli_kws = {{ }, {
-       { { "show", "quic", NULL }, "show quic [oneline|full] [all]          : display quic connections status", cli_parse_show_quic, cli_io_handler_dump_quic, cli_release_show_quic },
-       {{},}
-}};
-
-INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
-
 static void init_quic()
 {
        int thr;