summaryrefslogtreecommitdiffstats
path: root/src/backend.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:11:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:11:10 +0000
commitcff6d757e3ba609c08ef2aaa00f07e53551e5bf6 (patch)
tree08c4fc3255483ad397d712edb4214ded49149fd9 /src/backend.c
parentAdding upstream version 2.9.7. (diff)
downloadhaproxy-cff6d757e3ba609c08ef2aaa00f07e53551e5bf6.tar.xz
haproxy-cff6d757e3ba609c08ef2aaa00f07e53551e5bf6.zip
Adding upstream version 3.0.0.upstream/3.0.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend.c')
-rw-r--r--src/backend.c140
1 files changed, 90 insertions, 50 deletions
diff --git a/src/backend.c b/src/backend.c
index 39d2c75..d74ae40 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -39,6 +39,7 @@
#include <haproxy/lb_fwlc.h>
#include <haproxy/lb_fwrr.h>
#include <haproxy/lb_map.h>
+#include <haproxy/lb_ss.h>
#include <haproxy/log.h>
#include <haproxy/namespace.h>
#include <haproxy/obj_type.h>
@@ -61,14 +62,6 @@
#define TRACE_SOURCE &trace_strm
-int be_lastsession(const struct proxy *be)
-{
- if (be->be_counters.last_sess)
- return ns_to_sec(now_ns) - be->be_counters.last_sess;
-
- return -1;
-}
-
/* helper function to invoke the correct hash method */
unsigned int gen_hash(const struct proxy* px, const char* key, unsigned long len)
{
@@ -176,7 +169,7 @@ void update_backend_weight(struct proxy *px)
* If any server is found, it will be returned. If no valid server is found,
* NULL is returned.
*/
-static struct server *get_server_sh(struct proxy *px, const char *addr, int len, const struct server *avoid)
+struct server *get_server_sh(struct proxy *px, const char *addr, int len, const struct server *avoid)
{
unsigned int h, l;
@@ -220,7 +213,7 @@ static struct server *get_server_sh(struct proxy *px, const char *addr, int len,
* algorithm out of a tens because it gave him the best results.
*
*/
-static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid)
+struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid)
{
unsigned int hash = 0;
int c;
@@ -268,7 +261,7 @@ static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, co
* is returned. If any server is found, it will be returned. If no valid server
* is found, NULL is returned.
*/
-static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len, const struct server *avoid)
+struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len, const struct server *avoid)
{
unsigned int hash = 0;
const char *start, *end;
@@ -327,7 +320,7 @@ static struct server *get_server_ph(struct proxy *px, const char *uri, int uri_l
/*
* this does the same as the previous server_ph, but check the body contents
*/
-static struct server *get_server_ph_post(struct stream *s, const struct server *avoid)
+struct server *get_server_ph_post(struct stream *s, const struct server *avoid)
{
unsigned int hash = 0;
struct channel *req = &s->req;
@@ -412,7 +405,7 @@ static struct server *get_server_ph_post(struct stream *s, const struct server *
* is found, NULL is returned. When lbprm.arg_opt1 is set, the hash will only
* apply to the middle part of a domain name ("use_domain_only" option).
*/
-static struct server *get_server_hh(struct stream *s, const struct server *avoid)
+struct server *get_server_hh(struct stream *s, const struct server *avoid)
{
unsigned int hash = 0;
struct proxy *px = s->be;
@@ -485,7 +478,7 @@ static struct server *get_server_hh(struct stream *s, const struct server *avoid
}
/* RDP Cookie HASH. */
-static struct server *get_server_rch(struct stream *s, const struct server *avoid)
+struct server *get_server_rch(struct stream *s, const struct server *avoid)
{
unsigned int hash = 0;
struct proxy *px = s->be;
@@ -530,7 +523,7 @@ static struct server *get_server_rch(struct stream *s, const struct server *avoi
/* sample expression HASH. Returns NULL if the sample is not found or if there
* are no server, relying on the caller to fall back to round robin instead.
*/
-static struct server *get_server_expr(struct stream *s, const struct server *avoid)
+struct server *get_server_expr(struct stream *s, const struct server *avoid)
{
struct proxy *px = s->be;
struct sample *smp;
@@ -560,7 +553,7 @@ static struct server *get_server_expr(struct stream *s, const struct server *avo
}
/* random value */
-static struct server *get_server_rnd(struct stream *s, const struct server *avoid)
+struct server *get_server_rnd(struct stream *s, const struct server *avoid)
{
unsigned int hash = 0;
struct proxy *px = s->be;
@@ -653,9 +646,9 @@ int assign_server(struct stream *s)
if ((s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_HI &&
((s->sess->flags & SESS_FL_PREFER_LAST) ||
(s->be->options & PR_O_PREF_LAST))) {
- struct sess_srv_list *srv_list;
- list_for_each_entry(srv_list, &s->sess->srv_list, srv_list) {
- struct server *tmpsrv = objt_server(srv_list->target);
+ struct sess_priv_conns *pconns;
+ list_for_each_entry(pconns, &s->sess->priv_conns, sess_el) {
+ struct server *tmpsrv = objt_server(pconns->target);
if (tmpsrv && tmpsrv->proxy == s->be &&
((s->sess->flags & SESS_FL_PREFER_LAST) ||
@@ -663,7 +656,7 @@ int assign_server(struct stream *s)
server_has_room(tmpsrv) || (
tmpsrv->queue.length + 1 < s->be->max_ka_queue))) &&
srv_currently_usable(tmpsrv)) {
- list_for_each_entry(conn, &srv_list->conn_list, session_list) {
+ list_for_each_entry(conn, &pconns->conn_list, sess_el) {
if (!(conn->flags & CO_FL_WAIT_XPRT)) {
srv = tmpsrv;
s->target = &srv->obj_type;
@@ -813,6 +806,14 @@ int assign_server(struct stream *s)
break;
default:
+ if ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_SA) {
+ /* some special algos that cannot be grouped together */
+
+ if ((s->be->lbprm.algo & BE_LB_PARM) == BE_LB_SA_SS)
+ srv = ss_get_server(s->be);
+
+ break;
+ }
/* unknown balancing algorithm */
err = SRV_STATUS_INTERNAL;
goto out;
@@ -1232,7 +1233,7 @@ struct connection *conn_backend_get(struct stream *s, struct server *srv, int is
continue;
conn = srv_lookup_conn(is_safe ? &srv->per_thr[i].safe_conns : &srv->per_thr[i].idle_conns, hash);
while (conn) {
- if (conn->mux->takeover && conn->mux->takeover(conn, i) == 0) {
+ if (conn->mux->takeover && conn->mux->takeover(conn, i, 0) == 0) {
conn_delete_from_tree(conn);
_HA_ATOMIC_INC(&activity[tid].fd_takeover);
found = 1;
@@ -1245,7 +1246,7 @@ struct connection *conn_backend_get(struct stream *s, struct server *srv, int is
if (!found && !is_safe && srv->curr_safe_nb > 0) {
conn = srv_lookup_conn(&srv->per_thr[i].safe_conns, hash);
while (conn) {
- if (conn->mux->takeover && conn->mux->takeover(conn, i) == 0) {
+ if (conn->mux->takeover && conn->mux->takeover(conn, i, 0) == 0) {
conn_delete_from_tree(conn);
_HA_ATOMIC_INC(&activity[tid].fd_takeover);
found = 1;
@@ -1348,9 +1349,7 @@ int connect_server(struct stream *s)
int reuse = 0;
int init_mux = 0;
int err;
-#ifdef USE_OPENSSL
- struct sample *sni_smp = NULL;
-#endif
+ struct sample *name_smp = NULL;
struct sockaddr_storage *bind_addr = NULL;
int proxy_line_ret;
int64_t hash = 0;
@@ -1372,13 +1371,11 @@ int connect_server(struct stream *s)
if (err != SRV_STATUS_OK)
return SF_ERR_INTERNAL;
-#ifdef USE_OPENSSL
- if (srv && srv->ssl_ctx.sni) {
- sni_smp = sample_fetch_as_type(s->be, s->sess, s,
- SMP_OPT_DIR_REQ | SMP_OPT_FINAL,
- srv->ssl_ctx.sni, SMP_T_STR);
+ if (srv && srv->pool_conn_name_expr) {
+ name_smp = sample_fetch_as_type(s->be, s->sess, s,
+ SMP_OPT_DIR_REQ | SMP_OPT_FINAL,
+ srv->pool_conn_name_expr, SMP_T_STR);
}
-#endif
/* do not reuse if mode is not http */
if (!IS_HTX_STRM(s)) {
@@ -1402,17 +1399,12 @@ int connect_server(struct stream *s)
/* 1. target */
hash_params.target = s->target;
-#ifdef USE_OPENSSL
- /* 2. sni
- * only test if the sample is not null as smp_make_safe (called before
- * ssl_sock_set_servername) can only fails if this is not the case
- */
- if (sni_smp) {
- hash_params.sni_prehash =
- conn_hash_prehash(sni_smp->data.u.str.area,
- sni_smp->data.u.str.data);
+ /* 2. pool-conn-name */
+ if (name_smp) {
+ hash_params.name_prehash =
+ conn_hash_prehash(name_smp->data.u.str.area,
+ name_smp->data.u.str.data);
}
-#endif /* USE_OPENSSL */
/* 3. destination address */
if (srv && srv_is_transparent(srv))
@@ -1423,13 +1415,43 @@ int connect_server(struct stream *s)
/* 5. proxy protocol */
if (srv && srv->pp_opts) {
- proxy_line_ret = make_proxy_line(trash.area, trash.size, srv, cli_conn, s);
+ proxy_line_ret = make_proxy_line(trash.area, trash.size, srv, cli_conn, s, strm_sess(s));
if (proxy_line_ret) {
hash_params.proxy_prehash =
conn_hash_prehash(trash.area, proxy_line_ret);
}
}
+ /* 6. Custom mark, tos? */
+ if (s->flags & (SF_BC_MARK | SF_BC_TOS)) {
+ /* mark: 32bits, tos: 8bits = 40bits
+ * last 2 bits are there to indicate if mark and/or tos are set
+ * total: 42bits:
+ *
+ * 63==== (unused) ====42 39----32 31-----------------------------0
+ * 0000000000000000000000 11 00000111 00000000000000000000000000000011
+ * ^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * || | |
+ * / \ \ \
+ * / \ \ \
+ * tos? mark? \ mark value (32bits)
+ * tos value (8bits)
+ * ie: in the above example:
+ * - mark is set, mark = 3
+ * - tos is set, tos = 7
+ */
+ if (s->flags & SF_BC_MARK) {
+ hash_params.mark_tos_prehash |= s->bc_mark;
+ /* 41th bit: mark set */
+ hash_params.mark_tos_prehash |= 1ULL << 40;
+ }
+ if (s->flags & SF_BC_TOS) {
+ hash_params.mark_tos_prehash |= (uint64_t)s->bc_tos << 32;
+ /* 42th bit: tos set */
+ hash_params.mark_tos_prehash |= 1ULL << 41;
+ }
+ }
+
hash = conn_calculate_hash(&hash_params);
/* first, search for a matching connection in the session's idle conns */
@@ -1617,6 +1639,18 @@ skip_reuse:
srv_conn->src = bind_addr;
bind_addr = NULL;
+ /* mark? */
+ if (s->flags & SF_BC_MARK) {
+ srv_conn->mark = s->bc_mark;
+ srv_conn->flags |= CO_FL_OPT_MARK;
+ }
+
+ /* tos? */
+ if (s->flags & SF_BC_TOS) {
+ srv_conn->tos = s->bc_tos;
+ srv_conn->flags |= CO_FL_OPT_TOS;
+ }
+
srv_conn->hash_node->node.key = hash;
}
}
@@ -1744,7 +1778,13 @@ skip_reuse:
return err;
#ifdef USE_OPENSSL
- if (!(s->flags & SF_SRV_REUSED)) {
+ /* Set socket SNI unless connection is reused. */
+ if (srv && srv->ssl_ctx.sni && !(s->flags & SF_SRV_REUSED)) {
+ struct sample *sni_smp = NULL;
+
+ sni_smp = sample_fetch_as_type(s->be, s->sess, s,
+ SMP_OPT_DIR_REQ | SMP_OPT_FINAL,
+ srv->ssl_ctx.sni, SMP_T_STR);
if (smp_make_safe(sni_smp))
ssl_sock_set_servername(srv_conn, sni_smp->data.u.str.area);
}
@@ -2515,8 +2555,8 @@ void back_handle_st_rdy(struct stream *s)
*/
void set_backend_down(struct proxy *be)
{
- be->last_change = ns_to_sec(now_ns);
- _HA_ATOMIC_INC(&be->down_trans);
+ be->be_counters.last_change = ns_to_sec(now_ns);
+ _HA_ATOMIC_INC(&be->be_counters.down_trans);
if (!(global.mode & MODE_STARTING)) {
ha_alert("%s '%s' has no server available!\n", proxy_type_str(be), be->id);
@@ -2588,10 +2628,10 @@ no_cookie:
}
int be_downtime(struct proxy *px) {
- if (px->lbprm.tot_weight && px->last_change < ns_to_sec(now_ns)) // ignore negative time
+ if (px->lbprm.tot_weight && px->be_counters.last_change < ns_to_sec(now_ns)) // ignore negative time
return px->down_time;
- return ns_to_sec(now_ns) - px->last_change + px->down_time;
+ return ns_to_sec(now_ns) - px->be_counters.last_change + px->down_time;
}
/*
@@ -2836,7 +2876,7 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
}
else if (strcmp(args[0], "sticky") == 0) {
curproxy->lbprm.algo &= ~BE_LB_ALGO;
- curproxy->lbprm.algo |= BE_LB_ALGO_LS;
+ curproxy->lbprm.algo |= BE_LB_ALGO_SS;
}
else {
memprintf(err, "only supports 'roundrobin', 'static-rr', 'leastconn', 'source', 'uri', 'url_param', 'hash', 'hdr(name)', 'rdp-cookie(name)', 'log-hash' and 'sticky' options.");
@@ -3029,7 +3069,7 @@ smp_fetch_be_sess_rate(const struct arg *args, struct sample *smp, const char *k
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
- smp->data.u.sint = read_freq_ctr(&px->be_sess_per_sec);
+ smp->data.u.sint = read_freq_ctr(&px->be_counters.sess_per_sec);
return 1;
}
@@ -3212,7 +3252,7 @@ smp_fetch_srv_sess_rate(const struct arg *args, struct sample *smp, const char *
{
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
- smp->data.u.sint = read_freq_ctr(&args->data.srv->sess_per_sec);
+ smp->data.u.sint = read_freq_ctr(&args->data.srv->counters.sess_per_sec);
return 1;
}