This setup page is specific to the Multipath TCP support in the Linux kernel.
Kernel version
MPTCP support debuted with version 5.6 of the Linux kernel. It has continued to evolve, and is still evolving today. See the ChangeLog for more details.
For this reason, we do recommend you to use a recent kernel, ideally the last stable version, or the last “long term support” (LTS) one.
Note that the RedHat/CentOS kernels have a good support for MPTCP, where new features and bug fixes are regularly backported.
Enable MPTCP
Most recent GNU/Linux distributions support MPTCP by default. It is very likely MPTCP is already enabled, and you can skip this section.
Linux kernel build configuration
The Linux kernel being used has to be compiled with CONFIG_MPTCP=y
and CONFIG_MPTCP_IPV6=y
options, and ideally CONFIG_INET_MPTCP_DIAG=y/m
. If not, please report this to your GNU/Linux distribution: MPTCP in the kernel doesn’t add much overhead, and is enabled in most main Linux distributions (Debian, Ubuntu, RedHat, Fedora, etc.), and other specific ones like Raspbian.
Note that CONFIG_MPTCP_IPV6=y
requires IPV6
to be inlined (=y
), and not built as a module (=m
). Having IPV6
inlined is recommended by NetDev maintainers anyway: today, it is very likely that IPv6 will be used, e.g. for the loopback address.
Enable the creation of MPTCP sockets
If available, MPTCP should be enabled by default. If not, change this sysctl
knob:
sysctl -w net.mptcp.enabled=1
Note that MPTCP can also be blocked by SELinux, eBPF, etc. Please check with your system administrators if it is the case.
Force applications to use MPTCP
By default, applications will only use MPTCP if it has been explicitly requested when creating a stream network socket to communicate with the outside work. In other words, you likely have to enable an option in the app you want to use with MPTCP, or to force MPTCP by changing the behaviour of an app. The best is to have MPTCP supported natively by applications, so they know where MPTCP is being used, and they can act accordingly, e.g. force a fallback to TCP if MPTCP is not supported by the kernel, etc.
Apps can be forced to use MPTCP with one of the following methods:
-
mptcpize: internally, it uses the
LD_PRELOAD
technique to force creatingMPTCP
sockets, instead of aTCP
ones. OnlyMPTCP
sockets will then be created, instead ofTCP
.mptcpize run <command> mptcpize enable <systemd unit>
-
GODEBUG: For applications written in GO, the libC is not used, so
mptcpize
does not work. Since GoLang 1.21, it is possible to force MPTCP by setting the environment variableGODEBUG=multipathtcp=1
:GODEBUG=multipathtcp=1 <command>
-
eBPF: since kernel v6.6, it is possible to change the socket being created per cGroup. A small eBPF program – e.g. mptcpify – can be used, see this example.
-
SystemTap can also be used to modify the
socket
system call. See this documentation for more details about that.
Using multiple IP addresses
To be able to use multiple IP addresses on a host to create multiple subflows (paths), the MPTCP path-manager needs to know which IP addresses can be used.
A server having only one network interface does not need to configure anything else: the client will be able to attach additional subflows as needed – max 2 by default, see the Path-Manager’s Limits section below.
It might be interesting to announce additional IPv4/6 addresses. Some clients might be connected to networks having only an IPv4 or an IPv6 address. Also, consider that IPv4 and IPv6 packets are often routed differently through some networks, resulting in different latencies.
Path-Manager configuration
With the default in-kernel MPTCP path-manager, additional IP addresses need to be specified, and limits might need to be changed. Check the Path-Manager page for more details about this component.
Manual routing configuration
Only if MPTCP endpoints have not been configured with a network interface
The system needs to know how to route packets from a specific IP address to the correct network interface.
This manual routing configuration should not be required if the MPTCP endpoints have been configured with a network interface dev <interface>
, and if the GNU/Linux distribution has automatically configured default route attached to each network interface. To verify the latter, please check if the following command ip route show default
lists all the IPs you want to use with a dev
and a src
.
To be able to use multiple paths from different local IP addresses at the same time, it is then required to configure the system to route the traffic from a specific local IP address (e.g. the one of the Wi-Fi) through the correct interface, and not the default one. Such configuration can be automated with tools like Network Manager, but here, we will focus on the manual configuration, using ip route
and ip rule
commands.
For each (additional) interface that will be used with MPTCP, run the following commands with the correct IP address and a different table number:
ip rule add from <local interface IP address> table <table number>
ip route add default via <default gateway IP> dev <interface name> table <table number>
This configuration might need to be done with both IPv4 and IPv6 addresses.
Example
On a system with 3 network interfaces:
- Ethernet:
- IP Address: 10.1.1.2
- Gateway (next hop): 10.1.1.1
- Wi-Fi:
- IP Address: 192.168.1.2
- Gateway (next hop): 192.168.1.1
- Cellular:
- IP Address: 100.64.1.134
- Gateway (next hop): 100.64.1.133
Where the Ethernet interface is the default one:
$ ip route show default
default via 10.1.1.1 dev eth0 (...) metric 100
default via 192.168.1.1 dev wlan0 (...) metric 600
default via 100.64.1.133 dev usb0 (...) metric 1000
It is then required to configure the routing for the Wi-Fi and the cellular interface, not to have the traffic routed only through the Ethernet interface:
ip rule add from 192.168.1.2 table 42
ip route add default via 192.168.1.1 dev wlan0 table 42
ip rule add from 100.64.1.134 table 43
ip route add default via 100.64.1.133 dev wlan0 table 43