Skip to content

Commit

Permalink
mptcp: Use per-subflow storage for DATA_FIN sequence number
Browse files Browse the repository at this point in the history
Instead of reading the MPTCP-level sequence number when sending DATA_FIN,
store the data in the subflow so it can be safely accessed when the
subflow TCP headers are written to the packet without the MPTCP-level
lock held. This also allows the MPTCP-level socket to close individual
subflows without closing the MPTCP connection.

Signed-off-by: Mat Martineau <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
mjmartineau authored and davem330 committed Mar 4, 2020
1 parent 1954b86 commit 76c42a2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 6 deletions.
5 changes: 2 additions & 3 deletions net/mptcp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
*/
ext->use_map = 1;
ext->dsn64 = 1;
ext->data_seq = mptcp_sk(subflow->conn)->write_seq;
ext->data_seq = subflow->data_fin_tx_seq;
ext->subflow_seq = 0;
ext->data_len = 1;
} else {
Expand Down Expand Up @@ -354,8 +354,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
if (mpext)
opts->ext_copy = *mpext;

if (skb && tcp_fin &&
subflow->conn->sk_state != TCP_ESTABLISHED)
if (skb && tcp_fin && subflow->data_fin_tx_enable)
mptcp_write_data_fin(subflow, &opts->ext_copy);
ret = true;
}
Expand Down
20 changes: 17 additions & 3 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ static void mptcp_cancel_work(struct sock *sk)
sock_put(sk);
}

static void mptcp_subflow_shutdown(struct sock *ssk, int how)
static void mptcp_subflow_shutdown(struct sock *ssk, int how,
bool data_fin_tx_enable, u64 data_fin_tx_seq)
{
lock_sock(ssk);

Expand All @@ -733,6 +734,14 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int how)
tcp_disconnect(ssk, O_NONBLOCK);
break;
default:
if (data_fin_tx_enable) {
struct mptcp_subflow_context *subflow;

subflow = mptcp_subflow_ctx(ssk);
subflow->data_fin_tx_seq = data_fin_tx_seq;
subflow->data_fin_tx_enable = 1;
}

ssk->sk_shutdown |= how;
tcp_shutdown(ssk, how);
break;
Expand All @@ -749,6 +758,7 @@ static void mptcp_close(struct sock *sk, long timeout)
struct mptcp_subflow_context *subflow, *tmp;
struct mptcp_sock *msk = mptcp_sk(sk);
LIST_HEAD(conn_list);
u64 data_fin_tx_seq;

lock_sock(sk);

Expand All @@ -757,11 +767,15 @@ static void mptcp_close(struct sock *sk, long timeout)

list_splice_init(&msk->conn_list, &conn_list);

data_fin_tx_seq = msk->write_seq;

release_sock(sk);

list_for_each_entry_safe(subflow, tmp, &conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);

subflow->data_fin_tx_seq = data_fin_tx_seq;
subflow->data_fin_tx_enable = 1;
__mptcp_close_ssk(sk, ssk, subflow, timeout);
}

Expand Down Expand Up @@ -854,7 +868,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
*err = -ENOBUFS;
local_bh_enable();
release_sock(sk);
mptcp_subflow_shutdown(newsk, SHUT_RDWR + 1);
mptcp_subflow_shutdown(newsk, SHUT_RDWR + 1, 0, 0);
tcp_close(newsk, 0);
return NULL;
}
Expand Down Expand Up @@ -1309,7 +1323,7 @@ static int mptcp_shutdown(struct socket *sock, int how)
mptcp_for_each_subflow(msk, subflow) {
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);

mptcp_subflow_shutdown(tcp_sk, how);
mptcp_subflow_shutdown(tcp_sk, how, 1, msk->write_seq);
}

out_unlock:
Expand Down
2 changes: 2 additions & 0 deletions net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ struct mptcp_subflow_context {
mpc_map : 1,
data_avail : 1,
rx_eof : 1,
data_fin_tx_enable : 1,
can_ack : 1; /* only after processing the remote a key */
u64 data_fin_tx_seq;

struct sock *tcp_sock; /* tcp sk backpointer */
struct sock *conn; /* parent mptcp_sock */
Expand Down

0 comments on commit 76c42a2

Please sign in to comment.