diff options
author | Mat Martineau <mathew.j.martineau@linux.intel.com> | 2020-02-29 02:47:40 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-04 04:01:43 +0300 |
commit | 76c42a29c0eb15ea3fdc9867a0a52e53fb4fbd76 (patch) | |
tree | dda4bfc901f985c1b14b0a51a49c9f0e6c74bf8b /net/mptcp/protocol.c | |
parent | 1954b86016cf8522970e1b7aba801233d777ec47 (diff) | |
download | linux-76c42a29c0eb15ea3fdc9867a0a52e53fb4fbd76.tar.xz |
mptcp: Use per-subflow storage for DATA_FIN sequence number
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 <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mptcp/protocol.c')
-rw-r--r-- | net/mptcp/protocol.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 07559b45eec5..4c075a9f7ed0 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -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); @@ -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; @@ -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); @@ -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); } @@ -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; } @@ -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: |