mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 22:31:28 +02:00
[MINOR] More flexible clearing of stick table
* Allow clearing of all entries of a table * Allow clearing of all entries of a table that match a data filter
This commit is contained in:
parent
d5b9fd9591
commit
c88b887d8d
@ -9309,15 +9309,34 @@ clear counters all
|
|||||||
server. This has the same effect as restarting. This command is restricted
|
server. This has the same effect as restarting. This command is restricted
|
||||||
and can only be issued on sockets configured for level "admin".
|
and can only be issued on sockets configured for level "admin".
|
||||||
|
|
||||||
clear table <table> key <key>
|
clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ]
|
||||||
Remove entry <key> from the stick-table <table>. The key must be of the same
|
Remove entries from the stick-table <table>.
|
||||||
type as the table, which currently is limited to IPv4. This is typically used
|
|
||||||
un unblock some users complaining they have been abusively denied access to a
|
This is typically used to unblock some users complaining they have been
|
||||||
service, but this can also be used to clear some stickiness entries matching
|
abusively denied access to a service, but this can also be used to clear some
|
||||||
a server that is going to be replaced (see "show table" below for details).
|
stickiness entries matching a server that is going to be replaced (see "show
|
||||||
Note that sometimes, removal of a key will be refused because it is currently
|
table" below for details). Note that sometimes, removal of an entry will be
|
||||||
tracked by a session. Retrying a few seconds later after the session ends is
|
refused because it is currently tracked by a session. Retrying a few seconds
|
||||||
usuall enough.
|
later after the session ends is usual enough.
|
||||||
|
|
||||||
|
In the case where no options arguments are given all entries will be removed.
|
||||||
|
|
||||||
|
When the "data." form is used entries matching a filter applied using the
|
||||||
|
stored data (see "stick-table" in section 4.2) are removed. A stored data
|
||||||
|
type must be specified in <type>, and this data type must be stored in the
|
||||||
|
table otherwise an error is reported. The data is compared according to
|
||||||
|
<operator> with the 64-bit integer <value>. Operators are the same as with
|
||||||
|
the ACLs :
|
||||||
|
|
||||||
|
- eq : match entries whose data is equal to this value
|
||||||
|
- ne : match entries whose data is not equal to this value
|
||||||
|
- le : match entries whose data is less than or equal to this value
|
||||||
|
- ge : match entries whose data is greater than or equal to this value
|
||||||
|
- lt : match entries whose data is less than this value
|
||||||
|
- gt : match entries whose data is greater than this value
|
||||||
|
|
||||||
|
When the key form is used the entry <key> is removed. The key must be of the
|
||||||
|
same type as the table, which currently is limited to IPv4.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
||||||
@ -9333,6 +9352,9 @@ clear table <table> key <key>
|
|||||||
>>> # table: http_proxy, type: ip, size:204800, used:1
|
>>> # table: http_proxy, type: ip, size:204800, used:1
|
||||||
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
|
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
|
||||||
bytes_out_rate(60000)=191
|
bytes_out_rate(60000)=191
|
||||||
|
$ echo "clear table http_proxy data.gpc0 eq 1" | socat stdio /tmp/sock1
|
||||||
|
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
||||||
|
>>> # table: http_proxy, type: ip, size:204800, used:1
|
||||||
|
|
||||||
disable server <backend>/<server>
|
disable server <backend>/<server>
|
||||||
Mark the server DOWN for maintenance. In this mode, no more checks will be
|
Mark the server DOWN for maintenance. In this mode, no more checks will be
|
||||||
@ -9538,10 +9560,9 @@ show table <name> [ data.<type> <operator> <value> ] | [ key <key> ]
|
|||||||
- lt : match entries whose data is less than this value
|
- lt : match entries whose data is less than this value
|
||||||
- gt : match entries whose data is greater than this value
|
- gt : match entries whose data is greater than this value
|
||||||
|
|
||||||
When the key form is used the filter applies to the key of
|
|
||||||
the stick table entry (see "stick-table" in section 4.2).
|
When the key form is used the entry <key> is shown. The key must be of the
|
||||||
The stick table must be of type ip otherwise an error will
|
same type as the table, which currently is limited to IPv4.
|
||||||
be reported.
|
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#define STAT_CLI_O_SESS 6 /* dump sessions */
|
#define STAT_CLI_O_SESS 6 /* dump sessions */
|
||||||
#define STAT_CLI_O_ERR 7 /* dump errors */
|
#define STAT_CLI_O_ERR 7 /* dump errors */
|
||||||
#define STAT_CLI_O_TAB 8 /* dump tables */
|
#define STAT_CLI_O_TAB 8 /* dump tables */
|
||||||
|
#define STAT_CLI_O_CLR 9 /* clear tables */
|
||||||
|
|
||||||
/* status codes (strictly 4 chars) used in the URL to display a message */
|
/* status codes (strictly 4 chars) used in the URL to display a message */
|
||||||
#define STAT_STATUS_UNKN "UNKN" /* an unknown error occured, shouldn't happen */
|
#define STAT_STATUS_UNKN "UNKN" /* an unknown error occured, shouldn't happen */
|
||||||
|
@ -59,7 +59,7 @@ static int stats_dump_raw_to_buffer(struct stream_interface *si);
|
|||||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si);
|
static int stats_dump_full_sess_to_buffer(struct stream_interface *si);
|
||||||
static int stats_dump_sess_to_buffer(struct stream_interface *si);
|
static int stats_dump_sess_to_buffer(struct stream_interface *si);
|
||||||
static int stats_dump_errors_to_buffer(struct stream_interface *si);
|
static int stats_dump_errors_to_buffer(struct stream_interface *si);
|
||||||
static int stats_dump_table_to_buffer(struct stream_interface *si);
|
static int stats_table_request(struct stream_interface *si, bool show);
|
||||||
static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri);
|
static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri);
|
||||||
static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri);
|
static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri);
|
||||||
|
|
||||||
@ -599,7 +599,10 @@ static void stats_sock_table_request(struct stream_interface *si, char **args, b
|
|||||||
si->applet.state = STAT_ST_INIT;
|
si->applet.state = STAT_ST_INIT;
|
||||||
si->applet.ctx.table.proxy = NULL;
|
si->applet.ctx.table.proxy = NULL;
|
||||||
si->applet.ctx.table.entry = NULL;
|
si->applet.ctx.table.entry = NULL;
|
||||||
si->applet.st0 = STAT_CLI_O_TAB; // stats_dump_table_to_buffer
|
if (show)
|
||||||
|
si->applet.st0 = STAT_CLI_O_TAB;
|
||||||
|
else
|
||||||
|
si->applet.st0 = STAT_CLI_O_CLR;
|
||||||
|
|
||||||
if (*args[2]) {
|
if (*args[2]) {
|
||||||
si->applet.ctx.table.target = find_stktable(args[2]);
|
si->applet.ctx.table.target = find_stktable(args[2]);
|
||||||
@ -617,9 +620,9 @@ static void stats_sock_table_request(struct stream_interface *si, char **args, b
|
|||||||
|
|
||||||
if (strcmp(args[3], "key") == 0)
|
if (strcmp(args[3], "key") == 0)
|
||||||
stats_sock_table_key_request(si, args, show);
|
stats_sock_table_key_request(si, args, show);
|
||||||
else if (show && strncmp(args[3], "data.", 5) == 0)
|
else if (strncmp(args[3], "data.", 5) == 0)
|
||||||
stats_sock_table_data_request(si, args);
|
stats_sock_table_data_request(si, args);
|
||||||
else if (!show || *args[3])
|
else if (*args[3])
|
||||||
goto err_args;
|
goto err_args;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -628,7 +631,7 @@ err_args:
|
|||||||
if (show)
|
if (show)
|
||||||
si->applet.ctx.cli.msg = "Optional argument only supports \"data.<store_data_type>\" <operator> <value> and key <key>\n";
|
si->applet.ctx.cli.msg = "Optional argument only supports \"data.<store_data_type>\" <operator> <value> and key <key>\n";
|
||||||
else
|
else
|
||||||
si->applet.ctx.cli.msg = "Required arguments: <table> key <key>\n";
|
si->applet.ctx.cli.msg = "Required arguments: <table> \"data.<store_data_type>\" <operator> <value> or <table> key <key>\n";
|
||||||
si->applet.st0 = STAT_CLI_PRINT;
|
si->applet.st0 = STAT_CLI_PRINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1181,7 +1184,11 @@ static void cli_io_handler(struct stream_interface *si)
|
|||||||
si->applet.st0 = STAT_CLI_PROMPT;
|
si->applet.st0 = STAT_CLI_PROMPT;
|
||||||
break;
|
break;
|
||||||
case STAT_CLI_O_TAB:
|
case STAT_CLI_O_TAB:
|
||||||
if (stats_dump_table_to_buffer(si))
|
if (stats_table_request(si, true))
|
||||||
|
si->applet.st0 = STAT_CLI_PROMPT;
|
||||||
|
break;
|
||||||
|
case STAT_CLI_O_CLR:
|
||||||
|
if (stats_table_request(si, false))
|
||||||
si->applet.st0 = STAT_CLI_PROMPT;
|
si->applet.st0 = STAT_CLI_PROMPT;
|
||||||
break;
|
break;
|
||||||
default: /* abnormal state */
|
default: /* abnormal state */
|
||||||
@ -3306,12 +3313,13 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
|
|||||||
* properly set. It returns 0 if the output buffer is full and it needs
|
* properly set. It returns 0 if the output buffer is full and it needs
|
||||||
* to be called again, otherwise non-zero.
|
* to be called again, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_table_to_buffer(struct stream_interface *si)
|
static int stats_table_request(struct stream_interface *si, bool show)
|
||||||
{
|
{
|
||||||
struct session *s = si->applet.private;
|
struct session *s = si->applet.private;
|
||||||
struct chunk msg;
|
struct chunk msg;
|
||||||
struct ebmb_node *eb;
|
struct ebmb_node *eb;
|
||||||
int dt;
|
int dt;
|
||||||
|
bool skip_entry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have 3 possible states in si->applet.state :
|
* We have 3 possible states in si->applet.state :
|
||||||
@ -3356,7 +3364,7 @@ static int stats_dump_table_to_buffer(struct stream_interface *si)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (si->applet.ctx.table.proxy->table.size) {
|
if (si->applet.ctx.table.proxy->table.size) {
|
||||||
if (!stats_dump_table_head_to_buffer(&msg, si, si->applet.ctx.table.proxy,
|
if (show && !stats_dump_table_head_to_buffer(&msg, si, si->applet.ctx.table.proxy,
|
||||||
si->applet.ctx.table.target))
|
si->applet.ctx.table.target))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3376,6 +3384,8 @@ static int stats_dump_table_to_buffer(struct stream_interface *si)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STAT_ST_LIST:
|
case STAT_ST_LIST:
|
||||||
|
skip_entry = false;
|
||||||
|
|
||||||
if (si->applet.ctx.table.data_type >= 0) {
|
if (si->applet.ctx.table.data_type >= 0) {
|
||||||
/* we're filtering on some data contents */
|
/* we're filtering on some data contents */
|
||||||
void *ptr;
|
void *ptr;
|
||||||
@ -3416,14 +3426,14 @@ static int stats_dump_table_to_buffer(struct stream_interface *si)
|
|||||||
(si->applet.ctx.table.data_op == STD_OP_EQ ||
|
(si->applet.ctx.table.data_op == STD_OP_EQ ||
|
||||||
si->applet.ctx.table.data_op == STD_OP_LT ||
|
si->applet.ctx.table.data_op == STD_OP_LT ||
|
||||||
si->applet.ctx.table.data_op == STD_OP_LE)))
|
si->applet.ctx.table.data_op == STD_OP_LE)))
|
||||||
goto skip_entry;
|
skip_entry = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stats_dump_table_entry_to_buffer(&msg, si, si->applet.ctx.table.proxy,
|
if (show && !skip_entry &&
|
||||||
|
!stats_dump_table_entry_to_buffer(&msg, si, si->applet.ctx.table.proxy,
|
||||||
si->applet.ctx.table.entry))
|
si->applet.ctx.table.entry))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
skip_entry:
|
|
||||||
si->applet.ctx.table.entry->ref_cnt--;
|
si->applet.ctx.table.entry->ref_cnt--;
|
||||||
|
|
||||||
eb = ebmb_next(&si->applet.ctx.table.entry->key);
|
eb = ebmb_next(&si->applet.ctx.table.entry->key);
|
||||||
@ -3435,7 +3445,12 @@ static int stats_dump_table_to_buffer(struct stream_interface *si)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (show)
|
||||||
stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry);
|
stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry);
|
||||||
|
else if (!skip_entry && !si->applet.ctx.table.entry->ref_cnt)
|
||||||
|
stksess_kill(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry);
|
||||||
|
|
||||||
si->applet.ctx.table.proxy = si->applet.ctx.table.proxy->next;
|
si->applet.ctx.table.proxy = si->applet.ctx.table.proxy->next;
|
||||||
si->applet.state = STAT_ST_INFO;
|
si->applet.state = STAT_ST_INFO;
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user