Commit c25aeb4e authored by Geliang Tang's avatar Geliang Tang Committed by David S. Miller

mptcp: MP_FAIL suboption sending

This patch added the MP_FAIL suboption sending support.

Add a new flag named send_mp_fail in struct mptcp_subflow_context. If
this flag is set, send out MP_FAIL suboption.

Add a new member fail_seq in struct mptcp_out_options to save the data
sequence number to put into the MP_FAIL suboption.

An MP_FAIL option could be included in a RST or on the subflow-level
ACK.
Suggested-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarGeliang Tang <geliangtang@xiaomi.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d7b26908
...@@ -74,7 +74,10 @@ struct mptcp_out_options { ...@@ -74,7 +74,10 @@ struct mptcp_out_options {
struct mptcp_addr_info addr; struct mptcp_addr_info addr;
u64 ahmac; u64 ahmac;
}; };
struct mptcp_ext ext_copy; struct {
struct mptcp_ext ext_copy;
u64 fail_seq;
};
struct { struct {
u32 nonce; u32 nonce;
u32 token; u32 token;
......
...@@ -767,7 +767,7 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, ...@@ -767,7 +767,7 @@ static bool mptcp_established_options_mp_prio(struct sock *sk,
return true; return true;
} }
static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb, static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb,
unsigned int *size, unsigned int *size,
unsigned int remaining, unsigned int remaining,
struct mptcp_out_options *opts) struct mptcp_out_options *opts)
...@@ -775,12 +775,36 @@ static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_bu ...@@ -775,12 +775,36 @@ static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_bu
const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
if (remaining < TCPOLEN_MPTCP_RST) if (remaining < TCPOLEN_MPTCP_RST)
return; return false;
*size = TCPOLEN_MPTCP_RST; *size = TCPOLEN_MPTCP_RST;
opts->suboptions |= OPTION_MPTCP_RST; opts->suboptions |= OPTION_MPTCP_RST;
opts->reset_transient = subflow->reset_transient; opts->reset_transient = subflow->reset_transient;
opts->reset_reason = subflow->reset_reason; opts->reset_reason = subflow->reset_reason;
return true;
}
static bool mptcp_established_options_mp_fail(struct sock *sk,
unsigned int *size,
unsigned int remaining,
struct mptcp_out_options *opts)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
if (likely(!subflow->send_mp_fail))
return false;
if (remaining < TCPOLEN_MPTCP_FAIL)
return false;
*size = TCPOLEN_MPTCP_FAIL;
opts->suboptions |= OPTION_MPTCP_FAIL;
opts->fail_seq = subflow->map_seq;
pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq);
return true;
} }
bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
...@@ -799,15 +823,28 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, ...@@ -799,15 +823,28 @@ 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)) {
mptcp_established_options_rst(sk, skb, size, remaining, opts); if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
*size += opt_size;
remaining -= opt_size;
}
if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) {
*size += opt_size;
remaining -= opt_size;
}
return true; return true;
} }
snd_data_fin = mptcp_data_fin_enabled(msk); snd_data_fin = mptcp_data_fin_enabled(msk);
if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts)) if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts))
ret = true; ret = true;
else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) {
ret = true; ret = true;
if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
*size += opt_size;
remaining -= opt_size;
return true;
}
}
/* we reserved enough space for the above options, and exceeding the /* we reserved enough space for the above options, and exceeding the
* TCP option space would be fatal * TCP option space would be fatal
...@@ -1210,6 +1247,20 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) ...@@ -1210,6 +1247,20 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext)
void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
struct mptcp_out_options *opts) struct mptcp_out_options *opts)
{ {
if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) {
const struct sock *ssk = (const struct sock *)tp;
struct mptcp_subflow_context *subflow;
subflow = mptcp_subflow_ctx(ssk);
subflow->send_mp_fail = 0;
*ptr++ = mptcp_option(MPTCPOPT_MP_FAIL,
TCPOLEN_MPTCP_FAIL,
0, 0);
put_unaligned_be64(opts->fail_seq, ptr);
ptr += 2;
}
/* RST is mutually exclusive with everything else */ /* RST is mutually exclusive with everything else */
if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
*ptr++ = mptcp_option(MPTCPOPT_RST, *ptr++ = mptcp_option(MPTCPOPT_RST,
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define OPTION_MPTCP_PRIO BIT(9) #define OPTION_MPTCP_PRIO BIT(9)
#define OPTION_MPTCP_RST BIT(10) #define OPTION_MPTCP_RST BIT(10)
#define OPTION_MPTCP_DSS BIT(11) #define OPTION_MPTCP_DSS BIT(11)
#define OPTION_MPTCP_FAIL BIT(12)
/* MPTCP option subtypes */ /* MPTCP option subtypes */
#define MPTCPOPT_MP_CAPABLE 0 #define MPTCPOPT_MP_CAPABLE 0
...@@ -68,6 +69,7 @@ ...@@ -68,6 +69,7 @@
#define TCPOLEN_MPTCP_PRIO_ALIGN 4 #define TCPOLEN_MPTCP_PRIO_ALIGN 4
#define TCPOLEN_MPTCP_FASTCLOSE 12 #define TCPOLEN_MPTCP_FASTCLOSE 12
#define TCPOLEN_MPTCP_RST 4 #define TCPOLEN_MPTCP_RST 4
#define TCPOLEN_MPTCP_FAIL 12
#define TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM (TCPOLEN_MPTCP_DSS_CHECKSUM + TCPOLEN_MPTCP_MPC_ACK_DATA) #define TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM (TCPOLEN_MPTCP_DSS_CHECKSUM + TCPOLEN_MPTCP_MPC_ACK_DATA)
...@@ -429,6 +431,7 @@ struct mptcp_subflow_context { ...@@ -429,6 +431,7 @@ struct mptcp_subflow_context {
mpc_map : 1, mpc_map : 1,
backup : 1, backup : 1,
send_mp_prio : 1, send_mp_prio : 1,
send_mp_fail : 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