summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network
diff options
context:
space:
mode:
authorTamir Duberstein <tamird@google.com>2021-05-27 05:04:04 -0700
committergVisor bot <gvisor-bot@google.com>2021-05-27 05:06:04 -0700
commit2c1df1f445df67b7481e6ee3deee0007a576fefe (patch)
treebc4b4668610a3bb547f95446f74f01e1f6bdd092 /pkg/tcpip/network
parent93d98b874b0687f53a508f3733c3fa8d687091cb (diff)
Use fake clocks in all tests
...except TCP tests and NDP tests that mutate globals. These will be undertaken later. Updates #5940. PiperOrigin-RevId: 376145608
Diffstat (limited to 'pkg/tcpip/network')
-rw-r--r--pkg/tcpip/network/arp/BUILD2
-rw-r--r--pkg/tcpip/network/arp/arp_test.go129
-rw-r--r--pkg/tcpip/network/ipv4/ipv4_test.go11
-rw-r--r--pkg/tcpip/network/ipv6/icmp_test.go30
-rw-r--r--pkg/tcpip/network/ipv6/ndp_test.go26
5 files changed, 93 insertions, 105 deletions
diff --git a/pkg/tcpip/network/arp/BUILD b/pkg/tcpip/network/arp/BUILD
index a72eb1aad..6fa1aee18 100644
--- a/pkg/tcpip/network/arp/BUILD
+++ b/pkg/tcpip/network/arp/BUILD
@@ -28,13 +28,13 @@ go_test(
":arp",
"//pkg/tcpip",
"//pkg/tcpip/buffer",
+ "//pkg/tcpip/faketime",
"//pkg/tcpip/header",
"//pkg/tcpip/link/channel",
"//pkg/tcpip/link/sniffer",
"//pkg/tcpip/network/ipv4",
"//pkg/tcpip/stack",
"//pkg/tcpip/testutil",
- "//pkg/tcpip/transport/icmp",
"@com_github_google_go_cmp//cmp:go_default_library",
"@com_github_google_go_cmp//cmp/cmpopts:go_default_library",
],
diff --git a/pkg/tcpip/network/arp/arp_test.go b/pkg/tcpip/network/arp/arp_test.go
index 3ca78490f..5fcbfeaa2 100644
--- a/pkg/tcpip/network/arp/arp_test.go
+++ b/pkg/tcpip/network/arp/arp_test.go
@@ -15,15 +15,14 @@
package arp_test
import (
- "context"
"fmt"
"testing"
- "time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
+ "gvisor.dev/gvisor/pkg/tcpip/faketime"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
@@ -31,7 +30,6 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/testutil"
- "gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
)
const (
@@ -39,15 +37,6 @@ const (
stackLinkAddr = tcpip.LinkAddress("\x0a\x0a\x0b\x0b\x0c\x0c")
remoteLinkAddr = tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06")
-
- defaultChannelSize = 1
- defaultMTU = 65536
-
- // eventChanSize defines the size of event channels used by the neighbor
- // cache's event dispatcher. The size chosen here needs to be sufficient to
- // queue all the events received during tests before consumption.
- // If eventChanSize is too small, the tests may deadlock.
- eventChanSize = 32
)
var (
@@ -123,24 +112,6 @@ func (d *arpDispatcher) OnNeighborRemoved(nicID tcpip.NICID, entry stack.Neighbo
d.C <- e
}
-func (d *arpDispatcher) waitForEvent(ctx context.Context, want eventInfo) error {
- select {
- case got := <-d.C:
- if diff := cmp.Diff(want, got, cmp.AllowUnexported(got), cmpopts.IgnoreFields(stack.NeighborEntry{}, "UpdatedAt")); diff != "" {
- return fmt.Errorf("got invalid event (-want +got):\n%s", diff)
- }
- case <-ctx.Done():
- return fmt.Errorf("%s for %s", ctx.Err(), want)
- }
- return nil
-}
-
-func (d *arpDispatcher) waitForEventWithTimeout(want eventInfo, timeout time.Duration) error {
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
- defer cancel()
- return d.waitForEvent(ctx, want)
-}
-
func (d *arpDispatcher) nextEvent() (eventInfo, bool) {
select {
case event := <-d.C:
@@ -153,55 +124,45 @@ func (d *arpDispatcher) nextEvent() (eventInfo, bool) {
type testContext struct {
s *stack.Stack
linkEP *channel.Endpoint
- nudDisp *arpDispatcher
+ nudDisp arpDispatcher
}
-func newTestContext(t *testing.T) *testContext {
- c := stack.DefaultNUDConfigurations()
- // Transition from Reachable to Stale almost immediately to test if receiving
- // probes refreshes positive reachability.
- c.BaseReachableTime = time.Microsecond
-
- d := arpDispatcher{
- // Create an event channel large enough so the neighbor cache doesn't block
- // while dispatching events. Blocking could interfere with the timing of
- // NUD transitions.
- C: make(chan eventInfo, eventChanSize),
+func makeTestContext(t *testing.T, eventDepth int, packetDepth int) testContext {
+ t.Helper()
+
+ tc := testContext{
+ nudDisp: arpDispatcher{
+ C: make(chan eventInfo, eventDepth),
+ },
}
- s := stack.New(stack.Options{
- NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, arp.NewProtocol},
- TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol4},
- NUDConfigs: c,
- NUDDisp: &d,
+ tc.s = stack.New(stack.Options{
+ NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, arp.NewProtocol},
+ NUDDisp: &tc.nudDisp,
+ Clock: &faketime.NullClock{},
})
- ep := channel.New(defaultChannelSize, defaultMTU, stackLinkAddr)
- ep.LinkEPCapabilities |= stack.CapabilityResolutionRequired
-
- wep := stack.LinkEndpoint(ep)
+ tc.linkEP = channel.New(packetDepth, header.IPv4MinimumMTU, stackLinkAddr)
+ tc.linkEP.LinkEPCapabilities |= stack.CapabilityResolutionRequired
+ wep := stack.LinkEndpoint(tc.linkEP)
if testing.Verbose() {
- wep = sniffer.New(ep)
+ wep = sniffer.New(wep)
}
- if err := s.CreateNIC(nicID, wep); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
+ if err := tc.s.CreateNIC(nicID, wep); err != nil {
+ t.Fatalf("CreateNIC failed: %s", err)
}
- if err := s.AddAddress(nicID, ipv4.ProtocolNumber, stackAddr); err != nil {
- t.Fatalf("AddAddress for ipv4 failed: %v", err)
+ if err := tc.s.AddAddress(nicID, ipv4.ProtocolNumber, stackAddr); err != nil {
+ t.Fatalf("AddAddress for ipv4 failed: %s", err)
}
- s.SetRouteTable([]tcpip.Route{{
+ tc.s.SetRouteTable([]tcpip.Route{{
Destination: header.IPv4EmptySubnet,
NIC: nicID,
}})
- return &testContext{
- s: s,
- linkEP: ep,
- nudDisp: &d,
- }
+ return tc
}
func (c *testContext) cleanup() {
@@ -209,7 +170,7 @@ func (c *testContext) cleanup() {
}
func TestMalformedPacket(t *testing.T) {
- c := newTestContext(t)
+ c := makeTestContext(t, 0, 0)
defer c.cleanup()
v := make(buffer.View, header.ARPSize)
@@ -228,7 +189,7 @@ func TestMalformedPacket(t *testing.T) {
}
func TestDisabledEndpoint(t *testing.T) {
- c := newTestContext(t)
+ c := makeTestContext(t, 0, 0)
defer c.cleanup()
ep, err := c.s.GetNetworkEndpoint(nicID, header.ARPProtocolNumber)
@@ -253,7 +214,7 @@ func TestDisabledEndpoint(t *testing.T) {
}
func TestDirectReply(t *testing.T) {
- c := newTestContext(t)
+ c := makeTestContext(t, 0, 0)
defer c.cleanup()
const senderMAC = "\x01\x02\x03\x04\x05\x06"
@@ -284,7 +245,7 @@ func TestDirectReply(t *testing.T) {
}
func TestDirectRequest(t *testing.T) {
- c := newTestContext(t)
+ c := makeTestContext(t, 1, 1)
defer c.cleanup()
tests := []struct {
@@ -391,17 +352,21 @@ func TestDirectRequest(t *testing.T) {
}
// Verify the sender was saved in the neighbor cache.
- wantEvent := eventInfo{
- eventType: entryAdded,
- nicID: nicID,
- entry: stack.NeighborEntry{
- Addr: test.senderAddr,
- LinkAddr: test.senderLinkAddr,
- State: stack.Stale,
- },
- }
- if err := c.nudDisp.waitForEventWithTimeout(wantEvent, time.Second); err != nil {
- t.Fatal(err)
+ if got, ok := c.nudDisp.nextEvent(); ok {
+ want := eventInfo{
+ eventType: entryAdded,
+ nicID: nicID,
+ entry: stack.NeighborEntry{
+ Addr: test.senderAddr,
+ LinkAddr: test.senderLinkAddr,
+ State: stack.Stale,
+ },
+ }
+ if diff := cmp.Diff(want, got, cmp.AllowUnexported(eventInfo{}), cmpopts.IgnoreFields(stack.NeighborEntry{}, "UpdatedAt")); diff != "" {
+ t.Errorf("got invalid event (-want +got):\n%s", diff)
+ }
+ } else {
+ t.Fatal("event didn't arrive")
}
neighbors, err := c.s.Neighbors(nicID, ipv4.ProtocolNumber)
@@ -589,7 +554,7 @@ func TestLinkAddressRequest(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocol, ipv4.NewProtocol},
})
- linkEP := channel.New(defaultChannelSize, defaultMTU, stackLinkAddr)
+ linkEP := channel.New(1, header.IPv4MinimumMTU, stackLinkAddr)
if err := s.CreateNIC(nicID, &testLinkEndpoint{LinkEndpoint: linkEP, writeErr: test.linkErr}); err != nil {
t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err)
}
@@ -663,15 +628,16 @@ func TestLinkAddressRequest(t *testing.T) {
}
func TestDADARPRequestPacket(t *testing.T) {
+ clock := faketime.NewManualClock()
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocolWithOptions(arp.Options{
DADConfigs: stack.DADConfigurations{
DupAddrDetectTransmits: 1,
- RetransmitTimer: time.Second,
},
}), ipv4.NewProtocol},
+ Clock: clock,
})
- e := channel.New(1, defaultMTU, stackLinkAddr)
+ e := channel.New(1, header.IPv4MinimumMTU, stackLinkAddr)
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err)
}
@@ -682,7 +648,8 @@ func TestDADARPRequestPacket(t *testing.T) {
t.Fatalf("got s.CheckDuplicateAddress(%d, %d, %s, _) = %d, want = %d", nicID, header.IPv4ProtocolNumber, remoteAddr, res, stack.DADStarting)
}
- pkt, ok := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ pkt, ok := e.Read()
if !ok {
t.Fatal("expected to send an ARP request")
}
diff --git a/pkg/tcpip/network/ipv4/ipv4_test.go b/pkg/tcpip/network/ipv4/ipv4_test.go
index 93d820a5b..0a1f02de0 100644
--- a/pkg/tcpip/network/ipv4/ipv4_test.go
+++ b/pkg/tcpip/network/ipv4/ipv4_test.go
@@ -16,7 +16,6 @@ package ipv4_test
import (
"bytes"
- "context"
"encoding/hex"
"fmt"
"io/ioutil"
@@ -3086,7 +3085,7 @@ func TestPacketQueing(t *testing.T) {
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
- p, ok := e.ReadContext(context.Background())
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -3129,7 +3128,7 @@ func TestPacketQueing(t *testing.T) {
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
- p, ok := e.ReadContext(context.Background())
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -3153,9 +3152,11 @@ func TestPacketQueing(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
e := channel.New(1, defaultMTU, host1NICLinkAddr)
e.LinkEPCapabilities |= stack.CapabilityResolutionRequired
+ clock := faketime.NewManualClock()
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocol, ipv4.NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
+ Clock: clock,
})
if err := s.CreateNIC(nicID, e); err != nil {
@@ -3178,7 +3179,8 @@ func TestPacketQueing(t *testing.T) {
// Wait for a ARP request since link address resolution should be
// performed.
{
- p, ok := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -3219,6 +3221,7 @@ func TestPacketQueing(t *testing.T) {
}
// Expect the response now that the link address has resolved.
+ clock.RunImmediatelyScheduledJobs()
test.checkResp(t, e)
// Since link resolution was already performed, it shouldn't be performed
diff --git a/pkg/tcpip/network/ipv6/icmp_test.go b/pkg/tcpip/network/ipv6/icmp_test.go
index d7b04554e..c2e9544c1 100644
--- a/pkg/tcpip/network/ipv6/icmp_test.go
+++ b/pkg/tcpip/network/ipv6/icmp_test.go
@@ -16,7 +16,6 @@ package ipv6
import (
"bytes"
- "context"
"net"
"reflect"
"strings"
@@ -26,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/checker"
+ "gvisor.dev/gvisor/pkg/tcpip/faketime"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
@@ -366,6 +366,8 @@ type testContext struct {
linkEP0 *channel.Endpoint
linkEP1 *channel.Endpoint
+
+ clock *faketime.ManualClock
}
type endpointWithResolutionCapability struct {
@@ -377,15 +379,19 @@ func (e endpointWithResolutionCapability) Capabilities() stack.LinkEndpointCapab
}
func newTestContext(t *testing.T) *testContext {
+ clock := faketime.NewManualClock()
c := &testContext{
s0: stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol6},
+ Clock: clock,
}),
s1: stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol6},
+ Clock: clock,
}),
+ clock: clock,
}
c.linkEP0 = channel.New(defaultChannelSize, defaultMTU, linkAddr0)
@@ -452,10 +458,14 @@ type routeArgs struct {
remoteLinkAddr tcpip.LinkAddress
}
-func routeICMPv6Packet(t *testing.T, args routeArgs, fn func(*testing.T, header.ICMPv6)) {
+func routeICMPv6Packet(t *testing.T, clock *faketime.ManualClock, args routeArgs, fn func(*testing.T, header.ICMPv6)) {
t.Helper()
- pi, _ := args.src.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ pi, ok := args.src.Read()
+ if !ok {
+ t.Fatal("packet didn't arrive")
+ }
{
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
@@ -528,7 +538,7 @@ func TestLinkResolution(t *testing.T) {
{src: c.linkEP0, dst: c.linkEP1, typ: header.ICMPv6NeighborSolicit, remoteLinkAddr: header.EthernetAddressFromMulticastIPv6Address(header.SolicitedNodeAddr(lladdr1))},
{src: c.linkEP1, dst: c.linkEP0, typ: header.ICMPv6NeighborAdvert},
} {
- routeICMPv6Packet(t, args, func(t *testing.T, icmpv6 header.ICMPv6) {
+ routeICMPv6Packet(t, c.clock, args, func(t *testing.T, icmpv6 header.ICMPv6) {
if got, want := tcpip.Address(icmpv6[8:][:16]), lladdr1; got != want {
t.Errorf("%d: got target = %s, want = %s", icmpv6.Type(), got, want)
}
@@ -539,7 +549,7 @@ func TestLinkResolution(t *testing.T) {
{src: c.linkEP0, dst: c.linkEP1, typ: header.ICMPv6EchoRequest},
{src: c.linkEP1, dst: c.linkEP0, typ: header.ICMPv6EchoReply},
} {
- routeICMPv6Packet(t, args, nil)
+ routeICMPv6Packet(t, c.clock, args, nil)
}
}
@@ -1320,7 +1330,7 @@ func TestPacketQueing(t *testing.T) {
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
- p, ok := e.ReadContext(context.Background())
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -1366,7 +1376,7 @@ func TestPacketQueing(t *testing.T) {
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
- p, ok := e.ReadContext(context.Background())
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -1391,9 +1401,11 @@ func TestPacketQueing(t *testing.T) {
e := channel.New(1, header.IPv6MinimumMTU, host1NICLinkAddr)
e.LinkEPCapabilities |= stack.CapabilityResolutionRequired
+ clock := faketime.NewManualClock()
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
+ Clock: clock,
})
if err := s.CreateNIC(nicID, e); err != nil {
@@ -1416,7 +1428,8 @@ func TestPacketQueing(t *testing.T) {
// Wait for a neighbor solicitation since link address resolution should
// be performed.
{
- p, ok := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ p, ok := e.Read()
if !ok {
t.Fatalf("timed out waiting for packet")
}
@@ -1470,6 +1483,7 @@ func TestPacketQueing(t *testing.T) {
}
// Expect the response now that the link address has resolved.
+ clock.RunImmediatelyScheduledJobs()
test.checkResp(t, e)
// Since link resolution was already performed, it shouldn't be performed
diff --git a/pkg/tcpip/network/ipv6/ndp_test.go b/pkg/tcpip/network/ipv6/ndp_test.go
index 0f24500e7..2c2416328 100644
--- a/pkg/tcpip/network/ipv6/ndp_test.go
+++ b/pkg/tcpip/network/ipv6/ndp_test.go
@@ -16,7 +16,6 @@ package ipv6
import (
"bytes"
- "context"
"math/rand"
"strings"
"testing"
@@ -400,8 +399,10 @@ func TestNeighborSolicitationResponse(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
+ clock := faketime.NewManualClock()
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{NewProtocol},
+ Clock: clock,
})
e := channel.New(1, 1280, nicLinkAddr)
e.LinkEPCapabilities |= stack.CapabilityResolutionRequired
@@ -471,7 +472,8 @@ func TestNeighborSolicitationResponse(t *testing.T) {
}
if test.performsLinkResolution {
- p, got := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ p, got := e.Read()
if !got {
t.Fatal("expected an NDP NS response")
}
@@ -526,7 +528,8 @@ func TestNeighborSolicitationResponse(t *testing.T) {
}))
}
- p, got := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ p, got := e.Read()
if !got {
t.Fatal("expected an NDP NA response")
}
@@ -850,12 +853,12 @@ func TestNDPValidation(t *testing.T) {
routerOnly := stats.RouterOnlyPacketsDroppedByHost
typStat := typ.statCounter(stats)
- icmp := header.ICMPv6(buffer.NewView(typ.size + len(typ.extraData)))
- copy(icmp[typ.size:], typ.extraData)
- icmp.SetType(typ.typ)
- icmp.SetCode(test.code)
- icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
- Header: icmp[:typ.size],
+ icmpH := header.ICMPv6(buffer.NewView(typ.size + len(typ.extraData)))
+ copy(icmpH[typ.size:], typ.extraData)
+ icmpH.SetType(typ.typ)
+ icmpH.SetCode(test.code)
+ icmpH.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmpH[:typ.size],
Src: lladdr0,
Dst: lladdr1,
PayloadCsum: header.Checksum(typ.extraData /* initial */, 0),
@@ -881,7 +884,7 @@ func TestNDPValidation(t *testing.T) {
t.FailNow()
}
- handleIPv6Payload(buffer.View(icmp), test.hopLimit, test.atomicFragment, ep)
+ handleIPv6Payload(buffer.View(icmpH), test.hopLimit, test.atomicFragment, ep)
// Rx count of the NDP packet should have increased.
if got := typStat.Value(); got != 1 {
@@ -1260,7 +1263,8 @@ func TestCheckDuplicateAddress(t *testing.T) {
snmc := header.SolicitedNodeAddr(lladdr0)
remoteLinkAddr := header.EthernetAddressFromMulticastIPv6Address(snmc)
checkDADMsg := func() {
- p, ok := e.ReadContext(context.Background())
+ clock.RunImmediatelyScheduledJobs()
+ p, ok := e.Read()
if !ok {
t.Fatalf("expected %d-th DAD message", dadPacketsSent)
}