From: Christopher Faulet Date: Thu, 4 Jul 2024 07:58:12 +0000 (+0200) Subject: MEDIUM: proxy/spoe: Add a SPOP mode X-Git-Tag: v3.1-dev4~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1538c4aa820e17b885f34862329512bffcd5e15e;p=thirdparty%2Fhaproxy.git MEDIUM: proxy/spoe: Add a SPOP mode The SPOE was significantly lightened. It is now possible to refactor it to use a dedicated multiplexer. The first step is to add a SPOP mode for proxies. The corresponding multiplexer mode is also added. For now, there is no SPOP multiplexer, so it is only declarative. But at the end, the SPOP multiplexer will be automatically selected for servers inside a SPOP backend. The related issue is #2502. --- diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 83969da06e..dba52fa320 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -306,7 +306,8 @@ enum proto_proxy_mode { PROTO_MODE_NONE = 0, PROTO_MODE_TCP = 1 << 0, // must not be changed! PROTO_MODE_HTTP = 1 << 1, // must not be changed! - PROTO_MODE_ANY = PROTO_MODE_TCP | PROTO_MODE_HTTP, + PROTO_MODE_SPOP = 1 << 2, // must not be changed! + PROTO_MODE_ANY = PROTO_MODE_TCP | PROTO_MODE_HTTP | PROTO_MODE_SPOP, }; enum proto_proxy_side { diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index aa61cc71af..dc187eb918 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -722,10 +722,9 @@ static inline int conn_pr_mode_to_proto_mode(int proxy_mode) { int mode; - /* for now we only support TCP and HTTP proto_modes, so we - * consider that if it's not HTTP, then it's TCP - */ - mode = 1 << (proxy_mode == PR_MODE_HTTP); + mode = ((proxy_mode == PR_MODE_HTTP) ? PROTO_MODE_HTTP : + (proxy_mode == PR_MODE_SPOP) ? PROTO_MODE_SPOP : + PROTO_MODE_TCP); return mode; } diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 262dc11d5e..9bafb22e5c 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -52,6 +52,7 @@ enum pr_mode { PR_MODE_CLI, PR_MODE_SYSLOG, PR_MODE_PEERS, + PR_MODE_SPOP, PR_MODES } __attribute__((packed)); diff --git a/include/haproxy/tcpcheck.h b/include/haproxy/tcpcheck.h index 55c564a20c..95244a5212 100644 --- a/include/haproxy/tcpcheck.h +++ b/include/haproxy/tcpcheck.h @@ -119,6 +119,20 @@ static inline void action_kw_tcp_check_build_list(struct buffer *chk) action_build_list(&tcp_check_keywords.list, chk); } +/* + * Map tcpcheck rules type (TCPCHK_RULES_*) to equivalent proto_proxy_mode (PROTO_MODE_*) + */ +static inline int tcpchk_rules_type_to_proto_mode(int tcpchk_rules_type) +{ + int mode; + + mode = (((tcpchk_rules_type & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) ? PROTO_MODE_HTTP : + (((tcpchk_rules_type & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_SPOP_CHK) ? PROTO_MODE_SPOP : + PROTO_MODE_TCP)); + + return mode; +} + #endif /* _HAPROXY_TCPCHECK_H */ /* diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 1f6ddc2adc..2beb9377b0 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -545,6 +545,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) if (strcmp(args[1], "http") == 0) curproxy->mode = PR_MODE_HTTP; else if (strcmp(args[1], "tcp") == 0) curproxy->mode = PR_MODE_TCP; else if (strcmp(args[1], "log") == 0 && (curproxy->cap & PR_CAP_BE)) curproxy->mode = PR_MODE_SYSLOG; + else if (strcmp(args[1], "spop") == 0 && (curproxy->cap & PR_CAP_BE)) curproxy->mode = PR_MODE_SPOP; else if (strcmp(args[1], "health") == 0) { ha_alert("parsing [%s:%d] : 'mode health' doesn't exist anymore. Please use 'http-request return status 200' instead.\n", file, linenum); err_code |= ERR_ALERT | ERR_FATAL; diff --git a/src/cfgparse.c b/src/cfgparse.c index 2434de2cb6..990d2a4880 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2977,6 +2977,11 @@ init_proxies_list_stage1: cfgerr += proxy_cfg_ensure_no_http(curproxy); break; + case PR_MODE_SPOP: + cfgerr += proxy_cfg_ensure_no_http(curproxy); + cfgerr += proxy_cfg_ensure_no_log(curproxy); + break; + case PR_MODE_PEERS: case PR_MODES: /* should not happen, bug gcc warn missing switch statement */ diff --git a/src/check.c b/src/check.c index 64464c4f4f..40d403b272 100644 --- a/src/check.c +++ b/src/check.c @@ -1826,12 +1826,14 @@ int init_srv_check(struct server *srv) */ if (srv->mux_proto && !srv->check.mux_proto && ((srv->mux_proto->mode == PROTO_MODE_HTTP && check_type == TCPCHK_RULES_HTTP_CHK) || + (srv->mux_proto->mode == PROTO_MODE_SPOP && check_type == TCPCHK_RULES_SPOP_CHK) || (srv->mux_proto->mode == PROTO_MODE_TCP && check_type != TCPCHK_RULES_HTTP_CHK))) { srv->check.mux_proto = srv->mux_proto; } /* test that check proto is valid if explicitly defined */ else if (srv->check.mux_proto && ((srv->check.mux_proto->mode == PROTO_MODE_HTTP && check_type != TCPCHK_RULES_HTTP_CHK) || + (srv->check.mux_proto->mode == PROTO_MODE_SPOP && check_type != TCPCHK_RULES_SPOP_CHK) || (srv->check.mux_proto->mode == PROTO_MODE_TCP && check_type == TCPCHK_RULES_HTTP_CHK))) { ha_alert("config: %s '%s': server '%s' uses an incompatible MUX protocol for the selected check type\n", proxy_type_str(srv->proxy), srv->proxy->id, srv->id); diff --git a/src/connection.c b/src/connection.c index 3fedad9a58..668e626f5e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -271,12 +272,7 @@ int conn_install_mux_fe(struct connection *conn, void *ctx) struct ist mux_proto; const char *alpn_str = NULL; int alpn_len = 0; - int mode; - - if (bind_conf->frontend->mode == PR_MODE_HTTP) - mode = PROTO_MODE_HTTP; - else - mode = PROTO_MODE_TCP; + int mode = conn_pr_mode_to_proto_mode(bind_conf->frontend->mode); conn_get_alpn(conn, &alpn_str, &alpn_len); mux_proto = ist2(alpn_str, alpn_len); @@ -326,12 +322,7 @@ int conn_install_mux_be(struct connection *conn, void *ctx, struct session *sess struct ist mux_proto; const char *alpn_str = NULL; int alpn_len = 0; - int mode; - - if (prx->mode == PR_MODE_HTTP) - mode = PROTO_MODE_HTTP; - else - mode = PROTO_MODE_TCP; + int mode = conn_pr_mode_to_proto_mode(prx->mode); conn_get_alpn(conn, &alpn_str, &alpn_len); mux_proto = ist2(alpn_str, alpn_len); @@ -369,12 +360,7 @@ int conn_install_mux_chk(struct connection *conn, void *ctx, struct session *ses struct ist mux_proto; const char *alpn_str = NULL; int alpn_len = 0; - int mode; - - if ((check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) - mode = PROTO_MODE_HTTP; - else - mode = PROTO_MODE_TCP; + int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck_rules->flags); conn_get_alpn(conn, &alpn_str, &alpn_len); mux_proto = ist2(alpn_str, alpn_len); @@ -1811,6 +1797,8 @@ void list_mux_proto(FILE *out) mode = "TCP"; else if (item->mode == PROTO_MODE_HTTP) mode = "HTTP"; + else if (item->mode == PROTO_MODE_SPOP) + mode = "SPOP"; else mode = "NONE"; diff --git a/src/extcheck.c b/src/extcheck.c index 05c53ff9f6..f01931b9d9 100644 --- a/src/extcheck.c +++ b/src/extcheck.c @@ -348,6 +348,7 @@ int prepare_external_check(struct check *check) case PR_MODE_PEERS: svmode = "peers"; break; case PR_MODE_HTTP: svmode = (s->mux_proto) ? s->mux_proto->token.ptr : "h1"; break; case PR_MODE_TCP: svmode = "tcp"; break; + case PR_MODE_SPOP: svmode = "spop"; break; /* all valid cases must be enumerated above, below is to avoid a warning */ case PR_MODES: svmode = "?"; break; } diff --git a/src/fcgi-app.c b/src/fcgi-app.c index 5790cebcf8..b3a9b7c595 100644 --- a/src/fcgi-app.c +++ b/src/fcgi-app.c @@ -642,7 +642,7 @@ static int cfg_fcgi_apps_postparser() struct fcgi_flt_conf *fcgi_conf = find_px_fcgi_conf(px); int nb_fcgi_srv = 0; - if (px->mode == PR_MODE_TCP && fcgi_conf) { + if (px->mode != PR_MODE_HTTP && fcgi_conf) { ha_alert("proxy '%s': FCGI application cannot be used in non-HTTP mode.\n", px->id); err_code |= ERR_ALERT | ERR_FATAL; diff --git a/src/proxy.c b/src/proxy.c index 10cb780257..da589a28e1 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -431,6 +431,8 @@ const char *proxy_mode_str(int mode) { return "syslog"; else if (mode == PR_MODE_PEERS) return "peers"; + else if (mode == PR_MODE_SPOP) + return "spop"; else return "unknown"; } @@ -1881,11 +1883,11 @@ void proxy_cond_disable(struct proxy *p) * peers, etc) we must not report them at all as they're not really on * the data plane but on the control plane. */ - if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP || p->mode == PR_MODE_SYSLOG) && !(p->cap & PR_CAP_INT)) + if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP || p->mode == PR_MODE_SYSLOG || p->mode == PR_MODE_SPOP) && !(p->cap & PR_CAP_INT)) ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", p->id, p->fe_counters.cum_conn, p->be_counters.cum_sess); - if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP) && !(p->cap & PR_CAP_INT)) + if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP || p->mode == PR_MODE_SPOP) && !(p->cap & PR_CAP_INT)) send_log(p, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", p->id, p->fe_counters.cum_conn, p->be_counters.cum_sess);