mptcp: add the outgoing RM_ADDR support
authorGeliang Tang <geliangtang@gmail.com>
Thu, 24 Sep 2020 00:29:48 +0000 (08:29 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 25 Sep 2020 02:58:33 +0000 (19:58 -0700)
This patch added a new signal named rm_addr_signal in PM. On outgoing path,
we called mptcp_pm_should_rm_signal to check if rm_addr_signal has been
set. If it has been, we sent out the RM_ADDR option.

Suggested-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mptcp/options.c
net/mptcp/pm.c
net/mptcp/protocol.h

index ee0cb05463244665d92b28bbf882a19ae3d5c871..bbc124876417a1fb54558350959f597a175248df 100644 (file)
@@ -614,6 +614,31 @@ static bool mptcp_established_options_add_addr(struct sock *sk,
        return true;
 }
 
+static bool mptcp_established_options_rm_addr(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);
+       u8 rm_id;
+
+       if (!mptcp_pm_should_rm_signal(msk) ||
+           !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
+               return false;
+
+       if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
+               return false;
+
+       *size = TCPOLEN_MPTCP_RM_ADDR_BASE;
+       opts->suboptions |= OPTION_MPTCP_RM_ADDR;
+       opts->rm_id = rm_id;
+
+       pr_debug("rm_id=%d", opts->rm_id);
+
+       return true;
+}
+
 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
                               unsigned int *size, unsigned int remaining,
                               struct mptcp_out_options *opts)
@@ -644,6 +669,10 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
                *size += opt_size;
                remaining -= opt_size;
                ret = true;
+       } else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
+               *size += opt_size;
+               remaining -= opt_size;
+               ret = true;
        }
 
        return ret;
index ce12b8b26ad2c76c5e49013ff8ee89f9dc57d066..81b07ae213b9a80fa0f608b6e765b3e8adc4d655 100644 (file)
@@ -174,6 +174,29 @@ out_unlock:
        return ret;
 }
 
+bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+                            u8 *rm_id)
+{
+       int ret = false;
+
+       spin_lock_bh(&msk->pm.lock);
+
+       /* double check after the lock is acquired */
+       if (!mptcp_pm_should_rm_signal(msk))
+               goto out_unlock;
+
+       if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
+               goto out_unlock;
+
+       *rm_id = msk->pm.rm_id;
+       WRITE_ONCE(msk->pm.rm_addr_signal, false);
+       ret = true;
+
+out_unlock:
+       spin_unlock_bh(&msk->pm.lock);
+       return ret;
+}
+
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
 {
        return mptcp_pm_nl_get_local_id(msk, skc);
@@ -185,8 +208,10 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
        msk->pm.add_addr_accepted = 0;
        msk->pm.local_addr_used = 0;
        msk->pm.subflows = 0;
+       msk->pm.rm_id = 0;
        WRITE_ONCE(msk->pm.work_pending, false);
        WRITE_ONCE(msk->pm.add_addr_signal, false);
+       WRITE_ONCE(msk->pm.rm_addr_signal, false);
        WRITE_ONCE(msk->pm.accept_addr, false);
        WRITE_ONCE(msk->pm.accept_subflow, false);
        msk->pm.status = 0;
index 91adc9a197577cb2d3153637d09e3c4db87b4c1c..8929b0c7660a7d2293aead95ece6f70671677991 100644 (file)
@@ -163,6 +163,7 @@ struct mptcp_pm_data {
        spinlock_t      lock;           /*protects the whole PM data */
 
        bool            add_addr_signal;
+       bool            rm_addr_signal;
        bool            server_side;
        bool            work_pending;
        bool            accept_addr;
@@ -176,6 +177,7 @@ struct mptcp_pm_data {
        u8              local_addr_max;
        u8              subflows_max;
        u8              status;
+       u8              rm_id;
 };
 
 struct mptcp_data_frag {
@@ -443,6 +445,11 @@ static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
        return READ_ONCE(msk->pm.add_addr_signal);
 }
 
+static inline bool mptcp_pm_should_rm_signal(struct mptcp_sock *msk)
+{
+       return READ_ONCE(msk->pm.rm_addr_signal);
+}
+
 static inline unsigned int mptcp_add_addr_len(int family)
 {
        if (family == AF_INET)
@@ -452,6 +459,8 @@ static inline unsigned int mptcp_add_addr_len(int family)
 
 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
                              struct mptcp_addr_info *saddr);
+bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+                            u8 *rm_id);
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 void __init mptcp_pm_nl_init(void);