mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
MINOR: quic: filter show quic by address
Add the possibilty to restrict show quic output to only a single connection. This is done by specifying a quic_conn address pointer. Default format selection has evolved with it. Indeed, it seems more fitting to use full format by default when filtering on a connection. However, it's still possible to revert to the original oneline format with it by specifying it explicitely.
This commit is contained in:
parent
60fcc27577
commit
c4f5ff8369
@ -3067,14 +3067,19 @@ show resolvers [<resolvers section id>]
|
|||||||
too_big: too big response
|
too_big: too big response
|
||||||
outdated: number of response arrived too late (after another name server)
|
outdated: number of response arrived too late (after another name server)
|
||||||
|
|
||||||
show quic [oneline|full] [all]
|
show quic [oneline|full] [<filter>]
|
||||||
Dump information on all active QUIC frontend connections. This command is
|
Dump information on all active QUIC frontend connections. This command is
|
||||||
restricted and can only be issued on sockets configured for levels "operator"
|
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
|
or "admin".
|
||||||
the verbosity. Currently supported values are "oneline" which is the default
|
|
||||||
if format is unspecified or "full". By default, connections on closing or
|
An optional format can be specified as first argument to control the
|
||||||
draining state are not displayed. Use the extra argument "all" to include
|
verbosity. Currently supported values are "oneline" which is the default if
|
||||||
them in the output.
|
format is unspecified or "full".
|
||||||
|
|
||||||
|
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
|
||||||
|
extra argument "all" to include them in the output. It's also possible to
|
||||||
|
restrict to a single connection by specifying its hexadecimal address.
|
||||||
|
|
||||||
show servers conn [<backend>]
|
show servers conn [<backend>]
|
||||||
Dump the current and idle connections state of the servers belonging to the
|
Dump the current and idle connections state of the servers belonging to the
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
unsigned int qc_epoch = 0;
|
unsigned int qc_epoch = 0;
|
||||||
|
|
||||||
enum quic_dump_format {
|
enum quic_dump_format {
|
||||||
|
QUIC_DUMP_FMT_DEFAULT, /* value used if not explicitely specified. */
|
||||||
|
|
||||||
QUIC_DUMP_FMT_ONELINE,
|
QUIC_DUMP_FMT_ONELINE,
|
||||||
QUIC_DUMP_FMT_FULL,
|
QUIC_DUMP_FMT_FULL,
|
||||||
};
|
};
|
||||||
@ -22,10 +24,23 @@ struct show_quic_ctx {
|
|||||||
unsigned int thr;
|
unsigned int thr;
|
||||||
int flags;
|
int flags;
|
||||||
enum quic_dump_format format;
|
enum quic_dump_format format;
|
||||||
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
|
#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
|
||||||
|
|
||||||
|
/* Returns the output format for show quic. If specified explicitely use it as
|
||||||
|
* set. Else format depends if filtering on a single connection instance. If
|
||||||
|
* true, full format is preferred else oneline.
|
||||||
|
*/
|
||||||
|
static enum quic_dump_format cli_show_quic_format(const struct show_quic_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->format == QUIC_DUMP_FMT_DEFAULT)
|
||||||
|
return ctx->ptr ? QUIC_DUMP_FMT_FULL : QUIC_DUMP_FMT_ONELINE;
|
||||||
|
else
|
||||||
|
return ctx->format;
|
||||||
|
}
|
||||||
|
|
||||||
static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx, void *private)
|
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));
|
struct show_quic_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
|
||||||
@ -37,10 +52,11 @@ static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx
|
|||||||
ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
|
ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
|
||||||
ctx->thr = 0;
|
ctx->thr = 0;
|
||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
ctx->format = QUIC_DUMP_FMT_ONELINE;
|
ctx->format = QUIC_DUMP_FMT_DEFAULT;
|
||||||
|
ctx->ptr = 0;
|
||||||
|
|
||||||
if (strcmp(args[argc], "oneline") == 0) {
|
if (strcmp(args[argc], "oneline") == 0) {
|
||||||
/* format already used as default value */
|
ctx->format = QUIC_DUMP_FMT_ONELINE;
|
||||||
++argc;
|
++argc;
|
||||||
}
|
}
|
||||||
else if (strcmp(args[argc], "full") == 0) {
|
else if (strcmp(args[argc], "full") == 0) {
|
||||||
@ -48,9 +64,24 @@ static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx
|
|||||||
++argc;
|
++argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*args[argc]) {
|
if (*args[argc]) {
|
||||||
if (strcmp(args[argc], "all") == 0)
|
struct ist istarg = ist(args[argc]);
|
||||||
|
|
||||||
|
if (istmatchi(istarg, ist("0x"))) {
|
||||||
|
char *nptr;
|
||||||
|
ctx->ptr = (void *)strtol(args[argc], &nptr, 16);
|
||||||
|
if (*nptr) {
|
||||||
|
cli_err(appctx, "Invalid quic_conn pointer.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (istmatch(istarg, ist("all"))) {
|
||||||
ctx->flags |= QC_CLI_FL_SHOW_ALL;
|
ctx->flags |= QC_CLI_FL_SHOW_ALL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cli_err(appctx, "Invalid argument.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
++argc;
|
++argc;
|
||||||
}
|
}
|
||||||
@ -309,7 +340,7 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
|
|||||||
ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
|
ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
|
||||||
|
|
||||||
/* Print legend for oneline format. */
|
/* Print legend for oneline format. */
|
||||||
if (ctx->format == QUIC_DUMP_FMT_ONELINE) {
|
if (cli_show_quic_format(ctx) == QUIC_DUMP_FMT_ONELINE) {
|
||||||
chunk_appendf(&trash, "# conn/frontend state "
|
chunk_appendf(&trash, "# conn/frontend state "
|
||||||
"in_flight infl_p lost_p "
|
"in_flight infl_p lost_p "
|
||||||
"Local Address Foreign Address "
|
"Local Address Foreign Address "
|
||||||
@ -322,11 +353,12 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
|
if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
|
||||||
/* If closing connections requested through "all", move
|
/* If closing connections requested through "all" or a
|
||||||
* to quic_conns_clo list after browsing quic_conns.
|
* specific connection is filtered, move to
|
||||||
* Else move directly to the next quic_conns thread.
|
* 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) {
|
if (ctx->flags & QC_CLI_FL_SHOW_ALL || ctx->ptr) {
|
||||||
ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
|
ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -344,6 +376,10 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
|
|||||||
qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
|
qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
|
||||||
if ((int)(qc->qc_epoch - ctx->epoch) > 0)
|
if ((int)(qc->qc_epoch - ctx->epoch) > 0)
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
|
/* Skip to next element if filter on a different connection. */
|
||||||
|
if (ctx->ptr && ctx->ptr != qc)
|
||||||
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
@ -355,13 +391,17 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ctx->format) {
|
switch (cli_show_quic_format(ctx)) {
|
||||||
case QUIC_DUMP_FMT_FULL:
|
case QUIC_DUMP_FMT_FULL:
|
||||||
dump_quic_full(ctx, qc);
|
dump_quic_full(ctx, qc);
|
||||||
break;
|
break;
|
||||||
case QUIC_DUMP_FMT_ONELINE:
|
case QUIC_DUMP_FMT_ONELINE:
|
||||||
dump_quic_oneline(ctx, qc);
|
dump_quic_oneline(ctx, qc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QUIC_DUMP_FMT_DEFAULT:
|
||||||
|
/* An explicit format must be returned by cli_show_quic_format(). */
|
||||||
|
ABORT_NOW();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applet_putchk(appctx, &trash) == -1) {
|
if (applet_putchk(appctx, &trash) == -1) {
|
||||||
@ -371,6 +411,10 @@ static int cli_io_handler_dump_quic(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->bref.ref = qc->el_th_ctx.n;
|
ctx->bref.ref = qc->el_th_ctx.n;
|
||||||
|
|
||||||
|
/* If filtered connection displayed, show quic can be stopped early. */
|
||||||
|
if (ctx->ptr)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -395,7 +439,7 @@ static void cli_release_show_quic(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct cli_kw_list cli_kws = {{ }, {
|
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 },
|
{ { "show", "quic", NULL }, "show quic [oneline|full] [<filter>] : display quic connections status", cli_parse_show_quic, cli_io_handler_dump_quic, cli_release_show_quic },
|
||||||
{{},}
|
{{},}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user