pr_debug("RM_ADDR: id=%d", mp_opt->rm_id);
                break;
 
+       case MPTCPOPT_MP_FASTCLOSE:
+               if (opsize != TCPOLEN_MPTCP_FASTCLOSE)
+                       break;
+
+               ptr += 2;
+               mp_opt->rcvr_key = get_unaligned_be64(ptr);
+               ptr += 8;
+               mp_opt->fastclose = 1;
+               break;
+
        default:
                break;
        }
        mp_opt->mp_join = 0;
        mp_opt->add_addr = 0;
        mp_opt->ahmac = 0;
+       mp_opt->fastclose = 0;
        mp_opt->port = 0;
        mp_opt->rm_addr = 0;
        mp_opt->dss = 0;
        if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
                return;
 
+       if (mp_opt.fastclose &&
+           msk->local_key == mp_opt.rcvr_key) {
+               WRITE_ONCE(msk->rcv_fastclose, true);
+               mptcp_schedule_work((struct sock *)msk);
+       }
+
        if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) {
                struct mptcp_addr_info addr;
 
 
        return true;
 }
 
+static void mptcp_check_fastclose(struct mptcp_sock *msk)
+{
+       struct mptcp_subflow_context *subflow, *tmp;
+       struct sock *sk = &msk->sk.icsk_inet.sk;
+
+       if (likely(!READ_ONCE(msk->rcv_fastclose)))
+               return;
+
+       mptcp_token_destroy(msk);
+
+       list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
+               struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
+
+               lock_sock(tcp_sk);
+               if (tcp_sk->sk_state != TCP_CLOSE) {
+                       tcp_send_active_reset(tcp_sk, GFP_ATOMIC);
+                       tcp_set_state(tcp_sk, TCP_CLOSE);
+               }
+               release_sock(tcp_sk);
+       }
+
+       inet_sk_state_store(sk, TCP_CLOSE);
+       sk->sk_shutdown = SHUTDOWN_MASK;
+       smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
+       set_bit(MPTCP_DATA_READY, &msk->flags);
+       set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags);
+
+       mptcp_close_wake_up(sk);
+}
+
 static void mptcp_worker(struct work_struct *work)
 {
        struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
 
        mptcp_check_data_fin_ack(sk);
        __mptcp_flush_join_list(msk);
+
+       mptcp_check_fastclose(msk);
+
        if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
                __mptcp_close_subflow(msk);
 
 
 #define OPTION_MPTCP_ADD_ADDR  BIT(6)
 #define OPTION_MPTCP_ADD_ADDR6 BIT(7)
 #define OPTION_MPTCP_RM_ADDR   BIT(8)
+#define OPTION_MPTCP_FASTCLOSE BIT(9)
 
 /* MPTCP option subtypes */
 #define MPTCPOPT_MP_CAPABLE    0
 #define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT      24
 #define TCPOLEN_MPTCP_PORT_LEN         4
 #define TCPOLEN_MPTCP_RM_ADDR_BASE     4
+#define TCPOLEN_MPTCP_FASTCLOSE                12
 
 /* MPTCP MP_JOIN flags */
 #define MPTCPOPT_BACKUP                BIT(0)
        u16     data_len;
        u16     mp_capable : 1,
                mp_join : 1,
+               fastclose : 1,
                dss : 1,
                add_addr : 1,
                rm_addr : 1,
        bool            fully_established;
        bool            rcv_data_fin;
        bool            snd_data_fin_enable;
+       bool            rcv_fastclose;
        bool            use_64bit_ack; /* Set when we received a 64-bit DSN */
        spinlock_t      join_list_lock;
        struct sock     *ack_hint;