Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
TEST_INCLUDES := \
defaults.sh \
ksft_runner.sh \
set_sysctls.py \
../../kselftest/ktap_helpers.sh \
# end of TEST_INCLUDES
TEST_PROGS := $(wildcard *.pkt)
include ../../lib.mk
@@ -0,0 +1,11 @@
CONFIG_HZ=1000
CONFIG_HZ_1000=y
CONFIG_IPV6=y
CONFIG_NET_NS=y
CONFIG_NET_SCH_FIFO=y
CONFIG_NET_SCH_FQ=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYN_COOKIES=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_MD5SIG=y
CONFIG_TUN=y
@@ -0,0 +1,64 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Set standard production config values that relate to TCP behavior.
# Flush old cached data (fastopen cookies).
ip tcp_metrics flush all > /dev/null 2>&1
# TCP min, default, and max receive and send buffer sizes.
sysctl -q net.ipv4.tcp_rmem="4096 540000 $((15*1024*1024))"
sysctl -q net.ipv4.tcp_wmem="4096 $((256*1024)) 4194304"
# TCP timestamps.
sysctl -q net.ipv4.tcp_timestamps=1
# TCP SYN(ACK) retry thresholds
sysctl -q net.ipv4.tcp_syn_retries=5
sysctl -q net.ipv4.tcp_synack_retries=5
# TCP Forward RTO-Recovery, RFC 5682.
sysctl -q net.ipv4.tcp_frto=2
# TCP Selective Acknowledgements (SACK)
sysctl -q net.ipv4.tcp_sack=1
# TCP Duplicate Selective Acknowledgements (DSACK)
sysctl -q net.ipv4.tcp_dsack=1
# TCP FACK (Forward Acknowldgement)
sysctl -q net.ipv4.tcp_fack=0
# TCP reordering degree ("dupthresh" threshold for entering Fast Recovery).
sysctl -q net.ipv4.tcp_reordering=3
# TCP congestion control.
sysctl -q net.ipv4.tcp_congestion_control=cubic
# TCP slow start after idle.
sysctl -q net.ipv4.tcp_slow_start_after_idle=0
# TCP RACK and TLP.
sysctl -q net.ipv4.tcp_early_retrans=4 net.ipv4.tcp_recovery=1
# TCP method for deciding when to defer sending to accumulate big TSO packets.
sysctl -q net.ipv4.tcp_tso_win_divisor=3
# TCP Explicit Congestion Notification (ECN)
sysctl -q net.ipv4.tcp_ecn=0
sysctl -q net.ipv4.tcp_pacing_ss_ratio=200
sysctl -q net.ipv4.tcp_pacing_ca_ratio=120
sysctl -q net.ipv4.tcp_notsent_lowat=4294967295 > /dev/null 2>&1
sysctl -q net.ipv4.tcp_fastopen=0x3
# Use TFO_COOKIE in ksft_runner.sh for this key.
sysctl -q net.ipv4.tcp_fastopen_key=a1a1a1a1-b2b2b2b2-c3c3c3c3-d4d4d4d4
sysctl -q net.ipv4.tcp_syncookies=1
# Override the default qdisc on the tun device.
# Many tests fail with timing errors if the default
# is FQ and that paces their flows.
tc qdisc add dev tun0 root pfifo
@@ -0,0 +1,71 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source "$(dirname $(realpath $0))/../../kselftest/ktap_helpers.sh"
declare -A ip_args=(
[ipv4]="--ip_version=ipv4
--local_ip=192.168.0.1
--gateway_ip=192.168.0.1
--netmask_ip=255.255.0.0
--remote_ip=192.0.2.1
-D TFO_COOKIE=3021b9d889017eeb
-D TFO_COOKIE_ZERO=b7c12350a90dc8f5
-D CMSG_LEVEL_IP=SOL_IP
-D CMSG_TYPE_RECVERR=IP_RECVERR"
[ipv4-mapped-ipv6]="--ip_version=ipv4-mapped-ipv6
--local_ip=192.168.0.1
--gateway_ip=192.168.0.1
--netmask_ip=255.255.0.0
--remote_ip=192.0.2.1
-D TFO_COOKIE=3021b9d889017eeb
-D TFO_COOKIE_ZERO=b7c12350a90dc8f5
-D CMSG_LEVEL_IP=SOL_IPV6
-D CMSG_TYPE_RECVERR=IPV6_RECVERR"
[ipv6]="--ip_version=ipv6
--mtu=1520
--local_ip=fd3d:0a0b:17d6::1
--gateway_ip=fd3d:0a0b:17d6:8888::1
--remote_ip=fd3d:fa7b:d17d::1
-D TFO_COOKIE=c1d1e9742a47a9bc
-D TFO_COOKIE_ZERO=82af1a8f9a205c34
-D CMSG_LEVEL_IP=SOL_IPV6
-D CMSG_TYPE_RECVERR=IPV6_RECVERR"
)
if [ $# -ne 1 ]; then
ktap_exit_fail_msg "usage: $0 <script>"
exit "$KSFT_FAIL"
fi
script="$(basename $1)"
if [ -z "$(which packetdrill)" ]; then
ktap_skip_all "packetdrill not found in PATH"
exit "$KSFT_SKIP"
fi
declare -a optargs
failfunc=ktap_test_fail
if [[ -n "${KSFT_MACHINE_SLOW}" ]]; then
optargs+=('--tolerance_usecs=14000')
failfunc=ktap_test_xfail
fi
ip_versions=$(grep -E '^--ip_version=' $script | cut -d '=' -f 2)
if [[ -z $ip_versions ]]; then
ip_versions="ipv4 ipv6 ipv4-mapped-ipv6"
elif [[ ! "$ip_versions" =~ ^ipv[46]$ ]]; then
ktap_exit_fail_msg "Too many or unsupported --ip_version: $ip_versions"
exit "$KSFT_FAIL"
fi
ktap_print_header
ktap_set_plan $(echo $ip_versions | wc -w)
for ip_version in $ip_versions; do
unshare -n packetdrill ${ip_args[$ip_version]} ${optargs[@]} $script > /dev/null \
&& ktap_test_pass $ip_version || $failfunc $ip_version
done
ktap_finished
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
"""Sets sysctl values and writes a file that restores them.
The arguments are of the form "<proc-file>=<val>" separated by spaces.
The program first reads the current value of the proc-file and creates
a shell script named "/tmp/sysctl_restore_${PACKETDRILL_PID}.sh" which
restores the values when executed. It then sets the new values.
PACKETDRILL_PID is set by packetdrill to the pid of itself, so a .pkt
file could restore sysctls by running `/tmp/sysctl_restore_${PPID}.sh`
at the end.
"""
import os
import subprocess
import sys
filename = '/tmp/sysctl_restore_%s.sh' % os.environ['PACKETDRILL_PID']
# Open file for restoring sysctl values
restore_file = open(filename, 'w')
print('#!/bin/bash', file=restore_file)
for a in sys.argv[1:]:
sysctl = a.split('=')
# sysctl[0] contains the proc-file name, sysctl[1] the new value
# read current value and add restore command to file
cur_val = subprocess.check_output(['cat', sysctl[0]], universal_newlines=True)
print('echo "%s" > %s' % (cur_val.strip(), sysctl[0]), file=restore_file)
# set new value
cmd = 'echo "%s" > %s' % (sysctl[1], sysctl[0])
os.system(cmd)
os.system('chmod u+x %s' % filename)
@@ -0,0 +1,24 @@
// 3rd ACK + 1st data segment lost, data segments with ce
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0.05 < SEWA 0:0(0) win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// 3rd ACK lost
// 1st data segment lost
+0.05 < [ce] EAP. 1001:2001(1000) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] WA. 1:1(0) ack 1 <ECN e1b 1 ceb 1000 e0b 1,nop,nop,nop,sack 1001:2001>
+.002 accept(3, ..., ...) = 4
+0.2 < [ce] EAP. 1:1001(1000) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.001 > [ect0] EWA. 1:1(0) ack 2001 <ECN e1b 1 ceb 2000 e0b 1,nop>
+0.05 < [ce] EAP. 2001:3001(1000) ack 1 win 264
+.001 > [ect0] . 1:1(0) ack 3001 <ECN e1b 1 ceb 3000 e0b 1,nop>
@@ -0,0 +1,30 @@
// 3rd ACK + 1st data segment lost, 2nd data segments with ce
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] SW. 0:0(0) ack 1 win 32767 <mss 1016,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
// 3rd ACK lost
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 write(4, ..., 2000) = 2000
// 1st data segment lost + 2nd gets CE
+.002 > [ect0] .5 1:1005(1004) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.000 > [ect0] P.5 1005:2001(996) ack 1 <ECN e1b 1 ceb 0 e0b 1, nop>
+0.05 < [ect0] .6 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 996 e1b 1,nop,nop,nop,sack 1005:2001>
+0.01 %{ assert tcpi_delivered_ce == 1, tcpi_delivered_ce }%
+0.002~+0.1 > [ect0] .5 1:1005(1004) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.05 < [ect0] .6 1:1(0) ack 2001 win 264 <ECN e0b 1005 ceb 996 e1b 1,nop>
+0.01 write(4, ..., 1000) = 1000
+0~+0.002 > [ect0] P.5 2001:3001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.1 < [ect0] .5 1:1001(1000) ack 3001 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+0~+0.01 > [ect0] .5 3001:3001(0) ack 1001 <ECN e1b 1 ceb 0 e0b 1001,nop>
@@ -0,0 +1,19 @@
// Test 3rd ACK flags when SYN-ACK is rexmitted
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.1 < [ect0] S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Our code currently sends a challenge ACK
// when it receives a SYN in ESTABLISHED state
// based on the latest SYN
+.002 > [ect0] A. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,18 @@
// Third ACK CE increases r.cep
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0.05 < SEWA 0:0(0) win 32767 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ce] W. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] WAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,22 @@
// 3rd ACK lost, CE for the first data segment
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0.05 < SEWA 0:0(0) win 32767 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// 3rd ACK lost
+0.05 < [ce] EAP. 1:1001(1000) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] WA. 1:1(0) ack 1001 <ECN e1b 1 ceb 1000 e0b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.05 < [ce] EAP. 1001:2001(1000) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.001 > [ect0] EWA. 1:1(0) ack 2001 <ECN e1b 1 ceb 2000 e0b 1 ,nop>
@@ -0,0 +1,26 @@
// Test SYN/ACK rexmit triggered 3rd ACK duplicate + CE on first data seg
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// SYN/ACK rexmitted => two 3rd ACKs in-flight
+1.0~+1.1 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Delivered 1st 3rd ACK
+0.05 < [ect0] W. 1:1(0) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
// Duplicate 3rd ACK delivered
+1.05 < [ect0] W. 1:1(0) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+0.05 < [ce] EAP. 1:1001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] WA. 1:1(0) ack 1001 <ECN e1b 1 ceb 1000 e0b 1,nop>
+0 read(4, ..., 1000) = 1000
@@ -0,0 +1,13 @@
// Test that when accurate ECN is disabled,
// client uses RFC3168 ECN for SYN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=1
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEW 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] S. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,nop,nop,nop,wscale 8>
+.002 > [noecn] . 1:1(0) ack 1
@@ -0,0 +1,28 @@
// Test that SYN-ACK with ACE flags and without
// ACE flags got dropped. Although we disable ECN,
// we shouldn't consider this as blackholed as
// these are dropped due to congestion
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [ect0] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SA. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN
+0.1 < [noecn] S 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.1 < [noecn] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
// Write with AccECN option but with ip-noecn since we received one SYN with ACE=0
+0.01 write(4, ..., 100) = 100
+.002 > [noecn] P5. 1:101(100) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,18 @@
// Test AccECN -> RFC3168 fallback when sysctl asks for RFC3168 ECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=1
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SE. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < . 1:1(0) ack 1 win 320
+.002 accept(3, ..., ...) = 4
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] P. 1:1001(1000) ack 1
@@ -0,0 +1,34 @@
// Client negotiates AccECN and starts sending
// AccECN option in last ACK and data segments
// Middlebox drops AccECN option and client
// reverts to ACE flags only
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
sysctl -q net.ipv4.tcp_ecn_option_beacon=1
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.05 < [ect0] EAP. 1:1001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EA. 1:1(0) ack 1001 <ECN e1b 1 ceb 0 e0b 1001,nop>
+0 read(4, ..., 1000) = 1000
+0.05 < [ect0] EAP. 1:1001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EA. 1:1(0) ack 1001 <ECN e1b 1 ceb 0 e0b 2001,nop,nop,nop,sack 1:1001>
+0.05 < [ect0] EAP. 1:1001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EA. 1:1(0) ack 1001 <nop,nop,sack 1:1001>
+0.05 < [ect0] EAP. 1001:2001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EA. 1:1(0) ack 2001
+0 read(4, ..., 1000) = 1000
@@ -0,0 +1,38 @@
// Client negotiates AccECN and starts sending
// AccECN option in last ACK and data segments
// Middlebox accepts AccECN option but some packets
// are lost due to congestion. Client should
// continue to send AccECN option
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.102 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.1 < [ect0] SW. 0:0(0) ack 1 win 32767 <mss 1024,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] A. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Send
+0.01 write(4, ..., 3000) = 3000
+.002 > [ect0] .5 1:1013(1012) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.002 > [ect0] P.5 1013:2025(1012) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.002 > [ect0] P.5 2025:3001(976) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// First two segments were lost due to congestion as SACK was
// received acknowledging 3rd segment
+0.1 < [ect0] .5 1:1(0) ack 1 win 264 <ECN e1b 1 ceb 0 e0b 977,nop,nop,nop,sack 2025:3001>
// Since data with option was SACKed, we can
// continue to use AccECN option for the rest of
// the connection. This one is a rexmt
+.02~+0.5 > [ect0] .5 1:1013(1012) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.1 < [ect0] .5 1:1(0) ack 3001 win 264 <ECN e1b 1 ceb 0 e0b 3000,nop>
// Send new data, it should contain AccECN option
+0.01 write(4, ..., 2000) = 2000
+.002 > [ect0] .5 3001:4013(1012) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.002 > [ect0] P.5 4013:5001(988) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,12 @@
// AccECN sysctl server-side only, no ECN/AccECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=5
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < S. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,nop,nop,nop,wscale 8>
+.002 > . 1:1(0) ack 1
@@ -0,0 +1,25 @@
// Test basic connection teardown where local process closes first:
// the local process calls close() first, so we send a FIN, and receive an ACK.
// Then we receive a FIN and ACK it.
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+.01...0.011 connect(3, ..., ...) = 0
+0 > [noecn] SEWA 0:0(0) <...>
+0 < [ect1] SW. 0:0(0) ack 1 win 32768 <mss 1000,nop,wscale 6,nop,nop,sackOK>
+0 > [ect0] EW. 1:1(0) ack 1
+0 write(3, ..., 1000) = 1000
+0 > [ect0] P5. 1:1001(1000) ack 1
+0 < [ect0] .5 1:1(0) ack 1001 win 257
+0 close(3) = 0
+0 > [ect0] F5. 1001:1001(0) ack 1
+0 < [ect0] .5 1:1(0) ack 1002 win 257
+0 < [ect0] F5. 1:1(0) ack 1002 win 257
+0 > [ect0] . 1002:1002(0) ack 2
@@ -0,0 +1,25 @@
// Test a large ACK (> ACE field max)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 14600) = 14600
+.002 > [ect0] P.5 1:14601(14600) ack 1
+0.05 < [ect0] .5 1:1(0) ack 1461 win 264
+0.05 < [ect0] .5 1:1(0) ack 14601 win 264
+0.01 %{ assert tcpi_delivered_ce == 8, tcpi_delivered_ce }%
@@ -0,0 +1,31 @@
// Test false overflow detection with option used to rule out overflow
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
// Stop sending option to allow easier testing
+0 `sysctl -q net.ipv4.tcp_ecn_option=0`
+0.002 write(4, ..., 14600) = 14600
+.002 > [ect0] P.5 1:14601(14600) ack 1
+0.05 < [ect0] .5 1:1(0) ack 1460 win 264 <ECN e0b 1461 ceb 0 e1b 1,nop>
+0.05 < [ect0] .5 1:1(0) ack 14601 win 264 <ECN e0b 14601 ceb 0 e1b 1,nop>
+0.01 %{
assert tcpi_delivered_ce == 0, tcpi_delivered_ce
assert tcpi_delivered_e0_bytes == 14600, tcpi_delivered_e0_bytes
}%
@@ -0,0 +1,24 @@
// Test a large ACK (> ACE field max)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 14600) = 14600
+.002 > [ect0] P.5 1:14601(14600) ack 1
+0.05 < [ect0] .5 1:1(0) ack 14601 win 264
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,25 @@
// Test a large ACK (> ACE field max)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 14600) = 14600
+.002 > [ect0] P.5 1:14601(14600) ack 1
// Fake CE
+0.05 < [ect0] .6 1:1(0) ack 14601 win 264
+0.01 %{ assert tcpi_delivered_ce == 1, tcpi_delivered_ce }%
@@ -0,0 +1,25 @@
// Test a large ACK (at ACE field max delta)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 14600) = 14600
+.002 > [ect0] P.5 1:14601(14600) ack 1
// Fake CE
+0.05 < [ect0] .4 1:1(0) ack 14601 win 264
+0.01 %{ assert tcpi_delivered_ce == 7, tcpi_delivered_ce }%
@@ -0,0 +1,70 @@
// Test basic AccECN CEP/CEB/E0B/E1B functionality & CEP wrapping
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{
assert tcpi_delivered_ce == 0, tcpi_delivered_ce
assert tcpi_delivered_ce_bytes == 0, tcpi_delivered_ce_bytes
}%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake CE
+0.05 < [ect0] WA. 1:1(0) ack 1001 win 264 <ECN e0b 1 ceb 1000 e1b 1,nop>
+0.01 %{
assert tcpi_delivered_ce == 1, tcpi_delivered_ce
assert tcpi_delivered_ce_bytes == 1000, tcpi_delivered_ce_bytes
}%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake ect0
+0.05 < [ect0] WA. 1:1(0) ack 2001 win 264 <ECN e0b 1001 ceb 1000 e1b 1,nop>
+0.01 %{
assert tcpi_delivered_ce == 1, tcpi_delivered_ce
assert tcpi_delivered_e0_bytes == 1000, tcpi_delivered_e0_bytes
}%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 2001:3001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake ce
+0.05 < [ect0] EWA. 1:1(0) ack 3001 win 264 <ECN e0b 1001 ceb 2000 e1b 1,nop>
+0.01 %{
assert tcpi_delivered_ce == 2, tcpi_delivered_ce
assert tcpi_delivered_ce_bytes == 2000, tcpi_delivered_ce_bytes
}%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 3001:4001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake ect1
+0.05 < [ect0] EWA. 1:1(0) ack 4001 win 264 <ECN e0b 1001 ceb 2000 e1b 1001,nop>
+0.01 %{
assert tcpi_delivered_ce == 2, tcpi_delivered_ce
assert tcpi_delivered_e1_bytes == 1000, tcpi_delivered_e1_bytes
}%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 4001:5001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake ce
+0.05 < [ect0] . 1:1(0) ack 5001 win 264 <ECN e0b 1001 ceb 3000 e1b 1001,nop>
+0.01 %{
assert tcpi_delivered_ce == 3, tcpi_delivered_ce
assert tcpi_delivered_ce_bytes == 3000, tcpi_delivered_ce_bytes
}%
@@ -0,0 +1,12 @@
// Test that tcp_ecn=4 uses RFC3168 ECN for SYN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=4
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.05 connect(4, ..., ...) = 0
+.002 > SEW 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > . 1:1(0) ack 1
@@ -0,0 +1,35 @@
// Test basic AccECN CEP/CEB/E0B/E1B functionality & CEP wrapping
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.05 < [ce] EAP. 1:1001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] WA. 1:1(0) ack 1001 <ECN e1b 1 ceb 1000 e0b 1,nop>
+0 read(4, ..., 1000) = 1000
+0.05 < [ect0] EAP. 1001:2001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] WA. 1:1(0) ack 2001 <ECN e1b 1 ceb 1000 e0b 1001,nop>
+0 read(4, ..., 1000) = 1000
+0.05 < [ce] EAP. 2001:3001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EWA. 1:1(0) ack 3001 <ECN e1b 1 ceb 2000 e0b 1001,nop>
+0 read(4, ..., 1000) = 1000
+0.05 < [ect1] EAP. 3001:4001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] EWA. 1:1(0) ack 4001 <ECN e1b 1001 ceb 2000 e0b 1001,nop>
+0 read(4, ..., 1000) = 1000
+0.05 < [ce] EAP. 4001:5001(1000) ack 1 win 257 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] . 1:1(0) ack 5001 <ECN e1b 1001 ceb 3000 e0b 1001,nop>
+0 read(4, ..., 1000) = 1000
@@ -0,0 +1,14 @@
// Test IP flags drop
--tolerance_usecs=50000
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 1.1 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.02 ~ +1.1 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] . 1:1(0) ack 1
@@ -0,0 +1,16 @@
// SYN/ACK option drop test
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.02 ~+2 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.02 ~+5 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.02 ~+8 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
@@ -0,0 +1,28 @@
// Test that SYN-ACK with ACE flags and without
// ACE flags got dropped. Although we disable ECN,
// we shouldn't consider this as blackholed as
// these are dropped due to congestion
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [noecn] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN-ACK without option
+1~+1.1 > [noecn] SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// SYN-ACK maybe getting blackholed, disable ECN
+2~+2.2 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+4~+4.4 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Received an ACK after sending 3rd retransmission, not a blackhole
+0.1 < [noecn] . 1:1(0) ack 1 win 320
+.002 accept(3, ..., ...) = 4
@@ -0,0 +1,18 @@
// Test that SYN with ACE flags and without
// ACE flags got dropped. Although we disable
// ECN, we shouldn't consider this as blackholed
// as these are dropped due to congestion
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 3.1 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.02~+1.1 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.02~+1.1 > [noecn] S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.02~+1.1 > [noecn] S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.1 < [noecn] S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0~+0.01 > [noecn] . 1:1(0) ack 1
@@ -0,0 +1,23 @@
// Test AccECN flags bleach
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] . 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [noecn] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < [ect0] EAP. 1:1(0) ack 1001 win 320
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,23 @@
// Test basic AccECN negotiation
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+.05 < [ect0] EAP. 1:1(0) ack 1001 win 256 <ECN e0b 1001 ceb 0 e1b 0,nop>
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,26 @@
// Test basic AccECN negotiation
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < [ect0] EAP. 1:1(0) ack 1001 win 320
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,23 @@
// Test basic AccECN negotiation without option
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < SW. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1
+.05 < [ect0] EAP. 1:1(0) ack 1001 win 256
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,23 @@
// Test basic AccECN negotiation, late option enable
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < SW. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1
+.05 < [ect0] EAP. 1:1(0) ack 1001 win 256 <ECN e0b 1001 ceb 0 e1b 1,nop>
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,20 @@
// Test client behavior on receiving a non ECN SYN-ACK
// after receiving an AccECN SYN-ACK and moving to
// ESTABLISHED state
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
// Receive an AccECN SYN-ACK and move to ESTABLISHED
+0.05 < [noecn] SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Receive a non ECN SYN-ACK and send a challenge ACK with ACE feedback
+0.1 < [noecn] S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,27 @@
// Test basic AccECN negotiation with option off using sysctl
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1
+0.05 < [ect0] EAP. 1:1(0) ack 1001 win 320
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1001:2001(1000) ack 1
@@ -0,0 +1,27 @@
// Test no progress filtering
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
// Fake CE and claim no progress
+0.05 < [ect0] WA. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 1000 e1b 1,nop>
+0.01 %{
assert tcpi_delivered_ce == 0, tcpi_delivered_ce
assert tcpi_delivered_ce_bytes == 0, tcpi_delivered_ce_bytes
}%
@@ -0,0 +1,28 @@
// Test that SYN-ACK with ACE flags and without
// ACE flags got dropped. Although we disable ECN,
// we shouldn't consider this as blackholed as
// these are dropped due to congestion
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [noecn] S 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN
+0.1 < [ect0] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.1 < [noecn] . 1:1(0) ack 1 win 320
+.002 accept(3, ..., ...) = 4
// Write with AccECN option but with ip-noecn since we received one SYN with ACE=0
+0.01 write(4, ..., 100) = 100
+.002 > [noecn] P. 1:101(100) ack 1
@@ -0,0 +1,18 @@
// Test RFC3168 fallback when sysctl asks for AccECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEW 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SE. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < . 1:1(0) ack 1 win 320
+.002 accept(3, ..., ...) = 4
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] P. 1:1001(1000) ack 1
@@ -0,0 +1,18 @@
// Test RFC3168 ECN when sysctl asks for RFC3168 ECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=1
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEW 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SE. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.05 < . 1:1(0) ack 1 win 320
+.002 accept(3, ..., ...) = 4
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] P. 1:1001(1000) ack 1
@@ -0,0 +1,28 @@
// Test SACK space grab to fit AccECN option
--tcp_ts_tick_usecs=1000
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+.01 < [ect1] EAP. 1001:2001(1000) ack 1 win 264
+0.002 > [ect0] EA. 1:1(0) ack 1 <ECN e1b 1001 ceb 0 e0b 1,nop,nop,nop,sack 1001:2001>
+.01 < [ect0] EAP. 3001:4001(1000) ack 1 win 264
+0.002 > [ect0] EA. 1:1(0) ack 1 <ECN e1b 1001 ceb 0 e0b 1001,nop,nop,nop,sack 3001:4001 1001:2001>
+.01 < [ce] EAP. 5001:6001(1000) ack 1 win 264
+0.002 > [ect0] WA. 1:1(0) ack 1 <ECN e1b 1001 ceb 1000 e0b 1001,nop,nop,nop,sack 5001:6001 3001:4001 1001:2001>
// DSACK works?
+.01 < [ect0] EAP. 5001:6001(1000) ack 1 win 264
+0.002 > [ect0] WA. 1:1(0) ack 1 <ECN e1b 1001 ceb 1000 e0b 2001,nop,nop,nop,sack 5001:6001 5001:6001 3001:4001>
+.01 < [ect1] EAP. 6001:7001(1000) ack 1 win 264
+0.002 > [ect0] WA. 1:1(0) ack 1 <ECN e1b 2001 ceb 1000 e0b 2001,nop,nop,nop,sack 5001:7001 3001:4001 1001:2001>
@@ -0,0 +1,39 @@
// Test SACK space grab to fit AccECN option
--tcp_ts_tick_usecs=1000
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,sackOK,TS val 1 ecr 0,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 1,ECN e1b 1 ceb 0 e0b 1,nop,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <nop,nop,TS val 2 ecr 100,ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
// One SACK block should allow all 3 AccECN fields:
+.01 < [ect1] EAP. 1001:2001(1000) ack 1 win 264 <nop,nop,TS val 3 ecr 100>
+0.002 > [ect0] EA. 1:1(0) ack 1 <nop,nop,TS val 160 ecr 2,ECN e1b 1001 ceb 0 e0b 1,nop,nop,nop,sack 1001:2001>
// Two SACK blocks should fit w/ AccECN if we only need to use 2 AccECN fields: check ect1 arriving.
+.01 < [ect1] EAP. 3001:4001(1000) ack 1 win 264 <nop,nop,TS val 4 ecr 100>
+0.002 > [ect0] EA. 1:1(0) ack 1 <nop,nop,TS val 172 ecr 2,ECN e1b 2001 ceb 0,nop,nop,sack 3001:4001 1001:2001>
// Two SACK blocks should fit w/ AccECN if we only need to use 2 AccECN fields: check CE arriving.
+.01 < [ce] EAP. 5001:6001(1000) ack 1 win 264 <nop,nop,TS val 5 ecr 100>
+0.002 > [ect0] WA. 1:1(0) ack 1 <nop,nop,TS val 184 ecr 2,ECN e1b 2001 ceb 1000,nop,nop,sack 5001:6001 3001:4001>
// Check that DSACK works, using 2 SACK blocks in total, if we only need to use 2 AccECN fields: check ect1 arriving.
+.01 < [ect1] EAP. 5001:6001(1000) ack 1 win 264 <nop,nop,TS val 5 ecr 100>
+0.002 > [ect0] WA. 1:1(0) ack 1 <nop,nop,TS val 196 ecr 2,ECN e1b 3001 ceb 1000,nop,nop,sack 5001:6001 5001:6001>
// Check the case where the AccECN option doesn't fit, because sending ect0
// with order 1 would rquire 3 AccECN fields,
// and TS (12 bytes) + 2 SACK blocks (20 bytes) + 3 AccECN fields (2 + 3*3 bytes) > 40 bytes.
// That's OK; Linux TCP AccECN is optimized for the ECT1 case, not ECT0.
+.01 < [ect0] EAP. 6001:7001(1000) ack 1 win 264 <nop,nop,TS val 5 ecr 100>
+0.002 > [ect0] WA. 1:1(0) ack 1 <nop,nop,TS val 204 ecr 2,nop,nop,sack 5001:7001 3001:4001 1001:2001>
@@ -0,0 +1,20 @@
// Test against classic ECN server
// Not-ECT on SYN and server sets 1|0|1 (AE is unused for classic ECN)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] SEA. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <nop, nop, TS val 200 ecr 700>
+0 write(4, ..., 100) = 100
+.002 > [ect0] P.5 1:101(100) ack 1 <nop,nop,TS val 300 ecr 700>
+0 close(4) = 0
+.002 > [ect0] F.5 101:101(0) ack 1 <nop,nop,TS val 400 ecr 700>
+0.1 < [noecn] R. 1:1(0) ack 102 win 4242
@@ -0,0 +1,20 @@
// Test against classic ECN server
// Not-ECT on SYN and server sets 0|0|1
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] SE. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 8>
+.002 > [noecn] . 1:1(0) ack 1 <nop, nop, TS val 200 ecr 700>
+0 write(4, ..., 100) = 100
+.002 > [ect0] P. 1:101(100) ack 1 <nop,nop,TS val 300 ecr 700>
+0 close(4) = 0
+0 > [noecn] F. 101:101(0) ack 1 <...>
+0.1 < R. 1:1(0) ack 102 win 4242
@@ -0,0 +1,19 @@
// Test against broken server (1|1|1)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] SEWA. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 8>
+.002 > [noecn] . 1:1(0) ack 1 <nop, nop, TS val 200 ecr 700>
+0 write(4, ..., 100) = 100
+.002 > [noecn] P. 1:101(100) ack 1 <nop,nop,TS val 300 ecr 700>
+0 close(4) = 0
+.002 > [noecn] F. 101:101(0) ack 1 <...>
+0.1 < [noecn] R. 1:1(0) ack 102 win 4242
@@ -0,0 +1,19 @@
// Test against Non ECN server (0|0|0)
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [noecn] S. 0:0(0) ack 1 win 32767 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 8>
+.002 > [noecn] . 1:1(0) ack 1 <nop, nop, TS val 200 ecr 700>
+0 write(4, ..., 100) = 100
+.002 > [noecn] P. 1:101(100) ack 1 <nop,nop,TS val 300 ecr 700>
+0 close(4) = 0
+.002 > [noecn] F. 101:101(0) ack 1 <nop,nop,TS val 400 ecr 700>
+0.1 < [noecn] R. 1:1(0) ack 102 win 4242
@@ -0,0 +1,18 @@
// Test AccECN with sysctl set to server-side only
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=5
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,18 @@
// Test that SYN with ACE flags was Acked
// after 2nd retransmission. In this case,
// since we got SYN-ACK that supports Accurate
// ECN, we consider this as successful negotiation
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 2.1 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+1~+1.1 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+1~+1.1 > [noecn] S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.1 < [noecn] SW. 0:0(0) ack 1 win 32767 <mss 1016,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+0~+0.01 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,16 @@
// Test that SYN with ACE flags got dropped
// We retry one more time with ACE and then
// fallback to disabled ECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 2.1 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+1~+1.1 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+1~+1.1 > [noecn] S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.1 < [noecn] S. 0:0(0) ack 1 win 32767 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0~+0.01 > [noecn] . 1:1(0) ack 1
@@ -0,0 +1,27 @@
// Test that SYN-ACK with ACE flags was Acked
// after 2nd retransmission. In this case,
// since we got the last ACK that supports Accurate
// ECN, we consider this as successful negotiation
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [noecn] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN-ACK without option
+1~+1.1 > [noecn] SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// SYN-ACK maybe getting blackholed, disable ECN
+2~+2.2 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Received an ACK with ACE flags, state should be set to negotiation succeeded
+0.1 < [noecn] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
@@ -0,0 +1,26 @@
// Test that SYN-ACK with ACE flags got dropped
// We retry one more time with ACE and then
// fallback to disabled ECN
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [noecn] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN-ACK without option
+1~+1.1 > [noecn] SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// SYN-ACK maybe getting blackholed, disable ECN
+2~+2.2 > [noecn] S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// Received an ACK with no ACE flags, state should be set to blackholed
+0.1 < [noecn] . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
@@ -0,0 +1,13 @@
// Test AccECN ECN field reflector in SYNACK
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [ce] SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SWA. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
@@ -0,0 +1,13 @@
// Test AccECN ECN field reflector in SYNACK
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [ect0] SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SA. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
@@ -0,0 +1,13 @@
// Test AccECN ECN field reflector in SYNACK
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [ect1] SEWA 0:0(0) win 32792 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SEW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
@@ -0,0 +1,27 @@
// Test SYNACK CE & received_ce update
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > [noecn] SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [ce] SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] WA. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 write(4, ..., 100) = 100
+.002 > [ect0] P.6 1:101(100) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < [ect0] P.5 1:101(100) ack 101 win 256 <ECN e0b 101 ceb 0 e1b 1,nop>
+.002 > [ect0] .6 101:101(0) ack 101 <ECN e1b 1 ceb 0 e0b 101,nop>
+0.01 write(4, ..., 100) = 100
+.002 > [ect0] P.6 101:201(100) ack 101 <ECN e1b 1 ceb 0 e0b 101,nop>
+0.1 < [ect1] P.5 201:301(100) ack 201 win 256 <ECN e0b 101 ceb 0 e1b 1,nop>
+.002 > [ect0] .6 201:201(0) ack 101 <ECN e1b 101 ceb 0 e0b 101,nop,nop,nop,sack 201:301>
+0.01 < [ce] .6 401:501(100) ack 201 win 256 <ECN e0b 101 ceb 0 e1b 1,nop>
+.002 > [ect0] .7 201:201(0) ack 101 <ECN e1b 101 ceb 100 e0b 101,nop,nop,nop,sack 401:501 201:301>
@@ -0,0 +1,22 @@
// Reflected SYNACK CE mark increases delivered_ce
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_fallback=0
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0.05 < SEWA 0:0(0) win 32767 <mss 1050,nop,nop,sackOK,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Fake ce for prev, ECT validator must be disabled for this to work
+0.05 < [ect0] WA. 1:1(0) ack 1 win 264 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 1, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,24 @@
// Test SYN=0 reflector
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [ect0] SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] A. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 write(4, ..., 100) = 100
+.002 > [ect0] P.5 1:101(100) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < [ect0] P.5 1:1(0) ack 101 win 256 <ECN e0b 101 ceb 0 e1b 1,nop>
+0.01 < [ect0] P.5 1:101(100) ack 101 win 256 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] .5 101:101(0) ack 101 <ECN e1b 1 ceb 0 e0b 101,nop>
+0 read(4, ..., 100) = 100
+0 close(4) = 0
+0 > F.5 101:101(0) ack 101 <...>
+0.1 < R. 101:101(0) ack 102 win 4242
@@ -0,0 +1,24 @@
// Test SYN=0 reflector
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < [ect1] SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] EW. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.01 write(4, ..., 100) = 100
+.002 > [ect0] P.5 1:101(100) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < [ect1] P.5 1:1(0) ack 101 win 256 <ECN e0b 101 ceb 0 e1b 1,nop>
+0.01 < [ect1] P.5 1:101(100) ack 101 win 256 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 > [ect0] .5 101:101(0) ack 101 <ECN e1b 101 ceb 0 e0b 1,nop>
+0 read(4, ..., 100) = 100
+0 close(4) = 0
+0 > F5. 101:101(0) ack 101 <...>
+0.1 < R. 101:101(0) ack 102 win 4242
@@ -0,0 +1,15 @@
// Test 3rd ACK flags when SYN-ACK is rexmitted
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+.002 ... 0.052 connect(4, ..., ...) = 0
+.002 > SEWA 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+0.05 < SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
+0.05 < SW. 0:0(0) ack 1 win 32767 <mss 1460,ECN e0b 1 ceb 0 e1b 1,nop,nop,nop,sackOK,nop,wscale 8>
+.002 > [ect0] W. 1:1(0) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,25 @@
// Test that we retransmit SYN-ACK with ACE and without
// AccECN options after
// SYN-ACK was lost and TCP moved to TCPS_SYN_RECEIVED
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
sysctl -q net.ipv4.tcp_ecn_option=2
`
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < [noecn] SEWA 0:0(0) win 32792 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.002 > [noecn] SW. 0:0(0) ack 1 <mss 1460,ECN e1b 1 ceb 0 e0b 1,nop,nop,nop,sackOK,nop,wscale 8>
// Retransmit SYN-ACK without option
+1~+1.1 > [noecn] SW. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0.1 < [noecn] W. 1:1(0) ack 1 win 320 <ECN e0b 1 ceb 0 e1b 1,nop>
+.002 accept(3, ..., ...) = 4
// We try to write with AccECN option
+0.01 write(4, ..., 100) = 100
+.002 > [ect0] P5. 1:101(100) ack 1 <ECN e1b 1 ceb 0 e0b 1,nop>
@@ -0,0 +1,26 @@
// Test TS progress filtering
--tcp_ts_tick_usecs=1000
--tolerance_usecs=7000
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,sackOK,TS val 1 ecr 0,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,sackOK,TS val 10 ecr 1,ECN e1b 1 ceb 0 e0b 1,nop,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <nop,nop,TS val 2 ecr 10>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <nop,nop,TS val 83 ecr 2>
// Fake CE and claim no progress
+0.05 < [ect0] WA. 1:1(0) ack 1 win 264 <nop,nop,TS val 2 ecr 83>
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
@@ -0,0 +1,25 @@
// Test TS progress filtering
--tcp_ts_tick_usecs=1000
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=3
`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < SEWA 0:0(0) win 32792 <mss 1050,sackOK,TS val 1 ecr 0,nop,wscale 8>
+.002 > SW. 0:0(0) ack 1 <mss 1460,sackOK,TS val 10 ecr 1,ECN e1b 1 ceb 0 e0b 1,nop,nop,wscale 8>
+0.05 < [ect0] W. 1:1(0) ack 1 win 264 <nop,nop,TS val 2 ecr 10>
+.002 accept(3, ..., ...) = 4
+0.01 %{ assert tcpi_delivered_ce == 0, tcpi_delivered_ce }%
+0.01 write(4, ..., 1000) = 1000
+.002 > [ect0] EAP. 1:1001(1000) ack 1 <nop,nop,TS val 83 ecr 2>
// Fake CE and claim no progress
+0.05 < [ect0] WA. 1:1(0) ack 1 win 264 <nop,nop,TS val 3 ecr 83>
+0.01 %{ assert tcpi_delivered_ce == 1, tcpi_delivered_ce }%
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
//
// Minimal active open.
// First to close connection.
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
// Connect to server: active open: three-way handshake
+0...0 connect(4, ..., ...) = 0
+0 > S 0:0(0) <mss 1460,sackOK,TS val 0 ecr 0,nop,wscale 8>
+0 < S. 0:0(0) ack 1 win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 7>
+0 > . 1:1(0) ack 1
// Send data
+0 send(4, ..., 1000, 0) = 1000
+0 > P. 1:1001(1000) ack 1
+0 < . 1:1(0) ack 1001 win 257
+0 close(4) = 0
+0 > F. 1001:1001(0) ack 1
+0 < F. 1:1(0) ack 1002 win 257
+0 > . 1002:1002(0) ack 2
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-2.0
//
// Minimal passive open.
// Peer is first to close.
`./defaults.sh`
// Open listener socket
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
// Incoming connection: passive open: three-way handshake
+0 < S 0:0(0) win 65535 <mss 1000,sackOK,nop,nop,nop,wscale 8>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 257
// Open connection socket and close listener socket
+0 accept(3, ..., ...) = 4
+0 close(3) = 0
// Peer sends data: acknowledge and receive
+0 < P. 1:1001(1000) ack 1 win 257
+0 > . 1:1(0) ack 1001
+0 recv(4, ..., 1000, 0) = 1000
// Peer initiates connection close
+0 < F. 1001:1001(0) ack 1 win 257
+.04 > . 1:1(0) ack 1002
// Local socket also closes its side
+0 close(4) = 0
+0 > F. 1:1(0) ack 1002
+0 < . 1002:1002(0) ack 2 win 257
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
// Test for blocking accept.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0...0.200 accept(3, ..., ...) = 4
+.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 257
+.1 write(4, ..., 2000) = 2000
+0 > P. 1:2001(2000) ack 1
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Test for blocking connect.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+.1...0.200 connect(3, ..., ...) = 0
+0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.1 < S. 0:0(0) ack 1 win 5792 <mss 1460,nop,wscale 2,nop,nop,sackOK>
+0 > . 1:1(0) ack 1
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0
// Test for blocking read.
--tolerance_usecs=10000
--mss=1000
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
+0...0.100 read(4, ..., 2000) = 2000
+.1 < P. 1:2001(2000) ack 1 win 257
+0 > . 1:1(0) ack 2001
+.1...0.200 read(4, ..., 2000) = 2000
+.1 < P. 2001:4001(2000) ack 1 win 257
+0 > . 1:1(0) ack 4001
+.1 < P. 4001:6001(2000) ack 1 win 257
+0 > . 1:1(0) ack 6001
+0...0.000 read(4, ..., 1000) = 1000
+0...0.000 read(4, ..., 1000) = 1000
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-2.0
// Test for blocking write.
--tolerance_usecs=10000
`./defaults.sh
./set_sysctls.py /proc/sys/net/ipv4/tcp_min_tso_segs=10
`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+.1 < S 0:0(0) win 50000 <mss 1000,nop,wscale 0>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 50000
+0 accept(3, ..., ...) = 4
// Kernel doubles our value -> sk->sk_sndbuf is set to 42000
+0 setsockopt(4, SOL_SOCKET, SO_SNDBUF, [21000], 4) = 0
+0 getsockopt(4, SOL_SOCKET, SO_SNDBUF, [42000], [4]) = 0
// A write of 60000 does not block.
+0...0.300 write(4, ..., 61000) = 61000 // this write() blocks
+.1 < . 1:1(0) ack 10001 win 50000
+.1 < . 1:1(0) ack 30001 win 50000
// This ACK should wakeup the write(). An ACK of 35001 does not.
+.1 < . 1:1(0) ack 36001 win 50000
// Reset to sysctls defaults.
`/tmp/sysctl_restore_${PPID}.sh`
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0
// Test basic connection teardown where local process closes first:
// the local process calls close() first, so we send a FIN, and receive an ACK.
// Then we receive a FIN and ACK it.
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+.01...0.011 connect(3, ..., ...) = 0
+0 > S 0:0(0) <...>
+0 < S. 0:0(0) ack 1 win 32768 <mss 1000,nop,wscale 6,nop,nop,sackOK>
+0 > . 1:1(0) ack 1
+0 write(3, ..., 1000) = 1000
+0 > P. 1:1001(1000) ack 1
+0 < . 1:1(0) ack 1001 win 257
+0 close(3) = 0
+0 > F. 1001:1001(0) ack 1
+0 < . 1:1(0) ack 1002 win 257
+0 < F. 1:1(0) ack 1002 win 257
+0 > . 1002:1002(0) ack 2
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
// Test to make sure no RST is being sent when close()
// is called on a socket with SYN_SENT state.
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+0 > S 0:0(0) <...>
// Application decideds to close the socket in SYN_SENT state
// Make sure no RST is sent after close().
+0 close(3) = 0
// Receive syn-ack to trigger the send side packet examination:
// If a RESET were sent right after close(), it would have failed with
// a mismatched timestamp.
+.1 < S. 0:0(0) ack 1 win 32000 <mss 1460,nop,wscale 7>
+0 > R 1:1(0)
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0
// Verify behavior for the sequence: remote side sends FIN, then we close().
// Since the remote side (client) closes first, we test our LAST_ACK code path.
`./defaults.sh`
// Initialize a server socket.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
// Client closes first.
+.01 < F. 1:1(0) ack 1 win 257
+0 > . 1:1(0) ack 2
// App notices that client closed.
+0 read(4, ..., 1000) = 0
// Then we close.
+.01 close(4) = 0
+0 > F. 1:1(0) ack 2
// Client ACKs our FIN.
+.01 < . 2:2(0) ack 2 win 257
// Verify that we send RST in response to any incoming segments
// (because the kernel no longer has any record of this socket).
+.01 < . 2:2(0) ack 2 win 257
+0 > R 2:2(0)
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
--mss=1000
`./defaults.sh`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+.1 < . 1:1(0) ack 1 win 32792
+0 accept(3, ..., ...) = 4
+0 < . 1:1001(1000) ack 1 win 32792
+0 > . 1:1(0) ack 1001
+0 read(4, ..., 1000) = 1000
// resend the payload + a FIN
+0 < F. 1:1001(1000) ack 1 win 32792
// Why do we have a delay and no dsack ?
+0~+.04 > . 1:1(0) ack 1002
+0 close(4) = 0
// According to RFC 2525, section 2.17
// we should _not_ send an RST here, because there was no data to consume.
+0 > F. 1:1(0) ack 1002
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0
// Check fix in 795a7dfbc3d9 ("net: tcp: accept old ack during closing")
// Set up config.
`./defaults.sh`
// Initialize a server socket.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 65535 <mss 1000,sackOK,nop,nop,nop,wscale 7>
* > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
+0 shutdown(4, SHUT_WR) = 0
* > F. 1:1(0) ack 1
// We expect to receive one ACK.
// But what happens if a FIN was already in transmt and received out-of-order ?
+0 < . 2:2(0) ack 2 win 257
// This FIN packet was sent before the prior ACK (see ack 1).
+0 < F. 1:1(0) ack 1 win 257
// Even if the FIN is received out-of-order, we should ACK it.
* > . 2:2(0) ack 2
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0
// Test various DSACK (RFC 2883) behaviors.
--mss=1000
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 1024
+0 accept(3, ..., ...) = 4
// First SACK range.
+0 < P. 1001:2001(1000) ack 1 win 1024
+0 > . 1:1(0) ack 1 <nop, nop, sack 1001:2001>
// Check SACK coalescing (contiguous sequence).
+0 < P. 2001:3001(1000) ack 1 win 1024
+0 > . 1:1(0) ack 1 <nop,nop,sack 1001:3001>
// Check we have two SACK ranges for non contiguous sequences.
+0 < P. 4001:5001(1000) ack 1 win 1024
+0 > . 1:1(0) ack 1 <nop,nop,sack 4001:5001 1001:3001>
// Three ranges.
+0 < P. 7001:8001(1000) ack 1 win 1024
+0 > . 1:1(0) ack 1 <nop,nop,sack 7001:8001 4001:5001 1001:3001>
// DSACK (1001:3001) + SACK (6001:7001)
+0 < P. 1:6001(6000) ack 1 win 1024
+0 > . 1:1(0) ack 6001 <nop,nop,sack 1001:3001 7001:8001>
// DSACK (7001:8001)
+0 < P. 6001:8001(2000) ack 1 win 1024
+0 > . 1:1(0) ack 8001 <nop,nop,sack 7001:8001>
// DSACK for an older segment.
+0 < P. 1:1001(1000) ack 1 win 1024
+0 > . 1:1(0) ack 8001 <nop,nop,sack 1:1001>
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
// Test ECN: verify that Linux TCP ECN sending code uses ECT0 (not ECT1).
//
`./defaults.sh
sysctl -q net.ipv4.tcp_ecn=1 # fully enabled
`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
// ECN handshake: send EW flags in SYN packet, E flag in SYN-ACK response
+.002 ... 0.004 connect(4, ..., ...) = 0
+0 > SEW 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.002 < SE. 0:0(0) ack 1 win 32767 <mss 1000,nop,wscale 6,nop,nop,sackOK>
+0 > . 1:1(0) ack 1
// Write 1 MSS.
+.002 write(4, ..., 1000) = 1000
// Send 1 MSS with ect0.
+0 > [ect0] P. 1:1001(1000) ack 1
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0
// Test TCP does not append any data from consequent writes to the tail
// skb created for the chunk. The large chunk itself should be packetized as
// usual.
`./defaults.sh
`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
// the tail.
+0 write(4, ..., 10400) = 10400
// Write another 10040B chunk with no coalescing options.
+0 send(4, ..., 10400, MSG_EOR) = 10400
// Write a 2KB chunk. This chunk should not be appended to the packets created
// the previous chunk.
+0 write(4, ..., 2000) = 2000
+0 > P. 1:10001(10000) ack 1
+.001 < . 1:1(0) ack 10001 win 514
// Now we have enough room to send out the 2 x 400B packets out.
+0 > P. 10001:20801(10800) ack 1
+.001 < . 1:1(0) ack 20801 win 514
// This 2KB packet should be sent alone.
+0 > P. 20801:22801(2000) ack 1
+.001 < . 1:1(0) ack 22801 win 514
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0
// Test TCP does not append any data from consequent writes to the tail
// skb created for the chunk. Also, when packets are retransmitted, they
// will not be coalesce into the same skb.
`./defaults.sh
`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
// the tail.
+0 write(4, ..., 10400) = 10400
// Write 10 400B chunks with no coalescing options.
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
// This chunk should not be appended to the skbs created for the previous chunk.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
+.001 < . 1:1(0) ack 10001 win 514
// Now we have enough room to send out the 2 x 400B packets out.
+0 > P. 10001:10801(800) ack 1
// The 9 remaining 400B chunks should be sent as individual packets.
+0 > P. 10801:11201(400) ack 1
+0 > P. 11201:11601(400) ack 1
+0 > P. 11601:12001(400) ack 1
+0 > P. 12001:12401(400) ack 1
+0 > P. 12401:12801(400) ack 1
+0 > P. 12801:13201(400) ack 1
+0 > P. 13201:13601(400) ack 1
+0 > P. 13601:14001(400) ack 1
+0 > P. 14001:14401(400) ack 1
// The last 10KB chunk should be sent separately.
+0 > P. 14401:24401(10000) ack 1
+.001 < . 1:1(0) ack 10401 win 514
+.001 < . 1:1(0) ack 10801 win 514
+.001 < . 1:1(0) ack 11201 win 514
+.001 < . 1:1(0) ack 11601 win 514
+.001 < . 1:1(0) ack 12001 win 514 <sack 13201:14401,nop,nop>
// TCP should fill the hole but no coalescing should happen, and all
// retransmissions should be sent out as individual packets.
// Note : This is timeout based retransmit.
// Do not put +0 here or flakes will come back.
+.004~+.008 > P. 12001:12401(400) ack 1
+.001 < . 1:1(0) ack 12401 win 514 <sack 13201:14401,nop,nop>
+0 > P. 12401:12801(400) ack 1
+0 > P. 12801:13201(400) ack 1
+.001 < . 1:1(0) ack 12801 win 514 <sack 13201:14401,nop,nop>
+.001 < . 1:1(0) ack 14401 win 514
+.001 < . 1:1(0) ack 24401 win 514
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0
// Test TCP does not append any data from consequent writes to the tail
// skb created for the chunk.
`./defaults.sh
`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
// the tail.
+0 write(4, ..., 10400) = 10400
// Write a 400B chunk with no coalescing options.
+0 send(4, ..., 400, MSG_EOR) = 400
// This chunk should not be appended to the skbs created for the previous chunk.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
+.001 < . 1:1(0) ack 10001 win 514
// Now we have enough room to send out the 2 x 400B packets out.
+0 > P. 10001:10801(800) ack 1
+0 > P. 10801:20801(10000) ack 1
+.001 < . 1:1(0) ack 10401 win 514
+.001 < . 1:1(0) ack 10801 win 514
+.001 < . 1:1(0) ack 20801 win 514
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
// Test TCP does not append any data from consequent writes to the tail
// skb created for the chunk even though we have 10 back-to-back small
// writes.
`./defaults.sh
`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
// the tail.
+0 write(4, ..., 10400) = 10400
// Write 10 400B chunks with no coalescing options.
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
+0 send(4, ..., 400, MSG_EOR) = 400
// This chunk should not be appended to the skbs created for the previous chunk.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
+.001 < . 1:1(0) ack 10001 win 514
// Now we have enough room to send out the 2 x 400B packets out.
+0 > P. 10001:10801(800) ack 1
// The 9 remaining 400B chunks should be sent as individual packets.
+0 > P. 10801:11201(400) ack 1
+0 > P. 11201:11601(400) ack 1
+0 > P. 11601:12001(400) ack 1
+0 > P. 12001:12401(400) ack 1
+0 > P. 12401:12801(400) ack 1
+0 > P. 12801:13201(400) ack 1
+0 > P. 13201:13601(400) ack 1
+0 > P. 13601:14001(400) ack 1
+0 > P. 14001:14401(400) ack 1
// The last 10KB chunk should be sent separately.
+0 > P. 14401:24401(10000) ack 1
+.001 < . 1:1(0) ack 10401 win 514
+.001 < . 1:1(0) ack 10801 win 514
+.001 < . 1:1(0) ack 11201 win 514
+.001 < . 1:1(0) ack 11601 win 514
+.001 < . 1:1(0) ack 12001 win 514
+.001 < . 1:1(0) ack 12401 win 514
+.001 < . 1:1(0) ack 12801 win 514
+.001 < . 1:1(0) ack 13201 win 514
+.001 < . 1:1(0) ack 13601 win 514
+.001 < . 1:1(0) ack 14001 win 514
+.001 < . 1:1(0) ack 14401 win 514
+.001 < . 1:1(0) ack 24401 win 514
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0
// Test PRR-slowstart implementation.
// In this variant we test a simple case where in-flight == ssthresh
// all the way through recovery, so during fast recovery we send one segment
// for each segment SACKed/ACKed.
// Set up config.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// RTT 100ms
+.1 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// Send 10 data segments.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
// Lost packet 1:1001.
+.11 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:4001,nop,nop>
// Enter fast recovery.
+0 > . 1:1001(1000) ack 1
+.01 %{
assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state
assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd
assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh
}%
// Write some more, which we will send 1 MSS at a time,
// as in-flight segments are SACKed or ACKed.
+.01 write(4, ..., 7000) = 7000
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:5001,nop,nop>
+0 > . 10001:11001(1000) ack 1
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:6001,nop,nop>
+0 > . 11001:12001(1000) ack 1
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:7001,nop,nop>
+0 > . 12001:13001(1000) ack 1
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:8001,nop,nop>
+0 > . 13001:14001(1000) ack 1
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:9001,nop,nop>
+0 > . 14001:15001(1000) ack 1
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:10001,nop,nop>
+0 > . 15001:16001(1000) ack 1
+.02 < . 1:1(0) ack 10001 win 320
+0 > P. 16001:17001(1000) ack 1
// Leave fast recovery.
+.01 %{
assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state
assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd
assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh
}%
+.03 < . 1:1(0) ack 12001 win 320
+.02 < . 1:1(0) ack 14001 win 320
+.02 < . 1:1(0) ack 16001 win 320
+.02 < . 1:1(0) ack 17001 win 320
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
// Test PRR-slowstart implementation. The sender sends 20 packets. Packet
// 1 to 4, and 11 to 16 are dropped.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// Write 20 data segments.
+0 write(4, ..., 20000) = 20000
+0 > P. 1:10001(10000) ack 1
// Receive first DUPACK, entering PRR part
+.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop>
+0 > . 10001:11001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop>
+0 > . 11001:12001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop>
+0 > . 1:1001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop>
+0 > . 1001:2001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop>
+0 > . 2001:3001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop>
+0 > . 3001:4001(1000) ack 1
// Enter PRR CRB
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:11001,nop,nop>
+0 > . 12001:13001(1000) ack 1
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:12001,nop,nop>
+0 > . 13001:14001(1000) ack 1
// Enter PRR slow start
+.01 < . 1:1(0) ack 1001 win 320 <sack 4001:12001,nop,nop>
+0 > P. 14001:16001(2000) ack 1
+.002 < . 1:1(0) ack 1001 win 320 <sack 2001:12001,nop,nop>
+0 > . 1001:2001(1000) ack 1
+0 > . 16001:17001(1000) ack 1
// inflight reaches ssthresh, goes into packet conservation mode
+.002 < . 1:1(0) ack 1001 win 320 <sack 2001:13001,nop,nop>
+0 > . 17001:18001(1000) ack 1
+.002 < . 1:1(0) ack 1001 win 320 <sack 2001:14001,nop,nop>
+0 > . 18001:19001(1000) ack 1
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0
// Test PRR-slowstart implementation. The sender sends 20 packets. Packet
// 1 to 4 are lost. The sender writes another 10 packets.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// Send 20 data segments.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
// Lost packet 1,2,3,4
+.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop>
+.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop>
+0 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop>
+0 > . 1:1001(1000) ack 1
+0 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop>
+0 > . 1001:2001(1000) ack 1
+0 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop>
+0 > . 2001:3001(1000) ack 1
+0 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop>
+0 > . 3001:4001(1000) ack 1
// Receiver ACKs all data.
+.01 < . 1:1(0) ack 1001 win 320 <sack 4001:10001,nop,nop>
+0 < . 1:1(0) ack 2001 win 320 <sack 4001:10001,nop,nop>
+0 < . 1:1(0) ack 3001 win 320 <sack 4001:10001,nop,nop>
+0 < . 1:1(0) ack 10001 win 320
// Writes another 10 packets, which the ssthresh*mss amount
// should be sent right away
+.01 write(4, ..., 10000) = 10000
+0 > . 10001:17001(7000) ack 1
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0
// Test PRR-slowstart implementation.
// In this variant we verify that the sender uses SACK info on an ACK
// below snd_una.
// Set up config.
`./defaults.sh`
// Establish a connection.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 8>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// RTT 10ms
+.01 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// Send 10 data segments.
+0 write(4, ..., 10000) = 10000
+0 > P. 1:10001(10000) ack 1
// Lost packet 1:1001,4001:5001,7001:8001.
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+0 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+0 < . 1:1(0) ack 1 win 320 <sack 1001:3001 8001:9001,nop,nop>
+0 > . 1:1001(1000) ack 1
+.012 < . 1:1(0) ack 4001 win 320 <sack 8001:9001,nop,nop>
+0 > . 4001:7001(3000) ack 1
+0 write(4, ..., 10000) = 10000
// The following ACK was reordered - delayed so that it arrives with
// an ACK field below snd_una. Here we check that the newly-SACKed
// 2MSS at 5001:7001 cause us to send out 2 more MSS.
+.002 < . 1:1(0) ack 3001 win 320 <sack 5001:7001,nop,nop>
+0 > . 7001:8001(1000) ack 1
+0 > . 10001:11001(1000) ack 1
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Test TFO_SERVER_COOKIE_NOT_REQD flag on receiving
// SYN with data but without Fast Open cookie option.
`./defaults.sh
./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x202`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
// Since TFO_SERVER_COOKIE_NOT_REQD, a TFO socket will be created with
// the data accepted.
+0 < S 0:1000(1000) win 32792 <mss 1460,sackOK,nop,nop>
+0 > S. 0:0(0) ack 1001 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 read(4, ..., 1024) = 1000
// Data After SYN will be accepted too.
+0 < . 1001:2001(1000) ack 1 win 5840
+0 > . 1:1(0) ack 2001
// Should change the implementation later to set the SYN flag as well.
+0 read(4, ..., 1024) = 1000
+0 write(4, ..., 1000) = 1000
+0 > P. 1:1001(1000) ack 2001
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Test TFO_SERVER_WO_SOCKOPT1 without setsockopt(TCP_FASTOPEN)
`./defaults.sh
./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x402`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 read(4, ..., 512) = 10
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Server w/o TCP_FASTOPEN socket option
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,FO TFO_COOKIE>
// Data is ignored since TCP_FASTOPEN is not set on the listener
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = -1 EAGAIN (Resource temporarily unavailable)
// The above should block until ack comes in below.
+0 < . 1:31(30) ack 1 win 5840
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 read(4, ..., 512) = 30
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Test that TFO-enabled server would not respond SYN-ACK with any TFO option
// when receiving a pure SYN-data. It should respond a pure SYN-ack.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6>
+0 > S. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 100
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 close(3) = 0
// Test ECN-setup SYN with ECN disabled because this has happened in reality
+0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < SEW 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6>
+0 > S. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 100
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 close(3) = 0
// Test ECN-setup SYN w/ ECN enabled
+0 `sysctl -q net.ipv4.tcp_ecn=2`
+0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < SEW 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6>
+0 > SE. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 100
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 close(3) = 0
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Test TFO server with SYN that has TFO cookie and data.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 read(4, ..., 512) = 10
+0 write(4, ..., 100) = 100
+0 > P. 1:101(100) ack 11
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
//
// Basic TFO server test
//
// Test zero-payload packet w/ valid TFO cookie - a TFO socket will
// still be created and accepted but read() will not return until a
// later pkt with 10 byte.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:0(0) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
// A TFO socket is created and is writable.
+0 write(4, ..., 100) = 100
+0 > P. 1:101(100) ack 1
+0...0.300 read(4, ..., 512) = 10
+.3 < P. 1:11(10) ack 1 win 5840
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-2.0
//
// A reproducer case for a TFO SYNACK RTO undo bug in:
// 794200d66273 ("tcp: undo cwnd on Fast Open spurious SYNACK retransmit")
// This sequence that tickles this bug is:
// - Fast Open server receives TFO SYN with data, sends SYNACK
// - (client receives SYNACK and sends ACK, but ACK is lost)
// - server app sends some data packets
// - (N of the first data packets are lost)
// - server receives client ACK that has a TS ECR matching first SYNACK,
// and also SACKs suggesting the first N data packets were lost
// - server performs undo of SYNACK RTO, then immediately enters recovery
// - buggy behavior in 794200d66273 then performed an undo that caused
// the connection to be in a bad state, in CA_Open with retrans_out != 0
// Check that outbound TS Val ticks are as we would expect with 1000 usec per
// timestamp tick:
--tcp_ts_tick_usecs=1000
`./defaults.sh`
// Initialize connection
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:1000(1000) win 65535 <mss 1012,sackOK,TS val 1000 ecr 0,wscale 7,nop,nop,nop,FO TFO_COOKIE>
+0 > S. 0:0(0) ack 1001 <mss 1460,sackOK,TS val 2000 ecr 1000,nop,wscale 8>
+0 accept(3, ..., ...) = 4
// Application writes more data
+.010 write(4, ..., 10000) = 10000
+0 > P. 1:5001(5000) ack 1001 <nop,nop,TS val 2010 ecr 1000>
+0 > P. 5001:10001(5000) ack 1001 <nop,nop,TS val 2010 ecr 1000>
+0 %{ assert tcpi_snd_cwnd == 10, tcpi_snd_cwnd }%
+0 < . 1001:1001(0) ack 1 win 257 <TS val 1010 ecr 2000,sack 2001:5001>
+0 > P. 1:2001(2000) ack 1001 <nop,nop,TS val 2010 ecr 1010>
+0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }%
+0 %{ assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd }%
+0 < . 1001:1001(0) ack 1 win 257 <TS val 1011 ecr 2000,sack 2001:6001>
+0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }%
+0 %{ assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd }%
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
//
// Test the Experimental Option
//
// SYN w/ FOEXP w/o cookie must generates SYN+ACK w/ FOEXP
// w/ a valid cookie, and the cookie must be the same one
// with one generated by IANA FO
`./defaults.sh`
// Request a TFO cookie by Experimental Option
// This must generate the same TFO_COOKIE
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FOEXP>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,FOEXP TFO_COOKIE>
+0 close(3) = 0
// Test if FOEXP with a valid cookie creates a TFO socket
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FOEXP TFO_COOKIE>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 read(4, ..., 512) = 10
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send a FIN pkt with the ACK bit to a TFO socket.
// The socket will go to TCP_CLOSE_WAIT state and data can be
// read until the socket is closed, at which time a FIN will be sent.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
// FIN is acked and the socket goes to TCP_CLOSE_WAIT state
// in tcp_fin() called from tcp_data_queue().
+0 < F. 11:11(0) ack 1 win 32792
+0 > . 1:1(0) ack 12
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 %{ assert tcpi_state == TCP_CLOSE_WAIT, tcpi_state }%
+0 read(4, ..., 512) = 10
+0 close(4) = 0
+0 > F. 1:1(0) ack 12
* > F. 1:1(0) ack 12
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send an ICMP host_unreachable pkt to a pending SYN_RECV req.
//
// If it's a TFO req, the ICMP error will cause it to switch
// to TCP_CLOSE state but remains in the acceptor queue.
--ip_version=ipv4
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
// Out-of-window icmp is ignored but accounted.
+0 `nstat > /dev/null`
+0 < icmp unreachable [5000:6000(1000)]
+0 `nstat | grep TcpExtOutOfWindowIcmps > /dev/null`
// Valid ICMP unreach.
+0 < icmp unreachable host_unreachable [0:10(10)]
// Unlike the non-TFO case, the req is still there to be accepted.
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
// tcp_done_with_error() in tcp_v4_err() sets sk->sk_state
// to TCP_CLOSE
+0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
// The 1st read will succeed and return the data in SYN
+0 read(4, ..., 512) = 10
// The 2nd read will fail.
+0 read(4, ..., 512) = -1 EHOSTUNREACH (No route to host)
// But is no longer writable because it's in TCP_CLOSE state.
+0 write(4, ..., 100) = -1 EPIPE (Broken Pipe)
// inbound pkt will trigger RST because the socket has been moved
// off the TCP hash tables.
+0 < . 1:1(0) ack 1 win 32792
+0 > R 1:1(0)
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send a RST to a TFO socket after it has been accepted.
//
// First read() will return all the data and this is consistent
// with the non-TFO case. Second read will return -1
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }%
// 1st read will return the data from SYN.
// tcp_reset() sets sk->sk_err to ECONNRESET for SYN_RECV.
+0 < R. 11:11(0) win 32792
+0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
// This one w/o ACK bit will cause the same effect.
// +0 < R 11:11(0) win 32792
// See Step 2 in tcp_validate_incoming().
// found_ok_skb in tcp_recvmsg_locked()
+0 read(4, ..., 512) = 10
// !copied && sk->sk_err -> sock_error(sk)
+0 read(4, ..., 512) = -1 ECONNRESET (Connection reset by peer)
+0 close(4) = 0
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send a RST to a TFO socket before it is accepted.
//
// The socket won't go away and after it's accepted the data
// in the SYN pkt can still be read. But that's about all that
// the acceptor can do with the socket.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 7,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK,nop,wscale 8>
// 1st read will return the data from SYN.
+0 < R. 11:11(0) win 257
// This one w/o ACK bit will cause the same effect.
// +0 < R 11:11(0) win 257
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
+0 read(4, ..., 512) = 10
+0 read(4, ..., 512) = -1 ECONNRESET (Connection reset by peer)
+0 close(4) = 0
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send a RST to a TFO socket after it is accepted.
//
// The socket will change to TCP_CLOSE state with pending data so
// write() will fail. Pending data can be still be read and close()
// won't trigger RST if data is not read
//
// 565b7b2d2e63 ("tcp: do not send reset to already closed sockets")
// https://lore.kernel.org/netdev/4C1A2502.1030502@openvz.org/
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop, FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }%
// tcp_done() sets sk->sk_state to TCP_CLOSE and clears tp->fastopen_rsk
+0 < R. 11:11(0) win 32792
+0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
+0 write(4, ..., 100) = -1 ECONNRESET(Connection reset by peer)
+0 close(4) = 0
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
//
// Send a RST to a fully established socket with pending data before
// it is accepted.
//
// The socket with pending data won't go away and can still be accepted
// with data read. But it will be in TCP_CLOSE state.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
// Invalid cookie, so accept() fails.
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO aaaaaaaaaaaaaaaa,nop,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK, FO TFO_COOKIE,nop,nop>
+0 accept(3, ..., ...) = -1 EAGAIN (Resource temporarily unavailable)
// Complete 3WHS and send data and RST
+0 < . 1:1(0) ack 1 win 32792
+0 < . 1:11(10) ack 1 win 32792
+0 < R. 11:11(0) win 32792
// A valid reset won't make the fully-established socket go away.
// It's just that the acceptor will get a dead, unusable socket
// in TCP_CLOSE state.
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
+0 write(4, ..., 100) = -1 ECONNRESET(Connection reset by peer)
+0 read(4, ..., 512) = 10
+0 read(4, ..., 512) = 0
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0
//
// Test the server cookie is generated by aes64 encoding of remote and local
// IP addresses with a master key specified via sockopt TCP_FASTOPEN_KEY
//
`./defaults.sh
./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen_key=00000000-00000000-00000000-00000000`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
// Set a key of a1a1a1a1-b2b2b2b2-c3c3c3c3-d4d4d4d4 (big endian).
// This would produce a cookie of TFO_COOKIE like many other
// tests (which the same key but set via sysctl).
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY,
"\xa1\xa1\xa1\xa1\xb2\xb2\xb2\xb2\xc3\xc3\xc3\xc3\xd4\xd4\xd4\xd4", 16) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
// Request a valid cookie TFO_COOKIE
+0 < S 1428932:1428942(10) win 10000 <mss 1012,nop,nop,FO,sackOK,TS val 1 ecr 0,nop,wscale 7>
+0 > S. 0:0(0) ack 1428933 <mss 1460,sackOK,TS val 10000 ecr 1,nop,wscale 8,FO TFO_COOKIE,nop,nop>
+0 < . 1:1(0) ack 1 win 257 <nop,nop,TS val 2 ecr 10000>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }%
+0 close(4) = 0
+0 > F. 1:1(0) ack 1 <nop,nop,TS val 10001 ecr 2>
+0 < F. 1:1(0) ack 2 win 257 <nop,nop,TS val 3 ecr 10001>
+0 > . 2:2(0) ack 2 <nop,nop,TS val 10002 ecr 3>
+0 close(3) = 0
// Restart the listener
+0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
// Test setting the key in the listen state, and produces an identical cookie
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY,
"\xa1\xa1\xa1\xa1\xb2\xb2\xb2\xb2\xc3\xc3\xc3\xc3\xd4\xd4\xd4\xd4", 16) = 0
+0 < S 6814000:6815000(1000) win 10000 <mss 1012,nop,nop,FO TFO_COOKIE,sackOK,TS val 10 ecr 0,nop,wscale 7>
+0 > S. 0:0(0) ack 6815001 <mss 1460,sackOK,TS val 10000 ecr 10,nop,wscale 8>
+0 accept(3, ..., ...) = 4
+0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }%
+0 < . 1001:1001(0) ack 1 win 257 <nop,nop,TS val 12 ecr 10000>
+0 read(4, ..., 8192) = 1000
+0 close(4) = 0
+0 > F. 1:1(0) ack 1001 <nop,nop,TS val 10101 ecr 12>
+0 < F. 1001:1001(0) ack 2 win 257 <nop,nop,TS val 112 ecr 10101>
+0 > . 2:2(0) ack 1002 <nop,nop,TS val 10102 ecr 112>
+0 close(3) = 0
// Restart the listener
+0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
// Test invalid key length (must be 16 bytes)
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, "", 0) = -1 (Invalid Argument)
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, "", 3) = -1 (Invalid Argument)
// Previous cookie won't be accepted b/c this listener uses the global key (0-0-0-0)
+0 < S 6814000:6815000(1000) win 10000 <mss 1012,nop,nop,FO TFO_COOKIE,sackOK,TS val 10 ecr 0,nop,wscale 7>
+0 > S. 0:0(0) ack 6814001 <mss 1460,sackOK,TS val 10000 ecr 10,nop,wscale 8,FO TFO_COOKIE_ZERO,nop,nop>
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
//
// Close a listener socket with pending TFO child.
// This will trigger RST pkt to go out.
`./defaults.sh`
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0
+0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop>
+0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK>
// RST pkt is generated for each not-yet-accepted TFO child.
// inet_csk_listen_stop() -> inet_child_forget() -> tcp_disconnect()
// -> tcp_need_reset() is true for SYN_RECV
+0 close(3) = 0
+0 > R. 1:1(0) ack 11

Some files were not shown because too many files have changed in this diff Show More