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 | ||||
| S:	Maintained | ||||
| F:	include/net/mptcp.h | ||||
| F:	include/uapi/linux/mptcp.h | ||||
| F:	net/mptcp/ | ||||
| F:	tools/testing/selftests/net/mptcp/ | ||||
| 
 | ||||
|  |  | |||
|  | @ -166,6 +166,7 @@ enum { | |||
| 	INET_ULP_INFO_UNSPEC, | ||||
| 	INET_ULP_INFO_NAME, | ||||
| 	INET_ULP_INFO_TLS, | ||||
| 	INET_ULP_INFO_MPTCP, | ||||
| 	__INET_ULP_INFO_MAX, | ||||
| }; | ||||
| #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
 | ||||
| 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) | ||||
| 
 | ||||
| void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops); | ||||
| 
 | ||||
| #endif /* __MPTCP_PROTOCOL_H */ | ||||
|  |  | |||
|  | @ -1148,6 +1148,8 @@ void mptcp_subflow_init(void) | |||
| 	subflow_v6m_specific.net_frag_header_len = 0; | ||||
| #endif | ||||
| 
 | ||||
| 	mptcp_diag_subflow_init(&subflow_ulp_ops); | ||||
| 
 | ||||
| 	if (tcp_register_ulp(&subflow_ulp_ops) != 0) | ||||
| 		panic("MPTCP: failed to register subflows to ULP\n"); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Davide Caratti
						Davide Caratti