diff --git a/pkg/tcpip/transport/tcp/BUILD b/pkg/tcpip/transport/tcp/BUILD index 5049a1c87..730a8b845 100644 --- a/pkg/tcpip/transport/tcp/BUILD +++ b/pkg/tcpip/transport/tcp/BUILD @@ -1,4 +1,4 @@ -load("//tools:defs.bzl", "go_library", "go_test", "more_shards") +load("//tools:defs.bzl", "go_library", "go_test") load("//tools/go_generics:defs.bzl", "go_template_instance") package(licenses = ["notice"]) @@ -78,43 +78,6 @@ go_library( ], ) -go_test( - name = "tcp_x_test", - size = "large", - srcs = [ - "dual_stack_test.go", - "forwarder_test.go", - "rcv_test.go", - "sack_scoreboard_test.go", - "tcp_noracedetector_test.go", - "tcp_rack_test.go", - "tcp_sack_test.go", - "tcp_test.go", - "tcp_timestamp_test.go", - ], - shard_count = more_shards, - deps = [ - ":tcp", - "//pkg/rand", - "//pkg/sync", - "//pkg/tcpip", - "//pkg/tcpip/checker", - "//pkg/tcpip/faketime", - "//pkg/tcpip/header", - "//pkg/tcpip/link/loopback", - "//pkg/tcpip/link/sniffer", - "//pkg/tcpip/network/ipv4", - "//pkg/tcpip/network/ipv6", - "//pkg/tcpip/seqnum", - "//pkg/tcpip/stack", - "//pkg/tcpip/testutil", - "//pkg/tcpip/transport/tcp/testing/context", - "//pkg/test/testutil", - "//pkg/waiter", - "@com_github_google_go_cmp//cmp:go_default_library", - ], -) - go_test( name = "tcp_test", size = "small", diff --git a/pkg/tcpip/transport/tcp/test/e2e/BUILD b/pkg/tcpip/transport/tcp/test/e2e/BUILD new file mode 100644 index 000000000..abdf5f840 --- /dev/null +++ b/pkg/tcpip/transport/tcp/test/e2e/BUILD @@ -0,0 +1,161 @@ +load("//tools:defs.bzl", "go_library", "go_test", "more_shards") + +package(licenses = ["notice"]) + +go_test( + name = "tcp_test", + size = "large", + srcs = ["tcp_test.go"], + shard_count = more_shards, + deps = [ + ":e2e", + "//pkg/rand", + "//pkg/sync", + "//pkg/tcpip", + "//pkg/tcpip/checker", + "//pkg/tcpip/faketime", + "//pkg/tcpip/header", + "//pkg/tcpip/link/loopback", + "//pkg/tcpip/link/sniffer", + "//pkg/tcpip/network/ipv4", + "//pkg/tcpip/network/ipv6", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/stack", + "//pkg/tcpip/testutil", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/test/testutil", + "//pkg/waiter", + "@com_github_google_go_cmp//cmp:go_default_library", + ], +) + +go_test( + name = "dual_stack_test", + size = "small", + srcs = ["dual_stack_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/checker", + "//pkg/tcpip/header", + "//pkg/tcpip/network/ipv4", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/waiter", + "@com_github_google_go_cmp//cmp:go_default_library", + ], +) + +go_library( + name = "e2e", + testonly = 1, + srcs = ["e2e.go"], + deps = [ + "//pkg/tcpip", + "//pkg/tcpip/checker", + "//pkg/tcpip/header", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/waiter", + "@com_github_google_go_cmp//cmp:go_default_library", + ], +) + +go_test( + name = "forwarder_test", + size = "small", + srcs = ["forwarder_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/header", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + ], +) + +go_test( + name = "rcv_test", + size = "small", + srcs = ["rcv_test.go"], + deps = [ + "//pkg/tcpip/header", + "//pkg/tcpip/seqnum", + ], +) + +go_test( + name = "sack_scoreboard_test", + size = "small", + srcs = ["sack_scoreboard_test.go"], + deps = [ + "//pkg/tcpip/header", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/transport/tcp", + ], +) + +go_test( + name = "tcp_timestamp_test", + size = "small", + srcs = ["tcp_timestamp_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/checker", + "//pkg/tcpip/header", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/waiter", + "@com_github_google_go_cmp//cmp:go_default_library", + ], +) + +go_test( + name = "tcp_rack_test", + size = "small", + srcs = ["tcp_rack_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/header", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/stack", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/test/testutil", + ], +) + +go_test( + name = "tcp_sack_test", + size = "small", + srcs = ["tcp_sack_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/checker", + "//pkg/tcpip/header", + "//pkg/tcpip/seqnum", + "//pkg/tcpip/stack", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/test/testutil", + ], +) + +go_test( + name = "tcp_noracedetector_test", + size = "small", + srcs = ["tcp_noracedetector_test.go"], + deps = [ + ":e2e", + "//pkg/tcpip", + "//pkg/tcpip/header", + "//pkg/tcpip/transport/tcp", + "//pkg/tcpip/transport/tcp/testing/context", + "//pkg/test/testutil", + ], +) diff --git a/pkg/tcpip/transport/tcp/dual_stack_test.go b/pkg/tcpip/transport/tcp/test/e2e/dual_stack_test.go similarity index 76% rename from pkg/tcpip/transport/tcp/dual_stack_test.go rename to pkg/tcpip/transport/tcp/test/e2e/dual_stack_test.go index 667fc3e2c..ac7c0fca2 100644 --- a/pkg/tcpip/transport/tcp/dual_stack_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/dual_stack_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package dual_stack_test import ( "strings" @@ -26,12 +26,13 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/seqnum" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/waiter" ) func TestV4MappedConnectOnV6Only(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) @@ -43,70 +44,18 @@ func TestV4MappedConnectOnV6Only(t *testing.T) { } } -func testV4Connect(t *testing.T, c *context.Context, checkers ...checker.NetworkChecker) { - // Start connection attempt. - we, ch := waiter.NewChannelEntry(waiter.WritableEvents) - c.WQ.EventRegister(&we) - defer c.WQ.EventUnregister(&we) - - err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV4MappedAddr, Port: context.TestPort}) - if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" { - t.Fatalf("c.EP.Connect(...) mismatch (-want +got):\n%s", d) - } - - // Receive SYN packet. - b := c.GetPacket() - synCheckers := append(checkers, checker.TCP( - checker.DstPort(context.TestPort), - checker.TCPFlags(header.TCPFlagSyn), - )) - checker.IPv4(t, b, synCheckers...) - - tcp := header.TCP(header.IPv4(b).Payload()) - c.IRS = seqnum.Value(tcp.SequenceNumber()) - - iss := seqnum.Value(789) - c.SendPacket(nil, &context.Headers{ - SrcPort: tcp.DestinationPort(), - DstPort: tcp.SourcePort(), - Flags: header.TCPFlagSyn | header.TCPFlagAck, - SeqNum: iss, - AckNum: c.IRS.Add(1), - RcvWnd: 30000, - }) - - // Receive ACK packet. - ackCheckers := append(checkers, checker.TCP( - checker.DstPort(context.TestPort), - checker.TCPFlags(header.TCPFlagAck), - checker.TCPSeqNum(uint32(c.IRS)+1), - checker.TCPAckNum(uint32(iss)+1), - )) - checker.IPv4(t, c.GetPacket(), ackCheckers...) - - // Wait for connection to be established. - select { - case <-ch: - if err := c.EP.LastError(); err != nil { - t.Fatalf("Unexpected error when connecting: %v", err) - } - case <-time.After(1 * time.Second): - t.Fatalf("Timed out waiting for connection") - } -} - func TestV4MappedConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) // Test the connection request. - testV4Connect(t, c) + e2e.TestV4Connect(t, c) } func TestV4ConnectWhenBoundToWildcard(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -117,11 +66,11 @@ func TestV4ConnectWhenBoundToWildcard(t *testing.T) { } // Test the connection request. - testV4Connect(t, c) + e2e.TestV4Connect(t, c) } func TestV4ConnectWhenBoundToV4MappedWildcard(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -132,11 +81,11 @@ func TestV4ConnectWhenBoundToV4MappedWildcard(t *testing.T) { } // Test the connection request. - testV4Connect(t, c) + e2e.TestV4Connect(t, c) } func TestV4ConnectWhenBoundToV4Mapped(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -147,83 +96,31 @@ func TestV4ConnectWhenBoundToV4Mapped(t *testing.T) { } // Test the connection request. - testV4Connect(t, c) -} - -func testV6Connect(t *testing.T, c *context.Context, checkers ...checker.NetworkChecker) { - // Start connection attempt to IPv6 address. - we, ch := waiter.NewChannelEntry(waiter.WritableEvents) - c.WQ.EventRegister(&we) - defer c.WQ.EventUnregister(&we) - - err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV6Addr, Port: context.TestPort}) - if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" { - t.Fatalf("Connect(...) mismatch (-want +got):\n%s", d) - } - - // Receive SYN packet. - b := c.GetV6Packet() - synCheckers := append(checkers, checker.TCP( - checker.DstPort(context.TestPort), - checker.TCPFlags(header.TCPFlagSyn), - )) - checker.IPv6(t, b, synCheckers...) - - tcp := header.TCP(header.IPv6(b).Payload()) - c.IRS = seqnum.Value(tcp.SequenceNumber()) - - iss := seqnum.Value(789) - c.SendV6Packet(nil, &context.Headers{ - SrcPort: tcp.DestinationPort(), - DstPort: tcp.SourcePort(), - Flags: header.TCPFlagSyn | header.TCPFlagAck, - SeqNum: iss, - AckNum: c.IRS.Add(1), - RcvWnd: 30000, - }) - - // Receive ACK packet. - ackCheckers := append(checkers, checker.TCP( - checker.DstPort(context.TestPort), - checker.TCPFlags(header.TCPFlagAck), - checker.TCPSeqNum(uint32(c.IRS)+1), - checker.TCPAckNum(uint32(iss)+1), - )) - checker.IPv6(t, c.GetV6Packet(), ackCheckers...) - - // Wait for connection to be established. - select { - case <-ch: - if err := c.EP.LastError(); err != nil { - t.Fatalf("Unexpected error when connecting: %v", err) - } - case <-time.After(1 * time.Second): - t.Fatalf("Timed out waiting for connection") - } + e2e.TestV4Connect(t, c) } func TestV6Connect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) // Test the connection request. - testV6Connect(t, c) + e2e.TestV6Connect(t, c) } func TestV6ConnectV6Only(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) // Test the connection request. - testV6Connect(t, c) + e2e.TestV6Connect(t, c) } func TestV6ConnectWhenBoundToWildcard(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -234,13 +131,13 @@ func TestV6ConnectWhenBoundToWildcard(t *testing.T) { } // Test the connection request. - testV6Connect(t, c) + e2e.TestV6Connect(t, c) } func TestStackV6OnlyConnectWhenBoundToWildcard(t *testing.T) { c := context.NewWithOpts(t, context.Options{ EnableV6: true, - MTU: defaultMTU, + MTU: e2e.DefaultMTU, }) defer c.Cleanup() @@ -253,11 +150,11 @@ func TestStackV6OnlyConnectWhenBoundToWildcard(t *testing.T) { } // Test the connection request. - testV6Connect(t, c) + e2e.TestV6Connect(t, c) } func TestV6ConnectWhenBoundToLocalAddress(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -268,11 +165,11 @@ func TestV6ConnectWhenBoundToLocalAddress(t *testing.T) { } // Test the connection request. - testV6Connect(t, c) + e2e.TestV6Connect(t, c) } func TestV4RefuseOnV6Only(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) @@ -309,7 +206,7 @@ func TestV4RefuseOnV6Only(t *testing.T) { } func TestV6RefuseOnBoundToV4Mapped(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -428,7 +325,7 @@ func testV4Accept(t *testing.T, c *context.Context) { } func TestV4AcceptOnV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -443,7 +340,7 @@ func TestV4AcceptOnV6(t *testing.T) { } func TestV4AcceptOnBoundToV4MappedWildcard(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -458,7 +355,7 @@ func TestV4AcceptOnBoundToV4MappedWildcard(t *testing.T) { } func TestV4AcceptOnBoundToV4Mapped(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -473,7 +370,7 @@ func TestV4AcceptOnBoundToV4Mapped(t *testing.T) { } func TestV6AcceptOnV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -546,7 +443,7 @@ func TestV6AcceptOnV6(t *testing.T) { } func TestV4AcceptOnV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -630,7 +527,7 @@ func testV4ListenClose(t *testing.T, c *context.Context) { } func TestV4ListenCloseOnV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. diff --git a/pkg/tcpip/transport/tcp/test/e2e/e2e.go b/pkg/tcpip/transport/tcp/test/e2e/e2e.go new file mode 100644 index 000000000..ed4d27d1f --- /dev/null +++ b/pkg/tcpip/transport/tcp/test/e2e/e2e.go @@ -0,0 +1,296 @@ +// Copyright 2022 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 e2e contains definitions common to all e2e tcp tests. +package e2e + +import ( + "bytes" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/checker" + "gvisor.dev/gvisor/pkg/tcpip/header" + "gvisor.dev/gvisor/pkg/tcpip/seqnum" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" + "gvisor.dev/gvisor/pkg/waiter" +) + +const ( + // DefaultMTU is the MTU, in bytes, used throughout the tests, except + // where another value is explicitly used. It is chosen to match the MTU + // of loopback interfaces on linux systems. + DefaultMTU = 65535 + + // DefaultIPv4MSS is the MSS sent by the network stack in SYN/SYN-ACK for an + // IPv4 endpoint when the MTU is set to defaultMTU in the test. + DefaultIPv4MSS = DefaultMTU - header.IPv4MinimumSize - header.TCPMinimumSize + + // TSOptionSize is the size in bytes of the TCP timestamp option. + TSOptionSize = 12 + + // MaxTCPOptionSize is the maximum size TCP Options in a TCP header. + MaxTCPOptionSize = 40 +) + +// CheckBrokenUpWrite does a large write > than the specified maxPayload and +// verifies that the received packets carry the expected payload and +// that the large write was broken up into > 1 packet. +func CheckBrokenUpWrite(t *testing.T, c *context.Context, maxPayload int) { + payloadMultiplier := 10 + dataLen := payloadMultiplier * maxPayload + data := make([]byte, dataLen) + for i := range data { + data[i] = byte(i) + } + + var r bytes.Reader + r.Reset(data) + if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { + t.Fatalf("Write failed: %s", err) + } + + // Check that data is received in chunks. + bytesReceived := 0 + numPackets := 0 + iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) + for bytesReceived != dataLen { + b := c.GetPacket() + numPackets++ + tcpHdr := header.TCP(header.IPv4(b).Payload()) + payloadLen := len(tcpHdr.Payload()) + checker.IPv4(t, b, + checker.TCP( + checker.DstPort(context.TestPort), + checker.TCPSeqNum(uint32(c.IRS)+1+uint32(bytesReceived)), + checker.TCPAckNum(uint32(iss)), + checker.TCPFlagsMatch(header.TCPFlagAck, ^header.TCPFlagPsh), + ), + ) + + pdata := data[bytesReceived : bytesReceived+payloadLen] + if p := tcpHdr.Payload(); !bytes.Equal(pdata, p) { + t.Fatalf("got data = %v, want = %v", p, pdata) + } + bytesReceived += payloadLen + var options []byte + if c.TimeStampEnabled { + // If timestamp option is enabled, echo back the timestamp and increment + // the TSEcr value included in the packet and send that back as the TSVal. + parsedOpts := tcpHdr.ParsedOptions() + tsOpt := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP} + header.EncodeTSOption(parsedOpts.TSEcr+1, parsedOpts.TSVal, tsOpt[2:]) + options = tsOpt[:] + } + // Acknowledge the data. + c.SendPacket(nil, &context.Headers{ + SrcPort: context.TestPort, + DstPort: c.Port, + Flags: header.TCPFlagAck, + SeqNum: iss, + AckNum: c.IRS.Add(1 + seqnum.Size(bytesReceived)), + RcvWnd: 30000, + TCPOpts: options, + }) + } + if numPackets == 1 { + t.Fatalf("expected write to be broken up into multiple packets, but got 1 packet") + } +} + +// CreateConnectedWithSACKPermittedOption creates and connects c.ep with the +// SACKPermitted option enabled if the stack in the context has the SACK support +// enabled. +func CreateConnectedWithSACKPermittedOption(c *context.Context) *context.RawEndpoint { + return c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{SACKPermitted: c.SACKEnabled()}) +} + +// CreateConnectedWithSACKAndTS creates and connects c.ep with the SACK & TS +// option enabled if the stack in the context has SACK and TS enabled. +func CreateConnectedWithSACKAndTS(c *context.Context) *context.RawEndpoint { + return c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{SACKPermitted: c.SACKEnabled(), TS: true}) +} + +// SetStackSACKPermitted sets the tcpip.TCPSACKEnabled option of the context stack to +// enabled value. +func SetStackSACKPermitted(t *testing.T, c *context.Context, enable bool) { + t.Helper() + opt := tcpip.TCPSACKEnabled(enable) + if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { + t.Fatalf("c.s.SetTransportProtocolOption(%d, &%T(%t)): %s", tcp.ProtocolNumber, opt, opt, err) + } +} + +// SetStackTCPRecovery sets the tcpip.TCPRecovery option of the context stack to +// the specified recovery value. +func SetStackTCPRecovery(t *testing.T, c *context.Context, recovery int) { + t.Helper() + opt := tcpip.TCPRecovery(recovery) + if err := c.Stack().SetTransportProtocolOption(header.TCPProtocolNumber, &opt); err != nil { + t.Fatalf("c.s.SetTransportProtocolOption(%d, &%v(%v)): %s", header.TCPProtocolNumber, opt, opt, err) + } +} + +// SendAndReceiveWithSACK creates a SACK enabled connection w/ RACK enabled if +// enableRACK is true. It then proceeds to write a large payload and verifies +// that numPackets were received. +func SendAndReceiveWithSACK(t *testing.T, c *context.Context, maxPayload int, numPackets int, enableRACK bool) []byte { + SetStackSACKPermitted(t, c, true) + if !enableRACK { + SetStackTCPRecovery(t, c, 0) + } + // The delay should be below initial RTO (1s) otherwise retransimission + // will start. Choose a relatively large value so that estimated RTT + // keeps high even after a few rounds of undelayed RTT samples. + c.CreateConnectedWithOptions(header.TCPSynOptions{SACKPermitted: c.SACKEnabled(), TS: true}, 800*time.Millisecond /* delay */) + + data := make([]byte, numPackets*maxPayload) + for i := range data { + data[i] = byte(i) + } + + // Write the data. + var r bytes.Reader + r.Reset(data) + if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { + t.Fatalf("Write failed: %s", err) + } + + bytesRead := 0 + for i := 0; i < numPackets; i++ { + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, TSOptionSize) + bytesRead += maxPayload + } + + return data +} + +// EnableCUBIC sets the CUBIC congestion control as the default congestion +// control algorithm for all newly created endpoints in the context stack. +func EnableCUBIC(t *testing.T, c *context.Context) { + t.Helper() + opt := tcpip.CongestionControlOption("cubic") + if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { + t.Fatalf("SetTransportProtocolOption(%d, &%T(%s)) %s", tcp.ProtocolNumber, opt, opt, err) + } +} + +// TestV4Connect establishes an IPv4 Connection with the context stack. +func TestV4Connect(t *testing.T, c *context.Context, checkers ...checker.NetworkChecker) { + // Start connection attempt. + we, ch := waiter.NewChannelEntry(waiter.WritableEvents) + c.WQ.EventRegister(&we) + defer c.WQ.EventUnregister(&we) + + err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV4MappedAddr, Port: context.TestPort}) + if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" { + t.Fatalf("c.EP.Connect(...) mismatch (-want +got):\n%s", d) + } + + // Receive SYN packet. + b := c.GetPacket() + synCheckers := append(checkers, checker.TCP( + checker.DstPort(context.TestPort), + checker.TCPFlags(header.TCPFlagSyn), + )) + checker.IPv4(t, b, synCheckers...) + + tcp := header.TCP(header.IPv4(b).Payload()) + c.IRS = seqnum.Value(tcp.SequenceNumber()) + + iss := seqnum.Value(789) + c.SendPacket(nil, &context.Headers{ + SrcPort: tcp.DestinationPort(), + DstPort: tcp.SourcePort(), + Flags: header.TCPFlagSyn | header.TCPFlagAck, + SeqNum: iss, + AckNum: c.IRS.Add(1), + RcvWnd: 30000, + }) + + // Receive ACK packet. + ackCheckers := append(checkers, checker.TCP( + checker.DstPort(context.TestPort), + checker.TCPFlags(header.TCPFlagAck), + checker.TCPSeqNum(uint32(c.IRS)+1), + checker.TCPAckNum(uint32(iss)+1), + )) + checker.IPv4(t, c.GetPacket(), ackCheckers...) + + // Wait for connection to be established. + select { + case <-ch: + if err := c.EP.LastError(); err != nil { + t.Fatalf("Unexpected error when connecting: %v", err) + } + case <-time.After(1 * time.Second): + t.Fatalf("Timed out waiting for connection") + } +} + +// TestV6Connect establishes an IPv6 Connection with the context stack. +func TestV6Connect(t *testing.T, c *context.Context, checkers ...checker.NetworkChecker) { + // Start connection attempt to IPv6 address. + we, ch := waiter.NewChannelEntry(waiter.WritableEvents) + c.WQ.EventRegister(&we) + defer c.WQ.EventUnregister(&we) + + err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV6Addr, Port: context.TestPort}) + if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" { + t.Fatalf("Connect(...) mismatch (-want +got):\n%s", d) + } + + // Receive SYN packet. + b := c.GetV6Packet() + synCheckers := append(checkers, checker.TCP( + checker.DstPort(context.TestPort), + checker.TCPFlags(header.TCPFlagSyn), + )) + checker.IPv6(t, b, synCheckers...) + + tcp := header.TCP(header.IPv6(b).Payload()) + c.IRS = seqnum.Value(tcp.SequenceNumber()) + + iss := seqnum.Value(789) + c.SendV6Packet(nil, &context.Headers{ + SrcPort: tcp.DestinationPort(), + DstPort: tcp.SourcePort(), + Flags: header.TCPFlagSyn | header.TCPFlagAck, + SeqNum: iss, + AckNum: c.IRS.Add(1), + RcvWnd: 30000, + }) + + // Receive ACK packet. + ackCheckers := append(checkers, checker.TCP( + checker.DstPort(context.TestPort), + checker.TCPFlags(header.TCPFlagAck), + checker.TCPSeqNum(uint32(c.IRS)+1), + checker.TCPAckNum(uint32(iss)+1), + )) + checker.IPv6(t, c.GetV6Packet(), ackCheckers...) + + // Wait for connection to be established. + select { + case <-ch: + if err := c.EP.LastError(); err != nil { + t.Fatalf("Unexpected error when connecting: %v", err) + } + case <-time.After(1 * time.Second): + t.Fatalf("Timed out waiting for connection") + } +} diff --git a/pkg/tcpip/transport/tcp/forwarder_test.go b/pkg/tcpip/transport/tcp/test/e2e/forwarder_test.go similarity index 95% rename from pkg/tcpip/transport/tcp/forwarder_test.go rename to pkg/tcpip/transport/tcp/test/e2e/forwarder_test.go index efbe54a16..b7f88ef46 100644 --- a/pkg/tcpip/transport/tcp/forwarder_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/forwarder_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package forwarder_test import ( "testing" @@ -21,6 +21,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" ) @@ -54,7 +55,7 @@ func TestForwarderSendMSSLessThanMTU(t *testing.T) { } // Check that data gets properly segmented. - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestForwarderDoesNotRejectECNFlags(t *testing.T) { diff --git a/pkg/tcpip/transport/tcp/rcv_test.go b/pkg/tcpip/transport/tcp/test/e2e/rcv_test.go similarity index 99% rename from pkg/tcpip/transport/tcp/rcv_test.go rename to pkg/tcpip/transport/tcp/test/e2e/rcv_test.go index e47a07030..8a026ec46 100644 --- a/pkg/tcpip/transport/tcp/rcv_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/rcv_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package rcv_test import ( "testing" diff --git a/pkg/tcpip/transport/tcp/sack_scoreboard_test.go b/pkg/tcpip/transport/tcp/test/e2e/sack_scoreboard_test.go similarity index 99% rename from pkg/tcpip/transport/tcp/sack_scoreboard_test.go rename to pkg/tcpip/transport/tcp/test/e2e/sack_scoreboard_test.go index b4e5ba0df..d3699dc05 100644 --- a/pkg/tcpip/transport/tcp/sack_scoreboard_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/sack_scoreboard_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package sack_scoreboard_test import ( "testing" diff --git a/pkg/tcpip/transport/tcp/tcp_noracedetector_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_noracedetector_test.go similarity index 99% rename from pkg/tcpip/transport/tcp/tcp_noracedetector_test.go rename to pkg/tcpip/transport/tcp/test/e2e/tcp_noracedetector_test.go index 84fb1c416..260889511 100644 --- a/pkg/tcpip/transport/tcp/tcp_noracedetector_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_noracedetector_test.go @@ -19,7 +19,7 @@ //go:build !race // +build !race -package tcp_test +package tcp_noracedetector_test import ( "bytes" @@ -31,6 +31,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/test/testutil" ) @@ -355,7 +356,7 @@ func TestCubicCongestionAvoidance(t *testing.T) { c := context.New(t, uint32(header.TCPMinimumSize+header.IPv4MinimumSize+maxPayload)) defer c.Cleanup() - enableCUBIC(t, c) + e2e.EnableCUBIC(t, c) c.CreateConnected(789, 30000, -1 /* epRcvBuf */) diff --git a/pkg/tcpip/transport/tcp/tcp_rack_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_rack_test.go similarity index 91% rename from pkg/tcpip/transport/tcp/tcp_rack_test.go rename to pkg/tcpip/transport/tcp/test/e2e/tcp_rack_test.go index 0d36d0dd0..566deed51 100644 --- a/pkg/tcpip/transport/tcp/tcp_rack_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_rack_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package tcp_rack_test import ( "bytes" @@ -24,25 +24,17 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/seqnum" "gvisor.dev/gvisor/pkg/tcpip/stack" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/test/testutil" ) const ( maxPayload = 10 - tsOptionSize = 12 maxTCPOptionSize = 40 mtu = header.TCPMinimumSize + header.IPv4MinimumSize + maxTCPOptionSize + maxPayload ) -func setStackTCPRecovery(t *testing.T, c *context.Context, recovery int) { - t.Helper() - opt := tcpip.TCPRecovery(recovery) - if err := c.Stack().SetTransportProtocolOption(header.TCPProtocolNumber, &opt); err != nil { - t.Fatalf("c.s.SetTransportProtocolOption(%d, &%v(%v)): %s", header.TCPProtocolNumber, opt, opt, err) - } -} - // TestRACKUpdate tests the RACK related fields are updated when an ACK is // received on a SACK enabled connection. func TestRACKUpdate(t *testing.T) { @@ -68,8 +60,8 @@ func TestRACKUpdate(t *testing.T) { } close(probeDone) }) - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) data := make([]byte, maxPayload) for i := range data { @@ -85,7 +77,7 @@ func TestRACKUpdate(t *testing.T) { } bytesRead := 0 - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) bytesRead += maxPayload c.SendAck(seqnum.Value(context.TestInitialSequenceNumber).Add(1), bytesRead) @@ -126,8 +118,8 @@ func TestRACKDetectReorder(t *testing.T) { } close(probeDone) }) - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) data := make([]byte, ackNumToVerify*maxPayload) for i := range data { data[i] = byte(i) @@ -142,7 +134,7 @@ func TestRACKDetectReorder(t *testing.T) { bytesRead := 0 for i := 0; i < ackNumToVerify; i++ { - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) bytesRead += maxPayload } @@ -157,37 +149,6 @@ func TestRACKDetectReorder(t *testing.T) { <-probeDone } -func sendAndReceiveWithSACK(t *testing.T, c *context.Context, numPackets int, enableRACK bool) []byte { - setStackSACKPermitted(t, c, true) - if !enableRACK { - setStackTCPRecovery(t, c, 0) - } - // The delay should be below initial RTO (1s) otherwise retransimission - // will start. Choose a relatively large value so that estimated RTT - // keeps high even after a few rounds of undelayed RTT samples. - c.CreateConnectedWithOptions(header.TCPSynOptions{SACKPermitted: c.SACKEnabled(), TS: true}, 800*time.Millisecond /* delay */) - - data := make([]byte, numPackets*maxPayload) - for i := range data { - data[i] = byte(i) - } - - // Write the data. - var r bytes.Reader - r.Reset(data) - if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { - t.Fatalf("Write failed: %s", err) - } - - bytesRead := 0 - for i := 0; i < numPackets; i++ { - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) - bytesRead += maxPayload - } - - return data -} - const ( validDSACKDetected = 1 failedToDetectDSACK = 2 @@ -223,7 +184,7 @@ func TestRACKTLPRecovery(t *testing.T) { // Send 8 packets. numPackets := 8 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Packets [6-8] are lost. Send cumulative ACK for [1-5]. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -231,7 +192,7 @@ func TestRACKTLPRecovery(t *testing.T) { c.SendAck(seq, bytesRead) // PTO should fire and send #8 packet as a TLP. - c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, e2e.TSOptionSize) var info tcpip.TCPInfoOption if err := c.EP.GetSockOpt(&info); err != nil { t.Fatalf("GetSockOpt failed: %v", err) @@ -249,9 +210,9 @@ func TestRACKTLPRecovery(t *testing.T) { // The sender should be entering RACK based loss-recovery and sending #6 and // #7 one after another. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) bytesRead += maxPayload - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) bytesRead += 2 * maxPayload c.SendAck(seq, bytesRead) @@ -294,7 +255,7 @@ func TestRACKTLPFallbackRTO(t *testing.T) { // Send 8 packets. numPackets := 8 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Packets [6-8] are lost. Send cumulative ACK for [1-5]. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -302,12 +263,12 @@ func TestRACKTLPFallbackRTO(t *testing.T) { c.SendAck(seq, bytesRead) // PTO should fire and send #8 packet as a TLP. - c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, e2e.TSOptionSize) // Either the TLP or the ACK the receiver sent with SACK blocks was lost. // Confirm that RTO fires and retransmits packet #6. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) metricPollFn := func() error { tcpStats := c.Stack().Stats().TCP @@ -346,7 +307,7 @@ func TestNoTLPRecoveryOnDSACK(t *testing.T) { // Send 8 packets. numPackets := 8 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Packets [1-5] are received first. [6-8] took a detour and will take a // while to arrive. Ack [1-5]. @@ -355,7 +316,7 @@ func TestNoTLPRecoveryOnDSACK(t *testing.T) { c.SendAck(seq, bytesRead) // The tail loss probe (#8 packet) is received. - c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, e2e.TSOptionSize) // Now that all 8 packets are received + duplicate 8th packet, send ack. bytesRead += 3 * maxPayload @@ -409,7 +370,7 @@ func TestNoTLPOnSACK(t *testing.T) { // Send 8 packets. numPackets := 8 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Packets [1-5] and #7 were received. #6 and #8 were dropped. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -420,7 +381,7 @@ func TestNoTLPOnSACK(t *testing.T) { // The sender should retransmit #6. If the sender sends a TLP, then #8 will // received and fail this test. - c.ReceiveAndCheckPacketWithOptions(data, 5*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 5*maxPayload, maxPayload, e2e.TSOptionSize) metricPollFn := func() error { tcpStats := c.Stack().Stats().TCP @@ -459,7 +420,7 @@ func TestRACKOnePacketTailLoss(t *testing.T) { // Send 3 packets. numPackets := 3 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Packets [1-2] are received. #3 is lost. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -467,7 +428,7 @@ func TestRACKOnePacketTailLoss(t *testing.T) { c.SendAck(seq, bytesRead) // PTO should fire and send #3 packet as a TLP. - c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, e2e.TSOptionSize) bytesRead += maxPayload c.SendAck(seq, bytesRead) @@ -510,7 +471,7 @@ func TestRACKDetectDSACK(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 8 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Cumulative ACK for [1-5] packets and SACK #8 packet (to prevent TLP). seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -520,7 +481,7 @@ func TestRACKDetectDSACK(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{eighthPStart, eighthPEnd}}) // Expect retransmission of #6 packet after RTO expires. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // Send DSACK block for #6 packet indicating both // initial and retransmitted packet are received and @@ -575,7 +536,7 @@ func TestRACKDetectDSACKWithOutOfOrder(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 10 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Cumulative ACK for [1-5] packets and SACK for #7 packet (to prevent TLP). seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -585,7 +546,7 @@ func TestRACKDetectDSACKWithOutOfOrder(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{seventhPStart, seventhPEnd}}) // Expect retransmission of #6 packet. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // Send DSACK block for #6 packet indicating both // initial and retransmitted packet are received and @@ -622,7 +583,7 @@ func TestRACKDetectDSACKWithOutOfOrderDup(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 10 - sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // ACK [1-5] packets. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -666,7 +627,7 @@ func TestRACKDetectDSACKSingleDup(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 4 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Send ACK for #1 packet. bytesRead := maxPayload @@ -680,7 +641,7 @@ func TestRACKDetectDSACKSingleDup(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) // Expect retransmission of #2 packet. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // ACK for retransmitted #2 packet. bytesRead += maxPayload @@ -737,7 +698,7 @@ func TestRACKDetectDSACKDupWithCumulativeACK(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 6 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Send ACK for #1 packet. bytesRead := maxPayload @@ -751,7 +712,7 @@ func TestRACKDetectDSACKDupWithCumulativeACK(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) // Expect retransmission of #2 packet. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // Received delayed #2 packet. bytesRead += maxPayload @@ -791,7 +752,7 @@ func TestRACKDetectDSACKDup(t *testing.T) { addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) numPackets := 7 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Send ACK for #1 packet. bytesRead := maxPayload @@ -810,7 +771,7 @@ func TestRACKDetectDSACKDup(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start1, end1}, {start, end}}) // Expect retransmission of #2 packet. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // Consider #2 packet has been dropped and SACK #4 packet. start2 := c.IRS.Add(1 + seqnum.Size(3*maxPayload)) @@ -859,7 +820,7 @@ func TestRACKWithInvalidDSACKBlock(t *testing.T) { }) numPackets := 10 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Cumulative ACK for [1-5] packets and SACK for #7 packet (to prevent TLP). seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -869,7 +830,7 @@ func TestRACKWithInvalidDSACKBlock(t *testing.T) { c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{seventhPStart, seventhPEnd}}) // Expect retransmission of #6 packet. - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) // Send DSACK block for #6 packet indicating both // initial and retransmitted packet are received and @@ -924,7 +885,7 @@ func TestRACKCheckReorderWindow(t *testing.T) { addReorderWindowCheckerProbe(c, ackNumToVerify, probeDone) const numPackets = 7 - sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Send ACK for #1 packet. bytesRead := maxPayload @@ -953,7 +914,7 @@ func TestRACKWithDuplicateACK(t *testing.T) { defer c.Cleanup() const numPackets = 4 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Send three duplicate ACKs to trigger fast recovery. The first // segment is considered as lost and will be retransmitted after @@ -967,7 +928,7 @@ func TestRACKWithDuplicateACK(t *testing.T) { } // Receive the retransmitted packet. - c.ReceiveAndCheckPacketWithOptions(data, 0, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 0, maxPayload, e2e.TSOptionSize) metricPollFn := func() error { tcpStats := c.Stack().Stats().TCP @@ -1016,7 +977,7 @@ func TestRACKUpdateSackedOut(t *testing.T) { ackNum++ }) - sendAndReceiveWithSACK(t, c, 8, true /* enableRACK */) + e2e.SendAndReceiveWithSACK(t, c, maxPayload, 8 /* numPackets */, true /* enableRACK */) // ACK for [3-5] packets. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -1038,8 +999,8 @@ func TestRACKWithWindowFull(t *testing.T) { c := context.New(t, uint32(mtu)) defer c.Cleanup() - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) const numPkts = 10 @@ -1057,12 +1018,12 @@ func TestRACKWithWindowFull(t *testing.T) { bytesRead := 0 for i := 0; i < numPkts; i++ { - c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, e2e.TSOptionSize) bytesRead += maxPayload } // Expect retransmission of last packet due to TLP. - c.ReceiveAndCheckPacketWithOptions(data, (numPkts-1)*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, (numPkts-1)*maxPayload, maxPayload, e2e.TSOptionSize) // SACK for first and last packet. start := c.IRS.Add(seqnum.Size(maxPayload)) @@ -1079,13 +1040,13 @@ func TestRACKWithWindowFull(t *testing.T) { time.Sleep(info.RTT) // Expect retransmission of #2 packet. - c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, e2e.TSOptionSize) // Send ACK for #2 packet. c.SendAck(seq, 3*maxPayload) // Expect retransmission of #3 packet. - c.ReceiveAndCheckPacketWithOptions(data, 3*maxPayload, maxPayload, tsOptionSize) + c.ReceiveAndCheckPacketWithOptions(data, 3*maxPayload, maxPayload, e2e.TSOptionSize) // Send ACK with zero window size. c.SendPacket(nil, &context.Headers{ diff --git a/pkg/tcpip/transport/tcp/tcp_sack_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_sack_test.go similarity index 93% rename from pkg/tcpip/transport/tcp/tcp_sack_test.go rename to pkg/tcpip/transport/tcp/test/e2e/tcp_sack_test.go index a3eb8b6ca..899d0f3ea 100644 --- a/pkg/tcpip/transport/tcp/tcp_sack_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_sack_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package tcp_sack_test import ( "bytes" @@ -28,42 +28,28 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/seqnum" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/test/testutil" ) -// createConnectedWithSACKPermittedOption creates and connects c.ep with the -// SACKPermitted option enabled if the stack in the context has the SACK support -// enabled. -func createConnectedWithSACKPermittedOption(c *context.Context) *context.RawEndpoint { - return c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{SACKPermitted: c.SACKEnabled()}) -} - -// createConnectedWithSACKAndTS creates and connects c.ep with the SACK & TS -// option enabled if the stack in the context has SACK and TS enabled. -func createConnectedWithSACKAndTS(c *context.Context) *context.RawEndpoint { - return c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{SACKPermitted: c.SACKEnabled(), TS: true}) -} - -func setStackSACKPermitted(t *testing.T, c *context.Context, enable bool) { - t.Helper() - opt := tcpip.TCPSACKEnabled(enable) - if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { - t.Fatalf("c.s.SetTransportProtocolOption(%d, &%T(%t)): %s", tcp.ProtocolNumber, opt, opt, err) - } -} +const ( + maxPayload = 10 + tsOptionSize = 12 + mtu = header.TCPMinimumSize + header.IPv4MinimumSize + e2e.MaxTCPOptionSize + maxPayload +) // TestSackPermittedConnect establishes a connection with the SACK option // enabled. func TestSackPermittedConnect(t *testing.T) { for _, sackEnabled := range []bool{false, true} { t.Run(fmt.Sprintf("stack.sackEnabled: %v", sackEnabled), func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() - setStackSACKPermitted(t, c, sackEnabled) - setStackTCPRecovery(t, c, 0) - rep := createConnectedWithSACKPermittedOption(c) + e2e.SetStackSACKPermitted(t, c, sackEnabled) + e2e.SetStackTCPRecovery(t, c, 0) + rep := e2e.CreateConnectedWithSACKPermittedOption(c) data := []byte{1, 2, 3} rep.SendPacket(data, nil) @@ -103,11 +89,11 @@ func TestSackPermittedConnect(t *testing.T) { func TestSackDisabledConnect(t *testing.T) { for _, sackEnabled := range []bool{false, true} { t.Run(fmt.Sprintf("sackEnabled: %v", sackEnabled), func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() - setStackSACKPermitted(t, c, sackEnabled) - setStackTCPRecovery(t, c, 0) + e2e.SetStackSACKPermitted(t, c, sackEnabled) + e2e.SetStackTCPRecovery(t, c, 0) rep := c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{}) @@ -159,7 +145,7 @@ func TestSackPermittedAccept(t *testing.T) { t.Run(fmt.Sprintf("test: %#v", tc), func(t *testing.T) { for _, sackEnabled := range []bool{false, true} { t.Run(fmt.Sprintf("test stack.sackEnabled: %v", sackEnabled), func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() if tc.cookieEnabled { @@ -168,10 +154,10 @@ func TestSackPermittedAccept(t *testing.T) { t.Fatalf("SetTransportProtocolOption(%d, &%T(%t)): %s", tcp.ProtocolNumber, opt, opt, err) } } - setStackSACKPermitted(t, c, sackEnabled) - setStackTCPRecovery(t, c, 0) + e2e.SetStackSACKPermitted(t, c, sackEnabled) + e2e.SetStackTCPRecovery(t, c, 0) - rep := c.AcceptWithOptionsNoDelay(tc.wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS, SACKPermitted: tc.sackPermitted}) + rep := c.AcceptWithOptionsNoDelay(tc.wndScale, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS, SACKPermitted: tc.sackPermitted}) // Now verify no SACK blocks are // received when sack is disabled. data := []byte{1, 2, 3} @@ -232,7 +218,7 @@ func TestSackDisabledAccept(t *testing.T) { t.Run(fmt.Sprintf("test: %#v", tc), func(t *testing.T) { for _, sackEnabled := range []bool{false, true} { t.Run(fmt.Sprintf("test: sackEnabled: %v", sackEnabled), func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() if tc.cookieEnabled { @@ -242,10 +228,10 @@ func TestSackDisabledAccept(t *testing.T) { } } - setStackSACKPermitted(t, c, sackEnabled) - setStackTCPRecovery(t, c, 0) + e2e.SetStackSACKPermitted(t, c, sackEnabled) + e2e.SetStackTCPRecovery(t, c, 0) - rep := c.AcceptWithOptionsNoDelay(tc.wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS}) + rep := c.AcceptWithOptionsNoDelay(tc.wndScale, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}) // Now verify no SACK blocks are // received when sack is disabled. @@ -373,11 +359,9 @@ func TestSACKRecovery(t *testing.T) { // Enabling SACK means the payload size is reduced to account // for the extra space required for the TCP options. // - // We increase the MTU by 40 bytes to account for SACK and Timestamp - // options. - const maxTCPOptionSize = 40 - - c := context.New(t, uint32(header.TCPMinimumSize+header.IPv4MinimumSize+maxTCPOptionSize+maxPayload)) + // We increase the MTU by e2e.MaxTCPOptionSize bytes to account for SACK + // and Timestamp options. + c := context.New(t, uint32(header.TCPMinimumSize+header.IPv4MinimumSize+e2e.MaxTCPOptionSize+maxPayload)) defer c.Cleanup() c.Stack().AddTCPProbe(func(s stack.TCPEndpointState) { @@ -390,9 +374,9 @@ func TestSACKRecovery(t *testing.T) { // causes the test to panic due to logging after test finished. log.Printf("state: %+v\n", s) }) - setStackSACKPermitted(t, c, true) - setStackTCPRecovery(t, c, 0) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.SetStackTCPRecovery(t, c, 0) + e2e.CreateConnectedWithSACKAndTS(c) const iterations = 3 data := make([]byte, 2*maxPayload*(tcp.InitialCwnd<<(iterations+1))) @@ -604,7 +588,7 @@ func TestRecoveryEntry(t *testing.T) { defer c.Cleanup() numPackets := 5 - data := sendAndReceiveWithSACK(t, c, numPackets, false /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, false /* enableRACK */) // Ack #1 packet. seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) @@ -768,8 +752,8 @@ func TestDetectSpuriousRecoveryWithRTO(t *testing.T) { close(probeDone) }) - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) numPackets := 5 data := make([]byte, numPackets*maxPayload) for i := range data { @@ -854,8 +838,8 @@ func TestSACKDetectSpuriousRecoveryWithDupACK(t *testing.T) { close(probeDone) }) - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) numPackets := 5 data := make([]byte, numPackets*maxPayload) for i := range data { @@ -930,10 +914,10 @@ func TestSACKDetectSpuriousRecoveryWithDupACK(t *testing.T) { func TestNoSpuriousRecoveryWithDSACK(t *testing.T) { c := context.New(t, uint32(mtu)) defer c.Cleanup() - setStackSACKPermitted(t, c, true) - createConnectedWithSACKAndTS(c) + e2e.SetStackSACKPermitted(t, c, true) + e2e.CreateConnectedWithSACKAndTS(c) numPackets := 5 - data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) + data := e2e.SendAndReceiveWithSACK(t, c, maxPayload, numPackets, true /* enableRACK */) // Receive the retransmitted packet after TLP. c.ReceiveAndCheckPacketWithOptions(data, 4*maxPayload, maxPayload, tsOptionSize) diff --git a/pkg/tcpip/transport/tcp/tcp_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go similarity index 97% rename from pkg/tcpip/transport/tcp/tcp_test.go rename to pkg/tcpip/transport/tcp/test/e2e/tcp_test.go index d391f4516..6d2c32d92 100644 --- a/pkg/tcpip/transport/tcp/tcp_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go @@ -38,6 +38,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/stack" tcpiptestutil "gvisor.dev/gvisor/pkg/tcpip/testutil" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/test/testutil" "gvisor.dev/gvisor/pkg/waiter" @@ -103,19 +104,8 @@ func (e *endpointTester) CheckReadFull(t *testing.T, count int, notifyRead <-cha return buf.Bytes() } -const ( - // defaultMTU is the MTU, in bytes, used throughout the tests, except - // where another value is explicitly used. It is chosen to match the MTU - // of loopback interfaces on linux systems. - defaultMTU = 65535 - - // defaultIPv4MSS is the MSS sent by the network stack in SYN/SYN-ACK for an - // IPv4 endpoint when the MTU is set to defaultMTU in the test. - defaultIPv4MSS = defaultMTU - header.IPv4MinimumSize - header.TCPMinimumSize -) - func TestGiveUpConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() var wq waiter.Queue @@ -162,7 +152,7 @@ func TestGiveUpConnect(t *testing.T) { // Test for ICMP error handling without completing handshake. func TestConnectICMPError(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() var wq waiter.Queue @@ -196,7 +186,7 @@ func TestConnectICMPError(t *testing.T) { // tests the handshake completion logic on ICMP errors. wep.StopWork() - c.SendICMPPacket(header.ICMPv4DstUnreachable, header.ICMPv4HostUnreachable, nil, syn, defaultMTU) + c.SendICMPPacket(header.ICMPv4DstUnreachable, header.ICMPv4HostUnreachable, nil, syn, e2e.DefaultMTU) for { if err := wep.LastErrorLocked(); err != nil { @@ -231,7 +221,7 @@ func TestConnectICMPError(t *testing.T) { } func TestConnectIncrementActiveConnection(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -244,7 +234,7 @@ func TestConnectIncrementActiveConnection(t *testing.T) { } func TestConnectDoesNotIncrementFailedConnectionAttempts(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -260,7 +250,7 @@ func TestConnectDoesNotIncrementFailedConnectionAttempts(t *testing.T) { } func TestActiveFailedConnectionAttemptIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -287,7 +277,7 @@ func TestActiveFailedConnectionAttemptIncrement(t *testing.T) { } func TestCloseWithoutConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -305,7 +295,7 @@ func TestCloseWithoutConnect(t *testing.T) { } func TestTCPSegmentsSentIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -322,7 +312,7 @@ func TestTCPSegmentsSentIncrement(t *testing.T) { } func TestTCPResetsSentIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() wq := &waiter.Queue{} @@ -384,7 +374,7 @@ func TestTCPResetsSentIncrement(t *testing.T) { // DstUnreachable packet when we try send a packet which is not part // of an active session. func TestTCPResetsSentNoICMP(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -416,7 +406,7 @@ func TestTCPResetsSentNoICMP(t *testing.T) { // a RST if an ACK is received on the listening socket for which there is no // active handshake in progress and we are not using SYN cookies. func TestTCPResetSentForACKWhenNotUsingSynCookies(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPLingerTimeout to 5 seconds so that sockets are marked closed @@ -526,7 +516,7 @@ func TestTCPResetSentForACKWhenNotUsingSynCookies(t *testing.T) { } func TestTCPResetsReceivedIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -550,7 +540,7 @@ func TestTCPResetsReceivedIncrement(t *testing.T) { } func TestTCPResetsDoNotGenerateResets(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -575,14 +565,14 @@ func TestTCPResetsDoNotGenerateResets(t *testing.T) { } func TestActiveHandshake(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) } func TestNonBlockingClose(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -598,7 +588,7 @@ func TestNonBlockingClose(t *testing.T) { } func TestConnectResetAfterClose(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPLinger to 3 seconds so that sockets are marked closed @@ -674,7 +664,7 @@ func TestConnectResetAfterClose(t *testing.T) { // TestCurrentConnectedIncrement tests increment of the current // established and connected counters. func TestCurrentConnectedIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPTimeWaitTimeout to 1 seconds so that sockets are marked closed @@ -760,7 +750,7 @@ func TestCurrentConnectedIncrement(t *testing.T) { // when the endpoint transitions to StateClose. The in-flight segments would be // re-enqueued to a any listening endpoint. func TestClosingWithEnqueuedSegments(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -875,7 +865,7 @@ func TestClosingWithEnqueuedSegments(t *testing.T) { } func TestSimpleReceive(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -1137,7 +1127,7 @@ func TestUserSuppliedMSSOnListenAccept(t *testing.T) { } } func TestSendRstOnListenerRxSynAckV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -1165,7 +1155,7 @@ func TestSendRstOnListenerRxSynAckV4(t *testing.T) { } func TestSendRstOnListenerRxSynAckV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) @@ -1198,7 +1188,7 @@ func TestSendRstOnListenerRxSynAckV6(t *testing.T) { // // This test uses IPv4. func TestTCPAckBeforeAcceptV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -1236,7 +1226,7 @@ func TestTCPAckBeforeAcceptV4(t *testing.T) { // // This test uses IPv6. func TestTCPAckBeforeAcceptV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) @@ -1269,7 +1259,7 @@ func TestTCPAckBeforeAcceptV6(t *testing.T) { } func TestSendRstOnListenerRxAckV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1 /* epRcvBuf */) @@ -1297,7 +1287,7 @@ func TestSendRstOnListenerRxAckV4(t *testing.T) { } func TestSendRstOnListenerRxAckV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true /* v6Only */) @@ -1327,7 +1317,7 @@ func TestSendRstOnListenerRxAckV6(t *testing.T) { // TestListenShutdown tests for the listening endpoint replying with RST // on read shutdown. func TestListenShutdown(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1 /* epRcvBuf */) @@ -1452,7 +1442,7 @@ func TestListenerReadinessOnEvent(t *testing.T) { // drain the accept-queue when closed. This should reset all of the // pending connections that are waiting to be accepted. func TestListenCloseWhileConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1 /* epRcvBuf */) @@ -1486,7 +1476,7 @@ func TestListenCloseWhileConnect(t *testing.T) { } func TestTOSV4(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() ep, err := c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) @@ -1509,7 +1499,7 @@ func TestTOSV4(t *testing.T) { t.Errorf("got GetSockOptInt(IPv4TOSOption) = %d, want = %d", v, tos) } - testV4Connect(t, c, checker.TOS(tos, 0)) + e2e.TestV4Connect(t, c, checker.TOS(tos, 0)) data := []byte{1, 2, 3} var r bytes.Reader @@ -1538,7 +1528,7 @@ func TestTOSV4(t *testing.T) { } func TestTrafficClassV6(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(false) @@ -1558,7 +1548,7 @@ func TestTrafficClassV6(t *testing.T) { } // Test the connection request. - testV6Connect(t, c, checker.TOS(tos, 0)) + e2e.TestV6Connect(t, c, checker.TOS(tos, 0)) data := []byte{1, 2, 3} var r bytes.Reader @@ -1597,7 +1587,7 @@ func TestConnectBindToDevice(t *testing.T) { {"AnyDevice", 0, tcp.StateEstablished}, } { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -1658,7 +1648,7 @@ func TestShutdownConnectingSocket(t *testing.T) { {"ShutdownReadWrite", tcpip.ShutdownRead | tcpip.ShutdownWrite}, } { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create an endpoint, don't handshake because we want to interfere with @@ -1722,7 +1712,7 @@ func TestSynSent(t *testing.T) { {"CloseOnSynSent", false}, } { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create an endpoint, don't handshake because we want to interfere with the @@ -1800,7 +1790,7 @@ func TestSynSent(t *testing.T) { } func TestOutOfOrderReceive(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -1868,7 +1858,7 @@ func TestOutOfOrderReceive(t *testing.T) { } func TestOutOfOrderFlood(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() rcvBufSz := math.MaxUint16 @@ -1942,7 +1932,7 @@ func TestOutOfOrderFlood(t *testing.T) { } func TestRstOnCloseWithUnreadData(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -2011,7 +2001,7 @@ func TestRstOnCloseWithUnreadData(t *testing.T) { } func TestRstOnCloseWithUnreadDataFinConvertRst(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -2102,7 +2092,7 @@ func TestRstOnCloseWithUnreadDataFinConvertRst(t *testing.T) { } func TestShutdownRead(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -2122,7 +2112,7 @@ func TestShutdownRead(t *testing.T) { } func TestFullWindowReceive(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() const rcvBufSz = 10 @@ -2405,7 +2395,7 @@ func TestSmallReceiveBufferReadiness(t *testing.T) { // segment overhead. It tests for the right edge of the window to not grow when // the endpoint is not being read from. func TestSmallSegReceiveWindowAdvertisement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() opt := tcpip.TCPReceiveBufferSizeRangeOption{ @@ -2417,7 +2407,7 @@ func TestSmallSegReceiveWindowAdvertisement(t *testing.T) { t.Fatalf("SetTransportProtocolOption(%d, &%#v): %s", tcp.ProtocolNumber, opt, err) } - c.AcceptWithOptionsNoDelay(tcp.FindWndScale(seqnum.Size(opt.Default)), header.TCPSynOptions{MSS: defaultIPv4MSS}) + c.AcceptWithOptionsNoDelay(tcp.FindWndScale(seqnum.Size(opt.Default)), header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}) // Bump up the receive buffer size such that, when the receive window grows, // the scaled window exceeds maxUint16. @@ -2482,7 +2472,7 @@ func TestSmallSegReceiveWindowAdvertisement(t *testing.T) { } func TestNoWindowShrinking(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Start off with a certain receive buffer then cut it in half and verify that @@ -2613,7 +2603,7 @@ func TestNoWindowShrinking(t *testing.T) { } func TestSimpleSend(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -2654,7 +2644,7 @@ func TestSimpleSend(t *testing.T) { } func TestZeroWindowSend(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 0 /* rcvWnd */, -1 /* epRcvBuf */) @@ -2719,7 +2709,7 @@ func TestZeroWindowSend(t *testing.T) { func TestScaledWindowConnect(t *testing.T) { // This test ensures that window scaling is used when the peer // does advertise it and connection is established with Connect(). - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set the window size greater than the maximum non-scaled window. @@ -2753,7 +2743,7 @@ func TestScaledWindowConnect(t *testing.T) { func TestNonScaledWindowConnect(t *testing.T) { // This test ensures that window scaling is not used when the peer // doesn't advertise it and connection is established with Connect(). - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set the window size greater than the maximum non-scaled window. @@ -2785,7 +2775,7 @@ func TestNonScaledWindowConnect(t *testing.T) { func TestScaledWindowAccept(t *testing.T) { // This test ensures that window scaling is used when the peer // does advertise it and connection is established with Accept(). - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create EP and start listening. @@ -2809,7 +2799,7 @@ func TestScaledWindowAccept(t *testing.T) { // Do 3-way handshake. // wndScale expected is 3 as 65535 * 3 * 2 < 65535 * 2^3 but > 65535 *2 *2 - c.PassiveConnectWithOptions(100, 3 /* wndScale */, header.TCPSynOptions{MSS: defaultIPv4MSS}, 0 /* delay */) + c.PassiveConnectWithOptions(100, 3 /* wndScale */, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}, 0 /* delay */) // Try to accept the connection. we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) @@ -2857,7 +2847,7 @@ func TestScaledWindowAccept(t *testing.T) { func TestNonScaledWindowAccept(t *testing.T) { // This test ensures that window scaling is not used when the peer // doesn't advertise it and connection is established with Accept(). - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create EP and start listening. @@ -2881,7 +2871,7 @@ func TestNonScaledWindowAccept(t *testing.T) { // Do 3-way handshake w/ window scaling disabled. The SYN-ACK to the SYN // should not carry the window scaling option. - c.PassiveConnect(100, -1, header.TCPSynOptions{MSS: defaultIPv4MSS}) + c.PassiveConnect(100, -1, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}) // Try to accept the connection. we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) @@ -2930,7 +2920,7 @@ func TestZeroScaledWindowReceive(t *testing.T) { // This test ensures that the endpoint sends a non-zero window size // advertisement when the scaled window transitions from 0 to non-zero, // but the actual window (not scaled) hasn't gotten to zero. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set the buffer size such that a window scale of 5 will be used. @@ -3014,7 +3004,7 @@ func TestZeroScaledWindowReceive(t *testing.T) { // we need to read at 3 packets. w := tcpip.LimitedWriter{ W: ioutil.Discard, - N: defaultMTU * 2, + N: e2e.DefaultMTU * 2, } for w.N != 0 { res, err := c.EP.Read(&w, tcpip.ReadOptions{}) @@ -3030,7 +3020,7 @@ func TestZeroScaledWindowReceive(t *testing.T) { checker.DstPort(context.TestPort), checker.TCPSeqNum(uint32(c.IRS)+1), checker.TCPAckNum(uint32(iss)+uint32(sent)), - checker.TCPWindowGreaterThanEq(uint16(defaultMTU>>ws)), + checker.TCPWindowGreaterThanEq(uint16(e2e.DefaultMTU>>ws)), checker.TCPFlags(header.TCPFlagAck), ), ) @@ -3064,7 +3054,7 @@ func TestSegmentMerging(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -3146,7 +3136,7 @@ func TestSegmentMerging(t *testing.T) { } func TestDelay(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -3196,7 +3186,7 @@ func TestDelay(t *testing.T) { } func TestUndelay(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -3279,7 +3269,7 @@ func TestMSSNotDelayed(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { const maxPayload = 100 - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnectedWithRawOptions(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */, []byte{ @@ -3332,75 +3322,13 @@ func TestMSSNotDelayed(t *testing.T) { } } -func testBrokenUpWrite(t *testing.T, c *context.Context, maxPayload int) { - payloadMultiplier := 10 - dataLen := payloadMultiplier * maxPayload - data := make([]byte, dataLen) - for i := range data { - data[i] = byte(i) - } - - var r bytes.Reader - r.Reset(data) - if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { - t.Fatalf("Write failed: %s", err) - } - - // Check that data is received in chunks. - bytesReceived := 0 - numPackets := 0 - iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) - for bytesReceived != dataLen { - b := c.GetPacket() - numPackets++ - tcpHdr := header.TCP(header.IPv4(b).Payload()) - payloadLen := len(tcpHdr.Payload()) - checker.IPv4(t, b, - checker.TCP( - checker.DstPort(context.TestPort), - checker.TCPSeqNum(uint32(c.IRS)+1+uint32(bytesReceived)), - checker.TCPAckNum(uint32(iss)), - checker.TCPFlagsMatch(header.TCPFlagAck, ^header.TCPFlagPsh), - ), - ) - - pdata := data[bytesReceived : bytesReceived+payloadLen] - if p := tcpHdr.Payload(); !bytes.Equal(pdata, p) { - t.Fatalf("got data = %v, want = %v", p, pdata) - } - bytesReceived += payloadLen - var options []byte - if c.TimeStampEnabled { - // If timestamp option is enabled, echo back the timestamp and increment - // the TSEcr value included in the packet and send that back as the TSVal. - parsedOpts := tcpHdr.ParsedOptions() - tsOpt := [12]byte{header.TCPOptionNOP, header.TCPOptionNOP} - header.EncodeTSOption(parsedOpts.TSEcr+1, parsedOpts.TSVal, tsOpt[2:]) - options = tsOpt[:] - } - // Acknowledge the data. - c.SendPacket(nil, &context.Headers{ - SrcPort: context.TestPort, - DstPort: c.Port, - Flags: header.TCPFlagAck, - SeqNum: iss, - AckNum: c.IRS.Add(1 + seqnum.Size(bytesReceived)), - RcvWnd: 30000, - TCPOpts: options, - }) - } - if numPackets == 1 { - t.Fatalf("expected write to be broken up into multiple packets, but got 1 packet") - } -} - func TestSendGreaterThanMTU(t *testing.T) { const maxPayload = 100 c := context.New(t, uint32(header.TCPMinimumSize+header.IPv4MinimumSize+maxPayload)) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestDefaultTTL(t *testing.T) { @@ -3520,7 +3448,7 @@ func TestActiveSendMSSLessThanMTU(t *testing.T) { c.CreateConnectedWithRawOptions(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */, []byte{ header.TCPOptionMSS, 4, byte(maxPayload / 256), byte(maxPayload % 256), }) - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestPassiveSendMSSLessThanMTU(t *testing.T) { @@ -3574,7 +3502,7 @@ func TestPassiveSendMSSLessThanMTU(t *testing.T) { } // Check that data gets properly segmented. - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestSynCookiePassiveSendMSSLessThanMTU(t *testing.T) { @@ -3628,7 +3556,7 @@ func TestSynCookiePassiveSendMSSLessThanMTU(t *testing.T) { } // Check that data gets properly segmented. - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestSynOptionsOnActiveConnect(t *testing.T) { @@ -3720,7 +3648,7 @@ func TestSynOptionsOnActiveConnect(t *testing.T) { } func TestCloseListener(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create listener. @@ -3747,7 +3675,7 @@ func TestCloseListener(t *testing.T) { } func TestReceiveOnResetConnection(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -3813,7 +3741,7 @@ loop: } func TestSendOnResetConnection(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -3843,7 +3771,7 @@ func TestSendOnResetConnection(t *testing.T) { // TestMaxRetransmitsTimeout tests if the connection is timed out after // a segment has been retransmitted MaxRetries times. func TestMaxRetransmitsTimeout(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() const numRetries = 2 @@ -3910,7 +3838,7 @@ func TestMaxRetransmitsTimeout(t *testing.T) { // TestMaxRTO tests if the retransmit interval caps to MaxRTO. func TestMaxRTO(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() rto := 1 * time.Second @@ -3956,7 +3884,7 @@ func TestMaxRTO(t *testing.T) { // result in a panic on an RTO as no segment should have been queued for // a zero sized write. func TestZeroSizedWriteRetransmit(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000 /* rcvWnd */, -1 /* epRcvBuf */) @@ -3995,7 +3923,7 @@ func TestRetransmitIPv4IDUniqueness(t *testing.T) { {"512Bytes", 512}, } { t.Run(tc.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() minRTOOpt := tcpip.TCPMinRTOOption(time.Second) @@ -4048,7 +3976,7 @@ func TestRetransmitIPv4IDUniqueness(t *testing.T) { } func TestFinImmediately(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4092,7 +4020,7 @@ func TestFinImmediately(t *testing.T) { } func TestFinRetransmit(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4147,7 +4075,7 @@ func TestFinRetransmit(t *testing.T) { } func TestFinWithNoPendingData(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4221,7 +4149,7 @@ func TestFinWithNoPendingData(t *testing.T) { } func TestFinWithPendingDataCwndFull(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4312,7 +4240,7 @@ func TestFinWithPendingDataCwndFull(t *testing.T) { } func TestFinWithPendingData(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4402,7 +4330,7 @@ func TestFinWithPendingData(t *testing.T) { } func TestFinWithPartialAck(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4507,7 +4435,7 @@ func TestFinWithPartialAck(t *testing.T) { } func TestUpdateListenBacklog(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create listener. @@ -4537,10 +4465,10 @@ func scaledSendWindow(t *testing.T, scale uint8) { // This test ensures that the endpoint is using the right scaling by // sending a buffer that is larger than the window size, and ensuring // that the endpoint doesn't send more than allowed. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() - maxPayload := defaultMTU - header.IPv4MinimumSize - header.TCPMinimumSize + maxPayload := e2e.DefaultMTU - header.IPv4MinimumSize - header.TCPMinimumSize c.CreateConnectedWithRawOptions(context.TestInitialSequenceNumber, 0, -1 /* epRcvBuf */, []byte{ header.TCPOptionMSS, 4, byte(maxPayload / 256), byte(maxPayload % 256), header.TCPOptionWS, 3, scale, header.TCPOptionNOP, @@ -4592,7 +4520,7 @@ func TestScaledSendWindow(t *testing.T) { } func TestReceivedValidSegmentCountIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) stats := c.Stack().Stats() @@ -4622,7 +4550,7 @@ func TestReceivedValidSegmentCountIncrement(t *testing.T) { } func TestReceivedInvalidSegmentCountIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) stats := c.Stack().Stats() @@ -4650,7 +4578,7 @@ func TestReceivedInvalidSegmentCountIncrement(t *testing.T) { } func TestReceivedIncorrectChecksumIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) stats := c.Stack().Stats() @@ -4684,7 +4612,7 @@ func TestReceivedSegmentQueuing(t *testing.T) { // endpoint and checks that they're all received and acknowledged by // the endpoint, that is, that none of the segments are dropped by // internal queues. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -4731,7 +4659,7 @@ func TestReadAfterClosedState(t *testing.T) { // has transitioned to closedState still works if there is pending // data. To transition to stateClosed without calling Close(), we must // shutdown the send path and the peer must send its own FIN. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPTimeWaitTimeout to 1 seconds so that sockets are marked closed @@ -4842,7 +4770,7 @@ func TestReadAfterClosedState(t *testing.T) { func TestReusePort(t *testing.T) { // This test ensures that ports are immediately available for reuse // after Close on the endpoints using them returns. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // First case, just an endpoint that was bound. @@ -5556,16 +5484,8 @@ func TestEndpointSetCongestionControl(t *testing.T) { } } -func enableCUBIC(t *testing.T, c *context.Context) { - t.Helper() - opt := tcpip.CongestionControlOption("cubic") - if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { - t.Fatalf("SetTransportProtocolOption(%d, &%T(%s)) %s", tcp.ProtocolNumber, opt, opt, err) - } -} - func TestKeepalive(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -5802,7 +5722,7 @@ func executeV6Handshake(t *testing.T, c *context.Context, srcPort uint16, synCoo // TestListenBacklogFull tests that netstack does not complete handshakes if the // listen backlog for the endpoint is full. func TestListenBacklogFull(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -5971,7 +5891,7 @@ func TestListenNoAcceptNonUnicastV4(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -6071,7 +5991,7 @@ func TestListenNoAcceptNonUnicastV6(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateV6Endpoint(true) @@ -6117,7 +6037,7 @@ func TestListenNoAcceptNonUnicastV6(t *testing.T) { } func TestListenSynRcvdQueueFull(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -6218,7 +6138,7 @@ func TestListenSynRcvdQueueFull(t *testing.T) { } func TestListenBacklogFullSynCookieInUse(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -6288,7 +6208,7 @@ func TestListenBacklogFullSynCookieInUse(t *testing.T) { } func TestSYNRetransmit(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -6332,7 +6252,7 @@ func TestSYNRetransmit(t *testing.T) { } func TestSynRcvdBadSeqNumber(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create TCP endpoint. @@ -6437,7 +6357,7 @@ func TestSynRcvdBadSeqNumber(t *testing.T) { } func TestPassiveConnectionAttemptIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() ep, err := c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) @@ -6490,7 +6410,7 @@ func TestPassiveConnectionAttemptIncrement(t *testing.T) { } func TestPassiveFailedConnectionAttemptIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -6565,7 +6485,7 @@ func TestPassiveFailedConnectionAttemptIncrement(t *testing.T) { } func TestListenDropIncrement(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() stats := c.Stack().Stats() @@ -6613,7 +6533,7 @@ func TestListenDropIncrement(t *testing.T) { } func TestEndpointBindListenAcceptState(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() wq := &waiter.Queue{} ep, err := c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, wq) @@ -6641,7 +6561,7 @@ func TestEndpointBindListenAcceptState(t *testing.T) { t.Errorf("unexpected endpoint state: want %s, got %s", want, got) } - c.PassiveConnectWithOptions(100, 5, header.TCPSynOptions{MSS: defaultIPv4MSS}, 0 /* delay */) + c.PassiveConnectWithOptions(100, 5, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}, 0 /* delay */) // Try to accept the connection. we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) @@ -6984,13 +6904,13 @@ func TestReceiveBufferAutoTuning(t *testing.T) { } func TestDelayEnabled(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() checkDelayOption(t, c, false, false) // Delay is disabled by default. for _, delayEnabled := range []bool{false, true} { t.Run(fmt.Sprintf("delayEnabled=%t", delayEnabled), func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() opt := tcpip.TCPDelayEnabled(delayEnabled) if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { @@ -7060,7 +6980,7 @@ func TestTCPLingerTimeout(t *testing.T) { } func TestTCPTimeWaitRSTIgnored(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() wq := &waiter.Queue{} @@ -7179,7 +7099,7 @@ func TestTCPTimeWaitRSTIgnored(t *testing.T) { } func TestTCPTimeWaitOutOfOrder(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() wq := &waiter.Queue{} @@ -7286,7 +7206,7 @@ func TestTCPTimeWaitOutOfOrder(t *testing.T) { } func TestTCPTimeWaitNewSyn(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() wq := &waiter.Queue{} @@ -7440,7 +7360,7 @@ func TestTCPTimeWaitNewSyn(t *testing.T) { } func TestTCPTimeWaitDuplicateFINExtendsTimeWait(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPTimeWaitTimeout to 5 seconds so that sockets are marked closed @@ -7591,7 +7511,7 @@ func TestTCPTimeWaitDuplicateFINExtendsTimeWait(t *testing.T) { } func TestTCPCloseWithData(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Set TCPTimeWaitTimeout to 5 seconds so that sockets are marked closed @@ -7764,7 +7684,7 @@ func TestTCPCloseWithData(t *testing.T) { } func TestTCPUserTimeout(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() initRTO := 1 * time.Second @@ -7855,7 +7775,7 @@ func TestTCPUserTimeout(t *testing.T) { } func TestKeepaliveWithUserTimeout(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRcvBuf */) @@ -7940,7 +7860,7 @@ func TestKeepaliveWithUserTimeout(t *testing.T) { func TestIncreaseWindowOnRead(t *testing.T) { // This test ensures that the endpoint sends an ack, // after read() when the window grows by more than 1 MSS. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() const rcvBuf = 65535 * 10 @@ -7950,7 +7870,7 @@ func TestIncreaseWindowOnRead(t *testing.T) { // payloads make it equal or longer than MSS. remain := rcvBuf * 2 sent := 0 - data := make([]byte, defaultMTU/2) + data := make([]byte, e2e.DefaultMTU/2) iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) for remain > len(data) { c.SendPacket(data, &context.Headers{ @@ -7973,8 +7893,8 @@ func TestIncreaseWindowOnRead(t *testing.T) { checker.TCPFlags(header.TCPFlagAck), ), ) - // Break once the window drops below defaultMTU/2 - if wnd := header.TCP(header.IPv4(pkt).Payload()).WindowSize(); wnd < defaultMTU/2 { + // Break once the window drops below e2e.DefaultMTU/2 + if wnd := header.TCP(header.IPv4(pkt).Payload()).WindowSize(); wnd < e2e.DefaultMTU/2 { break } } @@ -7983,9 +7903,9 @@ func TestIncreaseWindowOnRead(t *testing.T) { // worth of data as receive buffer space w := tcpip.LimitedWriter{ W: ioutil.Discard, - // defaultMTU is a good enough estimate for the MSS used for this + // e2e.DefaultMTU is a good enough estimate for the MSS used for this // connection. - N: defaultMTU * 2, + N: e2e.DefaultMTU * 2, } for w.N != 0 { _, err := c.EP.Read(&w, tcpip.ReadOptions{}) @@ -8010,7 +7930,7 @@ func TestIncreaseWindowOnRead(t *testing.T) { func TestIncreaseWindowOnBufferResize(t *testing.T) { // This test ensures that the endpoint sends an ack, // after available recv buffer grows to more than 1 MSS. - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() const rcvBuf = 65535 * 10 @@ -8020,7 +7940,7 @@ func TestIncreaseWindowOnBufferResize(t *testing.T) { // payloads make it equal or longer than MSS. remain := rcvBuf sent := 0 - data := make([]byte, defaultMTU/2) + data := make([]byte, e2e.DefaultMTU/2) iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) for remain > len(data) { c.SendPacket(data, &context.Headers{ @@ -8061,7 +7981,7 @@ func TestIncreaseWindowOnBufferResize(t *testing.T) { } func TestTCPDeferAccept(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -8120,7 +8040,7 @@ func TestTCPDeferAccept(t *testing.T) { } func TestTCPDeferAcceptTimeout(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.Create(-1) @@ -8191,7 +8111,7 @@ func TestTCPDeferAcceptTimeout(t *testing.T) { } func TestResetDuringClose(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnected(context.TestInitialSequenceNumber, 30000, -1 /* epRecvBuf */) @@ -8245,7 +8165,7 @@ func TestResetDuringClose(t *testing.T) { } func TestStackTimeWaitReuse(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() s := c.Stack() @@ -8259,7 +8179,7 @@ func TestStackTimeWaitReuse(t *testing.T) { } func TestSetStackTimeWaitReuse(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() s := c.Stack() @@ -8334,7 +8254,7 @@ func TestHandshakeRTT(t *testing.T) { tt := tt t.Run(fmt.Sprintf("connect=%t,TS=%t,cookie=%t,retrans=%t)", tt.connect, tt.tsEnabled, tt.useCookie, tt.retrans), func(t *testing.T) { t.Parallel() - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) if tt.useCookie { opt := tcpip.TCPAlwaysUseSynCookies(true) if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil { @@ -8349,7 +8269,7 @@ func TestHandshakeRTT(t *testing.T) { if tt.connect { c.CreateConnectedWithOptions(synOpts, tt.delay) } else { - synOpts.MSS = defaultIPv4MSS + synOpts.MSS = e2e.DefaultIPv4MSS synOpts.WS = -1 c.AcceptWithOptions(-1, synOpts, tt.delay) } @@ -8371,7 +8291,7 @@ func TestHandshakeRTT(t *testing.T) { } func TestSetRTO(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) minRTO, maxRTO := tcpRTOMinMax(t, c) for _, tt := range []struct { name string @@ -8400,7 +8320,7 @@ func TestSetRTO(t *testing.T) { }, } { t.Run(tt.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) var opt tcpip.SettableTransportProtocolOption if tt.minRTO > 0 { min := tcpip.TCPMinRTOOption(tt.minRTO) @@ -8453,7 +8373,7 @@ func generateRandomPayload(t *testing.T, n int) []byte { func TestSendBufferTuning(t *testing.T) { const maxPayload = 536 - const mtu = header.TCPMinimumSize + header.IPv4MinimumSize + maxTCPOptionSize + maxPayload + const mtu = header.TCPMinimumSize + header.IPv4MinimumSize + e2e.MaxTCPOptionSize + maxPayload const packetOverheadFactor = 2 testCases := []struct { @@ -8553,7 +8473,7 @@ func TestTimestampSynCookies(t *testing.T) { c := context.NewWithOpts(t, context.Options{ EnableV4: true, EnableV6: true, - MTU: defaultMTU, + MTU: e2e.DefaultMTU, Clock: clock, }) defer c.Cleanup() @@ -8655,7 +8575,7 @@ func TestECNFlagsAccept(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() // Create EP and start listening. @@ -8677,7 +8597,7 @@ func TestECNFlagsAccept(t *testing.T) { // Do 3-way handshake. const maxPayload = 100 - c.PassiveConnect(maxPayload, -1 /* wndScale */, header.TCPSynOptions{MSS: defaultIPv4MSS, Flags: tc.flags}) + c.PassiveConnect(maxPayload, -1 /* wndScale */, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS, Flags: tc.flags}) // Try to accept the connection. we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) diff --git a/pkg/tcpip/transport/tcp/tcp_timestamp_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_timestamp_test.go similarity index 96% rename from pkg/tcpip/transport/tcp/tcp_timestamp_test.go rename to pkg/tcpip/transport/tcp/test/e2e/tcp_timestamp_test.go index a18f6b2d7..669f8f6d2 100644 --- a/pkg/tcpip/transport/tcp/tcp_timestamp_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_timestamp_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package tcp_test +package tcp_timestamp_test import ( "bytes" @@ -25,6 +25,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context" "gvisor.dev/gvisor/pkg/waiter" ) @@ -39,7 +40,7 @@ func createConnectedWithTimestampOption(c *context.Context) *context.RawEndpoint // an active connect and sets the TS Echo Reply fields correctly when the // SYN-ACK also indicates support for the TS option and provides a TSVal. func TestTimeStampEnabledConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() rep := createConnectedWithTimestampOption(c) @@ -128,14 +129,14 @@ func TestTimeStampEnabledConnect(t *testing.T) { // timestamp option is not enabled and future packets do not contain a // timestamp. func TestTimeStampDisabledConnect(t *testing.T) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() c.CreateConnectedWithOptionsNoDelay(header.TCPSynOptions{}) } func timeStampEnabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndSize uint16) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() if cookieEnabled { @@ -147,7 +148,7 @@ func timeStampEnabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndS t.Logf("Test w/ CookieEnabled = %v", cookieEnabled) tsVal := rand.Uint32() - c.AcceptWithOptionsNoDelay(wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS, TS: true, TSVal: tsVal}) + c.AcceptWithOptionsNoDelay(wndScale, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS, TS: true, TSVal: tsVal}) // Now send some data and validate that timestamp is echoed correctly in the ACK. data := []byte{1, 2, 3} @@ -198,7 +199,7 @@ func TestTimeStampEnabledAccept(t *testing.T) { } func timeStampDisabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndSize uint16) { - c := context.New(t, defaultMTU) + c := context.New(t, e2e.DefaultMTU) defer c.Cleanup() if cookieEnabled { @@ -209,7 +210,7 @@ func timeStampDisabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wnd } t.Logf("Test w/ CookieEnabled = %v", cookieEnabled) - c.AcceptWithOptionsNoDelay(wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS}) + c.AcceptWithOptionsNoDelay(wndScale, header.TCPSynOptions{MSS: e2e.DefaultIPv4MSS}) // Now send some data with the accepted connection endpoint and validate // that no timestamp option is sent in the TCP segment. @@ -261,7 +262,7 @@ func TestSendGreaterThanMTUWithOptions(t *testing.T) { defer c.Cleanup() createConnectedWithTimestampOption(c) - testBrokenUpWrite(t, c, maxPayload) + e2e.CheckBrokenUpWrite(t, c, maxPayload) } func TestSegmentNotDroppedWhenTimestampMissing(t *testing.T) {