Skip to content

Commit 54f1944

Browse files
Paolo Abenikuba-moo
authored andcommitted
mptcp: factor out mptcp_connect()
The current MPTCP connect implementation duplicates a bit of inet code and does not use nor provide a struct proto->connect callback, which in turn will not fit the upcoming fastopen implementation. Refactor such implementation to use the common helper, moving the MPTCP-specific bits into mptcp_connect(). Additionally, avoid an indirect call to the subflow connect callback. Note that the fastopen call-path invokes mptcp_connect() while already holding the subflow socket lock. Explicitly keep track of such path via a new MPTCP-level flag and handle the locking accordingly. Additionally, track the connect flags in a new msk field to allow propagating them to the subflow inet_stream_connect call. Fixes: d98a82a ("mptcp: handle defer connect in mptcp_sendmsg") Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent e72e403 commit 54f1944

File tree

2 files changed

+73
-67
lines changed

2 files changed

+73
-67
lines changed

net/mptcp/protocol.c

Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,10 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
16981698

16991699
lock_sock(ssk);
17001700

1701+
msk->connect_flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
1702+
msk->is_sendmsg = 1;
17011703
ret = tcp_sendmsg_fastopen(ssk, msg, &copied_syn, len, NULL);
1704+
msk->is_sendmsg = 0;
17021705
copied += copied_syn;
17031706
if (ret == -EINPROGRESS && copied_syn > 0) {
17041707
/* reflect the new state on the MPTCP socket */
@@ -3507,10 +3510,73 @@ static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
35073510
return put_user(answ, (int __user *)arg);
35083511
}
35093512

3513+
static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
3514+
struct mptcp_subflow_context *subflow)
3515+
{
3516+
subflow->request_mptcp = 0;
3517+
__mptcp_do_fallback(msk);
3518+
}
3519+
3520+
static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
3521+
{
3522+
struct mptcp_subflow_context *subflow;
3523+
struct mptcp_sock *msk = mptcp_sk(sk);
3524+
struct socket *ssock;
3525+
int err = -EINVAL;
3526+
3527+
ssock = __mptcp_nmpc_socket(msk);
3528+
if (!ssock)
3529+
return -EINVAL;
3530+
3531+
mptcp_token_destroy(msk);
3532+
inet_sk_state_store(sk, TCP_SYN_SENT);
3533+
subflow = mptcp_subflow_ctx(ssock->sk);
3534+
#ifdef CONFIG_TCP_MD5SIG
3535+
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
3536+
* TCP option space.
3537+
*/
3538+
if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
3539+
mptcp_subflow_early_fallback(msk, subflow);
3540+
#endif
3541+
if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk)) {
3542+
MPTCP_INC_STATS(sock_net(ssock->sk), MPTCP_MIB_TOKENFALLBACKINIT);
3543+
mptcp_subflow_early_fallback(msk, subflow);
3544+
}
3545+
if (likely(!__mptcp_check_fallback(msk)))
3546+
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE);
3547+
3548+
/* if reaching here via the fastopen/sendmsg path, the caller already
3549+
* acquired the subflow socket lock, too.
3550+
*/
3551+
if (msk->is_sendmsg)
3552+
err = __inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags, 1);
3553+
else
3554+
err = inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags);
3555+
inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
3556+
3557+
/* on successful connect, the msk state will be moved to established by
3558+
* subflow_finish_connect()
3559+
*/
3560+
if (unlikely(err && err != -EINPROGRESS)) {
3561+
inet_sk_state_store(sk, inet_sk_state_load(ssock->sk));
3562+
return err;
3563+
}
3564+
3565+
mptcp_copy_inaddrs(sk, ssock->sk);
3566+
3567+
/* unblocking connect, mptcp-level inet_stream_connect will error out
3568+
* without changing the socket state, update it here.
3569+
*/
3570+
if (err == -EINPROGRESS)
3571+
sk->sk_socket->state = ssock->state;
3572+
return err;
3573+
}
3574+
35103575
static struct proto mptcp_prot = {
35113576
.name = "MPTCP",
35123577
.owner = THIS_MODULE,
35133578
.init = mptcp_init_sock,
3579+
.connect = mptcp_connect,
35143580
.disconnect = mptcp_disconnect,
35153581
.close = mptcp_close,
35163582
.accept = mptcp_accept,
@@ -3562,78 +3628,16 @@ static int mptcp_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
35623628
return err;
35633629
}
35643630

3565-
static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
3566-
struct mptcp_subflow_context *subflow)
3567-
{
3568-
subflow->request_mptcp = 0;
3569-
__mptcp_do_fallback(msk);
3570-
}
3571-
35723631
static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
35733632
int addr_len, int flags)
35743633
{
3575-
struct mptcp_sock *msk = mptcp_sk(sock->sk);
3576-
struct mptcp_subflow_context *subflow;
3577-
struct socket *ssock;
3578-
int err = -EINVAL;
3634+
int ret;
35793635

35803636
lock_sock(sock->sk);
3581-
if (uaddr) {
3582-
if (addr_len < sizeof(uaddr->sa_family))
3583-
goto unlock;
3584-
3585-
if (uaddr->sa_family == AF_UNSPEC) {
3586-
err = mptcp_disconnect(sock->sk, flags);
3587-
sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
3588-
goto unlock;
3589-
}
3590-
}
3591-
3592-
if (sock->state != SS_UNCONNECTED && msk->subflow) {
3593-
/* pending connection or invalid state, let existing subflow
3594-
* cope with that
3595-
*/
3596-
ssock = msk->subflow;
3597-
goto do_connect;
3598-
}
3599-
3600-
ssock = __mptcp_nmpc_socket(msk);
3601-
if (!ssock)
3602-
goto unlock;
3603-
3604-
mptcp_token_destroy(msk);
3605-
inet_sk_state_store(sock->sk, TCP_SYN_SENT);
3606-
subflow = mptcp_subflow_ctx(ssock->sk);
3607-
#ifdef CONFIG_TCP_MD5SIG
3608-
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
3609-
* TCP option space.
3610-
*/
3611-
if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
3612-
mptcp_subflow_early_fallback(msk, subflow);
3613-
#endif
3614-
if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk)) {
3615-
MPTCP_INC_STATS(sock_net(ssock->sk), MPTCP_MIB_TOKENFALLBACKINIT);
3616-
mptcp_subflow_early_fallback(msk, subflow);
3617-
}
3618-
if (likely(!__mptcp_check_fallback(msk)))
3619-
MPTCP_INC_STATS(sock_net(sock->sk), MPTCP_MIB_MPCAPABLEACTIVE);
3620-
3621-
do_connect:
3622-
err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
3623-
inet_sk(sock->sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
3624-
sock->state = ssock->state;
3625-
3626-
/* on successful connect, the msk state will be moved to established by
3627-
* subflow_finish_connect()
3628-
*/
3629-
if (!err || err == -EINPROGRESS)
3630-
mptcp_copy_inaddrs(sock->sk, ssock->sk);
3631-
else
3632-
inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
3633-
3634-
unlock:
3637+
mptcp_sk(sock->sk)->connect_flags = flags;
3638+
ret = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
36353639
release_sock(sock->sk);
3636-
return err;
3640+
return ret;
36373641
}
36383642

36393643
static int mptcp_listen(struct socket *sock, int backlog)

net/mptcp/protocol.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ struct mptcp_sock {
285285
u8 mpc_endpoint_id;
286286
u8 recvmsg_inq:1,
287287
cork:1,
288-
nodelay:1;
288+
nodelay:1,
289+
is_sendmsg:1;
290+
int connect_flags;
289291
struct work_struct work;
290292
struct sk_buff *ooo_last_skb;
291293
struct rb_root out_of_order_queue;

0 commit comments

Comments
 (0)