mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Refactor tcp_tests to separate individual tests.
This change should reduce the run time of the tcp_test target as well as allow us to add leakchecking code to each test individually rather than create standalone main_test.go file. It also cleans up the BUILD file in the tcp directory so that the only tests in the BUILD file are the whitebox tests and blackbox tests are now segregated to a separate directory. PiperOrigin-RevId: 424225303
This commit is contained in:
committed by
gVisor bot
parent
e3c34d68d3
commit
d3cce99370
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
+29
-132
@@ -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.
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -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) {
|
||||
@@ -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"
|
||||
+1
-1
@@ -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"
|
||||
+3
-2
@@ -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 */)
|
||||
|
||||
+44
-83
@@ -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{
|
||||
+36
-52
@@ -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)
|
||||
+128
-208
File diff suppressed because it is too large
Load Diff
+9
-8
@@ -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) {
|
||||
Reference in New Issue
Block a user