]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: prepare hash calcul for server conns
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 18 Jan 2021 13:57:50 +0000 (14:57 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 12 Feb 2021 11:33:05 +0000 (12:33 +0100)
This is a preliminary work for the calcul of the backend connection
hash. A structure conn_hash_params is the input for the operation,
containing the various specific parameters of a connection.

The high bits of the hash will reflect the parameters present as input.
A set of macros is written to manipulate the connection hash and extract
the parameters/payload.

include/haproxy/connection-t.h
include/haproxy/connection.h
src/backend.c
src/connection.c

index 32d5a60f9453830a63a27f68dcac612137910d23..dd52bd3a7eeac2092c9462ae7944271dfe20bbdd 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <import/ebmbtree.h>
 #include <import/ist.h>
+#include <import/xxhash.h>
 
 #include <haproxy/api-t.h>
 #include <haproxy/listener-t.h>
@@ -466,6 +467,28 @@ struct conn_stream {
        void *ctx;                           /* mux-specific context */
 };
 
+/* Hash header flag reflecting the input parameters present
+ * CAUTION! Always update CONN_HASH_PARAMS_TYPE_COUNT when adding a new entry.
+ */
+enum conn_hash_params_t {
+       /* to remove as soon as one useful parameter is present */
+       CONN_HASH_DUMMY_PARAM,
+};
+#define CONN_HASH_PARAMS_TYPE_COUNT 1
+
+#define CONN_HASH_PAYLOAD_LEN \
+       (((sizeof(((struct connection *)0)->hash)) * 8) - CONN_HASH_PARAMS_TYPE_COUNT)
+
+#define CONN_HASH_GET_PAYLOAD(hash) \
+       (((hash) << CONN_HASH_PARAMS_TYPE_COUNT) >> CONN_HASH_PARAMS_TYPE_COUNT)
+
+/* To avoid overflow, dynamically sized parameters must be pre-hashed. Their
+ * hashed will then be reused as input for the generation of the final
+ * connection hash.
+ */
+struct conn_hash_params {
+};
+
 /* This structure describes a connection with its methods and data.
  * A connection may be performed to proxy or server via a local or remote
  * socket, and can also be made to an internal applet. It can support
index 03e7e2efd054ed26b470b123fad7aae6c792f59e..a7a83b1c0bdbf34ad04d60358376733a697d4f72 100644 (file)
@@ -1115,6 +1115,39 @@ static inline int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct
        return 0;
 }
 
+/* Generate the hash of a connection with params as input
+ * Each non-null field of params is taken into account for the hash calcul.
+ */
+XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params);
+
+static inline XXH64_hash_t conn_hash_prehash(char *buf, size_t size)
+{
+       return XXH64(buf, size, 0);
+}
+
+/* Append <data> into <buf> at <idx> offset in preparation for connection hash
+ * calcul. <idx> is incremented beyond data <size>. In the same time, <flags>
+ * are updated with <type> for the hash header.
+ */
+static inline void conn_hash_update(char *buf, size_t *idx,
+                                    const void *data, size_t size,
+                                    enum conn_hash_params_t *flags,
+                                    enum conn_hash_params_t type)
+{
+       memcpy(&buf[*idx], data, size);
+       *idx += size;
+       *flags |= type;
+}
+
+static inline XXH64_hash_t conn_hash_digest(char *buf, size_t bufsize,
+                                            enum conn_hash_params_t flags)
+{
+       const uint64_t flags_u64 = (uint64_t)flags;
+       const XXH64_hash_t hash = XXH64(buf, bufsize, 0);
+
+       return (flags_u64 << CONN_HASH_PAYLOAD_LEN) | CONN_HASH_GET_PAYLOAD(hash);
+}
+
 #endif /* _HAPROXY_CONNECTION_H */
 
 /*
index c7fb3496d0a5bfb9a9b0a0760cebef6431674608..4b2c9f8272fb82cc9573ddf2dbab599acc049cec 100644 (file)
@@ -1247,6 +1247,11 @@ int connect_server(struct stream *s)
        int init_mux = 0;
        int err;
        int64_t hash = 0;
+       struct conn_hash_params hash_params;
+
+       /* first, set unique connection parameters and then calculate hash */
+       memset(&hash_params, 0, sizeof(hash_params));
+       hash = conn_calculate_hash(&hash_params);
 
        /* This will catch some corner cases such as lying connections resulting from
         * retries or connect timeouts but will rarely trigger.
@@ -1672,6 +1677,8 @@ skip_reuse:
                }
        }
 
+       srv_conn->hash = hash;
+
        return SF_ERR_NONE;  /* connection is OK */
 }
 
index fc605f986344cedeee4d435cc84fc6e5aaed2573..f5dbffbc1928ec0b478ac3d849d1c68416efd739 100644 (file)
@@ -1411,3 +1411,16 @@ static struct cfg_kw_list cfg_kws = {ILH, {
 }};
 
 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+
+XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params)
+{
+       char *buf;
+       size_t idx = 0;
+       XXH64_hash_t hash = 0;
+       enum conn_hash_params_t hash_flags = 0;
+
+       buf = trash.area;
+
+       hash = conn_hash_digest(buf, idx, hash_flags);
+       return hash;
+}