diff --git a/include/proto/checks.h b/include/proto/checks.h index 37681f1a4..d9491753d 100644 --- a/include/proto/checks.h +++ b/include/proto/checks.h @@ -26,6 +26,8 @@ #include #include +#include + const char *get_check_status_description(short check_status); const char *get_check_status_info(short check_status); void __health_adjust(struct server *s, short status); diff --git a/include/types/checks.h b/include/types/checks.h index f92f0da60..b980faae0 100644 --- a/include/types/checks.h +++ b/include/types/checks.h @@ -159,6 +159,7 @@ enum { struct check { struct session *sess; /* Health check session. */ + struct vars vars; /* Health check dynamic variables. */ struct xprt_ops *xprt; /* transport layer operations for health checks */ struct conn_stream *cs; /* conn_stream state for health checks */ struct buffer bi, bo; /* input and output buffers to send/recv check */ diff --git a/include/types/vars.h b/include/types/vars.h index 9b166e9d6..a72469fd1 100644 --- a/include/types/vars.h +++ b/include/types/vars.h @@ -12,6 +12,7 @@ enum vars_scope { SCOPE_REQ, SCOPE_RES, SCOPE_PROC, + SCOPE_CHECK, }; struct vars { diff --git a/src/checks.c b/src/checks.c index 49a0f3da6..9423e2d7d 100644 --- a/src/checks.c +++ b/src/checks.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -3224,12 +3225,13 @@ static int tcpcheck_main(struct check *check) } else { /* First evaluation, create a session */ - check->sess = session_new(&checks_fe, NULL, NULL); + check->sess = session_new(&checks_fe, NULL, (check->server ? &check->server->obj_type : NULL)); if (!check->sess) { chunk_printf(&trash, "TCPCHK error allocating check session"); set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.area); goto out_end_tcpcheck; } + vars_init(&check->vars, SCOPE_CHECK); rule = LIST_NEXT(check->tcpcheck_rules, typeof(rule), list); } @@ -3339,12 +3341,12 @@ static int tcpcheck_main(struct check *check) /* cleanup before leaving */ check->current_step = NULL; if (check->sess != NULL) { + vars_prune(&check->vars, check->sess, NULL); session_free(check->sess); check->sess = NULL; } out: return retcode; - } static const char *init_check(struct check *check, int type) diff --git a/src/vars.c b/src/vars.c index 403cb69f1..0b7b99001 100644 --- a/src/vars.c +++ b/src/vars.c @@ -14,6 +14,7 @@ #include #include #include +#include /* This contains a pool of struct vars */ DECLARE_STATIC_POOL(var_pool, "vars", sizeof(struct var)); @@ -33,6 +34,7 @@ static unsigned int var_proc_limit = 0; static unsigned int var_sess_limit = 0; static unsigned int var_txn_limit = 0; static unsigned int var_reqres_limit = 0; +static unsigned int var_check_limit = 0; __decl_rwlock(var_names_rwlock); @@ -46,6 +48,11 @@ static inline struct vars *get_vars(struct session *sess, struct stream *strm, e return &global.vars; case SCOPE_SESS: return &sess->vars; + case SCOPE_CHECK: { + struct server *srv = objt_server(sess->origin); + + return srv ? &srv->check.vars : NULL; + } case SCOPE_TXN: return strm ? &strm->vars_txn : NULL; case SCOPE_REQ: @@ -69,7 +76,15 @@ static void var_accounting_diff(struct vars *vars, struct session *sess, struct case SCOPE_TXN: if (strm) _HA_ATOMIC_ADD(&strm->vars_txn.size, size); + goto scope_sess; + case SCOPE_CHECK: { + struct server *srv = objt_server(sess->origin); + + if (srv != NULL) + _HA_ATOMIC_ADD(&srv->check.vars.size, size); + } /* fall through */ +scope_sess: case SCOPE_SESS: _HA_ATOMIC_ADD(&sess->vars.size, size); /* fall through */ @@ -97,7 +112,16 @@ static int var_accounting_add(struct vars *vars, struct session *sess, struct st case SCOPE_TXN: if (var_txn_limit && strm && strm->vars_txn.size + size > var_txn_limit) return 0; + goto scope_sess; + case SCOPE_CHECK: { + struct server *srv = objt_server(sess->origin); + + if (var_check_limit && srv && + srv->check.vars.size + size > var_check_limit) + return 0; + } /* fall through */ +scope_sess: case SCOPE_SESS: if (var_sess_limit && sess->vars.size + size > var_sess_limit) return 0; @@ -226,9 +250,14 @@ static char *register_name(const char *name, int len, enum vars_scope *scope, len -= 4; *scope = SCOPE_RES; } + else if (len > 6 && strncmp(name, "check.", 6) == 0) { + name += 6; + len -= 6; + *scope = SCOPE_CHECK; + } else { memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. " - "The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name); + "The scope can be 'proc', 'sess', 'txn', 'req', 'res' or 'check'", name); return res; } @@ -827,6 +856,13 @@ static int vars_max_size_reqres(char **args, int section_type, struct proxy *cur return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit); } +static int vars_max_size_check(char **args, int section_type, struct proxy *curpx, + struct proxy *defpx, const char *file, int line, + char **err) +{ + return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_check_limit); +} + static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI }, @@ -897,6 +933,7 @@ static struct cfg_kw_list cfg_kws = {{ },{ { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess }, { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn }, { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres }, + { CFG_GLOBAL, "tune.vars.check-max-size", vars_max_size_check }, { /* END */ } }};