Use opaque types to represent time

Introduce tcpip.MonotonicTime; replace int64 in tcpip.Clock method
returns with time.Time and MonotonicTime to improve type safety and
ensure that monotonic clock readings are never compared to wall clock
readings.

PiperOrigin-RevId: 375775907
This commit is contained in:
Tamir Duberstein
2021-05-25 13:00:29 -07:00
committed by gVisor bot
parent b8052176db
commit 4f2439fb0e
25 changed files with 474 additions and 331 deletions
+10 -9
View File
@@ -1553,22 +1553,23 @@ func (k *Kernel) SetSaveError(err error) {
var _ tcpip.Clock = (*Kernel)(nil)
// NowNanoseconds implements tcpip.Clock.NowNanoseconds.
func (k *Kernel) NowNanoseconds() int64 {
now, err := k.timekeeper.GetTime(sentrytime.Realtime)
// Now implements tcpip.Clock.NowNanoseconds.
func (k *Kernel) Now() time.Time {
nsec, err := k.timekeeper.GetTime(sentrytime.Realtime)
if err != nil {
panic("Kernel.NowNanoseconds: " + err.Error())
panic("timekeeper.GetTime(sentrytime.Realtime): " + err.Error())
}
return now
return time.Unix(0, nsec)
}
// NowMonotonic implements tcpip.Clock.NowMonotonic.
func (k *Kernel) NowMonotonic() int64 {
now, err := k.timekeeper.GetTime(sentrytime.Monotonic)
func (k *Kernel) NowMonotonic() tcpip.MonotonicTime {
nsec, err := k.timekeeper.GetTime(sentrytime.Monotonic)
if err != nil {
panic("Kernel.NowMonotonic: " + err.Error())
panic("timekeeper.GetTime(sentrytime.Monotonic): " + err.Error())
}
return now
var mt tcpip.MonotonicTime
return mt.Add(time.Duration(nsec) * time.Nanosecond)
}
// AfterFunc implements tcpip.Clock.AfterFunc.
+11 -10
View File
@@ -29,14 +29,14 @@ type NullClock struct{}
var _ tcpip.Clock = (*NullClock)(nil)
// NowNanoseconds implements tcpip.Clock.NowNanoseconds.
func (*NullClock) NowNanoseconds() int64 {
return 0
// Now implements tcpip.Clock.Now.
func (*NullClock) Now() time.Time {
return time.Time{}
}
// NowMonotonic implements tcpip.Clock.NowMonotonic.
func (*NullClock) NowMonotonic() int64 {
return 0
func (*NullClock) NowMonotonic() tcpip.MonotonicTime {
return tcpip.MonotonicTime{}
}
// AfterFunc implements tcpip.Clock.AfterFunc.
@@ -118,16 +118,17 @@ func NewManualClock() *ManualClock {
var _ tcpip.Clock = (*ManualClock)(nil)
// NowNanoseconds implements tcpip.Clock.NowNanoseconds.
func (mc *ManualClock) NowNanoseconds() int64 {
// Now implements tcpip.Clock.Now.
func (mc *ManualClock) Now() time.Time {
mc.mu.RLock()
defer mc.mu.RUnlock()
return mc.mu.now.UnixNano()
return mc.mu.now
}
// NowMonotonic implements tcpip.Clock.NowMonotonic.
func (mc *ManualClock) NowMonotonic() int64 {
return mc.NowNanoseconds()
func (mc *ManualClock) NowMonotonic() tcpip.MonotonicTime {
var mt tcpip.MonotonicTime
return mt.Add(mc.Now().Sub(time.Unix(0, 0)))
}
// AfterFunc implements tcpip.Clock.AfterFunc.
+2 -2
View File
@@ -26,7 +26,7 @@ func TestManualClockAdvance(t *testing.T) {
clock := faketime.NewManualClock()
start := clock.NowMonotonic()
clock.Advance(timeout)
if got, want := time.Duration(clock.NowMonotonic()-start)*time.Nanosecond, timeout; got != want {
if got, want := clock.NowMonotonic().Sub(start), timeout; got != want {
t.Errorf("got = %d, want = %d", got, want)
}
}
@@ -87,7 +87,7 @@ func TestManualClockAfterFunc(t *testing.T) {
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 {
if got, want := clock.NowMonotonic().Sub(start), test.advance; got != want {
t.Errorf("got elapsed = %d, want = %d", got, want)
}
})
+7 -3
View File
@@ -17,6 +17,7 @@ package header
import (
"encoding/binary"
"fmt"
"time"
"gvisor.dev/gvisor/pkg/tcpip"
)
@@ -813,9 +814,12 @@ const (
// ipv4TimestampTime provides the current time as specified in RFC 791.
func ipv4TimestampTime(clock tcpip.Clock) uint32 {
const millisecondsPerDay = 24 * 3600 * 1000
const nanoPerMilli = 1000000
return uint32((clock.NowNanoseconds() / nanoPerMilli) % millisecondsPerDay)
// Per RFC 791 page 21:
// The Timestamp is a right-justified, 32-bit timestamp in
// milliseconds since midnight UT.
now := clock.Now().UTC()
midnight := now.Truncate(24 * time.Hour)
return uint32(now.Sub(midnight).Milliseconds())
}
// IP Timestamp option fields.
+1 -1
View File
@@ -126,7 +126,7 @@ func (d *arpDispatcher) OnNeighborRemoved(nicID tcpip.NICID, entry stack.Neighbo
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{}, "UpdatedAtNanos")); diff != "" {
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():
@@ -251,7 +251,7 @@ func (f *Fragmentation) releaseReassemblersLocked() {
// The list is empty.
break
}
elapsed := time.Duration(now-r.creationTime) * time.Nanosecond
elapsed := now.Sub(r.createdAt)
if f.timeout > elapsed {
// If the oldest reassembler has not expired, schedule the release
// job so that this function is called back when it has expired.
@@ -35,21 +35,21 @@ type hole struct {
type reassembler struct {
reassemblerEntry
id FragmentID
memSize int
proto uint8
mu sync.Mutex
holes []hole
filled int
done bool
creationTime int64
pkt *stack.PacketBuffer
id FragmentID
memSize int
proto uint8
mu sync.Mutex
holes []hole
filled int
done bool
createdAt tcpip.MonotonicTime
pkt *stack.PacketBuffer
}
func newReassembler(id FragmentID, clock tcpip.Clock) *reassembler {
r := &reassembler{
id: id,
creationTime: clock.NowMonotonic(),
id: id,
createdAt: clock.NowMonotonic(),
}
r.holes = append(r.holes, hole{
first: 0,
@@ -611,7 +611,7 @@ func (g *GenericMulticastProtocolState) setDelayTimerForAddressRLocked(groupAddr
// If a timer for any address is already running, it is reset to the new
// random value only if the requested Maximum Response Delay is less than
// the remaining value of the running timer.
now := time.Unix(0 /* seconds */, g.opts.Clock.NowNanoseconds())
now := g.opts.Clock.Now()
if info.state == delayingMember {
if info.delayedReportJobFiresAt.IsZero() {
panic(fmt.Sprintf("delayed report unscheduled while in the delaying member state; group = %s", groupAddress))
+133 -133
View File
@@ -293,10 +293,10 @@ func addReachableEntryWithRemoved(nudDisp *testNUDDispatcher, clock *faketime.Ma
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: removedEntry.Addr,
LinkAddr: removedEntry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: removedEntry.Addr,
LinkAddr: removedEntry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
})
}
@@ -305,10 +305,10 @@ func addReachableEntryWithRemoved(nudDisp *testNUDDispatcher, clock *faketime.Ma
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAt: clock.Now(),
},
})
@@ -339,10 +339,10 @@ func addReachableEntryWithRemoved(nudDisp *testNUDDispatcher, clock *faketime.Ma
EventType: entryTestChanged,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -411,10 +411,10 @@ func TestNeighborCacheRemoveEntry(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -492,12 +492,12 @@ func (c *testContext) overflowCache(opts overflowOptions) error {
if !ok {
return fmt.Errorf("got c.linkRes.entries.entry(%d) = _, false, want = true", i)
}
durationReachableNanos := int64(c.linkRes.entries.size()-i-1) * typicalLatency.Nanoseconds()
durationReachableNanos := time.Duration(c.linkRes.entries.size()-i-1) * typicalLatency
wantEntry := NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: c.clock.NowNanoseconds() - durationReachableNanos,
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: c.clock.Now().Add(-durationReachableNanos),
}
wantUnorderedEntries = append(wantUnorderedEntries, wantEntry)
}
@@ -563,10 +563,10 @@ func TestNeighborCacheRemoveEntryThenOverflow(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -608,10 +608,10 @@ func TestNeighborCacheDuplicateStaticEntryWithSameLinkAddress(t *testing.T) {
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -655,10 +655,10 @@ func TestNeighborCacheDuplicateStaticEntryWithDifferentLinkAddress(t *testing.T)
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -681,10 +681,10 @@ func TestNeighborCacheDuplicateStaticEntryWithDifferentLinkAddress(t *testing.T)
EventType: entryTestChanged,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -725,10 +725,10 @@ func TestNeighborCacheRemoveStaticEntryThenOverflow(t *testing.T) {
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -750,10 +750,10 @@ func TestNeighborCacheRemoveStaticEntryThenOverflow(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -806,20 +806,20 @@ func TestNeighborCacheOverwriteWithStaticEntryThenOverflow(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: c.clock.Now(),
},
},
{
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -836,10 +836,10 @@ func TestNeighborCacheOverwriteWithStaticEntryThenOverflow(t *testing.T) {
startAtEntryIndex: 1,
wantStaticEntries: []NeighborEntry{
{
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: staticLinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -867,10 +867,10 @@ func TestNeighborCacheAddStaticEntryThenOverflow(t *testing.T) {
t.Errorf("unexpected error from c.linkRes.neigh.entry(%s, \"\", nil): %s", entry.Addr, err)
}
want := NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
}
if diff := cmp.Diff(want, e); diff != "" {
t.Errorf("c.linkRes.neigh.entry(%s, \"\", nil) mismatch (-want, +got):\n%s", entry.Addr, diff)
@@ -882,10 +882,10 @@ func TestNeighborCacheAddStaticEntryThenOverflow(t *testing.T) {
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -902,10 +902,10 @@ func TestNeighborCacheAddStaticEntryThenOverflow(t *testing.T) {
startAtEntryIndex: 1,
wantStaticEntries: []NeighborEntry{
{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Static,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -939,10 +939,10 @@ func TestNeighborCacheClear(t *testing.T) {
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Static,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Static,
UpdatedAt: clock.Now(),
},
},
}
@@ -965,20 +965,20 @@ func TestNeighborCacheClear(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
{
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Static,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Static,
UpdatedAt: clock.Now(),
},
},
}
@@ -1019,10 +1019,10 @@ func TestNeighborCacheClearThenOverflow(t *testing.T) {
EventType: entryTestRemoved,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: c.clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: c.clock.Now(),
},
},
}
@@ -1054,7 +1054,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
clock := faketime.NewManualClock()
linkRes := newTestNeighborResolver(&nudDisp, config, clock)
startedAt := clock.NowNanoseconds()
startedAt := clock.Now()
// The following logic is very similar to overflowCache, but
// periodically refreshes the frequently used entry.
@@ -1110,7 +1110,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
State: Reachable,
// Can be inferred since the frequently used entry is the first to
// be created and transitioned to Reachable.
UpdatedAtNanos: startedAt + typicalLatency.Nanoseconds(),
UpdatedAt: startedAt.Add(typicalLatency),
},
}
@@ -1119,12 +1119,12 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) {
if !ok {
t.Fatalf("got linkRes.entries.entry(%d) = _, false, want = true", i)
}
durationReachableNanos := int64(linkRes.entries.size()-i-1) * typicalLatency.Nanoseconds()
durationReachableNanos := time.Duration(linkRes.entries.size()-i-1) * typicalLatency
wantUnsortedEntries = append(wantUnsortedEntries, NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds() - durationReachableNanos,
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now().Add(-durationReachableNanos),
})
}
@@ -1182,12 +1182,12 @@ func TestNeighborCacheConcurrent(t *testing.T) {
if !ok {
t.Errorf("got linkRes.entries.entry(%d) = _, false, want = true", i)
}
durationReachableNanos := int64(linkRes.entries.size()-i-1) * typicalLatency.Nanoseconds()
durationReachableNanos := time.Duration(linkRes.entries.size()-i-1) * typicalLatency
wantUnsortedEntries = append(wantUnsortedEntries, NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds() - durationReachableNanos,
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now().Add(-durationReachableNanos),
})
}
@@ -1236,10 +1236,10 @@ func TestNeighborCacheReplace(t *testing.T) {
t.Fatalf("linkRes.neigh.entry(%s, '', nil): %s", entry.Addr, err)
}
want := NeighborEntry{
Addr: entry.Addr,
LinkAddr: updatedLinkAddr,
State: Delay,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: updatedLinkAddr,
State: Delay,
UpdatedAt: clock.Now(),
}
if diff := cmp.Diff(want, e); diff != "" {
t.Errorf("linkRes.neigh.entry(%s, '', nil) mismatch (-want, +got):\n%s", entry.Addr, diff)
@@ -1255,10 +1255,10 @@ func TestNeighborCacheReplace(t *testing.T) {
t.Errorf("unexpected error from linkRes.neigh.entry(%s, '', nil): %s", entry.Addr, err)
}
want := NeighborEntry{
Addr: entry.Addr,
LinkAddr: updatedLinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: updatedLinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
}
if diff := cmp.Diff(want, e); diff != "" {
t.Errorf("linkRes.neigh.entry(%s, '', nil) mismatch (-want, +got):\n%s", entry.Addr, diff)
@@ -1293,10 +1293,10 @@ func TestNeighborCacheResolutionFailed(t *testing.T) {
t.Fatalf("unexpected error from linkRes.neigh.entry(%s, '', nil): %s", entry.Addr, err)
}
want := NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("linkRes.neigh.entry(%s, '', nil) mismatch (-want, +got):\n%s", entry.Addr, diff)
@@ -1397,10 +1397,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
EventType: entryTestAdded,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAt: clock.Now(),
},
},
}
@@ -1428,10 +1428,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
EventType: entryTestChanged,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: "",
State: Unreachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: "",
State: Unreachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1447,10 +1447,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
{
wantEntries := []NeighborEntry{
{
Addr: entry.Addr,
LinkAddr: "",
State: Unreachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: "",
State: Unreachable,
UpdatedAt: clock.Now(),
},
}
if diff := cmp.Diff(linkRes.neigh.entries(), wantEntries, unorderedEntriesDiffOpts()...); diff != "" {
@@ -1480,10 +1480,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
EventType: entryTestChanged,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: "",
State: Incomplete,
UpdatedAt: clock.Now(),
},
},
}
@@ -1510,10 +1510,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
EventType: entryTestChanged,
NICID: 1,
Entry: NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1533,10 +1533,10 @@ func TestNeighborCacheRetryResolution(t *testing.T) {
}
wantEntry := NeighborEntry{
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entry.Addr,
LinkAddr: entry.LinkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
}
if diff := cmp.Diff(gotEntry, wantEntry); diff != "" {
t.Fatalf("neighbor entry mismatch (-got, +want):\n%s", diff)
+11 -11
View File
@@ -31,10 +31,10 @@ const (
// NeighborEntry describes a neighboring device in the local network.
type NeighborEntry struct {
Addr tcpip.Address
LinkAddr tcpip.LinkAddress
State NeighborState
UpdatedAtNanos int64
Addr tcpip.Address
LinkAddr tcpip.LinkAddress
State NeighborState
UpdatedAt time.Time
}
// NeighborState defines the state of a NeighborEntry within the Neighbor
@@ -138,10 +138,10 @@ func newNeighborEntry(cache *neighborCache, remoteAddr tcpip.Address, nudState *
// calling `setStateLocked`.
func newStaticNeighborEntry(cache *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress, state *NUDState) *neighborEntry {
entry := NeighborEntry{
Addr: addr,
LinkAddr: linkAddr,
State: Static,
UpdatedAtNanos: cache.nic.stack.clock.NowNanoseconds(),
Addr: addr,
LinkAddr: linkAddr,
State: Static,
UpdatedAt: cache.nic.stack.clock.Now(),
}
n := &neighborEntry{
cache: cache,
@@ -224,7 +224,7 @@ func (e *neighborEntry) cancelTimerLocked() {
//
// Precondition: e.mu MUST be locked.
func (e *neighborEntry) removeLocked() {
e.mu.neigh.UpdatedAtNanos = e.cache.nic.stack.clock.NowNanoseconds()
e.mu.neigh.UpdatedAt = e.cache.nic.stack.clock.Now()
e.dispatchRemoveEventLocked()
e.cancelTimerLocked()
// TODO(https://gvisor.dev/issues/5583): test the case where this function is
@@ -246,7 +246,7 @@ func (e *neighborEntry) setStateLocked(next NeighborState) {
prev := e.mu.neigh.State
e.mu.neigh.State = next
e.mu.neigh.UpdatedAtNanos = e.cache.nic.stack.clock.NowNanoseconds()
e.mu.neigh.UpdatedAt = e.cache.nic.stack.clock.Now()
config := e.nudState.Config()
switch next {
@@ -354,7 +354,7 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) {
case Unknown, Unreachable:
prev := e.mu.neigh.State
e.mu.neigh.State = Incomplete
e.mu.neigh.UpdatedAtNanos = e.cache.nic.stack.clock.NowNanoseconds()
e.mu.neigh.UpdatedAt = e.cache.nic.stack.clock.Now()
switch prev {
case Unknown:
+110 -110
View File
@@ -349,10 +349,10 @@ func unknownToIncomplete(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *
EventType: entryTestAdded,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Incomplete,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Incomplete,
UpdatedAt: clock.Now(),
},
},
}
@@ -410,10 +410,10 @@ func unknownToStale(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entry
EventType: entryTestAdded,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -441,7 +441,7 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
// UpdatedAt should remain the same during address resolution.
e.mu.Lock()
startedAt := e.mu.neigh.UpdatedAtNanos
startedAt := e.mu.neigh.UpdatedAt
e.mu.Unlock()
// Wait for the rest of the reachability probe transmissions, signifying
@@ -465,7 +465,7 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
}
e.mu.Lock()
if got, want := e.mu.neigh.UpdatedAtNanos, startedAt; got != want {
if got, want := e.mu.neigh.UpdatedAt, startedAt; got != want {
t.Errorf("got e.mu.neigh.UpdatedAt = %q, want = %q", got, want)
}
e.mu.Unlock()
@@ -480,10 +480,10 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Unreachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Unreachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -542,10 +542,10 @@ func incompleteToReachableWithFlags(e *neighborEntry, nudDisp *testNUDDispatcher
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -639,10 +639,10 @@ func TestEntryIncompleteToStaleWhenUnsolicitedConfirmation(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -673,10 +673,10 @@ func TestEntryIncompleteToStaleWhenProbe(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -752,10 +752,10 @@ func incompleteToUnreachable(c NUDConfigurations, e *neighborEntry, nudDisp *tes
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Unreachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Unreachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -938,10 +938,10 @@ func reachableToStale(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDis
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -993,10 +993,10 @@ func TestEntryReachableToStaleWhenProbeWithDifferentAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1045,10 +1045,10 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddress(t *testing.T)
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1097,10 +1097,10 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddressAndOverride(t
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1186,10 +1186,10 @@ func TestEntryStaleToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1238,10 +1238,10 @@ func TestEntryStaleToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1279,10 +1279,10 @@ func TestEntryStaleToStaleWhenOverrideConfirmation(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1327,10 +1327,10 @@ func TestEntryStaleToStaleWhenProbeUpdateAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1386,10 +1386,10 @@ func staleToDelay(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTe
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Delay,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Delay,
UpdatedAt: clock.Now(),
},
},
}
@@ -1438,10 +1438,10 @@ func TestEntryDelayToReachableWhenUpperLevelConfirmation(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1493,10 +1493,10 @@ func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1548,10 +1548,10 @@ func TestEntryDelayToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -1640,10 +1640,10 @@ func TestEntryDelayToStaleWhenProbeWithDifferentAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1692,10 +1692,10 @@ func TestEntryDelayToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1765,10 +1765,10 @@ func delayToProbe(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDispatc
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Probe,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Probe,
UpdatedAt: clock.Now(),
},
},
}
@@ -1822,10 +1822,10 @@ func TestEntryProbeToStaleWhenProbeWithDifferentAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1877,10 +1877,10 @@ func TestEntryProbeToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr2,
State: Stale,
UpdatedAt: clock.Now(),
},
},
}
@@ -1998,10 +1998,10 @@ func probeToReachableWithFlags(e *neighborEntry, nudDisp *testNUDDispatcher, lin
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: linkAddr,
State: Reachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: linkAddr,
State: Reachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -2150,10 +2150,10 @@ func probeToUnreachable(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDD
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Unreachable,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: entryTestLinkAddr1,
State: Unreachable,
UpdatedAt: clock.Now(),
},
},
}
@@ -2222,10 +2222,10 @@ func unreachableToIncomplete(e *neighborEntry, nudDisp *testNUDDispatcher, linkR
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Incomplete,
UpdatedAtNanos: clock.NowNanoseconds(),
Addr: entryTestAddr1,
LinkAddr: tcpip.LinkAddress(""),
State: Incomplete,
UpdatedAt: clock.Now(),
},
},
}
+1 -1
View File
@@ -170,7 +170,7 @@ func TestNUDFunctions(t *testing.T) {
t.Errorf("s.Neigbors(%d, %d) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff)
} else if test.expectedErr == nil {
if diff := cmp.Diff(
[]stack.NeighborEntry{{Addr: llAddr2, LinkAddr: linkAddr1, State: stack.Static, UpdatedAtNanos: clock.NowNanoseconds()}},
[]stack.NeighborEntry{{Addr: llAddr2, LinkAddr: linkAddr1, State: stack.Static, UpdatedAt: clock.Now()}},
neighbors,
); diff != "" {
t.Errorf("neighbors mismatch (-want +got):\n%s", diff)
+1 -1
View File
@@ -4427,7 +4427,7 @@ func TestClearNeighborCacheOnNICDisable(t *testing.T) {
if neighbors, err := s.Neighbors(nicID, addr.proto); err != nil {
t.Fatalf("s.Neighbors(%d, %d): %s", nicID, addr.proto, err)
} else if diff := cmp.Diff(
[]stack.NeighborEntry{{Addr: addr.addr, LinkAddr: linkAddr, State: stack.Static, UpdatedAtNanos: clock.NowNanoseconds()}},
[]stack.NeighborEntry{{Addr: addr.addr, LinkAddr: linkAddr, State: stack.Static, UpdatedAt: clock.Now()}},
neighbors,
); diff != "" {
t.Fatalf("proto=%d neighbors mismatch (-want +got):\n%s", addr.proto, diff)
+8 -8
View File
@@ -60,11 +60,11 @@ type stdClock struct {
// monotonicOffset is assigned maxMonotonic after restore so that the
// monotonic time will continue from where it "left off" before saving as part
// of S/R.
monotonicOffset int64 `state:"nosave"`
monotonicOffset MonotonicTime `state:"nosave"`
// monotonicMU protects maxMonotonic.
monotonicMU sync.Mutex `state:"nosave"`
maxMonotonic int64
maxMonotonic MonotonicTime
}
// NewStdClock returns an instance of a clock that uses the time package.
@@ -76,25 +76,25 @@ func NewStdClock() Clock {
var _ Clock = (*stdClock)(nil)
// NowNanoseconds implements Clock.NowNanoseconds.
func (*stdClock) NowNanoseconds() int64 {
return time.Now().UnixNano()
// Now implements Clock.Now.
func (*stdClock) Now() time.Time {
return time.Now()
}
// NowMonotonic implements Clock.NowMonotonic.
func (s *stdClock) NowMonotonic() int64 {
func (s *stdClock) NowMonotonic() MonotonicTime {
sinceBase := time.Since(s.baseTime)
if sinceBase < 0 {
panic(fmt.Sprintf("got negative duration = %s since base time = %s", sinceBase, s.baseTime))
}
monotonicValue := sinceBase.Nanoseconds() + s.monotonicOffset
monotonicValue := s.monotonicOffset.Add(sinceBase)
s.monotonicMU.Lock()
defer s.monotonicMU.Unlock()
// Monotonic time values must never decrease.
if monotonicValue > s.maxMonotonic {
if s.maxMonotonic.Before(monotonicValue) {
s.maxMonotonic = monotonicValue
}
+30 -5
View File
@@ -64,17 +64,42 @@ func (e *ErrSaveRejection) Error() string {
return "save rejected due to unsupported networking state: " + e.Err.Error()
}
// MonotonicTime is a monotonic clock reading.
//
// +stateify savable
type MonotonicTime struct {
nanoseconds int64
}
// Before reports whether the monotonic clock reading mt is before u.
func (mt MonotonicTime) Before(u MonotonicTime) bool {
return mt.nanoseconds < u.nanoseconds
}
// Add returns the monotonic clock reading mt+d.
func (mt MonotonicTime) Add(d time.Duration) MonotonicTime {
return MonotonicTime{
nanoseconds: time.Unix(0, mt.nanoseconds).Add(d).Sub(time.Unix(0, 0)).Nanoseconds(),
}
}
// Sub returns the duration mt-u. If the result exceeds the maximum (or minimum)
// value that can be stored in a Duration, the maximum (or minimum) duration
// will be returned. To compute t-d for a duration d, use t.Add(-d).
func (mt MonotonicTime) Sub(u MonotonicTime) time.Duration {
return time.Unix(0, mt.nanoseconds).Sub(time.Unix(0, u.nanoseconds))
}
// A Clock provides the current time and schedules work for execution.
//
// Times returned by a Clock should always be used for application-visible
// time. Only monotonic times should be used for netstack internal timekeeping.
type Clock interface {
// NowNanoseconds returns the current real time as a number of
// nanoseconds since the Unix epoch.
NowNanoseconds() int64
// Now returns the current local time.
Now() time.Time
// NowMonotonic returns a monotonic time value at nanosecond resolution.
NowMonotonic() int64
// NowMonotonic returns the current monotonic clock reading.
NowMonotonic() MonotonicTime
// AfterFunc waits for the duration to elapse and then calls f in its own
// goroutine. It returns a Timer that can be used to cancel the call using
@@ -1034,7 +1034,7 @@ func (d *nudDispatcher) OnNeighborRemoved(nicID tcpip.NICID, entry stack.Neighbo
}
func (d *nudDispatcher) waitForEvent(want eventInfo) error {
if diff := cmp.Diff(want, <-d.c, cmp.AllowUnexported(eventInfo{}), cmpopts.IgnoreFields(stack.NeighborEntry{}, "UpdatedAtNanos")); diff != "" {
if diff := cmp.Diff(want, <-d.c, cmp.AllowUnexported(eventInfo{}), cmpopts.IgnoreFields(stack.NeighborEntry{}, "UpdatedAt")); diff != "" {
return fmt.Errorf("got invalid event (-want +got):\n%s", diff)
}
return nil
+62
View File
@@ -15,6 +15,7 @@
package tcpip_test
import (
"math"
"sync"
"testing"
"time"
@@ -22,6 +23,67 @@ import (
"gvisor.dev/gvisor/pkg/tcpip"
)
func TestMonotonicTimeBefore(t *testing.T) {
var mt tcpip.MonotonicTime
if mt.Before(mt) {
t.Errorf("%#v.Before(%#v)", mt, mt)
}
one := mt.Add(1)
if one.Before(mt) {
t.Errorf("%#v.Before(%#v)", one, mt)
}
if !mt.Before(one) {
t.Errorf("!%#v.Before(%#v)", mt, one)
}
}
func TestMonotonicTimeAddSub(t *testing.T) {
var mt tcpip.MonotonicTime
if one, two := mt.Add(2), mt.Add(1).Add(1); one != two {
t.Errorf("mt.Add(2) != mt.Add(1).Add(1) (%#v != %#v)", one, two)
}
min := mt.Add(math.MinInt64)
max := mt.Add(math.MaxInt64)
if overflow := mt.Add(1).Add(math.MaxInt64); overflow != max {
t.Errorf("mt.Add(math.MaxInt64) != mt.Add(1).Add(math.MaxInt64) (%#v != %#v)", max, overflow)
}
if underflow := mt.Add(-1).Add(math.MinInt64); underflow != min {
t.Errorf("mt.Add(math.MinInt64) != mt.Add(-1).Add(math.MinInt64) (%#v != %#v)", min, underflow)
}
if got, want := min.Sub(min), time.Duration(0); want != got {
t.Errorf("got min.Sub(min) = %d, want %d", got, want)
}
if got, want := max.Sub(max), time.Duration(0); want != got {
t.Errorf("got max.Sub(max) = %d, want %d", got, want)
}
if overflow, want := max.Sub(min), time.Duration(math.MaxInt64); overflow != want {
t.Errorf("mt.Add(math.MaxInt64).Sub(mt.Add(math.MinInt64) != %s (%#v)", want, overflow)
}
if underflow, want := min.Sub(max), time.Duration(math.MinInt64); underflow != want {
t.Errorf("mt.Add(math.MinInt64).Sub(mt.Add(math.MaxInt64) != %s (%#v)", want, underflow)
}
}
func TestMonotonicTimeSub(t *testing.T) {
var mt tcpip.MonotonicTime
if one, two := mt.Add(2), mt.Add(1).Add(1); one != two {
t.Errorf("mt.Add(2) != mt.Add(1).Add(1) (%#v != %#v)", one, two)
}
if max, overflow := mt.Add(math.MaxInt64), mt.Add(1).Add(math.MaxInt64); max != overflow {
t.Errorf("mt.Add(math.MaxInt64) != mt.Add(1).Add(math.MaxInt64) (%#v != %#v)", max, overflow)
}
if max, underflow := mt.Add(math.MinInt64), mt.Add(-1).Add(math.MinInt64); max != underflow {
t.Errorf("mt.Add(math.MinInt64) != mt.Add(-1).Add(math.MinInt64) (%#v != %#v)", max, underflow)
}
}
const (
shortDuration = 1 * time.Nanosecond
middleDuration = 100 * time.Millisecond
+4 -3
View File
@@ -16,6 +16,7 @@ package icmp
import (
"io"
"time"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
@@ -33,7 +34,7 @@ type icmpPacket struct {
icmpPacketEntry
senderAddress tcpip.FullAddress
data buffer.VectorisedView `state:".(buffer.VectorisedView)"`
timestamp int64
receivedAt time.Time `state:".(int64)"`
}
type endpointState int
@@ -193,7 +194,7 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult
Total: p.data.Size(),
ControlMessages: tcpip.ControlMessages{
HasTimestamp: true,
Timestamp: p.timestamp,
Timestamp: p.receivedAt.UnixNano(),
},
}
if opts.NeedRemoteAddr {
@@ -800,7 +801,7 @@ func (e *endpoint) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketB
e.rcvList.PushBack(packet)
e.rcvBufSize += packet.data.Size()
packet.timestamp = e.stack.Clock().NowNanoseconds()
packet.receivedAt = e.stack.Clock().Now()
e.rcvMu.Unlock()
e.stats.PacketsReceived.Increment()
@@ -15,11 +15,23 @@
package icmp
import (
"time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
// saveReceivedAt is invoked by stateify.
func (p *icmpPacket) saveReceivedAt() int64 {
return p.receivedAt.UnixNano()
}
// loadReceivedAt is invoked by stateify.
func (p *icmpPacket) loadReceivedAt(nsec int64) {
p.receivedAt = time.Unix(0, nsec)
}
// saveData saves icmpPacket.data field.
func (p *icmpPacket) saveData() buffer.VectorisedView {
// We cannot save p.data directly as p.data.views may alias to p.views,
+5 -5
View File
@@ -27,6 +27,7 @@ package packet
import (
"fmt"
"io"
"time"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
@@ -41,9 +42,8 @@ type packet struct {
packetEntry
// data holds the actual packet data, including any headers and
// payload.
data buffer.VectorisedView `state:".(buffer.VectorisedView)"`
// timestampNS is the unix time at which the packet was received.
timestampNS int64
data buffer.VectorisedView `state:".(buffer.VectorisedView)"`
receivedAt time.Time `state:".(int64)"`
// senderAddr is the network address of the sender.
senderAddr tcpip.FullAddress
// packetInfo holds additional information like the protocol
@@ -189,7 +189,7 @@ func (ep *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResul
Total: packet.data.Size(),
ControlMessages: tcpip.ControlMessages{
HasTimestamp: true,
Timestamp: packet.timestampNS,
Timestamp: packet.receivedAt.UnixNano(),
},
}
if opts.NeedRemoteAddr {
@@ -451,7 +451,7 @@ func (ep *endpoint) HandlePacket(nicID tcpip.NICID, localAddr tcpip.LinkAddress,
packet.data = buffer.NewVectorisedView(pkt.Size(), pkt.Views())
}
}
packet.timestampNS = ep.stack.Clock().NowNanoseconds()
packet.receivedAt = ep.stack.Clock().Now()
ep.rcvList.PushBack(&packet)
ep.rcvBufSize += packet.data.Size()

Some files were not shown because too many files have changed in this diff Show More