diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index f532a8e1eebb8..3d7267b451810 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -496,4 +496,14 @@ static inline void mptcp_do_fallback(struct sock *sk) #define pr_fallback(a) do { pr_debug("%s:fallback to TCP (msk=%p)",\ __FUNCTION__, a); } while (0) +static inline bool subflow_simultaneous_connect(struct sock *sk) +{ + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + struct sock *parent = subflow->conn; + + return sk->sk_state == TCP_ESTABLISHED && + !mptcp_sk(parent)->pm.server_side && + !subflow->conn_finished; +} + #endif /* __MPTCP_PROTOCOL_H */ diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 364ddd44413a5..664aa9158363e 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1116,6 +1116,16 @@ static void subflow_state_change(struct sock *sk) __subflow_state_change(sk); + if (subflow_simultaneous_connect(sk)) { + mptcp_do_fallback(sk); + pr_fallback(mptcp_sk(parent)); + subflow->conn_finished = 1; + if (inet_sk_state_load(parent) == TCP_SYN_SENT) { + inet_sk_state_store(parent, TCP_ESTABLISHED); + parent->sk_state_change(parent); + } + } + /* as recvmsg() does not acquire the subflow socket for ssk selection * a fin packet carrying a DSS can be unnoticed if we don't trigger * the data available machinery here.