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 {
struct mptcp_addr_info addr;
u64 ahmac;
};
struct mptcp_ext ext_copy;
struct {
struct mptcp_ext ext_copy;
u64 fail_seq;
};
struct {
u32 nonce;
u32 token;
......
......@@ -767,7 +767,7 @@ static bool mptcp_established_options_mp_prio(struct sock *sk,
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 remaining,
struct mptcp_out_options *opts)
......@@ -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);
if (remaining < TCPOLEN_MPTCP_RST)
return;
return false;
*size = TCPOLEN_MPTCP_RST;
opts->suboptions |= OPTION_MPTCP_RST;
opts->reset_transient = subflow->reset_transient;
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,
......@@ -799,15 +823,28 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
return false;
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;
}
snd_data_fin = mptcp_data_fin_enabled(msk);
if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts))
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;
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
* TCP option space would be fatal
......@@ -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,
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 */
if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
*ptr++ = mptcp_option(MPTCPOPT_RST,
......
......@@ -27,6 +27,7 @@
#define OPTION_MPTCP_PRIO BIT(9)
#define OPTION_MPTCP_RST BIT(10)
#define OPTION_MPTCP_DSS BIT(11)
#define OPTION_MPTCP_FAIL BIT(12)
/* MPTCP option subtypes */
#define MPTCPOPT_MP_CAPABLE 0
......@@ -68,6 +69,7 @@
#define TCPOLEN_MPTCP_PRIO_ALIGN 4
#define TCPOLEN_MPTCP_FASTCLOSE 12
#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)
......@@ -429,6 +431,7 @@ struct mptcp_subflow_context {
mpc_map : 1,
backup : 1,
send_mp_prio : 1,
send_mp_fail : 1,
rx_eof : 1,
can_ack : 1, /* only after processing the remote a key */
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