mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	mptcp: better msk-level shutdown.
Instead of re-implementing most of inet_shutdown, re-use such helper, and implement the MPTCP-specific bits at the 'proto' level. The msk-level disconnect() can now be invoked, lets provide a suitable implementation. As a side effect, this fixes bad state management for listener sockets. The latter could lead to division by 0 oops since commitea4ca586b1("mptcp: refine MPTCP-level ack scheduling"). Fixes:43b54c6ee3("mptcp: Use full MPTCP-level disconnect state machine") Fixes:ea4ca586b1("mptcp: refine MPTCP-level ack scheduling") Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									20bc80b6f5
								
							
						
					
					
						commit
						76e2a55d16
					
				
					 1 changed files with 17 additions and 45 deletions
				
			
		| 
						 | 
					@ -2642,11 +2642,12 @@ static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mptcp_disconnect(struct sock *sk, int flags)
 | 
					static int mptcp_disconnect(struct sock *sk, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Should never be called.
 | 
						struct mptcp_subflow_context *subflow;
 | 
				
			||||||
	 * inet_stream_connect() calls ->disconnect, but that
 | 
						struct mptcp_sock *msk = mptcp_sk(sk);
 | 
				
			||||||
	 * refers to the subflow socket, not the mptcp one.
 | 
					
 | 
				
			||||||
	 */
 | 
						__mptcp_flush_join_list(msk);
 | 
				
			||||||
	WARN_ON_ONCE(1);
 | 
						mptcp_for_each_subflow(msk, subflow)
 | 
				
			||||||
 | 
							tcp_disconnect(mptcp_subflow_tcp_sock(subflow), flags);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3089,6 +3090,14 @@ bool mptcp_finish_join(struct sock *ssk)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mptcp_shutdown(struct sock *sk, int how)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						pr_debug("sk=%p, how=%d", sk, how);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((how & SEND_SHUTDOWN) && mptcp_close_state(sk))
 | 
				
			||||||
 | 
							__mptcp_wr_shutdown(sk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct proto mptcp_prot = {
 | 
					static struct proto mptcp_prot = {
 | 
				
			||||||
	.name		= "MPTCP",
 | 
						.name		= "MPTCP",
 | 
				
			||||||
	.owner		= THIS_MODULE,
 | 
						.owner		= THIS_MODULE,
 | 
				
			||||||
| 
						 | 
					@ -3098,7 +3107,7 @@ static struct proto mptcp_prot = {
 | 
				
			||||||
	.accept		= mptcp_accept,
 | 
						.accept		= mptcp_accept,
 | 
				
			||||||
	.setsockopt	= mptcp_setsockopt,
 | 
						.setsockopt	= mptcp_setsockopt,
 | 
				
			||||||
	.getsockopt	= mptcp_getsockopt,
 | 
						.getsockopt	= mptcp_getsockopt,
 | 
				
			||||||
	.shutdown	= tcp_shutdown,
 | 
						.shutdown	= mptcp_shutdown,
 | 
				
			||||||
	.destroy	= mptcp_destroy,
 | 
						.destroy	= mptcp_destroy,
 | 
				
			||||||
	.sendmsg	= mptcp_sendmsg,
 | 
						.sendmsg	= mptcp_sendmsg,
 | 
				
			||||||
	.recvmsg	= mptcp_recvmsg,
 | 
						.recvmsg	= mptcp_recvmsg,
 | 
				
			||||||
| 
						 | 
					@ -3344,43 +3353,6 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
 | 
				
			||||||
	return mask;
 | 
						return mask;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mptcp_shutdown(struct socket *sock, int how)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mptcp_sock *msk = mptcp_sk(sock->sk);
 | 
					 | 
				
			||||||
	struct sock *sk = sock->sk;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pr_debug("sk=%p, how=%d", msk, how);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lock_sock(sk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	how++;
 | 
					 | 
				
			||||||
	if ((how & ~SHUTDOWN_MASK) || !how) {
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto out_unlock;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sock->state == SS_CONNECTING) {
 | 
					 | 
				
			||||||
		if ((1 << sk->sk_state) &
 | 
					 | 
				
			||||||
		    (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))
 | 
					 | 
				
			||||||
			sock->state = SS_DISCONNECTING;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			sock->state = SS_CONNECTED;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sk->sk_shutdown |= how;
 | 
					 | 
				
			||||||
	if ((how & SEND_SHUTDOWN) && mptcp_close_state(sk))
 | 
					 | 
				
			||||||
		__mptcp_wr_shutdown(sk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Wake up anyone sleeping in poll. */
 | 
					 | 
				
			||||||
	sk->sk_state_change(sk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out_unlock:
 | 
					 | 
				
			||||||
	release_sock(sk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct proto_ops mptcp_stream_ops = {
 | 
					static const struct proto_ops mptcp_stream_ops = {
 | 
				
			||||||
	.family		   = PF_INET,
 | 
						.family		   = PF_INET,
 | 
				
			||||||
	.owner		   = THIS_MODULE,
 | 
						.owner		   = THIS_MODULE,
 | 
				
			||||||
| 
						 | 
					@ -3394,7 +3366,7 @@ static const struct proto_ops mptcp_stream_ops = {
 | 
				
			||||||
	.ioctl		   = inet_ioctl,
 | 
						.ioctl		   = inet_ioctl,
 | 
				
			||||||
	.gettstamp	   = sock_gettstamp,
 | 
						.gettstamp	   = sock_gettstamp,
 | 
				
			||||||
	.listen		   = mptcp_listen,
 | 
						.listen		   = mptcp_listen,
 | 
				
			||||||
	.shutdown	   = mptcp_shutdown,
 | 
						.shutdown	   = inet_shutdown,
 | 
				
			||||||
	.setsockopt	   = sock_common_setsockopt,
 | 
						.setsockopt	   = sock_common_setsockopt,
 | 
				
			||||||
	.getsockopt	   = sock_common_getsockopt,
 | 
						.getsockopt	   = sock_common_getsockopt,
 | 
				
			||||||
	.sendmsg	   = inet_sendmsg,
 | 
						.sendmsg	   = inet_sendmsg,
 | 
				
			||||||
| 
						 | 
					@ -3444,7 +3416,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
 | 
				
			||||||
	.ioctl		   = inet6_ioctl,
 | 
						.ioctl		   = inet6_ioctl,
 | 
				
			||||||
	.gettstamp	   = sock_gettstamp,
 | 
						.gettstamp	   = sock_gettstamp,
 | 
				
			||||||
	.listen		   = mptcp_listen,
 | 
						.listen		   = mptcp_listen,
 | 
				
			||||||
	.shutdown	   = mptcp_shutdown,
 | 
						.shutdown	   = inet_shutdown,
 | 
				
			||||||
	.setsockopt	   = sock_common_setsockopt,
 | 
						.setsockopt	   = sock_common_setsockopt,
 | 
				
			||||||
	.getsockopt	   = sock_common_getsockopt,
 | 
						.getsockopt	   = sock_common_getsockopt,
 | 
				
			||||||
	.sendmsg	   = inet6_sendmsg,
 | 
						.sendmsg	   = inet6_sendmsg,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue