Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Davide Caratti and committed by
David S. Miller
5147dfb5 3b1d6210

+146 -1
+1
MAINTAINERS
··· 11727 11727 B: https://github.com/multipath-tcp/mptcp_net-next/issues 11728 11728 S: Maintained 11729 11729 F: include/net/mptcp.h 11730 + F: include/uapi/linux/mptcp.h 11730 11731 F: net/mptcp/ 11731 11732 F: tools/testing/selftests/net/mptcp/ 11732 11733
+1
include/uapi/linux/inet_diag.h
··· 166 166 INET_ULP_INFO_UNSPEC, 167 167 INET_ULP_INFO_NAME, 168 168 INET_ULP_INFO_TLS, 169 + INET_ULP_INFO_MPTCP, 169 170 __INET_ULP_INFO_MAX, 170 171 }; 171 172 #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1)
+35
include/uapi/linux/mptcp.h
··· 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 */
+1 -1
net/mptcp/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_MPTCP) += mptcp.o 3 3 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
+104
net/mptcp/diag.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* MPTCP socket monitoring support 3 + * 4 + * Copyright (c) 2019 Red Hat 5 + * 6 + * Author: Davide Caratti <dcaratti@redhat.com> 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 + }
+2
net/mptcp/protocol.h
··· 408 408 409 409 #define after64(seq2, seq1) before64(seq1, seq2) 410 410 411 + void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops); 412 + 411 413 #endif /* __MPTCP_PROTOCOL_H */
+2
net/mptcp/subflow.c
··· 1148 1148 subflow_v6m_specific.net_frag_header_len = 0; 1149 1149 #endif 1150 1150 1151 + mptcp_diag_subflow_init(&subflow_ulp_ops); 1152 + 1151 1153 if (tcp_register_ulp(&subflow_ulp_ops) != 0) 1152 1154 panic("MPTCP: failed to register subflows to ULP\n"); 1153 1155 }