diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 592f32ac0..033f76143 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -492,7 +492,7 @@ enum conn_hash_params_t { * connection hash. */ struct conn_hash_params { - struct server *srv; + void *target; XXH64_hash_t sni_prehash; struct sockaddr_storage *src_addr; struct sockaddr_storage *dst_addr; diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index f96f78c79..622e77243 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -429,6 +429,15 @@ static inline void sockaddr_free(struct sockaddr_storage **sap) *sap = NULL; } +/* returns 0 if the connection is valid and is a frontend connection, otherwise + * returns 1 indicating it's a backend connection. And uninitialized connection + * also returns 1 to better handle the usage in the middle of initialization. + */ +static inline int conn_is_back(const struct connection *conn) +{ + return !objt_listener(conn->target); +} + /* Tries to allocate a new connection and initialized its main fields. The * connection is returned on success, NULL on failure. The connection must * be released using pool_free() or conn_free(). @@ -444,8 +453,9 @@ static inline struct connection *conn_new(void *target) conn_init(conn, target); - if (obj_type(target) == OBJ_TYPE_SERVER) { - srv_use_conn(__objt_server(target), conn); + if (conn_is_back(conn)) { + if (obj_type(target) == OBJ_TYPE_SERVER) + srv_use_conn(__objt_server(target), conn); hash_node = conn_alloc_hash_node(conn); if (unlikely(!hash_node)) { @@ -968,15 +978,6 @@ static inline const struct mux_ops *conn_get_best_mux(struct connection *conn, return item ? item->mux : NULL; } -/* returns 0 if the connection is valid and is a frontend connection, otherwise - * returns 1 indicating it's a backend connection. And uninitialized connection - * also returns 1 to better handle the usage in the middle of initialization. - */ -static inline int conn_is_back(const struct connection *conn) -{ - return !objt_listener(conn->target); -} - /* returns a pointer to the proxy associated with this connection. For a front * connection it returns a pointer to the frontend ; for a back connection, it * returns a pointer to the backend. diff --git a/src/backend.c b/src/backend.c index 6d0fb8632..4c1839d38 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1277,14 +1277,18 @@ int connect_server(struct stream *s) int64_t hash = 0; struct conn_hash_params hash_params; + /* in standard configuration, srv will be valid + * it can be NULL for dispatch mode or transparent backend */ + srv = objt_server(s->target); + /* first, set unique connection parameters and then calculate hash */ memset(&hash_params, 0, sizeof(hash_params)); - srv = objt_server(s->target); - hash_params.srv = srv; + /* 1. target */ + hash_params.target = s->target; #ifdef USE_OPENSSL - /* 1. sni */ + /* 2. sni */ if (srv && srv->ssl_ctx.sni) { sni_smp = sample_fetch_as_type(s->be, s->sess, s, SMP_OPT_DIR_REQ | SMP_OPT_FINAL, @@ -1302,7 +1306,7 @@ int connect_server(struct stream *s) } #endif /* USE_OPENSSL */ - /* 2. destination address */ + /* 3. destination address */ if (!(s->flags & SF_ADDR_SET)) { err = alloc_dst_address(&s->target_addr, srv, s); if (err != SRV_STATUS_OK) @@ -1314,14 +1318,14 @@ int connect_server(struct stream *s) if (srv && (!is_addr(&srv->addr) || srv->flags & SRV_F_MAPPORTS)) hash_params.dst_addr = s->target_addr; - /* 3. source address */ + /* 4. source address */ err = alloc_bind_address(&bind_addr, srv, s); if (err != SRV_STATUS_OK) return SF_ERR_INTERNAL; hash_params.src_addr = bind_addr; - /* 4. proxy protocol */ + /* 5. proxy protocol */ if (srv && srv->pp_opts) { proxy_line_ret = make_proxy_line(trash.area, trash.size, srv, cli_conn, s); if (proxy_line_ret) { @@ -1330,8 +1334,7 @@ int connect_server(struct stream *s) } } - if (srv) - hash = conn_calculate_hash(&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. @@ -1503,7 +1506,11 @@ int connect_server(struct stream *s) if (srv_conn) { srv_conn->owner = s->sess; - if (reuse_mode == PR_O_REUSE_NEVR) + + /* connection will be attached to the session if + * http-reuse mode is never or it is not targeted to a + * server */ + if (reuse_mode == PR_O_REUSE_NEVR || !srv) conn_set_private(srv_conn); /* assign bind_addr to srv_conn */ @@ -1729,8 +1736,7 @@ int connect_server(struct stream *s) } } - if (srv) - srv_conn->hash_node->hash = hash; + srv_conn->hash_node->hash = hash; return SF_ERR_NONE; /* connection is OK */ } diff --git a/src/connection.c b/src/connection.c index a9edf0184..535fb6b15 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1465,7 +1465,7 @@ XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params) buf = trash.area; - conn_hash_update(buf, &idx, ¶ms->srv, sizeof(params->srv), &hash_flags, 0); + conn_hash_update(buf, &idx, ¶ms->target, sizeof(params->target), &hash_flags, 0); if (params->sni_prehash) { conn_hash_update(buf, &idx,