From e8b7337d860d5b959a56aac2191e432947d2a49b Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Thu, 19 Dec 2024 16:38:28 +0100 Subject: [PATCH] MINOR: stktable: support optional index for array types in {set, clear, show} table commands As discussed in GH #2286, {set, clear, show} table commands were unable to deal with array types such as gpt, because they handled such types as a non-array types, thus only the first entry (ie: gpt[0]) was considered. In this patch we add an extra logic around array-types handling so that it is possible to specify an array index right after the type, like this: set table peer/table key mykey data.gpt[2] value # where 2 is the entry index that we want to access If no index is specified, then it implicitly defaults to 0 to mimic previous behavior. --- doc/management.txt | 9 +++++++++ src/stick_table.c | 45 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index f085ad50a..aa542769c 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1869,6 +1869,9 @@ clear table [ data. ] | [ key ] | the entry cannot be matched using the key due to empty key or incompatible characters on the cli. + If data. is an array type, "[]" may be used to access a specific + index in the array, like so: data.gpt[1] + Example : $ echo "show table http_proxy" | socat stdio /tmp/sock1 >>> # table: http_proxy, type: ip, size:204800, used:2 @@ -2625,6 +2628,9 @@ set table
ptr [data. ]* pointer may be relevant if the entry cannot be matched using the key due to empty key or incompatible characters on the cli. + If data. is an array type, "[]" may be used to access a specific + index in the array, like so: data.gpt[1] + set timeout cli Change the CLI interface timeout for current connection. This can be useful during long debugging sessions where the user needs to constantly inspect @@ -3862,6 +3868,9 @@ show table [ data. [data. ...]] | the entry cannot be matched using the key due empty key or incompatible characters on the cli. + If data. is an array type, "[]" may be used to access a specific + index in the array, like so: data.gpt[1] + Example : $ echo "show table http_proxy" | socat stdio /tmp/sock1 >>> # table: http_proxy, type: ip, size:204800, used:2 diff --git a/src/stick_table.c b/src/stick_table.c index 775cd1e18..114fa4634 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -5281,6 +5281,7 @@ struct show_table_ctx { long long value[STKTABLE_FILTER_LEN]; /* value to compare against */ signed char data_type[STKTABLE_FILTER_LEN]; /* type of data to compare, or -1 if none */ signed char data_op[STKTABLE_FILTER_LEN]; /* operator (STD_OP_*) when data_type set */ + unsigned int data_idx[STKTABLE_FILTER_LEN]; /* index of data to consider for array types */ enum { STATE_NEXT = 0, /* px points to next table, entry=NULL */ STATE_DUMP, /* px points to curr table, entry is valid, refcount held */ @@ -5355,6 +5356,8 @@ static int table_process_entry(struct appctx *appctx, struct stksess *ts, char * case STK_CLI_ACT_SET: HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); for (cur_arg = 5; *args[cur_arg]; cur_arg += 2) { + unsigned int idx; + if (strncmp(args[cur_arg], "data.", 5) != 0) { cli_err(appctx, "\"data.\" followed by a value expected\n"); HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); @@ -5362,7 +5365,7 @@ static int table_process_entry(struct appctx *appctx, struct stksess *ts, char * return 1; } - data_type = stktable_get_data_type(args[cur_arg] + 5); + data_type = stktable_get_data_type_idx(args[cur_arg] + 5, &idx); if (data_type < 0) { cli_err(appctx, "Unknown data type\n"); HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); @@ -5384,7 +5387,17 @@ static int table_process_entry(struct appctx *appctx, struct stksess *ts, char * return 1; } - ptr = __stktable_data_ptr(t, ts, data_type); + if (stktable_data_types[data_type].is_array) { + ptr = stktable_data_ptr_idx(t, ts, data_type, idx); + if (!ptr) { + cli_err(appctx, "index out of range in this data array\n"); + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + stktable_touch_local(t, ts, 1); + return 1; + } + } + else + ptr = __stktable_data_ptr(t, ts, data_type); switch (stktable_data_types[data_type].std_type) { case STD_T_SINT: @@ -5515,7 +5528,7 @@ static int table_prepare_data_request(struct appctx *appctx, char **args) if (i > 0 && !*args[3+3*i]) // number of filter entries can be less than STKTABLE_FILTER_LEN break; /* condition on stored data value */ - ctx->data_type[i] = stktable_get_data_type(args[3+3*i] + 5); + ctx->data_type[i] = stktable_get_data_type_idx(args[3+3*i] + 5, &ctx->data_idx[i]); if (ctx->data_type[i] < 0) return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Unknown data type\n", i + 1)); @@ -5670,13 +5683,25 @@ static int cli_io_handler_table(struct appctx *appctx) if (ctx->data_type[i] == -1) break; dt = ctx->data_type[i]; - ptr = stktable_data_ptr(ctx->t, - ctx->entry, - dt); - /* table_prepare_data_request() normally ensures the - * type is both valid and stored - */ - BUG_ON(!ptr); + if (stktable_data_types[dt].is_array) { + ptr = stktable_data_ptr_idx(ctx->t, + ctx->entry, + dt, ctx->data_idx[i]); + if (!ptr) { + /* index out of range */ + skip_entry = 1; + break; + } + } + else { + ptr = stktable_data_ptr(ctx->t, + ctx->entry, + dt); + /* table_prepare_data_request() normally ensures the + * type is both valid and stored + */ + BUG_ON(!ptr); + } data = 0; switch (stktable_data_types[dt].std_type) {