Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Feb 2021 17:44:22 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 253464] TCP fast recovery not entered, when SACK negotiated as client (initiating host), but no SACK blocks received in DupAcks
Message-ID:  <bug-253464-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D253464

            Bug ID: 253464
           Summary: TCP fast recovery not entered, when SACK negotiated as
                    client (initiating host), but no SACK blocks received
                    in DupAcks
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: rscheff@freebsd.org

Just to document a peculiar effect.

Using packetdrill to set up a session, with fbsd being the client (actively
establishing the session), SACK was negotiated. However, the script itself
would only send duplicate ACKs without SACK blocks.

In this instance, Fastrecovery doesn't appear to get triggered - even after=
 a
high number of duplicate ACKs. Only RTO resume forward progress eventually.

Note that this is an edge case: hosts negotiating SACK are expected to prov=
ide
the information which segment triggered the duplicate ACK with the SACK opt=
ion,
thus impact is small.

But curiously enough, this effect does NOT happen, when fbsd is the server =
side
(listening and accepting the session) - even when the remainder of the two
sripts is absolutely identical.

```
// Testing ECN Packet markings
// Active Client

--tolerance_usecs=3D50000

// Flush Hostcache
0.0 `sysctl net.inet.tcp.cc.algorithm=3Dnewreno`
+0.01 `sysctl net.inet.tcp.ecn.enable=3D1`
+0.01 `sysctl net.inet.tcp.initcwnd_segments=3D10`
+0.01 `sysctl net.inet.tcp.hostcache.purgenow=3D1`

// Create a TCP socket.
+0.50 socket(..., SOCK_STREAM, IPPROTO_TCP) =3D 4
+0.01 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) =3D 0
+0.01 setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) =3D 0
+0.01 setsockopt(4, SOL_SOCKET, SO_DEBUG, [1], 4) =3D 0
+0.01 setsockopt(4, SOL_SOCKET, SO_SNDBUF, [1048576], 4) =3D 0

// Establish a TCP connection with ECN

+0.04 connect(4, ..., ...) =3D -1 // EINPROGRESS

+0 >[noecn] SEW 0:0(0) win 65535 <mss 1460, nop,wscale 6,sackOK,TS val ... =
ecr
0>
+0 <[noecn] SE. 0:0(0) ack 1 win 65535 <mss 1000, nop, wscale 10, sackOK, e=
ol,
nop>
+0 >[noecn] .   1:1(0) ack 1 <...>

+0.01 getsockopt(4, SOL_SOCKET, SO_ERROR, [0], [4]) =3D 0
+0.01 fcntl(4, F_SETFL, O_RDWR) =3D 0   // set back to blocking

// Send IW plus 1 segment, check ECN bits
1.00 write(4, ..., 11000) =3D 11000
+0    >[ect0]  .      1:1001(1000) ack 1
+0    <[noecn] E.     1:1(0) ack 1001 win 65535
+0    >[ect0]  .   1001:2001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 2001 win 65535
+0    >[ect0]  .   2001:3001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 3001 win 65535
+0    >[ect0]  .   3001:4001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 4001 win 65535
+0    >[ect0]  .   4001:5001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 5001 win 65535
+0    >[ect0]  .   5001:6001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 6001 win 65535
+0    >[ect0]  .   6001:7001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 7001 win 65535
+0    >[ect0]  .   7001:8001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 8001 win 65535
+0    >[ect0]  .   8001:9001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 9001 win 65535
+0    >[ect0]  .   9001:10001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 10001 win 65535
+0    >[ect0]  PW. 10001:11001(1000) ack 1


// Send few more "loss" packets
+0.01 write(4, ..., 5000) =3D 5000

+0    >[ect0]  .  11001:12001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 10001 win 65535  // 1st dupack
+0    >[ect0]  .  12001:13001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 10001 win 65535  // 2nd dupack
+0    >[ect0]  .  13001:14001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 10001 win 65535  // 3rd dupack
+0    >[ect0]  .  14001:15001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 10001 win 65535  // 4th dupack

+0    >[ect0]  P. 15001:16001(1000) ack 1         // not sent, RTO for the
missing segment instead
+0    <[noecn] .      1:1(0) ack 10001 win 65535
/*
// Retransmission without ECT
+0    >[noecn] .  10001:11001(1000) ack 1

+0    <[noecn] .      1:1(0) ack 11001 win 65535
+0    >[noecn] .  11001:12001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 12001 win 65535
+0    >[noecn] .  12001:13001(1000) ack 1
+0    <[noecn] .      1:1(0) ack 16001 win 65535

//More data should be ECT marked again, and
// have the CWR flag set now.
+0.01 write(4, ..., 1000) =3D 1000
+0    >[ect0]  PW. 16001:17001(1000) ack 1
+0    <[noecn] .       1:1(0) ack 17001 win 65535

+0.00 close(4) =3D 0
+0.01 >[noecn] F.  17001:17001(0) ack 1
+0.03 <[noecn] F.      1:1(0) ack 17002 win 65535
+0.01 >[noecn] .   17002:17002(0) ack 2

```

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-253464-227>