[PATCH v2] FEATURE: add opt-in MPTCP support
From: Dorian Craps Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. This attached patch adds the "mptcp" global option in the config, which allows the creation of an MPTCP socket instead of TCP on Linux. If Multipath TCP is not supported on the system, an error will be reported, and the application will stop. A test has been added, it is a copy of "default_rules.vtc" in tcp-rules with the addition of "mptcp" in the config. I'm not sure what else needs to be tested for the moment, with this global MPTCP option. Note: another patch is coming to support enabling MPTCP per address, but I prefer to already send this patch, just in case, as I will soon have less time to dedicate to this. Due to the limited impact within a data center environment, we have decided not to implement MPTCP between the proxy and the servers. The high-speed, low-latency nature of data center networks reduces the benefits of MPTCP, making the complexity of its implementation unnecessary in this context. Developed with the help of Matthieu Baerts (matt...@kernel.org) and Olivier Bonaventure (olivier.bonavent...@uclouvain.be) Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev [3] --- doc/configuration.txt | 9 +++ include/haproxy/proto_rhttp.h | 2 + reg-tests/tcp-rules/default_rules_mptcp.vtc | 65 + src/cfgparse-global.c | 21 ++- src/cfgparse.c | 3 +- 5 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 reg-tests/tcp-rules/default_rules_mptcp.vtc diff --git a/doc/configuration.txt b/doc/configuration.txt index 16094c194..cd43cd863 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1341,6 +1341,7 @@ The following keywords are supported in the "global" section : - maxsslconn - maxsslrate - maxzlibmem + - mptcp - no-memory-trimming - noepoll - noevports @@ -2958,6 +2959,14 @@ maxzlibmem with "show info" on the line "MaxZlibMemUsage", the memory used by zlib is "ZlibMemUsage" in bytes. +mptcp + Uses MPTCP instead of TCP. Multipath TCP or MPTCP is an extension to the + standard TCP and is described in RFC 8684. It allows a device to make use of + multiple interfaces at once to send and receive TCP packets over a single + MPTCP connection. MPTCP can aggregate the bandwidth of multiple interfaces or + prefer the one with the lowest latency, it also allows a fail-over if one path + is down, and the traffic is seamlessly reinjected on other paths. + no-memory-trimming Disables memory trimming ("malloc_trim") at a few moments where attempts are made to reclaim lots of memory (on memory shortage or on reload). Trimming diff --git a/include/haproxy/proto_rhttp.h b/include/haproxy/proto_rhttp.h index 421680fe5..80d2d6448 100644 --- a/include/haproxy/proto_rhttp.h +++ b/include/haproxy/proto_rhttp.h @@ -5,6 +5,8 @@ #include #include +extern struct protocol proto_rhttp; + int rhttp_bind_receiver(struct receiver *rx, char **errmsg); int rhttp_bind_listener(struct listener *listener, char *errmsg, int errlen); diff --git a/reg-tests/tcp-rules/default_rules_mptcp.vtc b/reg-tests/tcp-rules/default_rules_mptcp.vtc new file mode 100644 index 0..485d56a73 --- /dev/null +++ b/reg-tests/tcp-rules/default_rules_mptcp.vtc @@ -0,0 +1,65 @@ +varnishtest "Test declaration of TCP rules in default sections with mptcp in the config" + +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'" +feature cmd "test \"$(cat /proc/sys/net/mptcp/enabled)\" = 1" +feature ignore_unknown_macro + +server s1 { +rxreq +txresp +expect req.http.x-test1-frt == "def_front" +expect req.http.x-test1-bck == "def_back" +} -start + +haproxy h1 -c
RE: [PATCH] FEATURE: Adding MPTCP with option to disable it and fall-back to TCP
first of all, thank you for your interest. I already made a version with an option to enable MPTCP -https://github.com/CrapsDorian/haproxy/pull/1 I'm working on a new version with "mptcp@address" as Willy requested. Dorian
[PATCH] FEATURE: Adding MPTCP with option to disable it and fall-back to TCP
From: Dorian Craps Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. This attached patch uses MPTCP by default instead of TCP on Linux. There is a fallback if the creation of the MPTCP socket fails. A new option has been added in the config to be able to disable MPTCP support. It sounds good to have MPTCP enabled by default, so the client can decide when to use it or not. If the client didn't ask to use MPTCP, the kernel will return a "plain" TCP socket to the server application after an "accept()". [4] IPPROTO_MPTCP is defined just in case old libC are being used and don't have the ref. The running kernel is the only one who can tell if MPTCP is supported or not, it is probably best not to check that at build time. TCP_MAXSEG is currently not supported by MPTCP: is it an issue? MPTCP devs didn't add a support for it because it has not been requested with a use-case. If you think it is important, I can report that to them. Due to the limited impact within a data center environment, MPTCP support has only been added on the listening sockets, then not between the proxy and the servers. The high-speed, low-latency nature of data center networks reduces the benefits of MPTCP, making the complexity of its implementation unnecessary in this context. Developed with the help of Matthieu Baerts (matt...@kernel.org) and Olivier Bonaventure (olivier.bonavent...@uclouvain.be) Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev/ [3] Link: https://www.mptcp.dev/faq.html#why--when-should-mptcp-be-enabled-by-default [4] --- doc/configuration.txt| 4 include/haproxy/global-t.h | 1 + include/haproxy/protocol-t.h | 7 +++ src/cfgparse-global.c| 7 ++- src/cfgparse.c | 2 +- src/proto_rhttp.c| 5 + src/proto_tcp.c | 10 ++ src/protocol.c | 12 +++- src/sock_inet.c | 21 +++-- 9 files changed, 64 insertions(+), 5 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index d2d654c19..85b75de33 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1342,6 +1342,7 @@ The following keywords are supported in the "global" section : - maxsslrate - maxzlibmem - no-memory-trimming + - no-mptcp - noepoll - noevports - nogetaddrinfo @@ -2974,6 +2975,9 @@ no-memory-trimming nice with the new process. Note that advanced memory allocators usually do not suffer from such a problem. +no-mptcp + Disables Multipath TCP (MPTCP) support when the TCP protocol is requested. + noepoll Disables the use of the "epoll" event polling system on Linux. It is equivalent to the command-line argument "-de". The next polling system diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 92d2c6bc1..c2b81fb50 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -85,6 +85,7 @@ #define GTUNE_LISTENER_MQ_OPT(1<<28) #define GTUNE_LISTENER_MQ_ANY(GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT) #define GTUNE_QUIC_CC_HYSTART(1<<29) +#define GTUNE_NO_MPTCP (1<<30) #define NO_ZERO_COPY_FWD 0x0001 /* Globally disable zero-copy FF */ #define NO_ZERO_COPY_FWD_PT 0x0002 /* disable zero-copy FF for PT (recv & send are disabled automatically) */ diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index b85f29cc0..6a7d45c52 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -28,6 +28,12 @@ #include #include +#ifdef __linux__ +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP +#endif +#endif + /* some pointer types referenced below */ struct listener; struct receiver; @@ -99,6 +105,7 @@ struct protocol { enum proto_type proto_type; /* protocol type at the socket layer (PROTO_TYPE