All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/6] mptcp: Path manager mode selection
@ 2022-04-27 22:49 Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 1/6] mptcp: Remove redundant assignments in path manager init Mat Martineau
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:49 UTC (permalink / raw)
  To: netdev; +Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp

MPTCP already has an in-kernel path manager (PM) to add and remove TCP
subflows associated with a given MPTCP connection. This in-kernel PM has
been designed to handle typical server-side use cases, but is not very
flexible or configurable for client devices that may have more
complicated policies to implement.

This patch series from the MPTCP tree is the first step toward adding a
generic-netlink-based API for MPTCP path management, which a privileged
userspace daemon will be able to use to control subflow
establishment. These patches add a per-namespace sysctl to select the
default PM type (in-kernel or userspace) for new MPTCP sockets. New
self-tests confirm expected behavior when userspace PM is selected but
there is no daemon available to handle existing MPTCP PM events.

Subsequent patch series (already staged in the MPTCP tree) will add the
generic netlink path management API.


Mat Martineau (6):
  mptcp: Remove redundant assignments in path manager init
  mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode
  mptcp: Bypass kernel PM when userspace PM is enabled
  mptcp: Make kernel path manager check for userspace-managed sockets
  mptcp: Add a per-namespace sysctl to set the default path manager type
  selftests: mptcp: Add tests for userspace PM type

 Documentation/networking/mptcp-sysctl.rst     | 18 +++++
 net/mptcp/ctrl.c                              | 21 ++++++
 net/mptcp/pm.c                                | 50 +++++++++-----
 net/mptcp/pm_netlink.c                        | 30 ++++-----
 net/mptcp/protocol.h                          | 16 ++++-
 .../testing/selftests/net/mptcp/mptcp_join.sh | 66 +++++++++++++++++++
 6 files changed, 167 insertions(+), 34 deletions(-)


base-commit: 03fa8fc93e443e6caa485cc741328a1386c63630
-- 
2.36.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH net-next 1/6] mptcp: Remove redundant assignments in path manager init
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
@ 2022-04-27 22:49 ` Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 2/6] mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode Mat Martineau
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:49 UTC (permalink / raw)
  To: netdev; +Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp

A few members of the mptcp_pm_data struct were assigned to hard-coded
values in mptcp_pm_data_reset(), and then immediately changed in
mptcp_pm_nl_data_init().

Instead, flatten all the assignments in to mptcp_pm_data_reset().

v2: Resolve conflicts due to rename of mptcp_pm_data_reset()
v4: Resolve conflict in mptcp_pm_data_reset()

Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 net/mptcp/pm.c         | 32 ++++++++++++++++++--------------
 net/mptcp/pm_netlink.c | 12 ------------
 net/mptcp/protocol.h   |  1 -
 3 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 14f448d82bb2..4de90e618be3 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -415,21 +415,25 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
 
 void mptcp_pm_data_reset(struct mptcp_sock *msk)
 {
-	msk->pm.add_addr_signaled = 0;
-	msk->pm.add_addr_accepted = 0;
-	msk->pm.local_addr_used = 0;
-	msk->pm.subflows = 0;
-	msk->pm.rm_list_tx.nr = 0;
-	msk->pm.rm_list_rx.nr = 0;
-	WRITE_ONCE(msk->pm.work_pending, false);
-	WRITE_ONCE(msk->pm.addr_signal, 0);
-	WRITE_ONCE(msk->pm.accept_addr, false);
-	WRITE_ONCE(msk->pm.accept_subflow, false);
-	WRITE_ONCE(msk->pm.remote_deny_join_id0, false);
-	msk->pm.status = 0;
-	bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
+	bool subflows_allowed = !!mptcp_pm_get_subflows_max(msk);
+	struct mptcp_pm_data *pm = &msk->pm;
 
-	mptcp_pm_nl_data_init(msk);
+	pm->add_addr_signaled = 0;
+	pm->add_addr_accepted = 0;
+	pm->local_addr_used = 0;
+	pm->subflows = 0;
+	pm->rm_list_tx.nr = 0;
+	pm->rm_list_rx.nr = 0;
+	WRITE_ONCE(pm->work_pending,
+		   (!!mptcp_pm_get_local_addr_max(msk) && subflows_allowed) ||
+		   !!mptcp_pm_get_add_addr_signal_max(msk));
+	WRITE_ONCE(pm->addr_signal, 0);
+	WRITE_ONCE(pm->accept_addr,
+		   !!mptcp_pm_get_add_addr_accept_max(msk) && subflows_allowed);
+	WRITE_ONCE(pm->accept_subflow, subflows_allowed);
+	WRITE_ONCE(pm->remote_deny_join_id0, false);
+	pm->status = 0;
+	bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
 }
 
 void mptcp_pm_data_init(struct mptcp_sock *msk)
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index c20261b612e9..bbbbfb421eec 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1061,18 +1061,6 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
 	return ret;
 }
 
-void mptcp_pm_nl_data_init(struct mptcp_sock *msk)
-{
-	struct mptcp_pm_data *pm = &msk->pm;
-	bool subflows;
-
-	subflows = !!mptcp_pm_get_subflows_max(msk);
-	WRITE_ONCE(pm->work_pending, (!!mptcp_pm_get_local_addr_max(msk) && subflows) ||
-		   !!mptcp_pm_get_add_addr_signal_max(msk));
-	WRITE_ONCE(pm->accept_addr, !!mptcp_pm_get_add_addr_accept_max(msk) && subflows);
-	WRITE_ONCE(pm->accept_subflow, subflows);
-}
-
 #define MPTCP_PM_CMD_GRP_OFFSET       0
 #define MPTCP_PM_EV_GRP_OFFSET        1
 
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 3a8740fef918..0316605de559 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -828,7 +828,6 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 void __init mptcp_pm_nl_init(void);
-void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
 void mptcp_pm_nl_work(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
 				     const struct mptcp_rm_list *rm_list);
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 2/6] mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 1/6] mptcp: Remove redundant assignments in path manager init Mat Martineau
@ 2022-04-27 22:49 ` Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 3/6] mptcp: Bypass kernel PM when userspace PM is enabled Mat Martineau
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:49 UTC (permalink / raw)
  To: netdev; +Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp

When adding support for netlink path management commands, the kernel
needs to know whether paths are being controlled by the in-kernel path
manager or a userspace PM.

Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 net/mptcp/pm.c       | 4 ++++
 net/mptcp/protocol.h | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 4de90e618be3..f9f1bf4be95e 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -424,6 +424,10 @@ void mptcp_pm_data_reset(struct mptcp_sock *msk)
 	pm->subflows = 0;
 	pm->rm_list_tx.nr = 0;
 	pm->rm_list_rx.nr = 0;
+	WRITE_ONCE(pm->pm_type, MPTCP_PM_TYPE_KERNEL);
+	/* pm->work_pending must be only be set to 'true' when
+	 * pm->pm_type is set to MPTCP_PM_TYPE_KERNEL
+	 */
 	WRITE_ONCE(pm->work_pending,
 		   (!!mptcp_pm_get_local_addr_max(msk) && subflows_allowed) ||
 		   !!mptcp_pm_get_add_addr_signal_max(msk));
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 0316605de559..f65395f04f81 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -184,6 +184,14 @@ enum mptcp_pm_status {
 					 */
 };
 
+enum mptcp_pm_type {
+	MPTCP_PM_TYPE_KERNEL = 0,
+	MPTCP_PM_TYPE_USERSPACE,
+
+	__MPTCP_PM_TYPE_NR,
+	__MPTCP_PM_TYPE_MAX = __MPTCP_PM_TYPE_NR - 1,
+};
+
 /* Status bits below MPTCP_PM_ALREADY_ESTABLISHED need pm worker actions */
 #define MPTCP_PM_WORK_MASK ((1 << MPTCP_PM_ALREADY_ESTABLISHED) - 1)
 
@@ -212,6 +220,7 @@ struct mptcp_pm_data {
 	u8		add_addr_signaled;
 	u8		add_addr_accepted;
 	u8		local_addr_used;
+	u8		pm_type;
 	u8		subflows;
 	u8		status;
 	DECLARE_BITMAP(id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 3/6] mptcp: Bypass kernel PM when userspace PM is enabled
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 1/6] mptcp: Remove redundant assignments in path manager init Mat Martineau
  2022-04-27 22:49 ` [PATCH net-next 2/6] mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode Mat Martineau
@ 2022-04-27 22:49 ` Mat Martineau
  2022-04-27 22:50 ` [PATCH net-next 4/6] mptcp: Make kernel path manager check for userspace-managed sockets Mat Martineau
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:49 UTC (permalink / raw)
  To: netdev
  Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp,
	Kishen Maloor

When a MPTCP connection is managed by a userspace PM, bypass the kernel
PM for incoming advertisements and subflow events. Netlink events are
still sent to userspace.

v2: Remove unneeded check in mptcp_pm_rm_addr_received() (Kishen Maloor)
v3: Add and use helper function for PM mode (Paolo Abeni)

Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 net/mptcp/pm.c       | 2 +-
 net/mptcp/protocol.h | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index f9f1bf4be95e..5320270b3926 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -208,7 +208,7 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 
 	spin_lock_bh(&pm->lock);
 
-	if (!READ_ONCE(pm->accept_addr)) {
+	if (!READ_ONCE(pm->accept_addr) || mptcp_pm_is_userspace(msk)) {
 		mptcp_pm_announce_addr(msk, addr, true);
 		mptcp_pm_add_addr_send_ack(msk);
 	} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index f65395f04f81..79606e9d3f2a 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -805,6 +805,11 @@ static inline bool mptcp_pm_should_rm_signal(struct mptcp_sock *msk)
 	return READ_ONCE(msk->pm.addr_signal) & BIT(MPTCP_RM_ADDR_SIGNAL);
 }
 
+static inline bool mptcp_pm_is_userspace(const struct mptcp_sock *msk)
+{
+	return READ_ONCE(msk->pm.pm_type) == MPTCP_PM_TYPE_USERSPACE;
+}
+
 static inline unsigned int mptcp_add_addr_len(int family, bool echo, bool port)
 {
 	u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 4/6] mptcp: Make kernel path manager check for userspace-managed sockets
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
                   ` (2 preceding siblings ...)
  2022-04-27 22:49 ` [PATCH net-next 3/6] mptcp: Bypass kernel PM when userspace PM is enabled Mat Martineau
@ 2022-04-27 22:50 ` Mat Martineau
  2022-04-27 22:50 ` [PATCH net-next 5/6] mptcp: Add a per-namespace sysctl to set the default path manager type Mat Martineau
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:50 UTC (permalink / raw)
  To: netdev; +Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp

Userspace-managed sockets should not have their subflows or
advertisements changed by the kernel path manager.

v3: Use helper function for PM mode (Paolo Abeni)

Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 net/mptcp/pm_netlink.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index bbbbfb421eec..473e5aa7baf4 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1220,7 +1220,8 @@ static int mptcp_nl_add_subflow_or_signal_addr(struct net *net)
 	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
 		struct sock *sk = (struct sock *)msk;
 
-		if (!READ_ONCE(msk->fully_established))
+		if (!READ_ONCE(msk->fully_established) ||
+		    mptcp_pm_is_userspace(msk))
 			goto next;
 
 		lock_sock(sk);
@@ -1363,6 +1364,9 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
 		struct sock *sk = (struct sock *)msk;
 		bool remove_subflow;
 
+		if (mptcp_pm_is_userspace(msk))
+			goto next;
+
 		if (list_empty(&msk->conn_list)) {
 			mptcp_pm_remove_anno_addr(msk, addr, false);
 			goto next;
@@ -1397,7 +1401,7 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,
 		struct sock *sk = (struct sock *)msk;
 		struct mptcp_addr_info msk_local;
 
-		if (list_empty(&msk->conn_list))
+		if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
 			goto next;
 
 		local_address((struct sock_common *)msk, &msk_local);
@@ -1504,9 +1508,11 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
 	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
 		struct sock *sk = (struct sock *)msk;
 
-		lock_sock(sk);
-		mptcp_pm_remove_addrs_and_subflows(msk, rm_list);
-		release_sock(sk);
+		if (!mptcp_pm_is_userspace(msk)) {
+			lock_sock(sk);
+			mptcp_pm_remove_addrs_and_subflows(msk, rm_list);
+			release_sock(sk);
+		}
 
 		sock_put(sk);
 		cond_resched();
@@ -1779,7 +1785,7 @@ static int mptcp_nl_set_flags(struct net *net,
 	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
 		struct sock *sk = (struct sock *)msk;
 
-		if (list_empty(&msk->conn_list))
+		if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
 			goto next;
 
 		lock_sock(sk);
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 5/6] mptcp: Add a per-namespace sysctl to set the default path manager type
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
                   ` (3 preceding siblings ...)
  2022-04-27 22:50 ` [PATCH net-next 4/6] mptcp: Make kernel path manager check for userspace-managed sockets Mat Martineau
@ 2022-04-27 22:50 ` Mat Martineau
  2022-04-27 22:50 ` [PATCH net-next 6/6] selftests: mptcp: Add tests for userspace PM type Mat Martineau
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:50 UTC (permalink / raw)
  To: netdev; +Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp

The new net.mptcp.pm_type sysctl determines which path manager will be
used by each newly-created MPTCP socket.

v2: Handle builds without CONFIG_SYSCTL
v3: Clarify logic for type-specific PM init (Geliang Tang and Paolo Abeni)

Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/networking/mptcp-sysctl.rst | 18 ++++++++++++
 net/mptcp/ctrl.c                          | 21 ++++++++++++++
 net/mptcp/pm.c                            | 34 +++++++++++++++--------
 net/mptcp/protocol.h                      |  1 +
 4 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
index b0d4da71e68e..e263dfcc4b40 100644
--- a/Documentation/networking/mptcp-sysctl.rst
+++ b/Documentation/networking/mptcp-sysctl.rst
@@ -46,6 +46,24 @@ allow_join_initial_addr_port - BOOLEAN
 
 	Default: 1
 
+pm_type - INTEGER
+
+	Set the default path manager type to use for each new MPTCP
+	socket. In-kernel path management will control subflow
+	connections and address advertisements according to
+	per-namespace values configured over the MPTCP netlink
+	API. Userspace path management puts per-MPTCP-connection subflow
+	connection decisions and address advertisements under control of
+	a privileged userspace program, at the cost of more netlink
+	traffic to propagate all of the related events and commands.
+
+	This is a per-namespace sysctl.
+
+	* 0 - In-kernel path manager
+	* 1 - Userspace path manager
+
+	Default: 0
+
 stale_loss_cnt - INTEGER
 	The number of MPTCP-level retransmission intervals with no traffic and
 	pending outstanding data on a given subflow required to declare it stale.
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 8b235468c88f..ae20b7d92e28 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -16,6 +16,11 @@
 #define MPTCP_SYSCTL_PATH "net/mptcp"
 
 static int mptcp_pernet_id;
+
+#ifdef CONFIG_SYSCTL
+static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX;
+#endif
+
 struct mptcp_pernet {
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header *ctl_table_hdr;
@@ -26,6 +31,7 @@ struct mptcp_pernet {
 	u8 mptcp_enabled;
 	u8 checksum_enabled;
 	u8 allow_join_initial_addr_port;
+	u8 pm_type;
 };
 
 static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
@@ -58,6 +64,11 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net)
 	return mptcp_get_pernet(net)->stale_loss_cnt;
 }
 
+int mptcp_get_pm_type(const struct net *net)
+{
+	return mptcp_get_pernet(net)->pm_type;
+}
+
 static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 {
 	pernet->mptcp_enabled = 1;
@@ -65,6 +76,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 	pernet->checksum_enabled = 0;
 	pernet->allow_join_initial_addr_port = 1;
 	pernet->stale_loss_cnt = 4;
+	pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
 }
 
 #ifdef CONFIG_SYSCTL
@@ -108,6 +120,14 @@ static struct ctl_table mptcp_sysctl_table[] = {
 		.mode = 0644,
 		.proc_handler = proc_douintvec_minmax,
 	},
+	{
+		.procname = "pm_type",
+		.maxlen = sizeof(u8),
+		.mode = 0644,
+		.proc_handler = proc_dou8vec_minmax,
+		.extra1       = SYSCTL_ZERO,
+		.extra2       = &mptcp_pm_type_max
+	},
 	{}
 };
 
@@ -128,6 +148,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
 	table[2].data = &pernet->checksum_enabled;
 	table[3].data = &pernet->allow_join_initial_addr_port;
 	table[4].data = &pernet->stale_loss_cnt;
+	table[5].data = &pernet->pm_type;
 
 	hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
 	if (!hdr)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 5320270b3926..57f67578a47f 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -415,7 +415,7 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
 
 void mptcp_pm_data_reset(struct mptcp_sock *msk)
 {
-	bool subflows_allowed = !!mptcp_pm_get_subflows_max(msk);
+	u8 pm_type = mptcp_get_pm_type(sock_net((struct sock *)msk));
 	struct mptcp_pm_data *pm = &msk->pm;
 
 	pm->add_addr_signaled = 0;
@@ -424,17 +424,29 @@ void mptcp_pm_data_reset(struct mptcp_sock *msk)
 	pm->subflows = 0;
 	pm->rm_list_tx.nr = 0;
 	pm->rm_list_rx.nr = 0;
-	WRITE_ONCE(pm->pm_type, MPTCP_PM_TYPE_KERNEL);
-	/* pm->work_pending must be only be set to 'true' when
-	 * pm->pm_type is set to MPTCP_PM_TYPE_KERNEL
-	 */
-	WRITE_ONCE(pm->work_pending,
-		   (!!mptcp_pm_get_local_addr_max(msk) && subflows_allowed) ||
-		   !!mptcp_pm_get_add_addr_signal_max(msk));
+	WRITE_ONCE(pm->pm_type, pm_type);
+
+	if (pm_type == MPTCP_PM_TYPE_KERNEL) {
+		bool subflows_allowed = !!mptcp_pm_get_subflows_max(msk);
+
+		/* pm->work_pending must be only be set to 'true' when
+		 * pm->pm_type is set to MPTCP_PM_TYPE_KERNEL
+		 */
+		WRITE_ONCE(pm->work_pending,
+			   (!!mptcp_pm_get_local_addr_max(msk) &&
+			    subflows_allowed) ||
+			   !!mptcp_pm_get_add_addr_signal_max(msk));
+		WRITE_ONCE(pm->accept_addr,
+			   !!mptcp_pm_get_add_addr_accept_max(msk) &&
+			   subflows_allowed);
+		WRITE_ONCE(pm->accept_subflow, subflows_allowed);
+	} else {
+		WRITE_ONCE(pm->work_pending, 0);
+		WRITE_ONCE(pm->accept_addr, 0);
+		WRITE_ONCE(pm->accept_subflow, 0);
+	}
+
 	WRITE_ONCE(pm->addr_signal, 0);
-	WRITE_ONCE(pm->accept_addr,
-		   !!mptcp_pm_get_add_addr_accept_max(msk) && subflows_allowed);
-	WRITE_ONCE(pm->accept_subflow, subflows_allowed);
 	WRITE_ONCE(pm->remote_deny_join_id0, false);
 	pm->status = 0;
 	bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 79606e9d3f2a..54d2b3b2d100 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -585,6 +585,7 @@ unsigned int mptcp_get_add_addr_timeout(const struct net *net);
 int mptcp_is_checksum_enabled(const struct net *net);
 int mptcp_allow_join_id0(const struct net *net);
 unsigned int mptcp_stale_loss_cnt(const struct net *net);
+int mptcp_get_pm_type(const struct net *net);
 void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
 				     struct mptcp_options_received *mp_opt);
 bool __mptcp_retransmit_pending_data(struct sock *sk);
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 6/6] selftests: mptcp: Add tests for userspace PM type
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
                   ` (4 preceding siblings ...)
  2022-04-27 22:50 ` [PATCH net-next 5/6] mptcp: Add a per-namespace sysctl to set the default path manager type Mat Martineau
@ 2022-04-27 22:50 ` Mat Martineau
  2022-04-29  1:57 ` [PATCH net-next 0/6] mptcp: Path manager mode selection Jakub Kicinski
  2022-04-30  1:00 ` patchwork-bot+netdevbpf
  7 siblings, 0 replies; 11+ messages in thread
From: Mat Martineau @ 2022-04-27 22:50 UTC (permalink / raw)
  To: netdev
  Cc: Mat Martineau, davem, kuba, pabeni, matthieu.baerts, mptcp, Geliang Tang

These tests ensure that the in-kernel path manager is bypassed when
the userspace path manager is configured. Kernel code is still
responsible for ADD_ADDR echo, so also make sure that's working.

Tested-by: Geliang Tang <geliang.tang@suse.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 .../testing/selftests/net/mptcp/mptcp_join.sh | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index e5c8fc2816fb..b27854f976f7 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -70,6 +70,7 @@ init_partial()
 		ip netns add $netns || exit $ksft_skip
 		ip -net $netns link set lo up
 		ip netns exec $netns sysctl -q net.mptcp.enabled=1
+		ip netns exec $netns sysctl -q net.mptcp.pm_type=0
 		ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
 		ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
 		if [ $checksum -eq 1 ]; then
@@ -1611,6 +1612,13 @@ wait_attempt_fail()
 	return 1
 }
 
+set_userspace_pm()
+{
+	local ns=$1
+
+	ip netns exec $ns sysctl -q net.mptcp.pm_type=1
+}
+
 subflows_tests()
 {
 	if reset "no JOIN"; then
@@ -2698,6 +2706,63 @@ fail_tests()
 	fi
 }
 
+userspace_tests()
+{
+	# userspace pm type prevents add_addr
+	if reset "userspace pm type prevents add_addr"; then
+		set_userspace_pm $ns1
+		pm_nl_set_limits $ns1 0 2
+		pm_nl_set_limits $ns2 0 2
+		pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+		run_tests $ns1 $ns2 10.0.1.1
+		chk_join_nr 0 0 0
+		chk_add_nr 0 0
+	fi
+
+	# userspace pm type rejects join
+	if reset "userspace pm type rejects join"; then
+		set_userspace_pm $ns1
+		pm_nl_set_limits $ns1 1 1
+		pm_nl_set_limits $ns2 1 1
+		pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+		run_tests $ns1 $ns2 10.0.1.1
+		chk_join_nr 1 1 0
+	fi
+
+	# userspace pm type does not send join
+	if reset "userspace pm type does not send join"; then
+		set_userspace_pm $ns2
+		pm_nl_set_limits $ns1 1 1
+		pm_nl_set_limits $ns2 1 1
+		pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+		run_tests $ns1 $ns2 10.0.1.1
+		chk_join_nr 0 0 0
+	fi
+
+	# userspace pm type prevents mp_prio
+	if reset "userspace pm type prevents mp_prio"; then
+		set_userspace_pm $ns1
+		pm_nl_set_limits $ns1 1 1
+		pm_nl_set_limits $ns2 1 1
+		pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+		run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+		chk_join_nr 1 1 0
+		chk_prio_nr 0 0
+	fi
+
+	# userspace pm type prevents rm_addr
+	if reset "userspace pm type prevents rm_addr"; then
+		set_userspace_pm $ns1
+		set_userspace_pm $ns2
+		pm_nl_set_limits $ns1 0 1
+		pm_nl_set_limits $ns2 0 1
+		pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+		run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
+		chk_join_nr 0 0 0
+		chk_rm_nr 0 0
+	fi
+}
+
 implicit_tests()
 {
 	# userspace pm type prevents add_addr
@@ -2767,6 +2832,7 @@ all_tests_sorted=(
 	m@fullmesh_tests
 	z@fastclose_tests
 	F@fail_tests
+	u@userspace_tests
 	I@implicit_tests
 )
 
-- 
2.36.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 0/6] mptcp: Path manager mode selection
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
                   ` (5 preceding siblings ...)
  2022-04-27 22:50 ` [PATCH net-next 6/6] selftests: mptcp: Add tests for userspace PM type Mat Martineau
@ 2022-04-29  1:57 ` Jakub Kicinski
  2022-04-29  3:39   ` Mat Martineau
  2022-04-30  1:00 ` patchwork-bot+netdevbpf
  7 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2022-04-29  1:57 UTC (permalink / raw)
  To: Mat Martineau; +Cc: netdev, davem, pabeni, matthieu.baerts, mptcp

On Wed, 27 Apr 2022 15:49:56 -0700 Mat Martineau wrote:
> MPTCP already has an in-kernel path manager (PM) to add and remove TCP
> subflows associated with a given MPTCP connection. This in-kernel PM has
> been designed to handle typical server-side use cases, but is not very
> flexible or configurable for client devices that may have more
> complicated policies to implement.
> 
> This patch series from the MPTCP tree is the first step toward adding a
> generic-netlink-based API for MPTCP path management, which a privileged
> userspace daemon will be able to use to control subflow
> establishment. These patches add a per-namespace sysctl to select the
> default PM type (in-kernel or userspace) for new MPTCP sockets. New
> self-tests confirm expected behavior when userspace PM is selected but
> there is no daemon available to handle existing MPTCP PM events.
> 
> Subsequent patch series (already staged in the MPTCP tree) will add the
> generic netlink path management API.

Could you link to those patches, maybe? Feels a little strange to add
this sysctl to switch to user space mode now, before we had a chance
to judg^W review the netlink interface.

Does the pm_type switch not fit more neatly into the netlink interface
itself?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 0/6] mptcp: Path manager mode selection
  2022-04-29  1:57 ` [PATCH net-next 0/6] mptcp: Path manager mode selection Jakub Kicinski
@ 2022-04-29  3:39   ` Mat Martineau
  2022-04-30  0:51     ` Jakub Kicinski
  0 siblings, 1 reply; 11+ messages in thread
From: Mat Martineau @ 2022-04-29  3:39 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, davem, pabeni, matthieu.baerts, mptcp


On Thu, 28 Apr 2022, Jakub Kicinski wrote:

> On Wed, 27 Apr 2022 15:49:56 -0700 Mat Martineau wrote:
>> MPTCP already has an in-kernel path manager (PM) to add and remove TCP
>> subflows associated with a given MPTCP connection. This in-kernel PM has
>> been designed to handle typical server-side use cases, but is not very
>> flexible or configurable for client devices that may have more
>> complicated policies to implement.
>>
>> This patch series from the MPTCP tree is the first step toward adding a
>> generic-netlink-based API for MPTCP path management, which a privileged
>> userspace daemon will be able to use to control subflow
>> establishment. These patches add a per-namespace sysctl to select the
>> default PM type (in-kernel or userspace) for new MPTCP sockets. New
>> self-tests confirm expected behavior when userspace PM is selected but
>> there is no daemon available to handle existing MPTCP PM events.
>>
>> Subsequent patch series (already staged in the MPTCP tree) will add the
>> generic netlink path management API.
>
> Could you link to those patches, maybe? Feels a little strange to add
> this sysctl to switch to user space mode now, before we had a chance
> to judg^W review the netlink interface.
>

Hi Jakub -

Sure, no problem. If you'd prefer a pull request for this feature as a 
whole I could stage that.

Here's a tag (note: do not merge this as-is, the committer ids and full 
history aren't suitable) -> 
https://github.com/multipath-tcp/mptcp_net-next/commits/netdev-review-userspace-path-manager

The last 26 commits there cover the full userspace path manager kernel 
code, with the first 6 of those being this series.

Userspace path managers makes use of generic netlink MPTCP events that 
have already been upstream for a while, and the full series adds four 
netlink commands for userspace:

* MPTCP_PM_CMD_ANNOUNCE: advertise an address that's available for 
additional subflow connections.

* MPTCP_PM_CMD_REMOVE: revoke an advertisement

* MPTCP_PM_CMD_SUBFLOW_CREATE: initiate a new subflow on an existing MPTCP 
connection

* MPTCP_PM_CMD_SUBFLOW_DESTROY: close a subflow on an existing MPTCP 
connection

There's one commit for each command, each with an obvious title ("mptcp: 
netlink: Add MPTCP_PM_CMD_<name>")


> Does the pm_type switch not fit more neatly into the netlink interface
> itself?

We (on the MPTCP ML) did discuss that as a design option, and landed on 
the sysctl.

The stack can handle having no userspace PM daemon present since MPTCP 
connections can still be initiated without the PM and operate in single 
subflow mode at first. When the daemon starts up later it can manage the 
existing sockets and start announcing addresses or adding subflows. We 
wanted to avoid accidentally ending up with a mix of kernel-PM-managed and 
userspace-PM-managed sockets depending on when the daemon loaded.

Userspace PM daemons could depend on carrier policy or other complex 
dependencies, so it made sense to allow setting the sysctl early and leave 
more flexibility for launching the daemon later.

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 0/6] mptcp: Path manager mode selection
  2022-04-29  3:39   ` Mat Martineau
@ 2022-04-30  0:51     ` Jakub Kicinski
  0 siblings, 0 replies; 11+ messages in thread
From: Jakub Kicinski @ 2022-04-30  0:51 UTC (permalink / raw)
  To: Mat Martineau; +Cc: netdev, davem, pabeni, matthieu.baerts, mptcp

On Thu, 28 Apr 2022 20:39:01 -0700 (PDT) Mat Martineau wrote:
> Sure, no problem. If you'd prefer a pull request for this feature as a 
> whole I could stage that.
> 
> Here's a tag (note: do not merge this as-is, the committer ids and full 
> history aren't suitable) -> 
> https://github.com/multipath-tcp/mptcp_net-next/commits/netdev-review-userspace-path-manager
> 
> The last 26 commits there cover the full userspace path manager kernel 
> code, with the first 6 of those being this series.
> 
> Userspace path managers makes use of generic netlink MPTCP events that 
> have already been upstream for a while, and the full series adds four 
> netlink commands for userspace:
> 
> * MPTCP_PM_CMD_ANNOUNCE: advertise an address that's available for 
> additional subflow connections.
> 
> * MPTCP_PM_CMD_REMOVE: revoke an advertisement
> 
> * MPTCP_PM_CMD_SUBFLOW_CREATE: initiate a new subflow on an existing MPTCP 
> connection
> 
> * MPTCP_PM_CMD_SUBFLOW_DESTROY: close a subflow on an existing MPTCP 
> connection
> 
> There's one commit for each command, each with an obvious title ("mptcp: 
> netlink: Add MPTCP_PM_CMD_<name>")

Thanks for the explanation, applied!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 0/6] mptcp: Path manager mode selection
  2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
                   ` (6 preceding siblings ...)
  2022-04-29  1:57 ` [PATCH net-next 0/6] mptcp: Path manager mode selection Jakub Kicinski
@ 2022-04-30  1:00 ` patchwork-bot+netdevbpf
  7 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-04-30  1:00 UTC (permalink / raw)
  To: Mat Martineau; +Cc: netdev, davem, kuba, pabeni, matthieu.baerts, mptcp

Hello:

This series was applied to netdev/net-next.git (master)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 27 Apr 2022 15:49:56 -0700 you wrote:
> MPTCP already has an in-kernel path manager (PM) to add and remove TCP
> subflows associated with a given MPTCP connection. This in-kernel PM has
> been designed to handle typical server-side use cases, but is not very
> flexible or configurable for client devices that may have more
> complicated policies to implement.
> 
> This patch series from the MPTCP tree is the first step toward adding a
> generic-netlink-based API for MPTCP path management, which a privileged
> userspace daemon will be able to use to control subflow
> establishment. These patches add a per-namespace sysctl to select the
> default PM type (in-kernel or userspace) for new MPTCP sockets. New
> self-tests confirm expected behavior when userspace PM is selected but
> there is no daemon available to handle existing MPTCP PM events.
> 
> [...]

Here is the summary with links:
  - [net-next,1/6] mptcp: Remove redundant assignments in path manager init
    https://git.kernel.org/netdev/net-next/c/9273b9d57995
  - [net-next,2/6] mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode
    https://git.kernel.org/netdev/net-next/c/d85a8fde71e2
  - [net-next,3/6] mptcp: Bypass kernel PM when userspace PM is enabled
    https://git.kernel.org/netdev/net-next/c/14b06811bec6
  - [net-next,4/6] mptcp: Make kernel path manager check for userspace-managed sockets
    https://git.kernel.org/netdev/net-next/c/6961326e38fe
  - [net-next,5/6] mptcp: Add a per-namespace sysctl to set the default path manager type
    https://git.kernel.org/netdev/net-next/c/6bb63ccc25d4
  - [net-next,6/6] selftests: mptcp: Add tests for userspace PM type
    https://git.kernel.org/netdev/net-next/c/5ac1d2d63451

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-04-30  1:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 22:49 [PATCH net-next 0/6] mptcp: Path manager mode selection Mat Martineau
2022-04-27 22:49 ` [PATCH net-next 1/6] mptcp: Remove redundant assignments in path manager init Mat Martineau
2022-04-27 22:49 ` [PATCH net-next 2/6] mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode Mat Martineau
2022-04-27 22:49 ` [PATCH net-next 3/6] mptcp: Bypass kernel PM when userspace PM is enabled Mat Martineau
2022-04-27 22:50 ` [PATCH net-next 4/6] mptcp: Make kernel path manager check for userspace-managed sockets Mat Martineau
2022-04-27 22:50 ` [PATCH net-next 5/6] mptcp: Add a per-namespace sysctl to set the default path manager type Mat Martineau
2022-04-27 22:50 ` [PATCH net-next 6/6] selftests: mptcp: Add tests for userspace PM type Mat Martineau
2022-04-29  1:57 ` [PATCH net-next 0/6] mptcp: Path manager mode selection Jakub Kicinski
2022-04-29  3:39   ` Mat Martineau
2022-04-30  0:51     ` Jakub Kicinski
2022-04-30  1:00 ` patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.