Skip to content

Commit

Permalink
proxy/ipvs: add a GetAllLocalAddressesExcept() function
Browse files Browse the repository at this point in the history
  • Loading branch information
Lars Ekman committed Apr 29, 2023
1 parent 237d736 commit ca1e563
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
5 changes: 5 additions & 0 deletions pkg/proxy/ipvs/netlink.go
Expand Up @@ -40,4 +40,9 @@ type NetLinkHandle interface {
// Only the addresses of the current family are returned.
// IPv6 link-local and loopback addresses are excluded.
GetLocalAddresses(dev string) (sets.Set[string], error)
// GetAllLocalAddressesExcept return all local addresses on the node, except from the passed dev.
// This is not the same as to take the diff between GetAllLocalAddresses and GetLocalAddresses
// since an address can be assigned to many interfaces. This problem raised
// https://github.com/kubernetes/kubernetes/issues/114815
GetAllLocalAddressesExcept(dev string) (sets.Set[string], error)
}
28 changes: 28 additions & 0 deletions pkg/proxy/ipvs/netlink_linux.go
Expand Up @@ -24,6 +24,7 @@ import (
"net"

"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
utilproxy "k8s.io/kubernetes/pkg/proxy/util"
netutils "k8s.io/utils/net"

Expand Down Expand Up @@ -164,3 +165,30 @@ func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
}
return true
}

// GetAllLocalAddressesExcept return all local addresses on the node,
// except from the passed dev. This is not the same as to take the
// diff between GetAllLocalAddresses and GetLocalAddresses since an
// address can be assigned to many interfaces. This problem raised
// https://github.com/kubernetes/kubernetes/issues/114815
func (h *netlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
var addr []net.Addr
for _, iface := range ifaces {
if iface.Name == dev {
continue
}
ifadr, err := iface.Addrs()
if err != nil {
// This may happen if the interface was deleted. Ignore
// but log the error.
klog.ErrorS(err, "Reading addresses", "interface", iface.Name)
continue
}
addr = append(addr, ifadr...)
}
return utilproxy.AddressSet(h.isValidForSet, addr), nil
}
5 changes: 5 additions & 0 deletions pkg/proxy/ipvs/netlink_unsupported.go
Expand Up @@ -71,6 +71,11 @@ func (h *netlinkHandle) GetLocalAddresses(dev string) (sets.Set[string], error)
return nil, fmt.Errorf("netlink is not supported in this platform")
}

// GetAllLocalAddressesExcept is part of interface.
func (h *netlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
return nil, fmt.Errorf("netlink is not supported in this platform")
}

// Must match the one in proxier_test.go
func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
return false
Expand Down
3 changes: 1 addition & 2 deletions pkg/proxy/ipvs/proxier.go
Expand Up @@ -1013,11 +1013,10 @@ func (proxier *Proxier) syncProxyRules() {
klog.ErrorS(err, "Error listing addresses binded to dummy interface")
}
// nodeAddressSet All addresses *except* those on the dummy interface
nodeAddressSet, err := proxier.netlinkHandle.GetAllLocalAddresses()
nodeAddressSet, err := proxier.netlinkHandle.GetAllLocalAddressesExcept(defaultDummyDevice)
if err != nil {
klog.ErrorS(err, "Error listing node addresses")
}
nodeAddressSet = nodeAddressSet.Difference(alreadyBoundAddrs)

hasNodePort := false
for _, svc := range proxier.svcPortMap {
Expand Down
15 changes: 15 additions & 0 deletions pkg/proxy/ipvs/testing/fake.go
Expand Up @@ -140,6 +140,21 @@ func (h *FakeNetlinkHandle) GetAllLocalAddresses() (sets.Set[string], error) {
return res, nil
}

func (h *FakeNetlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
res := sets.New[string]()
for linkName := range h.localAddresses {
if linkName == dev {
continue
}
for _, addr := range h.localAddresses[linkName] {
if h.isValidForSet(addr) {
res.Insert(addr)
}
}
}
return res, nil
}

// SetLocalAddresses set IP addresses to the given interface device. It's not part of interface.
func (h *FakeNetlinkHandle) SetLocalAddresses(dev string, ips ...string) error {
if h.localAddresses == nil {
Expand Down
8 changes: 7 additions & 1 deletion pkg/proxy/ipvs/testing/fake_test.go
Expand Up @@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/proxy/ipvs"
)

// (I am unsure if this test has any value since it only tests the fake implementation)
func TestSetGetLocalAddresses(t *testing.T) {
fake := NewFakeNetlinkHandle(false)
_ = ipvs.NetLinkHandle(fake) // Ensure that the interface is honored
Expand All @@ -43,10 +44,15 @@ func TestSetGetLocalAddresses(t *testing.T) {
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
fake.SetLocalAddresses("kube-ipvs0", "4.3.2.1")
fake.SetLocalAddresses("kube-ipvs0", "1.2.3.4", "4.3.2.1")
addr, _ = fake.GetAllLocalAddresses()
expected = sets.New("1.2.3.4", "4.3.2.1")
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
addr, _ = fake.GetAllLocalAddressesExcept("kube-ipvs0")
expected = sets.New("1.2.3.4")
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
}

0 comments on commit ca1e563

Please sign in to comment.