Page MenuHomeFreeBSD

Mitigate a case where TCP rack can send an extra ack.
ClosedPublic

Authored by rrs on Mon, Feb 23, 1:55 PM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Mar 1, 3:56 PM
Unknown Object (File)
Sun, Mar 1, 2:23 PM
Unknown Object (File)
Sun, Mar 1, 3:41 AM
Unknown Object (File)
Sun, Mar 1, 3:41 AM
Unknown Object (File)
Sun, Mar 1, 3:40 AM
Unknown Object (File)
Sun, Mar 1, 3:39 AM
Unknown Object (File)
Thu, Feb 26, 2:59 AM
Unknown Object (File)
Wed, Feb 25, 11:29 PM

Details

Reviewers
tuexen
rscheff
Group Reviewers
transport
Summary

Rack will in theory send an extra rate limited ack when we get to a closing state (sending a FIN) so that
if we have only 1 packet outstanding we might encourage the connection to close out. However it does this
always which is not always wise. Change it so that it only does that if its been more than an srtt since
we have had some activity i.e. a send or a receive of a packet.

Test Plan

This little pkt-drill script will fail without the patch but will pass once we
get the prevention in place. It makes it so two extra acks are not sent
at close() (one for the close call and one for the disconnect() that happens under
the covers)

Without this patch the following packetdrill scripts passes:

--ip_version=ipv4
--mtu=16384

 0.000 `kldload -n tcp_rack cc_htcp`
+0.000 `sysctl -w net.inet.tcp.sack.enable=1`
+0.000 `sysctl -w net.inet.tcp.ecn.enable=3`
+0.000 `sysctl -w net.inet.tcp.hostcache.purgenow=1`

+0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.000 setsockopt(3, IPPROTO_TCP, TCP_FUNCTION_BLK, {function_set_name="rack",
                                                     pcbcnt=0}, 36) = 0
+0.000 setsockopt(3, IPPROTO_TCP, TCP_CONGESTION, "htcp", 4) = 0
+0.000 bind(3, ..., ...) = 0
+0.000 listen(3, 1) = 0
+0.000 < SEWA     0:0(0)                win 65535 <mss 16344,sackOK,eol,eol>
+0.000 > SW.      0:0(0)       ack    1 win 65535 <mss 16344,sackOK,eol,eol>
+0.050 <   .2     1:1(0)       ack    1 win 65535
+0.000 accept(3, ..., ...) = 4
+0.000 setsockopt(4, IPPROTO_TCP, TCP_LOG, [4], 4) = 0
+0.000 close(3) = 0
+0.100 send(4, ..., 8192, 0) = 8192 
+0.000 >  P.5     1:8193(8192) ack    1 win 65535
+0.050 <   .      1:1(0)       ack 8193 win 32000
+0.100 send(4, ..., 1038, 0) = 1038 
+0.000 close(4) = 0
+0.000 >  P.5  8193:9231(1038) ack    1 win 65535
+0.002 >   .5  8192:8192(0)    ack    1 win 65535 // XXX
+0.050 <  F.5     1:1(0)       ack 9231 win 32000 
+0.000 >  F.5  9231:9231(0)    ack    2 win 65535
+0.050 <   .5     2:2(0)       ack 9232 win 32000

With this patch, the behavior is:

--ip_version=ipv4
--mtu=16384

 0.000 `kldload -n tcp_rack cc_htcp`
+0.000 `sysctl -w net.inet.tcp.rfc1323=1`
+0.000 `sysctl -w net.inet.tcp.blackhole=0`
+0.000 `sysctl -w net.inet.tcp.sack.enable=1`
+0.000 `sysctl -w net.inet.tcp.ecn.enable=3`
+0.000 `sysctl -w net.inet.tcp.rexmit_slop=200`
+0.000 `sysctl -w net.inet.tcp.rexmit_drop_options=0`
+0.000 `sysctl -w net.inet.tcp.hostcache.purgenow=1`

+0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.000 setsockopt(3, IPPROTO_TCP, TCP_FUNCTION_BLK, {function_set_name="rack",
                                                     pcbcnt=0}, 36) = 0
+0.000 setsockopt(3, IPPROTO_TCP, TCP_CONGESTION, "htcp", 4) = 0
+0.000 bind(3, ..., ...) = 0
+0.000 listen(3, 1) = 0
+0.000 < SEWA     0:0(0)                win 65535 <mss 16344,sackOK,eol,eol>
+0.000 > SW.      0:0(0)       ack    1 win 65535 <mss 16344,sackOK,eol,eol>
+0.000 <   .2     1:1(0)       ack    1 win 65535
+0.000 accept(3, ..., ...) = 4
+0.000 setsockopt(4, IPPROTO_TCP, TCP_LOG, [4], 4) = 0
+0.000 close(3) = 0
+0.100 send(4, ..., 8192, 0) = 8192 
+0.000 >  P.5     1:8193(8192) ack    1 win 65535
+0.000 <   .      1:1(0)       ack 8193 win 32000
+0.100 send(4, ..., 1038, 0) = 1038 
+0.000 close(4) = 0
+0.000 >  P.5  8193:9231(1038) ack    1 win 65535
+0.000 <  F.5     1:1(0)       ack 9231 win 32000 
+0.000 >  F.5  9231:9231(0)    ack    2 win 65535
+0.000 <   .5     2:2(0)       ack 9232 win 32000

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

rrs requested review of this revision.Mon, Feb 23, 1:55 PM

I added a script which show the behavior before the patch. I also cleaned up the formatting of the script showing the behavior after the script.

rscheff added a subscriber: rscheff.

Reducing the number of challenge ACKs when closing out the connection makes sense.

This revision is now accepted and ready to land.Mon, Feb 23, 5:07 PM

And I have found the case where we are getting the initial ack that causes the ack-war beginning.. not the
src of the continued ack-war (thats in tcp_timewait) but the initial extra ack :)

This revision now requires review to proceed.Mon, Feb 23, 5:43 PM

Fix the compile bug and get the tested code in.

This revision is now accepted and ready to land.Tue, Feb 24, 3:28 PM