From 5436afc9488531a5e2adff3a1a766af375e0922c Mon Sep 17 00:00:00 2001 From: Willy Tarreau 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 to backend 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 is already bound to all processes of + * , there is no risk of looping and we ensure to follow the shortest + * path to the destination. + * + * It is possible to set to NULL for the first call so that the function + * takes care of visiting the initial frontend in . + * + * 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