forked from mirrors/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>
This commit is contained in:
		
							parent
							
								
									3b1d6210a9
								
							
						
					
					
						commit
						5147dfb508
					
				
					 7 changed files with 146 additions and 1 deletions
				
			
		|  | @ -11727,6 +11727,7 @@ W:	https://github.com/multipath-tcp/mptcp_net-next/wiki | ||||||
| B:	https://github.com/multipath-tcp/mptcp_net-next/issues | B:	https://github.com/multipath-tcp/mptcp_net-next/issues | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	include/net/mptcp.h | F:	include/net/mptcp.h | ||||||
|  | F:	include/uapi/linux/mptcp.h | ||||||
| F:	net/mptcp/ | F:	net/mptcp/ | ||||||
| F:	tools/testing/selftests/net/mptcp/ | F:	tools/testing/selftests/net/mptcp/ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -166,6 +166,7 @@ enum { | ||||||
| 	INET_ULP_INFO_UNSPEC, | 	INET_ULP_INFO_UNSPEC, | ||||||
| 	INET_ULP_INFO_NAME, | 	INET_ULP_INFO_NAME, | ||||||
| 	INET_ULP_INFO_TLS, | 	INET_ULP_INFO_TLS, | ||||||
|  | 	INET_ULP_INFO_MPTCP, | ||||||
| 	__INET_ULP_INFO_MAX, | 	__INET_ULP_INFO_MAX, | ||||||
| }; | }; | ||||||
| #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) | #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								include/uapi/linux/mptcp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/uapi/linux/mptcp.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ | ||||||
|  | #ifndef _UAPI_MPTCP_H | ||||||
|  | #define _UAPI_MPTCP_H | ||||||
|  | 
 | ||||||
|  | #include <linux/const.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | 
 | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_MCAP_REM		_BITUL(0) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_MCAP_LOC		_BITUL(1) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_JOIN_REM		_BITUL(2) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_JOIN_LOC		_BITUL(3) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_BKUP_REM		_BITUL(4) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_BKUP_LOC		_BITUL(5) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED	_BITUL(6) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_CONNECTED		_BITUL(7) | ||||||
|  | #define MPTCP_SUBFLOW_FLAG_MAPVALID		_BITUL(8) | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_UNSPEC, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_TOKEN_REM, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_TOKEN_LOC, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_MAP_SEQ, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_SSN_OFFSET, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_MAP_DATALEN, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_FLAGS, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_ID_REM, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_ID_LOC, | ||||||
|  | 	MPTCP_SUBFLOW_ATTR_PAD, | ||||||
|  | 	__MPTCP_SUBFLOW_ATTR_MAX | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1) | ||||||
|  | #endif /* _UAPI_MPTCP_H */ | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| # SPDX-License-Identifier: GPL-2.0
 | # SPDX-License-Identifier: GPL-2.0
 | ||||||
| obj-$(CONFIG_MPTCP) += mptcp.o | obj-$(CONFIG_MPTCP) += mptcp.o | ||||||
| 
 | 
 | ||||||
| mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o | mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								net/mptcp/diag.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								net/mptcp/diag.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0
 | ||||||
|  | /* MPTCP socket monitoring support
 | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2019 Red Hat | ||||||
|  |  * | ||||||
|  |  * Author: Davide Caratti <dcaratti@redhat.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/net.h> | ||||||
|  | #include <linux/inet_diag.h> | ||||||
|  | #include <net/netlink.h> | ||||||
|  | #include <uapi/linux/mptcp.h> | ||||||
|  | #include "protocol.h" | ||||||
|  | 
 | ||||||
|  | static int subflow_get_info(const struct sock *sk, struct sk_buff *skb) | ||||||
|  | { | ||||||
|  | 	struct mptcp_subflow_context *sf; | ||||||
|  | 	struct nlattr *start; | ||||||
|  | 	u32 flags = 0; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP); | ||||||
|  | 	if (!start) | ||||||
|  | 		return -EMSGSIZE; | ||||||
|  | 
 | ||||||
|  | 	rcu_read_lock(); | ||||||
|  | 	sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data); | ||||||
|  | 	if (!sf) { | ||||||
|  | 		err = 0; | ||||||
|  | 		goto nla_failure; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (sf->mp_capable) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_MCAP_REM; | ||||||
|  | 	if (sf->request_mptcp) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_MCAP_LOC; | ||||||
|  | 	if (sf->mp_join) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_JOIN_REM; | ||||||
|  | 	if (sf->request_join) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_JOIN_LOC; | ||||||
|  | 	if (sf->backup) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_BKUP_REM; | ||||||
|  | 	if (sf->request_bkup) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_BKUP_LOC; | ||||||
|  | 	if (sf->fully_established) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED; | ||||||
|  | 	if (sf->conn_finished) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_CONNECTED; | ||||||
|  | 	if (sf->map_valid) | ||||||
|  | 		flags |= MPTCP_SUBFLOW_FLAG_MAPVALID; | ||||||
|  | 
 | ||||||
|  | 	if (nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_REM, sf->remote_token) || | ||||||
|  | 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_LOC, sf->token) || | ||||||
|  | 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, | ||||||
|  | 			sf->rel_write_seq) || | ||||||
|  | 	    nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq, | ||||||
|  | 			      MPTCP_SUBFLOW_ATTR_PAD) || | ||||||
|  | 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, | ||||||
|  | 			sf->map_subflow_seq) || | ||||||
|  | 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) || | ||||||
|  | 	    nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN, | ||||||
|  | 			sf->map_data_len) || | ||||||
|  | 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) || | ||||||
|  | 	    nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) || | ||||||
|  | 	    nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, sf->local_id)) { | ||||||
|  | 		err = -EMSGSIZE; | ||||||
|  | 		goto nla_failure; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rcu_read_unlock(); | ||||||
|  | 	nla_nest_end(skb, start); | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | nla_failure: | ||||||
|  | 	rcu_read_unlock(); | ||||||
|  | 	nla_nest_cancel(skb, start); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static size_t subflow_get_info_size(const struct sock *sk) | ||||||
|  | { | ||||||
|  | 	size_t size = 0; | ||||||
|  | 
 | ||||||
|  | 	size += nla_total_size(0) +	/* INET_ULP_INFO_MPTCP */ | ||||||
|  | 		nla_total_size(4) +	/* MPTCP_SUBFLOW_ATTR_TOKEN_REM */ | ||||||
|  | 		nla_total_size(4) +	/* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */ | ||||||
|  | 		nla_total_size(4) +	/* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */ | ||||||
|  | 		nla_total_size_64bit(8) +	/* MPTCP_SUBFLOW_ATTR_MAP_SEQ */ | ||||||
|  | 		nla_total_size(4) +	/* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */ | ||||||
|  | 		nla_total_size(2) +	/* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ | ||||||
|  | 		nla_total_size(2) +	/* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */ | ||||||
|  | 		nla_total_size(4) +	/* MPTCP_SUBFLOW_ATTR_FLAGS */ | ||||||
|  | 		nla_total_size(1) +	/* MPTCP_SUBFLOW_ATTR_ID_REM */ | ||||||
|  | 		nla_total_size(1) +	/* MPTCP_SUBFLOW_ATTR_ID_LOC */ | ||||||
|  | 		0; | ||||||
|  | 	return size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops) | ||||||
|  | { | ||||||
|  | 	ops->get_info = subflow_get_info; | ||||||
|  | 	ops->get_info_size = subflow_get_info_size; | ||||||
|  | } | ||||||
|  | @ -408,4 +408,6 @@ static inline bool before64(__u64 seq1, __u64 seq2) | ||||||
| 
 | 
 | ||||||
| #define after64(seq2, seq1)	before64(seq1, seq2) | #define after64(seq2, seq1)	before64(seq1, seq2) | ||||||
| 
 | 
 | ||||||
|  | void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops); | ||||||
|  | 
 | ||||||
| #endif /* __MPTCP_PROTOCOL_H */ | #endif /* __MPTCP_PROTOCOL_H */ | ||||||
|  |  | ||||||
|  | @ -1148,6 +1148,8 @@ void mptcp_subflow_init(void) | ||||||
| 	subflow_v6m_specific.net_frag_header_len = 0; | 	subflow_v6m_specific.net_frag_header_len = 0; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | 	mptcp_diag_subflow_init(&subflow_ulp_ops); | ||||||
|  | 
 | ||||||
| 	if (tcp_register_ulp(&subflow_ulp_ops) != 0) | 	if (tcp_register_ulp(&subflow_ulp_ops) != 0) | ||||||
| 		panic("MPTCP: failed to register subflows to ULP\n"); | 		panic("MPTCP: failed to register subflows to ULP\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Davide Caratti
						Davide Caratti