summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-09-30 02:50:44 +0000
committergVisor bot <gvisor-bot@google.com>2020-09-30 02:50:44 +0000
commit559d40e7fbc7ad980469df2a44ab36c270880dd2 (patch)
tree231653b6e08db75e039c4aaf72dd138d1a2689a9 /pkg/tcpip/stack
parent9fd0394592b2ad55898755f8b5b98fe425239c32 (diff)
parente5ece9aea730c105ab336e6bd2858322686a5708 (diff)
Merge release-20200921.0-76-ge5ece9aea (automated)
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r--pkg/tcpip/stack/addressable_endpoint_state.go111
-rw-r--r--pkg/tcpip/stack/nic.go22
-rw-r--r--pkg/tcpip/stack/registration.go13
3 files changed, 93 insertions, 53 deletions
diff --git a/pkg/tcpip/stack/addressable_endpoint_state.go b/pkg/tcpip/stack/addressable_endpoint_state.go
index 270ac4977..db8ac1c2b 100644
--- a/pkg/tcpip/stack/addressable_endpoint_state.go
+++ b/pkg/tcpip/stack/addressable_endpoint_state.go
@@ -412,6 +412,60 @@ func (a *AddressableEndpointState) decAddressRefLocked(addrState *addressState)
a.releaseAddressStateLocked(addrState)
}
+// MainAddress implements AddressableEndpoint.
+func (a *AddressableEndpointState) MainAddress() tcpip.AddressWithPrefix {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+
+ ep := a.acquirePrimaryAddressRLocked(func(ep *addressState) bool {
+ return ep.GetKind() == Permanent
+ })
+ if ep == nil {
+ return tcpip.AddressWithPrefix{}
+ }
+
+ addr := ep.AddressWithPrefix()
+ a.decAddressRefLocked(ep)
+ return addr
+}
+
+// acquirePrimaryAddressRLocked returns an acquired primary address that is
+// valid according to isValid.
+//
+// Precondition: e.mu must be read locked
+func (a *AddressableEndpointState) acquirePrimaryAddressRLocked(isValid func(*addressState) bool) *addressState {
+ var deprecatedEndpoint *addressState
+ for _, ep := range a.mu.primary {
+ if !isValid(ep) {
+ continue
+ }
+
+ if !ep.Deprecated() {
+ if ep.IncRef() {
+ // ep is not deprecated, so return it immediately.
+ //
+ // If we kept track of a deprecated endpoint, decrement its reference
+ // count since it was incremented when we decided to keep track of it.
+ if deprecatedEndpoint != nil {
+ a.decAddressRefLocked(deprecatedEndpoint)
+ deprecatedEndpoint = nil
+ }
+
+ return ep
+ }
+ } else if deprecatedEndpoint == nil && ep.IncRef() {
+ // We prefer an endpoint that is not deprecated, but we keep track of
+ // ep in case a doesn't have any non-deprecated endpoints.
+ //
+ // If we end up finding a more preferred endpoint, ep's reference count
+ // will be decremented.
+ deprecatedEndpoint = ep
+ }
+ }
+
+ return deprecatedEndpoint
+}
+
// AcquireAssignedAddress implements AddressableEndpoint.
func (a *AddressableEndpointState) AcquireAssignedAddress(localAddr tcpip.Address, allowTemp bool, tempPEB PrimaryEndpointBehavior) AddressEndpoint {
a.mu.Lock()
@@ -461,47 +515,34 @@ func (a *AddressableEndpointState) AcquireAssignedAddress(localAddr tcpip.Addres
return ep
}
-// AcquirePrimaryAddress implements AddressableEndpoint.
-func (a *AddressableEndpointState) AcquirePrimaryAddress(remoteAddr tcpip.Address, allowExpired bool) AddressEndpoint {
+// AcquireOutgoingPrimaryAddress implements AddressableEndpoint.
+func (a *AddressableEndpointState) AcquireOutgoingPrimaryAddress(remoteAddr tcpip.Address, allowExpired bool) AddressEndpoint {
a.mu.RLock()
defer a.mu.RUnlock()
- var deprecatedEndpoint *addressState
- for _, ep := range a.mu.primary {
- if !ep.IsAssigned(allowExpired) {
- continue
- }
-
- if !ep.Deprecated() {
- if ep.IncRef() {
- // ep is not deprecated, so return it immediately.
- //
- // If we kept track of a deprecated endpoint, decrement its reference
- // count since it was incremented when we decided to keep track of it.
- if deprecatedEndpoint != nil {
- a.decAddressRefLocked(deprecatedEndpoint)
- deprecatedEndpoint = nil
- }
-
- return ep
- }
- } else if deprecatedEndpoint == nil && ep.IncRef() {
- // We prefer an endpoint that is not deprecated, but we keep track of
- // ep in case a doesn't have any non-deprecated endpoints.
- //
- // If we end up finding a more preferred endpoint, ep's reference count
- // will be decremented.
- deprecatedEndpoint = ep
- }
- }
+ ep := a.acquirePrimaryAddressRLocked(func(ep *addressState) bool {
+ return ep.IsAssigned(allowExpired)
+ })
- // a doesn't have any valid non-deprecated endpoints, so return
- // deprecatedEndpoint (which may be nil if a doesn't have any valid deprecated
- // endpoints either).
- if deprecatedEndpoint == nil {
+ // From https://golang.org/doc/faq#nil_error:
+ //
+ // Under the covers, interfaces are implemented as two elements, a type T and
+ // a value V.
+ //
+ // An interface value is nil only if the V and T are both unset, (T=nil, V is
+ // not set), In particular, a nil interface will always hold a nil type. If we
+ // store a nil pointer of type *int inside an interface value, the inner type
+ // will be *int regardless of the value of the pointer: (T=*int, V=nil). Such
+ // an interface value will therefore be non-nil even when the pointer value V
+ // inside is nil.
+ //
+ // Since acquirePrimaryAddressRLocked returns a nil value with a non-nil type,
+ // we need to explicitly return nil below if ep is (a typed) nil.
+ if ep == nil {
return nil
}
- return deprecatedEndpoint
+
+ return ep
}
// PrimaryAddresses implements AddressableEndpoint.
diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go
index 212c6edae..23022292c 100644
--- a/pkg/tcpip/stack/nic.go
+++ b/pkg/tcpip/stack/nic.go
@@ -244,22 +244,19 @@ func (n *NIC) setSpoofing(enable bool) {
n.mu.Unlock()
}
-// primaryEndpoint will return the first non-deprecated endpoint if such an
-// endpoint exists for the given protocol and remoteAddr. If no non-deprecated
-// endpoint exists, the first deprecated endpoint will be returned.
-//
-// If an IPv6 primary endpoint is requested, Source Address Selection (as
-// defined by RFC 6724 section 5) will be performed.
+// primaryAddress returns an address that can be used to communicate with
+// remoteAddr.
func (n *NIC) primaryEndpoint(protocol tcpip.NetworkProtocolNumber, remoteAddr tcpip.Address) AssignableAddressEndpoint {
n.mu.RLock()
- defer n.mu.RUnlock()
+ spoofing := n.mu.spoofing
+ n.mu.RUnlock()
ep, ok := n.networkEndpoints[protocol]
if !ok {
return nil
}
- return ep.AcquirePrimaryAddress(remoteAddr, n.mu.spoofing)
+ return ep.AcquireOutgoingPrimaryAddress(remoteAddr, spoofing)
}
type getAddressBehaviour int
@@ -360,13 +357,12 @@ func (n *NIC) primaryAddresses() []tcpip.ProtocolAddress {
// address exists. If no non-deprecated address exists, the first deprecated
// address will be returned.
func (n *NIC) primaryAddress(proto tcpip.NetworkProtocolNumber) tcpip.AddressWithPrefix {
- addressEndpoint := n.primaryEndpoint(proto, "")
- if addressEndpoint == nil {
+ ep, ok := n.networkEndpoints[proto]
+ if !ok {
return tcpip.AddressWithPrefix{}
}
- addr := addressEndpoint.AddressWithPrefix()
- addressEndpoint.DecRef()
- return addr
+
+ return ep.MainAddress()
}
// removeAddress removes an address from n.
diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go
index 567e1904e..b6f823b54 100644
--- a/pkg/tcpip/stack/registration.go
+++ b/pkg/tcpip/stack/registration.go
@@ -435,7 +435,10 @@ type AddressableEndpoint interface {
// permanent address.
RemovePermanentAddress(addr tcpip.Address) *tcpip.Error
- // AcquireAssignedAddress returns an AddressEndpoint for the passed address
+ // MainAddress returns the endpoint's primary permanent address.
+ MainAddress() tcpip.AddressWithPrefix
+
+ // AcquireAssignedAddress returns an address endpoint for the passed address
// that is considered bound to the endpoint, optionally creating a temporary
// endpoint if requested and no existing address exists.
//
@@ -444,15 +447,15 @@ type AddressableEndpoint interface {
// Returns nil if the specified address is not local to this endpoint.
AcquireAssignedAddress(localAddr tcpip.Address, allowTemp bool, tempPEB PrimaryEndpointBehavior) AddressEndpoint
- // AcquirePrimaryAddress returns a primary endpoint to use when communicating
- // with the passed remote address.
+ // AcquireOutgoingPrimaryAddress returns a primary address that may be used as
+ // a source address when sending packets to the passed remote address.
//
// If allowExpired is true, expired addresses may be returned.
//
// The returned endpoint's reference count is incremented.
//
- // Returns nil if a primary endpoint is not available.
- AcquirePrimaryAddress(remoteAddr tcpip.Address, allowExpired bool) AddressEndpoint
+ // Returns nil if a primary address is not available.
+ AcquireOutgoingPrimaryAddress(remoteAddr tcpip.Address, allowExpired bool) AddressEndpoint
// PrimaryAddresses returns the primary addresses.
PrimaryAddresses() []tcpip.AddressWithPrefix