diff --git a/doc/management.txt b/doc/management.txt index 4efeb90bd7..83c4c1dc70 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -3076,8 +3076,8 @@ show quic [] [] be interpreted in different way. The first possibility is to used predefined values, "oneline" for the default format and "full" to display all information. Alternatively, a list of comma-delimited fields can be specified - to restrict output. Currently supported values are "tp", "sock", "pktns" and - "cc". + to restrict output. Currently supported values are "tp", "sock", "pktns", + "cc" and "mux". The final argument is used to restrict or extend the connection list. By default, connections on closing or draining state are not displayed. Use the diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index da686c1bb4..b1d216860d 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -115,6 +115,8 @@ static inline void qcs_wait_http_req(struct qcs *qcs) LIST_APPEND(&qcc->opening_list, &qcs->el_opening); } +void qcc_show_quic(struct qcc *qcc); + #endif /* USE_QUIC */ #endif /* _HAPROXY_MUX_QUIC_H */ diff --git a/src/mux_quic.c b/src/mux_quic.c index 1d82b5125d..46e21b4b81 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -125,6 +126,9 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type) else if (quic_stream_is_local(qcc, id)) { qfctl_init(&qcs->tx.fc, qcc->rfctl.msd_uni_l); } + else { + qcs->tx.fc.off_real = 0; + } qcs->rx.ncbuf = NCBUF_NULL; qcs->rx.app_buf = BUF_NULL; @@ -3185,6 +3189,27 @@ static const struct mux_ops qmux_ops = { .name = "QUIC", }; +void qcc_show_quic(struct qcc *qcc) +{ + struct eb64_node *node; + chunk_appendf(&trash, " qcc=0x%p flags=0x%x sc=%llu hreq=%llu\n", + qcc, qcc->flags, (ullong)qcc->nb_sc, (ullong)qcc->nb_hreq); + + node = eb64_first(&qcc->streams_by_id); + while (node) { + struct qcs *qcs = eb64_entry(node, struct qcs, by_id); + chunk_appendf(&trash, " qcs=0x%p id=%llu flags=0x%x st=%s", + qcs, (ullong)qcs->id, qcs->flags, + qcs_st_to_str(qcs->st)); + if (!quic_stream_is_uni(qcs->id) || !quic_stream_is_local(qcc, qcs->id)) + chunk_appendf(&trash, " rxoff=%llu", (ullong)qcs->rx.offset); + if (!quic_stream_is_uni(qcs->id) || !quic_stream_is_remote(qcc, qcs->id)) + chunk_appendf(&trash, " txoff=%llu", (ullong)qcs->tx.fc.off_real); + chunk_appendf(&trash, "\n"); + node = eb64_next(node); + } +} + static struct mux_proto_list mux_proto_quic = { .token = IST("quic"), .mode = PROTO_MODE_HTTP, .side = PROTO_SIDE_FE, .mux = &qmux_ops }; diff --git a/src/quic_cli.c b/src/quic_cli.c index 526acc6582..49501d53d8 100644 --- a/src/quic_cli.c +++ b/src/quic_cli.c @@ -3,9 +3,10 @@ #include #include #include -#include +#include #include #include +#include /* incremented by each "show quic". */ unsigned int qc_epoch = 0; @@ -21,8 +22,9 @@ enum quic_dump_format { #define QUIC_DUMP_FLD_SOCK 0x0002 #define QUIC_DUMP_FLD_PKTNS 0x0004 #define QUIC_DUMP_FLD_CC 0x0008 +#define QUIC_DUMP_FLD_MUX 0x0010 /* Do not forget to update FLD_MASK when adding a new field. */ -#define QUIC_DUMP_FLD_MASK 0x000f +#define QUIC_DUMP_FLD_MASK 0x001f /* appctx context used by "show quic" command */ struct show_quic_ctx { @@ -90,6 +92,9 @@ static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx else if (isteq(field, ist("cc"))) { ctx->fields |= QUIC_DUMP_FLD_CC; } + else if (isteq(field, ist("mux"))) { + ctx->fields |= QUIC_DUMP_FLD_MUX; + } else { /* Current argument is comma-separated so it is * interpreted as a field list but an unknown @@ -202,10 +207,8 @@ static void dump_quic_oneline(struct show_quic_ctx *ctx, struct quic_conn *qc) 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; + int expire, addnl; unsigned char cid_len; addnl = 0; @@ -351,23 +354,8 @@ static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc) 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; - } - } + if (ctx->fields & QUIC_DUMP_FLD_MUX && qc->mux_state == QC_MUX_READY) + qcc_show_quic(qc->qcc); chunk_appendf(&trash, "\n"); }