[PATCH v2] FEATURE: add opt-in MPTCP support

2024-05-16 Thread Dorian Craps
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

2024-05-08 Thread Dorian Craps
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

2024-04-24 Thread Dorian Craps
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