mptcp: fix connect timeout handling
commit 786fc12457268cc9b555dde6c22ae7300d4b40e1 upstream.
Ondrej reported a functional issue WRT timeout handling on connect
with a nice reproducer.
The problem is that the current mptcp connect waits for both the
MPTCP socket level timeout, and the first subflow socket timeout.
The latter is not influenced/touched by the exposed setsockopt().
Overall the above makes the SO_SNDTIMEO a no-op on connect.
Since mptcp_connect is invoked via inet_stream_connect and the
latter properly handle the MPTCP level timeout, we can address the
issue making the nested subflow level connect always unblocking.
This also allow simplifying a bit the code, dropping an ugly hack
to handle the fastopen and custom proto_ops connect.
The issues predates the blamed commit below, but the current resolution
requires the infrastructure introduced there.
Fixes: 54f1944ed6
("mptcp: factor out mptcp_connect()")
Reported-by: Ondrej Mosnacek <omosnace@redhat.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/399
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
97ecfe67f5
commit
977a63afd4
@ -1683,7 +1683,6 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct sock *ssk, struct msgh
|
|||||||
|
|
||||||
lock_sock(ssk);
|
lock_sock(ssk);
|
||||||
msg->msg_flags |= MSG_DONTWAIT;
|
msg->msg_flags |= MSG_DONTWAIT;
|
||||||
msk->connect_flags = O_NONBLOCK;
|
|
||||||
msk->fastopening = 1;
|
msk->fastopening = 1;
|
||||||
ret = tcp_sendmsg_fastopen(ssk, msg, copied_syn, len, NULL);
|
ret = tcp_sendmsg_fastopen(ssk, msg, copied_syn, len, NULL);
|
||||||
msk->fastopening = 0;
|
msk->fastopening = 0;
|
||||||
@ -3638,9 +3637,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||||||
* acquired the subflow socket lock, too.
|
* acquired the subflow socket lock, too.
|
||||||
*/
|
*/
|
||||||
if (msk->fastopening)
|
if (msk->fastopening)
|
||||||
err = __inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags, 1);
|
err = __inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK, 1);
|
||||||
else
|
else
|
||||||
err = inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags);
|
err = inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK);
|
||||||
inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
|
inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
|
||||||
|
|
||||||
/* on successful connect, the msk state will be moved to established by
|
/* on successful connect, the msk state will be moved to established by
|
||||||
@ -3653,12 +3652,10 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||||||
|
|
||||||
mptcp_copy_inaddrs(sk, ssock->sk);
|
mptcp_copy_inaddrs(sk, ssock->sk);
|
||||||
|
|
||||||
/* unblocking connect, mptcp-level inet_stream_connect will error out
|
/* silence EINPROGRESS and let the caller inet_stream_connect
|
||||||
* without changing the socket state, update it here.
|
* handle the connection in progress
|
||||||
*/
|
*/
|
||||||
if (err == -EINPROGRESS)
|
return 0;
|
||||||
sk->sk_socket->state = ssock->state;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto mptcp_prot = {
|
static struct proto mptcp_prot = {
|
||||||
@ -3717,18 +3714,6 @@ static int mptcp_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
|
|
||||||
int addr_len, int flags)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
lock_sock(sock->sk);
|
|
||||||
mptcp_sk(sock->sk)->connect_flags = flags;
|
|
||||||
ret = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
|
|
||||||
release_sock(sock->sk);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mptcp_listen(struct socket *sock, int backlog)
|
static int mptcp_listen(struct socket *sock, int backlog)
|
||||||
{
|
{
|
||||||
struct mptcp_sock *msk = mptcp_sk(sock->sk);
|
struct mptcp_sock *msk = mptcp_sk(sock->sk);
|
||||||
@ -3879,7 +3864,7 @@ static const struct proto_ops mptcp_stream_ops = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.release = inet_release,
|
.release = inet_release,
|
||||||
.bind = mptcp_bind,
|
.bind = mptcp_bind,
|
||||||
.connect = mptcp_stream_connect,
|
.connect = inet_stream_connect,
|
||||||
.socketpair = sock_no_socketpair,
|
.socketpair = sock_no_socketpair,
|
||||||
.accept = mptcp_stream_accept,
|
.accept = mptcp_stream_accept,
|
||||||
.getname = inet_getname,
|
.getname = inet_getname,
|
||||||
@ -3974,7 +3959,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.release = inet6_release,
|
.release = inet6_release,
|
||||||
.bind = mptcp_bind,
|
.bind = mptcp_bind,
|
||||||
.connect = mptcp_stream_connect,
|
.connect = inet_stream_connect,
|
||||||
.socketpair = sock_no_socketpair,
|
.socketpair = sock_no_socketpair,
|
||||||
.accept = mptcp_stream_accept,
|
.accept = mptcp_stream_accept,
|
||||||
.getname = inet6_getname,
|
.getname = inet6_getname,
|
||||||
|
@ -288,7 +288,6 @@ struct mptcp_sock {
|
|||||||
nodelay:1,
|
nodelay:1,
|
||||||
fastopening:1,
|
fastopening:1,
|
||||||
in_accept_queue:1;
|
in_accept_queue:1;
|
||||||
int connect_flags;
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct sk_buff *ooo_last_skb;
|
struct sk_buff *ooo_last_skb;
|
||||||
struct rb_root out_of_order_queue;
|
struct rb_root out_of_order_queue;
|
||||||
|
Loading…
Reference in New Issue
Block a user