]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: stick-tables: compute the shard of string keys on the stored key
authorFrederic Lecaille <flecaille@haproxy.com>
Wed, 21 Oct 2026 12:43:57 +0000 (14:43 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 26 Oct 2026 15:30:43 +0000 (16:30 +0100)
stksess_setkey_shard() computes the peers shard from the raw sample
length, while the key is stored truncated to the table's key size and to
the first NUL, and the peers receiver computes the shard from the received
key. For a key longer than the table's "len" (e.g. a User-Agent in a
len-32 table) or containing a NUL, the creator and the receivers assign
different shards to the same entry, so entries may be sent to the wrong
peers.

Compute the shard from the stored key, as the receiver does. The key
argument is then unused, remove it.

Introduced in 2.7 by 36d156564 ("MINOR: peers: Support for peer shards"),
to be backported to 2.8 and above.

include/haproxy/stick_table.h
src/stick_table.c

index 72bdc9558383b19437c08a7382c498f4e93ccb62..497dbce2ed8b803f1234c64dcfd2bacb532e611f 100644 (file)
@@ -43,7 +43,7 @@ extern struct stktable_type stktable_types[];
 void stktable_store_name(struct stktable *t);
 struct stktable *stktable_find_by_name(const char *name);
 struct stksess *stksess_new(struct stktable *t, struct stktable_key *key);
-void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key);
+size_t stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key);
 void stksess_free(struct stktable *t, struct stksess *ts);
 int stksess_kill(struct stktable *t, struct stksess *ts);
 int stktable_get_key_shard(struct stktable *t, const void *key, size_t len);
index 9c447bb99f73a960c2feecbf04158dd5a01e4452..9cf5d8d169a0378283e4feff20532248a360da71 100644 (file)
@@ -184,10 +184,14 @@ int stksess_kill(struct stktable *t, struct stksess *ts)
 
 /*
  * Initialize or update the key in the sticky session <ts> present in table <t>
- * from the value present in <key>.
+ * from the value present in <key>. The length of the key as it is stored is
+ * returned, which is the entry's identity in the table and over the peers
+ * protocol.
  */
-void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key)
+size_t stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key)
 {
+       size_t keylen = t->key_size;
+
        if (t->type != SMP_T_STR)
                memcpy(ts->key.key, key->key, t->key_size);
        else {
@@ -204,7 +208,10 @@ void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key
 
                memcpy(ts->key.key, key->key, key_len);
                ts->key.key[key_len] = 0;
+               keylen = key_len;
        }
+
+       return keylen;
 }
 
 /*
@@ -242,20 +249,13 @@ int stktable_get_key_shard(struct stktable *t, const void *key, size_t len)
 }
 
 /*
- * Set the shard for <key> key of <ts> sticky session attached to <t> stick table.
+ * Set the shard from the already initialized stored key of <ts> and its length
+ * <keylen> as computed by stksess_setkey().
  * Use zero for stick-table without peers synchronisation.
  */
-static void stksess_setkey_shard(struct stktable *t, struct stksess *ts,
-                                 struct stktable_key *key)
+static void stksess_setkey_shard(struct stktable *t, struct stksess *ts, size_t keylen)
 {
-       size_t keylen;
-
-       if (t->type == SMP_T_STR)
-               keylen = key->key_len;
-       else
-               keylen = t->key_size;
-
-       ts->shard = stktable_get_key_shard(t, key->key, keylen);
+       ts->shard = stktable_get_key_shard(t, ts->key.key, keylen);
 }
 
 /*
@@ -474,8 +474,10 @@ struct stksess *stksess_new(struct stktable *t, struct stktable_key *key)
                ts = (void *)ts + round_ptr_size(t->data_size);
                __stksess_init(t, ts);
                if (key) {
-                       stksess_setkey(t, ts, key);
-                       stksess_setkey_shard(t, ts, key);
+                       size_t keylen;
+
+                       keylen = stksess_setkey(t, ts, key);
+                       stksess_setkey_shard(t, ts, keylen);
                }
        } else
                HA_ATOMIC_DEC(&t->current);