diff options
-rw-r--r-- | pkg/tcpip/stack/neighbor_cache.go | 10 | ||||
-rw-r--r-- | pkg/tcpip/stack/neighbor_entry.go | 57 | ||||
-rw-r--r-- | pkg/tcpip/stack/neighborstate_string.go | 7 |
3 files changed, 51 insertions, 23 deletions
diff --git a/pkg/tcpip/stack/neighbor_cache.go b/pkg/tcpip/stack/neighbor_cache.go index a77fe575a..533287c4c 100644 --- a/pkg/tcpip/stack/neighbor_cache.go +++ b/pkg/tcpip/stack/neighbor_cache.go @@ -25,9 +25,13 @@ const neighborCacheSize = 512 // max entries per interface // NeighborStats holds metrics for the neighbor table. type NeighborStats struct { - // FailedEntryLookups counts the number of lookups performed on an entry in - // Failed state. + // FailedEntryLookups is deprecated; UnreachableEntryLookups should be used + // instead. FailedEntryLookups *tcpip.StatCounter + + // UnreachableEntryLookups counts the number of lookups performed on an + // entry in Unreachable state. + UnreachableEntryLookups *tcpip.StatCounter } // neighborCache maps IP addresses to link addresses. It uses the Least @@ -143,7 +147,7 @@ func (n *neighborCache) entry(remoteAddr, localAddr tcpip.Address, onResolve fun onResolve(LinkResolutionResult{LinkAddress: entry.mu.neigh.LinkAddr, Success: true}) } return entry.mu.neigh, nil, nil - case Unknown, Incomplete, Failed: + case Unknown, Incomplete, Unreachable: if onResolve != nil { entry.mu.onResolve = append(entry.mu.onResolve, onResolve) } diff --git a/pkg/tcpip/stack/neighbor_entry.go b/pkg/tcpip/stack/neighbor_entry.go index 4ed149ee8..03fef52ee 100644 --- a/pkg/tcpip/stack/neighbor_entry.go +++ b/pkg/tcpip/stack/neighbor_entry.go @@ -38,7 +38,8 @@ type NeighborEntry struct { } // NeighborState defines the state of a NeighborEntry within the Neighbor -// Unreachability Detection state machine, as per RFC 4861 section 7.3.2. +// Unreachability Detection state machine, as per RFC 4861 section 7.3.2 and +// RFC 7048. type NeighborState uint8 const ( @@ -61,13 +62,24 @@ const ( Delay // Probe means a reachability confirmation is actively being sought by // periodically retransmitting reachability probes until a reachability - // confirmation is received, or until the max amount of probes has been sent. + // confirmation is received, or until the maximum number of probes has been + // sent. Probe // Static describes entries that have been explicitly added by the user. They // do not expire and are not deleted until explicitly removed. Static - // Failed means recent attempts of reachability have returned inconclusive. + // Failed is deprecated and should no longer be used. + // + // TODO(gvisor.dev/issue/4667): Remove this once all references to Failed + // are removed from Fuchsia. Failed + // Unreachable means reachability confirmation failed; the maximum number of + // reachability probes has been sent and no replies have been received. + // + // TODO(gvisor.dev/issue/5472): Add the following sentence when we implement + // RFC 7048: "Packets continue to be sent to the neighbor while + // re-attempting to resolve the address." + Unreachable ) type timer struct { @@ -310,8 +322,8 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { } if timedoutResolution || err != nil { - e.dispatchRemoveEventLocked() - e.setStateLocked(Failed) + e.setStateLocked(Unreachable) + e.dispatchChangeEventLocked() return } @@ -320,7 +332,7 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { }), } - case Failed: + case Unreachable: e.notifyCompletionLocked(false /* succeeded */) case Unknown, Stale, Static: @@ -339,15 +351,19 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { // Precondition: e.mu MUST be locked. func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) { switch e.mu.neigh.State { - case Failed: - e.cache.nic.stats.Neighbor.FailedEntryLookups.Increment() - - fallthrough - case Unknown: + case Unknown, Unreachable: + prev := e.mu.neigh.State e.mu.neigh.State = Incomplete e.mu.neigh.UpdatedAtNanos = e.cache.nic.stack.clock.NowNanoseconds() - e.dispatchAddEventLocked() + switch prev { + case Unknown: + e.dispatchAddEventLocked() + case Unreachable: + e.dispatchChangeEventLocked() + e.cache.nic.stats.Neighbor.UnreachableEntryLookups.Increment() + } + config := e.nudState.Config() // Protected by e.mu. @@ -385,8 +401,8 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) { } if timedoutResolution || err != nil { - e.dispatchRemoveEventLocked() - e.setStateLocked(Failed) + e.setStateLocked(Unreachable) + e.dispatchChangeEventLocked() return } @@ -418,7 +434,7 @@ func (e *neighborEntry) handleProbeLocked(remoteLinkAddr tcpip.LinkAddress) { // checks MUST be done by the NetworkEndpoint. switch e.mu.neigh.State { - case Unknown, Failed: + case Unknown: e.mu.neigh.LinkAddr = remoteLinkAddr e.setStateLocked(Stale) e.dispatchAddEventLocked() @@ -447,6 +463,13 @@ func (e *neighborEntry) handleProbeLocked(remoteLinkAddr tcpip.LinkAddress) { e.dispatchChangeEventLocked() } + case Unreachable: + // TODO(gvisor.dev/issue/5472): Do not change the entry if the link + // address is the same, as per RFC 7048. + e.mu.neigh.LinkAddr = remoteLinkAddr + e.setStateLocked(Stale) + e.dispatchChangeEventLocked() + case Static: // Do nothing @@ -549,7 +572,7 @@ func (e *neighborEntry) handleConfirmationLocked(linkAddr tcpip.LinkAddress, fla } e.mu.isRouter = flags.IsRouter - case Unknown, Failed, Static: + case Unknown, Unreachable, Static: // Do nothing default: @@ -571,7 +594,7 @@ func (e *neighborEntry) handleUpperLevelConfirmationLocked() { e.dispatchChangeEventLocked() } - case Unknown, Incomplete, Failed, Static: + case Unknown, Incomplete, Unreachable, Static: // Do nothing default: diff --git a/pkg/tcpip/stack/neighborstate_string.go b/pkg/tcpip/stack/neighborstate_string.go index aa7311ec6..765df4d7a 100644 --- a/pkg/tcpip/stack/neighborstate_string.go +++ b/pkg/tcpip/stack/neighborstate_string.go @@ -1,4 +1,4 @@ -// Copyright 2020 The gVisor Authors. +// Copyright 2021 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,11 +30,12 @@ func _() { _ = x[Probe-5] _ = x[Static-6] _ = x[Failed-7] + _ = x[Unreachable-8] } -const _NeighborState_name = "UnknownIncompleteReachableStaleDelayProbeStaticFailed" +const _NeighborState_name = "UnknownIncompleteReachableStaleDelayProbeStaticFailedUnreachable" -var _NeighborState_index = [...]uint8{0, 7, 17, 26, 31, 36, 41, 47, 53} +var _NeighborState_index = [...]uint8{0, 7, 17, 26, 31, 36, 41, 47, 53, 64} func (i NeighborState) String() string { if i >= NeighborState(len(_NeighborState_index)-1) { |