summaryrefslogtreecommitdiffhomepage
path: root/test/packetimpact
diff options
context:
space:
mode:
Diffstat (limited to 'test/packetimpact')
-rw-r--r--test/packetimpact/dut/posix_server.cc3
-rw-r--r--test/packetimpact/proto/posix_server.proto3
-rw-r--r--test/packetimpact/runner/defs.bzl15
-rw-r--r--test/packetimpact/runner/dut.go81
-rw-r--r--test/packetimpact/testbench/BUILD2
-rw-r--r--test/packetimpact/testbench/connections.go33
-rw-r--r--test/packetimpact/testbench/dut.go56
-rw-r--r--test/packetimpact/testbench/layers.go12
-rw-r--r--test/packetimpact/testbench/layers_test.go8
-rw-r--r--test/packetimpact/testbench/testbench.go62
-rw-r--r--test/packetimpact/tests/BUILD32
-rw-r--r--test/packetimpact/tests/fin_wait2_timeout_test.go10
-rw-r--r--test/packetimpact/tests/ipv4_id_uniqueness_test.go2
-rw-r--r--test/packetimpact/tests/tcp_cork_mss_test.go12
-rw-r--r--test/packetimpact/tests/tcp_fin_retransmission_test.go87
-rw-r--r--test/packetimpact/tests/tcp_handshake_window_size_test.go8
-rw-r--r--test/packetimpact/tests/tcp_info_test.go2
-rw-r--r--test/packetimpact/tests/tcp_linger_test.go31
-rw-r--r--test/packetimpact/tests/tcp_network_unreachable_test.go11
-rw-r--r--test/packetimpact/tests/tcp_noaccept_close_rst_test.go2
-rw-r--r--test/packetimpact/tests/tcp_outside_the_window_closing_test.go86
-rw-r--r--test/packetimpact/tests/tcp_outside_the_window_test.go12
-rw-r--r--test/packetimpact/tests/tcp_paws_mechanism_test.go14
-rw-r--r--test/packetimpact/tests/tcp_queue_send_recv_in_syn_sent_test.go53
-rw-r--r--test/packetimpact/tests/tcp_rack_test.go20
-rw-r--r--test/packetimpact/tests/tcp_rcv_buf_space_test.go5
-rw-r--r--test/packetimpact/tests/tcp_retransmits_test.go36
-rw-r--r--test/packetimpact/tests/tcp_send_window_sizes_piggyback_test.go4
-rw-r--r--test/packetimpact/tests/tcp_synrcvd_reset_test.go10
-rw-r--r--test/packetimpact/tests/tcp_synsent_reset_test.go18
-rw-r--r--test/packetimpact/tests/tcp_timewait_reset_test.go14
-rw-r--r--test/packetimpact/tests/tcp_unacc_seq_ack_closing_test.go94
-rw-r--r--test/packetimpact/tests/tcp_unacc_seq_ack_test.go88
-rw-r--r--test/packetimpact/tests/tcp_user_timeout_test.go6
-rw-r--r--test/packetimpact/tests/tcp_window_shrink_test.go4
-rw-r--r--test/packetimpact/tests/tcp_zero_receive_window_test.go8
-rw-r--r--test/packetimpact/tests/tcp_zero_window_probe_retransmit_test.go22
-rw-r--r--test/packetimpact/tests/tcp_zero_window_probe_test.go12
-rw-r--r--test/packetimpact/tests/tcp_zero_window_probe_usertimeout_test.go12
-rw-r--r--test/packetimpact/tests/udp_discard_mcast_source_addr_test.go5
-rw-r--r--test/packetimpact/tests/udp_icmp_error_propagation_test.go21
-rw-r--r--test/packetimpact/tests/udp_send_recv_dgram_test.go3
42 files changed, 711 insertions, 308 deletions
diff --git a/test/packetimpact/dut/posix_server.cc b/test/packetimpact/dut/posix_server.cc
index 0d93b806e..ea83bbe72 100644
--- a/test/packetimpact/dut/posix_server.cc
+++ b/test/packetimpact/dut/posix_server.cc
@@ -395,7 +395,8 @@ class PosixImpl final : public posix_server::Posix::Service {
::grpc::Status Shutdown(grpc::ServerContext *context,
const ::posix_server::ShutdownRequest *request,
::posix_server::ShutdownResponse *response) override {
- if (shutdown(request->fd(), request->how()) < 0) {
+ response->set_ret(shutdown(request->fd(), request->how()));
+ if (response->ret() < 0) {
response->set_errno_(errno);
}
return ::grpc::Status::OK;
diff --git a/test/packetimpact/proto/posix_server.proto b/test/packetimpact/proto/posix_server.proto
index 521f03465..175a65336 100644
--- a/test/packetimpact/proto/posix_server.proto
+++ b/test/packetimpact/proto/posix_server.proto
@@ -214,7 +214,8 @@ message ShutdownRequest {
}
message ShutdownResponse {
- int32 errno_ = 1; // "errno" may fail to compile in c++.
+ int32 ret = 1;
+ int32 errno_ = 2; // "errno" may fail to compile in c++.
}
message RecvRequest {
diff --git a/test/packetimpact/runner/defs.bzl b/test/packetimpact/runner/defs.bzl
index 8ce5edf2b..567f64c41 100644
--- a/test/packetimpact/runner/defs.bzl
+++ b/test/packetimpact/runner/defs.bzl
@@ -203,6 +203,11 @@ ALL_TESTS = [
name = "tcp_outside_the_window",
),
PacketimpactTestInfo(
+ name = "tcp_outside_the_window_closing",
+ # TODO(b/181625316): Fix netstack then merge into tcp_outside_the_window.
+ expect_netstack_failure = True,
+ ),
+ PacketimpactTestInfo(
name = "tcp_noaccept_close_rst",
),
PacketimpactTestInfo(
@@ -212,6 +217,11 @@ ALL_TESTS = [
name = "tcp_unacc_seq_ack",
),
PacketimpactTestInfo(
+ name = "tcp_unacc_seq_ack_closing",
+ # TODO(b/181625316): Fix netstack then merge into tcp_unacc_seq_ack.
+ expect_netstack_failure = True,
+ ),
+ PacketimpactTestInfo(
name = "tcp_paws_mechanism",
# TODO(b/156682000): Fix netstack then remove the line below.
expect_netstack_failure = True,
@@ -277,6 +287,11 @@ ALL_TESTS = [
PacketimpactTestInfo(
name = "tcp_info",
),
+ PacketimpactTestInfo(
+ name = "tcp_fin_retransmission",
+ # TODO(b/181625316): Fix netstack then remove the line below.
+ expect_netstack_failure = True,
+ ),
]
def validate_all_tests():
diff --git a/test/packetimpact/runner/dut.go b/test/packetimpact/runner/dut.go
index 3da265b78..1064ca976 100644
--- a/test/packetimpact/runner/dut.go
+++ b/test/packetimpact/runner/dut.go
@@ -109,6 +109,7 @@ type dutInfo struct {
dut DUT
ctrlNet, testNet *dockerutil.Network
netInfo *testbench.DUTTestNet
+ uname *testbench.DUTUname
}
// setUpDUT will set up one DUT and return information for setting up the
@@ -182,6 +183,10 @@ func setUpDUT(ctx context.Context, t *testing.T, id int, mkDevice func(*dockerut
POSIXServerIP: AddressInSubnet(DUTAddr, *ctrlNet.Subnet),
POSIXServerPort: CtrlPort,
}
+ info.uname, err = dut.Uname(ctx)
+ if err != nil {
+ return dutInfo{}, fmt.Errorf("failed to get uname information on DUT: %w", err)
+ }
return info, nil
}
@@ -195,7 +200,7 @@ func TestWithDUT(ctx context.Context, t *testing.T, mkDevice func(*dockerutil.Co
dutInfoChan := make(chan dutInfo, numDUTs)
errChan := make(chan error, numDUTs)
var dockerNetworks []*dockerutil.Network
- var dutTestNets []*testbench.DUTTestNet
+ var dutInfos []*testbench.DUTInfo
var duts []DUT
setUpCtx, cancelSetup := context.WithCancel(ctx)
@@ -214,7 +219,10 @@ func TestWithDUT(ctx context.Context, t *testing.T, mkDevice func(*dockerutil.Co
select {
case info := <-dutInfoChan:
dockerNetworks = append(dockerNetworks, info.ctrlNet, info.testNet)
- dutTestNets = append(dutTestNets, info.netInfo)
+ dutInfos = append(dutInfos, &testbench.DUTInfo{
+ Net: info.netInfo,
+ Uname: info.uname,
+ })
duts = append(duts, info.dut)
case err := <-errChan:
t.Fatal(err)
@@ -241,28 +249,29 @@ func TestWithDUT(ctx context.Context, t *testing.T, mkDevice func(*dockerutil.Co
testbenchContainer,
testbenchAddr,
dockerNetworks,
+ nil, /* sysctls */
"tail", "-f", "/dev/null",
); err != nil {
t.Fatalf("cannot start testbench container: %s", err)
}
- for i := range dutTestNets {
- name, info, err := deviceByIP(ctx, testbenchContainer, dutTestNets[i].LocalIPv4)
+ for i := range dutInfos {
+ name, info, err := deviceByIP(ctx, testbenchContainer, dutInfos[i].Net.LocalIPv4)
if err != nil {
- t.Fatalf("failed to get the device name associated with %s: %s", dutTestNets[i].LocalIPv4, err)
+ t.Fatalf("failed to get the device name associated with %s: %s", dutInfos[i].Net.LocalIPv4, err)
}
- dutTestNets[i].LocalDevName = name
- dutTestNets[i].LocalDevID = info.ID
- dutTestNets[i].LocalMAC = info.MAC
+ dutInfos[i].Net.LocalDevName = name
+ dutInfos[i].Net.LocalDevID = info.ID
+ dutInfos[i].Net.LocalMAC = info.MAC
localIPv6, err := getOrAssignIPv6Addr(ctx, testbenchContainer, name)
if err != nil {
t.Fatalf("failed to get IPV6 address on %s: %s", testbenchContainer.Name, err)
}
- dutTestNets[i].LocalIPv6 = localIPv6
+ dutInfos[i].Net.LocalIPv6 = localIPv6
}
- dutTestNetsBytes, err := json.Marshal(dutTestNets)
+ dutInfosBytes, err := json.Marshal(dutInfos)
if err != nil {
- t.Fatalf("failed to marshal %v into json: %s", dutTestNets, err)
+ t.Fatalf("failed to marshal %v into json: %s", dutInfos, err)
}
baseSnifferArgs := []string{
@@ -296,7 +305,8 @@ func TestWithDUT(ctx context.Context, t *testing.T, mkDevice func(*dockerutil.Co
"-n",
}
}
- for _, n := range dutTestNets {
+ for _, info := range dutInfos {
+ n := info.Net
snifferArgs := append(baseSnifferArgs, "-i", n.LocalDevName)
if !tshark {
snifferArgs = append(
@@ -351,7 +361,7 @@ func TestWithDUT(ctx context.Context, t *testing.T, mkDevice func(*dockerutil.Co
testArgs = append(testArgs, extraTestArgs...)
testArgs = append(testArgs,
fmt.Sprintf("--native=%t", native),
- "--dut_test_nets_json", string(dutTestNetsBytes),
+ "--dut_infos_json", string(dutInfosBytes),
)
testbenchLogs, err := testbenchContainer.Exec(ctx, dockerutil.ExecOpts{}, testArgs...)
if (err != nil) != expectFailure {
@@ -388,6 +398,10 @@ type DUT interface {
// The t parameter is supposed to be used for t.Cleanup. Don't use it for
// t.Fatal/FailNow functions.
Prepare(ctx context.Context, t *testing.T, runOpts dockerutil.RunOpts, ctrlNet, testNet *dockerutil.Network) (net.IP, net.HardwareAddr, uint32, string, error)
+
+ // Uname gathers information of DUT using command uname.
+ Uname(ctx context.Context) (*testbench.DUTUname, error)
+
// Logs retrieves the logs from the dut.
Logs(ctx context.Context) (string, error)
}
@@ -415,6 +429,10 @@ func (dut *DockerDUT) Prepare(ctx context.Context, _ *testing.T, runOpts dockeru
dut.c,
DUTAddr,
[]*dockerutil.Network{ctrlNet, testNet},
+ map[string]string{
+ // This enables creating ICMP sockets on Linux.
+ "net.ipv4.ping_group_range": "0 0",
+ },
containerPosixServerBinary,
"--ip=0.0.0.0",
fmt.Sprintf("--port=%d", CtrlPort),
@@ -440,6 +458,38 @@ func (dut *DockerDUT) Prepare(ctx context.Context, _ *testing.T, runOpts dockeru
return remoteIPv6, dutDeviceInfo.MAC, dutDeviceInfo.ID, testNetDev, nil
}
+// Uname implements DUT.Uname.
+func (dut *DockerDUT) Uname(ctx context.Context) (*testbench.DUTUname, error) {
+ machine, err := dut.c.Exec(ctx, dockerutil.ExecOpts{}, "uname", "-m")
+ if err != nil {
+ return nil, err
+ }
+ kernelRelease, err := dut.c.Exec(ctx, dockerutil.ExecOpts{}, "uname", "-r")
+ if err != nil {
+ return nil, err
+ }
+ kernelVersion, err := dut.c.Exec(ctx, dockerutil.ExecOpts{}, "uname", "-v")
+ if err != nil {
+ return nil, err
+ }
+ kernelName, err := dut.c.Exec(ctx, dockerutil.ExecOpts{}, "uname", "-s")
+ if err != nil {
+ return nil, err
+ }
+ // TODO(gvisor.dev/issues/5586): -o is not supported on macOS.
+ operatingSystem, err := dut.c.Exec(ctx, dockerutil.ExecOpts{}, "uname", "-o")
+ if err != nil {
+ return nil, err
+ }
+ return &testbench.DUTUname{
+ Machine: strings.TrimRight(machine, "\n"),
+ KernelName: strings.TrimRight(kernelName, "\n"),
+ KernelRelease: strings.TrimRight(kernelRelease, "\n"),
+ KernelVersion: strings.TrimRight(kernelVersion, "\n"),
+ OperatingSystem: strings.TrimRight(operatingSystem, "\n"),
+ }, nil
+}
+
// Logs implements DUT.Logs.
func (dut *DockerDUT) Logs(ctx context.Context) (string, error) {
logs, err := dut.c.Logs(ctx)
@@ -545,11 +595,14 @@ func createDockerNetwork(ctx context.Context, n *dockerutil.Network) error {
// StartContainer will create a container instance from runOpts, connect it
// with the specified docker networks and start executing the specified cmd.
-func StartContainer(ctx context.Context, runOpts dockerutil.RunOpts, c *dockerutil.Container, containerAddr net.IP, ns []*dockerutil.Network, cmd ...string) error {
+func StartContainer(ctx context.Context, runOpts dockerutil.RunOpts, c *dockerutil.Container, containerAddr net.IP, ns []*dockerutil.Network, sysctls map[string]string, cmd ...string) error {
conf, hostconf, netconf := c.ConfigsFrom(runOpts, cmd...)
_ = netconf
hostconf.AutoRemove = true
hostconf.Sysctls = map[string]string{"net.ipv6.conf.all.disable_ipv6": "0"}
+ for k, v := range sysctls {
+ hostconf.Sysctls[k] = v
+ }
if err := c.CreateFrom(ctx, runOpts.Image, conf, hostconf, nil); err != nil {
return fmt.Errorf("unable to create container %s: %w", c.Name, err)
diff --git a/test/packetimpact/testbench/BUILD b/test/packetimpact/testbench/BUILD
index 983c2c030..43b4c7ca1 100644
--- a/test/packetimpact/testbench/BUILD
+++ b/test/packetimpact/testbench/BUILD
@@ -1,7 +1,6 @@
load("//tools:defs.bzl", "go_library", "go_test")
package(
- default_visibility = ["//test/packetimpact:__subpackages__"],
licenses = ["notice"],
)
@@ -15,6 +14,7 @@ go_library(
"rawsockets.go",
"testbench.go",
],
+ visibility = ["//test/packetimpact:__subpackages__"],
deps = [
"//pkg/tcpip",
"//pkg/tcpip/buffer",
diff --git a/test/packetimpact/testbench/connections.go b/test/packetimpact/testbench/connections.go
index 15e1a51de..8ad9040ff 100644
--- a/test/packetimpact/testbench/connections.go
+++ b/test/packetimpact/testbench/connections.go
@@ -677,17 +677,17 @@ func (conn *TCPIPv4) Connect(t *testing.T) {
t.Helper()
// Send the SYN.
- conn.Send(t, TCP{Flags: Uint8(header.TCPFlagSyn)})
+ conn.Send(t, TCP{Flags: TCPFlags(header.TCPFlagSyn)})
// Wait for the SYN-ACK.
- synAck, err := conn.Expect(t, TCP{Flags: Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
+ synAck, err := conn.Expect(t, TCP{Flags: TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("didn't get synack during handshake: %s", err)
}
conn.layerStates[len(conn.layerStates)-1].(*tcpState).synAck = synAck
// Send an ACK.
- conn.Send(t, TCP{Flags: Uint8(header.TCPFlagAck)})
+ conn.Send(t, TCP{Flags: TCPFlags(header.TCPFlagAck)})
}
// ConnectWithOptions performs a TCP 3-way handshake with given TCP options.
@@ -696,17 +696,17 @@ func (conn *TCPIPv4) ConnectWithOptions(t *testing.T, options []byte) {
t.Helper()
// Send the SYN.
- conn.Send(t, TCP{Flags: Uint8(header.TCPFlagSyn), Options: options})
+ conn.Send(t, TCP{Flags: TCPFlags(header.TCPFlagSyn), Options: options})
// Wait for the SYN-ACK.
- synAck, err := conn.Expect(t, TCP{Flags: Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
+ synAck, err := conn.Expect(t, TCP{Flags: TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("didn't get synack during handshake: %s", err)
}
conn.layerStates[len(conn.layerStates)-1].(*tcpState).synAck = synAck
// Send an ACK.
- conn.Send(t, TCP{Flags: Uint8(header.TCPFlagAck)})
+ conn.Send(t, TCP{Flags: TCPFlags(header.TCPFlagAck)})
}
// ExpectData is a convenient method that expects a Layer and the Layer after
@@ -823,6 +823,27 @@ func (conn *TCPIPv4) LocalAddr(t *testing.T) *unix.SockaddrInet4 {
return sa
}
+// GenerateOTWSeqSegment generates a segment with
+// seqnum = RCV.NXT + RCV.WND + seqNumOffset, the generated segment is only
+// acceptable when seqNumOffset is 0, otherwise an ACK is expected from the
+// receiver.
+func GenerateOTWSeqSegment(t *testing.T, conn *TCPIPv4, seqNumOffset seqnum.Size, windowSize seqnum.Size) TCP {
+ t.Helper()
+ lastAcceptable := conn.LocalSeqNum(t).Add(windowSize)
+ otwSeq := uint32(lastAcceptable.Add(seqNumOffset))
+ return TCP{SeqNum: Uint32(otwSeq), Flags: TCPFlags(header.TCPFlagAck)}
+}
+
+// GenerateUnaccACKSegment generates a segment with
+// acknum = SND.NXT + seqNumOffset, the generated segment is only acceptable
+// when seqNumOffset is 0, otherwise an ACK is expected from the receiver.
+func GenerateUnaccACKSegment(t *testing.T, conn *TCPIPv4, seqNumOffset seqnum.Size, windowSize seqnum.Size) TCP {
+ t.Helper()
+ lastAcceptable := conn.RemoteSeqNum(t)
+ unaccAck := uint32(lastAcceptable.Add(seqNumOffset))
+ return TCP{AckNum: Uint32(unaccAck), Flags: TCPFlags(header.TCPFlagAck)}
+}
+
// IPv4Conn maintains the state for all the layers in a IPv4 connection.
type IPv4Conn struct {
Connection
diff --git a/test/packetimpact/testbench/dut.go b/test/packetimpact/testbench/dut.go
index be5121d98..eabdc8cb3 100644
--- a/test/packetimpact/testbench/dut.go
+++ b/test/packetimpact/testbench/dut.go
@@ -19,7 +19,6 @@ import (
"encoding/binary"
"fmt"
"net"
- "syscall"
"testing"
"time"
@@ -35,24 +34,26 @@ type DUT struct {
conn *grpc.ClientConn
posixServer POSIXClient
Net *DUTTestNet
+ Uname *DUTUname
}
// NewDUT creates a new connection with the DUT over gRPC.
func NewDUT(t *testing.T) DUT {
t.Helper()
- n := GetDUTTestNet()
- dut := n.ConnectToDUT(t)
+ info := getDUTInfo()
+ dut := info.ConnectToDUT(t)
t.Cleanup(func() {
dut.TearDownConnection()
- dut.Net.Release()
+ info.release()
})
return dut
}
// ConnectToDUT connects to DUT through gRPC.
-func (n *DUTTestNet) ConnectToDUT(t *testing.T) DUT {
+func (info *DUTInfo) ConnectToDUT(t *testing.T) DUT {
t.Helper()
+ n := info.Net
posixServerAddress := net.JoinHostPort(n.POSIXServerIP.String(), fmt.Sprintf("%d", n.POSIXServerPort))
conn, err := grpc.Dial(posixServerAddress, grpc.WithInsecure(), grpc.WithKeepaliveParams(keepalive.ClientParameters{Timeout: RPCKeepalive}))
if err != nil {
@@ -63,6 +64,7 @@ func (n *DUTTestNet) ConnectToDUT(t *testing.T) DUT {
conn: conn,
posixServer: posixServer,
Net: n,
+ Uname: info.Uname,
}
}
@@ -196,7 +198,7 @@ func (dut *DUT) AcceptWithErrno(ctx context.Context, t *testing.T, sockfd int32)
if err != nil {
t.Fatalf("failed to call Accept: %s", err)
}
- return resp.GetFd(), dut.protoToSockaddr(t, resp.GetAddr()), syscall.Errno(resp.GetErrno_())
+ return resp.GetFd(), dut.protoToSockaddr(t, resp.GetAddr()), unix.Errno(resp.GetErrno_())
}
// Bind calls bind on the DUT and causes a fatal test failure if it doesn't
@@ -225,7 +227,7 @@ func (dut *DUT) BindWithErrno(ctx context.Context, t *testing.T, fd int32, sa un
if err != nil {
t.Fatalf("failed to call Bind: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// Close calls close on the DUT and causes a fatal test failure if it doesn't
@@ -253,7 +255,7 @@ func (dut *DUT) CloseWithErrno(ctx context.Context, t *testing.T, fd int32) (int
if err != nil {
t.Fatalf("failed to call Close: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// Connect calls connect on the DUT and causes a fatal test failure if it
@@ -267,7 +269,7 @@ func (dut *DUT) Connect(t *testing.T, fd int32, sa unix.Sockaddr) {
ret, err := dut.ConnectWithErrno(ctx, t, fd, sa)
// Ignore 'operation in progress' error that can be returned when the socket
// is non-blocking.
- if err != syscall.Errno(unix.EINPROGRESS) && ret != 0 {
+ if err != unix.EINPROGRESS && ret != 0 {
t.Fatalf("failed to connect socket: %s", err)
}
}
@@ -284,7 +286,7 @@ func (dut *DUT) ConnectWithErrno(ctx context.Context, t *testing.T, fd int32, sa
if err != nil {
t.Fatalf("failed to call Connect: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// GetSockName calls getsockname on the DUT and causes a fatal test failure if
@@ -313,7 +315,7 @@ func (dut *DUT) GetSockNameWithErrno(ctx context.Context, t *testing.T, sockfd i
if err != nil {
t.Fatalf("failed to call Bind: %s", err)
}
- return resp.GetRet(), dut.protoToSockaddr(t, resp.GetAddr()), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), dut.protoToSockaddr(t, resp.GetAddr()), unix.Errno(resp.GetErrno_())
}
func (dut *DUT) getSockOpt(ctx context.Context, t *testing.T, sockfd, level, optname, optlen int32, typ pb.GetSockOptRequest_SockOptType) (int32, *pb.SockOptVal, error) {
@@ -334,7 +336,7 @@ func (dut *DUT) getSockOpt(ctx context.Context, t *testing.T, sockfd, level, opt
if optval == nil {
t.Fatalf("GetSockOpt response does not contain a value")
}
- return resp.GetRet(), optval, syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), optval, unix.Errno(resp.GetErrno_())
}
// GetSockOpt calls getsockopt on the DUT and causes a fatal test failure if it
@@ -452,7 +454,7 @@ func (dut *DUT) ListenWithErrno(ctx context.Context, t *testing.T, sockfd, backl
if err != nil {
t.Fatalf("failed to call Listen: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// PollOne calls poll on the DUT and asserts that the expected event must be
@@ -519,7 +521,7 @@ func (dut *DUT) PollWithErrno(ctx context.Context, t *testing.T, pfds []unix.Pol
Revents: int16(protoPfd.GetEvents()),
})
}
- return resp.GetRet(), result, syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), result, unix.Errno(resp.GetErrno_())
}
// Send calls send on the DUT and causes a fatal test failure if it doesn't
@@ -550,7 +552,7 @@ func (dut *DUT) SendWithErrno(ctx context.Context, t *testing.T, sockfd int32, b
if err != nil {
t.Fatalf("failed to call Send: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// SendTo calls sendto on the DUT and causes a fatal test failure if it doesn't
@@ -582,7 +584,7 @@ func (dut *DUT) SendToWithErrno(ctx context.Context, t *testing.T, sockfd int32,
if err != nil {
t.Fatalf("failed to call SendTo: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// SetNonBlocking will set O_NONBLOCK flag for fd if nonblocking
@@ -602,7 +604,7 @@ func (dut *DUT) SetNonBlocking(t *testing.T, fd int32, nonblocking bool) {
t.Fatalf("failed to call SetNonblocking: %s", err)
}
if resp.GetRet() == -1 {
- t.Fatalf("fcntl(%d, %s) failed: %s", fd, resp.GetCmd(), syscall.Errno(resp.GetErrno_()))
+ t.Fatalf("fcntl(%d, %s) failed: %s", fd, resp.GetCmd(), unix.Errno(resp.GetErrno_()))
}
}
@@ -619,7 +621,7 @@ func (dut *DUT) setSockOpt(ctx context.Context, t *testing.T, sockfd, level, opt
if err != nil {
t.Fatalf("failed to call SetSockOpt: %s", err)
}
- return resp.GetRet(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
// SetSockOpt calls setsockopt on the DUT and causes a fatal test failure if it
@@ -720,7 +722,7 @@ func (dut *DUT) SocketWithErrno(t *testing.T, domain, typ, proto int32) (int32,
if err != nil {
t.Fatalf("failed to call Socket: %s", err)
}
- return resp.GetFd(), syscall.Errno(resp.GetErrno_())
+ return resp.GetFd(), unix.Errno(resp.GetErrno_())
}
// Recv calls recv on the DUT and causes a fatal test failure if it doesn't
@@ -751,7 +753,7 @@ func (dut *DUT) RecvWithErrno(ctx context.Context, t *testing.T, sockfd, len, fl
if err != nil {
t.Fatalf("failed to call Recv: %s", err)
}
- return resp.GetRet(), resp.GetBuf(), syscall.Errno(resp.GetErrno_())
+ return resp.GetRet(), resp.GetBuf(), unix.Errno(resp.GetErrno_())
}
// SetSockLingerOption sets SO_LINGER socket option on the DUT.
@@ -771,16 +773,19 @@ func (dut *DUT) SetSockLingerOption(t *testing.T, sockfd int32, timeout time.Dur
// Shutdown calls shutdown on the DUT and causes a fatal test failure if it
// doesn't succeed. If more control over the timeout or error handling is
// needed, use ShutdownWithErrno.
-func (dut *DUT) Shutdown(t *testing.T, fd, how int32) error {
+func (dut *DUT) Shutdown(t *testing.T, fd, how int32) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), RPCTimeout)
defer cancel()
- return dut.ShutdownWithErrno(ctx, t, fd, how)
+ ret, err := dut.ShutdownWithErrno(ctx, t, fd, how)
+ if ret != 0 {
+ t.Fatalf("failed to shutdown(%d, %d): %s", fd, how, err)
+ }
}
// ShutdownWithErrno calls shutdown on the DUT.
-func (dut *DUT) ShutdownWithErrno(ctx context.Context, t *testing.T, fd, how int32) error {
+func (dut *DUT) ShutdownWithErrno(ctx context.Context, t *testing.T, fd, how int32) (int32, error) {
t.Helper()
req := &pb.ShutdownRequest{
@@ -791,5 +796,8 @@ func (dut *DUT) ShutdownWithErrno(ctx context.Context, t *testing.T, fd, how int
if err != nil {
t.Fatalf("failed to call Shutdown: %s", err)
}
- return syscall.Errno(resp.GetErrno_())
+ if resp.GetErrno_() == 0 {
+ return resp.GetRet(), nil
+ }
+ return resp.GetRet(), unix.Errno(resp.GetErrno_())
}
diff --git a/test/packetimpact/testbench/layers.go b/test/packetimpact/testbench/layers.go
index 64a7a171a..2311f7686 100644
--- a/test/packetimpact/testbench/layers.go
+++ b/test/packetimpact/testbench/layers.go
@@ -407,6 +407,12 @@ func Uint8(v uint8) *uint8 {
return &v
}
+// TCPFlags is a helper routine that allocates a new
+// header.TCPFlags value to store v and returns a pointer to it.
+func TCPFlags(v header.TCPFlags) *header.TCPFlags {
+ return &v
+}
+
// Address is a helper routine that allocates a new tcpip.Address value to
// store v and returns a pointer to it.
func Address(v tcpip.Address) *tcpip.Address {
@@ -1030,7 +1036,7 @@ type TCP struct {
SeqNum *uint32
AckNum *uint32
DataOffset *uint8
- Flags *uint8
+ Flags *header.TCPFlags
WindowSize *uint16
Checksum *uint16
UrgentPointer *uint16
@@ -1063,7 +1069,7 @@ func (l *TCP) ToBytes() ([]byte, error) {
h.SetDataOffset(uint8(l.length()))
}
if l.Flags != nil {
- h.SetFlags(*l.Flags)
+ h.SetFlags(uint8(*l.Flags))
}
if l.WindowSize != nil {
h.SetWindowSize(*l.WindowSize)
@@ -1157,7 +1163,7 @@ func parseTCP(b []byte) (Layer, layerParser) {
SeqNum: Uint32(h.SequenceNumber()),
AckNum: Uint32(h.AckNumber()),
DataOffset: Uint8(h.DataOffset()),
- Flags: Uint8(h.Flags()),
+ Flags: TCPFlags(h.Flags()),
WindowSize: Uint16(h.WindowSize()),
Checksum: Uint16(h.Checksum()),
UrgentPointer: Uint16(h.UrgentPointer()),
diff --git a/test/packetimpact/testbench/layers_test.go b/test/packetimpact/testbench/layers_test.go
index eca0780b5..614a5de1e 100644
--- a/test/packetimpact/testbench/layers_test.go
+++ b/test/packetimpact/testbench/layers_test.go
@@ -178,7 +178,7 @@ func TestLayerStringFormat(t *testing.T) {
SeqNum: Uint32(3452155723),
AckNum: Uint32(2596996163),
DataOffset: Uint8(5),
- Flags: Uint8(20),
+ Flags: TCPFlags(header.TCPFlagRst | header.TCPFlagAck),
WindowSize: Uint16(64240),
Checksum: Uint16(0x2e2b),
},
@@ -188,7 +188,7 @@ func TestLayerStringFormat(t *testing.T) {
"SeqNum:3452155723 " +
"AckNum:2596996163 " +
"DataOffset:5 " +
- "Flags:20 " +
+ "Flags: R A " +
"WindowSize:64240 " +
"Checksum:11819" +
"}",
@@ -436,7 +436,7 @@ func TestTCPOptions(t *testing.T) {
DstPort: Uint16(54321),
SeqNum: Uint32(0),
AckNum: Uint32(0),
- Flags: Uint8(header.TCPFlagSyn),
+ Flags: TCPFlags(header.TCPFlagSyn),
WindowSize: Uint16(8192),
Checksum: Uint16(0xf51c),
UrgentPointer: Uint16(0),
@@ -480,7 +480,7 @@ func TestTCPOptions(t *testing.T) {
DstPort: Uint16(54321),
SeqNum: Uint32(0),
AckNum: Uint32(0),
- Flags: Uint8(header.TCPFlagSyn),
+ Flags: TCPFlags(header.TCPFlagSyn),
WindowSize: Uint16(8192),
Checksum: Uint16(0xe521),
UrgentPointer: Uint16(0),
diff --git a/test/packetimpact/testbench/testbench.go b/test/packetimpact/testbench/testbench.go
index 891897d55..a73c07e64 100644
--- a/test/packetimpact/testbench/testbench.go
+++ b/test/packetimpact/testbench/testbench.go
@@ -34,14 +34,29 @@ var (
// RPCTimeout is the gRPC timeout.
RPCTimeout = 100 * time.Millisecond
- // dutTestNetsJSON is the json string that describes all the test networks to
+ // dutInfosJSON is the json string that describes information about all the
// duts available to use.
- dutTestNetsJSON string
- // dutTestNets is the pool among which the testbench can choose a DUT to work
+ dutInfosJSON string
+ // dutInfo is the pool among which the testbench can choose a DUT to work
// with.
- dutTestNets chan *DUTTestNet
+ dutInfo chan *DUTInfo
)
+// DUTInfo has both network and uname information about the DUT.
+type DUTInfo struct {
+ Uname *DUTUname
+ Net *DUTTestNet
+}
+
+// DUTUname contains information about the DUT from uname.
+type DUTUname struct {
+ Machine string
+ KernelName string
+ KernelRelease string
+ KernelVersion string
+ OperatingSystem string
+}
+
// DUTTestNet describes the test network setup on dut and how the testbench
// should connect with an existing DUT.
type DUTTestNet struct {
@@ -86,7 +101,7 @@ func registerFlags(fs *flag.FlagSet) {
fs.BoolVar(&Native, "native", Native, "whether the test is running natively")
fs.DurationVar(&RPCTimeout, "rpc_timeout", RPCTimeout, "gRPC timeout")
fs.DurationVar(&RPCKeepalive, "rpc_keepalive", RPCKeepalive, "gRPC keepalive")
- fs.StringVar(&dutTestNetsJSON, "dut_test_nets_json", dutTestNetsJSON, "path to the dut test nets json file")
+ fs.StringVar(&dutInfosJSON, "dut_infos_json", dutInfosJSON, "json that describes the DUTs")
}
// Initialize initializes the testbench, it parse the flags and sets up the
@@ -94,27 +109,27 @@ func registerFlags(fs *flag.FlagSet) {
func Initialize(fs *flag.FlagSet) {
registerFlags(fs)
flag.Parse()
- if err := loadDUTTestNets(); err != nil {
+ if err := loadDUTInfos(); err != nil {
panic(err)
}
}
-// loadDUTTestNets loads available DUT test networks from the json file, it
+// loadDUTInfos loads available DUT test infos from the json file, it
// must be called after flag.Parse().
-func loadDUTTestNets() error {
- var parsedTestNets []DUTTestNet
- if err := json.Unmarshal([]byte(dutTestNetsJSON), &parsedTestNets); err != nil {
+func loadDUTInfos() error {
+ var dutInfos []DUTInfo
+ if err := json.Unmarshal([]byte(dutInfosJSON), &dutInfos); err != nil {
return fmt.Errorf("failed to unmarshal JSON: %w", err)
}
- if got, want := len(parsedTestNets), 1; got < want {
+ if got, want := len(dutInfos), 1; got < want {
return fmt.Errorf("got %d DUTs, the test requires at least %d DUTs", got, want)
}
// Using a buffered channel as semaphore
- dutTestNets = make(chan *DUTTestNet, len(parsedTestNets))
- for i := range parsedTestNets {
- parsedTestNets[i].LocalIPv4 = parsedTestNets[i].LocalIPv4.To4()
- parsedTestNets[i].RemoteIPv4 = parsedTestNets[i].RemoteIPv4.To4()
- dutTestNets <- &parsedTestNets[i]
+ dutInfo = make(chan *DUTInfo, len(dutInfos))
+ for i := range dutInfos {
+ dutInfos[i].Net.LocalIPv4 = dutInfos[i].Net.LocalIPv4.To4()
+ dutInfos[i].Net.RemoteIPv4 = dutInfos[i].Net.RemoteIPv4.To4()
+ dutInfo <- &dutInfos[i]
}
return nil
}
@@ -130,14 +145,13 @@ func GenerateRandomPayload(t *testing.T, n int) []byte {
return buf
}
-// GetDUTTestNet gets a usable DUTTestNet, the function will block until any
-// becomes available.
-func GetDUTTestNet() *DUTTestNet {
- return <-dutTestNets
+// getDUTInfo returns information about an available DUT from the pool. If no
+// DUT is readily available, getDUTInfo blocks until one becomes available.
+func getDUTInfo() *DUTInfo {
+ return <-dutInfo
}
-// Release releases the DUTTestNet back to the pool so that some other test
-// can use.
-func (n *DUTTestNet) Release() {
- dutTestNets <- n
+// release returns the DUTInfo back to the pool.
+func (info *DUTInfo) release() {
+ dutInfo <- info
}
diff --git a/test/packetimpact/tests/BUILD b/test/packetimpact/tests/BUILD
index 301cf4980..d5cb0ae06 100644
--- a/test/packetimpact/tests/BUILD
+++ b/test/packetimpact/tests/BUILD
@@ -124,6 +124,17 @@ packetimpact_testbench(
)
packetimpact_testbench(
+ name = "tcp_outside_the_window_closing",
+ srcs = ["tcp_outside_the_window_closing_test.go"],
+ deps = [
+ "//pkg/tcpip/header",
+ "//pkg/tcpip/seqnum",
+ "//test/packetimpact/testbench",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
+
+packetimpact_testbench(
name = "tcp_noaccept_close_rst",
srcs = ["tcp_noaccept_close_rst_test.go"],
deps = [
@@ -155,6 +166,17 @@ packetimpact_testbench(
)
packetimpact_testbench(
+ name = "tcp_unacc_seq_ack_closing",
+ srcs = ["tcp_unacc_seq_ack_closing_test.go"],
+ deps = [
+ "//pkg/tcpip/header",
+ "//pkg/tcpip/seqnum",
+ "//test/packetimpact/testbench",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
+
+packetimpact_testbench(
name = "tcp_paws_mechanism",
srcs = ["tcp_paws_mechanism_test.go"],
deps = [
@@ -375,6 +397,16 @@ packetimpact_testbench(
],
)
+packetimpact_testbench(
+ name = "tcp_fin_retransmission",
+ srcs = ["tcp_fin_retransmission_test.go"],
+ deps = [
+ "//pkg/tcpip/header",
+ "//test/packetimpact/testbench",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
+
validate_all_tests()
[packetimpact_go_test(
diff --git a/test/packetimpact/tests/fin_wait2_timeout_test.go b/test/packetimpact/tests/fin_wait2_timeout_test.go
index 11f0fcd1e..cff8ca51d 100644
--- a/test/packetimpact/tests/fin_wait2_timeout_test.go
+++ b/test/packetimpact/tests/fin_wait2_timeout_test.go
@@ -51,21 +51,21 @@ func TestFinWait2Timeout(t *testing.T) {
}
dut.Close(t, acceptFd)
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected a FIN-ACK within 1 second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
time.Sleep(5 * time.Second)
conn.Drain(t)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
if tt.linger2 {
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, time.Second); err != nil {
t.Fatalf("expected a RST packet within a second but got none: %s", err)
}
} else {
- if got, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, 10*time.Second); got != nil || err == nil {
+ if got, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, 10*time.Second); got != nil || err == nil {
t.Fatalf("expected no RST packets within ten seconds but got one: %s", got)
}
}
diff --git a/test/packetimpact/tests/ipv4_id_uniqueness_test.go b/test/packetimpact/tests/ipv4_id_uniqueness_test.go
index a63b41366..2b69ceecb 100644
--- a/test/packetimpact/tests/ipv4_id_uniqueness_test.go
+++ b/test/packetimpact/tests/ipv4_id_uniqueness_test.go
@@ -100,7 +100,7 @@ func TestIPv4RetransmitIdentificationUniqueness(t *testing.T) {
// Let the DUT estimate RTO with RTT from the DATA-ACK.
// TODO(gvisor.dev/issue/2685) Estimate RTO during handshake, after which
// we can skip sending this ACK.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
dut.Send(t, remoteFD, tc.payload, 0)
expectTCP := &testbench.TCP{SeqNum: testbench.Uint32(uint32(*conn.RemoteSeqNum(t)))}
diff --git a/test/packetimpact/tests/tcp_cork_mss_test.go b/test/packetimpact/tests/tcp_cork_mss_test.go
index a7ba5035e..1db3c9883 100644
--- a/test/packetimpact/tests/tcp_cork_mss_test.go
+++ b/test/packetimpact/tests/tcp_cork_mss_test.go
@@ -60,24 +60,24 @@ func TestTCPCorkMSS(t *testing.T) {
// Expect the segments to be coalesced and sent and capped to MSS.
expectedPayload := testbench.Payload{Bytes: expectedData[:mss]}
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, &expectedPayload, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, &expectedPayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
// Expect the coalesced segment to be split and transmitted.
expectedPayload = testbench.Payload{Bytes: expectedData[mss:]}
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, &expectedPayload, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, &expectedPayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
// Check for segments to *not* be held up because of TCP_CORK when
// the current send window is less than MSS.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(uint16(2 * len(sampleData)))})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(uint16(2 * len(sampleData)))})
dut.Send(t, acceptFD, sampleData, 0)
dut.Send(t, acceptFD, sampleData, 0)
expectedPayload = testbench.Payload{Bytes: append(sampleData, sampleData...)}
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, &expectedPayload, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, &expectedPayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
}
diff --git a/test/packetimpact/tests/tcp_fin_retransmission_test.go b/test/packetimpact/tests/tcp_fin_retransmission_test.go
new file mode 100644
index 000000000..500f7a783
--- /dev/null
+++ b/test/packetimpact/tests/tcp_fin_retransmission_test.go
@@ -0,0 +1,87 @@
+// Copyright 2020 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tcp_fin_retransmission_test
+
+import (
+ "flag"
+ "testing"
+ "time"
+
+ "golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/tcpip/header"
+ "gvisor.dev/gvisor/test/packetimpact/testbench"
+)
+
+func init() {
+ testbench.Initialize(flag.CommandLine)
+}
+
+// TestTCPClosingFinRetransmission tests that TCP implementation should retransmit
+// FIN segment in CLOSING state.
+func TestTCPClosingFinRetransmission(t *testing.T) {
+ for _, tt := range []struct {
+ description string
+ flags header.TCPFlags
+ }{
+ {"CLOSING", header.TCPFlagAck | header.TCPFlagFin},
+ {"FIN_WAIT_1", header.TCPFlagAck},
+ } {
+ t.Run(tt.description, func(t *testing.T) {
+ dut := testbench.NewDUT(t)
+ listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
+ defer dut.Close(t, listenFD)
+ conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
+ defer conn.Close(t)
+ conn.Connect(t)
+ acceptFD, _ := dut.Accept(t, listenFD)
+ defer dut.Close(t, acceptFD)
+
+ // Give a chance for the dut to estimate RTO with RTT from the DATA-ACK.
+ // TODO(gvisor.dev/issue/2685) Estimate RTO during handshake, after which
+ // we can skip the next block of code.
+ sampleData := []byte("Sample Data")
+ if got, want := dut.Send(t, acceptFD, sampleData, 0), len(sampleData); int(got) != want {
+ t.Fatalf("got dut.Send(t, %d, %s, 0) = %d, want %d", acceptFD, sampleData, got, want)
+ }
+ if _, err := conn.ExpectData(t, &testbench.TCP{}, &testbench.Payload{Bytes: sampleData}, time.Second); err != nil {
+ t.Fatalf("expected payload was not received: %s", err)
+ }
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
+
+ dut.Shutdown(t, acceptFD, unix.SHUT_WR)
+
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ t.Fatalf("expected FINACK from DUT, but got none: %s", err)
+ }
+
+ // Do not ack the FIN from DUT so that we can test for retransmission.
+ seqNumForTheirFIN := testbench.Uint32(uint32(*conn.RemoteSeqNum(t)) - 1)
+ conn.Send(t, testbench.TCP{AckNum: seqNumForTheirFIN, Flags: testbench.TCPFlags(tt.flags)})
+
+ if tt.flags&header.TCPFlagFin != 0 {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
+ t.Errorf("expected an ACK to our FIN, but got none: %s", err)
+ }
+ }
+
+ if _, err := conn.Expect(t, testbench.TCP{
+ SeqNum: seqNumForTheirFIN,
+ Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck),
+ }, time.Second); err != nil {
+ t.Errorf("expected retransmission of FIN from the DUT: %s", err)
+ }
+ })
+ }
+}
diff --git a/test/packetimpact/tests/tcp_handshake_window_size_test.go b/test/packetimpact/tests/tcp_handshake_window_size_test.go
index 5d1266f3c..668e0275c 100644
--- a/test/packetimpact/tests/tcp_handshake_window_size_test.go
+++ b/test/packetimpact/tests/tcp_handshake_window_size_test.go
@@ -38,8 +38,8 @@ func TestTCPHandshakeWindowSize(t *testing.T) {
defer conn.Close(t)
// Start handshake with zero window size.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn), WindowSize: testbench.Uint16(uint16(0))})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn), WindowSize: testbench.Uint16(uint16(0))})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
t.Fatalf("expected SYN-ACK: %s", err)
}
// Update the advertised window size to a non-zero value with the ACK that
@@ -47,7 +47,7 @@ func TestTCPHandshakeWindowSize(t *testing.T) {
//
// Set the window size with MSB set and expect the dut to treat it as
// an unsigned value.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(uint16(1 << 15))})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(uint16(1 << 15))})
acceptFd, _ := dut.Accept(t, listenFD)
defer dut.Close(t, acceptFd)
@@ -59,7 +59,7 @@ func TestTCPHandshakeWindowSize(t *testing.T) {
// expect the dut to honor the recently advertised non-zero window
// and actually send out the data instead of probing for zero window.
dut.Send(t, acceptFd, sampleData, 0)
- if _, err := conn.ExpectNextData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload, time.Second); err != nil {
+ if _, err := conn.ExpectNextData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
}
diff --git a/test/packetimpact/tests/tcp_info_test.go b/test/packetimpact/tests/tcp_info_test.go
index 69275e54b..3fc2c7fe5 100644
--- a/test/packetimpact/tests/tcp_info_test.go
+++ b/test/packetimpact/tests/tcp_info_test.go
@@ -51,7 +51,7 @@ func TestTCPInfo(t *testing.T) {
if _, err := conn.ExpectData(t, &testbench.TCP{}, samplePayload, time.Second); err != nil {
t.Fatalf("expected a packet with payload %v: %s", samplePayload, err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
info := linux.TCPInfo{}
infoBytes := dut.GetSockOpt(t, acceptFD, unix.SOL_TCP, unix.TCP_INFO, int32(linux.SizeOfTCPInfo))
diff --git a/test/packetimpact/tests/tcp_linger_test.go b/test/packetimpact/tests/tcp_linger_test.go
index bc4b64388..88942904d 100644
--- a/test/packetimpact/tests/tcp_linger_test.go
+++ b/test/packetimpact/tests/tcp_linger_test.go
@@ -17,7 +17,6 @@ package tcp_linger_test
import (
"context"
"flag"
- "syscall"
"testing"
"time"
@@ -58,10 +57,10 @@ func TestTCPLingerZeroTimeout(t *testing.T) {
dut.Close(t, acceptFD)
// If the linger timeout is set to zero, the DUT should send a RST.
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected RST-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
}
// TestTCPLingerOff tests when SO_LINGER is not set. DUT should send FIN-ACK
@@ -75,10 +74,10 @@ func TestTCPLingerOff(t *testing.T) {
dut.Close(t, acceptFD)
// If SO_LINGER is not set, DUT should send a FIN-ACK.
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected FIN-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
}
// TestTCPLingerNonZeroTimeout tests when SO_LINGER is set with non-zero timeout.
@@ -115,10 +114,10 @@ func TestTCPLingerNonZeroTimeout(t *testing.T) {
t.Errorf("expected close to return within a second, but returned later")
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected FIN-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
})
}
}
@@ -166,10 +165,10 @@ func TestTCPLingerSendNonZeroTimeout(t *testing.T) {
t.Fatalf("expected a packet with payload %v: %s", samplePayload, err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected FIN-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
})
}
}
@@ -183,19 +182,19 @@ func TestTCPLingerShutdownZeroTimeout(t *testing.T) {
defer closeAll(t, dut, listenFD, conn)
dut.SetSockLingerOption(t, acceptFD, 0, true)
- dut.Shutdown(t, acceptFD, syscall.SHUT_RDWR)
+ dut.Shutdown(t, acceptFD, unix.SHUT_RDWR)
dut.Close(t, acceptFD)
// Shutdown will send FIN-ACK with read/write option.
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected FIN-ACK packet within a second but got none: %s", err)
}
// If the linger timeout is set to zero, the DUT should send a RST.
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected RST-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
}
// TestTCPLingerShutdownSendNonZeroTimeout tests SO_LINGER with shutdown() and
@@ -220,7 +219,7 @@ func TestTCPLingerShutdownSendNonZeroTimeout(t *testing.T) {
sampleData := []byte("Sample Data")
dut.Send(t, acceptFD, sampleData, 0)
- dut.Shutdown(t, acceptFD, syscall.SHUT_RDWR)
+ dut.Shutdown(t, acceptFD, unix.SHUT_RDWR)
// Increase timeout as Close will take longer time to
// return when SO_LINGER is set with non-zero timeout.
@@ -243,10 +242,10 @@ func TestTCPLingerShutdownSendNonZeroTimeout(t *testing.T) {
t.Fatalf("expected a packet with payload %v: %s", samplePayload, err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected FIN-ACK packet within a second but got none: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
})
}
}
diff --git a/test/packetimpact/tests/tcp_network_unreachable_test.go b/test/packetimpact/tests/tcp_network_unreachable_test.go
index 53dc903e4..5168450ad 100644
--- a/test/packetimpact/tests/tcp_network_unreachable_test.go
+++ b/test/packetimpact/tests/tcp_network_unreachable_test.go
@@ -17,7 +17,6 @@ package tcp_synsent_reset_test
import (
"context"
"flag"
- "syscall"
"testing"
"time"
@@ -46,12 +45,12 @@ func TestTCPSynSentUnreachable(t *testing.T) {
defer cancel()
sa := unix.SockaddrInet4{Port: int(port)}
copy(sa.Addr[:], dut.Net.LocalIPv4)
- if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != syscall.Errno(unix.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != unix.EINPROGRESS {
t.Errorf("got connect() = %v, want EINPROGRESS", err)
}
// Get the SYN.
- tcpLayers, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, nil, time.Second)
+ tcpLayers, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, nil, time.Second)
if err != nil {
t.Fatalf("expected SYN: %s", err)
}
@@ -100,12 +99,12 @@ func TestTCPSynSentUnreachable6(t *testing.T) {
ZoneId: dut.Net.RemoteDevID,
}
copy(sa.Addr[:], dut.Net.LocalIPv6)
- if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != syscall.Errno(unix.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != unix.EINPROGRESS {
t.Errorf("got connect() = %v, want EINPROGRESS", err)
}
// Get the SYN.
- tcpLayers, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, nil, time.Second)
+ tcpLayers, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, nil, time.Second)
if err != nil {
t.Fatalf("expected SYN: %s", err)
}
@@ -156,7 +155,7 @@ func getConnectError(t *testing.T, dut *testbench.DUT, fd int32) error {
// failure).
dut.PollOne(t, fd, unix.POLLOUT, 10*time.Second)
if errno := dut.GetSockOptInt(t, fd, unix.SOL_SOCKET, unix.SO_ERROR); errno != 0 {
- return syscall.Errno(errno)
+ return unix.Errno(errno)
}
return nil
}
diff --git a/test/packetimpact/tests/tcp_noaccept_close_rst_test.go b/test/packetimpact/tests/tcp_noaccept_close_rst_test.go
index d2871df08..14eb7d93b 100644
--- a/test/packetimpact/tests/tcp_noaccept_close_rst_test.go
+++ b/test/packetimpact/tests/tcp_noaccept_close_rst_test.go
@@ -40,7 +40,7 @@ func TestTcpNoAcceptCloseReset(t *testing.T) {
// it will only respond RST instead of RST+ACK.
dut.PollOne(t, listenFd, unix.POLLIN, time.Second)
dut.Close(t, listenFd)
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)}, 1*time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)}, 1*time.Second); err != nil {
t.Fatalf("expected a RST-ACK packet but got none: %s", err)
}
}
diff --git a/test/packetimpact/tests/tcp_outside_the_window_closing_test.go b/test/packetimpact/tests/tcp_outside_the_window_closing_test.go
new file mode 100644
index 000000000..1097746c7
--- /dev/null
+++ b/test/packetimpact/tests/tcp_outside_the_window_closing_test.go
@@ -0,0 +1,86 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tcp_outside_the_window_closing_test
+
+import (
+ "flag"
+ "fmt"
+ "testing"
+ "time"
+
+ "golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/tcpip/header"
+ "gvisor.dev/gvisor/pkg/tcpip/seqnum"
+ "gvisor.dev/gvisor/test/packetimpact/testbench"
+)
+
+func init() {
+ testbench.Initialize(flag.CommandLine)
+}
+
+// TestAckOTWSeqInClosing tests that the DUT should send an ACK with
+// the right ACK number when receiving a packet with OTW Seq number
+// in CLOSING state. https://tools.ietf.org/html/rfc793#page-69
+func TestAckOTWSeqInClosing(t *testing.T) {
+ for seqNumOffset := seqnum.Size(0); seqNumOffset < 3; seqNumOffset++ {
+ for _, tt := range []struct {
+ description string
+ flags header.TCPFlags
+ payloads testbench.Layers
+ }{
+ {"SYN", header.TCPFlagSyn, nil},
+ {"SYNACK", header.TCPFlagSyn | header.TCPFlagAck, nil},
+ {"ACK", header.TCPFlagAck, nil},
+ {"FINACK", header.TCPFlagFin | header.TCPFlagAck, nil},
+ {"Data", header.TCPFlagAck, []testbench.Layer{&testbench.Payload{Bytes: []byte("abc123")}}},
+ } {
+ t.Run(fmt.Sprintf("%s%d", tt.description, seqNumOffset), func(t *testing.T) {
+ dut := testbench.NewDUT(t)
+ listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
+ defer dut.Close(t, listenFD)
+ conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
+ defer conn.Close(t)
+ conn.Connect(t)
+ acceptFD, _ := dut.Accept(t, listenFD)
+ defer dut.Close(t, acceptFD)
+
+ dut.Shutdown(t, acceptFD, unix.SHUT_WR)
+
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second); err != nil {
+ t.Fatalf("expected FINACK from DUT, but got none: %s", err)
+ }
+
+ // Do not ack the FIN from DUT so that the TCP state on DUT is CLOSING instead of CLOSED.
+ seqNumForTheirFIN := testbench.Uint32(uint32(*conn.RemoteSeqNum(t)) - 1)
+ conn.Send(t, testbench.TCP{AckNum: seqNumForTheirFIN, Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)})
+
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
+ t.Errorf("expected an ACK to our FIN, but got none: %s", err)
+ }
+
+ windowSize := seqnum.Size(*conn.SynAck(t).WindowSize) + seqNumOffset
+ conn.SendFrameStateless(t, conn.CreateFrame(t, testbench.Layers{&testbench.TCP{
+ SeqNum: testbench.Uint32(uint32(conn.LocalSeqNum(t).Add(windowSize))),
+ AckNum: seqNumForTheirFIN,
+ Flags: testbench.TCPFlags(tt.flags),
+ }}, tt.payloads...))
+
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
+ t.Errorf("expected an ACK but got none: %s", err)
+ }
+ })
+ }
+ }
+}
diff --git a/test/packetimpact/tests/tcp_outside_the_window_test.go b/test/packetimpact/tests/tcp_outside_the_window_test.go
index 8909a348e..7cd7ff703 100644
--- a/test/packetimpact/tests/tcp_outside_the_window_test.go
+++ b/test/packetimpact/tests/tcp_outside_the_window_test.go
@@ -37,7 +37,7 @@ func init() {
func TestTCPOutsideTheWindow(t *testing.T) {
for _, tt := range []struct {
description string
- tcpFlags uint8
+ tcpFlags header.TCPFlags
payload []testbench.Layer
seqNumOffset seqnum.Size
expectACK bool
@@ -76,11 +76,11 @@ func TestTCPOutsideTheWindow(t *testing.T) {
// to the AckNum.
localSeqNum := testbench.Uint32(uint32(*conn.LocalSeqNum(t)))
conn.Send(t, testbench.TCP{
- Flags: testbench.Uint8(tt.tcpFlags),
+ Flags: testbench.TCPFlags(tt.tcpFlags),
SeqNum: testbench.Uint32(uint32(conn.LocalSeqNum(t).Add(windowSize))),
}, tt.payload...)
- timeout := 3 * time.Second
- gotACK, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: localSeqNum}, timeout)
+ timeout := time.Second
+ gotACK, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: localSeqNum}, timeout)
if tt.expectACK && err != nil {
t.Fatalf("expected an ACK packet within %s but got none: %s", timeout, err)
}
@@ -93,11 +93,11 @@ func TestTCPOutsideTheWindow(t *testing.T) {
// has passed since the last ACK was sent.
t.Logf("sending another segment")
conn.Send(t, testbench.TCP{
- Flags: testbench.Uint8(tt.tcpFlags),
+ Flags: testbench.TCPFlags(tt.tcpFlags),
SeqNum: testbench.Uint32(uint32(conn.LocalSeqNum(t).Add(windowSize))),
}, tt.payload...)
timeout := 3 * time.Second
- gotACK, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: localSeqNum}, timeout)
+ gotACK, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: localSeqNum}, timeout)
if err == nil {
t.Fatalf("expected no ACK packet but got one: %s", gotACK)
}
diff --git a/test/packetimpact/tests/tcp_paws_mechanism_test.go b/test/packetimpact/tests/tcp_paws_mechanism_test.go
index 24d9ef4ec..9054955ea 100644
--- a/test/packetimpact/tests/tcp_paws_mechanism_test.go
+++ b/test/packetimpact/tests/tcp_paws_mechanism_test.go
@@ -38,8 +38,8 @@ func TestPAWSMechanism(t *testing.T) {
options := make([]byte, header.TCPOptionTSLength)
header.EncodeTSOption(currentTS(), 0, options)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn), Options: options})
- synAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn), Options: options})
+ synAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("didn't get synack during handshake: %s", err)
}
@@ -49,7 +49,7 @@ func TestPAWSMechanism(t *testing.T) {
}
tsecr := parsedSynOpts.TSVal
header.EncodeTSOption(currentTS(), tsecr, options)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), Options: options})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), Options: options})
acceptFD, _ := dut.Accept(t, listenFD)
defer dut.Close(t, acceptFD)
@@ -60,9 +60,9 @@ func TestPAWSMechanism(t *testing.T) {
// every time we send one, it should not cause any flakiness because timestamps
// only need to be non-decreasing.
time.Sleep(3 * time.Millisecond)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), Options: options}, &testbench.Payload{Bytes: sampleData})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), Options: options}, &testbench.Payload{Bytes: sampleData})
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected an ACK but got none: %s", err)
}
@@ -85,9 +85,9 @@ func TestPAWSMechanism(t *testing.T) {
// 3ms here is chosen arbitrarily and this time.Sleep() should not cause flakiness
// due to the exact same reasoning discussed above.
time.Sleep(3 * time.Millisecond)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), Options: options}, &testbench.Payload{Bytes: sampleData})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), Options: options}, &testbench.Payload{Bytes: sampleData})
- gotTCP, err = conn.Expect(t, testbench.TCP{AckNum: lastAckNum, Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ gotTCP, err = conn.Expect(t, testbench.TCP{AckNum: lastAckNum, Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected segment with AckNum %d but got none: %s", lastAckNum, err)
}
diff --git a/test/packetimpact/tests/tcp_queue_send_recv_in_syn_sent_test.go b/test/packetimpact/tests/tcp_queue_send_recv_in_syn_sent_test.go
index 7dd1c326a..1c8b72ebe 100644
--- a/test/packetimpact/tests/tcp_queue_send_recv_in_syn_sent_test.go
+++ b/test/packetimpact/tests/tcp_queue_send_recv_in_syn_sent_test.go
@@ -21,7 +21,6 @@ import (
"errors"
"flag"
"sync"
- "syscall"
"testing"
"time"
@@ -45,10 +44,10 @@ func TestQueueSendInSynSentHandshake(t *testing.T) {
sampleData := []byte("Sample Data")
dut.SetNonBlocking(t, socket, true)
- if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, syscall.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, unix.EINPROGRESS) {
t.Fatalf("failed to bring DUT to SYN-SENT, got: %s, want EINPROGRESS", err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, time.Second); err != nil {
t.Fatalf("expected a SYN from DUT, but got none: %s", err)
}
@@ -85,19 +84,19 @@ func TestQueueSendInSynSentHandshake(t *testing.T) {
time.Sleep(100 * time.Millisecond)
// Bring the connection to Established.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)})
// Expect the data from the DUT's enqueued send request.
//
// On Linux, this can be piggybacked with the ACK completing the
// handshake. On gVisor, getting such a piggyback is a bit more
// complicated because the actual data enqueuing occurs in the
// callers of endpoint Write.
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData}, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData}, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData})
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData})
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected an ACK from DUT, but got none: %s", err)
}
}
@@ -113,15 +112,15 @@ func TestQueueRecvInSynSentHandshake(t *testing.T) {
sampleData := []byte("Sample Data")
dut.SetNonBlocking(t, socket, true)
- if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, syscall.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, unix.EINPROGRESS) {
t.Fatalf("failed to bring DUT to SYN-SENT, got: %s, want EINPROGRESS", err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, time.Second); err != nil {
t.Fatalf("expected a SYN from DUT, but got none: %s", err)
}
- if _, _, err := dut.RecvWithErrno(context.Background(), t, socket, int32(len(sampleData)), 0); err != syscall.Errno(unix.EWOULDBLOCK) {
- t.Fatalf("expected error %s, got %s", syscall.Errno(unix.EWOULDBLOCK), err)
+ if _, _, err := dut.RecvWithErrno(context.Background(), t, socket, int32(len(sampleData)), 0); err != unix.EWOULDBLOCK {
+ t.Fatalf("expected error %s, got %s", unix.EWOULDBLOCK, err)
}
// Test blocking read.
@@ -160,14 +159,14 @@ func TestQueueRecvInSynSentHandshake(t *testing.T) {
time.Sleep(100 * time.Millisecond)
// Bring the connection to Established.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)})
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)})
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected an ACK from DUT, but got none: %s", err)
}
// Send sample payload so that DUT can recv.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData})
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagPsh | header.TCPFlagAck)}, &testbench.Payload{Bytes: sampleData})
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected an ACK from DUT, but got none: %s", err)
}
}
@@ -183,10 +182,10 @@ func TestQueueSendInSynSentRST(t *testing.T) {
sampleData := []byte("Sample Data")
dut.SetNonBlocking(t, socket, true)
- if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, syscall.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, unix.EINPROGRESS) {
t.Fatalf("failed to bring DUT to SYN-SENT, got: %s, want EINPROGRESS", err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, time.Second); err != nil {
t.Fatalf("expected a SYN from DUT, but got none: %s", err)
}
@@ -207,8 +206,8 @@ func TestQueueSendInSynSentRST(t *testing.T) {
// Issue SEND call in SYN-SENT, this should be queued for
// process until the connection is established.
n, err := dut.SendWithErrno(ctx, t, socket, sampleData, 0)
- if err != syscall.Errno(unix.ECONNREFUSED) {
- t.Errorf("expected error %s, got %s", syscall.Errno(unix.ECONNREFUSED), err)
+ if err != unix.ECONNREFUSED {
+ t.Errorf("expected error %s, got %s", unix.ECONNREFUSED, err)
}
if n != -1 {
t.Errorf("expected return value %d, got %d", -1, n)
@@ -224,7 +223,7 @@ func TestQueueSendInSynSentRST(t *testing.T) {
// request and the system actually being blocked.
time.Sleep(100 * time.Millisecond)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)})
}
// TestQueueRecvInSynSentRST tests recv behavior when the TCP state
@@ -238,15 +237,15 @@ func TestQueueRecvInSynSentRST(t *testing.T) {
sampleData := []byte("Sample Data")
dut.SetNonBlocking(t, socket, true)
- if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, syscall.EINPROGRESS) {
+ if _, err := dut.ConnectWithErrno(context.Background(), t, socket, conn.LocalAddr(t)); !errors.Is(err, unix.EINPROGRESS) {
t.Fatalf("failed to bring DUT to SYN-SENT, got: %s, want EINPROGRESS", err)
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, time.Second); err != nil {
t.Fatalf("expected a SYN from DUT, but got none: %s", err)
}
- if _, _, err := dut.RecvWithErrno(context.Background(), t, socket, int32(len(sampleData)), 0); err != syscall.Errno(unix.EWOULDBLOCK) {
- t.Fatalf("expected error %s, got %s", syscall.Errno(unix.EWOULDBLOCK), err)
+ if _, _, err := dut.RecvWithErrno(context.Background(), t, socket, int32(len(sampleData)), 0); err != unix.EWOULDBLOCK {
+ t.Fatalf("expected error %s, got %s", unix.EWOULDBLOCK, err)
}
// Test blocking read.
@@ -266,8 +265,8 @@ func TestQueueRecvInSynSentRST(t *testing.T) {
// Issue RECEIVE call in SYN-SENT, this should be queued for
// process until the connection is established.
n, _, err := dut.RecvWithErrno(ctx, t, socket, int32(len(sampleData)), 0)
- if err != syscall.Errno(unix.ECONNREFUSED) {
- t.Errorf("expected error %s, got %s", syscall.Errno(unix.ECONNREFUSED), err)
+ if err != unix.ECONNREFUSED {
+ t.Errorf("expected error %s, got %s", unix.ECONNREFUSED, err)
}
if n != -1 {
t.Errorf("expected return value %d, got %d", -1, n)
@@ -283,5 +282,5 @@ func TestQueueRecvInSynSentRST(t *testing.T) {
// request and the system actually being blocked.
time.Sleep(100 * time.Millisecond)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)})
}
diff --git a/test/packetimpact/tests/tcp_rack_test.go b/test/packetimpact/tests/tcp_rack_test.go
index ef902c54d..0a5b0f12b 100644
--- a/test/packetimpact/tests/tcp_rack_test.go
+++ b/test/packetimpact/tests/tcp_rack_test.go
@@ -97,7 +97,7 @@ func sendAndReceive(t *testing.T, dut testbench.DUT, conn testbench.TCPIPv4, num
if sendACK {
time.Sleep(simulatedRTT)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(sn))})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(sn))})
}
}
return lastSent
@@ -149,7 +149,7 @@ func TestRACKTLPLost(t *testing.T) {
// Cumulative ACK for #[1-5] packets.
ackNum := seqNum1.Add(seqnum.Size(6 * payloadSize))
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(ackNum))})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(ackNum))})
// Probe Timeout (PTO) should be two times RTT. Check that the last
// packet is retransmitted after probe timeout.
@@ -194,7 +194,7 @@ func TestRACKWithSACK(t *testing.T) {
sbOff += header.EncodeSACKBlocks([]header.SACKBlock{{
start, end,
}}, sackBlock[sbOff:])
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
rtt, _ := getRTTAndRTO(t, dut, acceptFd)
timeout := 2 * rtt
@@ -206,7 +206,7 @@ func TestRACKWithSACK(t *testing.T) {
time.Sleep(simulatedRTT)
// ACK for #1 packet.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(end))})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(end))})
// RACK considers transmission times of the packets to mark them lost.
// As the 3rd packet was sent before the retransmitted 1st packet, RACK
@@ -243,7 +243,7 @@ func TestRACKWithoutReorder(t *testing.T) {
start, end,
}}, sackBlock[sbOff:])
time.Sleep(simulatedRTT)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
// RACK marks #1 and #2 packets as lost and retransmits both after
// RTT + reorderWindow. The reorderWindow initially will be a small
@@ -289,7 +289,7 @@ func TestRACKWithReorder(t *testing.T) {
sbOff += header.EncodeSACKBlocks([]header.SACKBlock{{
start, end,
}}, sackBlock[sbOff:])
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
}
// Send a DSACK block indicating both original and retransmitted
@@ -304,7 +304,7 @@ func TestRACKWithReorder(t *testing.T) {
dbOff += header.EncodeSACKBlocks([]header.SACKBlock{{
start, end,
}}, dsackBlock[dbOff:])
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1 + numPkts*payloadSize)), Options: dsackBlock[:dbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1 + numPkts*payloadSize)), Options: dsackBlock[:dbOff]})
seqNum1.UpdateForward(seqnum.Size(numPkts * payloadSize))
sendTime := time.Now()
@@ -321,7 +321,7 @@ func TestRACKWithReorder(t *testing.T) {
sbOff += header.EncodeSACKBlocks([]header.SACKBlock{{
start, end,
}}, sackBlock[sbOff:])
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
// Expect the retransmission of #1 packet after RTT+ReorderWindow.
if _, err := conn.Expect(t, testbench.TCP{SeqNum: testbench.Uint32(uint32(seqNum1))}, time.Second); err != nil {
@@ -361,7 +361,7 @@ func TestRACKWithLostRetransmission(t *testing.T) {
start, end,
}}, sackBlock[sbOff:])
time.Sleep(simulatedRTT)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock[:sbOff]})
// RACK marks #1 packet as lost and retransmits it after
// RTT + reorderWindow. The reorderWindow is bounded between a small
@@ -394,7 +394,7 @@ func TestRACKWithLostRetransmission(t *testing.T) {
start, end,
}}, sackBlock1[sbOff1:])
time.Sleep(simulatedRTT)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock1[:sbOff1]})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: testbench.Uint32(uint32(seqNum1)), Options: sackBlock1[:sbOff1]})
// Expect re-retransmission of #1 packet without entering an RTO.
if _, err := conn.Expect(t, testbench.TCP{SeqNum: testbench.Uint32(uint32(seqNum1))}, timeout); err != nil {
diff --git a/test/packetimpact/tests/tcp_rcv_buf_space_test.go b/test/packetimpact/tests/tcp_rcv_buf_space_test.go
index d6ad5cda6..f121d44eb 100644
--- a/test/packetimpact/tests/tcp_rcv_buf_space_test.go
+++ b/test/packetimpact/tests/tcp_rcv_buf_space_test.go
@@ -17,7 +17,6 @@ package tcp_rcv_buf_space_test
import (
"context"
"flag"
- "syscall"
"testing"
"golang.org/x/sys/unix"
@@ -61,7 +60,7 @@ func TestReduceRecvBuf(t *testing.T) {
payloadBytes = l
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, []testbench.Layer{&testbench.Payload{Bytes: payload[:payloadBytes]}}...)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, []testbench.Layer{&testbench.Payload{Bytes: payload[:payloadBytes]}}...)
payload = payload[payloadBytes:]
}
@@ -73,7 +72,7 @@ func TestReduceRecvBuf(t *testing.T) {
// Second read should return EAGAIN as the last segment should have been
// dropped due to it exceeding the receive buffer space available in the
// socket.
- if ret, got, err := dut.RecvWithErrno(context.Background(), t, acceptFd, int32(len(sampleData)), syscall.MSG_DONTWAIT); got != nil || ret != -1 || err != syscall.EAGAIN {
+ if ret, got, err := dut.RecvWithErrno(context.Background(), t, acceptFd, int32(len(sampleData)), unix.MSG_DONTWAIT); got != nil || ret != -1 || err != unix.EAGAIN {
t.Fatalf("expected no packets but got: %s", got)
}
}
diff --git a/test/packetimpact/tests/tcp_retransmits_test.go b/test/packetimpact/tests/tcp_retransmits_test.go
index ba79fbf55..3dc8f63ab 100644
--- a/test/packetimpact/tests/tcp_retransmits_test.go
+++ b/test/packetimpact/tests/tcp_retransmits_test.go
@@ -15,6 +15,7 @@
package tcp_retransmits_test
import (
+ "bytes"
"flag"
"testing"
"time"
@@ -59,38 +60,43 @@ func TestRetransmits(t *testing.T) {
sampleData := []byte("Sample Data")
samplePayload := &testbench.Payload{Bytes: sampleData}
+ // Give a chance for the dut to estimate RTO with RTT from the DATA-ACK.
+ // This is to reduce the test run-time from the default initial RTO of 1s.
+ // TODO(gvisor.dev/issue/2685) Estimate RTO during handshake, after which
+ // we can skip this data send/recv which is solely to estimate RTO.
dut.Send(t, acceptFd, sampleData, 0)
if _, err := conn.ExpectData(t, &testbench.TCP{}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- // Give a chance for the dut to estimate RTO with RTT from the DATA-ACK.
- // TODO(gvisor.dev/issue/2685) Estimate RTO during handshake, after which
- // we can skip sending this ACK.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, nil, time.Second); err != nil {
+ t.Fatalf("expected packet was not received: %s", err)
+ }
+ // Wait for the DUT to receive the data, thus ensuring that the stack has
+ // estimated RTO before we query RTO via TCP_INFO.
+ if got := dut.Recv(t, acceptFd, int32(len(sampleData)), 0); !bytes.Equal(got, sampleData) {
+ t.Fatalf("got dut.Recv(t, %d, %d, 0) = %s, want %s", acceptFd, len(sampleData), got, sampleData)
+ }
const timeoutCorrection = time.Second
- const diffCorrection = time.Millisecond
+ const diffCorrection = 200 * time.Millisecond
rto := getRTO(t, dut, acceptFd)
- timeout := rto + timeoutCorrection
- startTime := time.Now()
dut.Send(t, acceptFd, sampleData, 0)
seq := testbench.Uint32(uint32(*conn.RemoteSeqNum(t)))
- if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: seq}, samplePayload, timeout); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: seq}, samplePayload, rto+timeoutCorrection); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
// Expect retransmits of the same segment.
for i := 0; i < 5; i++ {
- if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: seq}, samplePayload, timeout); err != nil {
- t.Fatalf("expected payload was not received within %d loop %d err %s", timeout, i, err)
+ startTime := time.Now()
+ rto = getRTO(t, dut, acceptFd)
+ if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: seq}, samplePayload, rto+timeoutCorrection); err != nil {
+ t.Fatalf("expected payload was not received within %s loop %d err %s", rto+timeoutCorrection, i, err)
}
-
if diff := time.Since(startTime); diff+diffCorrection < rto {
- t.Fatalf("retransmit came sooner got: %d want: >= %d probe %d", diff, rto, i)
+ t.Fatalf("retransmit came sooner got: %s want: >= %s probe %d", diff+diffCorrection, rto, i)
}
- startTime = time.Now()
- rto = getRTO(t, dut, acceptFd)
- timeout = rto + timeoutCorrection
}
}
diff --git a/test/packetimpact/tests/tcp_send_window_sizes_piggyback_test.go b/test/packetimpact/tests/tcp_send_window_sizes_piggyback_test.go
index 418393796..64b7288fb 100644
--- a/test/packetimpact/tests/tcp_send_window_sizes_piggyback_test.go
+++ b/test/packetimpact/tests/tcp_send_window_sizes_piggyback_test.go
@@ -71,7 +71,7 @@ func TestSendWindowSizesPiggyback(t *testing.T) {
dut.SetSockOptInt(t, acceptFd, unix.IPPROTO_TCP, unix.TCP_NODELAY, 1)
- expectedTCP := testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}
+ expectedTCP := testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}
dut.Send(t, acceptFd, sampleData, 0)
expectedPayload := testbench.Payload{Bytes: tt.expectedPayload1}
@@ -90,7 +90,7 @@ func TestSendWindowSizesPiggyback(t *testing.T) {
// Send ACK for the previous segment along with data for the dut to
// receive and ACK back. Sending this ACK would make room for the dut
// to transmit any enqueued segment.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh), WindowSize: testbench.Uint16(tt.windowSize)}, &testbench.Payload{Bytes: sampleData})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh), WindowSize: testbench.Uint16(tt.windowSize)}, &testbench.Payload{Bytes: sampleData})
// Expect the dut to piggyback the ACK for received data along with
// the segment enqueued for transmit.
diff --git a/test/packetimpact/tests/tcp_synrcvd_reset_test.go b/test/packetimpact/tests/tcp_synrcvd_reset_test.go
index 32271d7b2..3346d43c4 100644
--- a/test/packetimpact/tests/tcp_synrcvd_reset_test.go
+++ b/test/packetimpact/tests/tcp_synrcvd_reset_test.go
@@ -37,11 +37,11 @@ func TestTCPSynRcvdReset(t *testing.T) {
defer conn.Close(t)
// Expect dut connection to have transitioned to SYN-RCVD state.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
t.Fatalf("expected SYN-ACK %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)})
// Expect the connection to have transitioned SYN-RCVD to CLOSED.
//
@@ -49,8 +49,8 @@ func TestTCPSynRcvdReset(t *testing.T) {
// CLOSED. We cannot use TCP_INFO to lookup the state as this is a passive
// DUT connection.
for i := 0; i < 5; i++ {
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, nil, time.Second); err != nil {
t.Logf("retransmit%d ACK as we did not get the expected RST, %s", i, err)
continue
}
diff --git a/test/packetimpact/tests/tcp_synsent_reset_test.go b/test/packetimpact/tests/tcp_synsent_reset_test.go
index 2c8bb101b..cccb0abc6 100644
--- a/test/packetimpact/tests/tcp_synsent_reset_test.go
+++ b/test/packetimpact/tests/tcp_synsent_reset_test.go
@@ -42,7 +42,7 @@ func dutSynSentState(t *testing.T) (*testbench.DUT, *testbench.TCPIPv4, uint16,
copy(sa.Addr[:], dut.Net.LocalIPv4)
// Bring the dut to SYN-SENT state with a non-blocking connect.
dut.Connect(t, clientFD, &sa)
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)}, nil, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)}, nil, time.Second); err != nil {
t.Fatalf("expected SYN\n")
}
@@ -53,11 +53,11 @@ func dutSynSentState(t *testing.T) (*testbench.DUT, *testbench.TCPIPv4, uint16,
func TestTCPSynSentReset(t *testing.T) {
_, conn, _, _ := dutSynSentState(t)
defer conn.Close(t)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst | header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst | header.TCPFlagAck)})
// Expect the connection to have closed.
// TODO(gvisor.dev/issue/478): Check for TCP_INFO on the dut side.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, nil, time.Second); err != nil {
t.Fatalf("expected a TCP RST")
}
}
@@ -73,15 +73,15 @@ func TestTCPSynSentRcvdReset(t *testing.T) {
// Initiate new SYN connection with the same port pair
// (simultaneous open case), expect the dut connection to move to
// SYN-RCVD state
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagSyn | header.TCPFlagAck)}, nil, time.Second); err != nil {
t.Fatalf("expected SYN-ACK %s\n", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)})
// Expect the connection to have transitioned SYN-RCVD to CLOSED.
// TODO(gvisor.dev/issue/478): Check for TCP_INFO on the dut side.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, nil, time.Second); err != nil {
t.Fatalf("expected a TCP RST")
}
}
diff --git a/test/packetimpact/tests/tcp_timewait_reset_test.go b/test/packetimpact/tests/tcp_timewait_reset_test.go
index d1d2fb83d..89037f0a4 100644
--- a/test/packetimpact/tests/tcp_timewait_reset_test.go
+++ b/test/packetimpact/tests/tcp_timewait_reset_test.go
@@ -42,26 +42,26 @@ func TestTimeWaitReset(t *testing.T) {
// Trigger active close.
dut.Close(t, acceptFD)
- _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second)
+ _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected a FIN: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
// Send a FIN, DUT should transition to TIME_WAIT from FIN_WAIT2.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)})
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)})
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected an ACK for our FIN: %s", err)
}
// Send a RST, the DUT should transition to CLOSED from TIME_WAIT.
// This is the default Linux behavior, it can be changed to ignore RSTs via
// sysctl net.ipv4.tcp_rfc1337.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)})
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
// The DUT should reply with RST to our ACK as the state should have
// transitioned to CLOSED.
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, time.Second); err != nil {
t.Fatalf("expected a RST: %s", err)
}
}
diff --git a/test/packetimpact/tests/tcp_unacc_seq_ack_closing_test.go b/test/packetimpact/tests/tcp_unacc_seq_ack_closing_test.go
new file mode 100644
index 000000000..a208210ac
--- /dev/null
+++ b/test/packetimpact/tests/tcp_unacc_seq_ack_closing_test.go
@@ -0,0 +1,94 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tcp_unacc_seq_ack_closing_test
+
+import (
+ "flag"
+ "fmt"
+ "testing"
+ "time"
+
+ "golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/tcpip/header"
+ "gvisor.dev/gvisor/pkg/tcpip/seqnum"
+ "gvisor.dev/gvisor/test/packetimpact/testbench"
+)
+
+func init() {
+ testbench.Initialize(flag.CommandLine)
+}
+
+func TestSimultaneousCloseUnaccSeqAck(t *testing.T) {
+ for _, tt := range []struct {
+ description string
+ makeTestingTCP func(t *testing.T, conn *testbench.TCPIPv4, seqNumOffset, windowSize seqnum.Size) testbench.TCP
+ seqNumOffset seqnum.Size
+ expectAck bool
+ }{
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 0, expectAck: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 1, expectAck: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 2, expectAck: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 0, expectAck: false},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 1, expectAck: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 2, expectAck: true},
+ } {
+ t.Run(fmt.Sprintf("%s:offset=%d", tt.description, tt.seqNumOffset), func(t *testing.T) {
+ dut := testbench.NewDUT(t)
+ listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1 /*backlog*/)
+ defer dut.Close(t, listenFD)
+ conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
+ defer conn.Close(t)
+
+ conn.Connect(t)
+ acceptFD, _ := dut.Accept(t, listenFD)
+
+ // Trigger active close.
+ dut.Shutdown(t, acceptFD, unix.SHUT_WR)
+
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second)
+ if err != nil {
+ t.Fatalf("expected a FIN: %s", err)
+ }
+ // Do not ack the FIN from DUT so that we get to CLOSING.
+ seqNumForTheirFIN := testbench.Uint32(uint32(*conn.RemoteSeqNum(t)) - 1)
+ conn.Send(t, testbench.TCP{AckNum: seqNumForTheirFIN, Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)})
+
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
+ t.Errorf("expected an ACK to our FIN, but got none: %s", err)
+ }
+
+ sampleData := []byte("Sample Data")
+ samplePayload := &testbench.Payload{Bytes: sampleData}
+
+ origSeq := uint32(*conn.LocalSeqNum(t))
+ // Send a segment with OTW Seq / unacc ACK.
+ tcp := tt.makeTestingTCP(t, &conn, tt.seqNumOffset, seqnum.Size(*gotTCP.WindowSize))
+ if tt.description == "OTWSeq" {
+ // If we generate an OTW Seq segment, make sure we don't acknowledge their FIN so that
+ // we stay in CLOSING.
+ tcp.AckNum = seqNumForTheirFIN
+ }
+ conn.Send(t, tcp, samplePayload)
+
+ got, err := conn.Expect(t, testbench.TCP{AckNum: testbench.Uint32(origSeq), Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
+ if tt.expectAck && err != nil {
+ t.Errorf("expected an ack in CLOSING state, but got none: %s", err)
+ }
+ if !tt.expectAck && got != nil {
+ t.Errorf("expected no ack in CLOSING state, but got one: %s", got)
+ }
+ })
+ }
+}
diff --git a/test/packetimpact/tests/tcp_unacc_seq_ack_test.go b/test/packetimpact/tests/tcp_unacc_seq_ack_test.go
index ea962c818..ce0a26171 100644
--- a/test/packetimpact/tests/tcp_unacc_seq_ack_test.go
+++ b/test/packetimpact/tests/tcp_unacc_seq_ack_test.go
@@ -17,7 +17,6 @@ package tcp_unacc_seq_ack_test
import (
"flag"
"fmt"
- "syscall"
"testing"
"time"
@@ -39,12 +38,12 @@ func TestEstablishedUnaccSeqAck(t *testing.T) {
expectAck bool
restoreSeq bool
}{
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 0, expectAck: true, restoreSeq: true},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 1, expectAck: true, restoreSeq: true},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 2, expectAck: true, restoreSeq: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 0, expectAck: true, restoreSeq: false},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 1, expectAck: false, restoreSeq: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 2, expectAck: false, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 0, expectAck: true, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 1, expectAck: true, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 2, expectAck: true, restoreSeq: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 0, expectAck: true, restoreSeq: false},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 1, expectAck: false, restoreSeq: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 2, expectAck: false, restoreSeq: true},
} {
t.Run(fmt.Sprintf("%s:offset=%d", tt.description, tt.seqNumOffset), func(t *testing.T) {
dut := testbench.NewDUT(t)
@@ -59,8 +58,8 @@ func TestEstablishedUnaccSeqAck(t *testing.T) {
sampleData := []byte("Sample Data")
samplePayload := &testbench.Payload{Bytes: sampleData}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected ack %s", err)
}
@@ -74,7 +73,7 @@ func TestEstablishedUnaccSeqAck(t *testing.T) {
// ACK matches the TCP layer state.
*conn.LocalSeqNum(t) = origSeq
}
- gotAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ gotAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if tt.expectAck && err != nil {
t.Fatalf("expected an ack but got none: %s", err)
}
@@ -92,12 +91,12 @@ func TestPassiveCloseUnaccSeqAck(t *testing.T) {
seqNumOffset seqnum.Size
expectAck bool
}{
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 0, expectAck: false},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 1, expectAck: true},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 2, expectAck: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 0, expectAck: false},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 1, expectAck: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 2, expectAck: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 0, expectAck: false},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 1, expectAck: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 2, expectAck: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 0, expectAck: false},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 1, expectAck: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 2, expectAck: true},
} {
t.Run(fmt.Sprintf("%s:offset=%d", tt.description, tt.seqNumOffset), func(t *testing.T) {
dut := testbench.NewDUT(t)
@@ -110,8 +109,8 @@ func TestPassiveCloseUnaccSeqAck(t *testing.T) {
acceptFD, _ := dut.Accept(t, listenFD)
// Send a FIN to DUT to intiate the passive close.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagFin)})
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagFin)})
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected an ACK for our fin and DUT should enter CLOSE_WAIT: %s", err)
}
@@ -122,7 +121,7 @@ func TestPassiveCloseUnaccSeqAck(t *testing.T) {
// Send a segment with OTW Seq / unacc ACK.
conn.Send(t, tt.makeTestingTCP(t, &conn, tt.seqNumOffset, windowSize), samplePayload)
- gotAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ gotAck, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if tt.expectAck && err != nil {
t.Errorf("expected an ack but got none: %s", err)
}
@@ -132,14 +131,14 @@ func TestPassiveCloseUnaccSeqAck(t *testing.T) {
// Now let's verify DUT is indeed in CLOSE_WAIT
dut.Close(t, acceptFD)
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagFin)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagFin)}, time.Second); err != nil {
t.Fatalf("expected DUT to send a FIN: %s", err)
}
// Ack the FIN from DUT
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
// Send some extra data to DUT
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, samplePayload)
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, samplePayload)
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, time.Second); err != nil {
t.Fatalf("expected DUT to send an RST: %s", err)
}
})
@@ -153,12 +152,12 @@ func TestActiveCloseUnaccpSeqAck(t *testing.T) {
seqNumOffset seqnum.Size
restoreSeq bool
}{
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 0, restoreSeq: true},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 1, restoreSeq: true},
- {description: "OTWSeq", makeTestingTCP: generateOTWSeqSegment, seqNumOffset: 2, restoreSeq: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 0, restoreSeq: false},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 1, restoreSeq: true},
- {description: "UnaccAck", makeTestingTCP: generateUnaccACKSegment, seqNumOffset: 2, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 0, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 1, restoreSeq: true},
+ {description: "OTWSeq", makeTestingTCP: testbench.GenerateOTWSeqSegment, seqNumOffset: 2, restoreSeq: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 0, restoreSeq: false},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 1, restoreSeq: true},
+ {description: "UnaccAck", makeTestingTCP: testbench.GenerateUnaccACKSegment, seqNumOffset: 2, restoreSeq: true},
} {
t.Run(fmt.Sprintf("%s:offset=%d", tt.description, tt.seqNumOffset), func(t *testing.T) {
dut := testbench.NewDUT(t)
@@ -171,14 +170,14 @@ func TestActiveCloseUnaccpSeqAck(t *testing.T) {
acceptFD, _ := dut.Accept(t, listenFD)
// Trigger active close.
- dut.Shutdown(t, acceptFD, syscall.SHUT_WR)
+ dut.Shutdown(t, acceptFD, unix.SHUT_WR)
// Get to FIN_WAIT2
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)}, time.Second)
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected a FIN: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
sendUnaccSeqAck := func(state string) {
t.Helper()
@@ -193,7 +192,7 @@ func TestActiveCloseUnaccpSeqAck(t *testing.T) {
// incoming ACK matches the TCP layer state.
*conn.LocalSeqNum(t) = origSeq
}
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Errorf("expected an ack in %s state, but got none: %s", state, err)
}
}
@@ -201,8 +200,8 @@ func TestActiveCloseUnaccpSeqAck(t *testing.T) {
sendUnaccSeqAck("FIN_WAIT2")
// Send a FIN to DUT to get to TIME_WAIT
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagFin | header.TCPFlagAck)})
- if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagFin | header.TCPFlagAck)})
+ if _, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second); err != nil {
t.Fatalf("expected an ACK for our fin and DUT should enter TIME_WAIT: %s", err)
}
@@ -210,22 +209,3 @@ func TestActiveCloseUnaccpSeqAck(t *testing.T) {
})
}
}
-
-// generateOTWSeqSegment generates an segment with
-// seqnum = RCV.NXT + RCV.WND + seqNumOffset, the generated segment is only
-// acceptable when seqNumOffset is 0, otherwise an ACK is expected from the
-// receiver.
-func generateOTWSeqSegment(t *testing.T, conn *testbench.TCPIPv4, seqNumOffset seqnum.Size, windowSize seqnum.Size) testbench.TCP {
- lastAcceptable := conn.LocalSeqNum(t).Add(windowSize)
- otwSeq := uint32(lastAcceptable.Add(seqNumOffset))
- return testbench.TCP{SeqNum: testbench.Uint32(otwSeq), Flags: testbench.Uint8(header.TCPFlagAck)}
-}
-
-// generateUnaccACKSegment generates an segment with
-// acknum = SND.NXT + seqNumOffset, the generated segment is only acceptable
-// when seqNumOffset is 0, otherwise an ACK is expected from the receiver.
-func generateUnaccACKSegment(t *testing.T, conn *testbench.TCPIPv4, seqNumOffset seqnum.Size, windowSize seqnum.Size) testbench.TCP {
- lastAcceptable := conn.RemoteSeqNum(t)
- unaccAck := uint32(lastAcceptable.Add(seqNumOffset))
- return testbench.TCP{AckNum: testbench.Uint32(unaccAck), Flags: testbench.Uint8(header.TCPFlagAck)}
-}
diff --git a/test/packetimpact/tests/tcp_user_timeout_test.go b/test/packetimpact/tests/tcp_user_timeout_test.go
index b16e65366..ef38bd738 100644
--- a/test/packetimpact/tests/tcp_user_timeout_test.go
+++ b/test/packetimpact/tests/tcp_user_timeout_test.go
@@ -35,7 +35,7 @@ func sendPayload(t *testing.T, conn *testbench.TCPIPv4, dut *testbench.DUT, fd i
}
conn.Drain(t)
dut.Send(t, fd, sampleData, 0)
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, &testbench.Payload{Bytes: sampleData}, time.Second); err != nil {
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, &testbench.Payload{Bytes: sampleData}, time.Second); err != nil {
t.Fatalf("expected data but got none: %w", err)
}
}
@@ -79,14 +79,14 @@ func TestTCPUserTimeout(t *testing.T) {
time.Sleep(tt.sendDelay)
conn.Drain(t)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
// If TCP_USER_TIMEOUT was set and the above delay was longer than the
// TCP_USER_TIMEOUT then the DUT should send a RST in response to the
// testbench's packet.
expectRST := tt.userTimeout != 0 && tt.sendDelay > tt.userTimeout
expectTimeout := 5 * time.Second
- got, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, expectTimeout)
+ got, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, expectTimeout)
if expectRST && err != nil {
t.Errorf("expected RST packet within %s but got none: %s", expectTimeout, err)
}
diff --git a/test/packetimpact/tests/tcp_window_shrink_test.go b/test/packetimpact/tests/tcp_window_shrink_test.go
index 093484721..0d65a2ea2 100644
--- a/test/packetimpact/tests/tcp_window_shrink_test.go
+++ b/test/packetimpact/tests/tcp_window_shrink_test.go
@@ -48,7 +48,7 @@ func TestWindowShrink(t *testing.T) {
if _, err := conn.ExpectData(t, &testbench.TCP{}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
dut.Send(t, acceptFd, sampleData, 0)
dut.Send(t, acceptFd, sampleData, 0)
@@ -59,7 +59,7 @@ func TestWindowShrink(t *testing.T) {
t.Fatalf("expected payload was not received: %s", err)
}
// We close our receiving window here
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
dut.Send(t, acceptFd, []byte("Sample Data"), 0)
// Note: There is another kind of zero-window probing which Windows uses (by sending one
diff --git a/test/packetimpact/tests/tcp_zero_receive_window_test.go b/test/packetimpact/tests/tcp_zero_receive_window_test.go
index d06690705..d73495454 100644
--- a/test/packetimpact/tests/tcp_zero_receive_window_test.go
+++ b/test/packetimpact/tests/tcp_zero_receive_window_test.go
@@ -49,8 +49,8 @@ func TestZeroReceiveWindow(t *testing.T) {
// Expect the DUT to eventually advertise zero receive window.
// The test would timeout otherwise.
for readOnce := false; ; {
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected packet was not received: %s", err)
}
@@ -100,8 +100,8 @@ func TestNonZeroReceiveWindow(t *testing.T) {
// we sent. Once we have received ACKs with non-zero receive windows, we break
// the loop.
for {
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, time.Second)
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ gotTCP, err := conn.Expect(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, time.Second)
if err != nil {
t.Fatalf("expected packet was not received: %s", err)
}
diff --git a/test/packetimpact/tests/tcp_zero_window_probe_retransmit_test.go b/test/packetimpact/tests/tcp_zero_window_probe_retransmit_test.go
index d094c10eb..22b17a39e 100644
--- a/test/packetimpact/tests/tcp_zero_window_probe_retransmit_test.go
+++ b/test/packetimpact/tests/tcp_zero_window_probe_retransmit_test.go
@@ -15,6 +15,7 @@
package tcp_zero_window_probe_retransmit_test
import (
+ "bytes"
"flag"
"testing"
"time"
@@ -51,18 +52,23 @@ func TestZeroWindowProbeRetransmit(t *testing.T) {
if _, err := conn.ExpectData(t, &testbench.TCP{}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, nil, time.Second); err != nil {
- t.Fatalf("expected packet was not received: %s", err)
- }
// Check for the dut to keep the connection alive as long as the zero window
// probes are acknowledged. Check if the zero window probes are sent at
// exponentially increasing intervals. The timeout intervals are function
// of the recorded first zero probe transmission duration.
//
- // Advertize zero receive window again.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ // Advertize zero receive window along with a payload.
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh), WindowSize: testbench.Uint16(0)}, samplePayload)
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, nil, time.Second); err != nil {
+ t.Fatalf("expected packet was not received: %s", err)
+ }
+ // Wait for the payload to be received by the DUT, which is also an
+ // indication of receive of the peer window advertisement.
+ if got := dut.Recv(t, acceptFd, int32(len(sampleData)), 0); !bytes.Equal(got, sampleData) {
+ t.Fatalf("got dut.Recv(t, %d, %d, 0) = %s, want %s", acceptFd, len(sampleData), got, sampleData)
+ }
+
probeSeq := testbench.Uint32(uint32(*conn.RemoteSeqNum(t) - 1))
ackProbe := testbench.Uint32(uint32(*conn.RemoteSeqNum(t)))
@@ -98,10 +104,10 @@ func TestZeroWindowProbeRetransmit(t *testing.T) {
}
prev = got
// Acknowledge the zero-window probes from the dut.
- conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
}
// Advertize non-zero window.
- conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.TCPFlags(header.TCPFlagAck)})
// Expect the dut to recover and transmit data.
if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: ackProbe}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
diff --git a/test/packetimpact/tests/tcp_zero_window_probe_test.go b/test/packetimpact/tests/tcp_zero_window_probe_test.go
index 650a569cc..8b90fcbe9 100644
--- a/test/packetimpact/tests/tcp_zero_window_probe_test.go
+++ b/test/packetimpact/tests/tcp_zero_window_probe_test.go
@@ -53,8 +53,8 @@ func TestZeroWindowProbe(t *testing.T) {
t.Fatalf("expected payload was not received: %s", err)
}
sendTime := time.Now().Sub(start)
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, nil, time.Second); err != nil {
t.Fatalf("expected packet was not received: %s", err)
}
@@ -62,7 +62,7 @@ func TestZeroWindowProbe(t *testing.T) {
// probe to be sent.
//
// Advertize zero window to the dut.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
// Expected sequence number of the zero window probe.
probeSeq := testbench.Uint32(uint32(*conn.RemoteSeqNum(t) - 1))
@@ -93,7 +93,7 @@ func TestZeroWindowProbe(t *testing.T) {
// and sends out the sample payload after the send window opens.
//
// Advertize non-zero window to the dut and ack the zero window probe.
- conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.Uint8(header.TCPFlagAck)})
+ conn.Send(t, testbench.TCP{AckNum: ackProbe, Flags: testbench.TCPFlags(header.TCPFlagAck)})
// Expect the dut to recover and transmit data.
if _, err := conn.ExpectData(t, &testbench.TCP{SeqNum: ackProbe}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
@@ -104,8 +104,8 @@ func TestZeroWindowProbe(t *testing.T) {
// Basically with sequence number to one byte behind the unacknowledged
// sequence number.
p := testbench.Uint32(uint32(*conn.LocalSeqNum(t)))
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), SeqNum: testbench.Uint32(uint32(*conn.LocalSeqNum(t) - 1))})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), AckNum: p}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), SeqNum: testbench.Uint32(uint32(*conn.LocalSeqNum(t) - 1))})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), AckNum: p}, nil, time.Second); err != nil {
t.Fatalf("expected a packet with ack number: %d: %s", p, err)
}
}
diff --git a/test/packetimpact/tests/tcp_zero_window_probe_usertimeout_test.go b/test/packetimpact/tests/tcp_zero_window_probe_usertimeout_test.go
index 079fea68c..1ce4d22b7 100644
--- a/test/packetimpact/tests/tcp_zero_window_probe_usertimeout_test.go
+++ b/test/packetimpact/tests/tcp_zero_window_probe_usertimeout_test.go
@@ -51,8 +51,8 @@ func TestZeroWindowProbeUserTimeout(t *testing.T) {
if _, err := conn.ExpectData(t, &testbench.TCP{}, samplePayload, time.Second); err != nil {
t.Fatalf("expected payload was not received: %s", err)
}
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck | header.TCPFlagPsh)}, samplePayload)
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)}, nil, time.Second); err != nil {
t.Fatalf("expected packet was not received: %s", err)
}
@@ -60,7 +60,7 @@ func TestZeroWindowProbeUserTimeout(t *testing.T) {
// probe to be sent.
//
// Advertize zero window to the dut.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
// Expected sequence number of the zero window probe.
probeSeq := testbench.Uint32(uint32(*conn.RemoteSeqNum(t) - 1))
@@ -81,7 +81,7 @@ func TestZeroWindowProbeUserTimeout(t *testing.T) {
// Reduce the retransmit timeout.
dut.SetSockOptInt(t, acceptFd, unix.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int32(startProbeDuration.Milliseconds()))
// Advertize zero window again.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck), WindowSize: testbench.Uint16(0)})
// Ask the dut to send out data that would trigger zero window probe retransmissions.
dut.Send(t, acceptFd, sampleData, 0)
@@ -90,8 +90,8 @@ func TestZeroWindowProbeUserTimeout(t *testing.T) {
// Expect the connection to have timed out and closed which would cause the dut
// to reply with a RST to the ACK we send.
- conn.Send(t, testbench.TCP{Flags: testbench.Uint8(header.TCPFlagAck)})
- if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.Uint8(header.TCPFlagRst)}, nil, time.Second); err != nil {
+ conn.Send(t, testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagAck)})
+ if _, err := conn.ExpectData(t, &testbench.TCP{Flags: testbench.TCPFlags(header.TCPFlagRst)}, nil, time.Second); err != nil {
t.Fatalf("expected a TCP RST")
}
}
diff --git a/test/packetimpact/tests/udp_discard_mcast_source_addr_test.go b/test/packetimpact/tests/udp_discard_mcast_source_addr_test.go
index 52c6f9d91..f63cfcc9a 100644
--- a/test/packetimpact/tests/udp_discard_mcast_source_addr_test.go
+++ b/test/packetimpact/tests/udp_discard_mcast_source_addr_test.go
@@ -19,7 +19,6 @@ import (
"flag"
"fmt"
"net"
- "syscall"
"testing"
"golang.org/x/sys/unix"
@@ -56,7 +55,7 @@ func TestDiscardsUDPPacketsWithMcastSourceAddressV4(t *testing.T) {
)
ret, payload, errno := dut.RecvWithErrno(context.Background(), t, remoteFD, 100, 0)
- if errno != syscall.EAGAIN || errno != syscall.EWOULDBLOCK {
+ if errno != unix.EAGAIN || errno != unix.EWOULDBLOCK {
t.Errorf("Recv got unexpected result, ret=%d, payload=%q, errno=%s", ret, payload, errno)
}
})
@@ -86,7 +85,7 @@ func TestDiscardsUDPPacketsWithMcastSourceAddressV6(t *testing.T) {
&testbench.Payload{Bytes: []byte("test payload")},
)
ret, payload, errno := dut.RecvWithErrno(context.Background(), t, remoteFD, 100, 0)
- if errno != syscall.EAGAIN || errno != syscall.EWOULDBLOCK {
+ if errno != unix.EAGAIN || errno != unix.EWOULDBLOCK {
t.Errorf("Recv got unexpected result, ret=%d, payload=%q, errno=%s", ret, payload, errno)
}
})
diff --git a/test/packetimpact/tests/udp_icmp_error_propagation_test.go b/test/packetimpact/tests/udp_icmp_error_propagation_test.go
index 3fca8c7a3..3159d5b89 100644
--- a/test/packetimpact/tests/udp_icmp_error_propagation_test.go
+++ b/test/packetimpact/tests/udp_icmp_error_propagation_test.go
@@ -20,7 +20,6 @@ import (
"fmt"
"net"
"sync"
- "syscall"
"testing"
"time"
@@ -86,16 +85,16 @@ type testData struct {
remotePort uint16
cleanFD int32
cleanPort uint16
- wantErrno syscall.Errno
+ wantErrno unix.Errno
}
// wantErrno computes the errno to expect given the connection mode of a UDP
// socket and the ICMP error it will receive.
-func wantErrno(c connectionMode, icmpErr icmpError) syscall.Errno {
+func wantErrno(c connectionMode, icmpErr icmpError) unix.Errno {
if c && icmpErr == portUnreachable {
- return syscall.Errno(unix.ECONNREFUSED)
+ return unix.ECONNREFUSED
}
- return syscall.Errno(0)
+ return unix.Errno(0)
}
// sendICMPError sends an ICMP error message in response to a UDP datagram.
@@ -123,7 +122,7 @@ func sendICMPError(t *testing.T, conn *testbench.UDPIPv4, icmpErr icmpError, udp
conn.SendFrameStateless(t, layers)
}
-// testRecv tests observing the ICMP error through the recv syscall. A packet
+// testRecv tests observing the ICMP error through the recv unix. A packet
// is sent to the DUT, and if wantErrno is non-zero, then the first recv should
// fail and the second should succeed. Otherwise if wantErrno is zero then the
// first recv should succeed immediately.
@@ -136,7 +135,7 @@ func testRecv(ctx context.Context, t *testing.T, d testData) {
d.conn.Send(t, testbench.UDP{})
- if d.wantErrno != syscall.Errno(0) {
+ if d.wantErrno != unix.Errno(0) {
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
ret, _, err := d.dut.RecvWithErrno(ctx, t, d.remoteFD, 100, 0)
@@ -162,7 +161,7 @@ func testSendTo(ctx context.Context, t *testing.T, d testData) {
t.Fatalf("did not receive UDP packet from clean socket on DUT: %s", err)
}
- if d.wantErrno != syscall.Errno(0) {
+ if d.wantErrno != unix.Errno(0) {
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
ret, err := d.dut.SendToWithErrno(ctx, t, d.remoteFD, nil, 0, d.conn.LocalAddr(t))
@@ -183,11 +182,11 @@ func testSendTo(ctx context.Context, t *testing.T, d testData) {
func testSockOpt(_ context.Context, t *testing.T, d testData) {
// Check that there's no pending error on the clean socket.
- if errno := syscall.Errno(d.dut.GetSockOptInt(t, d.cleanFD, unix.SOL_SOCKET, unix.SO_ERROR)); errno != syscall.Errno(0) {
+ if errno := unix.Errno(d.dut.GetSockOptInt(t, d.cleanFD, unix.SOL_SOCKET, unix.SO_ERROR)); errno != unix.Errno(0) {
t.Fatalf("unexpected error (%[1]d) %[1]v on clean socket", errno)
}
- if errno := syscall.Errno(d.dut.GetSockOptInt(t, d.remoteFD, unix.SOL_SOCKET, unix.SO_ERROR)); errno != d.wantErrno {
+ if errno := unix.Errno(d.dut.GetSockOptInt(t, d.remoteFD, unix.SOL_SOCKET, unix.SO_ERROR)); errno != d.wantErrno {
t.Fatalf("SO_ERROR sockopt after ICMP error is (%[1]d) %[1]v, expected (%[2]d) %[2]v", errno, d.wantErrno)
}
@@ -310,7 +309,7 @@ func TestICMPErrorDuringUDPRecv(t *testing.T) {
go func() {
defer wg.Done()
- if wantErrno != syscall.Errno(0) {
+ if wantErrno != unix.Errno(0) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
diff --git a/test/packetimpact/tests/udp_send_recv_dgram_test.go b/test/packetimpact/tests/udp_send_recv_dgram_test.go
index 894d156cf..230b012c7 100644
--- a/test/packetimpact/tests/udp_send_recv_dgram_test.go
+++ b/test/packetimpact/tests/udp_send_recv_dgram_test.go
@@ -19,7 +19,6 @@ import (
"flag"
"fmt"
"net"
- "syscall"
"testing"
"time"
@@ -241,7 +240,7 @@ func TestUDP(t *testing.T) {
},
)
ret, recvPayload, errno := dut.RecvWithErrno(context.Background(), t, socketFD, 100, 0)
- if errno != syscall.EAGAIN || errno != syscall.EWOULDBLOCK {
+ if errno != unix.EAGAIN || errno != unix.EWOULDBLOCK {
t.Errorf("Recv got unexpected result, ret=%d, payload=%q, errno=%s", ret, recvPayload, errno)
}
}