Skip to content

Commit 5147dfb

Browse files
dcarattidavem330
authored andcommitted
mptcp: allow dumping subflow context to userspace
add ulp-specific diagnostic functions, so that subflow information can be dumped to userspace programs like 'ss'. v2 -> v3: - uapi: use bit macros appropriate for userspace Co-developed-by: Matthieu Baerts <[email protected]> Signed-off-by: Matthieu Baerts <[email protected]> Co-developed-by: Paolo Abeni <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Davide Caratti <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3b1d621 commit 5147dfb

File tree

7 files changed

+146
-1
lines changed

7 files changed

+146
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11727,6 +11727,7 @@ W: https://github.com/multipath-tcp/mptcp_net-next/wiki
1172711727
B: https://github.com/multipath-tcp/mptcp_net-next/issues
1172811728
S: Maintained
1172911729
F: include/net/mptcp.h
11730+
F: include/uapi/linux/mptcp.h
1173011731
F: net/mptcp/
1173111732
F: tools/testing/selftests/net/mptcp/
1173211733

include/uapi/linux/inet_diag.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ enum {
166166
INET_ULP_INFO_UNSPEC,
167167
INET_ULP_INFO_NAME,
168168
INET_ULP_INFO_TLS,
169+
INET_ULP_INFO_MPTCP,
169170
__INET_ULP_INFO_MAX,
170171
};
171172
#define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1)

include/uapi/linux/mptcp.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
2+
#ifndef _UAPI_MPTCP_H
3+
#define _UAPI_MPTCP_H
4+
5+
#include <linux/const.h>
6+
#include <linux/types.h>
7+
8+
#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
9+
#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
10+
#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2)
11+
#define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3)
12+
#define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4)
13+
#define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5)
14+
#define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6)
15+
#define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7)
16+
#define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8)
17+
18+
enum {
19+
MPTCP_SUBFLOW_ATTR_UNSPEC,
20+
MPTCP_SUBFLOW_ATTR_TOKEN_REM,
21+
MPTCP_SUBFLOW_ATTR_TOKEN_LOC,
22+
MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
23+
MPTCP_SUBFLOW_ATTR_MAP_SEQ,
24+
MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
25+
MPTCP_SUBFLOW_ATTR_SSN_OFFSET,
26+
MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
27+
MPTCP_SUBFLOW_ATTR_FLAGS,
28+
MPTCP_SUBFLOW_ATTR_ID_REM,
29+
MPTCP_SUBFLOW_ATTR_ID_LOC,
30+
MPTCP_SUBFLOW_ATTR_PAD,
31+
__MPTCP_SUBFLOW_ATTR_MAX
32+
};
33+
34+
#define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1)
35+
#endif /* _UAPI_MPTCP_H */

net/mptcp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_MPTCP) += mptcp.o
33

4-
mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o
4+
mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o

net/mptcp/diag.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* MPTCP socket monitoring support
3+
*
4+
* Copyright (c) 2019 Red Hat
5+
*
6+
* Author: Davide Caratti <[email protected]>
7+
*/
8+
9+
#include <linux/kernel.h>
10+
#include <linux/net.h>
11+
#include <linux/inet_diag.h>
12+
#include <net/netlink.h>
13+
#include <uapi/linux/mptcp.h>
14+
#include "protocol.h"
15+
16+
static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
17+
{
18+
struct mptcp_subflow_context *sf;
19+
struct nlattr *start;
20+
u32 flags = 0;
21+
int err;
22+
23+
start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP);
24+
if (!start)
25+
return -EMSGSIZE;
26+
27+
rcu_read_lock();
28+
sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
29+
if (!sf) {
30+
err = 0;
31+
goto nla_failure;
32+
}
33+
34+
if (sf->mp_capable)
35+
flags |= MPTCP_SUBFLOW_FLAG_MCAP_REM;
36+
if (sf->request_mptcp)
37+
flags |= MPTCP_SUBFLOW_FLAG_MCAP_LOC;
38+
if (sf->mp_join)
39+
flags |= MPTCP_SUBFLOW_FLAG_JOIN_REM;
40+
if (sf->request_join)
41+
flags |= MPTCP_SUBFLOW_FLAG_JOIN_LOC;
42+
if (sf->backup)
43+
flags |= MPTCP_SUBFLOW_FLAG_BKUP_REM;
44+
if (sf->request_bkup)
45+
flags |= MPTCP_SUBFLOW_FLAG_BKUP_LOC;
46+
if (sf->fully_established)
47+
flags |= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED;
48+
if (sf->conn_finished)
49+
flags |= MPTCP_SUBFLOW_FLAG_CONNECTED;
50+
if (sf->map_valid)
51+
flags |= MPTCP_SUBFLOW_FLAG_MAPVALID;
52+
53+
if (nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_REM, sf->remote_token) ||
54+
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_LOC, sf->token) ||
55+
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
56+
sf->rel_write_seq) ||
57+
nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq,
58+
MPTCP_SUBFLOW_ATTR_PAD) ||
59+
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
60+
sf->map_subflow_seq) ||
61+
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) ||
62+
nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
63+
sf->map_data_len) ||
64+
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) ||
65+
nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) ||
66+
nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, sf->local_id)) {
67+
err = -EMSGSIZE;
68+
goto nla_failure;
69+
}
70+
71+
rcu_read_unlock();
72+
nla_nest_end(skb, start);
73+
return 0;
74+
75+
nla_failure:
76+
rcu_read_unlock();
77+
nla_nest_cancel(skb, start);
78+
return err;
79+
}
80+
81+
static size_t subflow_get_info_size(const struct sock *sk)
82+
{
83+
size_t size = 0;
84+
85+
size += nla_total_size(0) + /* INET_ULP_INFO_MPTCP */
86+
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_REM */
87+
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */
88+
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
89+
nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
90+
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
91+
nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
92+
nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
93+
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */
94+
nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
95+
nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_LOC */
96+
0;
97+
return size;
98+
}
99+
100+
void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops)
101+
{
102+
ops->get_info = subflow_get_info;
103+
ops->get_info_size = subflow_get_info_size;
104+
}

net/mptcp/protocol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,6 @@ static inline bool before64(__u64 seq1, __u64 seq2)
408408

409409
#define after64(seq2, seq1) before64(seq1, seq2)
410410

411+
void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops);
412+
411413
#endif /* __MPTCP_PROTOCOL_H */

net/mptcp/subflow.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,8 @@ void mptcp_subflow_init(void)
11481148
subflow_v6m_specific.net_frag_header_len = 0;
11491149
#endif
11501150

1151+
mptcp_diag_subflow_init(&subflow_ulp_ops);
1152+
11511153
if (tcp_register_ulp(&subflow_ulp_ops) != 0)
11521154
panic("MPTCP: failed to register subflows to ULP\n");
11531155
}

0 commit comments

Comments
 (0)