]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks/vars: Add a check scope for variables
authorGaetan Rivet <grive@u256.net>
Fri, 21 Feb 2020 17:13:44 +0000 (18:13 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Apr 2020 07:39:37 +0000 (09:39 +0200)
Add a dedicated vars scope for checks. This scope is considered as part of the
session scope for accounting purposes.

The scope can be addressed by a valid session, even embryonic. The stream is not
necessary.

The scope is initialized after the check session is created. All variables are
then pruned before the session is destroyed.

include/proto/checks.h
include/types/checks.h
include/types/vars.h
src/checks.c
src/vars.c

index 37681f1a4d7bb2cfac859503c72786d6ba00cef4..d9491753dee105f7832bb3cec194dd652ceb053b 100644 (file)
@@ -26,6 +26,8 @@
 #include <common/config.h>
 #include <types/mailers.h>
 
+#include <types/action.h>
+
 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);
index f92f0da60ddfede5aadd044382a91974c79112ae..b980faae05e2ab20c5d8fe0a16bd650f12e18dcf 100644 (file)
@@ -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 */
index 9b166e9d650f59f69fcb8717b7e19792260cb5cd..a72469fd133ab49c200d0fc7d4d80a8e9102fbf4 100644 (file)
@@ -12,6 +12,7 @@ enum vars_scope {
        SCOPE_REQ,
        SCOPE_RES,
        SCOPE_PROC,
+       SCOPE_CHECK,
 };
 
 struct vars {
index 49a0f3da64b1fb4fae0151fce4b3bb082fcd27fa..9423e2d7dc1c0b7c4810c082788c413bde3aa34c 100644 (file)
@@ -58,6 +58,7 @@
 #include <proto/signal.h>
 #include <proto/stream_interface.h>
 #include <proto/task.h>
+#include <proto/vars.h>
 #include <proto/log.h>
 #include <proto/dns.h>
 #include <proto/proto_udp.h>
@@ -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)
index 403cb69f1d9197c5feda9843b58edf05a171f7d7..0b7b990019745ef93e51c0c97f2843e68477c215 100644 (file)
@@ -14,6 +14,7 @@
 #include <proto/stream.h>
 #include <proto/tcp_rules.h>
 #include <proto/vars.h>
+#include <proto/checks.h>
 
 /* 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 */ }
 }};