netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] tcp: address two poll() flakes
@ 2017-04-18 16:45 Eric Dumazet
  2017-04-18 16:45 ` [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST Eric Dumazet
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Eric Dumazet @ 2017-04-18 16:45 UTC (permalink / raw)
  To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet

Some packetdrill tests are failing when host kernel is using ASAN
or other debugging infrastructure.

I was able to fix the flakes by making sure we were not
sending wakeup events too soon.

Eric Dumazet (2):
  tcp: remove poll() flakes when receiving RST
  tcp: remove poll() flakes with FastOpen

 net/ipv4/tcp_input.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST
  2017-04-18 16:45 [PATCH net-next 0/2] tcp: address two poll() flakes Eric Dumazet
@ 2017-04-18 16:45 ` Eric Dumazet
  2017-04-18 17:49   ` Soheil Hassas Yeganeh
  2017-04-18 16:45 ` [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen Eric Dumazet
  2017-04-20 19:42 ` [PATCH net-next 0/2] tcp: address two poll() flakes David Miller
  2 siblings, 1 reply; 6+ messages in thread
From: Eric Dumazet @ 2017-04-18 16:45 UTC (permalink / raw)
  To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet

When a RST packet is processed, we send two wakeup events to interested
polling users.

First one by a sk->sk_error_report(sk) from tcp_reset(),
followed by a sk->sk_state_change(sk) from tcp_done().

Depending on machine load and luck, poll() can either return POLLERR,
or POLLIN|POLLOUT|POLLERR|POLLHUP (this happens on 99 % of the cases)

This is probably fine, but we can avoid the confusion by reordering
things so that we have more TCP fields updated before the first wakeup.

This might even allow us to remove some barriers we added in the past.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/tcp_input.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a5838858c362cd3270296001ceaae341e9e9bf01..37e2aa925f62395cfb48145cd3a76b6afebb64b1 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4008,10 +4008,10 @@ void tcp_reset(struct sock *sk)
 	/* This barrier is coupled with smp_rmb() in tcp_poll() */
 	smp_wmb();
 
+	tcp_done(sk);
+
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_error_report(sk);
-
-	tcp_done(sk);
 }
 
 /*
-- 
2.12.2.762.g0e3151a226-goog

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

* [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen
  2017-04-18 16:45 [PATCH net-next 0/2] tcp: address two poll() flakes Eric Dumazet
  2017-04-18 16:45 ` [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST Eric Dumazet
@ 2017-04-18 16:45 ` Eric Dumazet
  2017-04-20  5:55   ` Yuchung Cheng
  2017-04-20 19:42 ` [PATCH net-next 0/2] tcp: address two poll() flakes David Miller
  2 siblings, 1 reply; 6+ messages in thread
From: Eric Dumazet @ 2017-04-18 16:45 UTC (permalink / raw)
  To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet

When using TCP FastOpen for an active session, we send one wakeup event
from tcp_finish_connect(), right before the data eventually contained in
the received SYNACK is queued to sk->sk_receive_queue.

This means that depending on machine load or luck, poll() users
might receive POLLOUT events instead of POLLIN|POLLOUT

To fix this, we need to move the call to sk->sk_state_change()
after the (optional) call to tcp_rcv_fastopen_synack()

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/tcp_input.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 37e2aa925f62395cfb48145cd3a76b6afebb64b1..341f021f02a2931cd75b2e1e71af9729fc4c7895 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5580,10 +5580,6 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
 	else
 		tp->pred_flags = 0;
 
-	if (!sock_flag(sk, SOCK_DEAD)) {
-		sk->sk_state_change(sk);
-		sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
-	}
 }
 
 static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
@@ -5652,6 +5648,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_fastopen_cookie foc = { .len = -1 };
 	int saved_clamp = tp->rx_opt.mss_clamp;
+	bool fastopen_fail;
 
 	tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
 	if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
@@ -5755,10 +5752,15 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 
 		tcp_finish_connect(sk, skb);
 
-		if ((tp->syn_fastopen || tp->syn_data) &&
-		    tcp_rcv_fastopen_synack(sk, skb, &foc))
-			return -1;
+		fastopen_fail = (tp->syn_fastopen || tp->syn_data) &&
+				tcp_rcv_fastopen_synack(sk, skb, &foc);
 
+		if (!sock_flag(sk, SOCK_DEAD)) {
+			sk->sk_state_change(sk);
+			sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
+		}
+		if (fastopen_fail)
+			return -1;
 		if (sk->sk_write_pending ||
 		    icsk->icsk_accept_queue.rskq_defer_accept ||
 		    icsk->icsk_ack.pingpong) {
-- 
2.12.2.762.g0e3151a226-goog

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

* Re: [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST
  2017-04-18 16:45 ` [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST Eric Dumazet
@ 2017-04-18 17:49   ` Soheil Hassas Yeganeh
  0 siblings, 0 replies; 6+ messages in thread
From: Soheil Hassas Yeganeh @ 2017-04-18 17:49 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David S . Miller, netdev, Eric Dumazet

On Tue, Apr 18, 2017 at 12:45 PM, Eric Dumazet <edumazet@google.com> wrote:
> When a RST packet is processed, we send two wakeup events to interested
> polling users.
>
> First one by a sk->sk_error_report(sk) from tcp_reset(),
> followed by a sk->sk_state_change(sk) from tcp_done().
>
> Depending on machine load and luck, poll() can either return POLLERR,
> or POLLIN|POLLOUT|POLLERR|POLLHUP (this happens on 99 % of the cases)
>
> This is probably fine, but we can avoid the confusion by reordering
> things so that we have more TCP fields updated before the first wakeup.
>
> This might even allow us to remove some barriers we added in the past.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Acked-by: Soheil Hassas Yeganeh <soheil@google.com>

> ---
>  net/ipv4/tcp_input.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index a5838858c362cd3270296001ceaae341e9e9bf01..37e2aa925f62395cfb48145cd3a76b6afebb64b1 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -4008,10 +4008,10 @@ void tcp_reset(struct sock *sk)
>         /* This barrier is coupled with smp_rmb() in tcp_poll() */
>         smp_wmb();
>
> +       tcp_done(sk);
> +
>         if (!sock_flag(sk, SOCK_DEAD))
>                 sk->sk_error_report(sk);
> -
> -       tcp_done(sk);
>  }
>
>  /*
> --
> 2.12.2.762.g0e3151a226-goog
>

Thanks, Eric. Nice improvement!

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

* Re: [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen
  2017-04-18 16:45 ` [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen Eric Dumazet
@ 2017-04-20  5:55   ` Yuchung Cheng
  0 siblings, 0 replies; 6+ messages in thread
From: Yuchung Cheng @ 2017-04-20  5:55 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David S . Miller, netdev, Eric Dumazet

On Tue, Apr 18, 2017 at 9:45 AM, Eric Dumazet <edumazet@google.com> wrote:
>
> When using TCP FastOpen for an active session, we send one wakeup event
> from tcp_finish_connect(), right before the data eventually contained in
> the received SYNACK is queued to sk->sk_receive_queue.
>
> This means that depending on machine load or luck, poll() users
> might receive POLLOUT events instead of POLLIN|POLLOUT
>
> To fix this, we need to move the call to sk->sk_state_change()
> after the (optional) call to tcp_rcv_fastopen_synack()
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>

Thanks for the fix!

> ---
>  net/ipv4/tcp_input.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index 37e2aa925f62395cfb48145cd3a76b6afebb64b1..341f021f02a2931cd75b2e1e71af9729fc4c7895 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -5580,10 +5580,6 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
>         else
>                 tp->pred_flags = 0;
>
> -       if (!sock_flag(sk, SOCK_DEAD)) {
> -               sk->sk_state_change(sk);
> -               sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
> -       }
>  }
>
>  static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
> @@ -5652,6 +5648,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
>         struct tcp_sock *tp = tcp_sk(sk);
>         struct tcp_fastopen_cookie foc = { .len = -1 };
>         int saved_clamp = tp->rx_opt.mss_clamp;
> +       bool fastopen_fail;
>
>         tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
>         if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
> @@ -5755,10 +5752,15 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
>
>                 tcp_finish_connect(sk, skb);
>
> -               if ((tp->syn_fastopen || tp->syn_data) &&
> -                   tcp_rcv_fastopen_synack(sk, skb, &foc))
> -                       return -1;
> +               fastopen_fail = (tp->syn_fastopen || tp->syn_data) &&
> +                               tcp_rcv_fastopen_synack(sk, skb, &foc);
>
> +               if (!sock_flag(sk, SOCK_DEAD)) {
> +                       sk->sk_state_change(sk);
> +                       sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
> +               }
> +               if (fastopen_fail)
> +                       return -1;
>                 if (sk->sk_write_pending ||
>                     icsk->icsk_accept_queue.rskq_defer_accept ||
>                     icsk->icsk_ack.pingpong) {
> --
> 2.12.2.762.g0e3151a226-goog
>

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

* Re: [PATCH net-next 0/2] tcp: address two poll() flakes
  2017-04-18 16:45 [PATCH net-next 0/2] tcp: address two poll() flakes Eric Dumazet
  2017-04-18 16:45 ` [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST Eric Dumazet
  2017-04-18 16:45 ` [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen Eric Dumazet
@ 2017-04-20 19:42 ` David Miller
  2 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2017-04-20 19:42 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, eric.dumazet

From: Eric Dumazet <edumazet@google.com>
Date: Tue, 18 Apr 2017 09:45:50 -0700

> Some packetdrill tests are failing when host kernel is using ASAN
> or other debugging infrastructure.
> 
> I was able to fix the flakes by making sure we were not
> sending wakeup events too soon.

Series applied, thanks Eric.

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

end of thread, other threads:[~2017-04-20 19:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-18 16:45 [PATCH net-next 0/2] tcp: address two poll() flakes Eric Dumazet
2017-04-18 16:45 ` [PATCH net-next 1/2] tcp: remove poll() flakes when receiving RST Eric Dumazet
2017-04-18 17:49   ` Soheil Hassas Yeganeh
2017-04-18 16:45 ` [PATCH net-next 2/2] tcp: remove poll() flakes with FastOpen Eric Dumazet
2017-04-20  5:55   ` Yuchung Cheng
2017-04-20 19:42 ` [PATCH net-next 0/2] tcp: address two poll() flakes David Miller

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