OSDN Git Service

mptcp: avoid additional __inet_stream_connect() call
authorPaolo Abeni <pabeni@redhat.com>
Fri, 11 Aug 2023 15:57:15 +0000 (17:57 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 14 Aug 2023 06:06:13 +0000 (07:06 +0100)
The mptcp protocol maintains an additional socket just to easily
invoke a few stream operations on the first subflow. One of them is
__inet_stream_connect().

We are going to remove the first subflow socket soon, so avoid
the additional indirection via at connect time, calling directly
into the sock-level connect() ops.

The sk-level connect never return -EINPROGRESS, cleanup the error
path accordingly. Additionally, the ssk status on error is always
TCP_CLOSE. Avoid unneeded access to the subflow sk state.

No functional change intended.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mptcp/protocol.c

index abb3105..b888d63 100644 (file)
@@ -3589,22 +3589,24 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct mptcp_sock *msk = mptcp_sk(sk);
        struct socket *ssock;
        int err = -EINVAL;
+       struct sock *ssk;
 
        ssock = __mptcp_nmpc_socket(msk);
        if (IS_ERR(ssock))
                return PTR_ERR(ssock);
 
        inet_sk_state_store(sk, TCP_SYN_SENT);
-       subflow = mptcp_subflow_ctx(ssock->sk);
+       ssk = msk->first;
+       subflow = mptcp_subflow_ctx(ssk);
 #ifdef CONFIG_TCP_MD5SIG
        /* no MPTCP if MD5SIG is enabled on this socket or we may run out of
         * TCP option space.
         */
-       if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
+       if (rcu_access_pointer(tcp_sk(ssk)->md5sig_info))
                mptcp_subflow_early_fallback(msk, subflow);
 #endif
-       if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk)) {
-               MPTCP_INC_STATS(sock_net(ssock->sk), MPTCP_MIB_TOKENFALLBACKINIT);
+       if (subflow->request_mptcp && mptcp_token_new_connect(ssk)) {
+               MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT);
                mptcp_subflow_early_fallback(msk, subflow);
        }
        if (likely(!__mptcp_check_fallback(msk)))
@@ -3613,27 +3615,42 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        /* if reaching here via the fastopen/sendmsg path, the caller already
         * acquired the subflow socket lock, too.
         */
-       if (msk->fastopening)
-               err = __inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK, 1);
-       else
-               err = inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK);
-       inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
+       if (!msk->fastopening)
+               lock_sock(ssk);
+
+       /* the following mirrors closely a very small chunk of code from
+        * __inet_stream_connect()
+        */
+       if (ssk->sk_state != TCP_CLOSE)
+               goto out;
+
+       if (BPF_CGROUP_PRE_CONNECT_ENABLED(ssk)) {
+               err = ssk->sk_prot->pre_connect(ssk, uaddr, addr_len);
+               if (err)
+                       goto out;
+       }
+
+       err = ssk->sk_prot->connect(ssk, uaddr, addr_len);
+       if (err < 0)
+               goto out;
+
+       inet_sk(sk)->defer_connect = inet_sk(ssk)->defer_connect;
+
+out:
+       if (!msk->fastopening)
+               release_sock(ssk);
 
        /* on successful connect, the msk state will be moved to established by
         * subflow_finish_connect()
         */
-       if (unlikely(err && err != -EINPROGRESS)) {
+       if (unlikely(err)) {
                /* avoid leaving a dangling token in an unconnected socket */
                mptcp_token_destroy(msk);
-               inet_sk_state_store(sk, inet_sk_state_load(ssock->sk));
+               inet_sk_state_store(sk, TCP_CLOSE);
                return err;
        }
 
-       mptcp_copy_inaddrs(sk, ssock->sk);
-
-       /* silence EINPROGRESS and let the caller inet_stream_connect
-        * handle the connection in progress
-        */
+       mptcp_copy_inaddrs(sk, ssk);
        return 0;
 }