mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Kube-proxy/ipvs; Use go "net" lib to get nodeIPs
The nodeIPs to be used for nodePorts were collected using netlink which was unnecessary complex and caused se #93858
This commit is contained in:
		@@ -32,7 +32,12 @@ type NetLinkHandle interface {
 | 
				
			|||||||
	DeleteDummyDevice(devName string) error
 | 
						DeleteDummyDevice(devName string) error
 | 
				
			||||||
	// ListBindAddress will list all IP addresses which are bound in a given interface
 | 
						// ListBindAddress will list all IP addresses which are bound in a given interface
 | 
				
			||||||
	ListBindAddress(devName string) ([]string, error)
 | 
						ListBindAddress(devName string) ([]string, error)
 | 
				
			||||||
	// GetLocalAddresses returns all unique local type IP addresses based on specified device and filter device
 | 
						// GetAllLocalAddresses return all local addresses on the node.
 | 
				
			||||||
	// If device is not specified, it will list all unique local type addresses except filter device addresses
 | 
						// Only the addresses of the current family are returned.
 | 
				
			||||||
	GetLocalAddresses(dev, filterDev string) (sets.String, error)
 | 
						// IPv6 link-local and loopback addresses are excluded.
 | 
				
			||||||
 | 
						GetAllLocalAddresses() (sets.String, error)
 | 
				
			||||||
 | 
						// GetLocalAddresses return all local addresses for an interface.
 | 
				
			||||||
 | 
						// Only the addresses of the current family are returned.
 | 
				
			||||||
 | 
						// IPv6 link-local and loopback addresses are excluded.
 | 
				
			||||||
 | 
						GetLocalAddresses(dev string) (sets.String, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,8 +21,10 @@ package ipvs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
 | 
						utilproxy "k8s.io/kubernetes/pkg/proxy/util"
 | 
				
			||||||
	netutils "k8s.io/utils/net"
 | 
						netutils "k8s.io/utils/net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/vishvananda/netlink"
 | 
						"github.com/vishvananda/netlink"
 | 
				
			||||||
@@ -124,72 +126,41 @@ func (h *netlinkHandle) ListBindAddress(devName string) ([]string, error) {
 | 
				
			|||||||
	return ips, nil
 | 
						return ips, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLocalAddresses lists all LOCAL type IP addresses from host based on filter device.
 | 
					// GetAllLocalAddresses return all local addresses on the node.
 | 
				
			||||||
// If dev is not specified, it's equivalent to exec:
 | 
					// Only the addresses of the current family are returned.
 | 
				
			||||||
// $ ip route show table local type local proto kernel
 | 
					// IPv6 link-local and loopback addresses are excluded.
 | 
				
			||||||
// 10.0.0.1 dev kube-ipvs0  scope host  src 10.0.0.1
 | 
					func (h *netlinkHandle) GetAllLocalAddresses() (sets.String, error) {
 | 
				
			||||||
// 10.0.0.10 dev kube-ipvs0  scope host  src 10.0.0.10
 | 
						addr, err := net.InterfaceAddrs()
 | 
				
			||||||
// 10.0.0.252 dev kube-ipvs0  scope host  src 10.0.0.252
 | 
					 | 
				
			||||||
// 100.106.89.164 dev eth0  scope host  src 100.106.89.164
 | 
					 | 
				
			||||||
// 127.0.0.0/8 dev lo  scope host  src 127.0.0.1
 | 
					 | 
				
			||||||
// 127.0.0.1 dev lo  scope host  src 127.0.0.1
 | 
					 | 
				
			||||||
// 172.17.0.1 dev docker0  scope host  src 172.17.0.1
 | 
					 | 
				
			||||||
// 192.168.122.1 dev virbr0  scope host  src 192.168.122.1
 | 
					 | 
				
			||||||
// Then cut the unique src IP fields,
 | 
					 | 
				
			||||||
// --> result set: [10.0.0.1, 10.0.0.10, 10.0.0.252, 100.106.89.164, 127.0.0.1, 172.17.0.1, 192.168.122.1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// If dev is specified, it's equivalent to exec:
 | 
					 | 
				
			||||||
// $ ip route show table local type local proto kernel dev kube-ipvs0
 | 
					 | 
				
			||||||
// 10.0.0.1  scope host  src 10.0.0.1
 | 
					 | 
				
			||||||
// 10.0.0.10  scope host  src 10.0.0.10
 | 
					 | 
				
			||||||
// Then cut the unique src IP fields,
 | 
					 | 
				
			||||||
// --> result set: [10.0.0.1, 10.0.0.10]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// If filterDev is specified, the result will discard route of specified device and cut src from other routes.
 | 
					 | 
				
			||||||
func (h *netlinkHandle) GetLocalAddresses(dev, filterDev string) (sets.String, error) {
 | 
					 | 
				
			||||||
	chosenLinkIndex, filterLinkIndex := -1, -1
 | 
					 | 
				
			||||||
	if dev != "" {
 | 
					 | 
				
			||||||
		link, err := h.LinkByName(dev)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
			return nil, fmt.Errorf("error get device %s, err: %v", dev, err)
 | 
							return nil, fmt.Errorf("Could not get addresses: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		chosenLinkIndex = link.Attrs().Index
 | 
						return utilproxy.AddressSet(h.isValidForSet, addr), nil
 | 
				
			||||||
	} else if filterDev != "" {
 | 
					 | 
				
			||||||
		link, err := h.LinkByName(filterDev)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("error get filter device %s, err: %v", filterDev, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		filterLinkIndex = link.Attrs().Index
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	routeFilter := &netlink.Route{
 | 
					// GetLocalAddresses return all local addresses for an interface.
 | 
				
			||||||
		Table:    unix.RT_TABLE_LOCAL,
 | 
					// Only the addresses of the current family are returned.
 | 
				
			||||||
		Type:     unix.RTN_LOCAL,
 | 
					// IPv6 link-local and loopback addresses are excluded.
 | 
				
			||||||
		Protocol: unix.RTPROT_KERNEL,
 | 
					func (h *netlinkHandle) GetLocalAddresses(dev string) (sets.String, error) {
 | 
				
			||||||
	}
 | 
						ifi, err := net.InterfaceByName(dev)
 | 
				
			||||||
	filterMask := netlink.RT_FILTER_TABLE | netlink.RT_FILTER_TYPE | netlink.RT_FILTER_PROTOCOL
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// find chosen device
 | 
					 | 
				
			||||||
	if chosenLinkIndex != -1 {
 | 
					 | 
				
			||||||
		routeFilter.LinkIndex = chosenLinkIndex
 | 
					 | 
				
			||||||
		filterMask |= netlink.RT_FILTER_OIF
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	routes, err := h.RouteListFiltered(netlink.FAMILY_ALL, routeFilter, filterMask)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("error list route table, err: %v", err)
 | 
							return nil, fmt.Errorf("Could not get interface %s: %v", dev, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	res := sets.NewString()
 | 
						addr, err := ifi.Addrs()
 | 
				
			||||||
	for _, route := range routes {
 | 
						if err != nil {
 | 
				
			||||||
		if route.LinkIndex == filterLinkIndex {
 | 
							return nil, fmt.Errorf("Can't get addresses from %s: %v", ifi.Name, err)
 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		if h.isIPv6 {
 | 
						return utilproxy.AddressSet(h.isValidForSet, addr), nil
 | 
				
			||||||
			if route.Dst.IP.To4() == nil && !route.Dst.IP.IsLinkLocalUnicast() {
 | 
					 | 
				
			||||||
				res.Insert(route.Dst.IP.String())
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		} else if route.Src != nil {
 | 
					
 | 
				
			||||||
			res.Insert(route.Src.String())
 | 
					func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
 | 
				
			||||||
 | 
						if h.isIPv6 != netutils.IsIPv6(ip) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if h.isIPv6 && ip.IsLinkLocalUnicast() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return res, nil
 | 
						if ip.IsLoopback() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,44 +21,57 @@ package ipvs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type emptyHandle struct {
 | 
					// The type must match the one in proxier_test.go
 | 
				
			||||||
 | 
					type netlinkHandle struct {
 | 
				
			||||||
 | 
						isIPv6 bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewNetLinkHandle will create an EmptyHandle
 | 
					// NewNetLinkHandle will create an EmptyHandle
 | 
				
			||||||
func NewNetLinkHandle(ipv6 bool) NetLinkHandle {
 | 
					func NewNetLinkHandle(ipv6 bool) NetLinkHandle {
 | 
				
			||||||
	return &emptyHandle{}
 | 
						return &netlinkHandle{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureAddressBind checks if address is bound to the interface and, if not, binds it. If the address is already bound, return true.
 | 
					// EnsureAddressBind checks if address is bound to the interface and, if not, binds it. If the address is already bound, return true.
 | 
				
			||||||
func (h *emptyHandle) EnsureAddressBind(address, devName string) (exist bool, err error) {
 | 
					func (h *netlinkHandle) EnsureAddressBind(address, devName string) (exist bool, err error) {
 | 
				
			||||||
	return false, fmt.Errorf("netlink not supported for this platform")
 | 
						return false, fmt.Errorf("netlink not supported for this platform")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnbindAddress unbind address from the interface
 | 
					// UnbindAddress unbind address from the interface
 | 
				
			||||||
func (h *emptyHandle) UnbindAddress(address, devName string) error {
 | 
					func (h *netlinkHandle) UnbindAddress(address, devName string) error {
 | 
				
			||||||
	return fmt.Errorf("netlink not supported for this platform")
 | 
						return fmt.Errorf("netlink not supported for this platform")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureDummyDevice is part of interface
 | 
					// EnsureDummyDevice is part of interface
 | 
				
			||||||
func (h *emptyHandle) EnsureDummyDevice(devName string) (bool, error) {
 | 
					func (h *netlinkHandle) EnsureDummyDevice(devName string) (bool, error) {
 | 
				
			||||||
	return false, fmt.Errorf("netlink is not supported in this platform")
 | 
						return false, fmt.Errorf("netlink is not supported in this platform")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteDummyDevice is part of interface.
 | 
					// DeleteDummyDevice is part of interface.
 | 
				
			||||||
func (h *emptyHandle) DeleteDummyDevice(devName string) error {
 | 
					func (h *netlinkHandle) DeleteDummyDevice(devName string) error {
 | 
				
			||||||
	return fmt.Errorf("netlink is not supported in this platform")
 | 
						return fmt.Errorf("netlink is not supported in this platform")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListBindAddress is part of interface.
 | 
					// ListBindAddress is part of interface.
 | 
				
			||||||
func (h *emptyHandle) ListBindAddress(devName string) ([]string, error) {
 | 
					func (h *netlinkHandle) ListBindAddress(devName string) ([]string, error) {
 | 
				
			||||||
 | 
						return nil, fmt.Errorf("netlink is not supported in this platform")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetAllLocalAddresses is part of interface.
 | 
				
			||||||
 | 
					func (h *netlinkHandle) GetAllLocalAddresses() (sets.String, error) {
 | 
				
			||||||
	return nil, fmt.Errorf("netlink is not supported in this platform")
 | 
						return nil, fmt.Errorf("netlink is not supported in this platform")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLocalAddresses is part of interface.
 | 
					// GetLocalAddresses is part of interface.
 | 
				
			||||||
func (h *emptyHandle) GetLocalAddresses(dev, filterDev string) (sets.String, error) {
 | 
					func (h *netlinkHandle) GetLocalAddresses(dev string) (sets.String, error) {
 | 
				
			||||||
	return nil, fmt.Errorf("netlink is not supported in this platform")
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -289,33 +289,31 @@ type realIPGetter struct {
 | 
				
			|||||||
	nl NetLinkHandle
 | 
						nl NetLinkHandle
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NodeIPs returns all LOCAL type IP addresses from host which are taken as the Node IPs of NodePort service.
 | 
					// NodeIPs returns all LOCAL type IP addresses from host which are
 | 
				
			||||||
// It will list source IP exists in local route table with `kernel` protocol type, and filter out IPVS proxier
 | 
					// taken as the Node IPs of NodePort service. Filtered addresses:
 | 
				
			||||||
// created dummy device `kube-ipvs0` For example,
 | 
					//
 | 
				
			||||||
// $ ip route show table local type local proto kernel
 | 
					//  * Loopback addresses
 | 
				
			||||||
// 10.0.0.1 dev kube-ipvs0  scope host  src 10.0.0.1
 | 
					//  * Addresses of the "other" family (not handled by this proxier instance)
 | 
				
			||||||
// 10.0.0.10 dev kube-ipvs0  scope host  src 10.0.0.10
 | 
					//  * Link-local IPv6 addresses
 | 
				
			||||||
// 10.0.0.252 dev kube-ipvs0  scope host  src 10.0.0.252
 | 
					//  * Addresses on the created dummy device `kube-ipvs0`
 | 
				
			||||||
// 100.106.89.164 dev eth0  scope host  src 100.106.89.164
 | 
					//
 | 
				
			||||||
// 127.0.0.0/8 dev lo  scope host  src 127.0.0.1
 | 
					 | 
				
			||||||
// 127.0.0.1 dev lo  scope host  src 127.0.0.1
 | 
					 | 
				
			||||||
// 172.17.0.1 dev docker0  scope host  src 172.17.0.1
 | 
					 | 
				
			||||||
// 192.168.122.1 dev virbr0  scope host  src 192.168.122.1
 | 
					 | 
				
			||||||
// Then filter out dev==kube-ipvs0, and cut the unique src IP fields,
 | 
					 | 
				
			||||||
// Node IP set: [100.106.89.164, 172.17.0.1, 192.168.122.1]
 | 
					 | 
				
			||||||
// Note that loopback addresses are excluded.
 | 
					 | 
				
			||||||
func (r *realIPGetter) NodeIPs() (ips []net.IP, err error) {
 | 
					func (r *realIPGetter) NodeIPs() (ips []net.IP, err error) {
 | 
				
			||||||
	// Pass in empty filter device name for list all LOCAL type addresses.
 | 
					
 | 
				
			||||||
	nodeAddress, err := r.nl.GetLocalAddresses("", DefaultDummyDevice)
 | 
						nodeAddress, err := r.nl.GetAllLocalAddresses()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("error listing LOCAL type addresses from host, error: %v", err)
 | 
							return nil, fmt.Errorf("error listing LOCAL type addresses from host, error: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// translate ip string to IP
 | 
					
 | 
				
			||||||
	for _, ipStr := range nodeAddress.UnsortedList() {
 | 
						// We must exclude the addresses on the IPVS dummy interface
 | 
				
			||||||
		a := netutils.ParseIPSloppy(ipStr)
 | 
						bindedAddress, err := r.BindedIPs()
 | 
				
			||||||
		if a.IsLoopback() {
 | 
						if err != nil {
 | 
				
			||||||
			continue
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ipset := nodeAddress.Difference(bindedAddress)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// translate ip string to IP
 | 
				
			||||||
 | 
						for _, ipStr := range ipset.UnsortedList() {
 | 
				
			||||||
 | 
							a := netutils.ParseIPSloppy(ipStr)
 | 
				
			||||||
		ips = append(ips, a)
 | 
							ips = append(ips, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ips, nil
 | 
						return ips, nil
 | 
				
			||||||
@@ -323,7 +321,7 @@ func (r *realIPGetter) NodeIPs() (ips []net.IP, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// BindedIPs returns all addresses that are binded to the IPVS dummy interface kube-ipvs0
 | 
					// BindedIPs returns all addresses that are binded to the IPVS dummy interface kube-ipvs0
 | 
				
			||||||
func (r *realIPGetter) BindedIPs() (sets.String, error) {
 | 
					func (r *realIPGetter) BindedIPs() (sets.String, error) {
 | 
				
			||||||
	return r.nl.GetLocalAddresses(DefaultDummyDevice, "")
 | 
						return r.nl.GetLocalAddresses(DefaultDummyDevice)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Proxier implements proxy.Provider
 | 
					// Proxier implements proxy.Provider
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -385,6 +385,7 @@ func TestCanUseIPVSProxier(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetNodeIPs(t *testing.T) {
 | 
					func TestGetNodeIPs(t *testing.T) {
 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							isIPv6       bool
 | 
				
			||||||
		devAddresses map[string][]string
 | 
							devAddresses map[string][]string
 | 
				
			||||||
		expectIPs    []string
 | 
							expectIPs    []string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
@@ -405,22 +406,22 @@ func TestGetNodeIPs(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		// case 3
 | 
							// case 3
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"encap0": {"10.20.30.40"}, "lo": {"127.0.0.1"}, "docker0": {"172.17.0.1"}},
 | 
								devAddresses: map[string][]string{"encap0": {"10.20.30.40", "fe80::200:ff:fe01:1"}, "lo": {"127.0.0.1", "::1"}, "docker0": {"172.17.0.1"}},
 | 
				
			||||||
			expectIPs:    []string{"10.20.30.40", "172.17.0.1"},
 | 
								expectIPs:    []string{"10.20.30.40", "172.17.0.1"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// case 4
 | 
							// case 4
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"encaps9": {"10.20.30.40"}, "lo": {"127.0.0.1"}, "encap7": {"10.20.30.31"}},
 | 
								devAddresses: map[string][]string{"encaps9": {"10.20.30.40"}, "lo": {"127.0.0.1", "::1"}, "encap7": {"1000::", "10.20.30.31"}},
 | 
				
			||||||
			expectIPs:    []string{"10.20.30.40", "10.20.30.31"},
 | 
								expectIPs:    []string{"10.20.30.40", "10.20.30.31"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// case 5
 | 
							// case 5
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"kube-ipvs0": {"1.2.3.4"}, "lo": {"127.0.0.1"}, "encap7": {"10.20.30.31"}},
 | 
								devAddresses: map[string][]string{"kube-ipvs0": {"2000::", "1.2.3.4"}, "lo": {"127.0.0.1", "::1"}, "encap7": {"1000::", "10.20.30.31"}},
 | 
				
			||||||
			expectIPs:    []string{"10.20.30.31"},
 | 
								expectIPs:    []string{"10.20.30.31"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// case 6
 | 
							// case 6
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"kube-ipvs0": {"1.2.3.4", "2.3.4.5"}, "lo": {"127.0.0.1"}},
 | 
								devAddresses: map[string][]string{"kube-ipvs0": {"1.2.3.4", "2.3.4.5"}, "lo": {"127.0.0.1", "::1"}},
 | 
				
			||||||
			expectIPs:    []string{},
 | 
								expectIPs:    []string{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// case 7
 | 
							// case 7
 | 
				
			||||||
@@ -430,18 +431,31 @@ func TestGetNodeIPs(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		// case 8
 | 
							// case 8
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"kube-ipvs0": {"1.2.3.4", "2.3.4.5"}, "eth5": {"3.4.5.6"}, "lo": {"127.0.0.1"}},
 | 
								devAddresses: map[string][]string{"kube-ipvs0": {"1.2.3.4", "2.3.4.5"}, "eth5": {"3.4.5.6"}, "lo": {"127.0.0.1", "::1"}},
 | 
				
			||||||
			expectIPs:    []string{"3.4.5.6"},
 | 
								expectIPs:    []string{"3.4.5.6"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// case 9
 | 
							// case 9
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			devAddresses: map[string][]string{"ipvs0": {"1.2.3.4"}, "lo": {"127.0.0.1"}, "encap7": {"10.20.30.31"}},
 | 
								devAddresses: map[string][]string{"ipvs0": {"1.2.3.4"}, "lo": {"127.0.0.1", "::1"}, "encap7": {"10.20.30.31"}},
 | 
				
			||||||
			expectIPs:    []string{"10.20.30.31", "1.2.3.4"},
 | 
								expectIPs:    []string{"10.20.30.31", "1.2.3.4"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							// case 10
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								isIPv6:       true,
 | 
				
			||||||
 | 
								devAddresses: map[string][]string{"ipvs0": {"1.2.3.4", "1000::"}, "lo": {"127.0.0.1", "::1"}, "encap7": {"10.20.30.31", "2000::", "fe80::200:ff:fe01:1"}},
 | 
				
			||||||
 | 
								expectIPs:    []string{"1000::", "2000::"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// case 11
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								isIPv6:       true,
 | 
				
			||||||
 | 
								devAddresses: map[string][]string{"ipvs0": {"1.2.3.4", "1000::"}, "lo": {"127.0.0.1", "::1"}, "encap7": {"10.20.30.31", "2000::", "fe80::200:ff:fe01:1"}, "kube-ipvs0": {"1.2.3.4", "2.3.4.5", "2000::"}},
 | 
				
			||||||
 | 
								expectIPs:    []string{"1000::"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := range testCases {
 | 
						for i := range testCases {
 | 
				
			||||||
		fake := netlinktest.NewFakeNetlinkHandle()
 | 
							fake := netlinktest.NewFakeNetlinkHandle()
 | 
				
			||||||
 | 
							fake.IsIPv6 = testCases[i].isIPv6
 | 
				
			||||||
		for dev, addresses := range testCases[i].devAddresses {
 | 
							for dev, addresses := range testCases[i].devAddresses {
 | 
				
			||||||
			fake.SetLocalAddresses(dev, addresses...)
 | 
								fake.SetLocalAddresses(dev, addresses...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -5354,3 +5368,94 @@ func Test_EndpointSliceOnlyReadyAndTerminatingLocalWithFeatureGateDisabled(t *te
 | 
				
			|||||||
	assert.Nil(t, rsErr2, "Expected no error getting real servers")
 | 
						assert.Nil(t, rsErr2, "Expected no error getting real servers")
 | 
				
			||||||
	assert.Len(t, realServers2, 0, "Expected 0 real servers")
 | 
						assert.Len(t, realServers2, 0, "Expected 0 real servers")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIpIsValidForSet(t *testing.T) {
 | 
				
			||||||
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							isIPv6 bool
 | 
				
			||||||
 | 
							ip     string
 | 
				
			||||||
 | 
							res    bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"127.0.0.1",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"127.0.0.0",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"127.6.7.8",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"8.8.8.8",
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"192.168.0.1",
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"169.254.0.0",
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"::ffff:169.254.0.0", // IPv6 mapped IPv4
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								"1000::",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// IPv6
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								"::1",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								"1000::",
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								"fe80::200:ff:fe01:1",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								"8.8.8.8",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								"::ffff:8.8.8.8",
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
							v := &netlinkHandle{}
 | 
				
			||||||
 | 
							v.isIPv6 = tc.isIPv6
 | 
				
			||||||
 | 
							ip := netutils.ParseIPSloppy(tc.ip)
 | 
				
			||||||
 | 
							if ip == nil {
 | 
				
			||||||
 | 
								t.Errorf("Parse error: %s", tc.ip)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if v.isValidForSet(ip) != tc.res {
 | 
				
			||||||
 | 
								if tc.isIPv6 {
 | 
				
			||||||
 | 
									t.Errorf("IPv6: %s", tc.ip)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									t.Errorf("IPv4: %s", tc.ip)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ package testing
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"k8s.io/utils/net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -27,6 +28,8 @@ type FakeNetlinkHandle struct {
 | 
				
			|||||||
	// localAddresses is a network interface name to all of its IP addresses map, e.g.
 | 
						// localAddresses is a network interface name to all of its IP addresses map, e.g.
 | 
				
			||||||
	// eth0 -> [1.2.3.4, 10.20.30.40]
 | 
						// eth0 -> [1.2.3.4, 10.20.30.40]
 | 
				
			||||||
	localAddresses map[string][]string
 | 
						localAddresses map[string][]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						IsIPv6 bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewFakeNetlinkHandle will create a new FakeNetlinkHandle
 | 
					// NewFakeNetlinkHandle will create a new FakeNetlinkHandle
 | 
				
			||||||
@@ -112,25 +115,27 @@ func (h *FakeNetlinkHandle) ListBindAddress(devName string) ([]string, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLocalAddresses is a mock implementation
 | 
					// GetLocalAddresses is a mock implementation
 | 
				
			||||||
func (h *FakeNetlinkHandle) GetLocalAddresses(dev, filterDev string) (sets.String, error) {
 | 
					func (h *FakeNetlinkHandle) GetLocalAddresses(dev string) (sets.String, error) {
 | 
				
			||||||
	res := sets.NewString()
 | 
						res := sets.NewString()
 | 
				
			||||||
	if len(dev) != 0 {
 | 
					 | 
				
			||||||
	// list all addresses from a given network interface.
 | 
						// list all addresses from a given network interface.
 | 
				
			||||||
	for _, addr := range h.localAddresses[dev] {
 | 
						for _, addr := range h.localAddresses[dev] {
 | 
				
			||||||
 | 
							if h.isValidForSet(addr) {
 | 
				
			||||||
			res.Insert(addr)
 | 
								res.Insert(addr)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return res, nil
 | 
						return res, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
	// If filterDev is not given, will list all addresses from all available network interface.
 | 
					func (h *FakeNetlinkHandle) GetAllLocalAddresses() (sets.String, error) {
 | 
				
			||||||
 | 
						res := sets.NewString()
 | 
				
			||||||
 | 
						// List all addresses from all available network interfaces.
 | 
				
			||||||
	for linkName := range h.localAddresses {
 | 
						for linkName := range h.localAddresses {
 | 
				
			||||||
		if linkName == filterDev {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// list all addresses from a given network interface.
 | 
							// list all addresses from a given network interface.
 | 
				
			||||||
		for _, addr := range h.localAddresses[linkName] {
 | 
							for _, addr := range h.localAddresses[linkName] {
 | 
				
			||||||
 | 
								if h.isValidForSet(addr) {
 | 
				
			||||||
				res.Insert(addr)
 | 
									res.Insert(addr)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return res, nil
 | 
						return res, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,3 +151,17 @@ func (h *FakeNetlinkHandle) SetLocalAddresses(dev string, ips ...string) error {
 | 
				
			|||||||
	h.localAddresses[dev] = append(h.localAddresses[dev], ips...)
 | 
						h.localAddresses[dev] = append(h.localAddresses[dev], ips...)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *FakeNetlinkHandle) isValidForSet(ipString string) bool {
 | 
				
			||||||
 | 
						ip := net.ParseIPSloppy(ipString)
 | 
				
			||||||
 | 
						if h.IsIPv6 != (ip.To4() == nil) {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if h.IsIPv6 && ip.IsLinkLocalUnicast() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ip.IsLoopback() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,22 +27,22 @@ func TestSetGetLocalAddresses(t *testing.T) {
 | 
				
			|||||||
	fake := NewFakeNetlinkHandle()
 | 
						fake := NewFakeNetlinkHandle()
 | 
				
			||||||
	fake.SetLocalAddresses("eth0", "1.2.3.4")
 | 
						fake.SetLocalAddresses("eth0", "1.2.3.4")
 | 
				
			||||||
	expected := sets.NewString("1.2.3.4")
 | 
						expected := sets.NewString("1.2.3.4")
 | 
				
			||||||
	addr, _ := fake.GetLocalAddresses("eth0", "")
 | 
						addr, _ := fake.GetLocalAddresses("eth0")
 | 
				
			||||||
	if !reflect.DeepEqual(expected, addr) {
 | 
						if !reflect.DeepEqual(expected, addr) {
 | 
				
			||||||
		t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
 | 
							t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list, _ := fake.GetLocalAddresses("", "")
 | 
						list, _ := fake.GetAllLocalAddresses()
 | 
				
			||||||
	if !reflect.DeepEqual(expected, list) {
 | 
						if !reflect.DeepEqual(expected, list) {
 | 
				
			||||||
		t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, list)
 | 
							t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, list)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fake.SetLocalAddresses("lo", "127.0.0.1")
 | 
						fake.SetLocalAddresses("lo", "127.0.0.1")
 | 
				
			||||||
	expected = sets.NewString("127.0.0.1")
 | 
						expected = sets.NewString()
 | 
				
			||||||
	addr, _ = fake.GetLocalAddresses("lo", "")
 | 
						addr, _ = fake.GetLocalAddresses("lo")
 | 
				
			||||||
	if !reflect.DeepEqual(expected, addr) {
 | 
						if !reflect.DeepEqual(expected, addr) {
 | 
				
			||||||
		t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
 | 
							t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list, _ = fake.GetLocalAddresses("", "")
 | 
						list, _ = fake.GetAllLocalAddresses()
 | 
				
			||||||
	expected = sets.NewString("1.2.3.4", "127.0.0.1")
 | 
						expected = sets.NewString("1.2.3.4")
 | 
				
			||||||
	if !reflect.DeepEqual(expected, list) {
 | 
						if !reflect.DeepEqual(expected, list) {
 | 
				
			||||||
		t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, list)
 | 
							t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, list)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -252,6 +252,27 @@ func GetNodeAddresses(cidrs []string, nw NetworkInterfacer) (sets.String, error)
 | 
				
			|||||||
	return uniqueAddressList, nil
 | 
						return uniqueAddressList, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddressSet validates the addresses in the slice using the "isValid" function.
 | 
				
			||||||
 | 
					// Addresses that pass the validation are returned as a string Set.
 | 
				
			||||||
 | 
					func AddressSet(isValid func(ip net.IP) bool, addrs []net.Addr) sets.String {
 | 
				
			||||||
 | 
						ips := sets.NewString()
 | 
				
			||||||
 | 
						for _, a := range addrs {
 | 
				
			||||||
 | 
							var ip net.IP
 | 
				
			||||||
 | 
							switch v := a.(type) {
 | 
				
			||||||
 | 
							case *net.IPAddr:
 | 
				
			||||||
 | 
								ip = v.IP
 | 
				
			||||||
 | 
							case *net.IPNet:
 | 
				
			||||||
 | 
								ip = v.IP
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if isValid(ip) {
 | 
				
			||||||
 | 
								ips.Insert(ip.String())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ips
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LogAndEmitIncorrectIPVersionEvent logs and emits incorrect IP version event.
 | 
					// LogAndEmitIncorrectIPVersionEvent logs and emits incorrect IP version event.
 | 
				
			||||||
func LogAndEmitIncorrectIPVersionEvent(recorder events.EventRecorder, fieldName, fieldValue, svcNamespace, svcName string, svcUID types.UID) {
 | 
					func LogAndEmitIncorrectIPVersionEvent(recorder events.EventRecorder, fieldName, fieldValue, svcNamespace, svcName string, svcUID types.UID) {
 | 
				
			||||||
	errMsg := fmt.Sprintf("%s in %s has incorrect IP version", fieldValue, fieldName)
 | 
						errMsg := fmt.Sprintf("%s in %s has incorrect IP version", fieldValue, fieldName)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1283,3 +1283,119 @@ func randSeq() string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return string(b)
 | 
						return string(b)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mustParseIPAddr(str string) net.Addr {
 | 
				
			||||||
 | 
						a, err := net.ResolveIPAddr("ip", str)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic("mustParseIPAddr")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return a
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func mustParseIPNet(str string) net.Addr {
 | 
				
			||||||
 | 
						_, n, err := netutils.ParseCIDRSloppy(str)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic("mustParseIPNet")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func mustParseUnix(str string) net.Addr {
 | 
				
			||||||
 | 
						n, err := net.ResolveUnixAddr("unix", str)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic("mustParseUnix")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type cidrValidator struct {
 | 
				
			||||||
 | 
						cidr *net.IPNet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (v *cidrValidator) isValid(ip net.IP) bool {
 | 
				
			||||||
 | 
						return v.cidr.Contains(ip)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func newCidrValidator(cidr string) func(ip net.IP) bool {
 | 
				
			||||||
 | 
						_, n, err := netutils.ParseCIDRSloppy(cidr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic("mustParseIPNet")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						obj := cidrValidator{n}
 | 
				
			||||||
 | 
						return obj.isValid
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAddressSet(t *testing.T) {
 | 
				
			||||||
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							name      string
 | 
				
			||||||
 | 
							validator func(ip net.IP) bool
 | 
				
			||||||
 | 
							input     []net.Addr
 | 
				
			||||||
 | 
							expected  sets.String
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Empty",
 | 
				
			||||||
 | 
								func(ip net.IP) bool { return false },
 | 
				
			||||||
 | 
								nil,
 | 
				
			||||||
 | 
								sets.NewString(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Reject IPAddr x 2",
 | 
				
			||||||
 | 
								func(ip net.IP) bool { return false },
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseIPAddr("8.8.8.8"),
 | 
				
			||||||
 | 
									mustParseIPAddr("1000::"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Accept IPAddr x 2",
 | 
				
			||||||
 | 
								func(ip net.IP) bool { return true },
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseIPAddr("8.8.8.8"),
 | 
				
			||||||
 | 
									mustParseIPAddr("1000::"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString("8.8.8.8", "1000::"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Accept IPNet x 2",
 | 
				
			||||||
 | 
								func(ip net.IP) bool { return true },
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseIPNet("8.8.8.8/32"),
 | 
				
			||||||
 | 
									mustParseIPNet("1000::/128"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString("8.8.8.8", "1000::"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Accept Unix x 2",
 | 
				
			||||||
 | 
								func(ip net.IP) bool { return true },
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseUnix("/tmp/sock1"),
 | 
				
			||||||
 | 
									mustParseUnix("/tmp/sock2"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Cidr IPv4",
 | 
				
			||||||
 | 
								newCidrValidator("192.168.1.0/24"),
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseIPAddr("8.8.8.8"),
 | 
				
			||||||
 | 
									mustParseIPAddr("1000::"),
 | 
				
			||||||
 | 
									mustParseIPAddr("192.168.1.1"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString("192.168.1.1"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"Cidr IPv6",
 | 
				
			||||||
 | 
								newCidrValidator("1000::/64"),
 | 
				
			||||||
 | 
								[]net.Addr{
 | 
				
			||||||
 | 
									mustParseIPAddr("8.8.8.8"),
 | 
				
			||||||
 | 
									mustParseIPAddr("1000::"),
 | 
				
			||||||
 | 
									mustParseIPAddr("192.168.1.1"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								sets.NewString("1000::"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
							if !tc.expected.Equal(AddressSet(tc.validator, tc.input)) {
 | 
				
			||||||
 | 
								t.Errorf("%s", tc.name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user