]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: proxy/spoe: Add a SPOP mode
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 4 Jul 2024 07:58:12 +0000 (09:58 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jul 2024 13:27:04 +0000 (15:27 +0200)
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.

include/haproxy/connection-t.h
include/haproxy/connection.h
include/haproxy/proxy-t.h
include/haproxy/tcpcheck.h
src/cfgparse-listen.c
src/cfgparse.c
src/check.c
src/connection.c
src/extcheck.c
src/fcgi-app.c
src/proxy.c

index 83969da06e0c569d56ca353efbdf35c51b1f15c8..dba52fa320516f1efeede824c6532199c271ccb3 100644 (file)
@@ -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 {
index aa61cc71afdbaa6730df58d58a8ffade62ca68ab..dc187eb918e1148a75331c304859cf5b2237e875 100644 (file)
@@ -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;
 }
index 262dc11d5e381f1e567fb220edd81ffb68b768f8..9bafb22e5c0b3492e9d08ed7e64a0c9749414b98 100644 (file)
@@ -52,6 +52,7 @@ enum pr_mode {
        PR_MODE_CLI,
        PR_MODE_SYSLOG,
        PR_MODE_PEERS,
+       PR_MODE_SPOP,
        PR_MODES
 } __attribute__((packed));
 
index 55c564a20c2dc9702455f35a83dac2ffb1fcd9da..95244a521203c2be167f772c66f7a8a0240ffc82 100644 (file)
@@ -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 */
 
 /*
index 1f6ddc2adc898045f60622982250a3a67e197b2c..2beb9377b079ce8c7fddd86ac23feeeb15f7592a 100644 (file)
@@ -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;
index 2434de2cb6c084f51643727a9dfb950c4c654954..990d2a488078d64ef27e46c1dd4f11b3c168bf38 100644 (file)
@@ -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 */
index 64464c4f4f85eff121115351c2d7a5ca4bfccd71..40d403b2729cd760022f64e9c7e658d7f6c59f66 100644 (file)
@@ -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);
index 3fedad9a58ef23724a151b8fa6628f54d52836ab..668e626f5ec4a74f7a3155f438da29b1282a118f 100644 (file)
@@ -33,6 +33,7 @@
 #include <haproxy/session.h>
 #include <haproxy/ssl_sock.h>
 #include <haproxy/stconn.h>
+#include <haproxy/tcpcheck.h>
 #include <haproxy/tools.h>
 #include <haproxy/xxhash.h>
 
@@ -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";
 
index 05c53ff9f6f2d36a44c17d095ccd86c16b7fdd7c..f01931b9d9c180c5d68b50e553189f76890c7b55 100644 (file)
@@ -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;
        }
index 5790cebcf8e3b18d1e1d35e4ef40ed38232204e0..b3a9b7c595ae054a8f76f125ce8d8d3545dfefe6 100644 (file)
@@ -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;
index 10cb78025736802228fbfde8fef29be15f8ee186..da589a28e1b0f92397f770bf297de56dd9e9e566 100644 (file)
@@ -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);