Skip to contentSkip to conversation

mptcp: RM_ADDR/ADD_ADDR enhancements

PATCH In review Geliang Tang 4 participants 31 messages Sep 24, 2020 – Sep 25, 2020

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover mptcp: RM_ADDR/ADD_ADDR enhancements

This series include two enhancements for the MPTCP path management, namely RM_ADDR support and ADD_ADDR echo support, as specified by RFC sections 3.4.1 and 3.4.2.

1 RM_ADDR support include 9 patches (1-3 and 8-13):

Patch 1 is the helper for patch 2, these two patches add the RM_ADDR outgoing functions, which are derived from ADD_ADDR's corresponding functions.

Patch 3 adds the RM_ADDR incoming logic, when RM_ADDR suboption is received, close the subflow matching the rm_id, and update PM counter.

Patch 8 is the main remove routine. When the PM netlink removes an address, we traverse all the existing msk sockets to find the relevant sockets. Then trigger the RM_ADDR signal and remove the subflow which using this local address, this subflow removing functions has been implemented in patch 9.

Finally, patches 10-13 are the self-tests for RM_ADDR.

2 ADD_ADDR echo support include 7 patches (4-7 and 14-16).

Patch 4 adds the ADD_ADDR echo logic, when the ADD_ADDR suboption has been received, send out the same ADD_ADDR suboption with echo-flag, and no HMAC included.

Patches 5 and 6 are the self-tests for ADD_ADDR echo. Patch 7 is a little cleaning up.

Patch 14 and 15 are the helpers for patch 16. These three patches add the ADD_ADDR retransmition when no ADD_ADDR echo is received.

Geliang Tang (16):
mptcp: rename addr_signal and the related functions
mptcp: add the outgoing RM_ADDR support
mptcp: add the incoming RM_ADDR support
mptcp: send out ADD_ADDR with echo flag
mptcp: add ADD_ADDR related mibs
selftests: mptcp: add ADD_ADDR mibs check function
mptcp: add accept_subflow re-check
mptcp: remove addr and subflow in PM netlink
mptcp: implement mptcp_pm_remove_subflow
mptcp: add RM_ADDR related mibs
mptcp: add mptcp_destroy_common helper
selftests: mptcp: add remove cfg in mptcp_connect
selftests: mptcp: add remove addr and subflow test cases
mptcp: add struct mptcp_pm_add_entry
mptcp: add sk_stop_timer_sync helper
mptcp: retransmit ADD_ADDR when timeout

 include/net/sock.h                            |   2 +
 net/core/sock.c                               |   7 +
 net/mptcp/mib.c                               |   4 +
 net/mptcp/mib.h                               |   4 +
 net/mptcp/options.c                           |  81 +++--
 net/mptcp/pm.c                                |  91 ++++--
 net/mptcp/pm_netlink.c                        | 276 +++++++++++++++++-
 net/mptcp/protocol.c                          |  30 +-
 net/mptcp/protocol.h                          |  39 ++-
 net/mptcp/subflow.c                           |   3 +-
 .../selftests/net/mptcp/mptcp_connect.c       |  18 +-
 .../testing/selftests/net/mptcp/mptcp_join.sh | 189 +++++++++++-
 12 files changed, 674 insertions(+), 70 deletions(-)
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/16 mptcp: rename addr_signal and the related functions

This patch renamed addr_signal and the related functions with the explicit word "add".

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/options.c  | 14 +++++++-------
 net/mptcp/pm.c       | 12 ++++++------
 net/mptcp/protocol.h | 10 +++++-----
 3 files changed, 18 insertions(+), 18 deletions(-)
net/mptcp/options.c +7 -7
index 7fa822b55c34..ee0cb0546324 100644
@@ -571,18 +571,18 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
 }
 #endif
 
-static bool mptcp_established_options_addr(struct sock *sk,
-					   unsigned int *size,
-					   unsigned int remaining,
-					   struct mptcp_out_options *opts)
+static bool mptcp_established_options_add_addr(struct sock *sk,
+					       unsigned int *size,
+					       unsigned int remaining,
+					       struct mptcp_out_options *opts)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 	struct mptcp_addr_info saddr;
 	int len;
 
-	if (!mptcp_pm_should_signal(msk) ||
-	    !(mptcp_pm_addr_signal(msk, remaining, &saddr)))
+	if (!mptcp_pm_should_add_signal(msk) ||
+	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr)))
 		return false;
 
 	len = mptcp_add_addr_len(saddr.family);
@@ -640,7 +640,7 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
 
 	*size += opt_size;
 	remaining -= opt_size;
-	if (mptcp_established_options_addr(sk, &opt_size, remaining, opts)) {
+	if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
 		*size += opt_size;
 		remaining -= opt_size;
 		ret = true;
net/mptcp/pm.c +6 -6
index a8ad20559aaa..ce12b8b26ad2 100644
@@ -18,7 +18,7 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 	pr_debug("msk=%p, local_id=%d", msk, addr->id);
 
 	msk->pm.local = *addr;
-	WRITE_ONCE(msk->pm.addr_signal, true);
+	WRITE_ONCE(msk->pm.add_addr_signal, true);
 	return 0;
 }
 
@@ -151,22 +151,22 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 
 /* path manager helpers */
 
-bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
-			  struct mptcp_addr_info *saddr)
+bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+			      struct mptcp_addr_info *saddr)
 {
 	int ret = false;
 
 	spin_lock_bh(&msk->pm.lock);
 
 	/* double check after the lock is acquired */
-	if (!mptcp_pm_should_signal(msk))
+	if (!mptcp_pm_should_add_signal(msk))
 		goto out_unlock;
 
 	if (remaining < mptcp_add_addr_len(msk->pm.local.family))
 		goto out_unlock;
 
 	*saddr = msk->pm.local;
-	WRITE_ONCE(msk->pm.addr_signal, false);
+	WRITE_ONCE(msk->pm.add_addr_signal, false);
 	ret = true;
 
 out_unlock:
@@ -186,7 +186,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	msk->pm.local_addr_used = 0;
 	msk->pm.subflows = 0;
 	WRITE_ONCE(msk->pm.work_pending, false);
-	WRITE_ONCE(msk->pm.addr_signal, false);
+	WRITE_ONCE(msk->pm.add_addr_signal, false);
 	WRITE_ONCE(msk->pm.accept_addr, false);
 	WRITE_ONCE(msk->pm.accept_subflow, false);
 	msk->pm.status = 0;
net/mptcp/protocol.h +5 -5
index 493bd2c13bc6..91adc9a19757 100644
@@ -162,7 +162,7 @@ struct mptcp_pm_data {
 
 	spinlock_t	lock;		/*protects the whole PM data */
 
-	bool		addr_signal;
+	bool		add_addr_signal;
 	bool		server_side;
 	bool		work_pending;
 	bool		accept_addr;
@@ -438,9 +438,9 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
 int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
 
-static inline bool mptcp_pm_should_signal(struct mptcp_sock *msk)
+static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
 {
-	return READ_ONCE(msk->pm.addr_signal);
+	return READ_ONCE(msk->pm.add_addr_signal);
 }
 
 static inline unsigned int mptcp_add_addr_len(int family)
@@ -450,8 +450,8 @@ static inline unsigned int mptcp_add_addr_len(int family)
 	return TCPOLEN_MPTCP_ADD_ADDR6;
 }
 
-bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
-			  struct mptcp_addr_info *saddr);
+bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+			      struct mptcp_addr_info *saddr);
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 void __init mptcp_pm_nl_init(void);
Signature · 1 line
2.17.1
Reviewed-by on v1 1/16
#2 lore raw

Re: [MPTCP][PATCH net-next 01/16] mptcp: rename addr_signal and the related functions

Quoted 11 lines · Geliang Tang

This patch renamed addr_signal and the related functions with the explicit word "add".

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---

net/mptcp/options.c  | 14 +++++++-------
net/mptcp/pm.c       | 12 ++++++------
net/mptcp/protocol.h | 10 +++++-----
3 files changed, 18 insertions(+), 18 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#3 lore raw

PATCH 2/16 mptcp: add the outgoing RM_ADDR support

In reply to Geliang Tang

This patch added a new signal named rm_addr_signal in PM. On outgoing path, we called mptcp_pm_should_rm_signal to check if rm_addr_signal has been set. If it has been, we sent out the RM_ADDR option.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/options.c  | 29 +++++++++++++++++++++++++++++
 net/mptcp/pm.c       | 25 +++++++++++++++++++++++++
 net/mptcp/protocol.h |  9 +++++++++
 3 files changed, 63 insertions(+)
net/mptcp/options.c +29 -0
index ee0cb0546324..bbc124876417 100644
@@ -614,6 +614,31 @@ static bool mptcp_established_options_add_addr(struct sock *sk,
 	return true;
 }
 
+static bool mptcp_established_options_rm_addr(struct sock *sk,
+					      unsigned int *size,
+					      unsigned int remaining,
+					      struct mptcp_out_options *opts)
+{
+	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+	u8 rm_id;
+
+	if (!mptcp_pm_should_rm_signal(msk) ||
+	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
+		return false;
+
+	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
+		return false;
+
+	*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
+	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
+	opts->rm_id = rm_id;
+
+	pr_debug("rm_id=%d", opts->rm_id);
+
+	return true;
+}
+
 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
 			       unsigned int *size, unsigned int remaining,
 			       struct mptcp_out_options *opts)
@@ -644,6 +669,10 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
 		*size += opt_size;
 		remaining -= opt_size;
 		ret = true;
+	} else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
+		*size += opt_size;
+		remaining -= opt_size;
+		ret = true;
 	}
 
 	return ret;
net/mptcp/pm.c +25 -0
index ce12b8b26ad2..81b07ae213b9 100644
@@ -174,6 +174,29 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 	return ret;
 }
 
+bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+			     u8 *rm_id)
+{
+	int ret = false;
+
+	spin_lock_bh(&msk->pm.lock);
+
+	/* double check after the lock is acquired */
+	if (!mptcp_pm_should_rm_signal(msk))
+		goto out_unlock;
+
+	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
+		goto out_unlock;
+
+	*rm_id = msk->pm.rm_id;
+	WRITE_ONCE(msk->pm.rm_addr_signal, false);
+	ret = true;
+
+out_unlock:
+	spin_unlock_bh(&msk->pm.lock);
+	return ret;
+}
+
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
 {
 	return mptcp_pm_nl_get_local_id(msk, skc);
@@ -185,8 +208,10 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	msk->pm.add_addr_accepted = 0;
 	msk->pm.local_addr_used = 0;
 	msk->pm.subflows = 0;
+	msk->pm.rm_id = 0;
 	WRITE_ONCE(msk->pm.work_pending, false);
 	WRITE_ONCE(msk->pm.add_addr_signal, false);
+	WRITE_ONCE(msk->pm.rm_addr_signal, false);
 	WRITE_ONCE(msk->pm.accept_addr, false);
 	WRITE_ONCE(msk->pm.accept_subflow, false);
 	msk->pm.status = 0;
net/mptcp/protocol.h +9 -0
index 91adc9a19757..8929b0c7660a 100644
@@ -163,6 +163,7 @@ struct mptcp_pm_data {
 	spinlock_t	lock;		/*protects the whole PM data */
 
 	bool		add_addr_signal;
+	bool		rm_addr_signal;
 	bool		server_side;
 	bool		work_pending;
 	bool		accept_addr;
@@ -176,6 +177,7 @@ struct mptcp_pm_data {
 	u8		local_addr_max;
 	u8		subflows_max;
 	u8		status;
+	u8		rm_id;
 };
 
 struct mptcp_data_frag {
@@ -443,6 +445,11 @@ static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
 	return READ_ONCE(msk->pm.add_addr_signal);
 }
 
+static inline bool mptcp_pm_should_rm_signal(struct mptcp_sock *msk)
+{
+	return READ_ONCE(msk->pm.rm_addr_signal);
+}
+
 static inline unsigned int mptcp_add_addr_len(int family)
 {
 	if (family == AF_INET)
@@ -452,6 +459,8 @@ static inline unsigned int mptcp_add_addr_len(int family)
 
 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 			      struct mptcp_addr_info *saddr);
+bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+			     u8 *rm_id);
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 void __init mptcp_pm_nl_init(void);
Signature · 1 line
2.17.1
Reviewed-by on v1 2/16
#4 lore raw

Re: [MPTCP][PATCH net-next 02/16] mptcp: add the outgoing RM_ADDR support

Quoted 4 lines · Geliang Tang

This patch added a new signal named rm_addr_signal in PM. On outgoing path, we called mptcp_pm_should_rm_signal to check if rm_addr_signal has been set. If it has been, we sent out the RM_ADDR option.

Quoted 8 lines
Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---

net/mptcp/options.c  | 29 +++++++++++++++++++++++++++++
net/mptcp/pm.c       | 25 +++++++++++++++++++++++++
net/mptcp/protocol.h |  9 +++++++++
3 files changed, 63 insertions(+)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#5 lore raw

PATCH 3/16 mptcp: add the incoming RM_ADDR support

In reply to Geliang Tang

This patch added the RM_ADDR option parsing logic:

We parsed the incoming options to find if the rm_addr option is received, and called mptcp_pm_rm_addr_received to schedule PM work to a new status, named MPTCP_PM_RM_ADDR_RECEIVED.

PM work got this status, and called mptcp_pm_nl_rm_addr_received to handle it.

In mptcp_pm_nl_rm_addr_received, we closed the subflow matching the rm_id, and updated PM counter.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/options.c    |  5 +++++
 net/mptcp/pm.c         | 12 ++++++++++++
 net/mptcp/pm_netlink.c | 34 ++++++++++++++++++++++++++++++++++
 net/mptcp/protocol.c   | 12 ++++++++----
 net/mptcp/protocol.h   |  7 +++++++
 5 files changed, 66 insertions(+), 4 deletions(-)
net/mptcp/options.c +5 -0
index bbc124876417..a52a05effac9 100644
@@ -888,6 +888,11 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 		mp_opt.add_addr = 0;
 	}
 
+	if (mp_opt.rm_addr) {
+		mptcp_pm_rm_addr_received(msk, mp_opt.rm_id);
+		mp_opt.rm_addr = 0;
+	}
+
 	if (!mp_opt.dss)
 		return;
 
net/mptcp/pm.c +12 -0
index 81b07ae213b9..558462d87eb3 100644
@@ -149,6 +149,18 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 	spin_unlock_bh(&pm->lock);
 }
 
+void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
+{
+	struct mptcp_pm_data *pm = &msk->pm;
+
+	pr_debug("msk=%p remote_id=%d", msk, rm_id);
+
+	spin_lock_bh(&pm->lock);
+	mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
+	pm->rm_id = rm_id;
+	spin_unlock_bh(&pm->lock);
+}
+
 /* path manager helpers */
 
 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
net/mptcp/pm_netlink.c +34 -0
index b4a9624d7bf2..4124bc581308 100644
@@ -268,6 +268,40 @@ void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
 	spin_lock_bh(&msk->pm.lock);
 }
 
+void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
+{
+	struct mptcp_subflow_context *subflow, *tmp;
+	struct sock *sk = (struct sock *)msk;
+
+	pr_debug("address rm_id %d", msk->pm.rm_id);
+
+	if (!msk->pm.rm_id)
+		return;
+
+	if (list_empty(&msk->conn_list))
+		return;
+
+	list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
+		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+		int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
+		long timeout = 0;
+
+		if (msk->pm.rm_id != subflow->remote_id)
+			continue;
+
+		spin_unlock_bh(&msk->pm.lock);
+		mptcp_subflow_shutdown(sk, ssk, how);
+		__mptcp_close_ssk(sk, ssk, subflow, timeout);
+		spin_lock_bh(&msk->pm.lock);
+
+		msk->pm.add_addr_accepted--;
+		msk->pm.subflows--;
+		WRITE_ONCE(msk->pm.accept_addr, true);
+
+		break;
+	}
+}
+
 static bool address_use_port(struct mptcp_pm_addr_entry *entry)
 {
 	return (entry->addr.flags &
net/mptcp/protocol.c +8 -4
index 386cd4e60250..26b9233f247c 100644
@@ -1652,9 +1652,9 @@ static struct sock *mptcp_subflow_get_retrans(const struct mptcp_sock *msk)
  * so we need to use tcp_close() after detaching them from the mptcp
  * parent socket.
  */
-static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
-			      struct mptcp_subflow_context *subflow,
-			      long timeout)
+void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+		       struct mptcp_subflow_context *subflow,
+		       long timeout)
 {
 	struct socket *sock = READ_ONCE(ssk->sk_socket);
 
@@ -1685,6 +1685,10 @@ static void pm_work(struct mptcp_sock *msk)
 		pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_RECEIVED);
 		mptcp_pm_nl_add_addr_received(msk);
 	}
+	if (pm->status & BIT(MPTCP_PM_RM_ADDR_RECEIVED)) {
+		pm->status &= ~BIT(MPTCP_PM_RM_ADDR_RECEIVED);
+		mptcp_pm_nl_rm_addr_received(msk);
+	}
 	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
 		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
 		mptcp_pm_nl_fully_established(msk);
@@ -1846,7 +1850,7 @@ static void mptcp_cancel_work(struct sock *sk)
 		sock_put(sk);
 }
 
-static void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
+void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
 {
 	lock_sock(ssk);
 
net/mptcp/protocol.h +7 -0
index 8929b0c7660a..837e01057544 100644
@@ -152,6 +152,7 @@ struct mptcp_addr_info {
 
 enum mptcp_pm_status {
 	MPTCP_PM_ADD_ADDR_RECEIVED,
+	MPTCP_PM_RM_ADDR_RECEIVED,
 	MPTCP_PM_ESTABLISHED,
 	MPTCP_PM_SUBFLOW_ESTABLISHED,
 };
@@ -362,6 +363,10 @@ void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
 				     struct mptcp_options_received *mp_opt);
 bool mptcp_subflow_data_available(struct sock *sk);
 void __init mptcp_subflow_init(void);
+void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how);
+void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+		       struct mptcp_subflow_context *subflow,
+		       long timeout);
 
 /* called with sk socket lock held */
 int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
@@ -434,6 +439,7 @@ void mptcp_pm_subflow_established(struct mptcp_sock *msk,
 void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
 void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 				const struct mptcp_addr_info *addr);
+void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr);
@@ -468,6 +474,7 @@ void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
 void mptcp_pm_nl_fully_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk);
+void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
Signature · 1 line
2.17.1
Reviewed-by on v1 3/16
#6 lore raw

Re: [MPTCP][PATCH net-next 03/16] mptcp: add the incoming RM_ADDR support

Quoted 16 lines · Geliang Tang

This patch added the RM_ADDR option parsing logic:

We parsed the incoming options to find if the rm_addr option is received, and called mptcp_pm_rm_addr_received to schedule PM work to a new status, named MPTCP_PM_RM_ADDR_RECEIVED.

PM work got this status, and called mptcp_pm_nl_rm_addr_received to handle it.

In mptcp_pm_nl_rm_addr_received, we closed the subflow matching the rm_id, and updated PM counter.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
Quoted 7 lines

---

net/mptcp/options.c    |  5 +++++
net/mptcp/pm.c         | 12 ++++++++++++
net/mptcp/pm_netlink.c | 34 ++++++++++++++++++++++++++++++++++
net/mptcp/protocol.c   | 12 ++++++++----
net/mptcp/protocol.h   |  7 +++++++
5 files changed, 66 insertions(+), 4 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#7 lore raw

PATCH 4/16 mptcp: send out ADD_ADDR with echo flag

In reply to Geliang Tang

When the ADD_ADDR suboption has been received, we need to send out the same ADD_ADDR suboption with echo-flag=1, and no HMAC.

Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/options.c    | 27 ++++++++++++++++-----------
 net/mptcp/pm.c         | 18 +++++++++---------
 net/mptcp/pm_netlink.c |  4 +++-
 net/mptcp/protocol.h   |  6 ++++--
 4 files changed, 32 insertions(+), 23 deletions(-)
net/mptcp/options.c +16 -11
index a52a05effac9..a41996e6c6d7 100644
@@ -242,7 +242,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
 		mp_opt->add_addr = 1;
 		mp_opt->port = 0;
 		mp_opt->addr_id = *ptr++;
-		pr_debug("ADD_ADDR: id=%d", mp_opt->addr_id);
+		pr_debug("ADD_ADDR: id=%d, echo=%d", mp_opt->addr_id, mp_opt->echo);
 		if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) {
 			memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4);
 			ptr += 4;
@@ -579,10 +579,11 @@ static bool mptcp_established_options_add_addr(struct sock *sk,
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 	struct mptcp_addr_info saddr;
+	bool echo;
 	int len;
 
 	if (!mptcp_pm_should_add_signal(msk) ||
-	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr)))
+	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo)))
 		return false;
 
 	len = mptcp_add_addr_len(saddr.family);
@@ -594,22 +595,26 @@ static bool mptcp_established_options_add_addr(struct sock *sk,
 	if (saddr.family == AF_INET) {
 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
 		opts->addr = saddr.addr;
-		opts->ahmac = add_addr_generate_hmac(msk->local_key,
-						     msk->remote_key,
-						     opts->addr_id,
-						     &opts->addr);
+		if (!echo) {
+			opts->ahmac = add_addr_generate_hmac(msk->local_key,
+							     msk->remote_key,
+							     opts->addr_id,
+							     &opts->addr);
+		}
 	}
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
 	else if (saddr.family == AF_INET6) {
 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR6;
 		opts->addr6 = saddr.addr6;
-		opts->ahmac = add_addr6_generate_hmac(msk->local_key,
-						      msk->remote_key,
-						      opts->addr_id,
-						      &opts->addr6);
+		if (!echo) {
+			opts->ahmac = add_addr6_generate_hmac(msk->local_key,
+							      msk->remote_key,
+							      opts->addr_id,
+							      &opts->addr6);
+		}
 	}
 #endif
-	pr_debug("addr_id=%d, ahmac=%llu", opts->addr_id, opts->ahmac);
+	pr_debug("addr_id=%d, ahmac=%llu, echo=%d", opts->addr_id, opts->ahmac, echo);
 
 	return true;
 }
net/mptcp/pm.c +9 -9
index 558462d87eb3..39a76620d0a5 100644
@@ -13,11 +13,13 @@
 /* path manager command handlers */
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
-			   const struct mptcp_addr_info *addr)
+			   const struct mptcp_addr_info *addr,
+			   bool echo)
 {
 	pr_debug("msk=%p, local_id=%d", msk, addr->id);
 
 	msk->pm.local = *addr;
+	WRITE_ONCE(msk->pm.add_addr_echo, echo);
 	WRITE_ONCE(msk->pm.add_addr_signal, true);
 	return 0;
 }
@@ -135,15 +137,11 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 	pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
 		 READ_ONCE(pm->accept_addr));
 
-	/* avoid acquiring the lock if there is no room for fouther addresses */
-	if (!READ_ONCE(pm->accept_addr))
-		return;
-
 	spin_lock_bh(&pm->lock);
 
-	/* be sure there is something to signal re-checking under PM lock */
-	if (READ_ONCE(pm->accept_addr) &&
-	    mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED))
+	if (!READ_ONCE(pm->accept_addr))
+		mptcp_pm_announce_addr(msk, addr, true);
+	else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED))
 		pm->remote = *addr;
 
 	spin_unlock_bh(&pm->lock);
@@ -164,7 +162,7 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
 /* path manager helpers */
 
 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
-			      struct mptcp_addr_info *saddr)
+			      struct mptcp_addr_info *saddr, bool *echo)
 {
 	int ret = false;
 
@@ -178,6 +176,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 		goto out_unlock;
 
 	*saddr = msk->pm.local;
+	*echo = READ_ONCE(msk->pm.add_addr_echo);
 	WRITE_ONCE(msk->pm.add_addr_signal, false);
 	ret = true;
 
@@ -226,6 +225,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	WRITE_ONCE(msk->pm.rm_addr_signal, false);
 	WRITE_ONCE(msk->pm.accept_addr, false);
 	WRITE_ONCE(msk->pm.accept_subflow, false);
+	WRITE_ONCE(msk->pm.add_addr_echo, false);
 	msk->pm.status = 0;
 
 	spin_lock_init(&msk->pm.lock);
net/mptcp/pm_netlink.c +3 -1
index 4124bc581308..f6f96bc2046b 100644
@@ -198,7 +198,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
 
 		if (local) {
 			msk->pm.add_addr_signaled++;
-			mptcp_pm_announce_addr(msk, &local->addr);
+			mptcp_pm_announce_addr(msk, &local->addr, false);
 		} else {
 			/* pick failed, avoid fourther attempts later */
 			msk->pm.local_addr_used = msk->pm.add_addr_signal_max;
@@ -266,6 +266,8 @@ void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
 	spin_unlock_bh(&msk->pm.lock);
 	__mptcp_subflow_connect((struct sock *)msk, &local, &remote);
 	spin_lock_bh(&msk->pm.lock);
+
+	mptcp_pm_announce_addr(msk, &remote, true);
 }
 
 void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
net/mptcp/protocol.h +4 -2
index 837e01057544..ba253a6947b0 100644
@@ -169,6 +169,7 @@ struct mptcp_pm_data {
 	bool		work_pending;
 	bool		accept_addr;
 	bool		accept_subflow;
+	bool		add_addr_echo;
 	u8		add_addr_signaled;
 	u8		add_addr_accepted;
 	u8		local_addr_used;
@@ -442,7 +443,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
-			   const struct mptcp_addr_info *addr);
+			   const struct mptcp_addr_info *addr,
+			   bool echo);
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
 int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
 
@@ -464,7 +466,7 @@ static inline unsigned int mptcp_add_addr_len(int family)
 }
 
 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
-			      struct mptcp_addr_info *saddr);
+			      struct mptcp_addr_info *saddr, bool *echo);
 bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 			     u8 *rm_id);
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
Signature · 1 line
2.17.1
#8 lore raw

PATCH 5/16 mptcp: add ADD_ADDR related mibs

In reply to Geliang Tang

This patch added two mibs for ADD_ADDR, MPTCP_MIB_ADDADDR for receiving of the ADD_ADDR suboption with echo-flag=0, and MPTCP_MIB_ECHOADD for receiving the ADD_ADDR suboption with echo-flag=1.

Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Co-developed-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/mib.c     | 2 ++
 net/mptcp/mib.h     | 2 ++
 net/mptcp/options.c | 7 ++++++-
 3 files changed, 10 insertions(+), 1 deletion(-)
net/mptcp/mib.c +2 -0
index 056986c7a228..a33bf719ce6f 100644
@@ -27,6 +27,8 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("OFOMerge", MPTCP_MIB_OFOMERGE),
 	SNMP_MIB_ITEM("NoDSSInWindow", MPTCP_MIB_NODSSWINDOW),
 	SNMP_MIB_ITEM("DuplicateData", MPTCP_MIB_DUPDATA),
+	SNMP_MIB_ITEM("AddAddr", MPTCP_MIB_ADDADDR),
+	SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD),
 	SNMP_MIB_SENTINEL
 };
 
net/mptcp/mib.h +2 -0
index 937a177729f1..cdeea3732ddf 100644
@@ -20,6 +20,8 @@ enum linux_mptcp_mib_field {
 	MPTCP_MIB_OFOMERGE,		/* Segments merged in OoO queue */
 	MPTCP_MIB_NODSSWINDOW,		/* Segments not in MPTCP windows */
 	MPTCP_MIB_DUPDATA,		/* Segments discarded due to duplicate DSS */
+	MPTCP_MIB_ADDADDR,		/* Received ADD_ADDR with echo-flag=0 */
+	MPTCP_MIB_ECHOADD,		/* Received ADD_ADDR with echo-flag=1 */
 	__MPTCP_MIB_MAX
 };
 
net/mptcp/options.c +6 -1
index a41996e6c6d7..171039cbe9c4 100644
@@ -11,6 +11,7 @@
 #include <net/tcp.h>
 #include <net/mptcp.h>
 #include "protocol.h"
+#include "mib.h"
 
 static bool mptcp_cap_flag_sha256(u8 flags)
 {
@@ -888,8 +889,12 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 			addr.addr6 = mp_opt.addr6;
 		}
 #endif
-		if (!mp_opt.echo)
+		if (!mp_opt.echo) {
 			mptcp_pm_add_addr_received(msk, &addr);
+			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
+		} else {
+			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
+		}
 		mp_opt.add_addr = 0;
 	}
 
Signature · 1 line
2.17.1
#9 lore raw

PATCH 6/16 selftests: mptcp: add ADD_ADDR mibs check function

In reply to Geliang Tang

This patch added the ADD_ADDR related mibs counter check function chk_add_nr(). This function check both ADD_ADDR and ADD_ADDR with echo flag.

The output looks like this:

07 unused signal address syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
08 signal address syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
09 subflow and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
10 multiple subflows and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
11 remove subflow and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]

Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 .../testing/selftests/net/mptcp/mptcp_join.sh | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)
tools/testing/selftests/net/mptcp/mptcp_join.sh +44 -0
index c2943e4dfcfe..9d64abdde146 100755
@@ -276,6 +276,43 @@ chk_join_nr()
 	fi
 }
 
+chk_add_nr()
+{
+	local add_nr=$1
+	local echo_nr=$2
+	local count
+	local dump_stats
+
+	printf "%-39s %s" " " "add"
+	count=`ip netns exec $ns2 nstat -as | grep MPTcpExtAddAddr | awk '{print $2}'`
+	[ -z "$count" ] && count=0
+	if [ "$count" != "$add_nr" ]; then
+		echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
+		ret=1
+		dump_stats=1
+	else
+		echo -n "[ ok ]"
+	fi
+
+	echo -n " - echo  "
+	count=`ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}'`
+	[ -z "$count" ] && count=0
+	if [ "$count" != "$echo_nr" ]; then
+		echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
+		ret=1
+		dump_stats=1
+	else
+		echo "[ ok ]"
+	fi
+
+	if [ "${dump_stats}" = 1 ]; then
+		echo Server ns stats
+		ip netns exec $ns1 nstat -as | grep MPTcp
+		echo Client ns stats
+		ip netns exec $ns2 nstat -as | grep MPTcp
+	fi
+}
+
 sin=$(mktemp)
 sout=$(mktemp)
 cin=$(mktemp)
@@ -332,6 +369,7 @@ reset
 ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "unused signal address" 0 0 0
+chk_add_nr 1 1
 
 # accept and use add_addr
 reset
@@ -340,6 +378,7 @@ ip netns exec $ns2 ./pm_nl_ctl limits 1 1
 ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "signal address" 1 1 1
+chk_add_nr 1 1
 
 # accept and use add_addr with an additional subflow
 # note: signal address in server ns and local addresses in client ns must
@@ -352,6 +391,7 @@ ip netns exec $ns2 ./pm_nl_ctl limits 1 2
 ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "subflow and signal" 2 2 2
+chk_add_nr 1 1
 
 # accept and use add_addr with additional subflows
 reset
@@ -362,6 +402,7 @@ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
 ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "multiple subflows and signal" 3 3 3
+chk_add_nr 1 1
 
 # single subflow, syncookies
 reset_with_cookies
@@ -396,6 +437,7 @@ ip netns exec $ns2 ./pm_nl_ctl limits 1 1
 ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "signal address with syn cookies" 1 1 1
+chk_add_nr 1 1
 
 # test cookie with subflow and signal
 reset_with_cookies
@@ -405,6 +447,7 @@ ip netns exec $ns2 ./pm_nl_ctl limits 1 2
 ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "subflow and signal w cookies" 2 2 2
+chk_add_nr 1 1
 
 # accept and use add_addr with additional subflows
 reset_with_cookies
@@ -415,5 +458,6 @@ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
 ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
 run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "subflows and signal w. cookies" 3 3 3
+chk_add_nr 1 1
 
 exit $ret
Signature · 1 line
2.17.1
#10 lore raw

PATCH 7/16 mptcp: add accept_subflow re-check

In reply to Geliang Tang

The re-check of pm->accept_subflow with pm->lock held was missing, this patch fixed it.

Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/pm.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
net/mptcp/pm.c +6 -4
index 39a76620d0a5..be4157279e15 100644
@@ -48,7 +48,7 @@ void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side)
 bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
 {
 	struct mptcp_pm_data *pm = &msk->pm;
-	int ret;
+	int ret = 0;
 
 	pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
 		 pm->subflows_max, READ_ONCE(pm->accept_subflow));
@@ -58,9 +58,11 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
 		return false;
 
 	spin_lock_bh(&pm->lock);
-	ret = pm->subflows < pm->subflows_max;
-	if (ret && ++pm->subflows == pm->subflows_max)
-		WRITE_ONCE(pm->accept_subflow, false);
+	if (READ_ONCE(pm->accept_subflow)) {
+		ret = pm->subflows < pm->subflows_max;
+		if (ret && ++pm->subflows == pm->subflows_max)
+			WRITE_ONCE(pm->accept_subflow, false);
+	}
 	spin_unlock_bh(&pm->lock);
 
 	return ret;
Signature · 1 line
2.17.1
#11 lore raw

PATCH 8/16 mptcp: remove addr and subflow in PM netlink

In reply to Geliang Tang

This patch implements the remove announced addr and subflow logic in PM netlink.

When the PM netlink removes an address, we traverse all the existing msk sockets to find the relevant sockets.

We add a new list named anno_list in mptcp_pm_data, to record all the announced addrs. In the traversing, we check if it has been recorded. If it has been, we trigger the RM_ADDR signal.

We also check if this address is in conn_list. If it is, we remove the subflow which using this local address.

Since we call mptcp_pm_free_anno_list in mptcp_destroy, we need to move __mptcp_init_sock before the mptcp_is_enabled check in mptcp_init_sock.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/pm.c         |   7 ++-
 net/mptcp/pm_netlink.c | 122 +++++++++++++++++++++++++++++++++++++++--
 net/mptcp/protocol.c   |   9 +--
 net/mptcp/protocol.h   |   2 +
 net/mptcp/subflow.c    |   1 +
 5 files changed, 130 insertions(+), 11 deletions(-)
net/mptcp/pm.c +6 -1
index be4157279e15..f450bf0d49aa 100644
@@ -26,7 +26,11 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
 {
-	return -ENOTSUPP;
+	pr_debug("msk=%p, local_id=%d", msk, local_id);
+
+	msk->pm.rm_id = local_id;
+	WRITE_ONCE(msk->pm.rm_addr_signal, true);
+	return 0;
 }
 
 int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
@@ -231,6 +235,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	msk->pm.status = 0;
 
 	spin_lock_init(&msk->pm.lock);
+	INIT_LIST_HEAD(&msk->pm.anno_list);
 
 	mptcp_pm_nl_data_init(msk);
 }
net/mptcp/pm_netlink.c +116 -6

153 lines not on this page · raw message

net/mptcp/protocol.c +5 -4
index 26b9233f247c..b53e55826975 100644
@@ -1810,16 +1810,16 @@ static int mptcp_init_sock(struct sock *sk)
 	struct net *net = sock_net(sk);
 	int ret;
 
+	ret = __mptcp_init_sock(sk);
+	if (ret)
+		return ret;
+
 	if (!mptcp_is_enabled(net))
 		return -ENOPROTOOPT;
 
 	if (unlikely(!net->mib.mptcp_statistics) && !mptcp_mib_alloc(net))
 		return -ENOMEM;
 
-	ret = __mptcp_init_sock(sk);
-	if (ret)
-		return ret;
-
 	ret = __mptcp_socket_create(mptcp_sk(sk));
 	if (ret)
 		return ret;
@@ -2137,6 +2137,7 @@ static void mptcp_destroy(struct sock *sk)
 	if (msk->cached_ext)
 		__skb_ext_put(msk->cached_ext);
 
+	mptcp_pm_free_anno_list(msk);
 	sk_sockets_allocated_dec(sk);
 }
 
net/mptcp/protocol.h +2 -0
index ba253a6947b0..d1b1416797f8 100644
@@ -160,6 +160,7 @@ enum mptcp_pm_status {
 struct mptcp_pm_data {
 	struct mptcp_addr_info local;
 	struct mptcp_addr_info remote;
+	struct list_head anno_list;
 
 	spinlock_t	lock;		/*protects the whole PM data */
 
@@ -441,6 +442,7 @@ void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
 void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 				const struct mptcp_addr_info *addr);
 void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
+void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
net/mptcp/subflow.c +1 -0
index 141d555b7bd2..a1fefc965e17 100644
@@ -437,6 +437,7 @@ static void mptcp_sock_destruct(struct sock *sk)
 
 	skb_rbtree_purge(&mptcp_sk(sk)->out_of_order_queue);
 	mptcp_token_destroy(mptcp_sk(sk));
+	mptcp_pm_free_anno_list(mptcp_sk(sk));
 	inet_sock_destruct(sk);
 }
 
Signature · 1 line
2.17.1
Reviewed-by on v1 8/16
#12 lore raw

Re: [MPTCP][PATCH net-next 08/16] mptcp: remove addr and subflow in PM netlink

Quoted 21 lines · Geliang Tang

This patch implements the remove announced addr and subflow logic in PM netlink.

When the PM netlink removes an address, we traverse all the existing msk sockets to find the relevant sockets.

We add a new list named anno_list in mptcp_pm_data, to record all the announced addrs. In the traversing, we check if it has been recorded. If it has been, we trigger the RM_ADDR signal.

We also check if this address is in conn_list. If it is, we remove the subflow which using this local address.

Since we call mptcp_pm_free_anno_list in mptcp_destroy, we need to move __mptcp_init_sock before the mptcp_is_enabled check in mptcp_init_sock.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
Quoted 7 lines

---

net/mptcp/pm.c         |   7 ++-
net/mptcp/pm_netlink.c | 122 +++++++++++++++++++++++++++++++++++++++--
net/mptcp/protocol.c   |   9 +--
net/mptcp/protocol.h   |   2 +
net/mptcp/subflow.c    |   1 +
5 files changed, 130 insertions(+), 11 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#13 lore raw

PATCH 9/16 mptcp: implement mptcp_pm_remove_subflow

In reply to Geliang Tang

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

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

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

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/pm.c         |  9 +++++++--
 net/mptcp/pm_netlink.c | 33 +++++++++++++++++++++++++++++++++
 net/mptcp/protocol.h   |  3 ++-
 3 files changed, 42 insertions(+), 3 deletions(-)
net/mptcp/pm.c +7 -2
index f450bf0d49aa..7e81f53d1e5d 100644
@@ -33,9 +33,14 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
 	return 0;
 }
 
-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
+int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id)
 {
-	return -ENOTSUPP;
+	pr_debug("msk=%p, local_id=%d", msk, local_id);
+
+	spin_lock_bh(&msk->pm.lock);
+	mptcp_pm_nl_rm_subflow_received(msk, local_id);
+	spin_unlock_bh(&msk->pm.lock);
+	return 0;
 }
 
 /* path manager event handlers */
net/mptcp/pm_netlink.c +33 -0
index 97f9280f83fb..9064c8098521 100644
@@ -350,6 +350,39 @@ void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
 	}
 }
 
+void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id)
+{
+	struct mptcp_subflow_context *subflow, *tmp;
+	struct sock *sk = (struct sock *)msk;
+
+	pr_debug("subflow rm_id %d", rm_id);
+
+	if (!rm_id)
+		return;
+
+	if (list_empty(&msk->conn_list))
+		return;
+
+	list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
+		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+		int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
+		long timeout = 0;
+
+		if (rm_id != subflow->local_id)
+			continue;
+
+		spin_unlock_bh(&msk->pm.lock);
+		mptcp_subflow_shutdown(sk, ssk, how);
+		__mptcp_close_ssk(sk, ssk, subflow, timeout);
+		spin_lock_bh(&msk->pm.lock);
+
+		msk->pm.local_addr_used--;
+		msk->pm.subflows--;
+
+		break;
+	}
+}
+
 static bool address_use_port(struct mptcp_pm_addr_entry *entry)
 {
 	return (entry->addr.flags &
net/mptcp/protocol.h +2 -1
index d1b1416797f8..df6cc94df1f7 100644
@@ -448,7 +448,7 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
 			   bool echo);
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
+int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id);
 
 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
 {
@@ -479,6 +479,7 @@ void mptcp_pm_nl_fully_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk);
 void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk);
+void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 
 static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
Signature · 1 line
2.17.1
Reviewed-by on v1 9/16
#14 lore raw

[MPTCP] Re: [MPTCP][PATCH net-next 09/16] mptcp: implement mptcp_pm_remove_subflow

Quoted 14 lines · Geliang Tang

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

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

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

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
Quoted 5 lines

---

net/mptcp/pm.c         |  9 +++++++--
net/mptcp/pm_netlink.c | 33 +++++++++++++++++++++++++++++++++
net/mptcp/protocol.h   |  3 ++-
3 files changed, 42 insertions(+), 3 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

Reviewed-by on v1 9/16
#15 lore raw

Re: [MPTCP][PATCH net-next 09/16] mptcp: implement mptcp_pm_remove_subflow

In reply to Geliang Tang
Quoted 14 lines · Geliang Tang

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

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

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

Quoted 5 lines

---

net/mptcp/pm.c         |  9 +++++++--
net/mptcp/pm_netlink.c | 33 +++++++++++++++++++++++++++++++++
net/mptcp/protocol.h   |  3 ++-
3 files changed, 42 insertions(+), 3 deletions(-)

Resending this reviewed-by tag so patchwork picks it up (previous mail was not delivered to the mailing list, but I'm assuming it did go to other recipients).

--
Mat Martineau
Intel

#16 lore raw

PATCH 10/16 mptcp: add RM_ADDR related mibs

In reply to Geliang Tang

This patch added two new mibs for RM_ADDR, named MPTCP_MIB_RMADDR and MPTCP_MIB_RMSUBFLOW, when the RM_ADDR suboption is received, increase the first mib counter, when the local subflow is removed, increase the second mib counter.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/mib.c        | 2 ++
 net/mptcp/mib.h        | 2 ++
 net/mptcp/pm_netlink.c | 5 +++++
 3 files changed, 9 insertions(+)
net/mptcp/mib.c +2 -0
index a33bf719ce6f..84d119436b22 100644
@@ -29,6 +29,8 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("DuplicateData", MPTCP_MIB_DUPDATA),
 	SNMP_MIB_ITEM("AddAddr", MPTCP_MIB_ADDADDR),
 	SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD),
+	SNMP_MIB_ITEM("RmAddr", MPTCP_MIB_RMADDR),
+	SNMP_MIB_ITEM("RmSubflow", MPTCP_MIB_RMSUBFLOW),
 	SNMP_MIB_SENTINEL
 };
 
net/mptcp/mib.h +2 -0
index cdeea3732ddf..47bcecce1106 100644
@@ -22,6 +22,8 @@ enum linux_mptcp_mib_field {
 	MPTCP_MIB_DUPDATA,		/* Segments discarded due to duplicate DSS */
 	MPTCP_MIB_ADDADDR,		/* Received ADD_ADDR with echo-flag=0 */
 	MPTCP_MIB_ECHOADD,		/* Received ADD_ADDR with echo-flag=1 */
+	MPTCP_MIB_RMADDR,		/* Received RM_ADDR */
+	MPTCP_MIB_RMSUBFLOW,		/* Remove a subflow */
 	__MPTCP_MIB_MAX
 };
 
net/mptcp/pm_netlink.c +5 -0
index 9064c8098521..b33aebd85bd5 100644
@@ -15,6 +15,7 @@
 #include <uapi/linux/mptcp.h>
 
 #include "protocol.h"
+#include "mib.h"
 
 /* forward declaration */
 static struct genl_family mptcp_genl_family;
@@ -346,6 +347,8 @@ void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
 		msk->pm.subflows--;
 		WRITE_ONCE(msk->pm.accept_addr, true);
 
+		__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMADDR);
+
 		break;
 	}
 }
@@ -379,6 +382,8 @@ void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id)
 		msk->pm.local_addr_used--;
 		msk->pm.subflows--;
 
+		__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
+
 		break;
 	}
 }
Signature · 1 line
2.17.1
Reviewed-by on v1 10/16
#17 lore raw

Re: [MPTCP][PATCH net-next 10/16] mptcp: add RM_ADDR related mibs

Quoted 10 lines · Geliang Tang

This patch added two new mibs for RM_ADDR, named MPTCP_MIB_RMADDR and MPTCP_MIB_RMSUBFLOW, when the RM_ADDR suboption is received, increase the first mib counter, when the local subflow is removed, increase the second mib counter.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
Quoted 5 lines

---

net/mptcp/mib.c        | 2 ++
net/mptcp/mib.h        | 2 ++
net/mptcp/pm_netlink.c | 5 +++++
3 files changed, 9 insertions(+)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#18 lore raw

PATCH 11/16 mptcp: add mptcp_destroy_common helper

In reply to Geliang Tang

This patch added a new helper named mptcp_destroy_common containing the shared code between mptcp_destroy() and mptcp_sock_destruct().

Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/protocol.c | 11 ++++++++---
 net/mptcp/protocol.h |  1 +
 net/mptcp/subflow.c  |  4 +---
 3 files changed, 10 insertions(+), 6 deletions(-)
net/mptcp/protocol.c +8 -3
index b53e55826975..34c037731f35 100644
@@ -2128,16 +2128,21 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
 	return newsk;
 }
 
+void mptcp_destroy_common(struct mptcp_sock *msk)
+{
+	skb_rbtree_purge(&msk->out_of_order_queue);
+	mptcp_token_destroy(msk);
+	mptcp_pm_free_anno_list(msk);
+}
+
 static void mptcp_destroy(struct sock *sk)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
 
-	skb_rbtree_purge(&msk->out_of_order_queue);
-	mptcp_token_destroy(msk);
 	if (msk->cached_ext)
 		__skb_ext_put(msk->cached_ext);
 
-	mptcp_pm_free_anno_list(msk);
+	mptcp_destroy_common(msk);
 	sk_sockets_allocated_dec(sk);
 }
 
net/mptcp/protocol.h +1 -0
index df6cc94df1f7..db1e5de2fee7 100644
@@ -408,6 +408,7 @@ bool mptcp_finish_join(struct sock *sk);
 void mptcp_data_acked(struct sock *sk);
 void mptcp_subflow_eof(struct sock *sk);
 bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
+void mptcp_destroy_common(struct mptcp_sock *msk);
 
 void __init mptcp_token_init(void);
 static inline void mptcp_token_init_request(struct request_sock *req)
net/mptcp/subflow.c +1 -3
index a1fefc965e17..ac2b19993f1a 100644
@@ -435,9 +435,7 @@ static void mptcp_sock_destruct(struct sock *sk)
 		sock_orphan(sk);
 	}
 
-	skb_rbtree_purge(&mptcp_sk(sk)->out_of_order_queue);
-	mptcp_token_destroy(mptcp_sk(sk));
-	mptcp_pm_free_anno_list(mptcp_sk(sk));
+	mptcp_destroy_common(mptcp_sk(sk));
 	inet_sock_destruct(sk);
 }
 
Signature · 1 line
2.17.1
Reviewed-by on v1 11/16
#19 lore raw

Re: [MPTCP][PATCH net-next 11/16] mptcp: add mptcp_destroy_common helper

Quoted 10 lines · Geliang Tang

This patch added a new helper named mptcp_destroy_common containing the shared code between mptcp_destroy() and mptcp_sock_destruct().

Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---

net/mptcp/protocol.c | 11 ++++++++---
net/mptcp/protocol.h |  1 +
net/mptcp/subflow.c  |  4 +---
3 files changed, 10 insertions(+), 6 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#20 lore raw

PATCH 12/16 selftests: mptcp: add remove cfg in mptcp_connect

In reply to Geliang Tang

This patch added a new cfg, named cfg_remove in mptcp_connect. This new cfg_remove is copied from cfg_join. The only difference between them is in the do_rnd_write function. Here we slow down the transfer process of all data to let the RM_ADDR suboption can be sent and received completely. Otherwise the remove address and subflow test cases don't work.

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 .../selftests/net/mptcp/mptcp_connect.c        | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_connect.c +15 -3
index a54966531a64..77bb62feb872 100644
@@ -54,6 +54,7 @@ static int pf = AF_INET;
 static int cfg_sndbuf;
 static int cfg_rcvbuf;
 static bool cfg_join;
+static bool cfg_remove;
 static int cfg_wait;
 
 static void die_usage(void)
@@ -271,6 +272,9 @@ static size_t do_rnd_write(const int fd, char *buf, const size_t len)
 	if (cfg_join && first && do_w > 100)
 		do_w = 100;
 
+	if (cfg_remove && do_w > 50)
+		do_w = 50;
+
 	bw = write(fd, buf, do_w);
 	if (bw < 0)
 		perror("write");
@@ -281,6 +285,9 @@ static size_t do_rnd_write(const int fd, char *buf, const size_t len)
 		first = false;
 	}
 
+	if (cfg_remove)
+		usleep(200000);
+
 	return bw;
 }
 
@@ -428,7 +435,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd)
 	}
 
 	/* leave some time for late join/announce */
-	if (cfg_join)
+	if (cfg_join || cfg_remove)
 		usleep(cfg_wait);
 
 	close(peerfd);
@@ -686,7 +693,7 @@ static void maybe_close(int fd)
 {
 	unsigned int r = rand();
 
-	if (!cfg_join && (r & 1))
+	if (!(cfg_join || cfg_remove) && (r & 1))
 		close(fd);
 }
 
@@ -822,13 +829,18 @@ static void parse_opts(int argc, char **argv)
 {
 	int c;
 
-	while ((c = getopt(argc, argv, "6jlp:s:hut:m:S:R:w:")) != -1) {
+	while ((c = getopt(argc, argv, "6jrlp:s:hut:m:S:R:w:")) != -1) {
 		switch (c) {
 		case 'j':
 			cfg_join = true;
 			cfg_mode = CFG_MODE_POLL;
 			cfg_wait = 400000;
 			break;
+		case 'r':
+			cfg_remove = true;
+			cfg_mode = CFG_MODE_POLL;
+			cfg_wait = 400000;
+			break;
 		case 'l':
 			listen_mode = true;
 			break;
Signature · 1 line
2.17.1
Reviewed-by on v1 12/16
#21 lore raw

Re: [MPTCP][PATCH net-next 12/16] selftests: mptcp: add remove cfg in mptcp_connect

Quoted 6 lines · Geliang Tang

This patch added a new cfg, named cfg_remove in mptcp_connect. This new cfg_remove is copied from cfg_join. The only difference between them is in the do_rnd_write function. Here we slow down the transfer process of all data to let the RM_ADDR suboption can be sent and received completely. Otherwise the remove address and subflow test cases don't work.

Quoted 8 lines
Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---
.../selftests/net/mptcp/mptcp_connect.c | 18 +++++++++++++++---

1 file changed, 15 insertions(+), 3 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#22 lore raw

PATCH 13/16 selftests: mptcp: add remove addr and subflow test cases

In reply to Geliang Tang

This patch added the remove addr and subflow test cases and two new functions.

The first function run_remove_tests calls do_transfer with two new arguments, rm_nr_ns1 and rm_nr_ns2, for the numbers of addresses should be removed during the transfer process in namespace 1 and namespace 2.

If both these two arguments are 0, we do the join test cases with "mptcp_connect -j" command. Otherwise, do the remove test cases with "mptcp_connect -r" command.

The second function chk_rm_nr checks the RM_ADDR related mibs's counters.

The output of the test cases looks like this:

11 remove single subflow syn[ ok ] - synack[ ok ] - ack[ ok ]
rm [ ok ] - sf [ ok ]
12 remove multiple subflows syn[ ok ] - synack[ ok ] - ack[ ok ]
rm [ ok ] - sf [ ok ]
13 remove single address syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]
14 remove subflow and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]
15 remove subflows and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]

Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 .../testing/selftests/net/mptcp/mptcp_join.sh | 145 +++++++++++++++++-
 1 file changed, 142 insertions(+), 3 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +142 -3
index 9d64abdde146..08f53d86dedc 100755
@@ -8,6 +8,7 @@ cin=""
 cout=""
 ksft_skip=4
 timeout=30
+mptcp_connect=""
 capture=0
 
 TEST_COUNT=0
@@ -132,6 +133,8 @@ do_transfer()
 	cl_proto="$3"
 	srv_proto="$4"
 	connect_addr="$5"
+	rm_nr_ns1="$6"
+	rm_nr_ns2="$7"
 
 	port=$((10000+$TEST_COUNT))
 	TEST_COUNT=$((TEST_COUNT+1))
@@ -156,14 +159,44 @@ do_transfer()
 		sleep 1
 	fi
 
-	ip netns exec ${listener_ns} ./mptcp_connect -j -t $timeout -l -p $port -s ${srv_proto} 0.0.0.0 < "$sin" > "$sout" &
+	if [[ $rm_nr_ns1 -eq 0 && $rm_nr_ns2 -eq 0 ]]; then
+		mptcp_connect="./mptcp_connect -j"
+	else
+		mptcp_connect="./mptcp_connect -r"
+	fi
+
+	ip netns exec ${listener_ns} $mptcp_connect -t $timeout -l -p $port -s ${srv_proto} 0.0.0.0 < "$sin" > "$sout" &
 	spid=$!
 
 	sleep 1
 
-	ip netns exec ${connector_ns} ./mptcp_connect -j -t $timeout -p $port -s ${cl_proto} $connect_addr < "$cin" > "$cout" &
+	ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr < "$cin" > "$cout" &
 	cpid=$!
 
+	if [ $rm_nr_ns1 -gt 0 ]; then
+		counter=1
+		sleep 1
+
+		while [ $counter -le $rm_nr_ns1 ]
+		do
+			ip netns exec ${listener_ns} ./pm_nl_ctl del $counter
+			sleep 1
+			let counter+=1
+		done
+	fi
+
+	if [ $rm_nr_ns2 -gt 0 ]; then
+		counter=1
+		sleep 1
+
+		while [ $counter -le $rm_nr_ns2 ]
+		do
+			ip netns exec ${connector_ns} ./pm_nl_ctl del $counter
+			sleep 1
+			let counter+=1
+		done
+	fi
+
 	wait $cpid
 	retc=$?
 	wait $spid
@@ -219,7 +252,24 @@ run_tests()
 	connect_addr="$3"
 	lret=0
 
-	do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr}
+	do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 0 0
+	lret=$?
+	if [ $lret -ne 0 ]; then
+		ret=$lret
+		return
+	fi
+}
+
+run_remove_tests()
+{
+	listener_ns="$1"
+	connector_ns="$2"
+	connect_addr="$3"
+	rm_nr_ns1="$4"
+	rm_nr_ns2="$5"
+	lret=0
+
+	do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} ${rm_nr_ns1} ${rm_nr_ns2}
 	lret=$?
 	if [ $lret -ne 0 ]; then
 		ret=$lret
@@ -313,6 +363,43 @@ chk_add_nr()
 	fi
 }
 
+chk_rm_nr()
+{
+	local rm_addr_nr=$1
+	local rm_subflow_nr=$2
+	local count
+	local dump_stats
+
+	printf "%-39s %s" " " "rm "
+	count=`ip netns exec $ns1 nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'`
+	[ -z "$count" ] && count=0
+	if [ "$count" != "$rm_addr_nr" ]; then
+		echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
+		ret=1
+		dump_stats=1
+	else
+		echo -n "[ ok ]"
+	fi
+
+	echo -n " - sf    "
+	count=`ip netns exec $ns2 nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
+	[ -z "$count" ] && count=0
+	if [ "$count" != "$rm_subflow_nr" ]; then
+		echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
+		ret=1
+		dump_stats=1
+	else
+		echo "[ ok ]"
+	fi
+
+	if [ "${dump_stats}" = 1 ]; then
+		echo Server ns stats
+		ip netns exec $ns1 nstat -as | grep MPTcp
+		echo Client ns stats
+		ip netns exec $ns2 nstat -as | grep MPTcp
+	fi
+}
+
 sin=$(mktemp)
 sout=$(mktemp)
 cin=$(mktemp)
@@ -404,6 +491,58 @@ run_tests $ns1 $ns2 10.0.1.1
 chk_join_nr "multiple subflows and signal" 3 3 3
 chk_add_nr 1 1
 
+# single subflow, remove
+reset
+ip netns exec $ns1 ./pm_nl_ctl limits 0 1
+ip netns exec $ns2 ./pm_nl_ctl limits 0 1
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
+run_remove_tests $ns1 $ns2 10.0.1.1 0 1
+chk_join_nr "remove single subflow" 1 1 1
+chk_rm_nr 1 1
+
+# multiple subflows, remove
+reset
+ip netns exec $ns1 ./pm_nl_ctl limits 0 2
+ip netns exec $ns2 ./pm_nl_ctl limits 0 2
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
+run_remove_tests $ns1 $ns2 10.0.1.1 0 2
+chk_join_nr "remove multiple subflows" 2 2 2
+chk_rm_nr 2 2
+
+# single address, remove
+reset
+ip netns exec $ns1 ./pm_nl_ctl limits 0 1
+ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
+ip netns exec $ns2 ./pm_nl_ctl limits 1 1
+run_remove_tests $ns1 $ns2 10.0.1.1 1 0
+chk_join_nr "remove single address" 1 1 1
+chk_add_nr 1 1
+chk_rm_nr 0 0
+
+# subflow and signal, remove
+reset
+ip netns exec $ns1 ./pm_nl_ctl limits 0 2
+ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
+ip netns exec $ns2 ./pm_nl_ctl limits 1 2
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
+run_remove_tests $ns1 $ns2 10.0.1.1 1 1
+chk_join_nr "remove subflow and signal" 2 2 2
+chk_add_nr 1 1
+chk_rm_nr 1 1
+
+# subflows and signal, remove
+reset
+ip netns exec $ns1 ./pm_nl_ctl limits 0 3
+ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
+ip netns exec $ns2 ./pm_nl_ctl limits 1 3
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
+ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
+run_remove_tests $ns1 $ns2 10.0.1.1 1 2
+chk_join_nr "remove subflows and signal" 3 3 3
+chk_add_nr 1 1
+chk_rm_nr 2 2
+
 # single subflow, syncookies
 reset_with_cookies
 ip netns exec $ns1 ./pm_nl_ctl limits 0 1
Signature · 1 line
2.17.1
Reviewed-by on v1 13/16
#23 lore raw

Re: [MPTCP][PATCH net-next 13/16] selftests: mptcp: add remove addr and subflow test cases

Quoted 29 lines · Geliang Tang

This patch added the remove addr and subflow test cases and two new functions.

The first function run_remove_tests calls do_transfer with two new arguments, rm_nr_ns1 and rm_nr_ns2, for the numbers of addresses should be removed during the transfer process in namespace 1 and namespace 2.

If both these two arguments are 0, we do the join test cases with "mptcp_connect -j" command. Otherwise, do the remove test cases with "mptcp_connect -r" command.

The second function chk_rm_nr checks the RM_ADDR related mibs's counters.

The output of the test cases looks like this:

11 remove single subflow syn[ ok ] - synack[ ok ] - ack[ ok ]
rm [ ok ] - sf [ ok ]
12 remove multiple subflows syn[ ok ] - synack[ ok ] - ack[ ok ]
rm [ ok ] - sf [ ok ]
13 remove single address syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]
14 remove subflow and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]
15 remove subflows and signal syn[ ok ] - synack[ ok ] - ack[ ok ]
add[ ok ] - echo [ ok ]
rm [ ok ] - sf [ ok ]

Quoted 8 lines
Suggested-by Matthieu Baerts <matthieu.baerts(a)tessares.net>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---
.../testing/selftests/net/mptcp/mptcp_join.sh | 145 +++++++++++++++++-

1 file changed, 142 insertions(+), 3 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#24 lore raw

PATCH 14/16 mptcp: add struct mptcp_pm_add_entry

In reply to Geliang Tang

Add a new struct mptcp_pm_add_entry to describe add_addr's entry.

Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/pm_netlink.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)
net/mptcp/pm_netlink.c +12 -7
index b33aebd85bd5..701972b55a45 100644
@@ -28,6 +28,11 @@ struct mptcp_pm_addr_entry {
 	struct rcu_head		rcu;
 };
 
+struct mptcp_pm_add_entry {
+	struct list_head	list;
+	struct mptcp_addr_info	addr;
+};
+
 struct pm_nl_pernet {
 	/* protects pernet updates */
 	spinlock_t		lock;
@@ -181,7 +186,7 @@ static void check_work_pending(struct mptcp_sock *msk)
 static bool lookup_anno_list_by_saddr(struct mptcp_sock *msk,
 				      struct mptcp_addr_info *addr)
 {
-	struct mptcp_pm_addr_entry *entry;
+	struct mptcp_pm_add_entry *entry;
 
 	list_for_each_entry(entry, &msk->pm.anno_list, list) {
 		if (addresses_equal(&entry->addr, addr, false))
@@ -194,23 +199,23 @@ static bool lookup_anno_list_by_saddr(struct mptcp_sock *msk,
 static bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
 				     struct mptcp_pm_addr_entry *entry)
 {
-	struct mptcp_pm_addr_entry *clone = NULL;
+	struct mptcp_pm_add_entry *add_entry = NULL;
 
 	if (lookup_anno_list_by_saddr(msk, &entry->addr))
 		return false;
 
-	clone = kmemdup(entry, sizeof(*entry), GFP_ATOMIC);
-	if (!clone)
+	add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC);
+	if (!add_entry)
 		return false;
 
-	list_add(&clone->list, &msk->pm.anno_list);
+	list_add(&add_entry->list, &msk->pm.anno_list);
 
 	return true;
 }
 
 void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
 {
-	struct mptcp_pm_addr_entry *entry, *tmp;
+	struct mptcp_pm_add_entry *entry, *tmp;
 
 	pr_debug("msk=%p", msk);
 
@@ -654,7 +659,7 @@ __lookup_addr_by_id(struct pm_nl_pernet *pernet, unsigned int id)
 static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
 				      struct mptcp_addr_info *addr)
 {
-	struct mptcp_pm_addr_entry *entry, *tmp;
+	struct mptcp_pm_add_entry *entry, *tmp;
 
 	list_for_each_entry_safe(entry, tmp, &msk->pm.anno_list, list) {
 		if (addresses_equal(&entry->addr, addr, false)) {
Signature · 1 line
2.17.1
Reviewed-by on v1 14/16
#25 lore raw

Re: [MPTCP][PATCH net-next 14/16] mptcp: add struct mptcp_pm_add_entry

Quoted 7 lines · Geliang Tang

Add a new struct mptcp_pm_add_entry to describe add_addr's entry.

Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---
net/mptcp/pm_netlink.c | 19 ++++++++++++-------

1 file changed, 12 insertions(+), 7 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#26 lore raw

PATCH 15/16 mptcp: add sk_stop_timer_sync helper

In reply to Geliang Tang

This patch added a new helper sk_stop_timer_sync, it deactivates a timer like sk_stop_timer, but waits for the handler to finish.

Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 include/net/sock.h | 2 ++
 net/core/sock.c    | 7 +++++++
 2 files changed, 9 insertions(+)
include/net/sock.h +2 -0
index eaa5cac5e836..a5c6ae78df77 100644
@@ -2195,6 +2195,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
 
 void sk_stop_timer(struct sock *sk, struct timer_list *timer);
 
+void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer);
+
 int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue,
 			struct sk_buff *skb, unsigned int flags,
 			void (*destructor)(struct sock *sk,
net/core/sock.c +7 -0
index ba9e7d91e2ef..d9a537e6876a 100644
@@ -2947,6 +2947,13 @@ void sk_stop_timer(struct sock *sk, struct timer_list* timer)
 }
 EXPORT_SYMBOL(sk_stop_timer);
 
+void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer)
+{
+	if (del_timer_sync(timer))
+		__sock_put(sk);
+}
+EXPORT_SYMBOL(sk_stop_timer_sync);
+
 void sock_init_data(struct socket *sock, struct sock *sk)
 {
 	sk_init_common(sk);
Signature · 1 line
2.17.1
Reviewed-by on v1 15/16
#27 lore raw

Re: [MPTCP][PATCH net-next 15/16] mptcp: add sk_stop_timer_sync helper

Quoted 9 lines · Geliang Tang

This patch added a new helper sk_stop_timer_sync, it deactivates a timer like sk_stop_timer, but waits for the handler to finish.

Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>

---
include/net/sock.h | 2 ++
net/core/sock.c | 7 +++++++

2 files changed, 9 insertions(+)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

#28 lore raw

PATCH 16/16 mptcp: retransmit ADD_ADDR when timeout

In reply to Geliang Tang

This patch implemented the retransmition of ADD_ADDR when no ADD_ADDR echo is received. It added a timer with the announced address. When timeout occurs, ADD_ADDR will be retransmitted.

Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
---
 net/mptcp/options.c    |   1 +
 net/mptcp/pm_netlink.c | 109 ++++++++++++++++++++++++++++++++++-------
 net/mptcp/protocol.h   |   3 ++
 3 files changed, 96 insertions(+), 17 deletions(-)
net/mptcp/options.c +1 -0
index 171039cbe9c4..14a290fae767 100644
@@ -893,6 +893,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 			mptcp_pm_add_addr_received(msk, &addr);
 			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
 		} else {
+			mptcp_pm_del_add_timer(msk, &addr);
 			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
 		}
 		mp_opt.add_addr = 0;
net/mptcp/pm_netlink.c +92 -17

173 lines not on this page · raw message

net/mptcp/protocol.h +3 -0
index db1e5de2fee7..7cfe52aeb2b8 100644
@@ -444,6 +444,9 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 				const struct mptcp_addr_info *addr);
 void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
 void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
+struct mptcp_pm_add_entry *
+mptcp_pm_del_add_timer(struct mptcp_sock *msk,
+		       struct mptcp_addr_info *addr);
 
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
Signature · 1 line
2.17.1
Reviewed-by on v1 16/16
#29 lore raw

Re: [MPTCP][PATCH net-next 16/16] mptcp: retransmit ADD_ADDR when timeout

Quoted 8 lines · Geliang Tang

This patch implemented the retransmition of ADD_ADDR when no ADD_ADDR echo is received. It added a timer with the announced address. When timeout occurs, ADD_ADDR will be retransmitted.

Suggested-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>
Suggested-by Paolo Abeni <pabeni(a)redhat.com>
Acked-by Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by Geliang Tang <geliangtang(a)gmail.com>
Quoted 5 lines

---

net/mptcp/options.c    |   1 +
net/mptcp/pm_netlink.c | 109 ++++++++++++++++++++++++++++++++++-------
net/mptcp/protocol.h   |   3 ++
3 files changed, 96 insertions(+), 17 deletions(-)
Reviewed-by Mat Martineau <mathew.j.martineau(a)linux.intel.com>

--
Mat Martineau
Intel

maintainer
#30 lore raw
In reply to Geliang Tang

From: Geliang Tang <geliangtang(a)gmail.com>
Date: Thu, 24 Sep 2020 08:29:46 +0800

Quoted 26 lines

This series include two enhancements for the MPTCP path management, namely RM_ADDR support and ADD_ADDR echo support, as specified by RFC sections 3.4.1 and 3.4.2.

1 RM_ADDR support include 9 patches (1-3 and 8-13):

Patch 1 is the helper for patch 2, these two patches add the RM_ADDR outgoing functions, which are derived from ADD_ADDR's corresponding functions.

Patch 3 adds the RM_ADDR incoming logic, when RM_ADDR suboption is received, close the subflow matching the rm_id, and update PM counter.

Patch 8 is the main remove routine. When the PM netlink removes an address, we traverse all the existing msk sockets to find the relevant sockets. Then trigger the RM_ADDR signal and remove the subflow which using this local address, this subflow removing functions has been implemented in patch 9.

Finally, patches 10-13 are the self-tests for RM_ADDR.

2 ADD_ADDR echo support include 7 patches (4-7 and 14-16).

Patch 4 adds the ADD_ADDR echo logic, when the ADD_ADDR suboption has been received, send out the same ADD_ADDR suboption with echo-flag, and no HMAC included.

Quoted 5 lines

Patches 5 and 6 are the self-tests for ADD_ADDR echo. Patch 7 is a little cleaning up.

Patch 14 and 15 are the helpers for patch 16. These three patches add the ADD_ADDR retransmition when no ADD_ADDR echo is received.

Series applied, thank you.