]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: lb-chash: fix key calculation when using default hash-key id
authorWilly Tarreau <w@1wt.eu>
Thu, 16 Oct 2025 08:30:57 +0000 (10:30 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 16 Oct 2025 08:43:09 +0000 (10:43 +0200)
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
src/lb_chash.c

index 1453ed34bfaff1b1876ef2a9a7ee89196d0bfa3c..034be6845a50cec688cf312a5b083a47c135439f 100644 (file)
@@ -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
index f5b075ab374578740da57f550584e6e7de606014..59300d13a9c784e6b9f6c06d8f83cf55851fa892 100644 (file)
@@ -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;
        }