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().

Reviewed-by: Mat Martineau <[email protected]>
Tested-by: Geliang Tang <[email protected]>
Signed-off-by: Paolo Abeni <[email protected]>
  • Loading branch information
Paolo Abeni authored and jenkins-tessares committed Nov 20, 2020
1 parent 0b55511 commit 0493cf3
Show file tree
Hide file tree
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
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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))
Expand Down
9 changes: 9 additions & 0 deletions net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions net/mptcp/subflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 0493cf3

Please sign in to comment.