Skip to content

Commit 27dee08

Browse files
Dwyane-Yanchenhengqi
authored andcommitted
BCC: python: add a useful tool for mptcp
Multipath TCP (MPTCP) is an extension of the standard TCP protocol that allows a single transport connection to use multiple network interfaces or paths. MPTCP is useful for applications like bandwidth aggregation, failover, and more resilient connections. Linux kernel starts to support MPTCP since v5.6, this patch provides a method which can easily force applications use MPTCP socket without modifing its code. Co-developed-by: Geliang Tang <[email protected]> Signed-off-by: Geliang Tang <[email protected]> Signed-off-by: Gang Yan <[email protected]>
1 parent 18bc672 commit 27dee08

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ pair of .c and .py files, and some are directories of files.
173173
- tools/[tcptop](tools/tcptop.py): Summarize TCP send/recv throughput by host. Top for TCP. [Examples](tools/tcptop_example.txt).
174174
- tools/[tcptracer](tools/tcptracer.py): Trace TCP established connections (connect(), accept(), close()). [Examples](tools/tcptracer_example.txt).
175175
- tools/[tcpcong](tools/tcpcong.py): Trace TCP socket congestion control status duration. [Examples](tools/tcpcong_example.txt).
176+
- tools/[mptcpify](tools/mptcpify.py): Force applications to use MPTCP instead of TCP. [Examples](tools/mptcpify_example.txt).
176177

177178
##### Storage and Filesystems Tools
178179

tools/mptcpify.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env python
2+
#
3+
# mptcpify Make the applications to use MPTCP.
4+
# For Linux, uses BCC, eBPF. Embedded C.
5+
#
6+
# USAGE: ./mptcpify
7+
# ./mptcpify -t curl,iperf3
8+
#
9+
# Copyright 2025 Kylin Software, Inc.
10+
# Licensed under the Apache License, Version 2.0 (the "License")
11+
#
12+
# 05-Apr-2025 Gang Yan Created this.
13+
14+
import ctypes as ct
15+
import argparse
16+
import signal
17+
import time
18+
19+
from bcc import BPF
20+
21+
#arguments
22+
parser = argparse.ArgumentParser(
23+
description="mptcpify try to force applications to use MPTCP instead of TCP")
24+
parser.add_argument("-t", "--targets", type=str,
25+
help="use ',' for multi targets, eg: 'iperf3,rsync'. "
26+
"Without '-t', it can works on all applications by default.")
27+
28+
args_str = parser.parse_args()
29+
if args_str.targets != None:
30+
mode = 1
31+
args_list = [t.strip() for t in args_str.targets.split(',')]
32+
else:
33+
mode = 0
34+
35+
if (not BPF.support_fmod_ret()):
36+
print("Your kernel version is too old,"
37+
" fmod_ret method is only support kernel v5.7 and later.")
38+
exit()
39+
40+
TASK_COMM_LEN = 16
41+
42+
class app_name(ct.Structure):
43+
_fields_ = [("str", ct.c_char * TASK_COMM_LEN)]
44+
45+
# define BPF program
46+
prog = """
47+
#include <linux/net.h>
48+
#include <uapi/linux/in.h>
49+
#include <linux/string.h>
50+
51+
struct app_name {
52+
char name[TASK_COMM_LEN];
53+
};
54+
55+
BPF_ARRAY(work_mode, int, 1);
56+
BPF_HASH(support_apps, struct app_name);
57+
58+
KMOD_RET(update_socket_protocol, int family, int type, int protocol, int ret)
59+
{
60+
struct app_name target = {};
61+
int index = 0;
62+
int *mode = work_mode.lookup(&index);
63+
bpf_get_current_comm(&target.name, TASK_COMM_LEN);
64+
65+
if ((family == AF_INET || family == AF_INET6) &&
66+
type == SOCK_STREAM &&
67+
(!protocol || protocol == IPPROTO_TCP) &&
68+
(*mode == 0 || support_apps.lookup(&target)))
69+
return IPPROTO_MPTCP;
70+
71+
return protocol;
72+
73+
}
74+
75+
"""
76+
77+
b = BPF(text=prog)
78+
b.attach_fmod_ret("update_socket_protocol")
79+
80+
work_mode = b["work_mode"]
81+
support_apps = b.get_table("support_apps")
82+
if mode:
83+
for i in args_list:
84+
app = i.encode()
85+
name = app_name()
86+
name.str = app[:TASK_COMM_LEN-1].ljust(TASK_COMM_LEN, b'\0')
87+
support_apps[name] = ct.c_uint32(1)
88+
89+
work_mode[ct.c_int(0)] = ct.c_int(mode)
90+
91+
print("MPTCP is been forced for ", args_list if mode == 1 else "all applications");
92+
signal.pause()

tools/mptcpify_example.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Demonstrations of mptcpify, the Linux eBPF/bcc version.
2+
3+
4+
mptcpify forces the application to use to MPTCP instead of TCP.
5+
6+
mptcpify has been verified with iperf3 and rsync[TCP module]. It can be used
7+
for incresing the speed of transferring data with rsync.
8+
9+
The MPTCP configuration is decribed in
10+
https://www.mptcp.dev/pm.html
11+
12+
USAGE message:
13+
14+
usage: sudo python ./mptcpify.py [-h] [-t TARGETS]
15+
16+
mptcpify try to force applications to use MPTCP instead of TCP
17+
18+
options:
19+
-h, --help show this help message and exit
20+
-t TARGETS, --targets TARGETS
21+
use ',' for multi targets, eg: 'iperf3,rsync'. Without '-t', it can works on all applications by default.
22+
23+
Here are some example output.
24+
25+
1、curl
26+
$ curl https://check.mptcp.dev
27+
You are not using MPTCP.
28+
29+
$ sudo python3 mptcpify.py -t curl &
30+
$ curl https://check.mptcp.dev
31+
You are using MPTCP.
32+
33+
2、iperf3
34+
'iperf.sh' can be obtained through th link below:
35+
https://github.com/Dwyane-Yan/bcc_test_iperf/blob/main/iperf.sh
36+
37+
$ sudo ./iperf.sh
38+
[ ID] Interval Transfer Bitrate
39+
[ 5] 0.00-1.00 sec 11.4 MBytes 95.3 Mbits/sec
40+
41+
$ sudo python3 mptcpify.py -t iperf3
42+
$ sudo ./iperf.sh
43+
[ ID] Interval Transfer Bitrate
44+
[ 5] 0.00-1.00 sec 87.0 MBytes 729 Mbits/sec

0 commit comments

Comments
 (0)