Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 03 Apr 2012 15:45:19 +0200
From:      Andre Oppermann <andre@freebsd.org>
To:        Darren Reed <darernr@freebsd.org>
Cc:        darrenr@freebsd.org, freebsd-net@freebsd.org
Subject:   Re: FreeBSD TCP ignores zero window size
Message-ID:  <4F7AFEEF.60708@freebsd.org>
In-Reply-To: <4F780373.6030107@freebsd.org>
References:  <4F75C1A3.4030401@freebsd.org> <4F75D9ED.7080707@freebsd.org> <4F780373.6030107@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On 01.04.2012 09:27, Darren Reed wrote:
> Andre,
>
> Your changes bring it closer to working correctly with a
> small change: rather than "tiwin > tp->snd_wnd", it should
> be "tiwin != tp->snd_wnd". In this trace, the remote end
> has set a window scale factor of 5 during connection
> establishment.
>
> The same change should be made in the if() a few lines down.

Window updates are a tricky thing by that we must not accept
old and outdated segments to update our window.  Hence we have
to test for freshness while at the same time be open enough
to handle weird cases like bidirectional data transfers on
lossy links with data waiting in reassembly queues on both
sides.

There are two clear cut cases we can accept a window update:

  a) the incoming segment ACK'ed new data (moved snd_una).
  b) the incoming segment carries new data (moved rcv_nxt).

The latter gets tricky already with the addition of the
reassembly queue.  Here only segments that have a higher SEQ
than highest already present in the reassembly queue are OK.

And then we have a window probe where we'll get an answer
that neither moves our ACK (zero byte probes) nor carries
any data.  Here the window update is vital for the future
progress of the session.

> The problem here is that it only tracks the window size as
> it grows, not as it shrinks. Thus the remote end setting its
> window size to 0 is ignored.

My patch is wrong as the acked count is already integrated
by the time we reach this spot.  I'm working on a better
implementation.

> But having made that change, there appears to be still one
> problem that still lingers. As can be seen below, freebsd 8.2
> fails to properly ack the data that the remote end is trying
> to send, ultimately causing the connection to be dropped.

It's the other way around.  remote.ssh is sending old data
which freebsd82.62922 has already ack'ed.  The sessions seems
to be de-synchronized, perhaps some middle box mucking with
the segments trying to modulate something?

> Darren
>
> 16:06:50.207927 IP remote.ssh > freebsd82.62922: . 6268613:6270053(1440) ack 367219 win 128
> <nop,nop,timestamp 321 41540>
 > 16:06:50.208736 IP freebsd82.62922 > remote.ssh: . ack 6270053 win 8100 <nop,nop,timestamp 41562 321>
> 16:06:50.210902 IP remote.ssh > freebsd82.62922: . 6270053:6271493(1440) ack 367219 win 128
> <nop,nop,timestamp 321 41540>
> 16:06:50.211752 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 41562 321>

ACK 6,271,493 for data segment preceeding it.

> 16:06:50.229987 IP remote.ssh > freebsd82.62922: . ack 370099 win 38 <nop,nop,timestamp 321 41540>
> 16:06:50.419926 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 322 41540>
> 16:06:50.422858 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 322 41540>
> 16:06:51.207172 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 41662 322>
> 16:06:51.419263 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 324 41540>
> 16:06:53.203547 IP remote.ssh > freebsd82.62922: . 6267173:6268613(1440) ack 371315 win 0
> <nop,nop,timestamp 327 41540>

Incoming old data 6,267,173+1440 already ACK'ed 4320 bytes ago.

> 16:06:53.204320 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 41861 324>

ACK for highest SEQ seen again to re-synchronize.

> 16:06:53.415648 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 328 41540>
> 16:06:59.207766 IP remote.ssh > freebsd82.62922: . 6267173:6268613(1440) ack 371315 win 0
> <nop,nop,timestamp 339 41540>

remote.ssh doesn't get and retransmits...

> 16:06:59.208469 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 42462 328>
> 16:06:59.419342 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 340 41540>
> 16:07:11.212606 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 363 41540>

keeps on going with reduced MSS.

> 16:07:11.213158 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 43662 340>
> 16:07:11.424414 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 364 41540>
> 16:07:35.227356 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 411 41540>
> 16:07:35.227954 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 46064 364>
> 16:07:35.440105 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 412 41540>
> 16:08:23.257747 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 507 41540>
> 16:08:23.258471 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 50868 412>
> 16:08:23.469790 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 508 41540>
> 16:09:27.299037 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 635 41540>
> 16:09:27.299734 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 57273 508>
> 16:09:27.510740 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 636 41540>
> 16:10:31.340328 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 763 41540>
> 16:10:31.340996 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 63678 636>
> 16:10:31.552639 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 764 41540>
> 16:11:35.380906 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 891 41540>
> 16:11:35.381519 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 70083 764>
> 16:11:35.592948 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 892 41540>
> 16:12:39.421327 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 1019 41540>
> 16:12:39.421957 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 76487 892>
> 16:12:39.633531 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 1020 41540>
> 16:13:43.462137 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 1147 41540>
> 16:13:43.462625 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 82892 1020>
> 16:13:43.674110 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 1148 41540>
> 16:14:47.502951 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 1275 41540>
> 16:14:47.503637 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 89297 1148>
> 16:14:47.715729 IP remote.ssh > freebsd82.62922: . ack 371315 win 0 <nop,nop,timestamp 1276 41540>
> 16:15:51.542134 IP remote.ssh > freebsd82.62922: . 6267173:6267697(524) ack 371315 win 0
> <nop,nop,timestamp 1403 41540>
> 16:15:51.542794 IP freebsd82.62922 > remote.ssh: . ack 6271493 win 8280 <nop,nop,timestamp 95702 1276>
> 16:16:55.581199 IP remote.ssh > freebsd82.62922: R 6271493:6271493(0) ack 371315 win 0

Retransmission timeout exhausted and sending a reset with the
correct SEQ that freebsd82.62922 is trying to ack all the time!
The time difference between that last sync-ack and the RST doesn't
make it look like a direct response as in a closed socket.

-- 
Andre



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4F7AFEEF.60708>