Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align IP selection behavior with kernel #22866

Merged
merged 2 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 37 additions & 27 deletions pkg/node/address_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package node

import (
"bytes"
"fmt"
"net"
"sort"
Expand Down Expand Up @@ -47,28 +46,37 @@ retryInterface:
}

retryScope:
ipsPublic := []net.IP{}
ipsPrivate := []net.IP{}
ipsPublic := []netlink.Addr{}
ipsPrivate := []netlink.Addr{}
hasPreferred := false

for _, a := range addr {
if a.Scope <= linkScopeMax {
if ip.ListContainsIP(ipsToExclude, a.IP) {
continue
}
if len(a.IP) >= ipLen {
if ip.IsPublicAddr(a.IP) {
ipsPublic = append(ipsPublic, a.IP)
} else {
ipsPrivate = append(ipsPrivate, a.IP)
}
// If the IP is the same as the preferredIP, that
// means that maybe it is restored from node_config.h,
// so if it is present we prefer this one.
if a.IP.Equal(preferredIP) {
hasPreferred = true
}
}
if a.Scope > linkScopeMax {
continue
}
if ip.ListContainsIP(ipsToExclude, a.IP) {
continue
}
if len(a.IP) < ipLen {
continue
}
isPreferredIP := a.IP.Equal(preferredIP)
if a.Flags&unix.IFA_F_SECONDARY > 0 && !isPreferredIP {
// Skip secondary addresses if they're not the preferredIP
continue
}

if ip.IsPublicAddr(a.IP) {
ipsPublic = append(ipsPublic, a)
} else {
ipsPrivate = append(ipsPrivate, a)
}
// If the IP is the same as the preferredIP, that
// means that maybe it is restored from node_config.h,
// so if it is present we prefer this one, even if it
// is a secondary address.
if isPreferredIP {
hasPreferred = true
}
}

Expand All @@ -83,11 +91,11 @@ retryScope:

// Just make sure that we always return the same one and not a
// random one. More info in the issue GH-7637.
sort.Slice(ipsPublic, func(i, j int) bool {
return bytes.Compare(ipsPublic[i], ipsPublic[j]) < 0
sort.SliceStable(ipsPublic, func(i, j int) bool {
return ipsPublic[i].LinkIndex < ipsPublic[j].LinkIndex
})

return ipsPublic[0], nil
return ipsPublic[0].IP, nil
}

if len(ipsPrivate) != 0 {
Expand All @@ -96,11 +104,11 @@ retryScope:
}

// Same stable order, see above ipsPublic.
sort.Slice(ipsPrivate, func(i, j int) bool {
return bytes.Compare(ipsPrivate[i], ipsPrivate[j]) < 0
sort.SliceStable(ipsPrivate, func(i, j int) bool {
return ipsPrivate[i].LinkIndex < ipsPrivate[j].LinkIndex
})

return ipsPrivate[0], nil
return ipsPrivate[0].IP, nil
}

// First, if a device is specified, fall back to anything wider
Expand All @@ -123,7 +131,9 @@ retryScope:
}

// firstGlobalV4Addr returns the first IPv4 global IP of an interface,
// where the IPs are sorted in ascending order.
// where the IPs are sorted in creation order (oldest to newest).
//
// All secondary IPs, except the preferredIP, are filtered out.
//
// Public IPs are preferred over private ones. When intf is defined only
// IPs belonging to that interface are considered.
Expand Down
5 changes: 5 additions & 0 deletions pkg/node/address_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ func (s *NodePrivilegedSuite) Test_firstGlobalV4Addr(c *C) {
preferredIP: "192.168.0.1",
want: "21.0.0.1",
},
{
name: "primary IP preferred by default",
ipsOnInterface: []string{"192.168.0.2", "192.168.0.1"},
want: "192.168.0.2",
},
}
const ifName = "dummy_iface"
for _, tc := range testCases {
Expand Down