All of lore.kernel.org
 help / color / mirror / Atom feed
* [MPTCP] Re: [RFC PATCH 5/5] subflow: do not create child subflow for fallback MP_JOIN
@ 2020-07-10 16:21 Paolo Abeni
  0 siblings, 0 replies; 2+ messages in thread
From: Paolo Abeni @ 2020-07-10 16:21 UTC (permalink / raw)
  To: mptcp

[-- Attachment #1: Type: text/plain, Size: 4363 bytes --]

On Thu, 2020-07-09 at 17:39 -0700, Mat Martineau wrote:
> On Tue, 30 Jun 2020, Paolo Abeni wrote:
> 
> > On MP_JOIN fallback, the child socket was used just to send-out
> > the due reset packet. As we don't use the child sock anymore
> > for such role, when can avoid creating the fallback MP_JOIN
> > sock entirely.
> > 
> > This saves a busy server from quite a bit of useless work, if
> > clients are storming with MP_JOIN reqs above the server limits
> > 
> > Signed-off-by: Paolo Abeni <pabeni(a)redhat.com>
> > ---
> > Note: to avoid changing the hook into tcp_check_req(), I had
> > to introduce a quite ugly const cast in subflow_syn_recv_sock().
> > I *think* it should be safe, but I'm 110% sure about unintended
> > implications - alike cc optimizing the calling code assuming sk
> > never changes, and generated code being bugged due to the above
> > cast.
> > 
> > I think should be safe, as the struct sock is not accessed
> > by tcp_check_req() when the relevant conditions held after
> > syn_recv_sock(), still something require additional eyeballs.
> > ---
> > net/mptcp/subflow.c | 21 +++++++++++++++++----
> > 1 file changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> > index 3077e07375b5..9f4f3e29587d 100644
> > --- a/net/mptcp/subflow.c
> > +++ b/net/mptcp/subflow.c
> > @@ -405,8 +405,11 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> > 	subflow_req = mptcp_subflow_rsk(req);
> > 	fallback_is_fatal = tcp_rsk(req)->is_mptcp && subflow_req->mp_join;
> > 	fallback = !tcp_rsk(req)->is_mptcp;
> > -	if (fallback)
> > +	if (fallback) {
> > +		if (fallback_is_fatal)
> > +			goto dispose_req;
> > 		goto create_child;
> > +	}
> > 
> > 	/* if the sk is MP_CAPABLE, we try to fetch the client key */
> > 	if (subflow_req->mp_capable) {
> > @@ -434,7 +437,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> > 		    !mptcp_can_accept_new_subflow(subflow_req->msk) ||
> > 		    !subflow_hmac_valid(req, &mp_opt)) {
> > 			SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
> > -			fallback = true;
> > +			goto dispose_req;
> > 		}
> > 	}
> > 
> > @@ -506,15 +509,25 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> > 		      !mptcp_subflow_ctx(child)->conn));
> > 	return child;
> > 
> > +dispose_req:
> > +	/* The last req reference will be released by the caller */
> > +	child = NULL;
> > +	*own_req = false;
> > +	reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
> > +	inet_csk_reqsk_queue_drop((struct sock *)sk, req);
> 
> I'm not sure about unintended consequences of this cast either. Even if it 
> looks ok now, the calling code could be changed.
> 
> Eric constified this parameter in 0c27171e66d9, saying "We'll soon no 
> longer hold listener socket lock, these functions do not modify the socket 
> in any way". It looks like the only modification to the socket by calling 
> inet_csk_reqsk_queue_drop() is an atomic_dec() or two, which should be an 
> ok thing to do. Do you think that would justify reverting that change to 
> the sk parameter?

Thank you for the feedback!

No, I think removing the 'const' from 'syn_recv_sock()' for this change
is a no-go.

> Looking at the call from tcp_check_req(), it looks like 
> ient_csk_reqsk_queue_drop() and req->rsk_ops->send_reset() can get called 
> again. This function will return NULL on this code path, and if the 
> tcp_abort_on_overflow sysctl is true, the drop/reset functions can get 
> called again. Is that not possible for not-obvious-to-me reasons?

No nothing prevent that code path from being executed - even if
requires non-default sysctl. Anyhow a duplicated rst packet should not
be too much problematic, I hope, and the 2nd execution of
inet_csk_reqsk_queue_drop() will be a no-op, as the sk will not be
hashed anymore.

Perhaps we can avoid the const cast changing a bit the hooking
in tcp_check_req(), but I'm reluctant to do that, as I changed the code
there recently. 

@Florian: do you foresee to have to touch tcp_check_req() for syncookie
handling? Perhaps we can unify the change there?

For the short term I'll send a v1 without 5/5 and including some other
fixes I'm assembling while working on issues/17.

Thanks!

Paolo

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

* [MPTCP] Re: [RFC PATCH 5/5] subflow: do not create child subflow for fallback MP_JOIN
@ 2020-07-10  0:39 Mat Martineau
  0 siblings, 0 replies; 2+ messages in thread
From: Mat Martineau @ 2020-07-10  0:39 UTC (permalink / raw)
  To: mptcp

[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]

On Tue, 30 Jun 2020, Paolo Abeni wrote:

> On MP_JOIN fallback, the child socket was used just to send-out
> the due reset packet. As we don't use the child sock anymore
> for such role, when can avoid creating the fallback MP_JOIN
> sock entirely.
>
> This saves a busy server from quite a bit of useless work, if
> clients are storming with MP_JOIN reqs above the server limits
>
> Signed-off-by: Paolo Abeni <pabeni(a)redhat.com>
> ---
> Note: to avoid changing the hook into tcp_check_req(), I had
> to introduce a quite ugly const cast in subflow_syn_recv_sock().
> I *think* it should be safe, but I'm 110% sure about unintended
> implications - alike cc optimizing the calling code assuming sk
> never changes, and generated code being bugged due to the above
> cast.
>
> I think should be safe, as the struct sock is not accessed
> by tcp_check_req() when the relevant conditions held after
> syn_recv_sock(), still something require additional eyeballs.
> ---
> net/mptcp/subflow.c | 21 +++++++++++++++++----
> 1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 3077e07375b5..9f4f3e29587d 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -405,8 +405,11 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> 	subflow_req = mptcp_subflow_rsk(req);
> 	fallback_is_fatal = tcp_rsk(req)->is_mptcp && subflow_req->mp_join;
> 	fallback = !tcp_rsk(req)->is_mptcp;
> -	if (fallback)
> +	if (fallback) {
> +		if (fallback_is_fatal)
> +			goto dispose_req;
> 		goto create_child;
> +	}
>
> 	/* if the sk is MP_CAPABLE, we try to fetch the client key */
> 	if (subflow_req->mp_capable) {
> @@ -434,7 +437,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> 		    !mptcp_can_accept_new_subflow(subflow_req->msk) ||
> 		    !subflow_hmac_valid(req, &mp_opt)) {
> 			SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
> -			fallback = true;
> +			goto dispose_req;
> 		}
> 	}
>
> @@ -506,15 +509,25 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
> 		      !mptcp_subflow_ctx(child)->conn));
> 	return child;
>
> +dispose_req:
> +	/* The last req reference will be released by the caller */
> +	child = NULL;
> +	*own_req = false;
> +	reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
> +	inet_csk_reqsk_queue_drop((struct sock *)sk, req);

I'm not sure about unintended consequences of this cast either. Even if it 
looks ok now, the calling code could be changed.

Eric constified this parameter in 0c27171e66d9, saying "We'll soon no 
longer hold listener socket lock, these functions do not modify the socket 
in any way". It looks like the only modification to the socket by calling 
inet_csk_reqsk_queue_drop() is an atomic_dec() or two, which should be an 
ok thing to do. Do you think that would justify reverting that change to 
the sk parameter?

Looking at the call from tcp_check_req(), it looks like 
ient_csk_reqsk_queue_drop() and req->rsk_ops->send_reset() can get called 
again. This function will return NULL on this code path, and if the 
tcp_abort_on_overflow sysctl is true, the drop/reset functions can get 
called again. Is that not possible for not-obvious-to-me reasons?

> +	goto reset;
> +
> dispose_child:
> +	/* The last child reference will be released by the caller */
> 	subflow_drop_ctx(child);
> 	tcp_rsk(req)->drop_req = true;
> 	inet_csk_prepare_for_destroy_sock(child);
> 	tcp_done(child);
> -	req->rsk_ops->send_reset(sk, skb);
>
> -	/* The last child reference will be released by the caller */
> +reset:
> +	req->rsk_ops->send_reset(sk, skb);
> 	return child;
> +
> }
>
> static struct inet_connection_sock_af_ops subflow_specific;
> -- 
> 2.26.2

--
Mat Martineau
Intel

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

end of thread, other threads:[~2020-07-10 16:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-10 16:21 [MPTCP] Re: [RFC PATCH 5/5] subflow: do not create child subflow for fallback MP_JOIN Paolo Abeni
  -- strict thread matches above, loose matches on Subject: below --
2020-07-10  0:39 Mat Martineau

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.