All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mat Martineau <mathew.j.martineau@linux.intel.com>
To: netdev@vger.kernel.org
Cc: Peter Krystad <peter.krystad@linux.intel.com>,
	eric.dumazet@gmail.com, Florian Westphal <fw@strlen.de>,
	Paolo Abeni <pabeni@redhat.com>,
	Mat Martineau <mathew.j.martineau@linux.intel.com>
Subject: [PATCH net-next v3 05/17] mptcp: Implement path manager interface commands
Date: Fri, 27 Mar 2020 14:48:41 -0700	[thread overview]
Message-ID: <20200327214853.140669-6-mathew.j.martineau@linux.intel.com> (raw)
In-Reply-To: <20200327214853.140669-1-mathew.j.martineau@linux.intel.com>

From: Peter Krystad <peter.krystad@linux.intel.com>

Fill in more path manager functionality by adding a worker function and
modifying the related stub functions to schedule the worker.

Co-developed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Florian Westphal <fw@strlen.de>
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Peter Krystad <peter.krystad@linux.intel.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 net/mptcp/pm.c       | 132 +++++++++++++++++++++++++++++++++++++++++--
 net/mptcp/protocol.c |   1 +
 net/mptcp/protocol.h |   1 +
 3 files changed, 129 insertions(+), 5 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index ad837da0193d..3aedad58778c 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -15,7 +15,11 @@ static struct workqueue_struct *pm_wq;
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr)
 {
-	return -ENOTSUPP;
+	pr_debug("msk=%p, local_id=%d", msk, addr->id);
+
+	msk->pm.local = *addr;
+	WRITE_ONCE(msk->pm.addr_signal, true);
+	return 0;
 }
 
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
@@ -41,13 +45,58 @@ void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side)
 
 bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
 {
-	pr_debug("msk=%p", msk);
-	return false;
+	struct mptcp_pm_data *pm = &msk->pm;
+	int ret;
+
+	pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
+		 pm->subflows_max, READ_ONCE(pm->accept_subflow));
+
+	/* try to avoid acquiring the lock below */
+	if (!READ_ONCE(pm->accept_subflow))
+		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);
+	spin_unlock_bh(&pm->lock);
+
+	return ret;
+}
+
+/* return true if the new status bit is currently cleared, that is, this event
+ * can be server, eventually by an already scheduled work
+ */
+static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
+				   enum mptcp_pm_status new_status)
+{
+	pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status,
+		 BIT(new_status));
+	if (msk->pm.status & BIT(new_status))
+		return false;
+
+	msk->pm.status |= BIT(new_status);
+	if (queue_work(pm_wq, &msk->pm.work))
+		sock_hold((struct sock *)msk);
+	return true;
 }
 
 void mptcp_pm_fully_established(struct mptcp_sock *msk)
 {
+	struct mptcp_pm_data *pm = &msk->pm;
+
 	pr_debug("msk=%p", msk);
+
+	/* try to avoid acquiring the lock below */
+	if (!READ_ONCE(pm->work_pending))
+		return;
+
+	spin_lock_bh(&pm->lock);
+
+	if (READ_ONCE(pm->work_pending))
+		mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
+
+	spin_unlock_bh(&pm->lock);
 }
 
 void mptcp_pm_connection_closed(struct mptcp_sock *msk)
@@ -58,7 +107,19 @@ void mptcp_pm_connection_closed(struct mptcp_sock *msk)
 void mptcp_pm_subflow_established(struct mptcp_sock *msk,
 				  struct mptcp_subflow_context *subflow)
 {
+	struct mptcp_pm_data *pm = &msk->pm;
+
 	pr_debug("msk=%p", msk);
+
+	if (!READ_ONCE(pm->work_pending))
+		return;
+
+	spin_lock_bh(&pm->lock);
+
+	if (READ_ONCE(pm->work_pending))
+		mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
+
+	spin_unlock_bh(&pm->lock);
 }
 
 void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id)
@@ -69,7 +130,23 @@ 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)
 {
-	pr_debug("msk=%p, remote_id=%d", msk, addr->id);
+	struct mptcp_pm_data *pm = &msk->pm;
+
+	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))
+		pm->remote = *addr;
+
+	spin_unlock_bh(&pm->lock);
 }
 
 /* path manager helpers */
@@ -77,7 +154,24 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 			  struct mptcp_addr_info *saddr)
 {
-	return false;
+	int ret = false;
+
+	spin_lock_bh(&msk->pm.lock);
+
+	/* double check after the lock is acquired */
+	if (!mptcp_pm_should_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);
+	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)
@@ -87,6 +181,28 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
 
 static void pm_worker(struct work_struct *work)
 {
+	struct mptcp_pm_data *pm = container_of(work, struct mptcp_pm_data,
+						work);
+	struct mptcp_sock *msk = container_of(pm, struct mptcp_sock, pm);
+	struct sock *sk = (struct sock *)msk;
+
+	lock_sock(sk);
+	spin_lock_bh(&msk->pm.lock);
+
+	pr_debug("msk=%p status=%x", msk, pm->status);
+	if (pm->status & BIT(MPTCP_PM_ADD_ADDR_RECEIVED)) {
+		pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_RECEIVED);
+	}
+	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
+		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
+	}
+	if (pm->status & BIT(MPTCP_PM_SUBFLOW_ESTABLISHED)) {
+		pm->status &= ~BIT(MPTCP_PM_SUBFLOW_ESTABLISHED);
+	}
+
+	spin_unlock_bh(&msk->pm.lock);
+	release_sock(sk);
+	sock_put(sk);
 }
 
 void mptcp_pm_data_init(struct mptcp_sock *msk)
@@ -105,6 +221,12 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
 	INIT_WORK(&msk->pm.work, pm_worker);
 }
 
+void mptcp_pm_close(struct mptcp_sock *msk)
+{
+	if (cancel_work_sync(&msk->pm.work))
+		sock_put((struct sock *)msk);
+}
+
 void mptcp_pm_init(void)
 {
 	pm_wq = alloc_workqueue("pm_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 8);
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3d84e0b83c99..5c4560287bd2 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -833,6 +833,7 @@ static void mptcp_close(struct sock *sk, long timeout)
 	}
 
 	mptcp_cancel_work(sk);
+	mptcp_pm_close(msk);
 
 	__skb_queue_purge(&sk->sk_receive_queue);
 
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index df134ac91274..209bdaa43dda 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -330,6 +330,7 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac);
 
 void mptcp_pm_init(void);
 void mptcp_pm_data_init(struct mptcp_sock *msk);
+void mptcp_pm_close(struct mptcp_sock *msk);
 void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side);
 void mptcp_pm_fully_established(struct mptcp_sock *msk);
 bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk);
-- 
2.26.0


  parent reply	other threads:[~2020-03-27 21:49 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-27 21:48 [PATCH net-next v3 00/17] Multipath TCP part 3: Multiple subflows and path management Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 01/17] mptcp: Add ADD_ADDR handling Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 02/17] mptcp: Add path manager interface Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 03/17] mptcp: Add handling of incoming MP_JOIN requests Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 04/17] mptcp: Add handling of outgoing " Mat Martineau
2021-10-27  0:54   ` Eric Dumazet
2021-10-27  8:45     ` Paolo Abeni
2021-10-27 15:06       ` Paolo Abeni
2021-10-27 20:38       ` Eric Dumazet
2020-03-27 21:48 ` Mat Martineau [this message]
2020-03-27 21:48 ` [PATCH net-next v3 06/17] mptcp: update per unacked sequence on pkt reception Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 07/17] mptcp: queue data for mptcp level retransmission Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 08/17] mptcp: introduce MPTCP retransmission timer Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 09/17] mptcp: implement memory accounting for mptcp rtx queue Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 10/17] mptcp: allow partial cleaning of rtx head dfrag Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 11/17] mptcp: rework mptcp_sendmsg_frag to accept optional dfrag Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 12/17] mptcp: implement and use MPTCP-level retransmission Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 13/17] mptcp: allow dumping subflow context to userspace Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 14/17] mptcp: add and use MIB counter infrastructure Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 15/17] mptcp: add netlink-based PM Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 16/17] selftests: add PM netlink functional tests Mat Martineau
2020-03-27 21:48 ` [PATCH net-next v3 17/17] selftests: add test-cases for MPTCP MP_JOIN Mat Martineau
2020-03-30  5:15 ` [PATCH net-next v3 00/17] Multipath TCP part 3: Multiple subflows and path management David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200327214853.140669-6-mathew.j.martineau@linux.intel.com \
    --to=mathew.j.martineau@linux.intel.com \
    --cc=eric.dumazet@gmail.com \
    --cc=fw@strlen.de \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=peter.krystad@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.