Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix IPv6 validation when VM gets route advertisements
For unknown reasons right now, on 456.x stemcells, the VM was not
receiving route advertisements, or was not assigning ipv6 addresses
received via the route advertiser. On newer stemcells, this was
happening and led to interfaces like eth1 having multiple IP addresses.

This broke in two places:
* arping: this does not exist for ipv6 and the replacement is ndp
(neighbor discovery protocol). For this commit, just ignore ipv6
addresses
* ip addr validation: bosh-agent validates that the IP assigned by the
bosh-director is actually configured on an interface. The previous logic
used the first address configured on the interface instead of
enumerating through all addresses. An example error message from
`/var/vcap/bosh/log/current`:

```
Validating network interface 'eth1' IP addresses, expected: '2601:0646:0100:69f5:0000:0000:0000:0001', actual: '2601:0646:0100:69f5:0102:03ff:fe04:0506'
```

While `ip a` would show something like:

```
1: eth1: ...
    link/ether ...
    inet6 2601:0646:0100:69f5:0102:03ff:fe04:0506/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591996sec preferred_lft 604796sec
    inet6 2601:0646:0100:69f5:0000:0000:0000:0001/64 scope global temporary dynamic
       valid_lft 588658sec preferred_lft 70072sec

```

Here, the bosh-agent only used the first entry as the "actual assigned
IP", which is incorrect.

[#169694744](https://www.pivotaltracker.com/story/show/169694744)

Co-authored-by: Brian Cunnie <bcunnie@pivotal.io>
  • Loading branch information
Aakash Shah and cunnie committed Dec 20, 2019
1 parent 21ec069 commit 7864a59
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 21 deletions.
11 changes: 11 additions & 0 deletions platform/net/arp/arping.go
@@ -1,6 +1,7 @@
package arp

import (
"net"
"path"
"sync"
"time"
Expand Down Expand Up @@ -47,6 +48,16 @@ func (a arping) BroadcastMACAddresses(addresses []boship.InterfaceAddress) {
var wg sync.WaitGroup

for _, addr := range addresses {
ip, err := addr.GetIP()
if err != nil {
continue
}

formattedIP := net.ParseIP(ip)
if formattedIP.To4() == nil {
continue
}

wg.Add(1) // Outside of goroutine

go func(address boship.InterfaceAddress) {
Expand Down
9 changes: 9 additions & 0 deletions platform/net/arp/arping_test.go
Expand Up @@ -79,5 +79,14 @@ var _ = Describe("arping", func() {
arping.BroadcastMACAddresses(addresses)
Expect(cmdRunner.RunCommands).To(BeEmpty())
})

It("ignores ipv6 addresses", func() {
addresses := []boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "fe80::"),
}

arping.BroadcastMACAddresses(addresses)
Expect(len(cmdRunner.RunCommands)).To(Equal(0))
})
})
})
25 changes: 17 additions & 8 deletions platform/net/ip/interface_addresses_validator.go
@@ -1,6 +1,8 @@
package ip

import (
"strings"

bosherr "github.com/cloudfoundry/bosh-utils/errors"
)

Expand All @@ -27,28 +29,35 @@ func (i *interfaceAddressesValidator) Validate(desiredInterfaceAddresses []Inter
for _, desiredInterfaceAddress := range desiredInterfaceAddresses {
ifaceName := desiredInterfaceAddress.GetInterfaceName()

iface, found := i.findInterfaceByName(ifaceName, systemInterfaceAddresses)
if !found {
ifaces := i.findInterfaceByName(ifaceName, systemInterfaceAddresses)
if len(ifaces) == 0 {
return bosherr.Errorf("Validating network interface '%s' IP addresses, no interface configured with that name", ifaceName)
}

actualIPs := []string{}
desiredIP, _ := desiredInterfaceAddress.GetIP()
actualIP, _ := iface.GetIP()
for _, iface := range ifaces {
actualIP, _ := iface.GetIP()

if desiredIP != actualIP {
return bosherr.Errorf("Validating network interface '%s' IP addresses, expected: '%s', actual: '%s'", ifaceName, desiredIP, actualIP)
if desiredIP == actualIP {
return nil
}
actualIPs = append(actualIPs, actualIP)
}

return bosherr.Errorf("Validating network interface '%s' IP addresses, expected: '%s', actual: [%s]", ifaceName, desiredIP, strings.Join(actualIPs, ", "))
}

return nil
}

func (i *interfaceAddressesValidator) findInterfaceByName(ifaceName string, ifaces []InterfaceAddress) (InterfaceAddress, bool) {
func (i *interfaceAddressesValidator) findInterfaceByName(ifaceName string, ifaces []InterfaceAddress) []InterfaceAddress {
result := []InterfaceAddress{}
for _, iface := range ifaces {
if iface.GetInterfaceName() == ifaceName {
return iface, true
result = append(result, iface)
}
}

return nil, false
return result
}
31 changes: 18 additions & 13 deletions platform/net/ip/interface_addresses_validator_test.go
Expand Up @@ -32,7 +32,22 @@ var _ = Describe("InterfaceAddressesValidator", func() {
It("returns nil", func() {
err := interfaceAddrsValidator.Validate([]boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "1.2.3.4"),
boship.NewSimpleInterfaceAddress("eth1", "5.6.7.8"),
})
Expect(err).ToNot(HaveOccurred())
})
})

Context("when an interface has multiple IPs", func() {
BeforeEach(func() {
interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "1.2.3.4"),
boship.NewSimpleInterfaceAddress("eth0", "fe80::1"),
}
})

It("returns nil", func() {
err := interfaceAddrsValidator.Validate([]boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "fe80::1"),
})
Expect(err).ToNot(HaveOccurred())
})
Expand All @@ -42,6 +57,7 @@ var _ = Describe("InterfaceAddressesValidator", func() {
BeforeEach(func() {
interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "1.2.3.5"),
boship.NewSimpleInterfaceAddress("eth0", "1.2.3.6"),
}
})

Expand All @@ -50,7 +66,7 @@ var _ = Describe("InterfaceAddressesValidator", func() {
boship.NewSimpleInterfaceAddress("eth0", "1.2.3.4"),
})
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("Validating network interface 'eth0' IP addresses, expected: '1.2.3.4', actual: '1.2.3.5'"))
Expect(err.Error()).To(ContainSubstring("Validating network interface 'eth0' IP addresses, expected: '1.2.3.4', actual: [1.2.3.5, 1.2.3.6]"))
})
})

Expand Down Expand Up @@ -83,15 +99,4 @@ var _ = Describe("InterfaceAddressesValidator", func() {
Expect(err.Error()).To(ContainSubstring("Validating network interface 'eth0' IP addresses, no interface configured with that name"))
})
})

Context("when resolv.conf has valid dns configurations", func() {
It("fails", func() {

})

})

Context("when resolv.conf has invalid dns configurations", func() {

})
})

0 comments on commit 7864a59

Please sign in to comment.