mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
MEDIUM: checks: Add implicit tcp-check connect rule
After the configuration parsing, when its validity check, an implicit tcp-check connect rule is added in front of the tcp-check ruleset if the first non-comment rule is not a connect one. This implicit rule is flagged to use the default check parameter. This means now, all tcp-check rulesets begin with a connect and are never empty. When tcp-check healthchecks are used, all connections are thus handled by tcpcheck_main() function.
This commit is contained in:
parent
06d963aeca
commit
a202d1d4c1
@ -211,10 +211,11 @@ struct analyze_status {
|
|||||||
unsigned char lr[HANA_OBS_SIZE]; /* result for l4/l7: 0 = ignore, 1 - error, 2 - OK */
|
unsigned char lr[HANA_OBS_SIZE]; /* result for l4/l7: 0 = ignore, 1 - error, 2 - OK */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCPCHK_OPT_NONE 0x0000 /* no options specified, default */
|
#define TCPCHK_OPT_NONE 0x0000 /* no options specified, default */
|
||||||
#define TCPCHK_OPT_SEND_PROXY 0x0001 /* send proxy-protocol string */
|
#define TCPCHK_OPT_SEND_PROXY 0x0001 /* send proxy-protocol string */
|
||||||
#define TCPCHK_OPT_SSL 0x0002 /* SSL connection */
|
#define TCPCHK_OPT_SSL 0x0002 /* SSL connection */
|
||||||
#define TCPCHK_OPT_LINGER 0x0004 /* Do not RST connection, let it linger */
|
#define TCPCHK_OPT_LINGER 0x0004 /* Do not RST connection, let it linger */
|
||||||
|
#define TCPCHK_OPT_DEFAULT_CONNECT 0x0008 /* Do a connect using server params */
|
||||||
|
|
||||||
struct tcpcheck_connect {
|
struct tcpcheck_connect {
|
||||||
uint16_t port; /* port to connect to */
|
uint16_t port; /* port to connect to */
|
||||||
|
129
src/checks.c
129
src/checks.c
@ -1604,7 +1604,6 @@ static int connect_conn_chk(struct task *t)
|
|||||||
struct conn_stream *cs = check->cs;
|
struct conn_stream *cs = check->cs;
|
||||||
struct connection *conn = cs_conn(cs);
|
struct connection *conn = cs_conn(cs);
|
||||||
struct protocol *proto;
|
struct protocol *proto;
|
||||||
struct tcpcheck_rule *tcp_rule = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
int connflags = 0;
|
int connflags = 0;
|
||||||
|
|
||||||
@ -1612,12 +1611,6 @@ static int connect_conn_chk(struct task *t)
|
|||||||
if (conn)
|
if (conn)
|
||||||
return SF_ERR_INTERNAL;
|
return SF_ERR_INTERNAL;
|
||||||
|
|
||||||
/* tcpcheck send/expect initialisation */
|
|
||||||
if (check->type == PR_O2_TCPCHK_CHK) {
|
|
||||||
check->current_step = check->last_started_step = NULL;
|
|
||||||
tcp_rule = get_first_tcpcheck_rule(check->tcpcheck_rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare the check buffer.
|
/* prepare the check buffer.
|
||||||
* This should not be used if check is the secondary agent check
|
* This should not be used if check is the secondary agent check
|
||||||
* of a server as s->proxy->check_req will relate to the
|
* of a server as s->proxy->check_req will relate to the
|
||||||
@ -1671,7 +1664,9 @@ static int connect_conn_chk(struct task *t)
|
|||||||
/* for tcp-checks, the initial connection setup is handled separately as
|
/* for tcp-checks, the initial connection setup is handled separately as
|
||||||
* it may be sent to a specific port and not to the server's.
|
* it may be sent to a specific port and not to the server's.
|
||||||
*/
|
*/
|
||||||
if (tcp_rule && tcp_rule->action == TCPCHK_ACT_CONNECT) {
|
if (check->type == PR_O2_TCPCHK_CHK) {
|
||||||
|
/* tcpcheck initialisation */
|
||||||
|
check->current_step = check->last_started_step = NULL;
|
||||||
tcpcheck_main(check);
|
tcpcheck_main(check);
|
||||||
return SF_ERR_UP;
|
return SF_ERR_UP;
|
||||||
}
|
}
|
||||||
@ -1723,12 +1718,8 @@ static int connect_conn_chk(struct task *t)
|
|||||||
return SF_ERR_RESOURCE;
|
return SF_ERR_RESOURCE;
|
||||||
cs_attach(cs, check, &check_conn_cb);
|
cs_attach(cs, check, &check_conn_cb);
|
||||||
|
|
||||||
/* only plain tcp-check supports quick ACK */
|
/* only plain tcp check supports quick ACK */
|
||||||
if (check->type != 0)
|
connflags |= (check->type ? CONNECT_HAS_DATA : CONNECT_DELACK_ALWAYS);
|
||||||
connflags |= CONNECT_HAS_DATA;
|
|
||||||
if ((check->type == 0 || check->type == PR_O2_TCPCHK_CHK) &&
|
|
||||||
(!tcp_rule || tcp_rule->action != TCPCHK_ACT_EXPECT))
|
|
||||||
connflags |= CONNECT_DELACK_ALWAYS;
|
|
||||||
|
|
||||||
ret = SF_ERR_INTERNAL;
|
ret = SF_ERR_INTERNAL;
|
||||||
if (proto && proto->connect)
|
if (proto && proto->connect)
|
||||||
@ -2738,6 +2729,12 @@ static int tcpcheck_get_step_id(struct check *check)
|
|||||||
if (!check->last_started_step)
|
if (!check->last_started_step)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* last step is the first implicit connect */
|
||||||
|
if (check->last_started_step->index == 0 &&
|
||||||
|
check->last_started_step->action == TCPCHK_ACT_CONNECT &&
|
||||||
|
(check->last_started_step->connect.options & TCPCHK_OPT_DEFAULT_CONNECT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return check->last_started_step->index + 1;
|
return check->last_started_step->index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2957,38 +2954,31 @@ static int tcpcheck_main(struct check *check)
|
|||||||
goto fail_check;
|
goto fail_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_addr(&check->addr)) {
|
/* connect to the check addr if specified on the
|
||||||
/* we'll connect to the check addr specified on the server */
|
* server. otherwise, use the server addr
|
||||||
*conn->dst = check->addr;
|
*/
|
||||||
}
|
*conn->dst = (is_addr(&check->addr) ? check->addr : s->addr);
|
||||||
else {
|
|
||||||
/* we'll connect to the addr on the server */
|
|
||||||
*conn->dst = s->addr;
|
|
||||||
}
|
|
||||||
proto = protocol_by_family(conn->dst->ss_family);
|
proto = protocol_by_family(conn->dst->ss_family);
|
||||||
|
|
||||||
/* port */
|
|
||||||
if (connect->port)
|
if (connect->port)
|
||||||
set_host_port(conn->dst, connect->port);
|
set_host_port(conn->dst, connect->port);
|
||||||
else if (check->port)
|
else if (check->port)
|
||||||
set_host_port(conn->dst, check->port);
|
set_host_port(conn->dst, check->port);
|
||||||
else if (s->svc_port)
|
|
||||||
set_host_port(conn->dst, s->svc_port);
|
|
||||||
|
|
||||||
if (connect->options & TCPCHK_OPT_SSL) {
|
|
||||||
xprt = xprt_get(XPRT_SSL);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
xprt = xprt_get(XPRT_RAW);
|
int i = get_host_port(&check->addr);
|
||||||
|
|
||||||
|
set_host_port(conn->dst, ((i > 0) ? i : s->svc_port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xprt = ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT)
|
||||||
|
? check->xprt
|
||||||
|
: ((connect->options & TCPCHK_OPT_SSL) ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW)));
|
||||||
|
|
||||||
conn_prepare(conn, proto, xprt);
|
conn_prepare(conn, proto, xprt);
|
||||||
|
|
||||||
if (conn_install_mux(conn, &mux_pt_ops, cs, proxy, NULL) < 0) {
|
if (conn_install_mux(conn, &mux_pt_ops, cs, proxy, NULL) < 0) {
|
||||||
ret = SF_ERR_RESOURCE;
|
ret = SF_ERR_RESOURCE;
|
||||||
goto fail_check;
|
goto fail_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs_attach(cs, check, &check_conn_cb);
|
cs_attach(cs, check, &check_conn_cb);
|
||||||
|
|
||||||
ret = SF_ERR_INTERNAL;
|
ret = SF_ERR_INTERNAL;
|
||||||
@ -3000,18 +2990,42 @@ static int tcpcheck_main(struct check *check)
|
|||||||
flags |= CONNECT_DELACK_ALWAYS;
|
flags |= CONNECT_DELACK_ALWAYS;
|
||||||
ret = proto->connect(conn, flags);
|
ret = proto->connect(conn, flags);
|
||||||
}
|
}
|
||||||
if (conn_ctrl_ready(conn) &&
|
|
||||||
connect->options & TCPCHK_OPT_SEND_PROXY) {
|
if (connect->options & TCPCHK_OPT_DEFAULT_CONNECT) {
|
||||||
conn->send_proxy_ofs = 1;
|
#ifdef USE_OPENSSL
|
||||||
conn->flags |= CO_FL_SEND_PROXY;
|
if (ret == SF_ERR_NONE) {
|
||||||
if (xprt_add_hs(conn) < 0)
|
if (s->check.sni)
|
||||||
ret = SF_ERR_RESOURCE;
|
ssl_sock_set_servername(conn, s->check.sni);
|
||||||
|
if (s->check.alpn_str)
|
||||||
|
ssl_sock_set_alpn(conn, (unsigned char *)s->check.alpn_str,
|
||||||
|
s->check.alpn_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (s->check.via_socks4 && (s->flags & SRV_F_SOCKS4_PROXY)) {
|
||||||
|
conn->send_proxy_ofs = 1;
|
||||||
|
conn->flags |= CO_FL_SOCKS4;
|
||||||
|
}
|
||||||
|
if (s->check.send_proxy && !(check->state & CHK_ST_AGENT)) {
|
||||||
|
conn->send_proxy_ofs = 1;
|
||||||
|
conn->flags |= CO_FL_SEND_PROXY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: add sock4 and sni option */
|
||||||
|
if (connect->options & TCPCHK_OPT_SEND_PROXY) {
|
||||||
|
conn->send_proxy_ofs = 1;
|
||||||
|
conn->flags |= CO_FL_SEND_PROXY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn_ctrl_ready(conn) && (connect->options & TCPCHK_OPT_LINGER)) {
|
||||||
|
/* Some servers don't like reset on close */
|
||||||
|
fdtab[cs->conn->handle.fd].linger_risk = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn_ctrl_ready(conn) &&
|
if (conn_ctrl_ready(conn) && (conn->flags & (CO_FL_SEND_PROXY | CO_FL_SOCKS4))) {
|
||||||
connect->options & TCPCHK_OPT_LINGER) {
|
if (xprt_add_hs(conn) < 0)
|
||||||
/* Some servers don't like reset on close */
|
ret = SF_ERR_RESOURCE;
|
||||||
fdtab[cs->conn->handle.fd].linger_risk = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It can return one of :
|
/* It can return one of :
|
||||||
@ -3796,6 +3810,35 @@ static int srv_check_healthcheck_port(struct check *chk)
|
|||||||
|
|
||||||
REGISTER_POST_CHECK(start_checks);
|
REGISTER_POST_CHECK(start_checks);
|
||||||
|
|
||||||
|
static int check_proxy_tcpcheck(struct proxy *px)
|
||||||
|
{
|
||||||
|
struct tcpcheck_rule *chk;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!px->tcpcheck_rules)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* If there is no connect rule preceeding all send / expect rules, an
|
||||||
|
* implicit one is inserted before all others
|
||||||
|
*/
|
||||||
|
chk = get_first_tcpcheck_rule(px->tcpcheck_rules);
|
||||||
|
if (!chk || chk->action != TCPCHK_ACT_CONNECT) {
|
||||||
|
chk = calloc(1, sizeof(*chk));
|
||||||
|
if (!chk) {
|
||||||
|
ha_alert("config : proxy '%s': unable to add implicit tcp-check connect rule "
|
||||||
|
"(out of memory).\n", px->id);
|
||||||
|
ret |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
chk->action = TCPCHK_ACT_CONNECT;
|
||||||
|
chk->connect.options = TCPCHK_OPT_DEFAULT_CONNECT;
|
||||||
|
LIST_ADD(px->tcpcheck_rules, &chk->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int init_srv_check(struct server *srv)
|
static int init_srv_check(struct server *srv)
|
||||||
{
|
{
|
||||||
const char *err;
|
const char *err;
|
||||||
@ -3929,6 +3972,8 @@ static void deinit_srv_agent_check(struct server *srv)
|
|||||||
free(srv->agent.send_string);
|
free(srv->agent.send_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
REGISTER_POST_PROXY_CHECK(check_proxy_tcpcheck);
|
||||||
REGISTER_POST_SERVER_CHECK(init_srv_check);
|
REGISTER_POST_SERVER_CHECK(init_srv_check);
|
||||||
REGISTER_POST_SERVER_CHECK(init_srv_agent_check);
|
REGISTER_POST_SERVER_CHECK(init_srv_agent_check);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user