1 // SPDX-License-Identifier: GPL-2.0
2 /* MPTCP socket monitoring support
4 * Copyright (c) 2019 Red Hat
6 * Author: Davide Caratti <dcaratti@redhat.com>
9 #include <linux/kernel.h>
10 #include <linux/net.h>
11 #include <linux/inet_diag.h>
12 #include <net/netlink.h>
15 static int subflow_get_info(struct sock
*sk
, struct sk_buff
*skb
)
17 struct mptcp_subflow_context
*sf
;
23 if (inet_sk_state_load(sk
) == TCP_LISTEN
)
26 start
= nla_nest_start_noflag(skb
, INET_ULP_INFO_MPTCP
);
30 slow
= lock_sock_fast(sk
);
32 sf
= rcu_dereference(inet_csk(sk
)->icsk_ulp_data
);
39 flags
|= MPTCP_SUBFLOW_FLAG_MCAP_REM
;
40 if (sf
->request_mptcp
)
41 flags
|= MPTCP_SUBFLOW_FLAG_MCAP_LOC
;
43 flags
|= MPTCP_SUBFLOW_FLAG_JOIN_REM
;
45 flags
|= MPTCP_SUBFLOW_FLAG_JOIN_LOC
;
47 flags
|= MPTCP_SUBFLOW_FLAG_BKUP_REM
;
49 flags
|= MPTCP_SUBFLOW_FLAG_BKUP_LOC
;
50 if (READ_ONCE(sf
->fully_established
))
51 flags
|= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED
;
52 if (sf
->conn_finished
)
53 flags
|= MPTCP_SUBFLOW_FLAG_CONNECTED
;
55 flags
|= MPTCP_SUBFLOW_FLAG_MAPVALID
;
57 if (nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_TOKEN_REM
, sf
->remote_token
) ||
58 nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_TOKEN_LOC
, sf
->token
) ||
59 nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ
,
61 nla_put_u64_64bit(skb
, MPTCP_SUBFLOW_ATTR_MAP_SEQ
, sf
->map_seq
,
62 MPTCP_SUBFLOW_ATTR_PAD
) ||
63 nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ
,
64 sf
->map_subflow_seq
) ||
65 nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_SSN_OFFSET
, sf
->ssn_offset
) ||
66 nla_put_u16(skb
, MPTCP_SUBFLOW_ATTR_MAP_DATALEN
,
68 nla_put_u32(skb
, MPTCP_SUBFLOW_ATTR_FLAGS
, flags
) ||
69 nla_put_u8(skb
, MPTCP_SUBFLOW_ATTR_ID_REM
, sf
->remote_id
) ||
70 nla_put_u8(skb
, MPTCP_SUBFLOW_ATTR_ID_LOC
, subflow_get_local_id(sf
))) {
76 unlock_sock_fast(sk
, slow
);
77 nla_nest_end(skb
, start
);
82 unlock_sock_fast(sk
, slow
);
83 nla_nest_cancel(skb
, start
);
87 static size_t subflow_get_info_size(const struct sock
*sk
)
91 size
+= nla_total_size(0) + /* INET_ULP_INFO_MPTCP */
92 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_REM */
93 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */
94 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
95 nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
96 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
97 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
98 nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
99 nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */
100 nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
101 nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_LOC */
106 void mptcp_diag_subflow_init(struct tcp_ulp_ops
*ops
)
108 ops
->get_info
= subflow_get_info
;
109 ops
->get_info_size
= subflow_get_info_size
;