Commit f284c0c7 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

mptcp: implement fastclose xmit path

Allow the MPTCP xmit path to add MP_FASTCLOSE suboption
on RST egress packets.

Additionally reorder related options writing to reduce
the number of conditionals required in the fast path.
Co-developed-by: default avatarGeliang Tang <geliang.tang@suse.com>
Signed-off-by: default avatarGeliang Tang <geliang.tang@suse.com>
Co-developed-by: default avatarMatthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: default avatarMatthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 58cd405b
...@@ -768,6 +768,28 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu ...@@ -768,6 +768,28 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu
return true; return true;
} }
static bool mptcp_established_options_fastclose(struct sock *sk,
unsigned int *size,
unsigned int remaining,
struct mptcp_out_options *opts)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
if (likely(!subflow->send_fastclose))
return false;
if (remaining < TCPOLEN_MPTCP_FASTCLOSE)
return false;
*size = TCPOLEN_MPTCP_FASTCLOSE;
opts->suboptions |= OPTION_MPTCP_FASTCLOSE;
opts->rcvr_key = msk->remote_key;
pr_debug("FASTCLOSE key=%llu", opts->rcvr_key);
return true;
}
static bool mptcp_established_options_mp_fail(struct sock *sk, static bool mptcp_established_options_mp_fail(struct sock *sk,
unsigned int *size, unsigned int *size,
unsigned int remaining, unsigned int remaining,
...@@ -806,10 +828,12 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, ...@@ -806,10 +828,12 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
return false; return false;
if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) { if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) {
if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { if (mptcp_established_options_fastclose(sk, &opt_size, remaining, opts) ||
mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
*size += opt_size; *size += opt_size;
remaining -= opt_size; remaining -= opt_size;
} }
/* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */
if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) {
*size += opt_size; *size += opt_size;
remaining -= opt_size; remaining -= opt_size;
...@@ -1251,17 +1275,8 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, ...@@ -1251,17 +1275,8 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
ptr += 2; ptr += 2;
} }
/* RST is mutually exclusive with everything else */ /* DSS, MPC, MPJ, ADD_ADDR, FASTCLOSE and RST are mutually exclusive,
if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { * see mptcp_established_options*()
*ptr++ = mptcp_option(MPTCPOPT_RST,
TCPOLEN_MPTCP_RST,
opts->reset_transient,
opts->reset_reason);
return;
}
/* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see
* mptcp_established_options*()
*/ */
if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { if (likely(OPTION_MPTCP_DSS & opts->suboptions)) {
struct mptcp_ext *mpext = &opts->ext_copy; struct mptcp_ext *mpext = &opts->ext_copy;
...@@ -1447,6 +1462,24 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, ...@@ -1447,6 +1462,24 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
ptr += 1; ptr += 1;
} }
} }
} else if (unlikely(OPTION_MPTCP_FASTCLOSE & opts->suboptions)) {
/* FASTCLOSE is mutually exclusive with others except RST */
*ptr++ = mptcp_option(MPTCPOPT_MP_FASTCLOSE,
TCPOLEN_MPTCP_FASTCLOSE,
0, 0);
put_unaligned_be64(opts->rcvr_key, ptr);
ptr += 2;
if (OPTION_MPTCP_RST & opts->suboptions)
goto mp_rst;
return;
} else if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
mp_rst:
*ptr++ = mptcp_option(MPTCPOPT_RST,
TCPOLEN_MPTCP_RST,
opts->reset_transient,
opts->reset_reason);
return;
} }
if (OPTION_MPTCP_PRIO & opts->suboptions) { if (OPTION_MPTCP_PRIO & opts->suboptions) {
......
...@@ -423,6 +423,7 @@ struct mptcp_subflow_context { ...@@ -423,6 +423,7 @@ struct mptcp_subflow_context {
backup : 1, backup : 1,
send_mp_prio : 1, send_mp_prio : 1,
send_mp_fail : 1, send_mp_fail : 1,
send_fastclose : 1,
rx_eof : 1, rx_eof : 1,
can_ack : 1, /* only after processing the remote a key */ can_ack : 1, /* only after processing the remote a key */
disposable : 1, /* ctx can be free at ulp release time */ disposable : 1, /* ctx can be free at ulp release time */
......
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