From: Willy Tarreau Date: Sat, 6 Aug 2011 15:05:02 +0000 (+0200) Subject: [MEDIUM] checks: group health checks methods by values and save option bits X-Git-Tag: v1.5-dev8~156 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1620ec39a7156c4fd518359975498c10b81ef7aa;p=thirdparty%2Fhaproxy.git [MEDIUM] checks: group health checks methods by values and save option bits Adding health checks has become a real pain, with cross-references to all checks everywhere because they're all a single bit. Since they're all exclusive, let's change this to have a check number only. We reserve 4 bits allowing up to 16 checks (15+tcp), only 7 of which are currently used. The code has shrunk by almost 1kB and we saved a few option bits. The "dispatch" option has been moved to px->options, making a few tests a bit cleaner. --- diff --git a/include/types/proxy.h b/include/types/proxy.h index b4385a9854..e4fcc7750d 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -78,14 +78,14 @@ enum { #define PR_O_COOK_INS 0x00000010 /* insert cookies when not accessing a server directly */ #define PR_O_COOK_PFX 0x00000020 /* rewrite all cookies by prefixing the right serverid */ #define PR_O_COOK_ANY (PR_O_COOK_RW | PR_O_COOK_IND | PR_O_COOK_INS | PR_O_COOK_PFX) -#define PR_O_SMTP_CHK 0x00000040 /* use SMTP EHLO check for server health - pvandijk@vision6.com.au */ +#define PR_O_DISPATCH 0x00000040 /* use dispatch mode */ #define PR_O_KEEPALIVE 0x00000080 /* follow keep-alive sessions */ #define PR_O_FWDFOR 0x00000100 /* insert x-forwarded-for with client address */ #define PR_O_BIND_SRC 0x00000200 /* bind to a specific source address when connect()ing */ #define PR_O_NULLNOLOG 0x00000400 /* a connect without request will not be logged */ #define PR_O_COOK_NOC 0x00000800 /* add a 'Cache-control' header with the cookie */ #define PR_O_COOK_POST 0x00001000 /* don't insert cookies for requests other than a POST */ -#define PR_O_HTTP_CHK 0x00002000 /* use HTTP 'OPTIONS' method to check server health */ +/* unused: 0x00002000 */ #define PR_O_PERSIST 0x00004000 /* server persistence stays effective even when server is down */ #define PR_O_LOGASAP 0x00008000 /* log as soon as possible, without waiting for the session to complete */ #define PR_O_HTTP_CLOSE 0x00010000 /* force 'connection: close' in both directions */ @@ -135,14 +135,12 @@ enum { #define PR_O2_AS_M_PP 0x00000000 /* path-parameters mode (the default mode) */ #define PR_O2_AS_M_QS 0x00010000 /* query-string mode */ #define PR_O2_AS_M_ANY 0x00010000 /* mask covering all PR_O2_AS_M_* values */ - -#define PR_O2_MYSQL_CHK 0x00020000 /* use MYSQL check for server health */ +#define PR_O2_NODELAY 0x00020000 /* fully interactive mode, never delay outgoing data */ #define PR_O2_USE_PXHDR 0x00040000 /* use Proxy-Connection for proxy requests */ #define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */ -#define PR_O2_SSL3_CHK 0x00100000 /* use SSLv3 CLIENT_HELLO packets for server health */ +/* unused: 0x00100000 */ #define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with server eventhough we close */ -#define PR_O2_LDAP_CHK 0x00400000 /* use LDAP check for server health */ - +/* unused: 0x00400000 */ #define PR_O2_EXP_NONE 0x00000000 /* http-check : no expect rule */ #define PR_O2_EXP_STS 0x00800000 /* http-check expect status */ #define PR_O2_EXP_RSTS 0x01000000 /* http-check expect rstatus */ @@ -152,10 +150,17 @@ enum { #define PR_O2_EXP_INV 0x04000000 /* http-check expect ! */ #define PR_O2_COOK_PSV 0x08000000 /* cookie ... preserve */ +/* server health checks */ +#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */ #define PR_O2_PGSQL_CHK 0x10000000 /* use PGSQL check for server health */ -#define PR_O2_DISPATCH 0x20000000 /* use dispatch mode */ -#define PR_O2_NODELAY 0x40000000 /* fully interactive mode, never delay outgoing data */ -#define PR_O2_REDIS_CHK 0x80000000 /* use LDAP check for server health */ +#define PR_O2_REDIS_CHK 0x20000000 /* use LDAP check for server health */ +#define PR_O2_SMTP_CHK 0x30000000 /* use SMTP EHLO check for server health - pvandijk@vision6.com.au */ +#define PR_O2_HTTP_CHK 0x40000000 /* use HTTP 'OPTIONS' method to check server health */ +#define PR_O2_MYSQL_CHK 0x50000000 /* use MYSQL check for server health */ +#define PR_O2_LDAP_CHK 0x60000000 /* use LDAP check for server health */ +#define PR_O2_SSL3_CHK 0x70000000 /* use SSLv3 CLIENT_HELLO packets for server health */ +/* unused: 0x80000000 to 0xF000000, reserved for health checks */ +#define PR_O2_CHK_ANY 0xF0000000 /* Mask to cover any check */ /* end of proxy->options2 */ /* bits for sticking rules */ diff --git a/src/backend.c b/src/backend.c index d76324fc54..2cbc8880cb 100644 --- a/src/backend.c +++ b/src/backend.c @@ -618,7 +618,7 @@ int assign_server(struct session *s) } set_target_server(&s->target, srv); } - else if ((s->be->options2 & PR_O2_DISPATCH) || (s->be->options & PR_O_TRANSP)) { + else if (s->be->options & (PR_O_DISPATCH | PR_O_TRANSP)) { set_target_proxy(&s->target, s->be); } else if ((s->be->options & PR_O_HTTP_PROXY) && @@ -720,7 +720,7 @@ int assign_server_address(struct session *s) } } } - else if (s->be->options2 & PR_O2_DISPATCH) { + else if (s->be->options & PR_O_DISPATCH) { /* connect to the defined dispatch addr */ s->req->cons->addr.s.to = s->be->dispatch_addr; } diff --git a/src/cfgparse.c b/src/cfgparse.c index 44fc1dabd9..8c61f3d535 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3255,13 +3255,8 @@ stats_error_parsing: /* use HTTP request to check servers' health */ free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; - curproxy->options |= PR_O_HTTP_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; + curproxy->options2 |= PR_O2_HTTP_CHK; if (!*args[2]) { /* no argument */ curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */ curproxy->check_len = strlen(DEF_CHECK_REQ); @@ -3289,25 +3284,15 @@ stats_error_parsing: free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 |= PR_O2_SSL3_CHK; } else if (!strcmp(args[1], "smtpchk")) { /* use SMTP request to check servers' health */ free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; - curproxy->options |= PR_O_SMTP_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; + curproxy->options2 |= PR_O2_SMTP_CHK; if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */ curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */ @@ -3333,12 +3318,7 @@ stats_error_parsing: free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 |= PR_O2_PGSQL_CHK; if (*(args[2])) { @@ -3397,12 +3377,7 @@ stats_error_parsing: free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 |= PR_O2_REDIS_CHK; curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1); @@ -3417,12 +3392,7 @@ stats_error_parsing: free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_LDAP_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 |= PR_O2_MYSQL_CHK; /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte. @@ -3489,12 +3459,7 @@ stats_error_parsing: /* use LDAP request to check servers' health */ free(curproxy->check_req); curproxy->check_req = NULL; - curproxy->options &= ~PR_O_HTTP_CHK; - curproxy->options &= ~PR_O_SMTP_CHK; - curproxy->options2 &= ~PR_O2_SSL3_CHK; - curproxy->options2 &= ~PR_O2_MYSQL_CHK; - curproxy->options2 &= ~PR_O2_PGSQL_CHK; - curproxy->options2 &= ~PR_O2_REDIS_CHK; + curproxy->options2 &= ~PR_O2_CHK_ANY; curproxy->options2 |= PR_O2_LDAP_CHK; curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1); @@ -3836,7 +3801,7 @@ stats_error_parsing: goto out; } curproxy->dispatch_addr = *sk; - curproxy->options2 |= PR_O2_DISPATCH; + curproxy->options |= PR_O_DISPATCH; } else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */ if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) @@ -5619,14 +5584,13 @@ int check_config_validity() cfgerr++; } #endif - else if (curproxy->options2 & PR_O2_DISPATCH) { + else if (curproxy->options & PR_O_DISPATCH) { Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n", proxy_type_str(curproxy), curproxy->id); err_code |= ERR_WARN; } } - else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) && - !(curproxy->options2 & PR_O2_DISPATCH)) { + else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) { /* If no LB algo is set in a backend, and we're not in * transparent mode, dispatch mode nor proxy mode, we * want to use balance roundrobin by default. @@ -5636,31 +5600,26 @@ int check_config_validity() } } - if (curproxy->options2 & PR_O2_DISPATCH) { - curproxy->options &= ~PR_O_TRANSP; - curproxy->options &= ~PR_O_HTTP_PROXY; - } - else if (curproxy->options & PR_O_HTTP_PROXY) { - curproxy->options2 &= ~PR_O2_DISPATCH; - curproxy->options &= ~PR_O_TRANSP; - } - else if (curproxy->options & PR_O_TRANSP) { - curproxy->options2 &= ~PR_O2_DISPATCH; - curproxy->options &= ~PR_O_HTTP_PROXY; - } - - if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) { - curproxy->options &= ~PR_O_DISABLE404; - Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n", - "disable-on-404", proxy_type_str(curproxy), curproxy->id); - err_code |= ERR_WARN; - } + if (curproxy->options & PR_O_DISPATCH) + curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY); + else if (curproxy->options & PR_O_HTTP_PROXY) + curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP); + else if (curproxy->options & PR_O_TRANSP) + curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY); - if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) { - curproxy->options &= ~PR_O2_CHK_SNDST; - Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n", - "send-state", proxy_type_str(curproxy), curproxy->id); - err_code |= ERR_WARN; + if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) { + if (curproxy->options & PR_O_DISABLE404) { + Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n", + "disable-on-404", proxy_type_str(curproxy), curproxy->id); + err_code |= ERR_WARN; + curproxy->options &= ~PR_O_DISABLE404; + } + if (curproxy->options2 & PR_O2_CHK_SNDST) { + Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n", + "send-state", proxy_type_str(curproxy), curproxy->id); + err_code |= ERR_WARN; + curproxy->options &= ~PR_O2_CHK_SNDST; + } } /* if a default backend was specified, let's find it */ @@ -6001,7 +5960,7 @@ out_uri_auth_compat: } } - if (curproxy->options2 & PR_O2_SSL3_CHK) { + if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) { curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1; curproxy->check_req = (char *)malloc(curproxy->check_len); memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len); diff --git a/src/checks.c b/src/checks.c index 50fe2a2048..2e22b49e33 100644 --- a/src/checks.c +++ b/src/checks.c @@ -768,13 +768,7 @@ static int event_srv_chk_w(int fd) if (!(s->result & SRV_CHK_ERROR)) { /* we don't want to mark 'UP' a server on which we detected an error earlier */ - if ((s->proxy->options & PR_O_HTTP_CHK) || - (s->proxy->options & PR_O_SMTP_CHK) || - (s->proxy->options2 & PR_O2_SSL3_CHK) || - (s->proxy->options2 & PR_O2_MYSQL_CHK) || - (s->proxy->options2 & PR_O2_PGSQL_CHK) || - (s->proxy->options2 & PR_O2_REDIS_CHK) || - (s->proxy->options2 & PR_O2_LDAP_CHK)) { + if (s->proxy->options2 & PR_O2_CHK_ANY) { int ret; const char *check_req = s->proxy->check_req; int check_len = s->proxy->check_len; @@ -783,12 +777,12 @@ static int event_srv_chk_w(int fd) * so we'll send the request, and won't wake the checker up now. */ - if (s->proxy->options2 & PR_O2_SSL3_CHK) { + if ((s->proxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) { /* SSL requires that we put Unix time in the request */ int gmt_time = htonl(date.tv_sec); memcpy(s->proxy->check_req + 11, &gmt_time, 4); } - else if (s->proxy->options & PR_O_HTTP_CHK) { + else if ((s->proxy->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK) { memcpy(trash, check_req, check_len); if (s->proxy->options2 & PR_O2_CHK_SNDST) @@ -956,7 +950,8 @@ static int event_srv_chk_r(int fd) } /* Run the checks... */ - if (s->proxy->options & PR_O_HTTP_CHK) { + switch (s->proxy->options2 & PR_O2_CHK_ANY) { + case PR_O2_HTTP_CHK: if (!done && s->check_data_len < strlen("HTTP/1.0 000\r")) goto wait_more_data; @@ -995,8 +990,9 @@ static int event_srv_chk_r(int fd) cut_crlf(desc); set_server_check_status(s, HCHK_STATUS_L7STS, desc); } - } - else if (s->proxy->options2 & PR_O2_SSL3_CHK) { + break; + + case PR_O2_SSL3_CHK: if (!done && s->check_data_len < 5) goto wait_more_data; @@ -1005,8 +1001,9 @@ static int event_srv_chk_r(int fd) set_server_check_status(s, HCHK_STATUS_L6OK, NULL); else set_server_check_status(s, HCHK_STATUS_L6RSP, NULL); - } - else if (s->proxy->options & PR_O_SMTP_CHK) { + break; + + case PR_O2_SMTP_CHK: if (!done && s->check_data_len < strlen("000\r")) goto wait_more_data; @@ -1031,8 +1028,9 @@ static int event_srv_chk_r(int fd) set_server_check_status(s, HCHK_STATUS_L7OKD, desc); else set_server_check_status(s, HCHK_STATUS_L7STS, desc); - } - else if (s->proxy->options2 & PR_O2_PGSQL_CHK) { + break; + + case PR_O2_PGSQL_CHK: if (!done && s->check_data_len < 9) goto wait_more_data; @@ -1047,8 +1045,9 @@ static int event_srv_chk_r(int fd) set_server_check_status(s, HCHK_STATUS_L7STS, desc); } - } - else if (s->proxy->options2 & PR_O2_REDIS_CHK) { + break; + + case PR_O2_REDIS_CHK: if (!done && s->check_data_len < 7) goto wait_more_data; @@ -1058,8 +1057,9 @@ static int event_srv_chk_r(int fd) else { set_server_check_status(s, HCHK_STATUS_L7STS, s->check_data); } - } - else if (s->proxy->options2 & PR_O2_MYSQL_CHK) { + break; + + case PR_O2_MYSQL_CHK: if (!done && s->check_data_len < 5) goto wait_more_data; @@ -1145,8 +1145,9 @@ static int event_srv_chk_r(int fd) set_server_check_status(s, HCHK_STATUS_L7RSP, desc); } } - } - else if (s->proxy->options2 & PR_O2_LDAP_CHK) { + break; + + case PR_O2_LDAP_CHK: if (!done && s->check_data_len < 14) goto wait_more_data; @@ -1199,11 +1200,13 @@ static int event_srv_chk_r(int fd) set_server_check_status(s, HCHK_STATUS_L7OKD, "Success"); } } - } - else { + break; + + default: /* other checks are valid if the connection succeeded anyway */ set_server_check_status(s, HCHK_STATUS_L4OK, NULL); - } + break; + } /* switch */ out_wakeup: if (s->result & SRV_CHK_ERROR) @@ -1552,7 +1555,7 @@ struct task *process_chk(struct task *t) if (!EV_FD_ISSET(fd, DIR_RD)) { set_server_check_status(s, HCHK_STATUS_L4TOUT, NULL); } else { - if (s->proxy->options2 & PR_O2_SSL3_CHK) + if ((s->proxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) set_server_check_status(s, HCHK_STATUS_L6TOUT, NULL); else /* HTTP, SMTP */ set_server_check_status(s, HCHK_STATUS_L7TOUT, NULL); diff --git a/src/frontend.c b/src/frontend.c index 558bb9ec1d..b2bc5d8a7b 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -243,7 +243,7 @@ int frontend_accept(struct session *s) fdtab[cfd].flags |= FD_FL_TCP_NOLING; if (unlikely((s->fe->mode == PR_MODE_HTTP && (s->flags & SN_MONITOR)) || - (s->fe->mode == PR_MODE_HEALTH && (s->fe->options & PR_O_HTTP_CHK)))) { + (s->fe->mode == PR_MODE_HEALTH && ((s->fe->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK)))) { /* Either we got a request from a monitoring system on an HTTP instance, * or we're in health check mode with the 'httpchk' option enabled. In * both cases, we return a fake "HTTP/1.0 200 OK" response and we exit.