mptcp.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support
@ 2021-07-09 11:04 Geliang Tang
  2021-07-09 11:04 ` [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager Geliang Tang
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

Implement the in-kernel fullmesh path manager like on the mptcp.org
kernel.

Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/193

Geliang Tang (9):
  mptcp: add a new sysctl path_manager
  mptcp: add fullmesh path manager
  mptcp: add fullmesh worker
  mptcp: register ipv4 addr notifier
  mptcp: register ipv6 addr notifier
  mptcp: add netdev up event handler
  mptcp: add netdev down event handler
  mptcp: add proc file mptcp_fullmesh
  selftests: mptcp: add fullmesh testcases

 Documentation/networking/mptcp-sysctl.rst     |   8 +
 net/mptcp/Makefile                            |   2 +-
 net/mptcp/ctrl.c                              |  16 +
 net/mptcp/pm.c                                |   9 +-
 net/mptcp/pm_fullmesh.c                       | 463 ++++++++++++++++++
 net/mptcp/pm_netlink.c                        |  14 +-
 net/mptcp/protocol.c                          |  11 +-
 net/mptcp/protocol.h                          |  11 +
 .../testing/selftests/net/mptcp/mptcp_join.sh |  66 ++-
 9 files changed, 588 insertions(+), 12 deletions(-)
 create mode 100644 net/mptcp/pm_fullmesh.c

-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager
  2021-07-09 11:04 [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Geliang Tang
@ 2021-07-09 11:04 ` Geliang Tang
  2021-07-09 11:04   ` [MPTCP][PATCH mptcp-next 2/9] mptcp: add fullmesh path manager Geliang Tang
  2021-07-13  0:04 ` [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Mat Martineau
  2021-07-16 17:28 ` Paolo Abeni
  2 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added a new sysctl, named path_manager, to support for
selection of different Path-Managers.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 Documentation/networking/mptcp-sysctl.rst |  8 ++++++++
 net/mptcp/ctrl.c                          | 16 ++++++++++++++++
 net/mptcp/pm.c                            |  6 +++++-
 net/mptcp/protocol.c                      |  9 +++++++--
 net/mptcp/protocol.h                      |  1 +
 5 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
index 76d939e688b8..08e2a50bd8e3 100644
--- a/Documentation/networking/mptcp-sysctl.rst
+++ b/Documentation/networking/mptcp-sysctl.rst
@@ -45,3 +45,11 @@ allow_join_initial_addr_port - BOOLEAN
 	This is a per-namespace sysctl.
 
 	Default: 1
+
+path_manager - STRING
+	Select the Path-Manager of your choice.
+
+	Support for selection of different Path-Managers. This is a
+	per-namespace sysctl.
+
+	Default: "netlink"
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 7d738bd06f2c..8208d07c2d69 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -15,6 +15,8 @@
 
 #define MPTCP_SYSCTL_PATH "net/mptcp"
 
+#define MPTCP_PM_NAME_MAX	16
+
 static int mptcp_pernet_id;
 struct mptcp_pernet {
 #ifdef CONFIG_SYSCTL
@@ -25,6 +27,7 @@ struct mptcp_pernet {
 	unsigned int add_addr_timeout;
 	u8 checksum_enabled;
 	u8 allow_join_initial_addr_port;
+	char path_manager[MPTCP_PM_NAME_MAX];
 };
 
 static struct mptcp_pernet *mptcp_get_pernet(struct net *net)
@@ -52,12 +55,18 @@ int mptcp_allow_join_id0(struct net *net)
 	return mptcp_get_pernet(net)->allow_join_initial_addr_port;
 }
 
+char *mptcp_get_path_manager(struct net *net)
+{
+	return mptcp_get_pernet(net)->path_manager;
+}
+
 static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 {
 	pernet->mptcp_enabled = 1;
 	pernet->add_addr_timeout = TCP_RTO_MAX;
 	pernet->checksum_enabled = 0;
 	pernet->allow_join_initial_addr_port = 1;
+	strcpy(pernet->path_manager, "netlink");
 }
 
 #ifdef CONFIG_SYSCTL
@@ -95,6 +104,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
 		.extra1       = SYSCTL_ZERO,
 		.extra2       = SYSCTL_ONE
 	},
+	{
+		.procname	= "path_manager",
+		.maxlen		= MPTCP_PM_NAME_MAX,
+		.mode		= 0644,
+		.proc_handler	= proc_dostring,
+	},
 	{}
 };
 
@@ -114,6 +129,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
 	table[1].data = &pernet->add_addr_timeout;
 	table[2].data = &pernet->checksum_enabled;
 	table[3].data = &pernet->allow_join_initial_addr_port;
+	table[4].data = &pernet->path_manager;
 
 	hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
 	if (!hdr)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 639271e09604..aa003cf72b68 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -310,6 +310,9 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
 
 void mptcp_pm_data_init(struct mptcp_sock *msk)
 {
+	struct net *net = sock_net((struct sock *)msk);
+	char *pm = mptcp_get_path_manager(net);
+
 	msk->pm.add_addr_signaled = 0;
 	msk->pm.add_addr_accepted = 0;
 	msk->pm.local_addr_used = 0;
@@ -326,7 +329,8 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	spin_lock_init(&msk->pm.lock);
 	INIT_LIST_HEAD(&msk->pm.anno_list);
 
-	mptcp_pm_nl_data_init(msk);
+	if (!strcmp(pm, "netlink"))
+		mptcp_pm_nl_data_init(msk);
 }
 
 void __init mptcp_pm_init(void)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 7ae80c1d7f79..938690f87b8f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2325,7 +2325,9 @@ static void mptcp_worker(struct work_struct *work)
 {
 	struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
 	struct sock *sk = &msk->sk.icsk_inet.sk;
+	struct net *net = sock_net(sk);
 	int state;
+	char *pm;
 
 	lock_sock(sk);
 	state = sk->sk_state;
@@ -2337,8 +2339,11 @@ static void mptcp_worker(struct work_struct *work)
 
 	mptcp_check_fastclose(msk);
 
-	if (msk->pm.status)
-		mptcp_pm_nl_work(msk);
+	if (msk->pm.status) {
+		pm = mptcp_get_path_manager(net);
+		if (!strcmp(pm, "netlink"))
+			mptcp_pm_nl_work(msk);
+	}
 
 	if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
 		mptcp_check_for_eof(msk);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 0f0c026c5f8b..17f2a2894fe6 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -553,6 +553,7 @@ int mptcp_is_enabled(struct net *net);
 unsigned int mptcp_get_add_addr_timeout(struct net *net);
 int mptcp_is_checksum_enabled(struct net *net);
 int mptcp_allow_join_id0(struct net *net);
+char *mptcp_get_path_manager(struct net *net);
 void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
 				     struct mptcp_options_received *mp_opt);
 bool mptcp_subflow_data_available(struct sock *sk);
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 2/9] mptcp: add fullmesh path manager
  2021-07-09 11:04 ` [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager Geliang Tang
@ 2021-07-09 11:04   ` Geliang Tang
  2021-07-09 11:04     ` [MPTCP][PATCH mptcp-next 3/9] mptcp: add fullmesh worker Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added the in-kernel fullmesh path manager. Implemented two
new init functions, mptcp_pm_fm_init and mptcp_pm_fm_data_init, and two
new struct, mptcp_fm_addr_entry and pm_fm_pernet.

In mptcp_pm_fm_init, register a pernet operation mptcp_pm_fm_pernet_ops.

In mptcp_pm_fm_data_init, initialize the necessary fields of mptcp_pm_data.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/Makefile      |  2 +-
 net/mptcp/pm.c          |  3 ++
 net/mptcp/pm_fullmesh.c | 85 +++++++++++++++++++++++++++++++++++++++++
 net/mptcp/protocol.h    |  2 +
 4 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 net/mptcp/pm_fullmesh.c

diff --git a/net/mptcp/Makefile b/net/mptcp/Makefile
index 6dae6852ee3a..dc7347d6fa39 100644
--- a/net/mptcp/Makefile
+++ b/net/mptcp/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_MPTCP) += mptcp.o
 
 mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o \
-	   mib.o pm_netlink.o sockopt.o
+	   mib.o pm_netlink.o pm_fullmesh.o sockopt.o
 
 obj-$(CONFIG_SYN_COOKIES) += syncookies.o
 obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index aa003cf72b68..35039ceb8aec 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -331,9 +331,12 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 
 	if (!strcmp(pm, "netlink"))
 		mptcp_pm_nl_data_init(msk);
+	else if (!strcmp(pm, "fullmesh"))
+		mptcp_pm_fm_data_init(msk);
 }
 
 void __init mptcp_pm_init(void)
 {
 	mptcp_pm_nl_init();
+	mptcp_pm_fm_init();
 }
diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
new file mode 100644
index 000000000000..4cdcb572b125
--- /dev/null
+++ b/net/mptcp/pm_fullmesh.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "MPTCP: " fmt
+
+#include <linux/kernel.h>
+#include <net/tcp.h>
+#include <net/netns/generic.h>
+#include <net/mptcp.h>
+#include <uapi/linux/mptcp.h>
+
+#include "protocol.h"
+
+#define MPTCP_PM_FM_MAX_ADDR	8
+
+static int pm_fm_pernet_id;
+
+struct mptcp_fm_addr_entry {
+	struct list_head	list;
+	struct mptcp_addr_info	addr;
+};
+
+struct pm_fm_pernet {
+	/* protects pernet updates */
+	spinlock_t		lock;
+	struct list_head	local_addr_list;
+	unsigned int		next_id;
+};
+
+void mptcp_pm_fm_data_init(struct mptcp_sock *msk)
+{
+	struct mptcp_pm_data *pm = &msk->pm;
+
+	WRITE_ONCE(pm->work_pending, true);
+	WRITE_ONCE(pm->accept_addr, true);
+	WRITE_ONCE(pm->accept_subflow, MPTCP_PM_FM_MAX_ADDR);
+}
+
+static int __net_init pm_fm_init_net(struct net *net)
+{
+	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
+
+	spin_lock_init(&pernet->lock);
+	INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
+	pernet->next_id = 1;
+
+	return 0;
+}
+
+static void __flush_addrs(struct net *net, struct list_head *list)
+{
+	while (!list_empty(list)) {
+		struct mptcp_fm_addr_entry *cur;
+
+		cur = list_entry(list->next,
+				 struct mptcp_fm_addr_entry, list);
+		list_del_rcu(&cur->list);
+	}
+}
+
+static void __net_exit pm_fm_exit_net(struct list_head *net_list)
+{
+	struct net *net;
+
+	list_for_each_entry(net, net_list, exit_list) {
+		struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
+
+		__flush_addrs(net, &pernet->local_addr_list);
+	}
+}
+
+static struct pernet_operations mptcp_pm_fm_pernet_ops = {
+	.init		= pm_fm_init_net,
+	.exit_batch	= pm_fm_exit_net,
+	.id		= &pm_fm_pernet_id,
+	.size		= sizeof(struct pm_fm_pernet),
+};
+
+void __init mptcp_pm_fm_init(void)
+{
+	int ret;
+
+	ret = register_pernet_subsys(&mptcp_pm_fm_pernet_ops);
+	if (ret)
+		return;
+}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 17f2a2894fe6..3de2a298e8d9 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -793,6 +793,8 @@ unsigned int mptcp_pm_get_add_addr_signal_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk);
+void __init mptcp_pm_fm_init(void);
+void mptcp_pm_fm_data_init(struct mptcp_sock *msk);
 
 void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk);
 void mptcp_sockopt_sync_all(struct mptcp_sock *msk);
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 3/9] mptcp: add fullmesh worker
  2021-07-09 11:04   ` [MPTCP][PATCH mptcp-next 2/9] mptcp: add fullmesh path manager Geliang Tang
@ 2021-07-09 11:04     ` Geliang Tang
  2021-07-09 11:04       ` [MPTCP][PATCH mptcp-next 4/9] mptcp: register ipv4 addr notifier Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch implemented the fullmesh worker named mptcp_pm_fm_work. In
it, deal with the PM established status and invoke the function
mptcp_pm_fm_create_subflow to create the subflow.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 95 +++++++++++++++++++++++++++++++++++++++++
 net/mptcp/pm_netlink.c  |  8 ++--
 net/mptcp/protocol.c    |  2 +
 net/mptcp/protocol.h    |  5 +++
 4 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index 4cdcb572b125..b27f13a031e3 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -26,6 +26,101 @@ struct pm_fm_pernet {
 	unsigned int		next_id;
 };
 
+static struct mptcp_fm_addr_entry *
+select_local_address(const struct pm_fm_pernet *pernet,
+		     struct mptcp_sock *msk)
+{
+	struct mptcp_fm_addr_entry *entry, *ret = NULL;
+	struct sock *sk = (struct sock *)msk;
+
+	msk_owned_by_me(msk);
+
+	rcu_read_lock();
+	__mptcp_flush_join_list(msk);
+	list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
+		if (entry->addr.family != sk->sk_family)
+				continue;
+
+		if (!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
+			ret = entry;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+static void check_work_pending(struct mptcp_sock *msk)
+{
+	if (msk->pm.local_addr_used == MPTCP_PM_FM_MAX_ADDR ||
+	    msk->pm.subflows == MPTCP_PM_FM_MAX_ADDR)
+		WRITE_ONCE(msk->pm.work_pending, false);
+}
+
+static void mptcp_pm_fm_create_subflow(struct mptcp_sock *msk)
+{
+	unsigned int local_addr_max = MPTCP_PM_FM_MAX_ADDR;
+	unsigned int subflows_max = MPTCP_PM_FM_MAX_ADDR;
+	struct sock *sk = (struct sock *)msk;
+	struct mptcp_fm_addr_entry *local;
+	struct pm_fm_pernet *pernet;
+
+	pernet = net_generic(sock_net(sk), pm_fm_pernet_id);
+
+	if (msk->pm.local_addr_used < local_addr_max &&
+	    msk->pm.subflows < subflows_max &&
+	    !READ_ONCE(msk->pm.remote_deny_join_id0)) {
+		local = select_local_address(pernet, msk);
+		if (local) {
+			struct mptcp_addr_info remote = { 0 };
+
+			msk->pm.local_addr_used++;
+			msk->pm.subflows++;
+			check_work_pending(msk);
+			remote_address((struct sock_common *)sk, &remote);
+			spin_unlock_bh(&msk->pm.lock);
+			__mptcp_subflow_connect(sk, &local->addr, &remote, 0, 0);
+			spin_lock_bh(&msk->pm.lock);
+			return;
+		}
+
+		/* lookup failed, avoid fourther attempts later */
+		msk->pm.local_addr_used = local_addr_max;
+		check_work_pending(msk);
+	}
+}
+
+static void mptcp_pm_fm_fully_established(struct mptcp_sock *msk)
+{
+	mptcp_pm_fm_create_subflow(msk);
+}
+
+static void mptcp_pm_fm_subflow_established(struct mptcp_sock *msk)
+{
+	mptcp_pm_fm_create_subflow(msk);
+}
+
+void mptcp_pm_fm_work(struct mptcp_sock *msk)
+{
+	struct mptcp_pm_data *pm = &msk->pm;
+
+	msk_owned_by_me(msk);
+
+	spin_lock_bh(&msk->pm.lock);
+
+	pr_debug("msk=%p status=%x", msk, pm->status);
+	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
+		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
+		mptcp_pm_fm_fully_established(msk);
+	}
+	if (pm->status & BIT(MPTCP_PM_SUBFLOW_ESTABLISHED)) {
+		pm->status &= ~BIT(MPTCP_PM_SUBFLOW_ESTABLISHED);
+		mptcp_pm_fm_subflow_established(msk);
+	}
+
+	spin_unlock_bh(&msk->pm.lock);
+}
+
 void mptcp_pm_fm_data_init(struct mptcp_sock *msk)
 {
 	struct mptcp_pm_data *pm = &msk->pm;
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 56263c2c4014..d050dbd89e24 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -108,8 +108,8 @@ static void local_address(const struct sock_common *skc,
 #endif
 }
 
-static void remote_address(const struct sock_common *skc,
-			   struct mptcp_addr_info *addr)
+void remote_address(const struct sock_common *skc,
+		    struct mptcp_addr_info *addr)
 {
 	addr->family = skc->skc_family;
 	addr->port = skc->skc_dport;
@@ -121,8 +121,8 @@ static void remote_address(const struct sock_common *skc,
 #endif
 }
 
-static bool lookup_subflow_by_saddr(const struct list_head *list,
-				    struct mptcp_addr_info *saddr)
+bool lookup_subflow_by_saddr(const struct list_head *list,
+			     struct mptcp_addr_info *saddr)
 {
 	struct mptcp_subflow_context *subflow;
 	struct mptcp_addr_info cur;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 938690f87b8f..2af54eb5fe44 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2343,6 +2343,8 @@ static void mptcp_worker(struct work_struct *work)
 		pm = mptcp_get_path_manager(net);
 		if (!strcmp(pm, "netlink"))
 			mptcp_pm_nl_work(msk);
+		else if (!strcmp(pm, "fullmesh"))
+			mptcp_pm_fm_work(msk);
 	}
 
 	if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 3de2a298e8d9..99c23a1887d8 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -717,6 +717,10 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
 struct mptcp_pm_add_entry *
 mptcp_lookup_anno_list_by_saddr(struct mptcp_sock *msk,
 				struct mptcp_addr_info *addr);
+bool lookup_subflow_by_saddr(const struct list_head *list,
+			     struct mptcp_addr_info *saddr);
+void remote_address(const struct sock_common *skc,
+		    struct mptcp_addr_info *addr);
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
@@ -794,6 +798,7 @@ unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk);
 void __init mptcp_pm_fm_init(void);
+void mptcp_pm_fm_work(struct mptcp_sock *msk);
 void mptcp_pm_fm_data_init(struct mptcp_sock *msk);
 
 void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk);
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 4/9] mptcp: register ipv4 addr notifier
  2021-07-09 11:04     ` [MPTCP][PATCH mptcp-next 3/9] mptcp: add fullmesh worker Geliang Tang
@ 2021-07-09 11:04       ` Geliang Tang
  2021-07-09 11:04         ` [MPTCP][PATCH mptcp-next 5/9] mptcp: register ipv6 " Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch registered a ipv4 addr notifier, named mptcp_pm_addr4_notifier,
to deal with the events of net device UP, DOWN and CHANGE, and skip the
loopback device.

Save the ipv4 address, and pass it to the event handler.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 49 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index b27f13a031e3..7c2d2b23fac3 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -3,6 +3,7 @@
 #define pr_fmt(fmt) "MPTCP: " fmt
 
 #include <linux/kernel.h>
+#include <linux/inetdevice.h>
 #include <net/tcp.h>
 #include <net/netns/generic.h>
 #include <net/mptcp.h>
@@ -130,6 +131,45 @@ void mptcp_pm_fm_data_init(struct mptcp_sock *msk)
 	WRITE_ONCE(pm->accept_subflow, MPTCP_PM_FM_MAX_ADDR);
 }
 
+static int mptcp_fm_cmd_mod_addr(struct net *net, const struct mptcp_addr_info *addr)
+{
+	return 0;
+}
+
+static void addr_event_handler(unsigned long event, struct net *net,
+			       struct mptcp_addr_info *addr)
+{
+	if (event == NETDEV_CHANGE)
+		mptcp_fm_cmd_mod_addr(net, addr);
+}
+
+static int mptcp_pm_addr4_event(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	const struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+	struct net *net = dev_net(ifa->ifa_dev->dev);
+	struct mptcp_addr_info addr = { 0 };
+
+	if (!(event == NETDEV_UP || event == NETDEV_DOWN || event == NETDEV_CHANGE))
+		goto out;
+
+	if (ifa->ifa_scope > RT_SCOPE_LINK ||
+	    ipv4_is_loopback(ifa->ifa_local))
+		goto out;
+
+	addr.family = AF_INET;
+	addr.addr.s_addr = ifa->ifa_local;
+
+	addr_event_handler(event, net, &addr);
+
+out:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mptcp_pm_addr4_notifier = {
+	.notifier_call = mptcp_pm_addr4_event,
+};
+
 static int __net_init pm_fm_init_net(struct net *net)
 {
 	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
@@ -177,4 +217,13 @@ void __init mptcp_pm_fm_init(void)
 	ret = register_pernet_subsys(&mptcp_pm_fm_pernet_ops);
 	if (ret)
 		return;
+
+	ret = register_inetaddr_notifier(&mptcp_pm_addr4_notifier);
+	if (ret)
+		goto err_reg_inetaddr;
+
+	return;
+
+err_reg_inetaddr:
+	unregister_pernet_subsys(&mptcp_pm_fm_pernet_ops);
 }
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 5/9] mptcp: register ipv6 addr notifier
  2021-07-09 11:04       ` [MPTCP][PATCH mptcp-next 4/9] mptcp: register ipv4 addr notifier Geliang Tang
@ 2021-07-09 11:04         ` Geliang Tang
  2021-07-09 11:04           ` [MPTCP][PATCH mptcp-next 6/9] mptcp: add netdev up event handler Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch registered a ipv6 addr notifier, named mptcp_pm_addr6_notifier,
to deal with the events of net device UP, DOWN and CHANGE, and skip the
loopback device.

Save the ipv6 address, and pass it to the event handler.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index 7c2d2b23fac3..4b2eddc2b4e9 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/inetdevice.h>
 #include <net/tcp.h>
+#include <net/addrconf.h>
 #include <net/netns/generic.h>
 #include <net/mptcp.h>
 #include <uapi/linux/mptcp.h>
@@ -170,6 +171,40 @@ static struct notifier_block mptcp_pm_addr4_notifier = {
 	.notifier_call = mptcp_pm_addr4_event,
 };
 
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+
+static int mptcp_pm_addr6_event(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	const struct inet6_ifaddr *ifa6 = (struct inet6_ifaddr *)ptr;
+	struct net *net = dev_net(ifa6->idev->dev);
+	int addr_type = ipv6_addr_type(&ifa6->addr);
+	struct mptcp_addr_info addr = { 0 };
+
+	if (!(event == NETDEV_UP || event == NETDEV_DOWN || event == NETDEV_CHANGE))
+		goto out;
+
+	if (ifa6->scope > RT_SCOPE_LINK ||
+	    addr_type == IPV6_ADDR_ANY ||
+	    (addr_type & IPV6_ADDR_LOOPBACK) ||
+	    (addr_type & IPV6_ADDR_LINKLOCAL))
+		goto out;
+
+	addr.family = AF_INET6;
+	addr.addr6 = ifa6->addr;
+
+	addr_event_handler(event, net, &addr);
+
+out:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mptcp_pm_addr6_notifier = {
+	.notifier_call = mptcp_pm_addr6_event,
+};
+
+#endif
+
 static int __net_init pm_fm_init_net(struct net *net)
 {
 	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
@@ -222,8 +257,17 @@ void __init mptcp_pm_fm_init(void)
 	if (ret)
 		goto err_reg_inetaddr;
 
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+	ret = register_inet6addr_notifier(&mptcp_pm_addr6_notifier);
+	if (ret)
+		goto err_reg_inet6addr;
+#endif
 	return;
 
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+err_reg_inet6addr:
+	unregister_inetaddr_notifier(&mptcp_pm_addr4_notifier);
+#endif
 err_reg_inetaddr:
 	unregister_pernet_subsys(&mptcp_pm_fm_pernet_ops);
 }
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 6/9] mptcp: add netdev up event handler
  2021-07-09 11:04         ` [MPTCP][PATCH mptcp-next 5/9] mptcp: register ipv6 " Geliang Tang
@ 2021-07-09 11:04           ` Geliang Tang
  2021-07-09 11:04             ` [MPTCP][PATCH mptcp-next 7/9] mptcp: add netdev down " Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added the net device UP event handler function named
mptcp_fm_cmd_add_addr. In it, alloc an address entry, populate it, and
append this entry to the local address list.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 45 ++++++++++++++++++++++++++++++++++++++++-
 net/mptcp/pm_netlink.c  |  4 ++--
 net/mptcp/protocol.h    |  2 ++
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index 4b2eddc2b4e9..1ef268d34360 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -132,6 +132,47 @@ void mptcp_pm_fm_data_init(struct mptcp_sock *msk)
 	WRITE_ONCE(pm->accept_subflow, MPTCP_PM_FM_MAX_ADDR);
 }
 
+static int mptcp_pm_fm_append_new_local_addr(struct pm_fm_pernet *pernet,
+					     struct mptcp_fm_addr_entry *entry)
+{
+	struct mptcp_fm_addr_entry *cur;
+
+	spin_lock_bh(&pernet->lock);
+
+	if (pernet->next_id > 255)
+		goto out;
+
+	list_for_each_entry(cur, &pernet->local_addr_list, list) {
+		if (addresses_equal(&cur->addr, &entry->addr, false))
+			goto out;
+	}
+
+	list_add_tail_rcu(&entry->list, &pernet->local_addr_list);
+
+out:
+	spin_unlock_bh(&pernet->lock);
+
+	return 0;
+}
+
+static int mptcp_fm_cmd_add_addr(struct net *net, const struct mptcp_addr_info *addr)
+{
+	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
+	struct mptcp_fm_addr_entry *entry;
+
+	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->addr = *addr;
+	entry->addr.id = pernet->next_id++;
+	entry->addr.port = 0;
+
+	mptcp_pm_fm_append_new_local_addr(pernet, entry);
+
+	return 0;
+}
+
 static int mptcp_fm_cmd_mod_addr(struct net *net, const struct mptcp_addr_info *addr)
 {
 	return 0;
@@ -140,7 +181,9 @@ static int mptcp_fm_cmd_mod_addr(struct net *net, const struct mptcp_addr_info *
 static void addr_event_handler(unsigned long event, struct net *net,
 			       struct mptcp_addr_info *addr)
 {
-	if (event == NETDEV_CHANGE)
+	if (event == NETDEV_UP)
+		mptcp_fm_cmd_add_addr(net, addr);
+	else if (event == NETDEV_CHANGE)
 		mptcp_fm_cmd_mod_addr(net, addr);
 }
 
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index d050dbd89e24..debec16e9209 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -57,8 +57,8 @@ struct pm_nl_pernet {
 #define MPTCP_PM_ADDR_MAX	8
 #define ADD_ADDR_RETRANS_MAX	3
 
-static bool addresses_equal(const struct mptcp_addr_info *a,
-			    struct mptcp_addr_info *b, bool use_port)
+bool addresses_equal(const struct mptcp_addr_info *a,
+		     struct mptcp_addr_info *b, bool use_port)
 {
 	bool addr_equals = false;
 
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 99c23a1887d8..ea93bd1b4fde 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -717,6 +717,8 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
 struct mptcp_pm_add_entry *
 mptcp_lookup_anno_list_by_saddr(struct mptcp_sock *msk,
 				struct mptcp_addr_info *addr);
+bool addresses_equal(const struct mptcp_addr_info *a,
+		     struct mptcp_addr_info *b, bool use_port);
 bool lookup_subflow_by_saddr(const struct list_head *list,
 			     struct mptcp_addr_info *saddr);
 void remote_address(const struct sock_common *skc,
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 7/9] mptcp: add netdev down event handler
  2021-07-09 11:04           ` [MPTCP][PATCH mptcp-next 6/9] mptcp: add netdev up event handler Geliang Tang
@ 2021-07-09 11:04             ` Geliang Tang
  2021-07-09 11:04               ` [MPTCP][PATCH mptcp-next 8/9] mptcp: add proc file mptcp_fullmesh Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added the net device DOWN event handler function named
mptcp_fm_cmd_del_addr. In it, traverse the local address list to find
the deleting address entry, pass this entry to mptcp_pm_free_addr_entry,
then start the rcu_work to remove the subflow and signal the RM_ADDR
suboption.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 105 ++++++++++++++++++++++++++++++++++++++++
 net/mptcp/pm_netlink.c  |   2 +-
 net/mptcp/protocol.h    |   1 +
 3 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index 1ef268d34360..a48287ff4cc0 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -102,6 +102,17 @@ static void mptcp_pm_fm_subflow_established(struct mptcp_sock *msk)
 	mptcp_pm_fm_create_subflow(msk);
 }
 
+static void mptcp_pm_fm_rm_addr_received(struct mptcp_sock *msk)
+{
+	mptcp_pm_nl_rm_addr_received(msk);
+}
+
+static void mptcp_pm_fm_rm_subflow_received(struct mptcp_sock *msk,
+					    const struct mptcp_rm_list *rm_list)
+{
+	mptcp_pm_nl_rm_subflow_received(msk, rm_list);
+}
+
 void mptcp_pm_fm_work(struct mptcp_sock *msk)
 {
 	struct mptcp_pm_data *pm = &msk->pm;
@@ -111,6 +122,10 @@ void mptcp_pm_fm_work(struct mptcp_sock *msk)
 	spin_lock_bh(&msk->pm.lock);
 
 	pr_debug("msk=%p status=%x", msk, pm->status);
+	if (pm->status & BIT(MPTCP_PM_RM_ADDR_RECEIVED)) {
+		pm->status &= ~BIT(MPTCP_PM_RM_ADDR_RECEIVED);
+		mptcp_pm_fm_rm_addr_received(msk);
+	}
 	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
 		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
 		mptcp_pm_fm_fully_established(msk);
@@ -173,6 +188,93 @@ static int mptcp_fm_cmd_add_addr(struct net *net, const struct mptcp_addr_info *
 	return 0;
 }
 
+static int mptcp_fm_remove_subflow_and_signal_addr(struct net *net, struct mptcp_addr_info *addr)
+{
+	struct mptcp_rm_list list = { .nr = 0 };
+	long s_slot = 0, s_num = 0;
+	struct mptcp_sock *msk;
+
+	list.ids[list.nr++] = addr->id;
+
+	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
+		struct sock *sk = (struct sock *)msk;
+		bool remove_subflow;
+
+		if (list_empty(&msk->conn_list))
+			goto next;
+
+		lock_sock(sk);
+		remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
+		if (remove_subflow) {
+			spin_lock_bh(&msk->pm.lock);
+			mptcp_pm_remove_addr(msk, &list);
+			mptcp_pm_fm_rm_subflow_received(msk, &list);
+			spin_unlock_bh(&msk->pm.lock);
+		}
+		release_sock(sk);
+
+next:
+		sock_put(sk);
+		cond_resched();
+	}
+	return 0;
+}
+
+struct addr_entry_release_work {
+	struct rcu_work rwork;
+	struct net *net;
+	struct mptcp_fm_addr_entry *entry;
+};
+
+static void mptcp_pm_release_addr_entry(struct work_struct *work)
+{
+	struct addr_entry_release_work *w;
+	struct mptcp_fm_addr_entry *entry;
+	struct net *net;
+
+	w = container_of(to_rcu_work(work), struct addr_entry_release_work, rwork);
+	net = w->net;
+	entry = w->entry;
+	if (entry) {
+		mptcp_fm_remove_subflow_and_signal_addr(net, &entry->addr);
+		kfree(entry);
+	}
+	kfree(w);
+}
+
+static void mptcp_pm_free_addr_entry(struct net *net, struct mptcp_fm_addr_entry *entry)
+{
+	struct addr_entry_release_work *w;
+
+	w = kmalloc(sizeof(*w), GFP_ATOMIC);
+	if (w) {
+		INIT_RCU_WORK(&w->rwork, mptcp_pm_release_addr_entry);
+		w->net = net;
+		w->entry = entry;
+		queue_rcu_work(system_wq, &w->rwork);
+	}
+}
+
+static int mptcp_fm_cmd_del_addr(struct net *net, struct mptcp_addr_info *addr)
+{
+	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
+	struct mptcp_fm_addr_entry *entry, *tmp;
+
+	spin_lock_bh(&pernet->lock);
+	list_for_each_entry_safe(entry, tmp, &pernet->local_addr_list, list) {
+		if (addresses_equal(&entry->addr, addr, false)) {
+			list_del_rcu(&entry->list);
+			spin_unlock_bh(&pernet->lock);
+			mptcp_pm_free_addr_entry(net, entry);
+
+			return 0;
+		}
+	}
+	spin_unlock_bh(&pernet->lock);
+
+	return 0;
+}
+
 static int mptcp_fm_cmd_mod_addr(struct net *net, const struct mptcp_addr_info *addr)
 {
 	return 0;
@@ -183,6 +285,8 @@ static void addr_event_handler(unsigned long event, struct net *net,
 {
 	if (event == NETDEV_UP)
 		mptcp_fm_cmd_add_addr(net, addr);
+	else if (event == NETDEV_DOWN)
+		mptcp_fm_cmd_del_addr(net, addr);
 	else if (event == NETDEV_CHANGE)
 		mptcp_fm_cmd_mod_addr(net, addr);
 }
@@ -267,6 +371,7 @@ static void __flush_addrs(struct net *net, struct list_head *list)
 		cur = list_entry(list->next,
 				 struct mptcp_fm_addr_entry, list);
 		list_del_rcu(&cur->list);
+		mptcp_pm_free_addr_entry(net, cur);
 	}
 }
 
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index debec16e9209..dea4dc4ad36e 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -642,7 +642,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
 	}
 }
 
-static void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
+void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
 {
 	mptcp_pm_nl_rm_addr_or_subflow(msk, &msk->pm.rm_list_rx, MPTCP_MIB_RMADDR);
 }
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index ea93bd1b4fde..fabadfd10af3 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -792,6 +792,7 @@ 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_addr_received(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
 				     const struct mptcp_rm_list *rm_list);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 8/9] mptcp: add proc file mptcp_fullmesh
  2021-07-09 11:04             ` [MPTCP][PATCH mptcp-next 7/9] mptcp: add netdev down " Geliang Tang
@ 2021-07-09 11:04               ` Geliang Tang
  2021-07-09 11:04                 ` [MPTCP][PATCH mptcp-next 9/9] selftests: mptcp: add fullmesh testcases Geliang Tang
  0 siblings, 1 reply; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added a proc file /proc/net/mptcp_fullmesh to show all the
addresses on the local address list.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 net/mptcp/pm_fullmesh.c | 42 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/net/mptcp/pm_fullmesh.c b/net/mptcp/pm_fullmesh.c
index a48287ff4cc0..290ca06e565f 100644
--- a/net/mptcp/pm_fullmesh.c
+++ b/net/mptcp/pm_fullmesh.c
@@ -4,6 +4,9 @@
 
 #include <linux/kernel.h>
 #include <linux/inetdevice.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
 #include <net/tcp.h>
 #include <net/addrconf.h>
 #include <net/netns/generic.h>
@@ -352,10 +355,46 @@ static struct notifier_block mptcp_pm_addr6_notifier = {
 
 #endif
 
+#ifdef CONFIG_PROC_FS
+
+/* Output /proc/net/mptcp_fullmesh */
+static int mptcp_fm_seq_show(struct seq_file *seq, void *v)
+{
+	const struct net *net = seq->private;
+	struct mptcp_fm_addr_entry *cur;
+	struct pm_fm_pernet *pernet;
+
+	pernet = net_generic(net, pm_fm_pernet_id);
+
+	seq_puts(seq, "ID, Family, Address\n");
+
+	spin_lock_bh(&pernet->lock);
+
+	list_for_each_entry(cur, &pernet->local_addr_list, list) {
+		seq_printf(seq, "%u, %u, ", cur->addr.id, cur->addr.family);
+		if (cur->addr.family == AF_INET)
+			seq_printf(seq, "%pI4\n", &cur->addr.addr);
+		else if (cur->addr.family == AF_INET6)
+			seq_printf(seq, "%pI6\n", &cur->addr.addr6);
+	}
+
+	spin_unlock_bh(&pernet->lock);
+
+	return 0;
+}
+
+#endif
+
 static int __net_init pm_fm_init_net(struct net *net)
 {
 	struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
 
+#ifdef CONFIG_PROC_FS
+	if (!proc_create_net_single("mptcp_fullmesh", 0444, net->proc_net,
+				    mptcp_fm_seq_show, NULL))
+		return -1;
+#endif
+
 	spin_lock_init(&pernet->lock);
 	INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
 	pernet->next_id = 1;
@@ -383,6 +422,9 @@ static void __net_exit pm_fm_exit_net(struct list_head *net_list)
 		struct pm_fm_pernet *pernet = net_generic(net, pm_fm_pernet_id);
 
 		__flush_addrs(net, &pernet->local_addr_list);
+#ifdef CONFIG_PROC_FS
+		remove_proc_entry("mptcp_fullmesh", net->proc_net);
+#endif
 	}
 }
 
-- 
2.31.1


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

* [MPTCP][PATCH mptcp-next 9/9] selftests: mptcp: add fullmesh testcases
  2021-07-09 11:04               ` [MPTCP][PATCH mptcp-next 8/9] mptcp: add proc file mptcp_fullmesh Geliang Tang
@ 2021-07-09 11:04                 ` Geliang Tang
  0 siblings, 0 replies; 12+ messages in thread
From: Geliang Tang @ 2021-07-09 11:04 UTC (permalink / raw)
  To: mptcp; +Cc: Geliang Tang

This patch added the net device UP and DOWN testcases for the fullmesh
path manager.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
---
 .../testing/selftests/net/mptcp/mptcp_join.sh | 66 ++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index f02f4de2f3a0..7e3fd0d94343 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -150,6 +150,14 @@ reset_with_allow_join_id0()
 	ip netns exec $ns2 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns2_enable
 }
 
+reset_fullmesh()
+{
+	reset
+
+	ip netns exec $ns1 sysctl -q net.mptcp.path_manager="fullmesh"
+	ip netns exec $ns2 sysctl -q net.mptcp.path_manager="fullmesh"
+}
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
 	echo "SKIP: Could not run test without ip tool"
@@ -342,6 +350,15 @@ do_transfer()
 		elif [ $rm_nr_ns1 -eq 9 ]; then
 			sleep 1
 			ip netns exec ${listener_ns} ./pm_nl_ctl del 0 ${connect_addr}
+		elif [ $rm_nr_ns1 -eq 10 ]; then
+			local addr
+			if is_v6 "${connect_addr}"; then
+				addr="dead:beef:3::1/64"
+			else
+				addr="10.0.3.1/24"
+			fi
+			sleep 2
+			ip -net "${listener_ns}" addr del $addr dev ns1eth3
 		fi
 	fi
 
@@ -390,6 +407,15 @@ do_transfer()
 			fi
 			sleep 1
 			ip netns exec ${connector_ns} ./pm_nl_ctl del 0 $addr
+		elif [ $rm_nr_ns2 -eq 10 ]; then
+			local addr
+			if is_v6 "${connect_addr}"; then
+				addr="dead:beef:3::2/64"
+			else
+				addr="10.0.3.2/24"
+			fi
+			sleep 2
+			ip -net "${connector_ns}" addr del $addr dev ns2eth3
 		fi
 	fi
 
@@ -1530,6 +1556,39 @@ deny_join_id0_tests()
 	chk_join_nr "subflow and address allow join id0 2" 1 1 1
 }
 
+fullmesh_tests()
+{
+	# fullmesh add
+	reset_fullmesh
+	ip netns exec $ns1 ./pm_nl_ctl limits 8 8
+	ip netns exec $ns2 ./pm_nl_ctl limits 8 8
+	run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+	chk_join_nr "fullmesh add" 3 3 3
+
+	# fullmesh add IPv6
+	reset_fullmesh
+	ip netns exec $ns1 ./pm_nl_ctl limits 8 8
+	ip netns exec $ns2 ./pm_nl_ctl limits 8 8
+	run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
+	chk_join_nr "fullmesh add IPv6" 3 3 3
+
+	# fullmesh del
+	reset_fullmesh
+	ip netns exec $ns1 ./pm_nl_ctl limits 8 8
+	ip netns exec $ns2 ./pm_nl_ctl limits 8 8
+	run_tests $ns1 $ns2 10.0.1.1 0 0 -10 slow
+	chk_join_nr "fullmesh del" 3 3 3
+	chk_rm_nr 1 1
+
+	# fullmesh del IPv6
+	reset_fullmesh
+	ip netns exec $ns1 ./pm_nl_ctl limits 8 8
+	ip netns exec $ns2 ./pm_nl_ctl limits 8 8
+	run_tests $ns1 $ns2 dead:beef:1::1 0 0 -10 slow
+	chk_join_nr "fullmesh del IPv6" 3 3 3
+	chk_rm_nr 1 1
+}
+
 all_tests()
 {
 	subflows_tests
@@ -1545,6 +1604,7 @@ all_tests()
 	syncookies_tests
 	checksum_tests
 	deny_join_id0_tests
+	fullmesh_tests
 }
 
 usage()
@@ -1563,6 +1623,7 @@ usage()
 	echo "  -k syncookies_tests"
 	echo "  -S checksum_tests"
 	echo "  -d deny_join_id0_tests"
+	echo "  -m fullmesh_tests"
 	echo "  -c capture pcap files"
 	echo "  -C enable data checksum"
 	echo "  -h help"
@@ -1598,7 +1659,7 @@ if [ $do_all_tests -eq 1 ]; then
 	exit $ret
 fi
 
-while getopts 'fsltra64bpkdchCS' opt; do
+while getopts 'fsltra64bpkdmchCS' opt; do
 	case $opt in
 		f)
 			subflows_tests
@@ -1639,6 +1700,9 @@ while getopts 'fsltra64bpkdchCS' opt; do
 		d)
 			deny_join_id0_tests
 			;;
+		m)
+			fullmesh_tests
+			;;
 		c)
 			;;
 		C)
-- 
2.31.1


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

* Re: [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support
  2021-07-09 11:04 [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Geliang Tang
  2021-07-09 11:04 ` [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager Geliang Tang
@ 2021-07-13  0:04 ` Mat Martineau
  2021-07-16 17:28 ` Paolo Abeni
  2 siblings, 0 replies; 12+ messages in thread
From: Mat Martineau @ 2021-07-13  0:04 UTC (permalink / raw)
  To: Geliang Tang; +Cc: mptcp

On Fri, 9 Jul 2021, Geliang Tang wrote:

> Implement the in-kernel fullmesh path manager like on the mptcp.org
> kernel.
>
> Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/193
>
> Geliang Tang (9):
>  mptcp: add a new sysctl path_manager
>  mptcp: add fullmesh path manager
>  mptcp: add fullmesh worker
>  mptcp: register ipv4 addr notifier
>  mptcp: register ipv6 addr notifier
>  mptcp: add netdev up event handler
>  mptcp: add netdev down event handler
>  mptcp: add proc file mptcp_fullmesh
>  selftests: mptcp: add fullmesh testcases
>
> Documentation/networking/mptcp-sysctl.rst     |   8 +
> net/mptcp/Makefile                            |   2 +-
> net/mptcp/ctrl.c                              |  16 +
> net/mptcp/pm.c                                |   9 +-
> net/mptcp/pm_fullmesh.c                       | 463 ++++++++++++++++++
> net/mptcp/pm_netlink.c                        |  14 +-
> net/mptcp/protocol.c                          |  11 +-
> net/mptcp/protocol.h                          |  11 +
> .../testing/selftests/net/mptcp/mptcp_join.sh |  66 ++-
> 9 files changed, 588 insertions(+), 12 deletions(-)
> create mode 100644 net/mptcp/pm_fullmesh.c
>
> -- 
> 2.31.1

Hi Geliang -

This patch set brings up a lot of questions - many of which it would have 
been good to address by having some design discussions before starting to 
write the code. But the patches are here, so let's discuss!


An early design goal of the upstream Linux MPTCP implementation 
(https://github.com/multipath-tcp/mptcp_net-next/wiki/%5Barchived%5D-Initial-Design) 
was to simplify the kernel side of MPTCP by moving functionality to 
userspace where possible - especially the path manager.

The current in-kernel path manager was designed for two main purposes: to 
handle path management on busy servers where kernel/userspace 
communication could become a bottleneck, and to provide basic path 
management capability until userspace path managers were ready (like 
mptcpd). Userspace path managers would then be the "playground" for 
various path management algorithms.

The multpath-tcp.org kernel has a variety of in-kernel path managers. 
These are typically built as kernel modules, so unused path managers can 
be excluded or built as modules and stay unloaded until they are needed. 
The fullmesh PM as implemented in this patchset is always compiled and 
using code space when CONFIG_MPTCP is enabled, and is always getting 
address notifications and updating per-namespace address lists even if the 
fullmesh pm isn't used.

Right now, I would ask you to wait before making more changes to this 
patch set so the MPTCP upstream community can discuss and decide what the 
proper direction is for path management.


Here are some path-manager-related topics I think the MPTCP upstream 
community should discuss before moving ahead:

* What's the long-term plan for in-kernel vs. userspace PM? Commit to one 
in-kernel PM, plus userspace? Or are there use cases for more in-kernel 
path managers?

* How do those plans affect iproute2?

* What are our limits or expectations for in-kernel PM complexity and 
resource usage?

* How do we structure path management to make sense to users? It could get 
confusing to try to explain the difference between an "in-kernel fullmesh 
PM" vs. "userspace fullmesh PM".

* What are the most important path managers and PM-related development 
tasks to prioritize?


I think this would be a good topic for a Thursday meeting, or we could 
schedule something at a different time.


Thanks,

--
Mat Martineau
Intel

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

* Re: [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support
  2021-07-09 11:04 [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Geliang Tang
  2021-07-09 11:04 ` [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager Geliang Tang
  2021-07-13  0:04 ` [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Mat Martineau
@ 2021-07-16 17:28 ` Paolo Abeni
  2 siblings, 0 replies; 12+ messages in thread
From: Paolo Abeni @ 2021-07-16 17:28 UTC (permalink / raw)
  To: Geliang Tang, mptcp

On Fri, 2021-07-09 at 19:04 +0800, Geliang Tang wrote:
> Implement the in-kernel fullmesh path manager like on the mptcp.org
> kernel.
> 
> Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/193

Following-up the yday disucssion in the public mtg, I skimmed over this
series.

I think this approach leads to quite a bit of duplicate code and
avoidable complexity.

I also think we could obtain a full-mash topology with some not to-
complex extension to the current NL PM:

- add and manage a new per endpoint flag, something alike 'fullmesh'
- in mptcp_pm_create_subflow_or_signal_addr(), if such flag is set,
  instead of:

	remote_address((struct sock_common *)sk, &remote);

  fill a temporary allocated array of all known remote address.
  After releaseing the pm lock loop on such array and create a subflow 
  for each remote address from the given local.
  Note that the we could still use an array even for non 'fullmash' 
  endpoint: with a single entry corresponding to the primary MPC
  subflow remote address.
- mptcp_pm_nl_add_addr_received(), fill a temporary allocate array of 
  all local address corresponding to fullmash endpoint. If such array 
  is empty, keep the current behavior.
  Elsewhere loop on such array and create a subflow for each local 
  address towards the given remote address

I hope that overall the above would require a limited amount of
changes. If so, I believe this way to be preferrable:
- 1 in kernel path manager
- a simple one
- a single configuration interface
- should cover the full-mesh use case and possibly more
- the idea is - some far day - use ebpf for more funcy stuff, if
needed.

WDYT?

Thanks!

Paolo


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

end of thread, other threads:[~2021-07-16 17:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-09 11:04 [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Geliang Tang
2021-07-09 11:04 ` [MPTCP][PATCH mptcp-next 1/9] mptcp: add a new sysctl path_manager Geliang Tang
2021-07-09 11:04   ` [MPTCP][PATCH mptcp-next 2/9] mptcp: add fullmesh path manager Geliang Tang
2021-07-09 11:04     ` [MPTCP][PATCH mptcp-next 3/9] mptcp: add fullmesh worker Geliang Tang
2021-07-09 11:04       ` [MPTCP][PATCH mptcp-next 4/9] mptcp: register ipv4 addr notifier Geliang Tang
2021-07-09 11:04         ` [MPTCP][PATCH mptcp-next 5/9] mptcp: register ipv6 " Geliang Tang
2021-07-09 11:04           ` [MPTCP][PATCH mptcp-next 6/9] mptcp: add netdev up event handler Geliang Tang
2021-07-09 11:04             ` [MPTCP][PATCH mptcp-next 7/9] mptcp: add netdev down " Geliang Tang
2021-07-09 11:04               ` [MPTCP][PATCH mptcp-next 8/9] mptcp: add proc file mptcp_fullmesh Geliang Tang
2021-07-09 11:04                 ` [MPTCP][PATCH mptcp-next 9/9] selftests: mptcp: add fullmesh testcases Geliang Tang
2021-07-13  0:04 ` [MPTCP][PATCH mptcp-next 0/9] fullmesh path manager support Mat Martineau
2021-07-16 17:28 ` Paolo Abeni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).