From 1f73d3524da419ecd420d88da03a58e03cb4f79d Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Thu, 5 Dec 2024 10:28:50 +0100 Subject: [PATCH] MINOR: stktable: implement "recv-only" table option When "recv-only" keyword is added on a stick table declaration (in peers or proxy section), haproxy considers that the table is only used for data retrieval from a remote location and not used to perform local updates. As such, it enables the retrieval of local-only values such as conn_cur that are ignored by default. This can be useful in some contexts where we want to know about local-values such are conn_cur from a remote peer. To do this, add stktable struct flags which default to NONE and enable the RECV_ONLY flag on the table then "recv-only" keyword is found in the table declaration. Then, when in peer_treat_updatemsg(), when handling table updates, don't ignore data updates for local-only values if the flag is set. --- doc/configuration.txt | 32 ++++++++++++++++++++++++++------ include/haproxy/stick_table-t.h | 6 ++++++ src/peers.c | 12 +++++++----- src/stick_table.c | 4 ++++ 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 1e39eea3f..684a7a80e 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4714,13 +4714,19 @@ user [password|insecure-password ] It is possible to propagate entries of any data-types in stick-tables between several HAProxy instances over TCP connections in a multi-master fashion. Each instance pushes its local updates and insertions to remote peers. The pushed -values overwrite remote ones without aggregation. As an exception, the data -type "conn_cur" is never learned from peers, as it is supposed to reflect local -values. Earlier versions used to synchronize it and to cause negative values in -active-active setups, and always-growing values upon reloads or active-passive +values overwrite remote ones without aggregation. + +One exception is the data type "conn_cur" which is never learned from peers by +default as it is supposed to reflect local values. Earlier versions used to +synchronize it by default which was known to cause negative values in active- +active setups, and always-growing values upon reloads or active-passive switches because the local value would reflect more connections than locally -present. This information, however, is pushed so that monitoring systems can -watch it. +present. However there are some setups where it could be relevant to learn +this value from peers, for instance when the table is a passive remote table +solely used to learn/monitor data from it without relying on it for write- +oriented operations or updates. To achieve this, the "recv-only" keyword can +be added on the table declaration. In any case, the "conn_cur" info is always +pushed so that monitoring systems can watch it. Interrupted exchanges are automatically detected and recovered from the last known point. In addition, during a soft restart, the old process connects to @@ -4845,6 +4851,7 @@ shards table type {ip | integer | string [len ] | binary [len ]} size [expire ] [write-to ] [nopurge] [store ]* + [recv-only] Configure a stickiness table for the current section. This line is parsed exactly the same way as the "stick-table" keyword in others section, except @@ -12879,6 +12886,7 @@ stick store-request [table ] [{if | unless} ] stick-table type {ip | integer | string [len ] | binary [len ]} size [expire ] [nopurge] [peers ] [srvkey ] [write-to ] [store ]* [brates-factor ] + [recv-only] Configure the stickiness table for the current section May be used in the following contexts: tcp, http @@ -13007,6 +13015,18 @@ stick-table type {ip | integer | string [len ] | binary [len ]} defined period. The factor must be greater than 0 and lower or equal to 1024. + [recv-only] indicates that we don't intent to use the table to perform + updates on it, but thay we only plan on using the table to + retrieve data from a remote peer which we are interested in. + Indeed, the use of this keyword enables the retrieval of + local-only values such as conn_cur that are not learned by + default as they would conflict with local updates performed + on the table by the local peer. Use of this option is only + relevant for tables that are not involved in tracking rules or + methods that perform update operations on the table, or put + simpler: remote tables that are only used to retrieve + information. + The data types that can be stored with an entry are the following : - server_id : this is an integer which holds the numeric ID of the server a request was assigned to. It is used by the "stick match", "stick store", diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h index dea1e982a..fcc79ceb6 100644 --- a/include/haproxy/stick_table-t.h +++ b/include/haproxy/stick_table-t.h @@ -155,6 +155,10 @@ struct stksess { /* WARNING! do not put anything after , it's used by the key */ }; +#define STK_FL_NONE 0x00 +#define STK_FL_RECV_ONLY 0x01 /* table is assumed to be remotely updated only + * (never updated locally) + */ /* stick table */ struct stktable { @@ -197,6 +201,8 @@ struct stktable { void *ptr; /* generic ptr to check if set or not */ } write_to; /* updates received on the source table will also update write_to */ + uint16_t flags; + THREAD_ALIGN(64); struct { diff --git a/src/peers.c b/src/peers.c index c17e6ecd5..f6001b1a3 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1823,12 +1823,14 @@ static int peer_treat_updatemsg(struct appctx *appctx, struct peer *p, int updt, if (!((1ULL << data_type) & st->remote_data)) continue; - /* We shouldn't learn local-only values. Also, when handling the - * write_to table we must ignore types that can be processed - * so we don't interfere with any potential arithmetic logic - * performed on them (ie: cumulative counters). + /* We shouldn't learn local-only values unless the table is + * considered as "recv-only". Also, when handling the write_to + * table we must ignore types that can be processed so we don't + * interfere with any potential arithmetic logic performed on + * them (ie: cumulative counters). */ - if (stktable_data_types[data_type].is_local || + if ((stktable_data_types[data_type].is_local && + !(table->flags & STK_FL_RECV_ONLY)) || (table != st->table && !stktable_data_types[data_type].as_is)) ignore = 1; diff --git a/src/stick_table.c b/src/stick_table.c index f49fb0af5..a18d89309 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -1373,6 +1373,10 @@ int parse_stick_table(const char *file, int linenum, char **args, } idx++; } + else if (strcmp(args[idx], "recv-only") == 0) { + t->flags |= STK_FL_RECV_ONLY; + idx++; + } else if (strcmp(args[idx], "write-to") == 0) { char *write_to;