diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 7acbc2d77..e2ae0297d 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -475,8 +475,10 @@ enum conn_hash_params_t { CONN_HASH_PARAMS_TYPE_SNI = 0x1, CONN_HASH_PARAMS_TYPE_DST_ADDR = 0x2, CONN_HASH_PARAMS_TYPE_DST_PORT = 0x4, + CONN_HASH_PARAMS_TYPE_SRC_ADDR = 0x8, + CONN_HASH_PARAMS_TYPE_SRC_PORT = 0x10, }; -#define CONN_HASH_PARAMS_TYPE_COUNT 3 +#define CONN_HASH_PARAMS_TYPE_COUNT 5 #define CONN_HASH_PAYLOAD_LEN \ (((sizeof(((struct connection *)0)->hash)) * 8) - CONN_HASH_PARAMS_TYPE_COUNT) @@ -491,6 +493,7 @@ enum conn_hash_params_t { struct conn_hash_params { struct server *srv; XXH64_hash_t *sni_prehash; + struct sockaddr_storage *src_addr; struct sockaddr_storage *dst_addr; }; diff --git a/src/backend.c b/src/backend.c index 38a540fd6..1ab0af828 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1266,6 +1266,7 @@ int connect_server(struct stream *s) int init_mux = 0; int err; struct sample *sni_smp = NULL; + struct sockaddr_storage *bind_addr; int64_t hash = 0; struct conn_hash_params hash_params; XXH64_hash_t sni_hash; @@ -1302,6 +1303,13 @@ 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 */ + err = alloc_bind_address(&bind_addr, srv, s); + if (err != SRV_STATUS_OK) + return SF_ERR_INTERNAL; + + hash_params.src_addr = bind_addr; + if (srv) hash = conn_calculate_hash(&hash_params); @@ -1381,21 +1389,6 @@ int connect_server(struct stream *s) /* here reuse might have been set above, indicating srv_conn finally * is OK. */ - if (reuse) { - /* Disable connection reuse if a dynamic source is used. - * As long as we don't share connections between servers, - * we don't need to disable connection reuse on no-idempotent - * requests nor when PROXY protocol is used. - */ - if (srv && srv->conn_src.opts & CO_SRC_BIND) { - if ((srv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_DYN) - reuse = 0; - } - else if (s->be->conn_src.opts & CO_SRC_BIND) { - if ((s->be->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_DYN) - reuse = 0; - } - } if (ha_used_fds > global.tune.pool_high_count && srv && srv->idle_conns_tree) { struct connection *tokill_conn = NULL; @@ -1489,9 +1482,7 @@ skip_reuse: if (reuse_mode == PR_O_REUSE_NEVR) conn_set_private(srv_conn); - err = alloc_bind_address(&srv_conn->src, srv, s); - if (err != SRV_STATUS_OK) - return SF_ERR_INTERNAL; + srv_conn->src = bind_addr; if (!sockaddr_alloc(&srv_conn->dst, 0, 0)) { conn_free(srv_conn); @@ -1499,6 +1490,7 @@ skip_reuse: } } else { + sockaddr_free(&bind_addr); return SF_ERR_RESOURCE; } } diff --git a/src/connection.c b/src/connection.c index 5e7a4c5d6..159f4c629 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1479,6 +1479,13 @@ XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params) CONN_HASH_PARAMS_TYPE_DST_PORT); } + if (params->src_addr) { + conn_calculate_hash_sockaddr(params->src_addr, + buf, &idx, &hash_flags, + CONN_HASH_PARAMS_TYPE_SRC_ADDR, + CONN_HASH_PARAMS_TYPE_SRC_PORT); + } + hash = conn_hash_digest(buf, idx, hash_flags); return hash; diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 485603d57..a53415397 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -392,14 +392,11 @@ int tcp_connect_server(struct connection *conn, int flags) if (conn->src && is_inet_addr(conn->src)) { switch (src->opts & CO_SRC_TPROXY_MASK) { case CO_SRC_TPROXY_CLI: - conn_set_private(conn); - /* fall through */ case CO_SRC_TPROXY_ADDR: flags = 3; break; case CO_SRC_TPROXY_CIP: case CO_SRC_TPROXY_DYN: - conn_set_private(conn); flags = 1; break; }