From 03e9a5a1e74b88c7ab7a9522c0345f8d54ec373b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 16 Oct 2025 10:30:57 +0200 Subject: [PATCH] BUG/MAJOR: lb-chash: fix key calculation when using default hash-key id A subtle regression was introduced in 3.0 by commit faa8c3e02 ("MEDIUM: lb-chash: Deterministic node hashes based on server address"). When keys are calculated from the server's ID (which is the default), due to the reorganisation of the code, the key ended up being hashed twice instead of being multiplied by the scaling range. While most users will never notice it, it is blocking some large cache users from upgrading from 2.8 to 3.0 or 3.2 because the keys are redistributed. After a check with users on the mailing list [1] it was estimated that keep the current situation is the worst choice because those who have not yet upgraded will face the problem while by fixing it, those who already have and for whom it happened smoothly will handle it just right again. As such this fix must be backported to 3.0 without waiting (in order to preserve those who upgrade from two redistributions). Please note that only configurations featuring "hash-type consistent" and not having "hash-key" present with a value other than "id" are affected, others are not (e.g. "hash-key addr" is unaffected). [1] https://www.mail-archive.com/haproxy@formilux.org/msg46115.html --- reg-tests/balance/balance-hash-maxconn.vtc | 6 +++--- src/lb_chash.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reg-tests/balance/balance-hash-maxconn.vtc b/reg-tests/balance/balance-hash-maxconn.vtc index 1453ed34b..034be6845 100644 --- a/reg-tests/balance/balance-hash-maxconn.vtc +++ b/reg-tests/balance/balance-hash-maxconn.vtc @@ -9,13 +9,13 @@ barrier b2 cond 2 server s0 { rxreq + barrier b2 sync barrier b1 sync txresp -hdr "Server: s0" } -start server s1 { rxreq - barrier b2 sync barrier b1 sync txresp -hdr "Server: s1" } -start @@ -47,7 +47,7 @@ client c1 -connect ${h1_px_sock} { txreq -url "/test-url" rxresp expect resp.status == 200 - expect resp.http.Server ~ s1 + expect resp.http.Server ~ s0 } -start barrier b2 sync @@ -57,7 +57,7 @@ client c2 -connect ${h1_px_sock} { txreq -url "/test-url" rxresp expect resp.status == 200 - expect resp.http.Server ~ s0 + expect resp.http.Server ~ s1 } -start client c1 -wait diff --git a/src/lb_chash.c b/src/lb_chash.c index f5b075ab3..59300d13a 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -123,7 +123,7 @@ static inline u32 chash_compute_server_key(struct server *s) case SRV_HASH_KEY_ID: default: - key = full_hash(s->puid); + key = s->puid * SRV_EWGHT_RANGE; break; }