This patch implemented the local subflow removing function,
mptcp_pm_remove_subflow, it simply called mptcp_pm_nl_rm_subflow_received
under the PM spin lock.

We use mptcp_pm_remove_subflow to remove a local subflow, so change it's
argument from remote_id to local_id.

We check subflow->local_id in mptcp_pm_nl_rm_subflow_received to remove
a subflow.

Suggested-by: Matthieu Baerts <matthieu.bae...@tessares.net>
Suggested-by: Paolo Abeni <pab...@redhat.com>
Suggested-by: Mat Martineau <mathew.j.martin...@linux.intel.com>
Signed-off-by: Geliang Tang <geliangt...@gmail.com>
---
 net/mptcp/pm.c         |  9 +++++++--
 net/mptcp/pm_netlink.c | 33 +++++++++++++++++++++++++++++++++
 net/mptcp/protocol.h   |  3 ++-
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index f450bf0d49aa..7e81f53d1e5d 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -33,9 +33,14 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
        return 0;
 }
 
-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
+int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id)
 {
-       return -ENOTSUPP;
+       pr_debug("msk=%p, local_id=%d", msk, local_id);
+
+       spin_lock_bh(&msk->pm.lock);
+       mptcp_pm_nl_rm_subflow_received(msk, local_id);
+       spin_unlock_bh(&msk->pm.lock);
+       return 0;
 }
 
 /* path manager event handlers */
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 97f9280f83fb..9064c8098521 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -350,6 +350,39 @@ void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
        }
 }
 
+void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id)
+{
+       struct mptcp_subflow_context *subflow, *tmp;
+       struct sock *sk = (struct sock *)msk;
+
+       pr_debug("subflow rm_id %d", rm_id);
+
+       if (!rm_id)
+               return;
+
+       if (list_empty(&msk->conn_list))
+               return;
+
+       list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
+               struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+               int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
+               long timeout = 0;
+
+               if (rm_id != subflow->local_id)
+                       continue;
+
+               spin_unlock_bh(&msk->pm.lock);
+               mptcp_subflow_shutdown(sk, ssk, how);
+               __mptcp_close_ssk(sk, ssk, subflow, timeout);
+               spin_lock_bh(&msk->pm.lock);
+
+               msk->pm.local_addr_used--;
+               msk->pm.subflows--;
+
+               break;
+       }
+}
+
 static bool address_use_port(struct mptcp_pm_addr_entry *entry)
 {
        return (entry->addr.flags &
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index d1b1416797f8..df6cc94df1f7 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -448,7 +448,7 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
                           const struct mptcp_addr_info *addr,
                           bool echo);
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
+int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id);
 
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
 {
@@ -479,6 +479,7 @@ void mptcp_pm_nl_fully_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk);
+void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
-- 
2.17.1

Reply via email to