Commit 7279da61 authored by Mat Martineau's avatar Mat Martineau Committed by David S. Miller

mptcp: Use MPTCP-level flag for sending DATA_FIN

Since DATA_FIN information is the same for every subflow, store it only
in the mptcp_sock.
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 242e63f6
...@@ -451,6 +451,8 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb, ...@@ -451,6 +451,8 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow, static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
struct sk_buff *skb, struct mptcp_ext *ext) struct sk_buff *skb, struct mptcp_ext *ext)
{ {
u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq);
if (!ext->use_map || !skb->len) { if (!ext->use_map || !skb->len) {
/* RFC6824 requires a DSS mapping with specific values /* RFC6824 requires a DSS mapping with specific values
* if DATA_FIN is set but no data payload is mapped * if DATA_FIN is set but no data payload is mapped
...@@ -458,10 +460,13 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow, ...@@ -458,10 +460,13 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
ext->data_fin = 1; ext->data_fin = 1;
ext->use_map = 1; ext->use_map = 1;
ext->dsn64 = 1; ext->dsn64 = 1;
ext->data_seq = subflow->data_fin_tx_seq; /* The write_seq value has already been incremented, so
* the actual sequence number for the DATA_FIN is one less.
*/
ext->data_seq = data_fin_tx_seq - 1;
ext->subflow_seq = 0; ext->subflow_seq = 0;
ext->data_len = 1; ext->data_len = 1;
} else if (ext->data_seq + ext->data_len == subflow->data_fin_tx_seq) { } else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
/* If there's an existing DSS mapping and it is the /* If there's an existing DSS mapping and it is the
* final mapping, DATA_FIN consumes 1 additional byte of * final mapping, DATA_FIN consumes 1 additional byte of
* mapping space. * mapping space.
...@@ -477,15 +482,17 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -477,15 +482,17 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
struct mptcp_out_options *opts) struct mptcp_out_options *opts)
{ {
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
unsigned int dss_size = 0; unsigned int dss_size = 0;
u64 snd_data_fin_enable;
struct mptcp_ext *mpext; struct mptcp_ext *mpext;
struct mptcp_sock *msk;
unsigned int ack_size; unsigned int ack_size;
bool ret = false; bool ret = false;
mpext = skb ? mptcp_get_ext(skb) : NULL; mpext = skb ? mptcp_get_ext(skb) : NULL;
snd_data_fin_enable = READ_ONCE(msk->snd_data_fin_enable);
if (!skb || (mpext && mpext->use_map) || subflow->data_fin_tx_enable) { if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
unsigned int map_size; unsigned int map_size;
map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64; map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
...@@ -495,7 +502,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -495,7 +502,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
if (mpext) if (mpext)
opts->ext_copy = *mpext; opts->ext_copy = *mpext;
if (skb && subflow->data_fin_tx_enable) if (skb && snd_data_fin_enable)
mptcp_write_data_fin(subflow, skb, &opts->ext_copy); mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
ret = true; ret = true;
} }
...@@ -504,7 +511,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -504,7 +511,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
* if the first subflow may have the already the remote key handy * if the first subflow may have the already the remote key handy
*/ */
opts->ext_copy.use_ack = 0; opts->ext_copy.use_ack = 0;
msk = mptcp_sk(subflow->conn);
if (!READ_ONCE(msk->can_ack)) { if (!READ_ONCE(msk->can_ack)) {
*size = ALIGN(dss_size, 4); *size = ALIGN(dss_size, 4);
return ret; return ret;
......
...@@ -1391,8 +1391,7 @@ static void mptcp_cancel_work(struct sock *sk) ...@@ -1391,8 +1391,7 @@ static void mptcp_cancel_work(struct sock *sk)
sock_put(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); lock_sock(ssk);
...@@ -1405,14 +1404,6 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int how, ...@@ -1405,14 +1404,6 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int how,
tcp_disconnect(ssk, O_NONBLOCK); tcp_disconnect(ssk, O_NONBLOCK);
break; break;
default: 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; ssk->sk_shutdown |= how;
tcp_shutdown(ssk, how); tcp_shutdown(ssk, how);
break; break;
...@@ -1426,7 +1417,6 @@ static void mptcp_close(struct sock *sk, long timeout) ...@@ -1426,7 +1417,6 @@ static void mptcp_close(struct sock *sk, long timeout)
struct mptcp_subflow_context *subflow, *tmp; struct mptcp_subflow_context *subflow, *tmp;
struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_sock *msk = mptcp_sk(sk);
LIST_HEAD(conn_list); LIST_HEAD(conn_list);
u64 data_fin_tx_seq;
lock_sock(sk); lock_sock(sk);
...@@ -1440,7 +1430,7 @@ static void mptcp_close(struct sock *sk, long timeout) ...@@ -1440,7 +1430,7 @@ static void mptcp_close(struct sock *sk, long timeout)
spin_unlock_bh(&msk->join_list_lock); spin_unlock_bh(&msk->join_list_lock);
list_splice_init(&msk->conn_list, &conn_list); list_splice_init(&msk->conn_list, &conn_list);
data_fin_tx_seq = msk->write_seq; msk->snd_data_fin_enable = 1;
__mptcp_clear_xmit(sk); __mptcp_clear_xmit(sk);
...@@ -1448,9 +1438,6 @@ static void mptcp_close(struct sock *sk, long timeout) ...@@ -1448,9 +1438,6 @@ static void mptcp_close(struct sock *sk, long timeout)
list_for_each_entry_safe(subflow, tmp, &conn_list, node) { list_for_each_entry_safe(subflow, tmp, &conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow); 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); __mptcp_close_ssk(sk, ssk, subflow, timeout);
} }
...@@ -2146,10 +2133,12 @@ static int mptcp_shutdown(struct socket *sock, int how) ...@@ -2146,10 +2133,12 @@ static int mptcp_shutdown(struct socket *sock, int how)
} }
__mptcp_flush_join_list(msk); __mptcp_flush_join_list(msk);
msk->snd_data_fin_enable = 1;
mptcp_for_each_subflow(msk, subflow) { mptcp_for_each_subflow(msk, subflow) {
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow); struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
mptcp_subflow_shutdown(tcp_sk, how, 1, msk->write_seq); mptcp_subflow_shutdown(tcp_sk, how);
} }
/* Wake up anyone sleeping in poll. */ /* Wake up anyone sleeping in poll. */
......
...@@ -199,6 +199,7 @@ struct mptcp_sock { ...@@ -199,6 +199,7 @@ struct mptcp_sock {
unsigned long flags; unsigned long flags;
bool can_ack; bool can_ack;
bool fully_established; bool fully_established;
bool snd_data_fin_enable;
spinlock_t join_list_lock; spinlock_t join_list_lock;
struct work_struct work; struct work_struct work;
struct list_head conn_list; struct list_head conn_list;
...@@ -291,10 +292,8 @@ struct mptcp_subflow_context { ...@@ -291,10 +292,8 @@ struct mptcp_subflow_context {
backup : 1, backup : 1,
data_avail : 1, data_avail : 1,
rx_eof : 1, rx_eof : 1,
data_fin_tx_enable : 1,
use_64bit_ack : 1, /* Set when we received a 64-bit DSN */ use_64bit_ack : 1, /* Set when we received a 64-bit DSN */
can_ack : 1; /* only after processing the remote a key */ can_ack : 1; /* only after processing the remote a key */
u64 data_fin_tx_seq;
u32 remote_nonce; u32 remote_nonce;
u64 thmac; u64 thmac;
u32 local_nonce; u32 local_nonce;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment