]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stktable: use {show,set,clear} table with ptr
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 18 Dec 2023 14:37:25 +0000 (15:37 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 21 Dec 2023 13:22:27 +0000 (14:22 +0100)
This patchs adds support for optional ptr (0xffff form) instead of key
argument to match against existing sticktable entries, ie: if the key is
empty or cannot be matched on the cli due to incompatible characters.
Lookup is performed using a linear search so it will be slower than key
search which relies on eb tree lookup.

Example:

set table mytable key mykey data.gpc0 1

show table mytable
> 0x7fbd00032bd8: key=mykey use=0 exp=86373242 shard=0 gpc0=1

clear table mytable ptr 0x7fbd00032bd8

This patchs depends on:
 - "MINOR: stktable: add table_process_entry helper function"

It should solve GH #2118

src/stick_table.c

index 0994bd31c791d8a8fa95b2d047374a36e3528cb3..6b461c00ff47f7d450d118cf87c05899e2737110 100644 (file)
@@ -385,6 +385,40 @@ struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key
        return ts;
 }
 
+/*
+ * Looks in table <t> for a sticky session matching ptr <ptr>.
+ * Returns pointer on requested sticky session or NULL if none was found.
+ * The refcount of the found entry is increased and this function
+ * is protected using the table lock
+ */
+struct stksess *stktable_lookup_ptr(struct stktable *t, void *ptr)
+{
+       struct stksess *ts = NULL;
+       struct ebmb_node *eb;
+
+       HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &t->lock);
+       /* linear search is performed, this could be optimized by adding
+        * an eb node dedicated to ptr lookups into stksess struct to
+        * leverage eb_lookup function instead.
+        */
+       eb = ebmb_first(&t->keys);
+       while (eb) {
+               struct stksess *cur;
+
+               cur = ebmb_entry(eb, struct stksess, key);
+               if (cur == ptr) {
+                       ts = cur;
+                       break;
+               }
+               eb = ebmb_next(eb);
+       }
+       if (ts)
+               HA_ATOMIC_INC(&ts->ref_cnt);
+       HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &t->lock);
+
+       return ts;
+}
+
 /*
  * Looks in table <t> for a sticky session with same key as <ts>.
  * Returns pointer on requested sticky session or NULL if none was found.
@@ -5080,6 +5114,32 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
        return table_process_entry(appctx, ts, args);
 }
 
+/* Processes a single table entry matching a specific ptr passed in argument.
+ * returns 0 if wants to be called again, 1 if has ended processing.
+ */
+static int table_process_entry_per_ptr(struct appctx *appctx, char **args)
+{
+       struct show_table_ctx *ctx = appctx->svcctx;
+       struct stktable *t = ctx->target;
+       long long int ptr;
+       char *error;
+       struct stksess *ts;
+
+       if (!*args[4] || args[4][0] != '0' || args[4][1] != 'x')
+               return cli_err(appctx, "Pointer expected (0xffff notation)\n");
+
+       /* Convert argument to integer value */
+       ptr = strtoll(args[4], &error, 16);
+       if (*error != '\0')
+               return cli_err(appctx, "Malformed ptr.\n");
+
+       ts = stktable_lookup_ptr(t, (void *)ptr);
+       if (!ts)
+               return cli_err(appctx, "No entry can be found matching ptr.\n");
+
+       return table_process_entry(appctx, ts, args);
+}
+
 /* Prepares the appctx fields with the data-based filters from the command line.
  * Returns 0 if the dump can proceed, 1 if has ended processing.
  */
@@ -5145,6 +5205,8 @@ static int cli_parse_table_req(char **args, char *payload, struct appctx *appctx
 
        if (strcmp(args[3], "key") == 0)
                return table_process_entry_per_key(appctx, args);
+       if (strcmp(args[3], "ptr") == 0)
+               return table_process_entry_per_ptr(appctx, args);
        else if (strncmp(args[3], "data.", 5) == 0)
                return table_prepare_data_request(appctx, args);
        else if (*args[3])
@@ -5155,11 +5217,11 @@ static int cli_parse_table_req(char **args, char *payload, struct appctx *appctx
 err_args:
        switch (ctx->action) {
        case STK_CLI_ACT_SHOW:
-               return cli_err(appctx, "Optional argument only supports \"data.<store_data_type>\" <operator> <value> and key <key>\n");
+               return cli_err(appctx, "Optional argument only supports \"data.<store_data_type>\" <operator> <value> or key <key> or ptr <ptr>\n");
        case STK_CLI_ACT_CLR:
-               return cli_err(appctx, "Required arguments: <table> \"data.<store_data_type>\" <operator> <value> or <table> key <key>\n");
+               return cli_err(appctx, "Required arguments: <table> \"data.<store_data_type>\" <operator> <value> or <table> key <key> or <table> ptr <ptr>\n");
        case STK_CLI_ACT_SET:
-               return cli_err(appctx, "Required arguments: <table> key <key> [data.<store_data_type> <value>]*\n");
+               return cli_err(appctx, "Required arguments: <table> key <key> [data.<store_data_type> <value>]* or <table> ptr <ptr> [data.<store_data_type> <value>]*\n");
        default:
                return cli_err(appctx, "Unknown action\n");
        }