mptcp: implement fastclose xmit path
authorPaolo Abeni <pabeni@redhat.com>
Fri, 7 Jan 2022 00:20:15 +0000 (16:20 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Jan 2022 11:27:06 +0000 (11:27 +0000)
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: Geliang Tang <geliang.tang@suse.com>
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mptcp/options.c
net/mptcp/protocol.h

index fe98e4f..46d35a2 100644 (file)
@@ -768,6 +768,28 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu
        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,
                                              unsigned int *size,
                                              unsigned int remaining,
@@ -806,10 +828,12 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
                return false;
 
        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;
                        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)) {
                        *size += opt_size;
                        remaining -= opt_size;
@@ -1251,17 +1275,8 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
                ptr += 2;
        }
 
-       /* RST is mutually exclusive with everything else */
-       if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
-               *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*()
+       /* DSS, MPC, MPJ, ADD_ADDR, FASTCLOSE and RST are mutually exclusive,
+        * see mptcp_established_options*()
         */
        if (likely(OPTION_MPTCP_DSS & opts->suboptions)) {
                struct mptcp_ext *mpext = &opts->ext_copy;
@@ -1447,6 +1462,24 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
                                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) {
index 0486c9f..f177936 100644 (file)
@@ -423,6 +423,7 @@ struct mptcp_subflow_context {
                backup : 1,
                send_mp_prio : 1,
                send_mp_fail : 1,
+               send_fastclose : 1,
                rx_eof : 1,
                can_ack : 1,        /* only after processing the remote a key */
                disposable : 1,     /* ctx can be free at ulp release time */