From a7a1f00425c6a742a0c953ae3cb6de513011d41b Mon Sep 17 00:00:00 2001 From: Ghanan Gowripalan Date: Wed, 15 Jan 2020 20:21:20 -0800 Subject: Support upgrading expired/removed IPv6 addresses to permanent SLAAC addresses If a previously added IPv6 address (statically or via SLAAC) was removed, it would be left in an expired state waiting to be cleaned up if any references to it were still held. During this time, the same address could be regenerated via SLAAC, which should be allowed. This change supports this scenario. When upgrading an endpoint from temporary or permanentExpired to permanent, respect the new configuration type (static or SLAAC) and deprecated status, along with the new PrimaryEndpointBehavior (which was already supported). Test: stack.TestAutoGenAddrAfterRemoval PiperOrigin-RevId: 289990168 --- pkg/tcpip/stack/nic.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'pkg/tcpip/stack/nic.go') diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index 1089fdf35..4452a1302 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -202,7 +202,7 @@ func (n *NIC) enable() *tcpip.Error { Address: addr, PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen, }, - }, CanBePrimaryEndpoint); err != nil { + }, CanBePrimaryEndpoint, static, false /* deprecated */); err != nil { return err } } @@ -533,7 +533,12 @@ func (n *NIC) getRefOrCreateTemp(protocol tcpip.NetworkProtocolNumber, address t return ref } -func (n *NIC) addPermanentAddressLocked(protocolAddress tcpip.ProtocolAddress, peb PrimaryEndpointBehavior) (*referencedNetworkEndpoint, *tcpip.Error) { +// addPermanentAddressLocked adds a permanent address to n. +// +// If n already has the address in a non-permanent state, +// addPermanentAddressLocked will promote it to permanent and update the +// endpoint with the properties provided. +func (n *NIC) addPermanentAddressLocked(protocolAddress tcpip.ProtocolAddress, peb PrimaryEndpointBehavior, configType networkEndpointConfigType, deprecated bool) (*referencedNetworkEndpoint, *tcpip.Error) { id := NetworkEndpointID{protocolAddress.AddressWithPrefix.Address} if ref, ok := n.endpoints[id]; ok { switch ref.getKind() { @@ -541,10 +546,14 @@ func (n *NIC) addPermanentAddressLocked(protocolAddress tcpip.ProtocolAddress, p // The NIC already have a permanent endpoint with that address. return nil, tcpip.ErrDuplicateAddress case permanentExpired, temporary: - // Promote the endpoint to become permanent and respect - // the new peb. + // Promote the endpoint to become permanent and respect the new peb, + // configType and deprecated status. if ref.tryIncRef() { + // TODO(b/147748385): Perform Duplicate Address Detection when promoting + // an IPv6 endpoint to permanent. ref.setKind(permanent) + ref.deprecated = deprecated + ref.configType = configType refs := n.primary[ref.protocol] for i, r := range refs { @@ -576,9 +585,13 @@ func (n *NIC) addPermanentAddressLocked(protocolAddress tcpip.ProtocolAddress, p } } - return n.addAddressLocked(protocolAddress, peb, permanent, static, false) + return n.addAddressLocked(protocolAddress, peb, permanent, configType, deprecated) } +// addAddressLocked adds a new protocolAddress to n. +// +// If the address is already known by n (irrespective of the state it is in), +// addAddressLocked does nothing and returns tcpip.ErrDuplicateAddress. func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb PrimaryEndpointBehavior, kind networkEndpointKind, configType networkEndpointConfigType, deprecated bool) (*referencedNetworkEndpoint, *tcpip.Error) { // TODO(b/141022673): Validate IP address before adding them. @@ -653,7 +666,7 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar func (n *NIC) AddAddress(protocolAddress tcpip.ProtocolAddress, peb PrimaryEndpointBehavior) *tcpip.Error { // Add the endpoint. n.mu.Lock() - _, err := n.addPermanentAddressLocked(protocolAddress, peb) + _, err := n.addPermanentAddressLocked(protocolAddress, peb, static, false /* deprecated */) n.mu.Unlock() return err @@ -935,7 +948,7 @@ func (n *NIC) joinGroupLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.A Address: addr, PrefixLen: netProto.DefaultPrefixLen(), }, - }, NeverPrimaryEndpoint); err != nil { + }, NeverPrimaryEndpoint, static, false /* deprecated */); err != nil { return err } } @@ -1313,7 +1326,8 @@ type referencedNetworkEndpoint struct { kind networkEndpointKind // configType is the method that was used to configure this endpoint. - // This must never change after the endpoint is added to a NIC. + // This must never change except during endpoint creation and promotion to + // permanent. configType networkEndpointConfigType // deprecated indicates whether or not the endpoint should be considered -- cgit v1.2.3