]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement oneline format for "show quic"
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 5 May 2023 14:08:34 +0000 (16:08 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 5 May 2023 16:08:37 +0000 (18:08 +0200)
Add a new output format "oneline" for "show quic" command. This prints
one connection per line with minimal information. The objective is to
have an equivalent of the netstat/ss tools with just enough information
to quickly find connection which are misbehaving.

A legend is printed on the first line to describe the field columns
starting with a dash character.

This should be backported up to 2.7.

doc/management.txt
src/quic_conn.c

index 42cf2042bb7b2e2046455e0001ace3e5bb00e95d..978b0482f4887d7bdd5ea671f9962b463ae9832c 100644 (file)
@@ -2988,10 +2988,10 @@ show quic [<format>] [all]
   Dump information on all active QUIC frontend connections. This command is
   restricted and can only be issued on sockets configured for levels "operator"
   or "admin". An optional format can be specified as first argument to control
-  the verbosity. Currently only supported value is "full" which is the default
-  if format is unspecified. By default, connections on closing or draining
-  state are not displayed. Use the extra argument "all" to include them in the
-  output.
+  the verbosity. Currently supported values are "oneline" which is the default
+  if format is unspecified or "full". By default, connections on closing or
+  draining state are not displayed. Use the extra argument "all" to include
+  them in the output.
 
 show servers conn [<backend>]
   Dump the current and idle connections state of the servers belonging to the
index 1d43cd8d98646aa7b23d886cd641a8b12fe15812..c3e0beccf6ec955392f0bf19d8dd8a85b3862e36 100644 (file)
@@ -8596,6 +8596,7 @@ void qc_finalize_affinity_rebind(struct quic_conn *qc)
 }
 
 enum quic_dump_format {
+       QUIC_DUMP_FMT_ONELINE,
        QUIC_DUMP_FMT_FULL,
 };
 
@@ -8621,12 +8622,16 @@ static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx
        ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
        ctx->thr = 0;
        ctx->flags = 0;
-       ctx->format = QUIC_DUMP_FMT_FULL;
+       ctx->format = QUIC_DUMP_FMT_ONELINE;
 
-       if (strcmp(args[argc], "full") == 0) {
+       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)
@@ -8640,6 +8645,54 @@ static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx
        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];
+       unsigned char cid_len;
+
+       chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr,
+                     qc->li->bind_conf->frontend->id);
+
+       /* 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->peer_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, "%15s:%s ", bufaddr, bufport);
+
+               addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
+               port_to_str(&qc->local_addr, bufport, sizeof(bufport));
+               chunk_appendf(&trash, "%15s:%s      ", 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)
 {
@@ -8779,6 +8832,15 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
        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                    "
+                                     "from                    to      "
+                                     "local & remote CIDs\n");
+                       applet_putchk(appctx, &trash);
+               }
        }
 
        while (1) {
@@ -8822,6 +8884,9 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
                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) {