]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stktable: support optional index for array types in {set, clear, show} table...
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 19 Dec 2024 15:38:28 +0000 (16:38 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Mon, 23 Dec 2024 16:32:11 +0000 (17:32 +0100)
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
src/stick_table.c

index f085ad50a837a0a188588caeaefaa3e837713660..aa542769cccc0d9dc482126f4951d02c5bafe5c0 100644 (file)
@@ -1869,6 +1869,9 @@ clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ] |
   the entry cannot be matched using the key due to empty key or incompatible
   characters on the cli.
 
+  If data.<type> 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 <table> ptr <ptr> [data.<data_type> <value>]*
   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.<data_type> is an array type, "[]" may be used to access a specific
+  index in the array, like so: data.gpt[1]
+
 set timeout cli <delay>
   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 <name> [ data.<type> <operator> <value> [data.<type> ...]] |
   the entry cannot be matched using the key due empty key or incompatible
   characters on the cli.
 
+  If data.<type> 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
index 775cd1e18c2ef7bb3e49e9bf557bd7d9397bc3fa..114fa463455fd31947f8fd2248f0073cfd9bac46 100644 (file)
@@ -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.<type>\" 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) {