Skip to content

Commit

Permalink
mptcp: keep unaccepted MPC subflow into join list
Browse files Browse the repository at this point in the history
This will simplify all operation dealing with subflows
before accept time (e.g. data fin processing, add_addr).

The join list is already flushed by mptcp_stream_accept()
before returning the newly created msk to the user space.

This also fixes an potential bug present into the old code:
conn_list was manipulated without helding the msk lock
in mptcp_stream_accept().

Tested-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Paolo Abeni authored and Jakub Kicinski committed Nov 20, 2020
1 parent 8b819a8 commit 0397c6d
Showing 3 changed files with 22 additions and 21 deletions.
24 changes: 8 additions & 16 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
@@ -2343,7 +2343,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
if (sk_is_mptcp(newsk)) {
struct mptcp_subflow_context *subflow;
struct sock *new_mptcp_sock;
struct sock *ssk = newsk;

subflow = mptcp_subflow_ctx(newsk);
new_mptcp_sock = subflow->conn;
@@ -2358,22 +2357,8 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,

/* acquire the 2nd reference for the owning socket */
sock_hold(new_mptcp_sock);

local_bh_disable();
bh_lock_sock(new_mptcp_sock);
msk = mptcp_sk(new_mptcp_sock);
msk->first = newsk;

newsk = new_mptcp_sock;
mptcp_copy_inaddrs(newsk, ssk);
list_add(&subflow->node, &msk->conn_list);
sock_hold(ssk);

mptcp_rcv_space_init(msk, ssk);
bh_unlock_sock(new_mptcp_sock);

__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
local_bh_enable();
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
} else {
MPTCP_INC_STATS(sock_net(sk),
MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK);
@@ -2824,6 +2809,12 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
if (err == 0 && !mptcp_is_tcpsk(newsock->sk)) {
struct mptcp_sock *msk = mptcp_sk(newsock->sk);
struct mptcp_subflow_context *subflow;
struct sock *newsk = newsock->sk;
bool slowpath;

slowpath = lock_sock_fast(newsk);
mptcp_copy_inaddrs(newsk, msk->first);
mptcp_rcv_space_init(msk, msk->first);

/* set ssk->sk_socket of accept()ed flows to mptcp socket.
* This is needed so NOSPACE flag can be set from tcp stack.
@@ -2835,6 +2826,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
if (!ssk->sk_socket)
mptcp_sock_graft(ssk, newsock);
}
unlock_sock_fast(newsk, slowpath);
}

if (inet_csk_listen_poll(ssock->sk))
9 changes: 9 additions & 0 deletions net/mptcp/protocol.h
Original file line number Diff line number Diff line change
@@ -403,6 +403,15 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow)
return subflow->map_seq + mptcp_subflow_get_map_offset(subflow);
}

static inline void mptcp_add_pending_subflow(struct mptcp_sock *msk,
struct mptcp_subflow_context *subflow)
{
sock_hold(mptcp_subflow_tcp_sock(subflow));
spin_lock_bh(&msk->join_list_lock);
list_add_tail(&subflow->node, &msk->join_list);
spin_unlock_bh(&msk->join_list_lock);
}

int mptcp_is_enabled(struct net *net);
unsigned int mptcp_get_add_addr_timeout(struct net *net);
void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
10 changes: 5 additions & 5 deletions net/mptcp/subflow.c
Original file line number Diff line number Diff line change
@@ -578,6 +578,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
*/
inet_sk_state_store((void *)new_msk, TCP_ESTABLISHED);

/* link the newly created socket to the msk */
mptcp_add_pending_subflow(mptcp_sk(new_msk), ctx);
WRITE_ONCE(mptcp_sk(new_msk)->first, child);

/* new mpc subflow takes ownership of the newly
* created mptcp socket
*/
@@ -1124,11 +1128,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
if (err && err != -EINPROGRESS)
goto failed;

sock_hold(ssk);
spin_lock_bh(&msk->join_list_lock);
list_add_tail(&subflow->node, &msk->join_list);
spin_unlock_bh(&msk->join_list_lock);

mptcp_add_pending_subflow(msk, subflow);
return err;

failed:

0 comments on commit 0397c6d

Please sign in to comment.