summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack
diff options
context:
space:
mode:
authorSam Balana <sbalana@google.com>2021-02-26 12:09:42 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-26 12:11:44 -0800
commit35a71a24f2dc5e7b36a07d054ea70e3729b4df46 (patch)
tree762dacf196fe69da381d12e2a9accb36501d15b6 /pkg/tcpip/stack
parentda2505df94770301e7907cfaff5e5c7fdd531b75 (diff)
Use helper functions in neighbor entry tests
Adds helper functions for transitioning into common states. This reduces the boilerplate by a fair amount, decreasing the barriers to entry for new features added to neighborEntry. PiperOrigin-RevId: 359810465
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r--pkg/tcpip/stack/neighbor_entry_test.go2989
1 files changed, 827 insertions, 2162 deletions
diff --git a/pkg/tcpip/stack/neighbor_entry_test.go b/pkg/tcpip/stack/neighbor_entry_test.go
index 47a9e2448..51c14d822 100644
--- a/pkg/tcpip/stack/neighbor_entry_test.go
+++ b/pkg/tcpip/stack/neighbor_entry_test.go
@@ -139,6 +139,8 @@ func (e testEntryEventInfo) String() string {
// testNUDDispatcher implements NUDDispatcher to validate the dispatching of
// events upon certain NUD state machine events.
type testNUDDispatcher struct {
+ // TODO(gvisor.bug/issue/5541): Refactor to use the embedded sync.Mutex
+ // pattern.
mu sync.Mutex
events []testEntryEventInfo
}
@@ -176,6 +178,8 @@ func (d *testNUDDispatcher) OnNeighborRemoved(nicID tcpip.NICID, entry NeighborE
}
type entryTestLinkResolver struct {
+ // TODO(gvisor.bug/issue/5541): Refactor to use the embedded sync.Mutex
+ // pattern.
mu sync.Mutex
probes []entryTestProbeInfo
}
@@ -323,12 +327,27 @@ func TestEntryUnknownToIncomplete(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
+ }
+}
+
+func unknownToIncomplete(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if e.mu.neigh.State != Unknown {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unknown)
+ }
+ e.handlePacketQueuedLocked(entryTestAddr2)
+ if e.mu.neigh.State != Incomplete {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ }
+ return nil
+ }(); err != nil {
+ return err
}
- e.mu.Unlock()
runImmediatelyScheduledJobs(clock)
wantProbes := []entryTestProbeInfo{
@@ -340,9 +359,10 @@ func TestEntryUnknownToIncomplete(t *testing.T) {
}
linkRes.mu.Lock()
diff := cmp.Diff(wantProbes, linkRes.probes)
+ linkRes.probes = nil
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
wantEvents := []testEntryEventInfo{
@@ -359,31 +379,50 @@ func TestEntryUnknownToIncomplete(t *testing.T) {
{
nudDisp.mu.Lock()
diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
nudDisp.mu.Unlock()
if diff != "" {
- t.Fatalf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
}
+ return nil
}
func TestEntryUnknownToStale(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handleProbeLocked(entryTestLinkAddr1)
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
+ }
+}
+
+func unknownToStale(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if e.mu.neigh.State != Unknown {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unknown)
+ }
+ e.handleProbeLocked(entryTestLinkAddr1)
+ if e.mu.neigh.State != Stale {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ }
+ return nil
+ }(); err != nil {
+ return err
}
- e.mu.Unlock()
// No probes should have been sent.
runImmediatelyScheduledJobs(clock)
- linkRes.mu.Lock()
- diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
wantEvents := []testEntryEventInfo{
@@ -397,11 +436,17 @@ func TestEntryUnknownToStale(t *testing.T) {
},
},
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ {
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
}
- nudDisp.mu.Unlock()
+
+ return nil
}
func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
@@ -409,48 +454,20 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
c.MaxMulticastProbes = 3
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- updatedAtNanos := e.mu.neigh.UpdatedAtNanos
- e.mu.Unlock()
-
- clock.Advance(c.RetransmitTimer)
// UpdatedAt should remain the same during address resolution.
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
-
e.mu.Lock()
- if got, want := e.mu.neigh.UpdatedAtNanos, updatedAtNanos; got != want {
- t.Errorf("got e.mu.neigh.UpdatedAt = %q, want = %q", got, want)
- }
+ updatedAtNanos := e.mu.neigh.UpdatedAtNanos
e.mu.Unlock()
- clock.Advance(c.RetransmitTimer)
+ // Wait for the rest of the reachability probe transmissions, signifying
+ // Incomplete to Incomplete transitions.
+ for i := uint32(1); i < c.MaxMulticastProbes; i++ {
+ clock.Advance(c.RetransmitTimer)
- // UpdatedAt should change after failing address resolution. Timing out after
- // sending the last probe transitions the entry to Unreachable.
- {
wantProbes := []entryTestProbeInfo{
{
RemoteAddress: entryTestAddr1,
@@ -460,25 +477,25 @@ func TestEntryIncompleteToIncompleteDoesNotChangeUpdatedAt(t *testing.T) {
}
linkRes.mu.Lock()
diff := cmp.Diff(wantProbes, linkRes.probes)
+ linkRes.probes = nil
linkRes.mu.Unlock()
if diff != "" {
t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
+
+ e.mu.Lock()
+ if got, want := e.mu.neigh.UpdatedAtNanos, updatedAtNanos; got != want {
+ t.Errorf("got e.mu.neigh.UpdatedAt = %q, want = %q", got, want)
+ }
+ e.mu.Unlock()
}
+ // UpdatedAt should change after failing address resolution. Timing out after
+ // sending the last probe transitions the entry to Unreachable.
clock.Advance(c.RetransmitTimer)
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -505,50 +522,47 @@ func TestEntryIncompleteToReachable(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+}
+
+func incompleteToReachableWithFlags(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock, flags ReachabilityConfirmationFlags) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if e.mu.neigh.State != Incomplete {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ }
+ e.handleConfirmationLocked(entryTestLinkAddr1, flags)
+ if e.mu.neigh.State != Reachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ }
+ if e.mu.neigh.LinkAddr != entryTestLinkAddr1 {
+ return fmt.Errorf("got e.mu.neigh.LinkAddr = %q, want = %q", e.mu.neigh.LinkAddr, entryTestLinkAddr1)
+ }
+ return nil
+ }(); err != nil {
+ return err
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
- e.mu.Unlock()
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -558,104 +572,75 @@ func TestEntryIncompleteToReachable(t *testing.T) {
},
},
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ {
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
}
- nudDisp.mu.Unlock()
+
+ return nil
}
-func TestEntryIncompleteToReachableWithRouterFlag(t *testing.T) {
- c := DefaultNUDConfigurations()
- e, nudDisp, linkRes, clock := entryTestSetup(c)
+func incompleteToReachable(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := incompleteToReachableWithFlags(e, nudDisp, linkRes, clock, ReachabilityConfirmationFlags{
+ Solicited: true,
+ Override: false,
+ IsRouter: false,
+ }); err != nil {
+ return err
+ }
e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
- }
+ isRouter := e.mu.isRouter
e.mu.Unlock()
+ if isRouter {
+ return fmt.Errorf("got e.mu.isRouter = %t, want = false", isRouter)
+ }
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ return nil
+}
+
+func TestEntryIncompleteToReachableWithRouterFlag(t *testing.T) {
+ c := DefaultNUDConfigurations()
+ e, nudDisp, linkRes, clock := entryTestSetup(c)
+
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachableWithRouterFlag(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachableWithRouterFlag(...) = %s", err)
}
+}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
+func incompleteToReachableWithRouterFlag(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := incompleteToReachableWithFlags(e, nudDisp, linkRes, clock, ReachabilityConfirmationFlags{
Solicited: true,
Override: false,
IsRouter: true,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ }); err != nil {
+ return err
}
- if !e.mu.isRouter {
- t.Errorf("got e.mu.isRouter = %t, want = true", e.mu.isRouter)
- }
- e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- }
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ e.mu.Lock()
+ isRouter := e.mu.isRouter
+ e.mu.Unlock()
+ if !isRouter {
+ return fmt.Errorf("got e.mu.isRouter = %t, want = true", isRouter)
}
- nudDisp.mu.Unlock()
+
+ return nil
}
func TestEntryIncompleteToStaleWhenUnsolicitedConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
- }
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
e.mu.Lock()
@@ -667,19 +652,13 @@ func TestEntryIncompleteToStaleWhenUnsolicitedConfirmation(t *testing.T) {
if e.mu.neigh.State != Stale {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
}
+ if e.mu.isRouter {
+ t.Errorf("got e.mu.isRouter = %t, want = false", e.mu.isRouter)
+ }
e.mu.Unlock()
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -700,26 +679,8 @@ func TestEntryIncompleteToStaleWhenProbe(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
- }
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
e.mu.Lock()
@@ -731,15 +692,6 @@ func TestEntryIncompleteToStaleWhenProbe(t *testing.T) {
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -761,53 +713,63 @@ func TestEntryIncompleteToUnreachable(t *testing.T) {
c.MaxMulticastProbes = 3
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- e.mu.Unlock()
+ if err := incompleteToUnreachable(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToUnreachable(...) = %s", err)
+ }
+}
- waitFor := c.RetransmitTimer * time.Duration(c.MaxMulticastProbes)
- clock.Advance(waitFor)
+func incompleteToUnreachable(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ {
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Incomplete {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Incomplete)
+ }
+ }
- wantProbes := []entryTestProbeInfo{
- // The Incomplete-to-Incomplete state transition is tested here by
- // verifying that 3 reachability probes were sent.
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
+ // The first probe was sent in the transition from Unknown to Incomplete.
+ clock.Advance(c.RetransmitTimer)
+
+ // Observe each subsequent multicast probe transmitted.
+ for i := uint32(1); i < c.MaxMulticastProbes; i++ {
+ wantProbes := []entryTestProbeInfo{{
RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
+ RemoteLinkAddress: "",
LocalAddress: entryTestAddr2,
- },
+ }}
+ linkRes.mu.Lock()
+ diff := cmp.Diff(wantProbes, linkRes.probes)
+ linkRes.probes = nil
+ linkRes.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("link address resolver probe #%d mismatch (-want, +got):\n%s", i+1, diff)
+ }
+
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Incomplete {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Incomplete)
+ }
+
+ clock.Advance(c.RetransmitTimer)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+
+ {
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Unreachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Unreachable)
+ }
}
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -818,16 +780,14 @@ func TestEntryIncompleteToUnreachable(t *testing.T) {
},
}
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
nudDisp.mu.Unlock()
-
- e.mu.Lock()
- if e.mu.neigh.State != Unreachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unreachable)
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
- e.mu.Unlock()
+
+ return nil
}
type testLocker struct{}
@@ -837,122 +797,67 @@ var _ sync.Locker = (*testLocker)(nil)
func (*testLocker) Lock() {}
func (*testLocker) Unlock() {}
-func TestEntryStaysReachableWhenConfirmationWithRouterFlag(t *testing.T) {
+func TestEntryReachableToReachableClearsRouterWhenConfirmationWithoutRouter(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- ipv6EP := e.cache.nic.networkEndpoints[header.IPv6ProtocolNumber].(*testIPv6Endpoint)
-
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachableWithRouterFlag(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachableWithRouterFlag(...) = %s", err)
}
e.mu.Lock()
e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
+ Solicited: false,
Override: false,
- IsRouter: true,
+ IsRouter: false,
})
if e.mu.neigh.State != Reachable {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
}
- if got, want := e.mu.isRouter, true; got != want {
- t.Errorf("got e.mu.isRouter = %t, want = %t", got, want)
- }
-
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
if got, want := e.mu.isRouter, false; got != want {
t.Errorf("got e.mu.isRouter = %t, want = %t", got, want)
}
+ ipv6EP := e.cache.nic.networkEndpoints[header.IPv6ProtocolNumber].(*testIPv6Endpoint)
if ipv6EP.invalidatedRtr != e.mu.neigh.Addr {
t.Errorf("got ipv6EP.invalidatedRtr = %s, want = %s", ipv6EP.invalidatedRtr, e.mu.neigh.Addr)
}
e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
+
+ // No events should have been dispatched.
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
+ diff := cmp.Diff([]testEntryEventInfo(nil), nudDisp.events, eventDiffOpts()...)
nudDisp.mu.Unlock()
-
- e.mu.Lock()
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ if diff != "" {
+ t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
- e.mu.Unlock()
}
-func TestEntryStaysReachableWhenProbeWithSameAddress(t *testing.T) {
+func TestEntryReachableToReachableWhenProbeWithSameAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
e.handleProbeLocked(entryTestLinkAddr1)
if e.mu.neigh.State != Reachable {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
@@ -962,31 +867,24 @@ func TestEntryStaysReachableWhenProbeWithSameAddress(t *testing.T) {
}
e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
+
+ // No events should have been dispatched.
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
+ diff := cmp.Diff([]testEntryEventInfo(nil), nudDisp.events, eventDiffOpts()...)
+ nudDisp.mu.Unlock()
+ if diff != "" {
t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
- nudDisp.mu.Unlock()
}
func TestEntryReachableToStaleWhenTimeout(t *testing.T) {
@@ -998,58 +896,65 @@ func TestEntryReachableToStaleWhenTimeout(t *testing.T) {
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
+ }
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
+ }
+ if err := reachableToStale(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("reachableToStale(...) = %s", err)
+ }
+}
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+// reachableToStale transitions a neighborEntry in Reachable state to Stale
+// state. Depends on the elimination of random factors in the ReachableTime
+// computation.
+//
+// c.MinRandomFactor = 1
+// c.MaxRandomFactor = 1
+func reachableToStale(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ // Ensure there are no random factors in the ReachableTime computation.
+ if c.MinRandomFactor != 1 {
+ return fmt.Errorf("got c.MinRandomFactor = %f, want = 1", c.MinRandomFactor)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if c.MaxRandomFactor != 1 {
+ return fmt.Errorf("got c.MaxRandomFactor = %f, want = 1", c.MaxRandomFactor)
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ {
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Reachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Reachable)
+ }
}
- e.mu.Unlock()
clock.Advance(c.BaseReachableTime)
+ {
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Stale {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Stale)
+ }
+ }
+
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1059,77 +964,51 @@ func TestEntryReachableToStaleWhenTimeout(t *testing.T) {
},
},
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
- nudDisp.mu.Unlock()
+ {
- e.mu.Lock()
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
}
- e.mu.Unlock()
+
+ return nil
}
func TestEntryReachableToStaleWhenProbeWithDifferentAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
e.handleProbeLocked(entryTestLinkAddr2)
if e.mu.neigh.State != Stale {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1150,34 +1029,14 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddress(t *testing.T)
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: false,
Override: false,
@@ -1188,26 +1047,19 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddress(t *testing.T)
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1228,34 +1080,14 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddressAndOverride(t
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: false,
Override: true,
@@ -1266,26 +1098,19 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddressAndOverride(t
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1302,38 +1127,15 @@ func TestEntryReachableToStaleWhenConfirmationWithDifferentAddressAndOverride(t
nudDisp.mu.Unlock()
}
-func TestEntryStaysStaleWhenProbeWithSameAddress(t *testing.T) {
+func TestEntryStaleToStaleWhenProbeWithSameAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
e.handleProbeLocked(entryTestLinkAddr1)
if e.mu.neigh.State != Stale {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
@@ -1343,28 +1145,20 @@ func TestEntryStaysStaleWhenProbeWithSameAddress(t *testing.T) {
}
e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
+
+ // No events should have been dispatched.
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
+ if diff := cmp.Diff([]testEntryEventInfo(nil), nudDisp.events); diff != "" {
t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
nudDisp.mu.Unlock()
@@ -1374,34 +1168,11 @@ func TestEntryStaleToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: true,
Override: true,
@@ -1415,26 +1186,19 @@ func TestEntryStaleToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1455,34 +1219,11 @@ func TestEntryStaleToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
e.handleConfirmationLocked("" /* linkAddr */, ReachabilityConfirmationFlags{
Solicited: true,
Override: false,
@@ -1496,26 +1237,19 @@ func TestEntryStaleToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1536,34 +1270,11 @@ func TestEntryStaleToStaleWhenOverrideConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: false,
Override: true,
@@ -1579,24 +1290,6 @@ func TestEntryStaleToStaleWhenOverrideConfirmation(t *testing.T) {
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1617,34 +1310,11 @@ func TestEntryStaleToStaleWhenProbeUpdateAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
e.handleProbeLocked(entryTestLinkAddr2)
if e.mu.neigh.State != Stale {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
@@ -1654,26 +1324,19 @@ func TestEntryStaleToStaleWhenProbeUpdateAddress(t *testing.T) {
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1694,60 +1357,44 @@ func TestEntryStaleToDelay(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
+}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+func staleToDelay(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if e.mu.neigh.State != Stale {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ }
+ e.handlePacketQueuedLocked(entryTestAddr2)
+ if e.mu.neigh.State != Delay {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
+ }
+ return nil
+ }(); err != nil {
+ return err
}
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
- e.mu.Unlock()
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1758,86 +1405,47 @@ func TestEntryStaleToDelay(t *testing.T) {
},
}
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
+
+ return nil
}
func TestEntryDelayToReachableWhenUpperLevelConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
e.handleUpperLevelConfirmationLocked()
if e.mu.neigh.State != Reachable {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
}
e.mu.Unlock()
- clock.Advance(c.BaseReachableTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1846,15 +1454,6 @@ func TestEntryDelayToReachableWhenUpperLevelConfirmation(t *testing.T) {
State: Reachable,
},
},
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
}
nudDisp.mu.Lock()
if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
@@ -1865,43 +1464,16 @@ func TestEntryDelayToReachableWhenUpperLevelConfirmation(t *testing.T) {
func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
- c.MaxMulticastProbes = 1
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: true,
Override: true,
@@ -1915,36 +1487,19 @@ func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
}
e.mu.Unlock()
- clock.Advance(c.BaseReachableTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -1953,15 +1508,6 @@ func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
State: Reachable,
},
},
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
- State: Stale,
- },
- },
}
nudDisp.mu.Lock()
if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
@@ -1972,43 +1518,16 @@ func TestEntryDelayToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
func TestEntryDelayToReachableWhenSolicitedConfirmationWithoutAddress(t *testing.T) {
c := DefaultNUDConfigurations()
- c.MaxMulticastProbes = 1
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
e.handleConfirmationLocked("" /* linkAddr */, ReachabilityConfirmationFlags{
Solicited: true,
Override: false,
@@ -2022,36 +1541,19 @@ func TestEntryDelayToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
}
e.mu.Unlock()
- clock.Advance(c.BaseReachableTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2060,15 +1562,6 @@ func TestEntryDelayToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
State: Reachable,
},
},
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
}
nudDisp.mu.Lock()
if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
@@ -2077,41 +1570,20 @@ func TestEntryDelayToReachableWhenSolicitedConfirmationWithoutAddress(t *testing
nudDisp.mu.Unlock()
}
-func TestEntryStaysDelayWhenOverrideConfirmationWithSameAddress(t *testing.T) {
+func TestEntryDelayToDelayWhenOverrideConfirmationWithSameAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
Override: true,
IsRouter: false,
})
@@ -2123,37 +1595,20 @@ func TestEntryStaysDelayWhenOverrideConfirmationWithSameAddress(t *testing.T) {
}
e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
+
+ // No events should have been dispatched.
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
+ if diff := cmp.Diff([]testEntryEventInfo(nil), nudDisp.events); diff != "" {
t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
nudDisp.mu.Unlock()
@@ -2163,70 +1618,33 @@ func TestEntryDelayToStaleWhenProbeWithDifferentAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
e.handleProbeLocked(entryTestLinkAddr2)
if e.mu.neigh.State != Stale {
t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2247,35 +1665,14 @@ func TestEntryDelayToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: false,
Override: true,
@@ -2286,35 +1683,19 @@ func TestEntryDelayToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
}
e.mu.Unlock()
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
+ }
+
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2335,85 +1716,58 @@ func TestEntryDelayToProbe(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
+ }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
+ }
+}
- runImmediatelyScheduledJobs(clock)
+func delayToProbe(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Delay {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Delay)
}
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Delay {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Delay)
- }
- e.mu.Unlock()
-
+ // Wait for the first unicast probe to be transmitted, marking the
+ // transition from Delay to Probe.
clock.Advance(c.DelayFirstProbeTime)
+
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Probe {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Probe)
}
+ }
+
+ wantProbes := []entryTestProbeInfo{
+ {
+ RemoteAddress: entryTestAddr1,
+ RemoteLinkAddress: entryTestLinkAddr1,
+ },
+ }
+ {
linkRes.mu.Lock()
diff := cmp.Diff(wantProbes, linkRes.probes)
+ linkRes.probes = nil
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
}
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2423,118 +1777,53 @@ func TestEntryDelayToProbe(t *testing.T) {
},
},
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ {
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
}
- nudDisp.mu.Unlock()
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
- e.mu.Unlock()
+ return nil
}
func TestEntryProbeToStaleWhenProbeWithDifferentAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
+ }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
+ e.handleProbeLocked(entryTestLinkAddr2)
+ if e.mu.neigh.State != Stale {
+ t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ }
e.mu.Unlock()
- clock.Advance(c.DelayFirstProbeTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
}
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
- e.handleProbeLocked(entryTestLinkAddr2)
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
- e.mu.Unlock()
-
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2555,105 +1844,40 @@ func TestEntryProbeToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
+ }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
}
e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
+ e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
Solicited: false,
- Override: false,
+ Override: true,
IsRouter: false,
})
- e.handlePacketQueuedLocked(entryTestAddr2)
+ if e.mu.neigh.State != Stale {
+ t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ }
e.mu.Unlock()
- clock.Advance(c.DelayFirstProbeTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
}
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
- e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: true,
- IsRouter: false,
- })
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
- }
- e.mu.Unlock()
-
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -2670,62 +1894,21 @@ func TestEntryProbeToStaleWhenConfirmationWithDifferentAddress(t *testing.T) {
nudDisp.mu.Unlock()
}
-func TestEntryStaysProbeWhenOverrideConfirmationWithSameAddress(t *testing.T) {
+func TestEntryProbeToProbeWhenOverrideConfirmationWithSameAddress(t *testing.T) {
c := DefaultNUDConfigurations()
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
-
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- clock.Advance(c.DelayFirstProbeTime)
- {
- wantProbes := []entryTestProbeInfo{
- // The second probe is caused by the Delay-to-Probe transition.
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
}
e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
Solicited: false,
Override: true,
@@ -2739,560 +1922,162 @@ func TestEntryStaysProbeWhenOverrideConfirmationWithSameAddress(t *testing.T) {
}
e.mu.Unlock()
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
+ {
+ linkRes.mu.Lock()
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
+ linkRes.mu.Unlock()
+ if diff != "" {
+ t.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ }
}
+
+ // No events should have been dispatched.
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
+ diff := cmp.Diff([]testEntryEventInfo(nil), nudDisp.events, eventDiffOpts()...)
+ nudDisp.mu.Unlock()
+ if diff != "" {
t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
- nudDisp.mu.Unlock()
}
-// TestEntryUnknownToStaleToProbeToReachable exercises the following scenario:
-// 1. Probe is received
-// 2. Entry is created in Stale
-// 3. Packet is queued on the entry
-// 4. Entry transitions to Delay then Probe
-// 5. Probe is sent
-func TestEntryUnknownToStaleToProbeToReachable(t *testing.T) {
+func TestEntryProbeToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
c := DefaultNUDConfigurations()
- // Eliminate random factors from ReachableTime computation so the transition
- // from Probe to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handleProbeLocked(entryTestLinkAddr1)
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- clock.Advance(c.DelayFirstProbeTime)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
-
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
- e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: true,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- if got, want := e.mu.neigh.LinkAddr, entryTestLinkAddr2; got != want {
- t.Errorf("got e.mu.neigh.LinkAddr = %q, want = %q", got, want)
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
- e.mu.Unlock()
-
- clock.Advance(c.BaseReachableTime)
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
- State: Reachable,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
- State: Stale,
- },
- },
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ if err := probeToReachableWithOverride(e, nudDisp, linkRes, clock, entryTestLinkAddr2); err != nil {
+ t.Fatalf("probeToReachableWithOverride(...) = %s", err)
}
- nudDisp.mu.Unlock()
}
-func TestEntryProbeToReachableWhenSolicitedOverrideConfirmation(t *testing.T) {
- c := DefaultNUDConfigurations()
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
- e, nudDisp, linkRes, clock := entryTestSetup(c)
+func probeToReachableWithFlags(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock, linkAddr tcpip.LinkAddress, flags ReachabilityConfirmationFlags) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+ prevLinkAddr := e.mu.neigh.LinkAddr
+ if e.mu.neigh.State != Probe {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
+ }
+ e.handleConfirmationLocked(linkAddr, flags)
- runImmediatelyScheduledJobs(clock)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
+ if e.mu.neigh.State != Reachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
}
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if linkAddr == "" {
+ linkAddr = prevLinkAddr
}
+ if e.mu.neigh.LinkAddr != linkAddr {
+ return fmt.Errorf("got e.mu.neigh.LinkAddr = %q, want = %q", e.mu.neigh.LinkAddr, linkAddr)
+ }
+ return nil
+ }(); err != nil {
+ return err
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- clock.Advance(c.DelayFirstProbeTime)
+ // No probes should have been sent.
+ runImmediatelyScheduledJobs(clock)
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
+ diff := cmp.Diff([]entryTestProbeInfo(nil), linkRes.probes)
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
}
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
- e.handleConfirmationLocked(entryTestLinkAddr2, ReachabilityConfirmationFlags{
- Solicited: true,
- Override: true,
- IsRouter: false,
- })
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
- if got, want := e.mu.neigh.LinkAddr, entryTestLinkAddr2; got != want {
- t.Errorf("got e.mu.neigh.LinkAddr = %q, want = %q", got, want)
- }
- e.mu.Unlock()
-
- clock.Advance(c.BaseReachableTime)
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
+ LinkAddr: linkAddr,
State: Reachable,
},
},
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
- State: Stale,
- },
- },
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
- nudDisp.mu.Unlock()
-}
-
-func TestEntryProbeToReachableWhenSolicitedConfirmationWithSameAddress(t *testing.T) {
- c := DefaultNUDConfigurations()
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
- e, nudDisp, linkRes, clock := entryTestSetup(c)
-
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
}
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
+ return nil
+}
+
+func probeToReachableWithOverride(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock, linkAddr tcpip.LinkAddress) error {
+ return probeToReachableWithFlags(e, nudDisp, linkRes, clock, linkAddr, ReachabilityConfirmationFlags{
+ Solicited: true,
+ Override: true,
IsRouter: false,
})
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+}
- clock.Advance(c.DelayFirstProbeTime)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
- }
+func TestEntryProbeToReachableWhenSolicitedConfirmationWithSameAddress(t *testing.T) {
+ c := DefaultNUDConfigurations()
+ e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
+ }
+ if err := probeToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("probeToReachable(...) = %s", err)
+ }
+}
+
+func probeToReachable(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ return probeToReachableWithFlags(e, nudDisp, linkRes, clock, entryTestLinkAddr1, ReachabilityConfirmationFlags{
Solicited: true,
Override: false,
IsRouter: false,
})
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
- e.mu.Unlock()
-
- clock.Advance(c.BaseReachableTime)
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- }
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
- nudDisp.mu.Unlock()
}
func TestEntryProbeToReachableWhenSolicitedConfirmationWithoutAddress(t *testing.T) {
c := DefaultNUDConfigurations()
- // Eliminate random factors from ReachableTime computation so the transition
- // from Stale to Reachable will only take BaseReachableTime duration.
- c.MinRandomFactor = 1
- c.MaxRandomFactor = 1
-
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- runImmediatelyScheduledJobs(clock)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
}
-
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
-
- clock.Advance(c.DelayFirstProbeTime)
- {
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
}
-
- e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
}
- e.handleConfirmationLocked("" /* linkAddr */, ReachabilityConfirmationFlags{
+ if err := probeToReachableWithoutAddress(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("probeToReachableWithoutAddress(...) = %s", err)
+ }
+}
+
+func probeToReachableWithoutAddress(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ return probeToReachableWithFlags(e, nudDisp, linkRes, clock, "" /* linkAddr */, ReachabilityConfirmationFlags{
Solicited: true,
Override: false,
IsRouter: false,
})
- if e.mu.neigh.State != Reachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Reachable)
- }
- e.mu.Unlock()
-
- clock.Advance(c.BaseReachableTime)
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Reachable,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- }
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
- nudDisp.mu.Unlock()
}
func TestEntryProbeToUnreachable(t *testing.T) {
@@ -3302,106 +2087,68 @@ func TestEntryProbeToUnreachable(t *testing.T) {
c.DelayFirstProbeTime = c.RetransmitTimer
e, nudDisp, linkRes, clock := entryTestSetup(c)
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+ if err := unknownToStale(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToStale(...) = %s", err)
+ }
+ if err := staleToDelay(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("staleToDelay(...) = %s", err)
+ }
+ if err := delayToProbe(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("delayToProbe(...) = %s", err)
+ }
+ if err := probeToUnreachable(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("probeToUnreachable(...) = %s", err)
+ }
+}
- runImmediatelyScheduledJobs(clock)
+func probeToUnreachable(c NUDConfigurations, e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
{
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- LocalAddress: entryTestAddr2,
- },
- }
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.probes = nil
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Probe {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Probe)
}
}
- e.mu.Lock()
- e.handleConfirmationLocked(entryTestLinkAddr1, ReachabilityConfirmationFlags{
- Solicited: false,
- Override: false,
- IsRouter: false,
- })
- e.handlePacketQueuedLocked(entryTestAddr2)
- e.mu.Unlock()
+ // The first probe was sent in the transition from Delay to Probe.
+ clock.Advance(c.RetransmitTimer)
- // Observe each probe sent while in the Probe state.
- for i := uint32(0); i < c.MaxUnicastProbes; i++ {
- clock.Advance(c.RetransmitTimer)
- wantProbes := []entryTestProbeInfo{
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: entryTestLinkAddr1,
- },
- }
+ // Observe each subsequent unicast probe transmitted.
+ for i := uint32(1); i < c.MaxUnicastProbes; i++ {
+ wantProbes := []entryTestProbeInfo{{
+ RemoteAddress: entryTestAddr1,
+ RemoteLinkAddress: entryTestLinkAddr1,
+ }}
linkRes.mu.Lock()
diff := cmp.Diff(wantProbes, linkRes.probes)
linkRes.probes = nil
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probe #%d mismatch (-want, +got):\n%s", i+1, diff)
+ return fmt.Errorf("link address resolver probe #%d mismatch (-want, +got):\n%s", i+1, diff)
}
e.mu.Lock()
- if e.mu.neigh.State != Probe {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Probe)
- }
+ state := e.mu.neigh.State
e.mu.Unlock()
+ if state != Probe {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Probe)
+ }
+
+ clock.Advance(c.RetransmitTimer)
}
- // Wait for the last probe to expire, causing a transition to Unreachable.
- clock.Advance(c.RetransmitTimer)
- e.mu.Lock()
- if e.mu.neigh.State != Unreachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unreachable)
+ {
+ e.mu.Lock()
+ state := e.mu.neigh.State
+ e.mu.Unlock()
+ if state != Unreachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", state, Unreachable)
+ }
}
- e.mu.Unlock()
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Stale,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Delay,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr1,
- State: Probe,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -3412,10 +2159,14 @@ func TestEntryProbeToUnreachable(t *testing.T) {
},
}
nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
- }
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
+
+ return nil
}
func TestEntryUnreachableToIncomplete(t *testing.T) {
@@ -3423,31 +2174,36 @@ func TestEntryUnreachableToIncomplete(t *testing.T) {
c.MaxMulticastProbes = 3
e, nudDisp, linkRes, clock := entryTestSetup(c)
- // TODO(gvisor.dev/issue/4872): Use helper functions to start entry tests in
- // their expected state.
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
- e.mu.Unlock()
+ if err := incompleteToUnreachable(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToUnreachable(...) = %s", err)
+ }
+ if err := unreachableToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unreachableToIncomplete(...) = %s", err)
+ }
+}
- waitFor := c.RetransmitTimer * time.Duration(c.MaxMulticastProbes)
- clock.Advance(waitFor)
+func unreachableToIncomplete(e *neighborEntry, nudDisp *testNUDDispatcher, linkRes *entryTestLinkResolver, clock *faketime.ManualClock) error {
+ if err := func() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if e.mu.neigh.State != Unreachable {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unreachable)
+ }
+ e.handlePacketQueuedLocked(entryTestAddr2)
+ if e.mu.neigh.State != Incomplete {
+ return fmt.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ }
+ return nil
+ }(); err != nil {
+ return err
+ }
+ runImmediatelyScheduledJobs(clock)
wantProbes := []entryTestProbeInfo{
- // The Incomplete-to-Incomplete state transition is tested here by
- // verifying that 3 reachability probes were sent.
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
{
RemoteAddress: entryTestAddr1,
RemoteLinkAddress: tcpip.LinkAddress(""),
@@ -3456,44 +2212,14 @@ func TestEntryUnreachableToIncomplete(t *testing.T) {
}
linkRes.mu.Lock()
diff := cmp.Diff(wantProbes, linkRes.probes)
+ linkRes.probes = nil
linkRes.mu.Unlock()
if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
- }
-
- e.mu.Lock()
- if e.mu.neigh.State != Unreachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unreachable)
- }
- e.mu.Unlock()
-
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
+ return fmt.Errorf("link address resolver probes mismatch (-want, +got):\n%s", diff)
}
- e.mu.Unlock()
wantEvents := []testEntryEventInfo{
{
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Unreachable,
- },
- },
- {
EventType: entryTestChanged,
NICID: entryTestNICID,
Entry: NeighborEntry{
@@ -3503,102 +2229,41 @@ func TestEntryUnreachableToIncomplete(t *testing.T) {
},
},
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ {
+ nudDisp.mu.Lock()
+ diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...)
+ nudDisp.events = nil
+ nudDisp.mu.Unlock()
+ if diff != "" {
+ return fmt.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ }
}
- nudDisp.mu.Unlock()
+ return nil
}
func TestEntryUnreachableToStale(t *testing.T) {
- wantProbes := []entryTestProbeInfo{
- // The Incomplete-to-Incomplete state transition is tested here by
- // verifying that 3 reachability probes were sent.
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- {
- RemoteAddress: entryTestAddr1,
- RemoteLinkAddress: tcpip.LinkAddress(""),
- LocalAddress: entryTestAddr2,
- },
- }
-
c := DefaultNUDConfigurations()
- c.MaxMulticastProbes = uint32(len(wantProbes))
- e, nudDisp, linkRes, clock := entryTestSetup(c)
-
- // TODO(gvisor.dev/issue/4872): Use helper functions to start entry tests in
- // their expected state.
- e.mu.Lock()
- e.handlePacketQueuedLocked(entryTestAddr2)
- if e.mu.neigh.State != Incomplete {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Incomplete)
- }
- e.mu.Unlock()
+ c.MaxMulticastProbes = 3
+ // Eliminate random factors from ReachableTime computation so the transition
+ // from Stale to Reachable will only take BaseReachableTime duration.
+ c.MinRandomFactor = 1
+ c.MaxRandomFactor = 1
- waitFor := c.RetransmitTimer * time.Duration(c.MaxMulticastProbes)
- clock.Advance(waitFor)
+ e, nudDisp, linkRes, clock := entryTestSetup(c)
- linkRes.mu.Lock()
- diff := cmp.Diff(wantProbes, linkRes.probes)
- linkRes.mu.Unlock()
- if diff != "" {
- t.Fatalf("link address resolver probes mismatch (-want, +got):\n%s", diff)
+ if err := unknownToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unknownToIncomplete(...) = %s", err)
}
-
- e.mu.Lock()
- if e.mu.neigh.State != Unreachable {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Unreachable)
+ if err := incompleteToUnreachable(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToUnreachable(...) = %s", err)
}
- e.mu.Unlock()
-
- e.mu.Lock()
- e.handleProbeLocked(entryTestLinkAddr2)
- if e.mu.neigh.State != Stale {
- t.Errorf("got e.mu.neigh.State = %q, want = %q", e.mu.neigh.State, Stale)
+ if err := unreachableToIncomplete(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("unreachableToIncomplete(...) = %s", err)
}
- e.mu.Unlock()
-
- wantEvents := []testEntryEventInfo{
- {
- EventType: entryTestAdded,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Incomplete,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: tcpip.LinkAddress(""),
- State: Unreachable,
- },
- },
- {
- EventType: entryTestChanged,
- NICID: entryTestNICID,
- Entry: NeighborEntry{
- Addr: entryTestAddr1,
- LinkAddr: entryTestLinkAddr2,
- State: Stale,
- },
- },
+ if err := incompleteToReachable(e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("incompleteToReachable(...) = %s", err)
}
- nudDisp.mu.Lock()
- if diff := cmp.Diff(wantEvents, nudDisp.events, eventDiffOpts()...); diff != "" {
- t.Errorf("nud dispatcher events mismatch (-want, +got):\n%s", diff)
+ if err := reachableToStale(c, e, nudDisp, linkRes, clock); err != nil {
+ t.Fatalf("reachableToStale(...) = %s", err)
}
- nudDisp.mu.Unlock()
}