mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Move stack.fakeClock into a separate package
PiperOrigin-RevId: 333138701
This commit is contained in:
committed by
gVisor bot
parent
13a9a622e1
commit
6e5ea605f4
@@ -0,0 +1,24 @@
|
||||
load("//tools:defs.bzl", "go_library", "go_test")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
go_library(
|
||||
name = "faketime",
|
||||
srcs = ["faketime.go"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/tcpip",
|
||||
"@com_github_dpjacques_clockwork//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "faketime_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"faketime_test.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/tcpip/faketime",
|
||||
],
|
||||
)
|
||||
@@ -12,7 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package stack
|
||||
// Package faketime provides a fake clock that implements tcpip.Clock interface.
|
||||
package faketime
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
@@ -23,7 +24,9 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
type fakeClock struct {
|
||||
// ManualClock implements tcpip.Clock and only advances manually with Advance
|
||||
// method.
|
||||
type ManualClock struct {
|
||||
clock clockwork.FakeClock
|
||||
|
||||
// mu protects the fields below.
|
||||
@@ -39,34 +42,35 @@ type fakeClock struct {
|
||||
waitGroups map[time.Time]*sync.WaitGroup
|
||||
}
|
||||
|
||||
func newFakeClock() *fakeClock {
|
||||
return &fakeClock{
|
||||
// NewManualClock creates a new ManualClock instance.
|
||||
func NewManualClock() *ManualClock {
|
||||
return &ManualClock{
|
||||
clock: clockwork.NewFakeClock(),
|
||||
times: &timeHeap{},
|
||||
waitGroups: make(map[time.Time]*sync.WaitGroup),
|
||||
}
|
||||
}
|
||||
|
||||
var _ tcpip.Clock = (*fakeClock)(nil)
|
||||
var _ tcpip.Clock = (*ManualClock)(nil)
|
||||
|
||||
// NowNanoseconds implements tcpip.Clock.NowNanoseconds.
|
||||
func (fc *fakeClock) NowNanoseconds() int64 {
|
||||
return fc.clock.Now().UnixNano()
|
||||
func (mc *ManualClock) NowNanoseconds() int64 {
|
||||
return mc.clock.Now().UnixNano()
|
||||
}
|
||||
|
||||
// NowMonotonic implements tcpip.Clock.NowMonotonic.
|
||||
func (fc *fakeClock) NowMonotonic() int64 {
|
||||
return fc.NowNanoseconds()
|
||||
func (mc *ManualClock) NowMonotonic() int64 {
|
||||
return mc.NowNanoseconds()
|
||||
}
|
||||
|
||||
// AfterFunc implements tcpip.Clock.AfterFunc.
|
||||
func (fc *fakeClock) AfterFunc(d time.Duration, f func()) tcpip.Timer {
|
||||
until := fc.clock.Now().Add(d)
|
||||
wg := fc.addWait(until)
|
||||
return &fakeTimer{
|
||||
clock: fc,
|
||||
func (mc *ManualClock) AfterFunc(d time.Duration, f func()) tcpip.Timer {
|
||||
until := mc.clock.Now().Add(d)
|
||||
wg := mc.addWait(until)
|
||||
return &manualTimer{
|
||||
clock: mc,
|
||||
until: until,
|
||||
timer: fc.clock.AfterFunc(d, func() {
|
||||
timer: mc.clock.AfterFunc(d, func() {
|
||||
defer wg.Done()
|
||||
f()
|
||||
}),
|
||||
@@ -75,110 +79,113 @@ func (fc *fakeClock) AfterFunc(d time.Duration, f func()) tcpip.Timer {
|
||||
|
||||
// addWait adds an additional wait to the WaitGroup for parallel execution of
|
||||
// all work scheduled for t. Returns a reference to the WaitGroup modified.
|
||||
func (fc *fakeClock) addWait(t time.Time) *sync.WaitGroup {
|
||||
fc.mu.RLock()
|
||||
wg, ok := fc.waitGroups[t]
|
||||
fc.mu.RUnlock()
|
||||
func (mc *ManualClock) addWait(t time.Time) *sync.WaitGroup {
|
||||
mc.mu.RLock()
|
||||
wg, ok := mc.waitGroups[t]
|
||||
mc.mu.RUnlock()
|
||||
|
||||
if ok {
|
||||
wg.Add(1)
|
||||
return wg
|
||||
}
|
||||
|
||||
fc.mu.Lock()
|
||||
heap.Push(fc.times, t)
|
||||
fc.mu.Unlock()
|
||||
mc.mu.Lock()
|
||||
heap.Push(mc.times, t)
|
||||
mc.mu.Unlock()
|
||||
|
||||
wg = &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
fc.mu.Lock()
|
||||
fc.waitGroups[t] = wg
|
||||
fc.mu.Unlock()
|
||||
mc.mu.Lock()
|
||||
mc.waitGroups[t] = wg
|
||||
mc.mu.Unlock()
|
||||
|
||||
return wg
|
||||
}
|
||||
|
||||
// removeWait removes a wait from the WaitGroup for parallel execution of all
|
||||
// work scheduled for t.
|
||||
func (fc *fakeClock) removeWait(t time.Time) {
|
||||
fc.mu.RLock()
|
||||
defer fc.mu.RUnlock()
|
||||
func (mc *ManualClock) removeWait(t time.Time) {
|
||||
mc.mu.RLock()
|
||||
defer mc.mu.RUnlock()
|
||||
|
||||
wg := fc.waitGroups[t]
|
||||
wg := mc.waitGroups[t]
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
// advance executes all work that have been scheduled to execute within d from
|
||||
// the current fake time. Blocks until all work has completed execution.
|
||||
func (fc *fakeClock) advance(d time.Duration) {
|
||||
// Advance executes all work that have been scheduled to execute within d from
|
||||
// the current time. Blocks until all work has completed execution.
|
||||
func (mc *ManualClock) Advance(d time.Duration) {
|
||||
// Block until all the work is done
|
||||
until := fc.clock.Now().Add(d)
|
||||
until := mc.clock.Now().Add(d)
|
||||
for {
|
||||
fc.mu.Lock()
|
||||
if fc.times.Len() == 0 {
|
||||
fc.mu.Unlock()
|
||||
return
|
||||
mc.mu.Lock()
|
||||
if mc.times.Len() == 0 {
|
||||
mc.mu.Unlock()
|
||||
break
|
||||
}
|
||||
|
||||
t := heap.Pop(fc.times).(time.Time)
|
||||
t := heap.Pop(mc.times).(time.Time)
|
||||
if t.After(until) {
|
||||
// No work to do
|
||||
heap.Push(fc.times, t)
|
||||
fc.mu.Unlock()
|
||||
return
|
||||
heap.Push(mc.times, t)
|
||||
mc.mu.Unlock()
|
||||
break
|
||||
}
|
||||
fc.mu.Unlock()
|
||||
mc.mu.Unlock()
|
||||
|
||||
diff := t.Sub(fc.clock.Now())
|
||||
fc.clock.Advance(diff)
|
||||
diff := t.Sub(mc.clock.Now())
|
||||
mc.clock.Advance(diff)
|
||||
|
||||
fc.mu.RLock()
|
||||
wg := fc.waitGroups[t]
|
||||
fc.mu.RUnlock()
|
||||
mc.mu.RLock()
|
||||
wg := mc.waitGroups[t]
|
||||
mc.mu.RUnlock()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
fc.mu.Lock()
|
||||
delete(fc.waitGroups, t)
|
||||
fc.mu.Unlock()
|
||||
mc.mu.Lock()
|
||||
delete(mc.waitGroups, t)
|
||||
mc.mu.Unlock()
|
||||
}
|
||||
if now := mc.clock.Now(); until.After(now) {
|
||||
mc.clock.Advance(until.Sub(now))
|
||||
}
|
||||
}
|
||||
|
||||
type fakeTimer struct {
|
||||
clock *fakeClock
|
||||
type manualTimer struct {
|
||||
clock *ManualClock
|
||||
timer clockwork.Timer
|
||||
|
||||
mu sync.RWMutex
|
||||
until time.Time
|
||||
}
|
||||
|
||||
var _ tcpip.Timer = (*fakeTimer)(nil)
|
||||
var _ tcpip.Timer = (*manualTimer)(nil)
|
||||
|
||||
// Reset implements tcpip.Timer.Reset.
|
||||
func (ft *fakeTimer) Reset(d time.Duration) {
|
||||
if !ft.timer.Reset(d) {
|
||||
func (t *manualTimer) Reset(d time.Duration) {
|
||||
if !t.timer.Reset(d) {
|
||||
return
|
||||
}
|
||||
|
||||
ft.mu.Lock()
|
||||
defer ft.mu.Unlock()
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
ft.clock.removeWait(ft.until)
|
||||
ft.until = ft.clock.clock.Now().Add(d)
|
||||
ft.clock.addWait(ft.until)
|
||||
t.clock.removeWait(t.until)
|
||||
t.until = t.clock.clock.Now().Add(d)
|
||||
t.clock.addWait(t.until)
|
||||
}
|
||||
|
||||
// Stop implements tcpip.Timer.Stop.
|
||||
func (ft *fakeTimer) Stop() bool {
|
||||
if !ft.timer.Stop() {
|
||||
func (t *manualTimer) Stop() bool {
|
||||
if !t.timer.Stop() {
|
||||
return false
|
||||
}
|
||||
|
||||
ft.mu.RLock()
|
||||
defer ft.mu.RUnlock()
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
|
||||
ft.clock.removeWait(ft.until)
|
||||
t.clock.removeWait(t.until)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package faketime_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip/faketime"
|
||||
)
|
||||
|
||||
func TestManualClockAdvance(t *testing.T) {
|
||||
const timeout = time.Millisecond
|
||||
clock := faketime.NewManualClock()
|
||||
start := clock.NowMonotonic()
|
||||
clock.Advance(timeout)
|
||||
if got, want := time.Duration(clock.NowMonotonic()-start)*time.Nanosecond, timeout; got != want {
|
||||
t.Errorf("got = %d, want = %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManualClockAfterFunc(t *testing.T) {
|
||||
const (
|
||||
timeout1 = time.Millisecond // timeout for counter1
|
||||
timeout2 = 2 * time.Millisecond // timeout for counter2
|
||||
)
|
||||
tests := []struct {
|
||||
name string
|
||||
advance time.Duration
|
||||
wantCounter1 int
|
||||
wantCounter2 int
|
||||
}{
|
||||
{
|
||||
name: "before timeout1",
|
||||
advance: timeout1 - 1,
|
||||
wantCounter1: 0,
|
||||
wantCounter2: 0,
|
||||
},
|
||||
{
|
||||
name: "timeout1",
|
||||
advance: timeout1,
|
||||
wantCounter1: 1,
|
||||
wantCounter2: 0,
|
||||
},
|
||||
{
|
||||
name: "timeout2",
|
||||
advance: timeout2,
|
||||
wantCounter1: 1,
|
||||
wantCounter2: 1,
|
||||
},
|
||||
{
|
||||
name: "after timeout2",
|
||||
advance: timeout2 + 1,
|
||||
wantCounter1: 1,
|
||||
wantCounter2: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
clock := faketime.NewManualClock()
|
||||
counter1 := 0
|
||||
counter2 := 0
|
||||
clock.AfterFunc(timeout1, func() {
|
||||
counter1++
|
||||
})
|
||||
clock.AfterFunc(timeout2, func() {
|
||||
counter2++
|
||||
})
|
||||
start := clock.NowMonotonic()
|
||||
clock.Advance(test.advance)
|
||||
if got, want := counter1, test.wantCounter1; got != want {
|
||||
t.Errorf("got counter1 = %d, want = %d", got, want)
|
||||
}
|
||||
if got, want := counter2, test.wantCounter2; got != want {
|
||||
t.Errorf("got counter2 = %d, want = %d", got, want)
|
||||
}
|
||||
if got, want := time.Duration(clock.NowMonotonic()-start)*time.Nanosecond, test.advance; got != want {
|
||||
t.Errorf("got elapsed = %d, want = %d", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,6 @@ go_test(
|
||||
name = "stack_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"fake_time_test.go",
|
||||
"forwarder_test.go",
|
||||
"linkaddrcache_test.go",
|
||||
"neighbor_cache_test.go",
|
||||
@@ -152,8 +151,8 @@ go_test(
|
||||
"//pkg/sync",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/faketime",
|
||||
"//pkg/tcpip/header",
|
||||
"@com_github_dpjacques_clockwork//:go_default_library",
|
||||
"@com_github_google_go_cmp//cmp:go_default_library",
|
||||
"@com_github_google_go_cmp//cmp/cmpopts:go_default_library",
|
||||
],
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"gvisor.dev/gvisor/pkg/sleep"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/faketime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -239,7 +240,7 @@ type entryEvent struct {
|
||||
func TestNeighborCacheGetConfig(t *testing.T) {
|
||||
nudDisp := testNUDDispatcher{}
|
||||
c := DefaultNUDConfigurations()
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, c, clock)
|
||||
|
||||
if got, want := neigh.config(), c; got != want {
|
||||
@@ -257,7 +258,7 @@ func TestNeighborCacheGetConfig(t *testing.T) {
|
||||
func TestNeighborCacheSetConfig(t *testing.T) {
|
||||
nudDisp := testNUDDispatcher{}
|
||||
c := DefaultNUDConfigurations()
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, c, clock)
|
||||
|
||||
c.MinRandomFactor = 1
|
||||
@@ -279,7 +280,7 @@ func TestNeighborCacheSetConfig(t *testing.T) {
|
||||
func TestNeighborCacheEntry(t *testing.T) {
|
||||
c := DefaultNUDConfigurations()
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, c, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -298,7 +299,7 @@ func TestNeighborCacheEntry(t *testing.T) {
|
||||
t.Errorf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -339,7 +340,7 @@ func TestNeighborCacheRemoveEntry(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -358,7 +359,7 @@ func TestNeighborCacheRemoveEntry(t *testing.T) {
|
||||
t.Errorf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -409,7 +410,7 @@ func TestNeighborCacheRemoveEntry(t *testing.T) {
|
||||
}
|
||||
|
||||
type testContext struct {
|
||||
clock *fakeClock
|
||||
clock *faketime.ManualClock
|
||||
neigh *neighborCache
|
||||
store *testEntryStore
|
||||
linkRes *testNeighborResolver
|
||||
@@ -418,7 +419,7 @@ type testContext struct {
|
||||
|
||||
func newTestContext(c NUDConfigurations) testContext {
|
||||
nudDisp := &testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(nudDisp, c, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -454,7 +455,7 @@ func (c *testContext) overflowCache(opts overflowOptions) error {
|
||||
if _, _, err := c.neigh.entry(entry.Addr, entry.LocalAddr, c.linkRes, nil); err != tcpip.ErrWouldBlock {
|
||||
return fmt.Errorf("got c.neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
c.clock.advance(c.neigh.config().RetransmitTimer)
|
||||
c.clock.Advance(c.neigh.config().RetransmitTimer)
|
||||
|
||||
var wantEvents []testEntryEventInfo
|
||||
|
||||
@@ -567,7 +568,7 @@ func TestNeighborCacheRemoveEntryThenOverflow(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got c.neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
c.clock.advance(c.neigh.config().RetransmitTimer)
|
||||
c.clock.Advance(c.neigh.config().RetransmitTimer)
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
EventType: entryTestAdded,
|
||||
@@ -803,7 +804,7 @@ func TestNeighborCacheOverwriteWithStaticEntryThenOverflow(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got c.neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
c.clock.advance(typicalLatency)
|
||||
c.clock.Advance(typicalLatency)
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
EventType: entryTestAdded,
|
||||
@@ -876,7 +877,7 @@ func TestNeighborCacheNotifiesWaker(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -902,7 +903,7 @@ func TestNeighborCacheNotifiesWaker(t *testing.T) {
|
||||
if doneCh == nil {
|
||||
t.Fatalf("expected done channel from neigh.entry(%s, %s, _, _)", entry.Addr, entry.LocalAddr)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
|
||||
select {
|
||||
case <-doneCh:
|
||||
@@ -944,7 +945,7 @@ func TestNeighborCacheRemoveWaker(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -974,7 +975,7 @@ func TestNeighborCacheRemoveWaker(t *testing.T) {
|
||||
// Remove the waker before the neighbor cache has the opportunity to send a
|
||||
// notification.
|
||||
neigh.removeWaker(entry.Addr, &w)
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
|
||||
select {
|
||||
case <-doneCh:
|
||||
@@ -1073,7 +1074,7 @@ func TestNeighborCacheClear(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -1092,7 +1093,7 @@ func TestNeighborCacheClear(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -1188,7 +1189,7 @@ func TestNeighborCacheClearThenOverflow(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got c.neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
c.clock.advance(typicalLatency)
|
||||
c.clock.Advance(typicalLatency)
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
EventType: entryTestAdded,
|
||||
@@ -1249,7 +1250,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
|
||||
config.MaxRandomFactor = 1
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -1277,7 +1278,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
select {
|
||||
case <-doneCh:
|
||||
default:
|
||||
@@ -1325,7 +1326,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Errorf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
select {
|
||||
case <-doneCh:
|
||||
default:
|
||||
@@ -1412,7 +1413,7 @@ func TestNeighborCacheConcurrent(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -1440,7 +1441,7 @@ func TestNeighborCacheConcurrent(t *testing.T) {
|
||||
wg.Wait()
|
||||
|
||||
// Process all the requests for a single entry concurrently
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
}
|
||||
|
||||
// All goroutines add in the same order and add more values than can fit in
|
||||
@@ -1472,7 +1473,7 @@ func TestNeighborCacheReplace(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -1491,7 +1492,7 @@ func TestNeighborCacheReplace(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
select {
|
||||
case <-doneCh:
|
||||
default:
|
||||
@@ -1541,7 +1542,7 @@ func TestNeighborCacheReplace(t *testing.T) {
|
||||
if err != tcpip.ErrWouldBlock {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(config.DelayFirstProbeTime + typicalLatency)
|
||||
clock.Advance(config.DelayFirstProbeTime + typicalLatency)
|
||||
select {
|
||||
case <-doneCh:
|
||||
default:
|
||||
@@ -1552,7 +1553,7 @@ func TestNeighborCacheReplace(t *testing.T) {
|
||||
// Verify the entry's new link address
|
||||
{
|
||||
e, _, err := neigh.entry(entry.Addr, entry.LocalAddr, linkRes, nil)
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error from neigh.entry(%s, %s, _, nil): %s", entry.Addr, entry.LocalAddr, err)
|
||||
}
|
||||
@@ -1572,7 +1573,7 @@ func TestNeighborCacheResolutionFailed(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
|
||||
nudDisp := testNUDDispatcher{}
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(&nudDisp, config, clock)
|
||||
store := newTestEntryStore()
|
||||
|
||||
@@ -1595,7 +1596,7 @@ func TestNeighborCacheResolutionFailed(t *testing.T) {
|
||||
if _, _, err := neigh.entry(entry.Addr, entry.LocalAddr, linkRes, nil); err != tcpip.ErrWouldBlock {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
clock.advance(typicalLatency)
|
||||
clock.Advance(typicalLatency)
|
||||
got, _, err := neigh.entry(entry.Addr, entry.LocalAddr, linkRes, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error from neigh.entry(%s, %s, _, nil): %s", entry.Addr, entry.LocalAddr, err)
|
||||
@@ -1618,7 +1619,7 @@ func TestNeighborCacheResolutionFailed(t *testing.T) {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
waitFor := config.DelayFirstProbeTime + typicalLatency*time.Duration(config.MaxMulticastProbes)
|
||||
clock.advance(waitFor)
|
||||
clock.Advance(waitFor)
|
||||
if _, _, err := neigh.entry(entry.Addr, entry.LocalAddr, linkRes, nil); err != tcpip.ErrNoLinkAddress {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrNoLinkAddress)
|
||||
}
|
||||
@@ -1636,7 +1637,7 @@ func TestNeighborCacheResolutionTimeout(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
config.RetransmitTimer = time.Millisecond // small enough to cause timeout
|
||||
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(nil, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
@@ -1654,7 +1655,7 @@ func TestNeighborCacheResolutionTimeout(t *testing.T) {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrWouldBlock)
|
||||
}
|
||||
waitFor := config.RetransmitTimer * time.Duration(config.MaxMulticastProbes)
|
||||
clock.advance(waitFor)
|
||||
clock.Advance(waitFor)
|
||||
if _, _, err := neigh.entry(entry.Addr, entry.LocalAddr, linkRes, nil); err != tcpip.ErrNoLinkAddress {
|
||||
t.Fatalf("got neigh.entry(%s, %s, _, nil) = %v, want = %s", entry.Addr, entry.LocalAddr, err, tcpip.ErrNoLinkAddress)
|
||||
}
|
||||
@@ -1664,7 +1665,7 @@ func TestNeighborCacheResolutionTimeout(t *testing.T) {
|
||||
// resolved immediately and don't send resolution requests.
|
||||
func TestNeighborCacheStaticResolution(t *testing.T) {
|
||||
config := DefaultNUDConfigurations()
|
||||
clock := newFakeClock()
|
||||
clock := faketime.NewManualClock()
|
||||
neigh := newTestNeighborCache(nil, config, clock)
|
||||
store := newTestEntryStore()
|
||||
linkRes := &testNeighborResolver{
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"gvisor.dev/gvisor/pkg/sleep"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/faketime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -221,8 +222,8 @@ func (r *entryTestLinkResolver) LinkAddressProtocol() tcpip.NetworkProtocolNumbe
|
||||
return entryTestNetNumber
|
||||
}
|
||||
|
||||
func entryTestSetup(c NUDConfigurations) (*neighborEntry, *testNUDDispatcher, *entryTestLinkResolver, *fakeClock) {
|
||||
clock := newFakeClock()
|
||||
func entryTestSetup(c NUDConfigurations) (*neighborEntry, *testNUDDispatcher, *entryTestLinkResolver, *faketime.ManualClock) {
|
||||
clock := faketime.NewManualClock()
|
||||
disp := testNUDDispatcher{}
|
||||
nic := NIC{
|
||||
id: entryTestNICID,
|
||||
@@ -267,7 +268,7 @@ func TestEntryInitiallyUnknown(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.RetransmitTimer)
|
||||
clock.Advance(c.RetransmitTimer)
|
||||
|
||||
// No probes should have been sent.
|
||||
linkRes.mu.Lock()
|
||||
@@ -300,7 +301,7 @@ func TestEntryUnknownToUnknownWhenConfirmationWithUnknownAddress(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(time.Hour)
|
||||
clock.Advance(time.Hour)
|
||||
|
||||
// No probes should have been sent.
|
||||
linkRes.mu.Lock()
|
||||
@@ -410,7 +411,7 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
|
||||
updatedAt := e.neigh.UpdatedAt
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.RetransmitTimer)
|
||||
clock.Advance(c.RetransmitTimer)
|
||||
|
||||
// UpdatedAt should remain the same during address resolution.
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
@@ -439,7 +440,7 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.RetransmitTimer)
|
||||
clock.Advance(c.RetransmitTimer)
|
||||
|
||||
// UpdatedAt should change after failing address resolution. Timing out after
|
||||
// sending the last probe transitions the entry to Failed.
|
||||
@@ -459,7 +460,7 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
clock.advance(c.RetransmitTimer)
|
||||
clock.Advance(c.RetransmitTimer)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -748,7 +749,7 @@ func TestEntryIncompleteToFailed(t *testing.T) {
|
||||
e.mu.Unlock()
|
||||
|
||||
waitFor := c.RetransmitTimer * time.Duration(c.MaxMulticastProbes)
|
||||
clock.advance(waitFor)
|
||||
clock.Advance(waitFor)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The Incomplete-to-Incomplete state transition is tested here by
|
||||
@@ -983,7 +984,7 @@ func TestEntryReachableToStaleWhenTimeout(t *testing.T) {
|
||||
t.Fatalf("link address resolver probes mismatch (-got, +want):\n%s", diff)
|
||||
}
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -1612,7 +1613,7 @@ func TestEntryDelayToReachableWhenUpperLevelConfirmation(t *testing.T) {
|
||||
t.Fatalf("link address resolver probes mismatch (-got, +want):\n%s", diff)
|
||||
}
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -1706,7 +1707,7 @@ func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
|
||||
t.Fatalf("link address resolver probes mismatch (-got, +want):\n%s", diff)
|
||||
}
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -1989,7 +1990,7 @@ func TestEntryDelayToProbe(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2069,7 +2070,7 @@ func TestEntryProbeToStaleWhenProbeWithDifferentAddress(t *testing.T) {
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2166,7 +2167,7 @@ func TestEntryProbeToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2267,7 +2268,7 @@ func TestEntryStaysProbeWhenOverrideConfirmationWithSameAddress(t *testing.T) {
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2364,7 +2365,7 @@ func TestEntryUnknownToStaleToProbeToReachable(t *testing.T) {
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// Probe caused by the Delay-to-Probe transition
|
||||
@@ -2398,7 +2399,7 @@ func TestEntryUnknownToStaleToProbeToReachable(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -2463,7 +2464,7 @@ func TestEntryProbeToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2503,7 +2504,7 @@ func TestEntryProbeToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -2575,7 +2576,7 @@ func TestEntryProbeToReachableWhenSolicitedConfirmationWithSameAddress(t *testin
|
||||
e.handlePacketQueuedLocked()
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.DelayFirstProbeTime)
|
||||
clock.Advance(c.DelayFirstProbeTime)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2612,7 +2613,7 @@ func TestEntryProbeToReachableWhenSolicitedConfirmationWithSameAddress(t *testin
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
clock.advance(c.BaseReachableTime)
|
||||
clock.Advance(c.BaseReachableTime)
|
||||
|
||||
wantEvents := []testEntryEventInfo{
|
||||
{
|
||||
@@ -2682,7 +2683,7 @@ func TestEntryProbeToFailed(t *testing.T) {
|
||||
e.mu.Unlock()
|
||||
|
||||
waitFor := c.DelayFirstProbeTime + c.RetransmitTimer*time.Duration(c.MaxUnicastProbes)
|
||||
clock.advance(waitFor)
|
||||
clock.Advance(waitFor)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
@@ -2787,7 +2788,7 @@ func TestEntryFailedGetsDeleted(t *testing.T) {
|
||||
e.mu.Unlock()
|
||||
|
||||
waitFor := c.DelayFirstProbeTime + c.RetransmitTimer*time.Duration(c.MaxUnicastProbes) + c.UnreachableTime
|
||||
clock.advance(waitFor)
|
||||
clock.Advance(waitFor)
|
||||
|
||||
wantProbes := []entryTestProbeInfo{
|
||||
// The first probe is caused by the Unknown-to-Incomplete transition.
|
||||
|
||||
Reference in New Issue
Block a user