mptcp: Use MPTCP-level flag for sending DATA_FIN
authorMat Martineau <mathew.j.martineau@linux.intel.com>
Tue, 28 Jul 2020 22:12:02 +0000 (15:12 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 29 Jul 2020 00:02:41 +0000 (17:02 -0700)
Since DATA_FIN information is the same for every subflow, store it only
in the mptcp_sock.

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.c
net/mptcp/protocol.h

index 0b122b2a9c697299eb330de02efc8c0f6ea4b9d9..f157cb7e14c09643f76b2ab90d0ef92f1314174b 100644 (file)
@@ -451,6 +451,8 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
 static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
                                 struct sk_buff *skb, struct mptcp_ext *ext)
 {
+       u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq);
+
        if (!ext->use_map || !skb->len) {
                /* RFC6824 requires a DSS mapping with specific values
                 * if DATA_FIN is set but no data payload is mapped
@@ -458,10 +460,13 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
                ext->data_fin = 1;
                ext->use_map = 1;
                ext->dsn64 = 1;
-               ext->data_seq = subflow->data_fin_tx_seq;
+               /* The write_seq value has already been incremented, so
+                * the actual sequence number for the DATA_FIN is one less.
+                */
+               ext->data_seq = data_fin_tx_seq - 1;
                ext->subflow_seq = 0;
                ext->data_len = 1;
-       } else if (ext->data_seq + ext->data_len == subflow->data_fin_tx_seq) {
+       } else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
                /* If there's an existing DSS mapping and it is the
                 * final mapping, DATA_FIN consumes 1 additional byte of
                 * mapping space.
@@ -477,15 +482,17 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
                                          struct mptcp_out_options *opts)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+       struct mptcp_sock *msk = mptcp_sk(subflow->conn);
        unsigned int dss_size = 0;
+       u64 snd_data_fin_enable;
        struct mptcp_ext *mpext;
-       struct mptcp_sock *msk;
        unsigned int ack_size;
        bool ret = false;
 
        mpext = skb ? mptcp_get_ext(skb) : NULL;
+       snd_data_fin_enable = READ_ONCE(msk->snd_data_fin_enable);
 
-       if (!skb || (mpext && mpext->use_map) || subflow->data_fin_tx_enable) {
+       if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
                unsigned int map_size;
 
                map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
@@ -495,7 +502,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
                if (mpext)
                        opts->ext_copy = *mpext;
 
-               if (skb && subflow->data_fin_tx_enable)
+               if (skb && snd_data_fin_enable)
                        mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
                ret = true;
        }
@@ -504,7 +511,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
         * if the first subflow may have the already the remote key handy
         */
        opts->ext_copy.use_ack = 0;
-       msk = mptcp_sk(subflow->conn);
        if (!READ_ONCE(msk->can_ack)) {
                *size = ALIGN(dss_size, 4);
                return ret;
index 7d7e0fa1721910ad87c9c0cd44aec0bc25d942ef..dd403ba3679a3a425359f068a73f36e685a5a962 100644 (file)
@@ -1391,8 +1391,7 @@ static void mptcp_cancel_work(struct sock *sk)
                sock_put(sk);
 }
 
-static void mptcp_subflow_shutdown(struct sock *ssk, int how,
-                                  bool data_fin_tx_enable, u64 data_fin_tx_seq)
+static void mptcp_subflow_shutdown(struct sock *ssk, int how)
 {
        lock_sock(ssk);
 
@@ -1405,14 +1404,6 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int how,
                tcp_disconnect(ssk, O_NONBLOCK);
                break;
        default:
-               if (data_fin_tx_enable) {
-                       struct mptcp_subflow_context *subflow;
-
-                       subflow = mptcp_subflow_ctx(ssk);
-                       subflow->data_fin_tx_seq = data_fin_tx_seq;
-                       subflow->data_fin_tx_enable = 1;
-               }
-
                ssk->sk_shutdown |= how;
                tcp_shutdown(ssk, how);
                break;
@@ -1426,7 +1417,6 @@ static void mptcp_close(struct sock *sk, long timeout)
        struct mptcp_subflow_context *subflow, *tmp;
        struct mptcp_sock *msk = mptcp_sk(sk);
        LIST_HEAD(conn_list);
-       u64 data_fin_tx_seq;
 
        lock_sock(sk);
 
@@ -1440,7 +1430,7 @@ static void mptcp_close(struct sock *sk, long timeout)
        spin_unlock_bh(&msk->join_list_lock);
        list_splice_init(&msk->conn_list, &conn_list);
 
-       data_fin_tx_seq = msk->write_seq;
+       msk->snd_data_fin_enable = 1;
 
        __mptcp_clear_xmit(sk);
 
@@ -1448,9 +1438,6 @@ static void mptcp_close(struct sock *sk, long timeout)
 
        list_for_each_entry_safe(subflow, tmp, &conn_list, node) {
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
-
-               subflow->data_fin_tx_seq = data_fin_tx_seq;
-               subflow->data_fin_tx_enable = 1;
                __mptcp_close_ssk(sk, ssk, subflow, timeout);
        }
 
@@ -2146,10 +2133,12 @@ static int mptcp_shutdown(struct socket *sock, int how)
        }
 
        __mptcp_flush_join_list(msk);
+       msk->snd_data_fin_enable = 1;
+
        mptcp_for_each_subflow(msk, subflow) {
                struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
 
-               mptcp_subflow_shutdown(tcp_sk, how, 1, msk->write_seq);
+               mptcp_subflow_shutdown(tcp_sk, how);
        }
 
        /* Wake up anyone sleeping in poll. */
index 67634b595466367f41f652a407ccfb1fde6e3323..3f49cc10577222bb10aa68e8d55ca763b18b7014 100644 (file)
@@ -199,6 +199,7 @@ struct mptcp_sock {
        unsigned long   flags;
        bool            can_ack;
        bool            fully_established;
+       bool            snd_data_fin_enable;
        spinlock_t      join_list_lock;
        struct work_struct work;
        struct list_head conn_list;
@@ -291,10 +292,8 @@ struct mptcp_subflow_context {
                backup : 1,
                data_avail : 1,
                rx_eof : 1,
-               data_fin_tx_enable : 1,
                use_64bit_ack : 1, /* Set when we received a 64-bit DSN */
                can_ack : 1;        /* only after processing the remote a key */
-       u64     data_fin_tx_seq;
        u32     remote_nonce;
        u64     thmac;
        u32     local_nonce;