New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core] add MPTCP support #132
Conversation
Thank you for suggesting the patch. If the feature was disabled by default, I would accept the patch as submitted. However, you are suggesting that this feature be enabled by default. Your entire justification is "If the option is not enabled by default, it looks difficult to convince each administrator to enable it explicitly" which translates to little more than "I want clients to be able to use this feature, so enable it by default on servers". First, what are the security and privacy implications, if any, to client or server, of enabling this by default in lighttpd? Second, would you please point me to established documentation to corroborate your statement that enabling MPTCP on listening sockets is "without any performance impact"? https://www.mptcp.dev/ notes the feature "Fallback from MPTCP to TCP if the peer or a middlebox do not support MPTCP." There is no performance impact to this? Fallback is good. However, lighttpd may be run on very small embedded systems, so extra cost needs to be accurately accounted, even if there is transparent fallback so that things do not break. Third, if enabling this by default, perhaps this feature should be available only when Fourth, is multipath TCP available only on Linux? I think it is more widely available. Restricting it to Linux is a limitation of this patch. However, multipath TCP must also be available on macOS and iOS if Apple enables it in clients. lighttpd can be run on a wide variety of servers, including some which you might consider clients such as phones (e.g. Android or iOS). To be clear, I would like to support MPTCP and this patch, but I have questions since I am not an expert in MPTCP. Before enabling this by default in lighttpd, I need to have a stronger understanding of potential implications and effects of doing so. Thank you. |
FreeBSD support for multipath TCP: https://freebsdfoundation.org/project/multipath-tcp-for-freebsd/ Edit: someone tried to compile a status of MPTCP in FreeBSD in 2023
|
Regarding the git usage of this PR, please do not merge the master branch. Instead, |
How does MPTCP (at the transport layer) compare with the feature of HTTP/3 QUIC streams (closer to the application layers) which can be transported over multiple paths? |
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, Multipath TCP 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, Multipath TCP 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 Multipath TCP on Linux, a server application must explicitly enable it when creating the socket. No need to change anything else in the application. This is what the attached patch is doing. It is important to note that a MPTCP-enabled server continues to accept regular TCP connections that do not use the Multipath TCP extension without any performance impact. When a connection request is received, and is linked to a listening socket with MPTCP support, the kernel will simply check if MPTCP options are present. If not, the accepted socket will be a "plain" TCP one. This commit modifies the creation of sockets on Linux, trying to use Multipath TCP is available. If not, a plain TCP socket is created instead. A new option is now available: `server.network-mptcp`. This option is enabled by default. It seems important to enable this option by default on the server side, to let clients using MPTCP while not degrading performances when "plain" TCP is used. If the option is not enabled by default, it looks difficult to convince each administrator to enable it explicitly. This technology is mainly useful for the client side while it doesn't change much for the server side where no other configuration is needed. 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] Co-developed-by: Maxime Dourov <mux99@live.be> Co-developed-by: Olivier Bonaventure <Olivier.Bonaventure@uclouvain.be> Co-developed-by: Matthieu Baerts <matttbe@kernel.org> Signed-off-by: Maxime Dourov (UCLouvain) <mux99@live.be>
Hi @gstrauss (I worked on this patch with Maxime)
Thank you for your review and the question.
We understand your reaction. I think adding a bit more context about our work here with Maxime at UCLouvain might help. UCLouvain is a university in Belgium where a lot of development around Multipath TCP (and Multipath QUIC) has been done. Today, MPTCP is available in the Linux kernel and iOS, but is mainly used by big companies: mainly Apple for some of their apps, some specific use-cases in datacenters, and ISPs to use both the cellular and the fixed network for some clients. In all these cases, the companies behind them control both the clients and the servers. If someone wants to have an app using MPTCP, they often simply use a tool like With the help of two students who want to learn by doing useful things in open source, we are trying to add native support to different apps. Our "dream" would be to have MPTCP enabled by default on the server side, so people can start using it with multiple servers without a proxy or asking sysadmins to enable it. In our minds, because of its low impact, it should not matter to have it enabled for a sysadmin: it is in theory as secured as TCP (see below), the server will continue to serve files, and this might be done quicker, or without interruptions when the client is switching from one network to another. But you are right; it is not as simple.
Regarding the security implications of the protocol, it is described in RFC 8684. In summary, the fundamental goal is for the security of MPTCP to be "no worse" than regular TCP today. Regarding the security implications of the Linux kernel implementations, it is like any software; there might be issues. But the Linux kernel is also known to quickly fix security issues once they have been identified. For the privacy concerns, the RFC doesn't mention anything, I think, but it looks like it is similar to TCP. Of course, here, if a client is doing a long transfer while switching from one network to another, the server can see it is the same client. Without MPTCP, the server would see the same requests twice, but from two different IPs. MPTCP can be used to improve privacy: if a path is known as being untrusted, but cheap, some data --e.g., TLS handshakes -- could be done over another path, trusted but more expensive.
Sorry, I'm not sure if I understand the question. If these proxies initiating connections to our server don't support MPTCP, MPTCP will not be used. Technically, if a request is established without MPTCP options in the TCP header, the Linux kernel will create a "plain" TCP socket, which is used by the userspace after an
We need to work on such a document, sorry. Just to be precise, there is no real performance impact if the client doesn't support MPTCP; apart from checking if MPTCP options are present in the TCP header, that's negligible. Here is what the kernel code is saying when the userspace uses /* we are being invoked after accepting a non-mp-capable
* flow: sk is a tcp_sk, not an mptcp one.
*
* Hand the socket over to tcp so all further socket ops
* bypass mptcp.
*/ When MPTCP is used, there is a small impact because there is an extra layer. It is difficult to measure the impact: we can do that when only one path is used, and see that the impact is extremely low, but it is mainly caused by a few bytes (~20B) added in the TCP header for MPTCP to work. When multiple subflows are used, the server will send data at a higher rate, or not have to re-send files.
To be able to survive on the "wild" Internet, MPTCP connections should be able to fall back to TCP in case of issues. Typically, a client initiates an MPTCP connection, and a middlebox will drop MPTCP options from the TCP headers because they are "unknown". On the server side, it will receive a request without MPTCP options; that's fine: a plain TCP socket will be created. If MPTCP options are dropped (or altered) later, the MPTCP socket will continue to be used, but it will directly call the TCP layer. That's the "extra layer" we cannot avoid. But as it is done nicely on the kernel side, the impact is very low.
Good point. I don't have any numbers to share for embedded systems, even if I used to work for a company where we were installing a TCP-2-MPTCP proxy on residential gateways. These routers were less powerful than most Raspberry Pi's :)
I don't think it is a good idea to restrict this with I didn't know about the impact of the log. We thought it would be OK because there will be only one log entry at the start of a server, no?
It is easily accessible with Linux, thanks to On iOS, it is available, but well:
On FreeBSD, there was an ongoing implementation, but that was years ago, as you mentioned. There are other implementations, but on specific systems (Citrix load balancer, userspace, etc.): So I think it is best to restrict this to Linux only for the moment.
Sorry for that: it was not supposed to be done. Maxime will make sure not to do that again.
QUIC doesn't support using multiple paths at the same time. There is a draft, some implementations support it, but the standardization is slow. The idea there is apparently to let apps manage the different paths themselves. More freedom, but more complex than just changing the socket protocol. QUIC does support connections migrations, but it is not as smooth as a seamless handover done by MPTCP, as only one path can be used at a time with QUIC for the moment.
We understand. |
Thank you for the detailed response. I will be following the links and reading more about MPTCP in the coming days, so at this moment, I won't respond directly to your detailed comments. In the meantime, I'd like to propose a practical approach to incrementally release these changes, even though the patch is small. I propose that this patch be committed with the feature disabled by default The next lighttpd release is likely some time in Q3 2024 time-frame unless bugs pop up or major feature development completes sooner, so announcing the change for the beginning of 2025 seems like a reasonable target to me. I realize that may be disappointing, but lighttpd 1.4.75 was just recently released and I am attempting to get that into the next Ubuntu long-term release which is already in feature freeze. In the details: On
Future looking: lighttpd mod_openssl and lighttpd mod_gnutls call |
@gstrauss thank you for your reply!
All good, take your time!
It sounds like a good idea! Should Maxime update some doc, and/or the default config file to reflect that?
That's OK, best not to rush anyway.
Good point, if MPTCP is used by default, it would probably be best not to warn the user multiple times. But if MPTCP has been explicitly enabled, should we not keep the log entry to let users understanding there was an issue? Or only warn them in case
Interesting, that could be used indeed, but please note that even if the kernel is recent enough (v5.6), MPTCP might still not be available: not compiled ( Please also note that MPTCP is currently not compatible with KTLS: they both use the same technique to extend TCP behaviour in the kernel (TCP ULP). Technically, it should be possible to chain these extensions, but that's not possible today (mainly because nobody requested it I think). I didn't know KTLS was used by default in lighttpd. |
In a world centered around MPTCP, yes that makes sense for you. On the other hand, I do not think adding many lines of code around this is worthwhile as this is linux-specific and a simple
lighttpd could at startup perform a single
Whether or not KTLS is enabled by default in lighttpd, that MPTCP and KTLS are not supported together should be carefully documented on the MPTCP site and this info shared with other projects to which your team sends patches. What behavior/errors would someone see if they enabled MPTCP in lighttpd and also use lighttpd mod_openssl or lighttpd mod_gnutls with KTLS? Would someone need to explicitly disable KTLS in order to use MPTCP? Would someone need to explicitly disable MPTCP in order to use KTLS? This interaction would need to be documented on the lighttpd wiki in both places where MPTCP will be documented, and where lighttpd TLS modules with KTLS are documented. Unfortunately, MPTCP and KTLS not being supported together is a blocker for enabling MPTCP by default in lighttpd. To keep progress moving, I am going to accept this patch, and will follow with another commit which makes some adjustments. |
My commits will automatically close this PR, but I welcome continuing the conversation here or in another PR. |
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, Multipath TCP 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, Multipath TCP 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 Multipath TCP on Linux, a server application must explicitly enable it when creating the socket. No need to change anything else in the application. This is what the attached patch is doing. It is important to note that a MPTCP-enabled server continues to accept regular TCP connections that do not use the Multipath TCP extension without any performance impact. When a connection request is received, and is linked to a listening socket with MPTCP support, the kernel will simply check if MPTCP options are present. If not, the accepted socket will be a "plain" TCP one. This commit modifies the creation of sockets on Linux, trying to use Multipath TCP is available. If not, a plain TCP socket is created instead. A new option is now available: `server.network-mptcp`. This option is enabled by default. It seems important to enable this option by default on the server side, to let clients using MPTCP while not degrading performances when "plain" TCP is used. If the option is not enabled by default, it looks difficult to convince each administrator to enable it explicitly. This technology is mainly useful for the client side while it doesn't change much for the server side where no other configuration is needed. 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] Co-developed-by: Maxime Dourov <mux99@live.be> Co-developed-by: Olivier Bonaventure <Olivier.Bonaventure@uclouvain.be> Co-developed-by: Matthieu Baerts <matttbe@kernel.org> Signed-off-by: Maxime Dourov (UCLouvain) <mux99@live.be> x-ref: "[core] add MPTCP support" #132
even though my subsequent commit message erroneously says "omit trace", I left the trace in if |
Yes, it is better. (I don't know why I didn't think about that, that's usually what we recommend :) )
Yes, we forgot about the KTLS incompatibility, but we should and we will document this! And we will check if it is possible to support both later on: multipath-tcp/mptcp_net-next#480
For the moment, MPTCP and KTLS cannot work together. If you create an MPTCP socket, and you want to use KTLS, the
We understand.
Thank you for having accepted the patch, and for these adjustments! |
Hi, after some testing, it appears that when MPTCP is enabled at the same time as KTLS. Since they are incompatible, the setsockopt() call to enable KTLS returns an error ( |
@mux99 thank you for confirming. Yes, openssl will recover if KTLS is not available. However, there will be a cost of one failed system call per connection to find that out. Just FYI: attempting to avoiding that excess syscall is the reason I added the |
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, Multipath TCP 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, Multipath TCP 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 Multipath TCP on Linux, a server application must explicitly
enable it when creating the socket. No need to change anything else in
the application. This is what the attached patch is doing.
It is important to note that a MPTCP-enabled server continues to accept
regular TCP connections that do not use the Multipath TCP extension
without any performance impact.
When a connection request is received, and is linked to a listening
socket with MPTCP support, the kernel will simply check if MPTCP
options are present. If not, the accepted socket will be a "plain" TCP
one.
This commit modifies the creation of sockets on Linux, trying to use
Multipath TCP is available. If not, a plain TCP socket is created
instead. A new option is now available:
server.network-mptcp
. Thisoption is enabled by default. It seems important to enable this option
by default on the server side, to let clients using MPTCP while not
degrading performances when "plain" TCP is used. If the option is not
enabled by default, it looks difficult to convince each administrator to
enable it explicitly. This technology is mainly useful for the client
side while it doesn't change much for the server side where no other
configuration is needed.
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]
Co-developed-by: Maxime Dourov mux99@live.be
Co-developed-by: Olivier Bonaventure Olivier.Bonaventure@uclouvain.be
Co-developed-by: Matthieu Baerts matttbe@kernel.org
Signed-off-by: Maxime Dourov (UCLouvain) mux99@live.be