diff --git a/doc/configuration.txt b/doc/configuration.txt index 26137459e..45d405145 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -24325,6 +24325,7 @@ bc_srv_queue integer be_id integer be_name string be_connect_timeout integer +be_max_retries integer be_queue_timeout integer be_server_timeout integer be_tarpit_timeout integer @@ -24333,6 +24334,7 @@ bytes_in integer bytes_out integer cur_connect_timeout integer cur_client_timeout integer +cur_max_retries integer cur_queue_timeout integer cur_server_timeout integer cur_tarpit_timeout integer @@ -24669,6 +24671,11 @@ be_connect_timeout : integer current backend. This timeout can be overwritten by a "set-timeout" rule. See also the "cur_connect_timeout". +be_max_retries : integer + Returns the configuration value for the connection retries of the current + backend. This value can be overwritten by a "set-retries" rule. See also the + "cur_max_retries". + be_name : string Returns a string containing the current backend's name. It can be used in frontends with responses to check which backend processed the request. If @@ -24712,6 +24719,11 @@ cur_client_timeout : integer In the default case, this will be equal to fe_client_timeout unless a "set-timeout" rule has been applied. See also "fe_client_timeout". +cur_max_retries : integer + Returns the currently applied connect retries for the stream. + In the default case, this will be equal to be_max_retries unless a + "set-retries" rule has been applied. See also "be_max_retries". + cur_queue_timeout : integer Returns the currently applied queue timeout in millisecond for the stream. In the default case, this will be equal to be_queue_timeout unless a diff --git a/reg-tests/stream/set-retries.vtc b/reg-tests/stream/set-retries.vtc new file mode 100644 index 000000000..ddffaf267 --- /dev/null +++ b/reg-tests/stream/set-retries.vtc @@ -0,0 +1,114 @@ +varnishtest "set-retries action test" + +feature ignore_unknown_macro + +server srv_h1 -repeat 6 { + rxreq + txresp -hdr "Connection: close" +} -start + + +haproxy hap -conf { + global + .if feature(THREAD) + thread-groups 1 + .endif + + defaults + timeout connect 5s + timeout client 5s + timeout server 5s + retries 3 + log global + + listen li1 + mode http + bind "fd@${li1}" + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + server srv_h1 ${srv_h1_addr}:${srv_h1_port} + + listen li2 + mode http + bind "fd@${li2}" + http-request set-retries 5 + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + server srv_h1 ${srv_h1_addr}:${srv_h1_port} + + listen li3 + mode http + bind "fd@${li3}" + http-request set-retries 5 + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + default_backend be1 + + listen li4 + mode http + bind "fd@${li4}" + http-request set-retries 4 + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + default_backend be2 + + frontend fe5 + mode http + bind "fd@${fe5}" + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + default_backend be1 + + frontend fe6 + mode http + bind "fd@${fe6}" + http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]" + default_backend be2 + + backend be1 + mode http + server srv_h1 ${srv_h1_addr}:${srv_h1_port} + + backend be2 + mode http + http-request set-retries 5 + server srv_h1 ${srv_h1_addr}:${srv_h1_port} + +} -start + +client c1 -connect ${hap_li1_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 3" +} -run + +client c2 -connect ${hap_li2_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 5" +} -run + +client c3 -connect ${hap_li3_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 3" +} -run + +client c4 -connect ${hap_li4_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 5" +} -run + +client c5 -connect ${hap_fe5_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 3" +} -run + +client c6 -connect ${hap_fe6_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.retries == "3 5" +} -run diff --git a/src/backend.c b/src/backend.c index d04466eea..4001135ba 100644 --- a/src/backend.c +++ b/src/backend.c @@ -3756,6 +3756,24 @@ smp_fetch_srv_uweight(const struct arg *args, struct sample *smp, const char *kw return 1; } +static int +smp_fetch_be_max_retries(const struct arg *args, struct sample *smp, const char *km, void *private) +{ + struct proxy *px = NULL; + + if (smp->strm) + px = smp->strm->be; + else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + px = __objt_check(smp->sess->origin)->proxy; + if (!px) + return 0; + + smp->flags = SMP_F_VOL_TXN; + smp->data.type = SMP_T_SINT; + smp->data.u.sint = px->conn_retries; + return 1; +} + static int smp_fetch_be_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private) { @@ -3929,6 +3947,7 @@ static struct sample_fetch_kw_list smp_kws = {ILH, { { "be_id", smp_fetch_be_id, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "be_name", smp_fetch_be_name, 0, NULL, SMP_T_STR, SMP_USE_BKEND, }, { "be_connect_timeout",smp_fetch_be_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, + { "be_max_retries", smp_fetch_be_max_retries, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "be_queue_timeout", smp_fetch_be_queue_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "be_server_timeout", smp_fetch_be_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "be_sess_rate", smp_fetch_be_sess_rate, ARG1(1,BE), NULL, SMP_T_SINT, SMP_USE_INTRN, }, diff --git a/src/stream.c b/src/stream.c index ccf0ea993..862f5576b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -4420,6 +4420,17 @@ static struct action_kw_list stream_http_after_res_actions = { ILH, { INITCALL1(STG_REGISTER, http_after_res_keywords_register, &stream_http_after_res_actions); +static int smp_fetch_cur_max_retries(const struct arg *args, struct sample *smp, const char *km, void *private) +{ + smp->flags = SMP_F_VOL_TXN; + smp->data.type = SMP_T_SINT; + if (!smp->strm) + return 0; + + smp->data.u.sint = smp->strm->max_retries; + return 1; +} + static int smp_fetch_cur_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private) { smp->flags = SMP_F_VOL_TXN; @@ -4687,6 +4698,7 @@ static int smp_fetch_redispatched(const struct arg *args, struct sample *smp, co static struct sample_fetch_kw_list smp_kws = {ILH, { { "cur_connect_timeout",smp_fetch_cur_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "cur_client_timeout", smp_fetch_cur_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, }, + { "cur_max_retries", smp_fetch_cur_max_retries, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "cur_server_timeout", smp_fetch_cur_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "cur_queue_timeout", smp_fetch_cur_queue_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, }, { "cur_tarpit_timeout", smp_fetch_cur_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND | SMP_USE_BKEND, },