From nobody Sun May  4 10:55:32 2025
Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org
 [10.30.226.201])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id D476B1DDC15
	for <mptcp@lists.linux.dev>; Fri,  7 Feb 2025 09:29:41 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=10.30.226.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1738920582; cv=none;
 b=QL5HfNEwcfxEM9f7ND5I4ENWf7DprzwUej58nsX0uLI2Rg2U06L3IO3pYlxA9D23KImVVxDPzW2VpFqoa5PFTib+yZWcK5pNCz6FIg2092WNjjrUknNoK0J+LSc4z/m2O45vIRI/trvHNuMDfTA6aWbiBqkBacMJHeBS2xMHWWs=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1738920582; c=relaxed/simple;
	bh=K/jTEAETklBrnH1Q/VZzMTqksGs/yeYRrG/6rfRtqFQ=;
	h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:
	 MIME-Version;
 b=ZYiuDea9C2tkx+SnPHotRaLAxQP5fob8f0iY0xQM1iH9N0V7SZOJbgffnBHYvpkZ8kfYS8zVzC3iExeOAySrlWl/zQxqlDNR/kSNC0eVDUQcYaAUmxd/05JHdW9qL0f2bW4Q0Sx9f81pEucM/qYVUpl8qg0uXDLuM5q236o8kTc=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b=EfucwOkw; arc=none smtp.client-ip=10.30.226.201
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b="EfucwOkw"
Received: by smtp.kernel.org (Postfix) with ESMTPSA id 23EE9C4CED6;
	Fri,  7 Feb 2025 09:29:39 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;
	s=k20201202; t=1738920581;
	bh=K/jTEAETklBrnH1Q/VZzMTqksGs/yeYRrG/6rfRtqFQ=;
	h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
	b=EfucwOkw1IcTa4oH218wPiPuNvBmdcqeBck5neJ30z3Wb0GQeugSJs+ATdn4fOnrg
	 cvQCwLjatW/16uJTQ/+bD2drgx/AQ8CI0Mwhln+yz4kgiwGOHY3MVJ/ISZE7q/TEgc
	 JJYgUUgkMG2D8xBH9Zk6cIZOR6202B5juzTatGGpOUIr9RGYmb8uPlxRQ7fSWYAeYg
	 lUwjbMk6cOvUjBTMV8/GlIoEdaZZhZm+6LaUMw++k05koCvR/ZiS+Wl8pNH+YZWLpi
	 wO5VNhZ9NPUyMViq+7o0lRfk1TV/BLwmfTLkdbZJxuhiujyGIq8mEztoCtdF2wvxWU
	 rocQx5GlGH9tg==
From: Geliang Tang <geliang@kernel.org>
To: mptcp@lists.linux.dev
Cc: Geliang Tang <tanggeliang@kylinos.cn>
Subject: [PATCH mptcp-next v4 1/4] mptcp: define struct mptcp_pm_ops
Date: Fri,  7 Feb 2025 17:29:31 +0800
Message-ID: 
 <c49ce8acc078af821c7214c3a3484344ab51fd3f.1738919954.git.tanggeliang@kylinos.cn>
X-Mailer: git-send-email 2.43.0
In-Reply-To: <cover.1738919954.git.tanggeliang@kylinos.cn>
References: <cover.1738919954.git.tanggeliang@kylinos.cn>
Precedence: bulk
X-Mailing-List: mptcp@lists.linux.dev
List-Id: <mptcp.lists.linux.dev>
List-Subscribe: <mailto:mptcp+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:mptcp+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

From: Geliang Tang <tanggeliang@kylinos.cn>

In order to allow users to develop their own BPF-based path manager,
this patch defines a struct ops "mptcp_pm_ops" for a userspace path
manager, which contains a set of interfaces.

Add a set of functions to register, unregister, find and validate a
given struct ops.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 include/net/mptcp.h  | 32 ++++++++++++++++++++++++
 net/mptcp/pm.c       | 59 ++++++++++++++++++++++++++++++++++++++++++++
 net/mptcp/protocol.h |  5 ++++
 3 files changed, 96 insertions(+)

diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index 72d6e6597add..d629da5f8e8b 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -14,6 +14,7 @@
=20
 struct mptcp_info;
 struct mptcp_sock;
+struct mptcp_pm_addr_entry;
 struct seq_file;
=20
 /* MPTCP sk_buff extension data */
@@ -121,6 +122,37 @@ struct mptcp_sched_ops {
 	void (*release)(struct mptcp_sock *msk);
 } ____cacheline_aligned_in_smp;
=20
+struct mptcp_pm_ops {
+	int (*created)(struct mptcp_sock *msk);
+	int (*established)(struct mptcp_sock *msk);
+	int (*closed)(struct mptcp_sock *msk);
+	int (*address_announced)(struct mptcp_sock *msk,
+				 struct mptcp_pm_addr_entry *local);
+	int (*address_removed)(struct mptcp_sock *msk, u8 id);
+	int (*subflow_established)(struct mptcp_sock *msk,
+				   struct mptcp_pm_addr_entry *local,
+				   struct mptcp_addr_info *remote);
+	int (*subflow_closed)(struct mptcp_sock *msk,
+			      struct mptcp_pm_addr_entry *local,
+			      struct mptcp_addr_info *remote);
+	int (*get_local_id)(struct mptcp_sock *msk,
+			    struct mptcp_pm_addr_entry *skc);
+	bool (*get_priority)(struct mptcp_sock *msk,
+			     struct mptcp_addr_info *skc);
+	int (*set_priority)(struct mptcp_sock *msk,
+			    struct mptcp_pm_addr_entry *local,
+			    struct mptcp_addr_info *remote);
+	int (*listener_created)(struct mptcp_sock *msk);
+	int (*listener_closed)(struct mptcp_sock *msk);
+
+	u8			type;
+	struct module		*owner;
+	struct list_head	list;
+
+	void (*init)(struct mptcp_sock *msk);
+	void (*release)(struct mptcp_sock *msk);
+} ____cacheline_aligned_in_smp;
+
 #ifdef CONFIG_MPTCP
 void mptcp_init(void);
=20
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 16cacce6c10f..344bc477c502 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -6,12 +6,17 @@
 #define pr_fmt(fmt) "MPTCP: " fmt
=20
 #include <linux/kernel.h>
+#include <linux/rculist.h>
+#include <linux/spinlock.h>
 #include <net/mptcp.h>
 #include "protocol.h"
=20
 #include "mib.h"
 #include "mptcp_pm_gen.h"
=20
+static DEFINE_SPINLOCK(mptcp_pm_list_lock);
+static LIST_HEAD(mptcp_pm_list);
+
 /* path manager command handlers */
=20
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
@@ -644,3 +649,57 @@ void __init mptcp_pm_init(void)
 {
 	mptcp_pm_nl_init();
 }
+
+/* Must be called with rcu read lock held */
+struct mptcp_pm_ops *mptcp_pm_find(enum mptcp_pm_type type)
+{
+	struct mptcp_pm_ops *pm;
+
+	list_for_each_entry_rcu(pm, &mptcp_pm_list, list) {
+		if (pm->type =3D=3D type)
+			return pm;
+	}
+
+	return NULL;
+}
+
+int mptcp_pm_validate(struct mptcp_pm_ops *pm)
+{
+	if (!pm->created && !pm->established && !pm->closed &&
+	    !pm->address_announced && !pm->address_removed &&
+	    !pm->subflow_established && !pm->subflow_closed &&
+	    !pm->get_local_id && !pm->get_priority && !pm->set_priority &&
+	    !pm->listener_created && !pm->listener_closed) {
+		pr_err("%u does not implement required ops\n", pm->type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int mptcp_pm_register(struct mptcp_pm_ops *pm)
+{
+	int ret;
+
+	ret =3D mptcp_pm_validate(pm);
+	if (ret)
+		return ret;
+
+	spin_lock(&mptcp_pm_list_lock);
+	if (mptcp_pm_find(pm->type)) {
+		spin_unlock(&mptcp_pm_list_lock);
+		return -EEXIST;
+	}
+	list_add_tail_rcu(&pm->list, &mptcp_pm_list);
+	spin_unlock(&mptcp_pm_list_lock);
+
+	pr_debug("userspace_pm type %u registered\n", pm->type);
+	return 0;
+}
+
+void mptcp_pm_unregister(struct mptcp_pm_ops *pm)
+{
+	spin_lock(&mptcp_pm_list_lock);
+	list_del_rcu(&pm->list);
+	spin_unlock(&mptcp_pm_list_lock);
+}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index bac5c925a72f..93445c24de93 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1047,6 +1047,11 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, con=
st struct mptcp_rm_list *rm_
 void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
 				struct mptcp_pm_addr_entry *entry);
=20
+struct mptcp_pm_ops *mptcp_pm_find(enum mptcp_pm_type type);
+int mptcp_pm_validate(struct mptcp_pm_ops *pm);
+int mptcp_pm_register(struct mptcp_pm_ops *pm);
+void mptcp_pm_unregister(struct mptcp_pm_ops *pm);
+
 void mptcp_free_local_addr_list(struct mptcp_sock *msk);
=20
 void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
--=20
2.43.0
From nobody Sun May  4 10:55:32 2025
Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org
 [10.30.226.201])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id C85AF1DE2D8
	for <mptcp@lists.linux.dev>; Fri,  7 Feb 2025 09:29:43 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=10.30.226.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1738920584; cv=none;
 b=GFNAuHGd09gdCCtLsaP+0vv/Siguxa+fH9NxLJy5GA+43QmnGPmmqetaEKo2Nq6cIXFgvim0OguRnj5pxtzyWV4sLf99+KHJIVTPaI18Dta1ftSyEzY4pwKaEaPcDbF92FDG0fFIbkNR3mnYrxxzO2/gN3hhxvL4UoE8Bk8KfCA=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1738920584; c=relaxed/simple;
	bh=C5DA2VYREDHFFathj4vYgqapxCLlZHnQmTactqOBdO8=;
	h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:
	 MIME-Version;
 b=W9PcJT12fxArfxY98PUWEzwkqXvUpjcN+gnu6A3Wvfg9DISmYZQhj1isKQ0UWNXwX++mwU0ft78WYJ/z3Vc4sRHLBIC3WRukKEV+cAoxPTuJPQUn4NE8oQwJTUf8oHXiulZLCHnV93Q/hnOT7ygt2i0iUdicqOYFNP91/WclDwk=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b=COBLUh0Y; arc=none smtp.client-ip=10.30.226.201
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b="COBLUh0Y"
Received: by smtp.kernel.org (Postfix) with ESMTPSA id 15F7CC4CED1;
	Fri,  7 Feb 2025 09:29:41 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;
	s=k20201202; t=1738920583;
	bh=C5DA2VYREDHFFathj4vYgqapxCLlZHnQmTactqOBdO8=;
	h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
	b=COBLUh0YmhjhUaxTVX1deme8Z1GGImx3qJAKDwnhmJa2VVV8HqiViMXfOo4Qd2h04
	 UJeuGMzF/VqAwLHzKMLrBhukijtV1RLG5wYGgKUzX8bE+XmEVmj0owEIIL7Chwh7K4
	 AkfwWyD2lGIihnZZyOemMs+UoUpXTNAwxKPcJPoZK/yk3IOqGPxb5W0wYrMlzaX3ox
	 QjlsY/EqUHG6iRggYwVqEAq+Oq6q+DuUqSQ1Fd7cqrmHSdbluOVHIyiCNuY5htYGVA
	 WvX5Q6uYVR7tldyesQdL31DZWNKWeUJ23kPDMf1eH6V0wyJ59+TqZDvnAJ8p21+CgP
	 PPuWbugVooiLg==
From: Geliang Tang <geliang@kernel.org>
To: mptcp@lists.linux.dev
Cc: Geliang Tang <tanggeliang@kylinos.cn>
Subject: [PATCH mptcp-next v4 2/4] mptcp: define BPF path manager type
Date: Fri,  7 Feb 2025 17:29:32 +0800
Message-ID: 
 <7d8321d1aba118d8541435fb9847d5dfbf3ad888.1738919954.git.tanggeliang@kylinos.cn>
X-Mailer: git-send-email 2.43.0
In-Reply-To: <cover.1738919954.git.tanggeliang@kylinos.cn>
References: <cover.1738919954.git.tanggeliang@kylinos.cn>
Precedence: bulk
X-Mailing-List: mptcp@lists.linux.dev
List-Id: <mptcp.lists.linux.dev>
List-Subscribe: <mailto:mptcp+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:mptcp+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

From: Geliang Tang <tanggeliang@kylinos.cn>

This patch defines a new path manager type: MPTCP_PM_TYPE_BPF_USERSPACE,
which is used for the userspace path manager implemented in BPF. This
path manager is also a userspace path manager, so add this new type in
mptcp_pm_is_userspace() too.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 net/mptcp/protocol.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 93445c24de93..cd36ffe8509b 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -198,6 +198,7 @@ enum mptcp_pm_status {
 enum mptcp_pm_type {
 	MPTCP_PM_TYPE_KERNEL =3D 0,
 	MPTCP_PM_TYPE_USERSPACE,
+	MPTCP_PM_TYPE_BPF_USERSPACE,
=20
 	__MPTCP_PM_TYPE_NR,
 	__MPTCP_PM_TYPE_MAX =3D __MPTCP_PM_TYPE_NR - 1,
@@ -1093,7 +1094,10 @@ static inline bool mptcp_pm_should_rm_signal(struct =
mptcp_sock *msk)
=20
 static inline bool mptcp_pm_is_userspace(const struct mptcp_sock *msk)
 {
-	return READ_ONCE(msk->pm.pm_type) =3D=3D MPTCP_PM_TYPE_USERSPACE;
+	enum mptcp_pm_type pm_type =3D READ_ONCE(msk->pm.pm_type);
+
+	return (pm_type =3D=3D MPTCP_PM_TYPE_USERSPACE ||
+		pm_type =3D=3D MPTCP_PM_TYPE_BPF_USERSPACE);
 }
=20
 static inline bool mptcp_pm_is_kernel(const struct mptcp_sock *msk)
--=20
2.43.0
From nobody Sun May  4 10:55:32 2025
Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org
 [10.30.226.201])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0BE3C236A64
	for <mptcp@lists.linux.dev>; Fri,  7 Feb 2025 09:29:45 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=10.30.226.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1738920586; cv=none;
 b=A17co1jL8jUDEi2qM/gKCKd9qk2G5IjUnfObfbH93Jt9uPo/ro/hzpUAdckCqjtBBAPqQD6V0+elw4CNFZmgA/1M9olhD7OiM4o4Zcjx6od8WDg+vaaidxhWBohHIf/ZLYjXeBskB3a6jnZcTUAE+6jAnK+pBrAYcdbONS2x0j0=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1738920586; c=relaxed/simple;
	bh=bh2JX3UEB3FYqDdzgYWMDAgmNZfKbnc3FYa/hZekcEY=;
	h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:
	 MIME-Version;
 b=HkD4Q0zzQRGpayMuL/lIKPh7GyVPx98GcXzk9S4F/GsxKWfFj2PmbeqnCSNMfb8dFN4C2oQ4rKk1OKjWs/G7Nmcl07eZ73FJClXoVdBnnrestcC/oOdCER+76uagRt+Fwek0QgMlIWsvP77fLWFFAlWZ/QCooFgwTGwXUee6fYY=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b=bMnpMOFx; arc=none smtp.client-ip=10.30.226.201
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b="bMnpMOFx"
Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1A27C4CED6;
	Fri,  7 Feb 2025 09:29:43 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;
	s=k20201202; t=1738920585;
	bh=bh2JX3UEB3FYqDdzgYWMDAgmNZfKbnc3FYa/hZekcEY=;
	h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
	b=bMnpMOFx3Zf0WgS7fFcaZ6c7mqd2Muk/j2fPrJLXfwIfUkE1tQuPFdINiOlQB3ngh
	 /2JohkKdOBMyQIX1a/DU6wlfr5+ZVqOtOPiUzBKeXE0S4uePAPCCqwd+Xx+xyyD0Ft
	 Yby+0GA+uetYOdtvwMyO2Ld9sBGlSKrumWo4Gsgj1yo9EYVH7dLm3WU+4rE/T1DqUg
	 TFalVYcf9YfqplyCYIt+PcKL6rP6F8wPWciOygPv4gRQ+5XvjBT09LrrIO1B6q6WFe
	 qJ+5clX5OD3tWqzx7Yez+NyETKHLZ80jyQ2rwutuCUWqN3HjmKbXqet9mxwzK4xxty
	 crpJQP9QrxnFA==
From: Geliang Tang <geliang@kernel.org>
To: mptcp@lists.linux.dev
Cc: Geliang Tang <tanggeliang@kylinos.cn>
Subject: [PATCH mptcp-next v4 3/4] mptcp: register default userspace pm
Date: Fri,  7 Feb 2025 17:29:33 +0800
Message-ID: 
 <5c5188d92bede3ba33554818e3eb0fe0dc10feb9.1738919954.git.tanggeliang@kylinos.cn>
X-Mailer: git-send-email 2.43.0
In-Reply-To: <cover.1738919954.git.tanggeliang@kylinos.cn>
References: <cover.1738919954.git.tanggeliang@kylinos.cn>
Precedence: bulk
X-Mailing-List: mptcp@lists.linux.dev
List-Id: <mptcp.lists.linux.dev>
List-Subscribe: <mailto:mptcp+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:mptcp+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

From: Geliang Tang <tanggeliang@kylinos.cn>

This patch defines the original userspace pm as the default path manager,
named mptcp_userspace_pm, and register it in mptcp_pm_data_init().

Extract address_announce() interface of the userspace PM from the handler
of netlink command MPTCP_PM_CMD_ANNOUNCE mptcp_pm_nl_announce_doit(), only
leave the code for obtaining msk through "info" and parsing address entry
in the handler.

Extract address_remove() interface of the userspace PM from the handler
of netlink command MPTCP_PM_CMD_REMOVE mptcp_pm_nl_remove_doit(), only
leave the code for parsing address id and obtaining msk through "info"
in the handler.

Extract subflow_create() interface of the userspace PM from the handler of
netlink command MPTCP_PM_CMD_SUBFLOW_CREATE

	mptcp_pm_nl_subflow_create_doit(),

only leave the code for obtaining msk through "info", parsing local address
entry and parsing remote address info in the handler.

Extract subflow_destroy() interface of the userspace PM from the handler of
netlink command MPTCP_PM_CMD_SUBFLOW_DESTROY

	mptcp_pm_nl_subflow_destroy_doit(),

only leave the code for obtaining msk through "info", parsing local address
entry and parsing remote address info in the handler.

Extract set_flags() interface of the userspace PM from function
mptcp_userspace_pm_set_flags(), only leave the code for obtaining
msk through "info" in this function.

All fives interfaces are invoked under holding the msk socket lock.

Extract get_local_id() interface of the userspace PM from function
mptcp_userspace_pm_get_local_id(), only leave the code for setting
new address entry in this function.

get_flags() interface of the userspace PM is defined as the same as
the function mptcp_userspace_pm_get_flags(), then this function
becomes a wrapper.

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 net/mptcp/pm.c           |   1 +
 net/mptcp/pm_userspace.c | 280 +++++++++++++++++++++++----------------
 net/mptcp/protocol.h     |   1 +
 3 files changed, 171 insertions(+), 111 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 344bc477c502..1304a0c99e12 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -648,6 +648,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 void __init mptcp_pm_init(void)
 {
 	mptcp_pm_nl_init();
+	mptcp_userspace_pm_init();
 }
=20
 /* Must be called with rcu read lock held */
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 6bf6a20ef7f3..3d324aaec550 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -130,19 +130,27 @@ mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_soc=
k *msk, unsigned int id)
 	return NULL;
 }
=20
-int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
-				    struct mptcp_addr_info *skc)
+static int userspace_pm_get_local_id(struct mptcp_sock *msk,
+				     struct mptcp_pm_addr_entry *skc)
 {
-	struct mptcp_pm_addr_entry *entry =3D NULL, new_entry;
-	__be16 msk_sport =3D  ((struct inet_sock *)
-			     inet_sk((struct sock *)msk))->inet_sport;
+	struct mptcp_pm_addr_entry *entry;
=20
 	spin_lock_bh(&msk->pm.lock);
-	entry =3D mptcp_userspace_pm_lookup_addr(msk, skc);
+	entry =3D mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
 	spin_unlock_bh(&msk->pm.lock);
 	if (entry)
 		return entry->addr.id;
=20
+	return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
+}
+
+int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
+				    struct mptcp_addr_info *skc)
+{
+	__be16 msk_sport =3D ((struct inet_sock *)
+			    inet_sk((struct sock *)msk))->inet_sport;
+	struct mptcp_pm_addr_entry new_entry;
+
 	memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
 	new_entry.addr =3D *skc;
 	new_entry.addr.id =3D 0;
@@ -151,11 +159,11 @@ int mptcp_userspace_pm_get_local_id(struct mptcp_sock=
 *msk,
 	if (new_entry.addr.port =3D=3D msk_sport)
 		new_entry.addr.port =3D 0;
=20
-	return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true);
+	return userspace_pm_get_local_id(msk, &new_entry);
 }
=20
-bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
-				  struct mptcp_addr_info *skc)
+static bool userspace_pm_get_priority(struct mptcp_sock *msk,
+				      struct mptcp_addr_info *skc)
 {
 	struct mptcp_pm_addr_entry *entry;
 	bool backup;
@@ -168,6 +176,12 @@ bool mptcp_userspace_pm_is_backup(struct mptcp_sock *m=
sk,
 	return backup;
 }
=20
+bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
+				  struct mptcp_addr_info *skc)
+{
+	return userspace_pm_get_priority(msk, skc);
+}
+
 static struct mptcp_sock *mptcp_userspace_pm_get_sock(const struct genl_in=
fo *info)
 {
 	struct mptcp_sock *msk;
@@ -193,6 +207,28 @@ static struct mptcp_sock *mptcp_userspace_pm_get_sock(=
const struct genl_info *in
 	return msk;
 }
=20
+static int userspace_pm_address_announced(struct mptcp_sock *msk,
+					  struct mptcp_pm_addr_entry *local)
+{
+	int err;
+
+	err =3D mptcp_userspace_pm_append_new_local_addr(msk, local, false);
+	if (err < 0)
+		return err;
+
+	spin_lock_bh(&msk->pm.lock);
+
+	if (mptcp_pm_alloc_anno_list(msk, &local->addr)) {
+		msk->pm.add_addr_signaled++;
+		mptcp_pm_announce_addr(msk, &local->addr, false);
+		mptcp_pm_nl_addr_send_ack(msk);
+	}
+
+	spin_unlock_bh(&msk->pm.lock);
+
+	return 0;
+}
+
 int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
 {
 	struct mptcp_pm_addr_entry addr_val;
@@ -227,26 +263,13 @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, st=
ruct genl_info *info)
 		goto announce_err;
 	}
=20
-	err =3D mptcp_userspace_pm_append_new_local_addr(msk, &addr_val, false);
-	if (err < 0) {
-		NL_SET_ERR_MSG_ATTR(info->extack, addr,
-				    "did not match address and id");
-		goto announce_err;
-	}
-
 	lock_sock(sk);
-	spin_lock_bh(&msk->pm.lock);
-
-	if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) {
-		msk->pm.add_addr_signaled++;
-		mptcp_pm_announce_addr(msk, &addr_val.addr, false);
-		mptcp_pm_nl_addr_send_ack(msk);
-	}
-
-	spin_unlock_bh(&msk->pm.lock);
+	err =3D userspace_pm_address_announced(msk, &addr_val);
 	release_sock(sk);
+	if (err)
+		NL_SET_ERR_MSG_ATTR(info->extack, addr,
+				    "did not match address and id");
=20
-	err =3D 0;
  announce_err:
 	sock_put(sk);
 	return err;
@@ -256,11 +279,8 @@ static int mptcp_userspace_pm_remove_id_zero_address(s=
truct mptcp_sock *msk)
 {
 	struct mptcp_rm_list list =3D { .nr =3D 0 };
 	struct mptcp_subflow_context *subflow;
-	struct sock *sk =3D (struct sock *)msk;
 	bool has_id_0 =3D false;
-	int err =3D -EINVAL;
=20
-	lock_sock(sk);
 	mptcp_for_each_subflow(msk, subflow) {
 		if (READ_ONCE(subflow->local_id) =3D=3D 0) {
 			has_id_0 =3D true;
@@ -268,7 +288,7 @@ static int mptcp_userspace_pm_remove_id_zero_address(st=
ruct mptcp_sock *msk)
 		}
 	}
 	if (!has_id_0)
-		goto remove_err;
+		return -EINVAL;
=20
 	list.ids[list.nr++] =3D 0;
=20
@@ -276,11 +296,7 @@ static int mptcp_userspace_pm_remove_id_zero_address(s=
truct mptcp_sock *msk)
 	mptcp_pm_remove_addr(msk, &list);
 	spin_unlock_bh(&msk->pm.lock);
=20
-	err =3D 0;
-
-remove_err:
-	release_sock(sk);
-	return err;
+	return 0;
 }
=20
 void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
@@ -303,9 +319,32 @@ void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
 	spin_unlock_bh(&msk->pm.lock);
 }
=20
+static int userspace_pm_address_removed(struct mptcp_sock *msk, u8 id)
+{
+	struct mptcp_pm_addr_entry *entry;
+
+	if (id =3D=3D 0)
+		return mptcp_userspace_pm_remove_id_zero_address(msk);
+
+	spin_lock_bh(&msk->pm.lock);
+	entry =3D mptcp_userspace_pm_lookup_addr_by_id(msk, id);
+	if (!entry) {
+		spin_unlock_bh(&msk->pm.lock);
+		return -EINVAL;
+	}
+
+	list_del_rcu(&entry->list);
+	spin_unlock_bh(&msk->pm.lock);
+
+	mptcp_pm_remove_addr_entry(msk, entry);
+
+	sock_kfree_s((struct sock *)msk, entry, sizeof(*entry));
+
+	return 0;
+}
+
 int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	struct mptcp_pm_addr_entry *match;
 	struct mptcp_sock *msk;
 	struct nlattr *id;
 	int err =3D -EINVAL;
@@ -324,32 +363,9 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struc=
t genl_info *info)
=20
 	sk =3D (struct sock *)msk;
=20
-	if (id_val =3D=3D 0) {
-		err =3D mptcp_userspace_pm_remove_id_zero_address(msk);
-		goto out;
-	}
-
 	lock_sock(sk);
-
-	spin_lock_bh(&msk->pm.lock);
-	match =3D mptcp_userspace_pm_lookup_addr_by_id(msk, id_val);
-	if (!match) {
-		spin_unlock_bh(&msk->pm.lock);
-		release_sock(sk);
-		goto out;
-	}
-
-	list_del_rcu(&match->list);
-	spin_unlock_bh(&msk->pm.lock);
-
-	mptcp_pm_remove_addr_entry(msk, match);
-
+	err =3D userspace_pm_address_removed(msk, id_val);
 	release_sock(sk);
-
-	sock_kfree_s(sk, match, sizeof(*match));
-
-	err =3D 0;
-out:
 	if (err)
 		NL_SET_ERR_MSG_ATTR_FMT(info->extack, id,
 					"address with id %u not found",
@@ -359,12 +375,38 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, stru=
ct genl_info *info)
 	return err;
 }
=20
+static int userspace_pm_subflow_established(struct mptcp_sock *msk,
+					    struct mptcp_pm_addr_entry *entry,
+					    struct mptcp_addr_info *remote)
+{
+	struct sock *sk =3D (struct sock *)msk;
+	struct mptcp_pm_local local;
+	int err;
+
+	err =3D mptcp_userspace_pm_append_new_local_addr(msk, entry, false);
+	if (err < 0)
+		return err;
+
+	local.addr =3D entry->addr;
+	local.flags =3D entry->flags;
+	local.ifindex =3D entry->ifindex;
+
+	err =3D __mptcp_subflow_connect(sk, &local, remote);
+	spin_lock_bh(&msk->pm.lock);
+	if (err)
+		mptcp_userspace_pm_delete_local_addr(msk, entry);
+	else
+		msk->pm.subflows++;
+	spin_unlock_bh(&msk->pm.lock);
+
+	return err;
+}
+
 int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info =
*info)
 {
 	struct mptcp_pm_addr_entry entry =3D { 0 };
 	struct mptcp_addr_info addr_r;
 	struct nlattr *raddr, *laddr;
-	struct mptcp_pm_local local;
 	struct mptcp_sock *msk;
 	int err =3D -EINVAL;
 	struct sock *sk;
@@ -402,31 +444,13 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *s=
kb, struct genl_info *info)
 		goto create_err;
 	}
=20
-	err =3D mptcp_userspace_pm_append_new_local_addr(msk, &entry, false);
-	if (err < 0) {
-		NL_SET_ERR_MSG_ATTR(info->extack, laddr,
-				    "did not match address and id");
-		goto create_err;
-	}
-
-	local.addr =3D entry.addr;
-	local.flags =3D entry.flags;
-	local.ifindex =3D entry.ifindex;
-
 	lock_sock(sk);
-	err =3D __mptcp_subflow_connect(sk, &local, &addr_r);
+	err =3D userspace_pm_subflow_established(msk, &entry, &addr_r);
 	release_sock(sk);
=20
 	if (err)
 		GENL_SET_ERR_MSG_FMT(info, "connect error: %d", err);
=20
-	spin_lock_bh(&msk->pm.lock);
-	if (err)
-		mptcp_userspace_pm_delete_local_addr(msk, &entry);
-	else
-		msk->pm.subflows++;
-	spin_unlock_bh(&msk->pm.lock);
-
  create_err:
 	sock_put(sk);
 	return err;
@@ -478,14 +502,34 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_so=
ck *msk,
 	return NULL;
 }
=20
+static int userspace_pm_subflow_closed(struct mptcp_sock *msk,
+				       struct mptcp_pm_addr_entry *local,
+				       struct mptcp_addr_info *remote)
+{
+	struct sock *ssk, *sk =3D (struct sock *)msk;
+
+	ssk =3D mptcp_nl_find_ssk(msk, &local->addr, remote);
+	if (!ssk)
+		return -ESRCH;
+
+	spin_lock_bh(&msk->pm.lock);
+	mptcp_userspace_pm_delete_local_addr(msk, local);
+	spin_unlock_bh(&msk->pm.lock);
+	mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
+	mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
+	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
+
+	return 0;
+}
+
 int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info=
 *info)
 {
 	struct mptcp_pm_addr_entry addr_l;
 	struct mptcp_addr_info addr_r;
 	struct nlattr *raddr, *laddr;
 	struct mptcp_sock *msk;
-	struct sock *sk, *ssk;
 	int err =3D -EINVAL;
+	struct sock *sk;
=20
 	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR) ||
 	    GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
@@ -536,37 +580,47 @@ int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *=
skb, struct genl_info *info
 	}
=20
 	lock_sock(sk);
-	ssk =3D mptcp_nl_find_ssk(msk, &addr_l.addr, &addr_r);
-	if (!ssk) {
-		GENL_SET_ERR_MSG(info, "subflow not found");
-		err =3D -ESRCH;
-		goto release_sock;
-	}
-
-	spin_lock_bh(&msk->pm.lock);
-	mptcp_userspace_pm_delete_local_addr(msk, &addr_l);
-	spin_unlock_bh(&msk->pm.lock);
-	mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
-	mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
-	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
-release_sock:
+	err =3D userspace_pm_subflow_closed(msk, &addr_l, &addr_r);
 	release_sock(sk);
+	if (err)
+		GENL_SET_ERR_MSG(info, "subflow not found");
=20
 destroy_err:
 	sock_put(sk);
 	return err;
 }
=20
+static int userspace_pm_set_priority(struct mptcp_sock *msk,
+				     struct mptcp_pm_addr_entry *local,
+				     struct mptcp_addr_info *remote)
+{
+	struct mptcp_pm_addr_entry *entry;
+	u8 bkup =3D 0;
+
+	if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
+		bkup =3D 1;
+
+	spin_lock_bh(&msk->pm.lock);
+	entry =3D mptcp_userspace_pm_lookup_addr(msk, &local->addr);
+	if (entry) {
+		if (bkup)
+			entry->flags |=3D MPTCP_PM_ADDR_FLAG_BACKUP;
+		else
+			entry->flags &=3D ~MPTCP_PM_ADDR_FLAG_BACKUP;
+	}
+	spin_unlock_bh(&msk->pm.lock);
+
+	return mptcp_pm_nl_mp_prio_send_ack(msk, &local->addr, remote, bkup);
+}
+
 int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_entry *local,
 				 struct genl_info *info)
 {
 	struct mptcp_addr_info rem =3D { .family =3D AF_UNSPEC, };
-	struct mptcp_pm_addr_entry *entry;
 	struct nlattr *attr, *attr_rem;
 	struct mptcp_sock *msk;
 	int ret =3D -EINVAL;
 	struct sock *sk;
-	u8 bkup =3D 0;
=20
 	if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
 		return ret;
@@ -597,21 +651,8 @@ int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_=
entry *local,
 		goto set_flags_err;
 	}
=20
-	if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
-		bkup =3D 1;
-
-	spin_lock_bh(&msk->pm.lock);
-	entry =3D mptcp_userspace_pm_lookup_addr(msk, &local->addr);
-	if (entry) {
-		if (bkup)
-			entry->flags |=3D MPTCP_PM_ADDR_FLAG_BACKUP;
-		else
-			entry->flags &=3D ~MPTCP_PM_ADDR_FLAG_BACKUP;
-	}
-	spin_unlock_bh(&msk->pm.lock);
-
 	lock_sock(sk);
-	ret =3D mptcp_pm_nl_mp_prio_send_ack(msk, &local->addr, &rem, bkup);
+	ret =3D userspace_pm_set_priority(msk, local, &rem);
 	release_sock(sk);
=20
 	/* mptcp_pm_nl_mp_prio_send_ack() only fails in one case */
@@ -691,3 +732,20 @@ int mptcp_userspace_pm_get_addr(u8 id, struct mptcp_pm=
_addr_entry *addr,
 	sock_put(sk);
 	return ret;
 }
+
+static struct mptcp_pm_ops mptcp_userspace_pm =3D {
+	.address_announced	=3D userspace_pm_address_announced,
+	.address_removed	=3D userspace_pm_address_removed,
+	.subflow_established	=3D userspace_pm_subflow_established,
+	.subflow_closed		=3D userspace_pm_subflow_closed,
+	.get_local_id		=3D userspace_pm_get_local_id,
+	.get_priority		=3D userspace_pm_get_priority,
+	.set_priority		=3D userspace_pm_set_priority,
+	.type			=3D MPTCP_PM_TYPE_USERSPACE,
+	.owner			=3D THIS_MODULE,
+};
+
+void __init mptcp_userspace_pm_init(void)
+{
+	mptcp_pm_register(&mptcp_userspace_pm);
+}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index cd36ffe8509b..79cd10447b7b 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1159,6 +1159,7 @@ static inline u8 subflow_get_local_id(const struct mp=
tcp_subflow_context *subflo
 }
=20
 void __init mptcp_pm_nl_init(void);
+void __init mptcp_userspace_pm_init(void);
 void mptcp_pm_nl_work(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk=
);
 unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk=
);
--=20
2.43.0
From nobody Sun May  4 10:55:32 2025
Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org
 [10.30.226.201])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6A4C236A90
	for <mptcp@lists.linux.dev>; Fri,  7 Feb 2025 09:29:47 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
 arc=none smtp.client-ip=10.30.226.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1738920587; cv=none;
 b=ibPQheF5FT7z4apvGwwA2HqtS60eqm0klyjZafXmIuUyuiR9eE69iyT4lbSEQ4dunDTctwwtxYZJH1luAk4OkNIU2eFlx9TeBELrxBZLVkaTWKWkWyAHQb5MGD7UcP8x93Czq9owPTDsSuACfB/pY6f6T5GsyAJw+i/qV137vBA=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1738920587; c=relaxed/simple;
	bh=/vjF+xOhxiZEDpE/Kt393D5jfpxh3o4DgiaTEoJRafg=;
	h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:
	 MIME-Version;
 b=CUrc1VBmvI9bCmxiY8A3qh//51ddOobQLYFIhu7GNW2qX9k7Sv2atmuydneumkpbaVU+rkFZxRqGIeJ8VjZMnGvNKO727je3MRAmfaLgltm0yOC0v89KPjKXmuoPlPNpBwcyOp/r9JnL3evJmCguo06rFa6dTXC00F8hhGohwqE=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
 dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b=h7/GSauW; arc=none smtp.client-ip=10.30.226.201
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
 header.b="h7/GSauW"
Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D19AC4CED6;
	Fri,  7 Feb 2025 09:29:45 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;
	s=k20201202; t=1738920587;
	bh=/vjF+xOhxiZEDpE/Kt393D5jfpxh3o4DgiaTEoJRafg=;
	h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
	b=h7/GSauWABj7vyQi1V8ZuyYT65ilxnq+/xvgDHEaGsBzAM43RMskvPuazJSD5Qltg
	 E8OQYAmxxK/A9CDEhLQ3OoAIzoUlQlVjmg+/W8XFx4zA/17sltfYZisuDUfAV1InwK
	 h9s18Myl/+JHEkE8vo80fm73N5EsLxCoGVjiUsruHswKWgFgsZqozXoZN0vVGfgy0L
	 IBEZIx4IV8fBXk5wBgiEeF/CUmKV6+pujP0dq1+M51MRKvDN9p/9RoDdT0B9884xVS
	 KhTWYI+HEmU+tYzVhUjq69UyW302HuCffBRcd6utgkHh947wRtU1N0UOxdgQybWJsQ
	 e19O35kkV9h6w==
From: Geliang Tang <geliang@kernel.org>
To: mptcp@lists.linux.dev
Cc: Geliang Tang <tanggeliang@kylinos.cn>
Subject: [PATCH mptcp-next v4 4/4] mptcp: initialize and release mptcp_pm_ops
Date: Fri,  7 Feb 2025 17:29:34 +0800
Message-ID: 
 <1a5446abf3d1d4d16074f5bb801f93e720228d32.1738919954.git.tanggeliang@kylinos.cn>
X-Mailer: git-send-email 2.43.0
In-Reply-To: <cover.1738919954.git.tanggeliang@kylinos.cn>
References: <cover.1738919954.git.tanggeliang@kylinos.cn>
Precedence: bulk
X-Mailing-List: mptcp@lists.linux.dev
List-Id: <mptcp.lists.linux.dev>
List-Subscribe: <mailto:mptcp+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:mptcp+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"

From: Geliang Tang <tanggeliang@kylinos.cn>

Add a struct mptcp_pm_ops pointer "ops" in struct mptcp_pm_data, and two
functions mptcp_pm_initialize() and mptcp_pm_release(), to set and release
this pointer. mptcp_pm_initialize() is invoked in mptcp_pm_data_reset(),
while mptcp_pm_release() is invoked in __mptcp_destroy_sock().

In this way, different userspace path managers can be initialized through
the pm_type sysctl, and then called into their respective interfaces
through "ops" of "msk->pm".

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 net/mptcp/pm.c           | 49 ++++++++++++++++++++++++++++++++++++++--
 net/mptcp/pm_netlink.c   | 11 ++++++++-
 net/mptcp/pm_userspace.c | 28 +++++++++++++++++------
 net/mptcp/protocol.c     | 10 +++++++-
 net/mptcp/protocol.h     |  3 +++
 5 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 1304a0c99e12..91c815856d14 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -76,6 +76,9 @@ void mptcp_pm_new_connection(struct mptcp_sock *msk, cons=
t struct sock *ssk, int
=20
 	WRITE_ONCE(pm->server_side, server_side);
 	mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC);
+
+	if (pm->ops && pm->ops->created)
+		pm->ops->created(msk);
 }
=20
 bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
@@ -153,16 +156,24 @@ void mptcp_pm_fully_established(struct mptcp_sock *ms=
k, const struct sock *ssk)
 	msk->pm.status |=3D BIT(MPTCP_PM_ALREADY_ESTABLISHED);
 	spin_unlock_bh(&pm->lock);
=20
-	if (announce)
+	if (announce) {
 		mptcp_event(MPTCP_EVENT_ESTABLISHED, msk, ssk, GFP_ATOMIC);
+
+		if (pm->ops && pm->ops->established)
+			pm->ops->established(msk);
+	}
 }
=20
 void mptcp_pm_connection_closed(struct mptcp_sock *msk)
 {
 	pr_debug("msk=3D%p\n", msk);
=20
-	if (msk->token)
+	if (msk->token) {
 		mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
+
+		if (msk->pm.ops && msk->pm.ops->closed)
+			msk->pm.ops->closed(msk);
+	}
 }
=20
 void mptcp_pm_subflow_established(struct mptcp_sock *msk)
@@ -629,6 +640,10 @@ void mptcp_pm_data_reset(struct mptcp_sock *msk)
 		WRITE_ONCE(pm->work_pending, 0);
 		WRITE_ONCE(pm->accept_addr, 0);
 		WRITE_ONCE(pm->accept_subflow, 0);
+
+		rcu_read_lock();
+		mptcp_pm_initialize(msk, mptcp_pm_find(pm_type));
+		rcu_read_unlock();
 	}
=20
 	WRITE_ONCE(pm->addr_signal, 0);
@@ -704,3 +719,33 @@ void mptcp_pm_unregister(struct mptcp_pm_ops *pm)
 	list_del_rcu(&pm->list);
 	spin_unlock(&mptcp_pm_list_lock);
 }
+
+int mptcp_pm_initialize(struct mptcp_sock *msk, struct mptcp_pm_ops *pm)
+{
+	if (!pm)
+		return -EINVAL;
+
+	if (!bpf_try_module_get(pm, pm->owner))
+		return -EBUSY;
+
+	msk->pm.ops =3D pm;
+	if (msk->pm.ops->init)
+		msk->pm.ops->init(msk);
+
+	pr_debug("userspace_pm type %u initialized\n", msk->pm.ops->type);
+	return 0;
+}
+
+void mptcp_pm_release(struct mptcp_sock *msk)
+{
+	struct mptcp_pm_ops *pm =3D msk->pm.ops;
+
+	if (!pm)
+		return;
+
+	msk->pm.ops =3D NULL;
+	if (pm->release)
+		pm->release(msk);
+
+	bpf_module_put(pm, pm->owner);
+}
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index ef85a60151ad..91f01f895e18 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1080,6 +1080,7 @@ static int mptcp_pm_nl_create_listen_socket(struct so=
ck *sk,
 	int addrlen =3D sizeof(struct sockaddr_in);
 	struct sockaddr_storage addr;
 	struct sock *newsk, *ssk;
+	struct mptcp_sock *msk;
 	int backlog =3D 1024;
 	int err;
=20
@@ -1104,8 +1105,9 @@ static int mptcp_pm_nl_create_listen_socket(struct so=
ck *sk,
 				      is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET",
 				      &mptcp_keys[is_ipv6]);
=20
+	msk =3D mptcp_sk(newsk);
 	lock_sock(newsk);
-	ssk =3D __mptcp_nmpc_sk(mptcp_sk(newsk));
+	ssk =3D __mptcp_nmpc_sk(msk);
 	release_sock(newsk);
 	if (IS_ERR(ssk))
 		return PTR_ERR(ssk);
@@ -1136,6 +1138,13 @@ static int mptcp_pm_nl_create_listen_socket(struct s=
ock *sk,
 	if (!err)
 		mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CREATED);
 	release_sock(ssk);
+
+	if (!err) {
+		lock_sock(newsk);
+		if (msk->pm.ops && msk->pm.ops->listener_created)
+			msk->pm.ops->listener_created(msk);
+		release_sock(newsk);
+	}
 	return err;
 }
=20
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 3d324aaec550..74406f8cc4cf 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -159,7 +159,9 @@ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *=
msk,
 	if (new_entry.addr.port =3D=3D msk_sport)
 		new_entry.addr.port =3D 0;
=20
-	return userspace_pm_get_local_id(msk, &new_entry);
+	return msk->pm.ops && msk->pm.ops->get_local_id ?
+	       msk->pm.ops->get_local_id(msk, &new_entry) :
+	       userspace_pm_get_local_id(msk, &new_entry);
 }
=20
 static bool userspace_pm_get_priority(struct mptcp_sock *msk,
@@ -179,7 +181,9 @@ static bool userspace_pm_get_priority(struct mptcp_sock=
 *msk,
 bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
 				  struct mptcp_addr_info *skc)
 {
-	return userspace_pm_get_priority(msk, skc);
+	return msk->pm.ops && msk->pm.ops->get_priority ?
+	       msk->pm.ops->get_priority(msk, skc) :
+	       userspace_pm_get_priority(msk, skc);
 }
=20
 static struct mptcp_sock *mptcp_userspace_pm_get_sock(const struct genl_in=
fo *info)
@@ -264,7 +268,9 @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, stru=
ct genl_info *info)
 	}
=20
 	lock_sock(sk);
-	err =3D userspace_pm_address_announced(msk, &addr_val);
+	err =3D msk->pm.ops && msk->pm.ops->address_announced ?
+	      msk->pm.ops->address_announced(msk, &addr_val) :
+	      userspace_pm_address_announced(msk, &addr_val);
 	release_sock(sk);
 	if (err)
 		NL_SET_ERR_MSG_ATTR(info->extack, addr,
@@ -364,7 +370,9 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct=
 genl_info *info)
 	sk =3D (struct sock *)msk;
=20
 	lock_sock(sk);
-	err =3D userspace_pm_address_removed(msk, id_val);
+	err =3D msk->pm.ops && msk->pm.ops->address_removed ?
+	      msk->pm.ops->address_removed(msk, id_val) :
+	      userspace_pm_address_removed(msk, id_val);
 	release_sock(sk);
 	if (err)
 		NL_SET_ERR_MSG_ATTR_FMT(info->extack, id,
@@ -445,7 +453,9 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb=
, struct genl_info *info)
 	}
=20
 	lock_sock(sk);
-	err =3D userspace_pm_subflow_established(msk, &entry, &addr_r);
+	err =3D msk->pm.ops && msk->pm.ops->subflow_established ?
+	      msk->pm.ops->subflow_established(msk, &entry, &addr_r) :
+	      userspace_pm_subflow_established(msk, &entry, &addr_r);
 	release_sock(sk);
=20
 	if (err)
@@ -580,7 +590,9 @@ int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *sk=
b, struct genl_info *info
 	}
=20
 	lock_sock(sk);
-	err =3D userspace_pm_subflow_closed(msk, &addr_l, &addr_r);
+	err =3D msk->pm.ops && msk->pm.ops->subflow_closed ?
+	      msk->pm.ops->subflow_closed(msk, &addr_l, &addr_r) :
+	      userspace_pm_subflow_closed(msk, &addr_l, &addr_r);
 	release_sock(sk);
 	if (err)
 		GENL_SET_ERR_MSG(info, "subflow not found");
@@ -652,7 +664,9 @@ int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_e=
ntry *local,
 	}
=20
 	lock_sock(sk);
-	ret =3D userspace_pm_set_priority(msk, local, &rem);
+	ret =3D msk->pm.ops && msk->pm.ops->set_priority ?
+	      msk->pm.ops->set_priority(msk, local, &rem) :
+	      userspace_pm_set_priority(msk, local, &rem);
 	release_sock(sk);
=20
 	/* mptcp_pm_nl_mp_prio_send_ack() only fails in one case */
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 2b48cf648346..3bfb4c786289 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2944,6 +2944,7 @@ static void __mptcp_destroy_sock(struct sock *sk)
 	sk_stop_timer(sk, &sk->sk_timer);
 	msk->pm.status =3D 0;
 	mptcp_release_sched(msk);
+	mptcp_pm_release(msk);
=20
 	sk->sk_prot->destroy(sk);
=20
@@ -2967,13 +2968,14 @@ static __poll_t mptcp_check_readable(struct sock *s=
k)
=20
 static void mptcp_check_listen_stop(struct sock *sk)
 {
+	struct mptcp_sock *msk =3D mptcp_sk(sk);
 	struct sock *ssk;
=20
 	if (inet_sk_state_load(sk) !=3D TCP_LISTEN)
 		return;
=20
 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-	ssk =3D mptcp_sk(sk)->first;
+	ssk =3D msk->first;
 	if (WARN_ON_ONCE(!ssk || inet_sk_state_load(ssk) !=3D TCP_LISTEN))
 		return;
=20
@@ -2983,6 +2985,9 @@ static void mptcp_check_listen_stop(struct sock *sk)
 	inet_csk_listen_stop(ssk);
 	mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
 	release_sock(ssk);
+
+	if (msk->pm.ops && msk->pm.ops->listener_closed)
+		msk->pm.ops->listener_closed(msk);
 }
=20
 bool __mptcp_close(struct sock *sk, long timeout)
@@ -3802,6 +3807,9 @@ static int mptcp_listen(struct socket *sock, int back=
log)
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
 		mptcp_copy_inaddrs(sk, ssk);
 		mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CREATED);
+
+		if (msk->pm.ops && msk->pm.ops->listener_created)
+			msk->pm.ops->listener_created(msk);
 	}
=20
 unlock:
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 79cd10447b7b..ba5f0abb6d8b 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -221,6 +221,7 @@ struct mptcp_pm_data {
 	struct mptcp_addr_info remote;
 	struct list_head anno_list;
 	struct list_head userspace_pm_local_addr_list;
+	struct mptcp_pm_ops *ops;
=20
 	spinlock_t	lock;		/*protects the whole PM data */
=20
@@ -1052,6 +1053,8 @@ struct mptcp_pm_ops *mptcp_pm_find(enum mptcp_pm_type=
 type);
 int mptcp_pm_validate(struct mptcp_pm_ops *pm);
 int mptcp_pm_register(struct mptcp_pm_ops *pm);
 void mptcp_pm_unregister(struct mptcp_pm_ops *pm);
+int mptcp_pm_initialize(struct mptcp_sock *msk, struct mptcp_pm_ops *pm);
+void mptcp_pm_release(struct mptcp_sock *msk);
=20
 void mptcp_free_local_addr_list(struct mptcp_sock *msk);
=20
--=20
2.43.0