]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stktable: implement "recv-only" table option
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 5 Dec 2024 09:28:50 +0000 (10:28 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 5 Dec 2024 11:15:24 +0000 (12:15 +0100)
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
include/haproxy/stick_table-t.h
src/peers.c
src/stick_table.c

index 1e39eea3fdc66ff3f4c063d9f6318d5a20eeb3ec..684a7a80e5ff90cb13e3cdaf4a4df3508cd8c68d 100644 (file)
@@ -4714,13 +4714,19 @@ user <username> [password|insecure-password <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 <shards>
 
 table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}
       size <size> [expire <expire>] [write-to <wtable>] [nopurge] [store <data_type>]*
+      [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 <pattern> [table <table>] [{if | unless} <condition>]
 stick-table type {ip | integer | string [len <length>] | binary [len <length>]}
             size <size> [expire <expire>] [nopurge] [peers <peersect>] [srvkey <srvkey>]
             [write-to <wtable>] [store <data_type>]* [brates-factor <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 <length>] | binary [len <length>]}
                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",
index dea1e982a62ae2e8cc12b636fbbab82ba3624a2b..fcc79ceb63089c4dc1a4159794917add9ae53007 100644 (file)
@@ -155,6 +155,10 @@ struct stksess {
        /* WARNING! do not put anything after <keys>, 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 {
index c17e6ecd53410de353f1ef53a93986d1838126ac..f6001b1a3e3fab651a36e7df26591fae38aead0b 100644 (file)
@@ -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;
 
index f49fb0af5963ff81f03e3b9c7dc5261c2581043e..a18d89309c6205f7c4276e21476a3e7eaf6593ae 100644 (file)
@@ -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;