]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mptcp: MP_FAIL suboption sending
authorGeliang Tang <geliangtang@xiaomi.com>
Tue, 24 Aug 2021 23:26:15 +0000 (16:26 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Aug 2021 10:02:34 +0000 (11:02 +0100)
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: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@xiaomi.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/mptcp.h
net/mptcp/options.c
net/mptcp/protocol.h

index 3236010afa298cf5a36a5d5df20ece3163884e97..6026bbefbffd8802939ef3a0827fc11b16cc38d4 100644 (file)
@@ -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;
index 1a59b3045a33fcfb6749db2891a3c1c708ac78e0..f2ebdd55d3ccd1ef17e6b921440d5cfe5cf392ca 100644 (file)
@@ -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,
index d276ce16f1264212a00e07a4c81f19fc2f865638..3e4a79cf520ab5da96fc8e4717f825fabaaef9a9 100644 (file)
@@ -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 */