Page MenuHomeFreeBSD

[tcp] Fix ECN on finalizing sessions.
ClosedPublic

Authored by rscheff on Tue, Apr 6, 9:56 PM.

Details

Summary

A subtle oversight would leak information, if a
local session is in the process of being shut
down, as that TCP state transition would be
observable well ahead of the actual transmission
of the FIN.

This would also subtly change new data packet
markings and thereby possibly the treatment of
those by the network (loss rather than marking).

This was found while investigating PR 254725, but
is unrelated to the issue there.

MFC after: 3 days

Test Plan

'''

// Create a listening TCP socket.
0.50 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.005 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.005 setsockopt(3, SOL_SOCKET, SO_DEBUG, [1], 4) = 0
+0.005 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [1048576], 4) = 0
+0.005 bind(3, ..., ...) = 0
+0.005 listen(3, 1) = 0

// Establish a TCP connection with ECN to explicitly track CWR

+0.035 < SEW 0:0(0) win 65535 <mss 1012, sackOK, wscale 10, nop, TS val 1 ecr 0>
+0.000 > SE. 0:0(0) ack 1 win 65535 <mss 1460,nop,wscale 6,sackOK,TS val -1 ecr 1>
+0.000 < . 1:1(0) ack 1 win 65535 <nop,nop,TS val 2 ecr -1>
+0.000 accept(3, ..., ...) = 4
+0 %{
print("\t\tcwnd\tssthresh\n")
print("initial window:\t{}\t{}".format(tcpi_snd_cwnd, tcpi_snd_ssthresh))
if (tcpi_snd_cwnd != 10000):

print("Error - Initial Window after 3WHS is not equal 10 MSS")

assert tcpi_snd_cwnd == 10000
}%

// First, send IW plus 1 segment, drop 2nd packet to pull ssthresh low
0.700 write(4, ..., 15000) = 15000

+0 > . 1:1001(1000) ack 1 <nop,nop,TS val -2 ecr 2>
+0 %{ print("window at data:\t{}\t{}".format(tcpi_snd_cwnd, tcpi_snd_ssthresh))
if (tcpi_snd_cwnd != 10000):

print("Error - Initial Window not equal to 10 MSS!")

assert tcpi_snd_cwnd == 10000
}%
+0 > . 1001:2001(1000) ack 1 <nop,nop,TS val -3 ecr 2>
+0 > . 2001:3001(1000) ack 1 <nop,nop,TS val -4 ecr 2>
+0 > . 3001:4001(1000) ack 1 <nop,nop,TS val -5 ecr 2>
+0 > . 4001:5001(1000) ack 1 <nop,nop,TS val -6 ecr 2>
+0 > . 5001:6001(1000) ack 1 <nop,nop,TS val -7 ecr 2>
+0 > . 6001:7001(1000) ack 1 <nop,nop,TS val -8 ecr 2>
+0 > . 7001:8001(1000) ack 1 <nop,nop,TS val -9 ecr 2>
+0 > . 8001:9001(1000) ack 1 <nop,nop,TS val -10 ecr 2>
+0 > . 9001:10001(1000) ack 1 <nop,nop,TS val -11 ecr 2>
// 1st RTO after 230 msec
+0.22~+0.24 > . 1:1001(1000) ack 1 <nop,nop,TS val -12 ecr 2>
+0 %{ print("after RTO:\t{}\t{}".format(tcpi_snd_cwnd, tcpi_snd_ssthresh))
if (tcpi_snd_cwnd > 1000):

print("Error - Window after RTO larger than 1 MSS!")

assert tcpi_snd_cwnd == 1000
}%

Shutdown the session for the FIN
+0 shutdown(4, SHUT_WR) = 0
+0 %{print("tcp state")}%
Ack the initial packet
+0 < . 1:1(0) ack 1001 win 65535 <nop,nop,TS val 3 ecr -2>
+0 %{ print("after ACK:\t{}\t{}".format(tcpi_snd_cwnd, tcpi_snd_ssthresh))
if (tcpi_snd_cwnd < 11000):

print("Error - Window after ACK smaller than 11 MSS!")

assert tcpi_snd_cwnd >= 11000
}%
+0.0 > . 10001:11001(1000) ack 1 <nop,nop,TS val -13 ecr 3> CWR missing with shutdown
+0.0 > W. 10001:11001(1000) ack 1 <nop,nop,TS val -13 ecr 3>
+0.0 > . 11001:12001(1000) ack 1 <nop,nop,TS val -14 ecr 3>

'''

Diff Detail

Repository
R10 FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.