Skip to content

Commit

Permalink
Prefer IPv4 addresses in the select address functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Foord committed Sep 28, 2016
1 parent 543e35d commit c364359
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 15 deletions.
23 changes: 20 additions & 3 deletions network/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,14 @@ func PrioritizeInternalHostPorts(hps []HostPort, machineLocal bool) []string {
func publicMatch(addr Address) scopeMatch {
switch addr.Scope {
case ScopePublic:
if addr.Type == IPv4Address {
return exactScopeIPv4
}
return exactScope
case ScopeCloudLocal, ScopeUnknown:
if addr.Type == IPv4Address {
return fallbackScopeIPv4
}
return fallbackScope
}
return invalidScope
Expand All @@ -453,15 +459,24 @@ func internalAddressMatcher(machineLocal bool) scopeMatchFunc {
func cloudLocalMatch(addr Address) scopeMatch {
switch addr.Scope {
case ScopeCloudLocal:
if addr.Type == IPv4Address {
return exactScopeIPv4
}
return exactScope
case ScopePublic, ScopeUnknown:
if addr.Type == IPv4Address {
return fallbackScopeIPv4
}
return fallbackScope
}
return invalidScope
}

func cloudOrMachineLocalMatch(addr Address) scopeMatch {
if addr.Scope == ScopeMachineLocal {
if addr.Type == IPv4Address {
return exactScopeIPv4
}
return exactScope
}
return cloudLocalMatch(addr)
Expand All @@ -471,7 +486,9 @@ type scopeMatch int

const (
invalidScope scopeMatch = iota
exactScopeIPv4
exactScope
fallbackScopeIPv4
fallbackScope
)

Expand All @@ -498,7 +515,7 @@ func bestAddressIndexes(numAddr int, getAddrFunc addressByIndexFunc, matchFunc s
matches := filterAndCollateAddressIndexes(numAddr, getAddrFunc, matchFunc)

// Retrieve the indexes of the addresses with the best scope and type match.
allowedMatchTypes := []scopeMatch{exactScope, fallbackScope}
allowedMatchTypes := []scopeMatch{exactScopeIPv4, exactScope, fallbackScopeIPv4, fallbackScope}
for _, matchType := range allowedMatchTypes {
indexes, ok := matches[matchType]
if ok && len(indexes) > 0 {
Expand All @@ -513,7 +530,7 @@ func prioritizedAddressIndexes(numAddr int, getAddrFunc addressByIndexFunc, matc
matches := filterAndCollateAddressIndexes(numAddr, getAddrFunc, matchFunc)

// Retrieve the indexes of the addresses with the best scope and type match.
allowedMatchTypes := []scopeMatch{exactScope, fallbackScope}
allowedMatchTypes := []scopeMatch{exactScopeIPv4, exactScope, fallbackScopeIPv4, fallbackScope}
var prioritized []int
for _, matchType := range allowedMatchTypes {
indexes, ok := matches[matchType]
Expand All @@ -530,7 +547,7 @@ func filterAndCollateAddressIndexes(numAddr int, getAddrFunc addressByIndexFunc,
for i := 0; i < numAddr; i++ {
matchType := matchFunc(getAddrFunc(i))
switch matchType {
case exactScope, fallbackScope:
case exactScopeIPv4, exactScope, fallbackScopeIPv4, fallbackScope:
matches[matchType] = append(matches[matchType], i)
}
}
Expand Down
64 changes: 52 additions & 12 deletions network/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,22 @@ var selectPublicTests = []selectTest{{
},
0,
}, {
"first public address is picked when both public IPs and public hostnames exist",
"public IP address is picked when both public IPs and public hostnames exist",
[]network.Address{
network.NewScopedAddress("10.0.0.1", network.ScopeUnknown),
network.NewScopedAddress("example.com", network.ScopePublic),
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
},
2,
}, {
"hostname is picked over cloud local address",
[]network.Address{
network.NewScopedAddress("10.0.0.1", network.ScopeUnknown),
network.NewScopedAddress("example.com", network.ScopePublic),
},
1,
}, {
"IPv4 preferred over IPv",
"IPv4 preferred over IPv6",
[]network.Address{
network.NewScopedAddress("2001:db8::1", network.ScopePublic),
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
Expand Down Expand Up @@ -405,7 +412,6 @@ var selectInternalTests = []selectTest{{
network.NewScopedAddress("2001:db8::1", network.ScopePublic),
network.NewScopedAddress("fc00::1", network.ScopeCloudLocal),
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
network.NewScopedAddress("10.0.0.1", network.ScopeCloudLocal),
},
1,
}, {
Expand All @@ -414,7 +420,6 @@ var selectInternalTests = []selectTest{{
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
network.NewScopedAddress("2001:db8::1", network.ScopePublic),
network.NewScopedAddress("fc00::1", network.ScopeCloudLocal),
network.NewScopedAddress("10.0.0.1", network.ScopeCloudLocal),
},
2,
}}
Expand All @@ -430,13 +435,21 @@ func (s *AddressSuite) TestSelectInternalAddress(c *gc.C) {
}

var selectInternalMachineTests = []selectTest{{
"first cloud local address is selected",
"first cloud local IPv4 address is selected",
[]network.Address{
network.NewScopedAddress("fc00::1", network.ScopeCloudLocal),
network.NewScopedAddress("2001:db8::1", network.ScopePublic),
network.NewScopedAddress("10.0.0.1", network.ScopeCloudLocal),
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
},
2,
}, {
"first cloud local address is selected",
[]network.Address{
network.NewScopedAddress("fc00::1", network.ScopeCloudLocal),
network.NewScopedAddress("2001:db8::1", network.ScopePublic),
network.NewScopedAddress("8.8.8.8", network.ScopePublic),
},
0,
}, {
"first cloud local hostname is selected",
Expand All @@ -455,7 +468,7 @@ var selectInternalMachineTests = []selectTest{{
},
0,
}, {
"first machine local address is selected even with public/cloud hostnames",
"first machine local IPv4 address is selected even with public/cloud hostnames",
[]network.Address{
network.NewScopedAddress("public.example.com", network.ScopePublic),
network.NewScopedAddress("::1", network.ScopeMachineLocal),
Expand All @@ -465,9 +478,19 @@ var selectInternalMachineTests = []selectTest{{
network.NewScopedAddress("fe80::1", network.ScopeLinkLocal),
network.NewScopedAddress("127.0.0.2", network.ScopeMachineLocal),
},
4,
}, {
"first machine local non-IPv4 address is selected even with public/cloud hostnames",
[]network.Address{
network.NewScopedAddress("public.example.com", network.ScopePublic),
network.NewScopedAddress("::1", network.ScopeMachineLocal),
network.NewScopedAddress("unknown.example.com", network.ScopeUnknown),
network.NewScopedAddress("cloud.internal", network.ScopeCloudLocal),
network.NewScopedAddress("fe80::1", network.ScopeLinkLocal),
},
1,
}, {
"first cloud local hostname is selected even with other machine/cloud addresses",
"cloud local IPv4 is selected even with other machine/cloud addresses",
[]network.Address{
network.NewScopedAddress("169.254.1.1", network.ScopeLinkLocal),
network.NewScopedAddress("cloud-unknown.internal", network.ScopeUnknown),
Expand All @@ -476,6 +499,15 @@ var selectInternalMachineTests = []selectTest{{
network.NewScopedAddress("127.0.0.1", network.ScopeMachineLocal),
network.NewScopedAddress("127.0.0.2", network.ScopeMachineLocal),
},
4,
}, {
"first cloud local hostname is selected even with other machine/cloud addresses",
[]network.Address{
network.NewScopedAddress("169.254.1.1", network.ScopeLinkLocal),
network.NewScopedAddress("cloud-unknown.internal", network.ScopeUnknown),
network.NewScopedAddress("cloud-local.internal", network.ScopeCloudLocal),
network.NewScopedAddress("fc00::1", network.ScopeCloudLocal),
},
2,
}}

Expand Down Expand Up @@ -506,7 +538,7 @@ var selectInternalHostPortsTests = []selectInternalHostPortsTest{{
},
[]string{"8.8.8.8:9999"},
}, {
"a cloud local IPv4 addresses are selected",
"cloud local IPv4 addresses are selected",
[]network.HostPort{
{network.NewScopedAddress("10.1.0.1", network.ScopeCloudLocal), 8888},
{network.NewScopedAddress("8.8.8.8", network.ScopePublic), 123},
Expand All @@ -522,14 +554,22 @@ var selectInternalHostPortsTests = []selectInternalHostPortsTest{{
},
[]string{},
}, {
"cloud local addresses are preferred to a public addresses",
"cloud local IPv4 addresses are preferred to a public addresses",
[]network.HostPort{
{network.NewScopedAddress("2001:db8::1", network.ScopePublic), 123},
{network.NewScopedAddress("fc00::1", network.ScopeCloudLocal), 123},
{network.NewScopedAddress("8.8.8.8", network.ScopePublic), 123},
{network.NewScopedAddress("10.0.0.1", network.ScopeCloudLocal), 4444},
},
[]string{"[fc00::1]:123", "10.0.0.1:4444"},
[]string{"10.0.0.1:4444"},
}, {
"cloud local IPv6 addresses are preferred to a public addresses",
[]network.HostPort{
{network.NewScopedAddress("2001:db8::1", network.ScopePublic), 123},
{network.NewScopedAddress("fc00::1", network.ScopeCloudLocal), 123},
{network.NewScopedAddress("8.8.8.8", network.ScopePublic), 123},
},
[]string{"[fc00::1]:123"},
}}

func (s *AddressSuite) TestSelectInternalHostPorts(c *gc.C) {
Expand All @@ -550,7 +590,7 @@ var prioritizeInternalHostPortsTests = []selectInternalHostPortsTest{{
},
[]string{"8.8.8.8:9999"},
}, {
"a cloud local IPv4 addresses are selected",
"cloud local IPv4 addresses are selected",
[]network.HostPort{
{network.NewScopedAddress("10.1.0.1", network.ScopeCloudLocal), 8888},
{network.NewScopedAddress("8.8.8.8", network.ScopePublic), 123},
Expand All @@ -573,7 +613,7 @@ var prioritizeInternalHostPortsTests = []selectInternalHostPortsTest{{
{network.NewScopedAddress("8.8.8.8", network.ScopePublic), 123},
{network.NewScopedAddress("10.0.0.1", network.ScopeCloudLocal), 4444},
},
[]string{"[fc00::1]:123", "10.0.0.1:4444", "[2001:db8::1]:123", "8.8.8.8:123"},
[]string{"10.0.0.1:4444", "[fc00::1]:123", "8.8.8.8:123", "[2001:db8::1]:123"},
}}

func (s *AddressSuite) TestPrioritizeInternalHostPorts(c *gc.C) {
Expand Down

0 comments on commit c364359

Please sign in to comment.