All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mat Martineau <mathew.j.martineau@linux.intel.com>
To: Geliang Tang <geliang.tang@suse.com>
Cc: mptcp@lists.linux.dev
Subject: Re: [PATCH mptcp-next v4 2/4] mptcp: reset subflow when MP_FAIL doesn't respond
Date: Mon, 14 Mar 2022 16:28:14 -0700 (PDT)	[thread overview]
Message-ID: <6d81053-849b-cdea-9230-80eb8b5d47b9@linux.intel.com> (raw)
In-Reply-To: <3ad7b8308cfb43d625b75d059db95ecdebca4caf.1646898548.git.geliang.tang@suse.com>

On Thu, 10 Mar 2022, Geliang Tang wrote:

> This patch added a new msk->flags bit MPTCP_FAIL_NO_RESPONSE, then reused
> sk_timer to trigger a check if we have not received a response from the
> peer after sending MP_FAIL. If the peer doesn't respond properly, reset
> the subflow.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> net/mptcp/pm.c       |  7 +++++++
> net/mptcp/protocol.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
> net/mptcp/protocol.h |  1 +
> net/mptcp/subflow.c  |  9 +++++++++
> 4 files changed, 61 insertions(+)
>
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index f5f4561f332a..e3a541ffebbd 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -276,6 +276,7 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
> {
> 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> +	struct sock *s = (struct sock *)msk;
>
> 	pr_debug("fail_seq=%llu", fail_seq);
>
> @@ -288,6 +289,12 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
> 		subflow->send_mp_fail = 1;
> 		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
> 		subflow->send_infinite_map = 1;
> +	} else if (s && inet_sk_state_load(s) != TCP_CLOSE) {
> +		pr_debug("MP_FAIL response received");
> +
> +		mptcp_data_lock(s);

I think the TCP_CLOSE state should be checked again after acquiring the 
lock to be sure the state hasn't changed - another thread could have 
acquired the lock and changed the socket state.

> +		sk_stop_timer(s, &s->sk_timer);
> +		mptcp_data_unlock(s);
> 	}
> }
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 3cb975227d12..d1a62e2a1d29 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -2166,9 +2166,33 @@ static void mptcp_retransmit_timer(struct timer_list *t)
> 	sock_put(sk);
> }
>
> +static struct mptcp_subflow_context *
> +mp_fail_response_expect_subflow(struct mptcp_sock *msk)
> +{
> +	struct mptcp_subflow_context *subflow, *ret = NULL;
> +
> +	mptcp_for_each_subflow(msk, subflow) {
> +		if (READ_ONCE(subflow->mp_fail_response_expect)) {
> +			ret = subflow;
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> static void mptcp_timeout_timer(struct timer_list *t)
> {
> 	struct sock *sk = from_timer(sk, t, sk_timer);
> +	struct mptcp_sock *msk = mptcp_sk(sk);
> +	struct mptcp_subflow_context *subflow;
> +
> +	subflow = mp_fail_response_expect_subflow(msk);

The msk needs to be locked before iterating over the subflows.

> +	if (subflow) {
> +		bh_lock_sock(sk);
> +		__set_bit(MPTCP_FAIL_NO_RESPONSE, &msk->flags);
> +		bh_unlock_sock(sk);
> +	}
>
> 	mptcp_schedule_work(sk);
> 	sock_put(sk);
> @@ -2494,6 +2518,23 @@ static void __mptcp_retrans(struct sock *sk)
> 		mptcp_reset_timer(sk);
> }
>
> +static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
> +{
> +	struct mptcp_subflow_context *subflow;
> +	struct sock *ssk;
> +	bool slow;
> +
> +	subflow = mp_fail_response_expect_subflow(msk);
> +	if (subflow) {
> +		pr_debug("MP_FAIL doesn't respond, reset the subflow");
> +
> +		ssk = mptcp_subflow_tcp_sock(subflow);
> +		slow = lock_sock_fast(ssk);
> +		mptcp_subflow_reset(ssk);
> +		unlock_sock_fast(ssk, slow);
> +	}
> +}
> +
> static void mptcp_worker(struct work_struct *work)
> {
> 	struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
> @@ -2534,6 +2575,9 @@ static void mptcp_worker(struct work_struct *work)
> 	if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
> 		__mptcp_retrans(sk);
>
> +	if (test_and_clear_bit(MPTCP_FAIL_NO_RESPONSE, &msk->flags))
> +		mptcp_mp_fail_no_response(msk);
> +
> unlock:
> 	release_sock(sk);
> 	sock_put(sk);
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 83f0205f0d95..bf58d3c886f5 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -116,6 +116,7 @@
> #define MPTCP_WORK_EOF		3
> #define MPTCP_FALLBACK_DONE	4
> #define MPTCP_WORK_CLOSE_SUBFLOW 5
> +#define MPTCP_FAIL_NO_RESPONSE	6
>
> /* MPTCP socket release cb flags */
> #define MPTCP_PUSH_PENDING	1
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index ca2352ad20d4..d38b8089988e 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -968,6 +968,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
> {
> 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
> 	bool csum_reqd = READ_ONCE(msk->csum_enabled);
> +	struct sock *sk = (struct sock *)msk;
> 	struct mptcp_ext *mpext;
> 	struct sk_buff *skb;
> 	u16 data_len;
> @@ -1009,6 +1010,11 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
> 		pr_debug("infinite mapping received");
> 		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
> 		subflow->map_data_len = 0;
> +		if (sk && inet_sk_state_load(sk) != TCP_CLOSE) {
> +			mptcp_data_lock(sk);

Similar to above, best to re-check for TCP_CLOSE.

> +			sk_stop_timer(sk, &sk->sk_timer);
> +			mptcp_data_unlock(sk);
> +		}
> 		return MAPPING_INVALID;
> 	}
>
> @@ -1219,6 +1225,9 @@ static bool subflow_check_data_avail(struct sock *ssk)
> 					sk_eat_skb(ssk, skb);
> 			} else {
> 				WRITE_ONCE(subflow->mp_fail_response_expect, true);
> +				sk_reset_timer((struct sock *)msk,
> +					       &((struct sock *)msk)->sk_timer,
> +					       jiffies + TCP_RTO_MAX);

Need to use mptcp_data_lock() here too. Can you also double-check other 
uses of sk_timer to make sure it's protected by the lock everywhere? The 
existing calls for using the timer at msk close might not all do this 
locking.

> 			}
> 			WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
> 			return true;
> -- 
> 2.34.1



--
Mat Martineau
Intel

  reply	other threads:[~2022-03-14 23:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-10  8:09 [PATCH mptcp-next v4 0/4] MP_FAIL echo and retrans Geliang Tang
2022-03-10  8:09 ` [PATCH mptcp-next v4 1/4] mptcp: add MP_FAIL response support Geliang Tang
2022-03-10  8:09 ` [PATCH mptcp-next v4 2/4] mptcp: reset subflow when MP_FAIL doesn't respond Geliang Tang
2022-03-14 23:28   ` Mat Martineau [this message]
2022-03-10  8:09 ` [PATCH mptcp-next v4 3/4] selftests: mptcp: check MP_FAIL response mibs Geliang Tang
2022-03-10  8:09 ` [PATCH mptcp-next v4 4/4] selftests: mptcp: print extra msg in chk_csum_nr Geliang Tang
2022-03-10  9:58   ` selftests: mptcp: print extra msg in chk_csum_nr: Tests Results MPTCP CI

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=6d81053-849b-cdea-9230-80eb8b5d47b9@linux.intel.com \
    --to=mathew.j.martineau@linux.intel.com \
    --cc=geliang.tang@suse.com \
    --cc=mptcp@lists.linux.dev \
    /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.