]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/socket: allow MPTCP protocol
authorMatthieu Baerts (NGI0) <matttbe@kernel.org>
Mon, 20 May 2024 16:37:17 +0000 (18:37 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 11 Jun 2024 23:14:08 +0000 (00:14 +0100)
Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension
that enables a TCP connection to use different paths. 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 re-injected on other paths.

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 [2]. To
use it on Linux, an application must explicitly enable it when creating
the socket:

  int sd = socket(AF_INET(6), SOCK_STREAM, IPPROTO_MPTCP);

No need to change anything else in the application.

This patch allows MPTCP protocol in the Socket unit configuration. So
now, a <unit>.socket can contain this to use MPTCP instead of TCP:

  [Socket]
  SocketProtocol=mptcp

MPTCP support has been allowed similarly to what has been already done
to allow SCTP: just one line in core/socket.c, a very simple addition
thanks to the flexible architecture already in place.

On top of that, IPPROTO_MPTCP has also been added in the list of allowed
protocols in two other places, and in the doc. It has also been added to
the missing_network.h file, for systems with an old libc -- note that it
was also required to include <netinet/in.h> in this file to avoid
redefinition errors.

Link: https://www.rfc-editor.org/rfc/rfc8684.html
Link: https://www.mptcp.dev
man/systemd.socket.xml
src/basic/missing_network.h
src/core/dbus-socket.c
src/core/load-fragment.c
src/core/socket.c
src/test/test-ip-protocol-list.c
test/fuzz/fuzz-unit-file/syslog.socket

index aa0e661002afcab7538243eb51fc49778d40de9e..67384bfcc4df1a5b3eb596ee36bcfb7fcdfa1f09 100644 (file)
 
       <varlistentry>
         <term><varname>SocketProtocol=</varname></term>
-        <listitem><para>Takes one of <option>udplite</option>
-        or <option>sctp</option>. The socket will use the UDP-Lite
-        (<constant>IPPROTO_UDPLITE</constant>) or SCTP
-        (<constant>IPPROTO_SCTP</constant>) protocol, respectively.</para>
+        <listitem><para>Takes one of <option>udplite</option>,
+        <option>sctp</option> or <option>mptcp</option>. The socket will use
+        the UDP-Lite (<constant>IPPROTO_UDPLITE</constant>), SCTP
+        (<constant>IPPROTO_SCTP</constant>) or MPTCP
+        (<constant>IPPROTO_MPTCP</constant>) protocol, respectively.</para>
 
         <xi:include href="version-info.xml" xpointer="v229"/>
         </listitem>
index 776c7c837576f56b69e09bce253022d9228395b9..ff5b30d3e1b5da4fd56547d30e057658191ece1a 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <netinet/in.h>
+
 /* linux/in6.h or netinet/in.h */
 #ifndef IPV6_UNICAST_IF
 #define IPV6_UNICAST_IF 76
 #define IPV6_TRANSPARENT 75
 #endif
 
+/* linux/in.h or netinet/in.h */
+#ifndef IPPROTO_MPTCP
+#define IPPROTO_MPTCP 262
+#endif
+
 /* Not exposed but defined at include/net/ip.h */
 #ifndef IPV4_MIN_MTU
 #define IPV4_MIN_MTU 68
index 03c5b4ad2ae5edc188c88854469a0a0ab70d8bd8..320a93e981e715052e675f4488ee43275c8c818b 100644 (file)
@@ -131,7 +131,7 @@ static const char* socket_protocol_to_string(int32_t i) {
         if (i == IPPROTO_IP)
                 return "";
 
-        if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
+        if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP, IPPROTO_MPTCP))
                 return NULL;
 
         return ip_protocol_to_name(i);
index 5ae68886afe79229d81bb8029481754d69d64b64..4ff1e66d7ba83b6fa9a64cdc51ac5a3dec868f13 100644 (file)
@@ -81,7 +81,7 @@ static int parse_socket_protocol(const char *s) {
         r = parse_ip_protocol(s);
         if (r < 0)
                 return r;
-        if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP))
+        if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP, IPPROTO_MPTCP))
                 return -EPROTONOSUPPORT;
 
         return r;
index 41147d4bf74e0211f17988c01141b6fe3954049a..726b805d43f567fa8a076ac750784c031126210a 100644 (file)
@@ -1645,6 +1645,10 @@ static int socket_open_fds(Socket *orig_s) {
                         switch (p->address.type) {
 
                         case SOCK_STREAM:
+                                if (IN_SET(s->socket_protocol, IPPROTO_SCTP, IPPROTO_MPTCP))
+                                        p->address.protocol = s->socket_protocol;
+                                break;
+
                         case SOCK_SEQPACKET:
                                 if (s->socket_protocol == IPPROTO_SCTP)
                                         p->address.protocol = s->socket_protocol;
index 9d0403c2f9d71f78a3768f9e54d0f3d8a3bf7279..5077ae2360e986c6ef0a5c9438bc05211f4a33db 100644 (file)
@@ -54,6 +54,8 @@ TEST(string) {
 TEST(parse_ip_protocol) {
         assert_se(parse_ip_protocol("sctp") == IPPROTO_SCTP);
         assert_se(parse_ip_protocol("ScTp") == IPPROTO_SCTP);
+        assert_se(parse_ip_protocol("mptcp") == IPPROTO_MPTCP);
+        assert_se(parse_ip_protocol("MPTCP") == IPPROTO_MPTCP);
         assert_se(parse_ip_protocol("ip") == IPPROTO_IP);
         assert_se(parse_ip_protocol("") == IPPROTO_IP);
         assert_se(parse_ip_protocol("1") == 1);
index bb046a5c6f4079828fb50c6e900f01d7e177abf9..daf974345235d2ec99697b5810daba0ba21dd97b 100644 (file)
@@ -58,6 +58,7 @@ ListenMessageQueue=
 ListenUSBFunction=
 SocketProtocol=udplite
 SocketProtocol=sctp
+SocketProtocol=mptcp
 SocketProtocol=
 BindIPv6Only=false
 Backlog=33