Browse Source

haproxy: patches from upstream

- [PATCH 01/13] DOC: clearly state that the "show sess" output format
- [PATCH 02/13] MINOR: stats: fix minor typo fix in
- [PATCH 03/13] MEDIUM: Improve signal handling in systemd wrapper.
- [PATCH 04/13] MINOR: Also accept SIGHUP/SIGTERM in systemd-wrapper
- [PATCH 05/13] DOC: indicate in the doc that track-sc* can wait if
- [PATCH 06/13] MEDIUM: http: enable header manipulation for 101
- [PATCH 07/13] BUG/MEDIUM: config: propagate frontend to backend
- [PATCH 08/13] MEDIUM: config: properly propagate process binding
- [PATCH 09/13] MEDIUM: config: make the frontends automatically bind
- [PATCH 10/13] MEDIUM: config: compute the exact bind-process before
- [PATCH 11/13] MEDIUM: config: only warn if stats are attached to
- [PATCH 12/13] MEDIUM: config: report it when tcp-request rules are
- [PATCH 13/13] MINOR: config: detect the case where a tcp-request

Signed-off-by: Thomas Heil <heil@terminal-consulting.de>
lilik-openwrt-22.03
Thomas Heil 10 years ago
parent
commit
85c47b0630
14 changed files with 1060 additions and 1 deletions
  1. +1
    -1
      net/haproxy/Makefile
  2. +35
    -0
      net/haproxy/patches/0001-DOC-clearly-state-that-the-show-sess-output-format-i.patch
  3. +28
    -0
      net/haproxy/patches/0002-MINOR-stats-fix-minor-typo-fix-in-stats_dump_errors_.patch
  4. +105
    -0
      net/haproxy/patches/0003-MEDIUM-Improve-signal-handling-in-systemd-wrapper.patch
  5. +48
    -0
      net/haproxy/patches/0004-MINOR-Also-accept-SIGHUP-SIGTERM-in-systemd-wrapper.patch
  6. +52
    -0
      net/haproxy/patches/0005-DOC-indicate-in-the-doc-that-track-sc-can-wait-if-da.patch
  7. +80
    -0
      net/haproxy/patches/0006-MEDIUM-http-enable-header-manipulation-for-101-respo.patch
  8. +60
    -0
      net/haproxy/patches/0007-BUG-MEDIUM-config-propagate-frontend-to-backend-proc.patch
  9. +142
    -0
      net/haproxy/patches/0008-MEDIUM-config-properly-propagate-process-binding-bet.patch
  10. +93
    -0
      net/haproxy/patches/0009-MEDIUM-config-make-the-frontends-automatically-bind-.patch
  11. +209
    -0
      net/haproxy/patches/0010-MEDIUM-config-compute-the-exact-bind-process-before-.patch
  12. +45
    -0
      net/haproxy/patches/0011-MEDIUM-config-only-warn-if-stats-are-attached-to-mul.patch
  13. +110
    -0
      net/haproxy/patches/0012-MEDIUM-config-report-it-when-tcp-request-rules-are-m.patch
  14. +52
    -0
      net/haproxy/patches/0013-MINOR-config-detect-the-case-where-a-tcp-request-con.patch

+ 1
- 1
net/haproxy/Makefile View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=haproxy
PKG_VERSION:=1.5.4
PKG_RELEASE:=01
PKG_RELEASE:=13
PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.5/src/
PKG_MD5SUM:=b027035bfd8f28326634f802c3447a34


+ 35
- 0
net/haproxy/patches/0001-DOC-clearly-state-that-the-show-sess-output-format-i.patch View File

@ -0,0 +1,35 @@
From e99d44d4bc3423b721c7f654fd1778b9822a94e3 Mon Sep 17 00:00:00 2001
From: Olivier <webmaster@ajeux.com>
Date: Fri, 5 Sep 2014 18:49:10 +0200
Subject: [PATCH 01/13] DOC: clearly state that the "show sess" output format
is not fixed
It requires to look at the code (src/dumpstats.c) since the format may
change at any moment.
(cherry picked from commit ce31e6e3baebe75a2e6f6b5c66553db8d76dff0c)
---
doc/configuration.txt | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 19df5ae..1ecf15a 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -13734,9 +13734,11 @@ show sess <id>
of "show sess" (it corresponds to the session pointer). Those information are
useless to most users but may be used by haproxy developers to troubleshoot a
complex bug. The output format is intentionally not documented so that it can
- freely evolve depending on demands. The special id "all" dumps the states of
- all sessions, which can be avoided as much as possible as it is highly CPU
- intensive and can take a lot of time.
+ freely evolve depending on demands. You may find a description of all fields
+ returned in src/dumpstats.c
+
+ The special id "all" dumps the states of all sessions, which must be avoided
+ as much as possible as it is highly CPU intensive and can take a lot of time.
show stat [<iid> <type> <sid>]
Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is
--
1.8.5.5

+ 28
- 0
net/haproxy/patches/0002-MINOR-stats-fix-minor-typo-fix-in-stats_dump_errors_.patch View File

@ -0,0 +1,28 @@
From 815d7d5c348575181874429b93b0ebdb0cf873c2 Mon Sep 17 00:00:00 2001
From: Olivier Doucet <webmaster@ajeux.com>
Date: Mon, 8 Sep 2014 11:23:00 +0200
Subject: [PATCH 02/13] MINOR: stats: fix minor typo fix in
stats_dump_errors_to_buffer()
Remove the space before the colon to match the format used in the frontend.
(cherry picked from commit 08afdcb47bc39c071787f8fc2066776e1c5e8607)
---
src/dumpstats.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 5365042..09bc7f6 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -6045,7 +6045,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si)
break;
case 1:
chunk_appendf(&trash,
- " backend %s (#%d) : invalid response\n"
+ " backend %s (#%d): invalid response\n"
" frontend %s (#%d)",
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid,
es->oe->id, es->oe->uuid);
--
1.8.5.5

+ 105
- 0
net/haproxy/patches/0003-MEDIUM-Improve-signal-handling-in-systemd-wrapper.patch View File

@ -0,0 +1,105 @@
From 62c8565cd5bbda6ac0dd818fa26922eeaef1605c Mon Sep 17 00:00:00 2001
From: Conrad Hoffmann <conrad@soundcloud.com>
Date: Mon, 28 Jul 2014 23:52:20 +0200
Subject: [PATCH 03/13] MEDIUM: Improve signal handling in systemd wrapper.
Move all code out of the signal handlers, since this is potentially
dangerous. To make sure the signal handlers behave as expected, use
sigaction() instead of signal(). That also obsoletes messing with
the signal mask after restart.
Signed-off-by: Conrad Hoffmann <conrad@soundcloud.com>
(cherry picked from commit 5b5ea9c93384da49eea0f67ebed0966d4167b17a)
---
src/haproxy-systemd-wrapper.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 529b213..90a94ce 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -22,6 +22,8 @@
#define SD_DEBUG "<7>"
#define SD_NOTICE "<5>"
+static volatile sig_atomic_t caught_signal;
+
static char *pid_file = "/run/haproxy.pid";
static int wrapper_argc;
static char **wrapper_argv;
@@ -103,7 +105,12 @@ static int read_pids(char ***pid_strv)
return read;
}
-static void sigusr2_handler(int signum __attribute__((unused)))
+static void signal_handler(int signum)
+{
+ caught_signal = signum;
+}
+
+static void do_restart(void)
{
setenv(REEXEC_FLAG, "1", 1);
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing\n");
@@ -111,7 +118,7 @@ static void sigusr2_handler(int signum __attribute__((unused)))
execv(wrapper_argv[0], wrapper_argv);
}
-static void sigint_handler(int signum __attribute__((unused)))
+static void do_shutdown(void)
{
int i, pid;
char **pid_strv = NULL;
@@ -147,25 +154,21 @@ int main(int argc, char **argv)
--argc; ++argv;
init(argc, argv);
- signal(SIGINT, &sigint_handler);
- signal(SIGUSR2, &sigusr2_handler);
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_handler = &signal_handler;
+ sigaction(SIGUSR2, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
if (getenv(REEXEC_FLAG) != NULL) {
/* We are being re-executed: restart HAProxy gracefully */
int i;
char **pid_strv = NULL;
int nb_pid = read_pids(&pid_strv);
- sigset_t sigs;
unsetenv(REEXEC_FLAG);
spawn_haproxy(pid_strv, nb_pid);
- /* Unblock SIGUSR2 which was blocked by the signal handler
- * before re-exec */
- sigprocmask(SIG_BLOCK, NULL, &sigs);
- sigdelset(&sigs, SIGUSR2);
- sigprocmask(SIG_SETMASK, &sigs, NULL);
-
for (i = 0; i < nb_pid; ++i)
free(pid_strv[i]);
free(pid_strv);
@@ -176,8 +179,16 @@ int main(int argc, char **argv)
}
status = -1;
- while (-1 != wait(&status) || errno == EINTR)
- ;
+ while (-1 != wait(&status) || errno == EINTR) {
+ if (caught_signal == SIGUSR2) {
+ caught_signal = 0;
+ do_restart();
+ }
+ else if (caught_signal == SIGINT) {
+ caught_signal = 0;
+ do_shutdown();
+ }
+ }
fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: exit, haproxy RC=%d\n",
status);
--
1.8.5.5

+ 48
- 0
net/haproxy/patches/0004-MINOR-Also-accept-SIGHUP-SIGTERM-in-systemd-wrapper.patch View File

@ -0,0 +1,48 @@
From 6bb7bf7949dd019403b65f400c4b3d0d8589327b Mon Sep 17 00:00:00 2001
From: Matt Robenolt <matt@ydekproductions.com>
Date: Thu, 11 Sep 2014 05:19:30 +0000
Subject: [PATCH 04/13] MINOR: Also accept SIGHUP/SIGTERM in systemd-wrapper
My proposal is to let haproxy-systemd-wrapper also accept normal
SIGHUP/SIGTERM signals to play nicely with other process managers
besides just systemd. In my use case, this will be for using with
runit which has to ability to change the signal used for a
"reload" or "stop" command. It also might be worth renaming this
bin to just haproxy-wrapper or something of that sort to separate
itself away from systemd. But that's a different discussion. :)
(cherry picked from commit c54bdd2a118161b4dc36963b4201edfa7341dadb)
---
src/haproxy-systemd-wrapper.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c
index 90a94ce..cc8baa8 100644
--- a/src/haproxy-systemd-wrapper.c
+++ b/src/haproxy-systemd-wrapper.c
@@ -158,7 +158,9 @@ int main(int argc, char **argv)
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = &signal_handler;
sigaction(SIGUSR2, &sa, NULL);
+ sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
if (getenv(REEXEC_FLAG) != NULL) {
/* We are being re-executed: restart HAProxy gracefully */
@@ -180,11 +182,11 @@ int main(int argc, char **argv)
status = -1;
while (-1 != wait(&status) || errno == EINTR) {
- if (caught_signal == SIGUSR2) {
+ if (caught_signal == SIGUSR2 || caught_signal == SIGHUP) {
caught_signal = 0;
do_restart();
}
- else if (caught_signal == SIGINT) {
+ else if (caught_signal == SIGINT || caught_signal == SIGTERM) {
caught_signal = 0;
do_shutdown();
}
--
1.8.5.5

+ 52
- 0
net/haproxy/patches/0005-DOC-indicate-in-the-doc-that-track-sc-can-wait-if-da.patch View File

@ -0,0 +1,52 @@
From 531485c08ffb15b939a28ecf47090e4c93341d1b Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 15:48:15 +0200
Subject: [PATCH 05/13] DOC: indicate in the doc that track-sc* can wait if
data are missing
Since commit 1b71eb5 ("BUG/MEDIUM: counters: fix track-sc* to wait on
unstable contents"), we don't need the "if HTTP" anymore. But the doc
was not updated to reflect this.
Since this change was backported to 1.5, this doc update should be
backported as well.
(cherry picked from commit 4d54c7ca0286588de5060acce9aff8aa9645bb98)
---
doc/configuration.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 1ecf15a..3c75c92 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -7470,9 +7470,9 @@ tcp-request content <action> [{if | unless} <condition>]
contents will always be immediately present when the rule is evaluated first.
Tracking layer7 information is also possible provided that the information
- are present when the rule is processed. The current solution for making the
- rule engine wait for such information is to set an inspect delay and to
- condition its execution with an ACL relying on such information.
+ are present when the rule is processed. The rule processing engine is able to
+ wait until the inspect delay expires when the data to be tracked is not yet
+ available.
Example:
# Accept HTTP requests containing a Host header saying "example.com"
@@ -7497,12 +7497,12 @@ tcp-request content <action> [{if | unless} <condition>]
Example:
# Track the last IP from X-Forwarded-For
tcp-request inspect-delay 10s
- tcp-request content track-sc0 hdr(x-forwarded-for,-1) if HTTP
+ tcp-request content track-sc0 hdr(x-forwarded-for,-1)
Example:
# track request counts per "base" (concatenation of Host+URL)
tcp-request inspect-delay 10s
- tcp-request content track-sc0 base table req-rate if HTTP
+ tcp-request content track-sc0 base table req-rate
Example: track per-frontend and per-backend counters, block abusers at the
frontend when the backend detects abuse.
--
1.8.5.5

+ 80
- 0
net/haproxy/patches/0006-MEDIUM-http-enable-header-manipulation-for-101-respo.patch View File

@ -0,0 +1,80 @@
From 0cb4b899d370b9d04b3457a1d75dbd658c1a1646 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 10:40:38 +0200
Subject: [PATCH 06/13] MEDIUM: http: enable header manipulation for 101
responses
Ryan Brock reported that server stickiness did not work for WebSocket
because the cookies and headers are not modified on 1xx responses. He
found that his browser correctly presents the cookies learned on 101
responses, which was not specifically defined in the WebSocket spec,
nor in the cookie spec. 101 is a very special case. Being part of 1xx,
it's an interim response. But within 1xx, it's special because it's
the last HTTP/1 response that transits on the wire, which is different
from 100 or 102 which may appear multiple times. So in that sense, we
can consider it as a final response regarding HTTP/1, and it makes
sense to allow header processing there. Note that we still ensure not
to mangle the Connection header, which is critical for HTTP upgrade to
continue to work smoothly with agents that are a bit picky about what
tokens are found there.
The rspadd rules are now processed for 101 responses as well, but the
cache-control checks are not performed (since no body is delivered).
Ryan confirmed that this patch works for him.
It would make sense to backport it to 1.5 given that it improves end
user experience on WebSocket servers.
(cherry picked from commit ce730de86719d0b5079dd8b0843559e4ff0a1ecc)
---
src/proto_http.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/proto_http.c b/src/proto_http.c
index 4d27b2c..7e35c8b 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -6249,7 +6249,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit,
/* add response headers from the rule sets in the same order */
list_for_each_entry(wl, &rule_set->rsp_add, list) {
- if (txn->status < 200)
+ if (txn->status < 200 && txn->status != 101)
break;
if (wl->cond) {
int ret = acl_exec_cond(wl->cond, px, s, txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
@@ -6270,7 +6270,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit,
}
/* OK that's all we can do for 1xx responses */
- if (unlikely(txn->status < 200))
+ if (unlikely(txn->status < 200 && txn->status != 101))
goto skip_header_mangling;
/*
@@ -6283,7 +6283,7 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit,
/*
* Check for cache-control or pragma headers if required.
*/
- if ((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC))
+ if (((s->be->options & PR_O_CHK_CACHE) || (s->be->ck_opts & PR_CK_NOC)) && txn->status != 101)
check_response_for_cacheability(s, rep);
/*
@@ -6399,9 +6399,11 @@ int http_process_res_common(struct session *s, struct channel *rep, int an_bit,
* Adjust "Connection: close" or "Connection: keep-alive" if needed.
* If an "Upgrade" token is found, the header is left untouched in order
* not to have to deal with some client bugs : some of them fail an upgrade
- * if anything but "Upgrade" is present in the Connection header.
+ * if anything but "Upgrade" is present in the Connection header. We don't
+ * want to touch any 101 response either since it's switching to another
+ * protocol.
*/
- if (!(txn->flags & TX_HDR_CONN_UPG) &&
+ if ((txn->status != 101) && !(txn->flags & TX_HDR_CONN_UPG) &&
(((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) ||
((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
(s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL))) {
--
1.8.5.5

+ 60
- 0
net/haproxy/patches/0007-BUG-MEDIUM-config-propagate-frontend-to-backend-proc.patch View File

@ -0,0 +1,60 @@
From b53934eec71ab34eb3762a89cec326360a5b0bc5 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 11:31:31 +0200
Subject: [PATCH 07/13] BUG/MEDIUM: config: propagate frontend to backend
process binding again.
This basically reverts 3507d5d ("MEDIUM: proxy: only adjust the backend's
bind-process when already set"). It was needed during the transition to
the new process binding method but is causing trouble now because frontend
to backend binding is not properly propagated.
This fix should be backported to 1.5.
(cherry picked from commit 8a3478ed31a16904f45178c153f4649faf6de675)
---
src/cfgparse.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 943eba0..5288600 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6165,9 +6165,8 @@ int check_config_validity()
/* we force the backend to be present on at least all of
* the frontend's processes.
*/
- if (target->bind_proc)
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
+ target->bind_proc = curproxy->bind_proc ?
+ (target->bind_proc | curproxy->bind_proc) : 0;
/* Emit a warning if this proxy also has some servers */
if (curproxy->srv) {
@@ -6203,9 +6202,8 @@ int check_config_validity()
/* we force the backend to be present on at least all of
* the frontend's processes.
*/
- if (target->bind_proc)
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
+ target->bind_proc = curproxy->bind_proc ?
+ (target->bind_proc | curproxy->bind_proc) : 0;
}
}
}
@@ -6257,9 +6255,8 @@ int check_config_validity()
/* we force the backend to be present on at least all of
* the frontend's processes.
*/
- if (target->bind_proc)
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
+ target->bind_proc = curproxy->bind_proc ?
+ (target->bind_proc | curproxy->bind_proc) : 0;
}
}
--
1.8.5.5

+ 142
- 0
net/haproxy/patches/0008-MEDIUM-config-properly-propagate-process-binding-bet.patch View File

@ -0,0 +1,142 @@
From 5436afc9488531a5e2adff3a1a766af375e0922c Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 12:17:36 +0200
Subject: [PATCH 08/13] MEDIUM: config: properly propagate process binding
between proxies
We now recursively propagate the bind-process values between frontends
and backends instead of doing it during name resolving. This ensures
that we're able to properly propagate all the bind-process directives
even across "listen" instances, which are not perfectly covered at the
moment, depending on the declaration order.
(cherry picked from commit 64ab6077b768ee02b04a36b30ee195639a2fabc1)
---
src/cfgparse.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 65 insertions(+), 16 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 5288600..b9853ef 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -5932,6 +5932,64 @@ int readcfgfile(const char *file)
return err_code;
}
+/* This function propagates processes from frontend <from> to backend <to> so
+ * that it is always guaranteed that a backend pointed to by a frontend is
+ * bound to all of its processes. After that, if the target is a "listen"
+ * instance, the function recursively descends the target's own targets along
+ * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
+ * checked first to ensure that <to> is already bound to all processes of
+ * <from>, there is no risk of looping and we ensure to follow the shortest
+ * path to the destination.
+ *
+ * It is possible to set <to> to NULL for the first call so that the function
+ * takes care of visiting the initial frontend in <from>.
+ *
+ * It is important to note that the function relies on the fact that all names
+ * have already been resolved.
+ */
+void propagate_processes(struct proxy *from, struct proxy *to)
+{
+ struct switching_rule *rule;
+ struct hdr_exp *exp;
+
+ if (to) {
+ /* check whether we need to go down */
+ if (from->bind_proc &&
+ (from->bind_proc & to->bind_proc) == from->bind_proc)
+ return;
+
+ if (!from->bind_proc && !to->bind_proc)
+ return;
+
+ to->bind_proc = from->bind_proc ?
+ (to->bind_proc | from->bind_proc) : 0;
+
+ /* now propagate down */
+ from = to;
+ }
+
+ if (!from->cap & PR_CAP_FE)
+ return;
+
+ /* default_backend */
+ if (from->defbe.be)
+ propagate_processes(from, from->defbe.be);
+
+ /* use_backend */
+ list_for_each_entry(rule, &from->switching_rules, list) {
+ to = rule->be.backend;
+ propagate_processes(from, to);
+ }
+
+ /* reqsetbe */
+ for (exp = from->req_exp; exp != NULL; exp = exp->next) {
+ if (exp->action != ACT_SETBE)
+ continue;
+ to = (struct proxy *)exp->replace;
+ propagate_processes(from, to);
+ }
+}
+
/*
* Returns the error code, 0 if OK, or any combination of :
* - ERR_ABORT: must abort ASAP
@@ -6162,11 +6220,6 @@ int check_config_validity()
} else {
free(curproxy->defbe.name);
curproxy->defbe.be = target;
- /* we force the backend to be present on at least all of
- * the frontend's processes.
- */
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
/* Emit a warning if this proxy also has some servers */
if (curproxy->srv) {
@@ -6199,11 +6252,6 @@ int check_config_validity()
} else {
free((void *)exp->replace);
exp->replace = (const char *)target;
- /* we force the backend to be present on at least all of
- * the frontend's processes.
- */
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
}
}
}
@@ -6252,15 +6300,10 @@ int check_config_validity()
} else {
free((void *)rule->be.name);
rule->be.backend = target;
- /* we force the backend to be present on at least all of
- * the frontend's processes.
- */
- target->bind_proc = curproxy->bind_proc ?
- (target->bind_proc | curproxy->bind_proc) : 0;
}
}
- /* find the target proxy for 'use_backend' rules */
+ /* find the target server for 'use_server' rules */
list_for_each_entry(srule, &curproxy->server_rules, list) {
struct server *target = findserver(curproxy, srule->srv.name);
@@ -7131,6 +7174,12 @@ out_uri_auth_compat:
}
}
+ /* At this point, target names have already been resolved */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->cap & PR_CAP_FE)
+ propagate_processes(curproxy, NULL);
+ }
+
/* automatically compute fullconn if not set. We must not do it in the
* loop above because cross-references are not yet fully resolved.
*/
--
1.8.5.5

+ 93
- 0
net/haproxy/patches/0009-MEDIUM-config-make-the-frontends-automatically-bind-.patch View File

@ -0,0 +1,93 @@
From e56c4f1f76c6731a5a0f4b128540071cffeb1951 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 13:21:03 +0200
Subject: [PATCH 09/13] MEDIUM: config: make the frontends automatically bind
to the listeners' processes
When a frontend does not have any bind-process directive, make it
automatically bind to the union of all of its listeners' processes
instead of binding to all processes. That will make it possible to
have the expected behaviour without having to explicitly specify a
bind-process directive.
Note that if the listeners are not bound to a specific process, the
default is still to bind to all processes.
This change could be backported to 1.5 as it simplifies process
management, and was planned to be done during the 1.5 development phase.
(cherry picked from commit b369a045d545b41ef2b250bf747caf83c97e0ca8)
---
doc/configuration.txt | 4 ++++
src/cfgparse.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 3c75c92..1e32057 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1905,6 +1905,10 @@ bind-process [ all | odd | even | <number 1-64>[-<number 1-64>] ] ...
Each "bind" line may further be limited to a subset of the proxy's processes,
please consult the "process" bind keyword in section 5.1.
+ When a frontend has no explicit "bind-process" line, it tries to bind to all
+ the processes referenced by its "bind" lines. That means that frontends can
+ easily adapt to their listeners' processes.
+
If some backends are referenced by frontends bound to other processes, the
backend automatically inherits the frontend's processes.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index b9853ef..d53f69e 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -7175,11 +7175,47 @@ out_uri_auth_compat:
}
/* At this point, target names have already been resolved */
+
+ /* Make each frontend inherit bind-process from its listeners when not specified. */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->bind_proc)
+ continue;
+
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
+ unsigned long mask;
+
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
+ curproxy->bind_proc |= mask;
+ }
+
+ if (!curproxy->bind_proc)
+ curproxy->bind_proc = ~0UL;
+ }
+
+ if (global.stats_fe) {
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
+ unsigned long mask;
+
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
+ global.stats_fe->bind_proc |= mask;
+ }
+ if (!global.stats_fe->bind_proc)
+ global.stats_fe->bind_proc = ~0UL;
+ }
+
+ /* propagate bindings from frontends to backends */
for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
if (curproxy->cap & PR_CAP_FE)
propagate_processes(curproxy, NULL);
}
+ /* Bind each unbound backend to all processes when not specified. */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->bind_proc)
+ continue;
+ curproxy->bind_proc = ~0UL;
+ }
+
/* automatically compute fullconn if not set. We must not do it in the
* loop above because cross-references are not yet fully resolved.
*/
--
1.8.5.5

+ 209
- 0
net/haproxy/patches/0010-MEDIUM-config-compute-the-exact-bind-process-before-.patch View File

@ -0,0 +1,209 @@
From 91b00c2194b728ccd61133cca83f03de3650b674 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 13:41:21 +0200
Subject: [PATCH 10/13] MEDIUM: config: compute the exact bind-process before
listener's maxaccept
This is a continuation of previous patch, the listener's maxaccept is divided
by the number of processes, so it's best if we can swap the two blocks so that
the number of processes is already known when computing the maxaccept value.
(cherry picked from commit 419ead8eca9237f9cc2ec32630d96fde333282ee)
---
src/cfgparse.c | 156 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 81 insertions(+), 75 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index d53f69e..f3907bf 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6042,12 +6042,11 @@ int check_config_validity()
proxy = next;
}
- while (curproxy != NULL) {
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
struct switching_rule *rule;
struct server_rule *srule;
struct sticking_rule *mrule;
struct tcp_rule *trule;
- struct listener *listener;
unsigned int next_id;
int nbproc;
@@ -6115,14 +6114,6 @@ int check_config_validity()
}
}
- /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
- * We now check how many processes the proxy will effectively run on.
- */
-
- nbproc = global.nbproc;
- if (curproxy->bind_proc)
- nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
-
if (global.nbproc > 1 && curproxy->table.peers.name) {
Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
curproxy->id);
@@ -7005,6 +6996,86 @@ out_uri_auth_compat:
if (curproxy->options2 & PR_O2_RDPC_PRST)
curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
}
+ }
+
+ /***********************************************************/
+ /* At this point, target names have already been resolved. */
+ /***********************************************************/
+
+ /* Check multi-process mode compatibility */
+
+ if (global.nbproc > 1 && global.stats_fe) {
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
+ unsigned long mask;
+
+ mask = nbits(global.nbproc);
+ if (global.stats_fe->bind_proc)
+ mask &= global.stats_fe->bind_proc;
+
+ if (bind_conf->bind_proc)
+ mask &= bind_conf->bind_proc;
+
+ /* stop here if more than one process is used */
+ if (popcount(mask) > 1)
+ break;
+ }
+ if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
+ Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
+ }
+ }
+
+ /* Make each frontend inherit bind-process from its listeners when not specified. */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->bind_proc)
+ continue;
+
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
+ unsigned long mask;
+
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
+ curproxy->bind_proc |= mask;
+ }
+
+ if (!curproxy->bind_proc)
+ curproxy->bind_proc = ~0UL;
+ }
+
+ if (global.stats_fe) {
+ list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
+ unsigned long mask;
+
+ mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
+ global.stats_fe->bind_proc |= mask;
+ }
+ if (!global.stats_fe->bind_proc)
+ global.stats_fe->bind_proc = ~0UL;
+ }
+
+ /* propagate bindings from frontends to backends */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->cap & PR_CAP_FE)
+ propagate_processes(curproxy, NULL);
+ }
+
+ /* Bind each unbound backend to all processes when not specified. */
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ if (curproxy->bind_proc)
+ continue;
+ curproxy->bind_proc = ~0UL;
+ }
+
+ /*******************************************************/
+ /* At this step, all proxies have a non-null bind_proc */
+ /*******************************************************/
+
+ /* perform the final checks before creating tasks */
+
+ for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
+ struct listener *listener;
+ unsigned int next_id;
+ int nbproc;
+
+ nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
#ifdef USE_OPENSSL
/* Configure SSL for each bind line.
@@ -7149,71 +7220,6 @@ out_uri_auth_compat:
curproxy->id);
cfgerr++;
}
-
- curproxy = curproxy->next;
- }
-
- /* Check multi-process mode compatibility */
- if (global.nbproc > 1 && global.stats_fe) {
- list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
- unsigned long mask;
-
- mask = nbits(global.nbproc);
- if (global.stats_fe->bind_proc)
- mask &= global.stats_fe->bind_proc;
-
- if (bind_conf->bind_proc)
- mask &= bind_conf->bind_proc;
-
- /* stop here if more than one process is used */
- if (popcount(mask) > 1)
- break;
- }
- if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
- Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
- }
- }
-
- /* At this point, target names have already been resolved */
-
- /* Make each frontend inherit bind-process from its listeners when not specified. */
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
- if (curproxy->bind_proc)
- continue;
-
- list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
- unsigned long mask;
-
- mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
- curproxy->bind_proc |= mask;
- }
-
- if (!curproxy->bind_proc)
- curproxy->bind_proc = ~0UL;
- }
-
- if (global.stats_fe) {
- list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
- unsigned long mask;
-
- mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
- global.stats_fe->bind_proc |= mask;
- }
- if (!global.stats_fe->bind_proc)
- global.stats_fe->bind_proc = ~0UL;
- }
-
- /* propagate bindings from frontends to backends */
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
- if (curproxy->cap & PR_CAP_FE)
- propagate_processes(curproxy, NULL);
- }
-
- /* Bind each unbound backend to all processes when not specified. */
- for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
- if (curproxy->bind_proc)
- continue;
- curproxy->bind_proc = ~0UL;
}
/* automatically compute fullconn if not set. We must not do it in the
--
1.8.5.5

+ 45
- 0
net/haproxy/patches/0011-MEDIUM-config-only-warn-if-stats-are-attached-to-mul.patch View File

@ -0,0 +1,45 @@
From 036a83e9c300a42386cd378022420e52a43b314f Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 15:11:04 +0200
Subject: [PATCH 11/13] MEDIUM: config: only warn if stats are attached to
multi-process bind directives
Some users want to have a stats frontend with one line per process, but while
100% valid and safe, the config parser emits a warning. Relax this check to
ensure that the warning is only emitted if at least one of the listeners is
bound to multiple processes, or if the directive is placed in a backend called
from multiple processes (since in this case we don't know if it's safe).
(cherry picked from commit eb791e03b5c5abfddb24a439fa6434788db026b7)
---
src/cfgparse.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index f3907bf..5668393 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -7189,8 +7189,19 @@ out_uri_auth_compat:
if (nbproc > 1) {
if (curproxy->uri_auth) {
- Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
- curproxy->id);
+ int count, maxproc = 0;
+
+ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
+ count = popcount(bind_conf->bind_proc);
+ if (count > maxproc)
+ maxproc = count;
+ }
+ /* backends have 0, frontends have 1 or more */
+ if (maxproc != 1)
+ Warning("Proxy '%s': in multi-process mode, stats will be"
+ " limited to process assigned to the current request.\n",
+ curproxy->id);
+
if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
curproxy->id);
--
1.8.5.5

+ 110
- 0
net/haproxy/patches/0012-MEDIUM-config-report-it-when-tcp-request-rules-are-m.patch View File

@ -0,0 +1,110 @@
From 8b3c808c37dd5672f87e7b61085295e1316a6694 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 15:39:51 +0200
Subject: [PATCH 12/13] MEDIUM: config: report it when tcp-request rules are
misplaced
A config where a tcp-request rule appears after an http-request rule
might seem valid but it is not. So let's report a warning about this
since this case is hard to detect by the naked eye.
(cherry picked from commit 3986b9c14037f446f5f5bec6207a39e1bd753fae)
---
include/common/cfgparse.h | 2 ++
src/cfgparse.c | 38 ++++++++++++++++++++++++++++++++++++++
src/proto_tcp.c | 4 ++++
3 files changed, 44 insertions(+)
diff --git a/include/common/cfgparse.h b/include/common/cfgparse.h
index 80310ae..86a0035 100644
--- a/include/common/cfgparse.h
+++ b/include/common/cfgparse.h
@@ -73,6 +73,8 @@ int check_config_validity();
int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err);
int cfg_register_section(char *section_name,
int (*section_parser)(const char *, int, char **, int));
+int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg);
+int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg);
/*
* Sends a warning if proxy <proxy> does not have at least one of the
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 5668393..9ff44e9 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -317,6 +317,19 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
return 0;
}
+/* Report a warning if a rule is placed after a 'tcp-request content' rule.
+ * Return 1 if the warning has been emitted, otherwise 0.
+ */
+int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
+{
+ if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
+ Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
+ file, line, arg);
+ return 1;
+ }
+ return 0;
+}
+
/* Report a warning if a rule is placed after a 'block' rule.
* Return 1 if the warning has been emitted, otherwise 0.
*/
@@ -408,6 +421,31 @@ int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line
return 0;
}
+/* report a warning if a "tcp request connection" rule is dangerously placed */
+int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
+{
+ return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
+ warnif_rule_after_block(proxy, file, line, arg) ||
+ warnif_rule_after_http_req(proxy, file, line, arg) ||
+ warnif_rule_after_reqxxx(proxy, file, line, arg) ||
+ warnif_rule_after_reqadd(proxy, file, line, arg) ||
+ warnif_rule_after_redirect(proxy, file, line, arg) ||
+ warnif_rule_after_use_backend(proxy, file, line, arg) ||
+ warnif_rule_after_use_server(proxy, file, line, arg);
+}
+
+/* report a warning if a "tcp request content" rule is dangerously placed */
+int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
+{
+ return warnif_rule_after_block(proxy, file, line, arg) ||
+ warnif_rule_after_http_req(proxy, file, line, arg) ||
+ warnif_rule_after_reqxxx(proxy, file, line, arg) ||
+ warnif_rule_after_reqadd(proxy, file, line, arg) ||
+ warnif_rule_after_redirect(proxy, file, line, arg) ||
+ warnif_rule_after_use_backend(proxy, file, line, arg) ||
+ warnif_rule_after_use_server(proxy, file, line, arg);
+}
+
/* report a warning if a block rule is dangerously placed */
int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
{
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 72dc92b..940c3f1 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1711,6 +1711,8 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
warn++;
}
+ /* the following function directly emits the warning */
+ warnif_misplaced_tcp_cont(curpx, file, line, args[0]);
LIST_ADDQ(&curpx->tcp_req.inspect_rules, &rule->list);
}
else if (strcmp(args[1], "connection") == 0) {
@@ -1754,6 +1756,8 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
warn++;
}
+ /* the following function directly emits the warning */
+ warnif_misplaced_tcp_conn(curpx, file, line, args[0]);
LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list);
}
else {
--
1.8.5.5

+ 52
- 0
net/haproxy/patches/0013-MINOR-config-detect-the-case-where-a-tcp-request-con.patch View File

@ -0,0 +1,52 @@
From 7fc7ebd5785629074297ee324b22e0aee9ad00f9 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 16 Sep 2014 16:21:19 +0200
Subject: [PATCH 13/13] MINOR: config: detect the case where a tcp-request
content rule has no inspect-delay
If a frontend has any tcp-request content rule relying on request contents
without any inspect delay, we now emit a warning as this will randomly match.
This can be backported to 1.5 as it reduces the support effort.
(cherry picked from commit e42bd96d0acc38ea7c546c8de8115ffd1dd6c3f3)
---
src/cfgparse.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9ff44e9..f723a3a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6998,6 +6998,29 @@ out_uri_auth_compat:
newsrv = newsrv->next;
}
+ /* check if we have a frontend with "tcp-request content" looking at L7
+ * with no inspect-delay
+ */
+ if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
+ list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
+ if (trule->action == TCP_ACT_CAPTURE &&
+ !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
+ break;
+ if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
+ !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
+ break;
+ }
+
+ if (&trule->list != &curproxy->tcp_req.inspect_rules) {
+ Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
+ " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
+ " This means that these rules will randomly find their contents. This can be fixed by"
+ " setting the tcp-request inspect-delay.\n",
+ proxy_type_str(curproxy), curproxy->id);
+ err_code |= ERR_WARN;
+ }
+ }
+
if (curproxy->cap & PR_CAP_FE) {
if (!curproxy->accept)
curproxy->accept = frontend_accept;
--
1.8.5.5

Loading…
Cancel
Save