1
These patches provide a method to verify the 'mptcp_diag_dump_one'
1
These patches provide a method to verify the 'mptcp_diag_dump_one'
2
function, and the new tool 'mptcp_diag' can get the specific mptcp_info
2
function, and the new tool 'mptcp_diag' can get the specific mptcp_info
3
through multi msks.
3
through multi msks.
4
5
Hi Matt:
6
7
Thank you for your suggestions regarding these patches, they have been
8
very useful to me. Sorry for the misunderstanding caused by my misuse of
9
the 'CLOSE' keyword. Currently, I have used the 'Link' instead. These
10
patches are designed for 'mptcp_dump_one'.
11
12
There may need another test case for 'subflow_get_info_size'. I will
13
continue to work on resolving this issue.
14
15
Best wishes!
4
16
5
Gang Yan (2):
17
Gang Yan (2):
6
selftests: mptcp: Add a tool to get specific msk_info
18
selftests: mptcp: Add a tool to get specific msk_info
7
selftests: mptcp: add a test for mptcp_diag_dump_one
19
selftests: mptcp: add a test for mptcp_diag_dump_one
8
20
9
tools/testing/selftests/net/mptcp/Makefile | 2 +-
21
tools/testing/selftests/net/mptcp/Makefile | 2 +-
10
tools/testing/selftests/net/mptcp/diag.sh | 23 ++
22
tools/testing/selftests/net/mptcp/diag.sh | 27 ++
11
.../testing/selftests/net/mptcp/mptcp_diag.c | 235 ++++++++++++++++++
23
.../testing/selftests/net/mptcp/mptcp_diag.c | 271 ++++++++++++++++++
12
3 files changed, 259 insertions(+), 1 deletion(-)
24
3 files changed, 299 insertions(+), 1 deletion(-)
13
create mode 100644 tools/testing/selftests/net/mptcp/mptcp_diag.c
25
create mode 100644 tools/testing/selftests/net/mptcp/mptcp_diag.c
14
26
15
--
27
--
16
2.43.0
28
2.43.0
diff view generated by jsdifflib
...
...
3
present, specific information can be obtained for a given connection
3
present, specific information can be obtained for a given connection
4
through the 'mptcp_diag_dump_one' by using the 'token' associated with
4
through the 'mptcp_diag_dump_one' by using the 'token' associated with
5
the msk.
5
the msk.
6
6
7
Signed-off-by: Gang Yan <yangang@kylinos.cn>
7
Signed-off-by: Gang Yan <yangang@kylinos.cn>
8
9
---
10
Notes:
11
- v4:
12
- With reference to include/uapi/linux/mptcp.h, the structure members
13
of mptcp_info have been supplemented.
14
- Improve the code style of 'print_info_msg'
15
- With reference to iproute2, make 'parse_nlmsg' compatible with older
16
kernel versions.
17
- Check argc in 'parse_opts' to make sure '-t' is passed.
8
---
18
---
9
tools/testing/selftests/net/mptcp/Makefile | 2 +-
19
tools/testing/selftests/net/mptcp/Makefile | 2 +-
10
.../testing/selftests/net/mptcp/mptcp_diag.c | 235 ++++++++++++++++++
20
.../testing/selftests/net/mptcp/mptcp_diag.c | 271 ++++++++++++++++++
11
2 files changed, 236 insertions(+), 1 deletion(-)
21
2 files changed, 272 insertions(+), 1 deletion(-)
12
create mode 100644 tools/testing/selftests/net/mptcp/mptcp_diag.c
22
create mode 100644 tools/testing/selftests/net/mptcp/mptcp_diag.c
13
23
14
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
24
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/tools/testing/selftests/net/mptcp/Makefile
26
--- a/tools/testing/selftests/net/mptcp/Makefile
...
...
29
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
30
--- /dev/null
40
--- /dev/null
31
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
41
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
32
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
33
+// SPDX-License-Identifier: GPL-2.0
43
+// SPDX-License-Identifier: GPL-2.0
34
+/* Copyright (c) 2025, Kylin Software*/
44
+/* Copyright (c) 2025, Kylin Software */
35
+
45
+
36
+#include <linux/sock_diag.h>
46
+#include <linux/sock_diag.h>
37
+#include <linux/rtnetlink.h>
47
+#include <linux/rtnetlink.h>
38
+#include <linux/inet_diag.h>
48
+#include <linux/inet_diag.h>
39
+#include <linux/netlink.h>
49
+#include <linux/netlink.h>
...
...
49
+
59
+
50
+#ifndef IPPROTO_MPTCP
60
+#ifndef IPPROTO_MPTCP
51
+#define IPPROTO_MPTCP 262
61
+#define IPPROTO_MPTCP 262
52
+#endif
62
+#endif
53
+
63
+
54
+#ifndef MPTCP_INFO
55
+struct mptcp_info {
64
+struct mptcp_info {
56
+    __u8 mptcpi_subflows;
65
+    __u8 mptcpi_subflows;
57
+    __u8 mptcpi_add_addr_signal;
66
+    __u8 mptcpi_add_addr_signal;
58
+    __u8 mptcpi_add_addr_accepted;
67
+    __u8 mptcpi_add_addr_accepted;
59
+    __u8 mptcpi_subflows_max;
68
+    __u8 mptcpi_subflows_max;
...
...
70
+    __u32 mptcpi_retransmits;
79
+    __u32 mptcpi_retransmits;
71
+    __u64 mptcpi_bytes_retrans;
80
+    __u64 mptcpi_bytes_retrans;
72
+    __u64 mptcpi_bytes_sent;
81
+    __u64 mptcpi_bytes_sent;
73
+    __u64 mptcpi_bytes_received;
82
+    __u64 mptcpi_bytes_received;
74
+    __u64 mptcpi_bytes_acked;
83
+    __u64 mptcpi_bytes_acked;
84
+    __u8    mptcpi_subflows_total;
85
+    __u8    reserved[3];
86
+    __u32    mptcpi_last_data_sent;
87
+    __u32    mptcpi_last_data_recv;
88
+    __u32    mptcpi_last_ack_recv;
75
+};
89
+};
76
+
77
+#define MPTCP_INFO 1
78
+#endif
79
+
90
+
80
+static void die_perror(const char *msg)
91
+static void die_perror(const char *msg)
81
+{
92
+{
82
+    perror(msg);
93
+    perror(msg);
83
+    exit(1);
94
+    exit(1);
...
...
143
+        break;
154
+        break;
144
+    }
155
+    }
145
+}
156
+}
146
+
157
+
147
+static void parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
158
+static void parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
148
+         int len, unsigned short flags)
159
+             int len, unsigned short flags)
149
+{
160
+{
150
+    unsigned short type;
161
+    unsigned short type;
151
+
162
+
152
+    memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
163
+    memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
153
+    while (RTA_OK(rta, len)) {
164
+    while (RTA_OK(rta, len)) {
154
+        type = rta->rta_type & ~flags;
165
+        type = rta->rta_type & ~flags;
155
+        if ((type <= max) && (!tb[type]))
166
+        if (type <= max && !tb[type])
156
+            tb[type] = rta;
167
+            tb[type] = rta;
157
+        rta = RTA_NEXT(rta, len);
168
+        rta = RTA_NEXT(rta, len);
158
+    }
169
+    }
159
+}
170
+}
160
+
171
+
161
+static struct mptcp_info *parse_nlmsg(struct nlmsghdr *nlh)
172
+static void print_info_msg(struct mptcp_info *info)
173
+{
174
+    printf("Token & Flags\n");
175
+    printf("token:     %x\n", info->mptcpi_token);
176
+    printf("flags:     %x\n", info->mptcpi_flags);
177
+    printf("csum_enabled: %u\n", info->mptcpi_csum_enabled);
178
+
179
+    printf("\nBasic Info\n");
180
+    printf("subflows:        %u\n", info->mptcpi_subflows);
181
+    printf("subflows_max:        %u\n", info->mptcpi_subflows_max);
182
+    printf("subflows_total:        %u\n", info->mptcpi_subflows_total);
183
+    printf("local_addr_used:    %u\n", info->mptcpi_local_addr_used);
184
+    printf("local_addr_max:        %u\n", info->mptcpi_local_addr_max);
185
+    printf("add_addr_signal:    %u\n", info->mptcpi_add_addr_signal);
186
+    printf("add_addr_accepted:    %u\n", info->mptcpi_add_addr_accepted);
187
+    printf("add_addr_signal_max:    %u\n", info->mptcpi_add_addr_signal_max);
188
+    printf("add_addr_accepted_max:    %u\n", info->mptcpi_add_addr_accepted_max);
189
+
190
+    printf("\nTransmission Info\n");
191
+    printf("write_seq:     %llx\n", info->mptcpi_write_seq);
192
+    printf("snd_una:     %llx\n", info->mptcpi_snd_una);
193
+    printf("rcv_nxt:     %llx\n", info->mptcpi_rcv_nxt);
194
+    printf("last_data_sent:     %x\n", info->mptcpi_last_data_sent);
195
+    printf("last_data_recv:     %x\n", info->mptcpi_last_data_recv);
196
+    printf("last_ack_recv:     %x\n", info->mptcpi_last_ack_recv);
197
+    printf("retransmits:     %u\n", info->mptcpi_retransmits);
198
+    printf("retransmit bytes: %llu\n", info->mptcpi_bytes_retrans);
199
+    printf("bytes_sent:     %llu\n", info->mptcpi_bytes_sent);
200
+    printf("bytes_received: %llu\n", info->mptcpi_bytes_received);
201
+    printf("bytes_acked:     %llu\n", info->mptcpi_bytes_acked);
202
+}
203
+
204
+static void parse_nlmsg(struct nlmsghdr *nlh)
162
+{
205
+{
163
+    struct inet_diag_msg *r = NLMSG_DATA(nlh);
206
+    struct inet_diag_msg *r = NLMSG_DATA(nlh);
164
+    struct rtattr *tb[INET_DIAG_MAX+1];
207
+    struct rtattr *tb[INET_DIAG_MAX + 1];
165
+    struct mptcp_info *info;
208
+
166
+
209
+    parse_rtattr_flags(tb, INET_DIAG_MAX, (struct rtattr *)(r + 1),
167
+    parse_rtattr_flags(tb, INET_DIAG_MAX, (struct rtattr *)(r+1),
168
+             nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)),
210
+             nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)),
169
+             NLA_F_NESTED);
211
+             NLA_F_NESTED);
170
+
212
+
171
+    if (tb[INET_DIAG_INFO]) {
213
+    if (tb[INET_DIAG_INFO]) {
172
+        info = RTA_DATA(tb[INET_DIAG_INFO]);
214
+        struct mptcp_info *info;
173
+        return info;
215
+        int len;
174
+    }
216
+
175
+
217
+        len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
176
+    die_perror("Has no INET_DIAG_INFO");
218
+        /* workaround fort older kernels with less fields */
177
+    return info;
219
+        if (len < sizeof(*info)) {
178
+}
220
+            info = alloca(sizeof(*info));
179
+
221
+            memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
180
+static struct mptcp_info *recv_nlmsg(int fd, struct nlmsghdr *nlh)
222
+            memset((char *)info + len, 0, sizeof(*info) - len);
223
+        } else
224
+            info = RTA_DATA(tb[INET_DIAG_INFO]);
225
+        print_info_msg(info);
226
+    }
227
+}
228
+
229
+static void recv_nlmsg(int fd, struct nlmsghdr *nlh)
181
+{
230
+{
182
+    char rcv_buff[8192];
231
+    char rcv_buff[8192];
183
+    struct sockaddr_nl rcv_nladdr = {
232
+    struct sockaddr_nl rcv_nladdr = {
184
+        .nl_family = AF_NETLINK
233
+        .nl_family = AF_NETLINK
185
+    };
234
+    };
...
...
191
+        .msg_name = &rcv_nladdr,
240
+        .msg_name = &rcv_nladdr,
192
+        .msg_namelen = sizeof(rcv_nladdr),
241
+        .msg_namelen = sizeof(rcv_nladdr),
193
+        .msg_iov = &rcv_iov,
242
+        .msg_iov = &rcv_iov,
194
+        .msg_iovlen = 1
243
+        .msg_iovlen = 1
195
+    };
244
+    };
196
+    struct mptcp_info *info = NULL;
197
+    int len;
245
+    int len;
198
+
246
+
199
+    len = recvmsg(fd, &rcv_msg, 0);
247
+    len = recvmsg(fd, &rcv_msg, 0);
200
+    nlh = (struct nlmsghdr *)rcv_buff;
248
+    nlh = (struct nlmsghdr *)rcv_buff;
201
+
249
+
...
...
205
+            break;
253
+            break;
206
+        } else if (nlh->nlmsg_type == NLMSG_ERROR) {
254
+        } else if (nlh->nlmsg_type == NLMSG_ERROR) {
207
+            struct nlmsgerr *err;
255
+            struct nlmsgerr *err;
208
+
256
+
209
+            err = (struct nlmsgerr *)NLMSG_DATA(nlh);
257
+            err = (struct nlmsgerr *)NLMSG_DATA(nlh);
210
+            printf("Error %d:%s\n", -(err->error), strerror(-(err->error)));
258
+            printf("Error %d:%s\n",
259
+             -(err->error), strerror(-(err->error)));
211
+            break;
260
+            break;
212
+        }
261
+        }
213
+        info = parse_nlmsg(nlh);
262
+        parse_nlmsg(nlh);
214
+        nlh = NLMSG_NEXT(nlh, len);
263
+        nlh = NLMSG_NEXT(nlh, len);
215
+    }
264
+    }
216
+    close(fd);
265
+}
217
+    return info;
266
+
218
+}
267
+static void get_mptcpinfo(__u32 token)
219
+
220
+static struct mptcp_info *get_mptcpinfo(__u32 token)
221
+{
268
+{
222
+    struct nlmsghdr *nlh = NULL;
269
+    struct nlmsghdr *nlh = NULL;
223
+    int fd;
270
+    int fd;
224
+
271
+
225
+    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
272
+    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
226
+    if (fd < 0)
273
+    if (fd < 0)
227
+        die_perror("Netlink socket");
274
+        die_perror("Netlink socket");
228
+
275
+
229
+    send_query(fd, token);
276
+    send_query(fd, token);
230
+    return recv_nlmsg(fd, nlh);
277
+    recv_nlmsg(fd, nlh);
278
+
279
+    close(fd);
231
+}
280
+}
232
+
281
+
233
+static void parse_opts(int argc, char **argv, __u32 *target_token)
282
+static void parse_opts(int argc, char **argv, __u32 *target_token)
234
+{
283
+{
235
+    int c;
284
+    int c;
285
+
286
+    if (argc < 2)
287
+        die_usage(1);
236
+
288
+
237
+    while ((c = getopt(argc, argv, "ht:")) != -1) {
289
+    while ((c = getopt(argc, argv, "ht:")) != -1) {
238
+        switch (c) {
290
+        switch (c) {
239
+        case 'h':
291
+        case 'h':
240
+            die_usage(1);
292
+            die_usage(0);
241
+            break;
293
+            break;
242
+        case 't':
294
+        case 't':
243
+            sscanf(optarg, "%x", target_token);
295
+            sscanf(optarg, "%x", target_token);
244
+            break;
296
+            break;
245
+        default:
297
+        default:
...
...
249
+    }
301
+    }
250
+}
302
+}
251
+
303
+
252
+int main(int argc, char *argv[])
304
+int main(int argc, char *argv[])
253
+{
305
+{
254
+    struct mptcp_info *info = NULL;
255
+    __u32 target_token;
306
+    __u32 target_token;
256
+
307
+
257
+    parse_opts(argc, argv, &target_token);
308
+    parse_opts(argc, argv, &target_token);
258
+    info = get_mptcpinfo(target_token);
309
+    get_mptcpinfo(target_token);
259
+
260
+    if (info)
261
+        printf("token:%x\n", info->mptcpi_token);
262
+    else
263
+        perror("No Such msk using this token!\n");
264
+
310
+
265
+    return 0;
311
+    return 0;
266
+}
312
+}
267
+
313
+
268
--
314
--
269
2.43.0
315
2.43.0
diff view generated by jsdifflib
1
This patch introduces a new 'chk_diag' test in diag.sh. It retrieves
1
This patch introduces a new 'chk_diag' test in diag.sh. It retrieves
2
the token for a specified MPTCP socket (msk) using the 'ss' command and
2
the token for a specified MPTCP socket (msk) using the 'ss' command and
3
then accesses the 'mptcp_diag_dump_one' in kernel via ./mptcp_diag
3
then accesses the 'mptcp_diag_dump_one' in kernel via ./mptcp_diag
4
to verify if the correct token is returned.
4
to verify if the correct token is returned.
5
5
6
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/524
6
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/524
7
Signed-off-by: Gang Yan <yangang@kylinos.cn>
7
Signed-off-by: Gang Yan <yangang@kylinos.cn>
8
8
---
9
---
9
tools/testing/selftests/net/mptcp/diag.sh | 23 +++++++++++++++++++++++
10
Notes:
10
1 file changed, 23 insertions(+)
11
- v4:
12
- Optimized the check logic for 'ss_token' and 'token′, and before
13
that,first check if 'ss_token' is empty.
14
---
15
tools/testing/selftests/net/mptcp/diag.sh | 27 +++++++++++++++++++++++
16
1 file changed, 27 insertions(+)
11
17
12
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
18
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
13
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100755
14
--- a/tools/testing/selftests/net/mptcp/diag.sh
20
--- a/tools/testing/selftests/net/mptcp/diag.sh
15
+++ b/tools/testing/selftests/net/mptcp/diag.sh
21
+++ b/tools/testing/selftests/net/mptcp/diag.sh
16
@@ -XXX,XX +XXX,XX @@ chk_msk_cestab()
22
@@ -XXX,XX +XXX,XX @@ chk_msk_cestab()
17
         "${expected}" "${msg}" ""
23
         "${expected}" "${msg}" ""
18
}
24
}
19
25
20
+chk_dumpone()
26
+chk_dump_one()
21
+{
27
+{
22
+    local ss_token="$(ss -inmHMN $ns | grep 'token:' |\
28
+    local ss_token
23
+             head -n 1 |\
29
+    local token
24
+             sed 's/.*token:\([0-9a-f]*\).*/\1/')"
30
+    local msg
25
+    local token="$(ip netns exec $ns ./mptcp_diag -t $ss_token |\
31
+
26
+         grep 'token:' |\
32
+    ss_token="$(ss -inmHMN $ns | grep 'token:' |\
27
+         sed 's/.*token:\([0-9a-f]*\).*/\1/')"
33
+         head -n 1 |\
28
+    local msg="...chk dumpone"
34
+         sed 's/.*token:\([0-9a-f]*\).*/\1/')"
35
+
36
+    token="$(ip netns exec $ns ./mptcp_diag -t $ss_token |\
37
+         awk -F':[ \t]+' '/^token/ {print $2}')"
38
+
39
+    msg="....chk dump_one"
29
+
40
+
30
+    mptcp_lib_print_title "$msg"
41
+    mptcp_lib_print_title "$msg"
31
+ if [ "$ss_token" != "$token" ]; then
42
+    if [ -n "$ss_token" ] && [ "$ss_token" = "$token" ]; then
43
+        mptcp_lib_pr_ok
44
+        mptcp_lib_result_pass "${msg}"
45
+    else
32
+        mptcp_lib_pr_fail "expected $ss_token found $token"
46
+        mptcp_lib_pr_fail "expected $ss_token found $token"
33
+        mptcp_lib_result_fail "${msg}"
47
+        mptcp_lib_result_fail "${msg}"
34
+        ret=${KSFT_FAIL}
48
+        ret=${KSFT_FAIL}
35
+    else
36
+ mptcp_lib_pr_ok
37
+ mptcp_lib_result_pass "${msg}"
38
+    fi
49
+    fi
39
+
40
+}
50
+}
41
+
51
+
42
msk_info_get_value()
52
msk_info_get_value()
43
{
53
{
44
    local port="${1}"
54
    local port="${1}"
45
@@ -XXX,XX +XXX,XX @@ chk_msk_remote_key_nr 2 "....chk remote_key"
55
@@ -XXX,XX +XXX,XX @@ chk_msk_remote_key_nr 2 "....chk remote_key"
46
chk_msk_fallback_nr 0 "....chk no fallback"
56
chk_msk_fallback_nr 0 "....chk no fallback"
47
chk_msk_inuse 2
57
chk_msk_inuse 2
48
chk_msk_cestab 2
58
chk_msk_cestab 2
49
+chk_dumpone
59
+chk_dump_one
50
flush_pids
60
flush_pids
51
61
52
chk_msk_inuse 0 "2->0"
62
chk_msk_inuse 0 "2->0"
53
--
63
--
54
2.43.0
64
2.43.0
65
diff view generated by jsdifflib