diff options
author | gVisor bot <gvisor-bot@google.com> | 2020-09-30 02:50:44 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-09-30 02:50:44 +0000 |
commit | 559d40e7fbc7ad980469df2a44ab36c270880dd2 (patch) | |
tree | 231653b6e08db75e039c4aaf72dd138d1a2689a9 /pkg/tcpip/stack | |
parent | 9fd0394592b2ad55898755f8b5b98fe425239c32 (diff) | |
parent | e5ece9aea730c105ab336e6bd2858322686a5708 (diff) |
Merge release-20200921.0-76-ge5ece9aea (automated)
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r-- | pkg/tcpip/stack/addressable_endpoint_state.go | 111 | ||||
-rw-r--r-- | pkg/tcpip/stack/nic.go | 22 | ||||
-rw-r--r-- | pkg/tcpip/stack/registration.go | 13 |
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 |