Move GetNodeAddresses() and ContainsIPv4Loopback() into a new file

Both sound slightly generic, but implement semantics specific to the
handling of NodePort addresses.

(No changes other than moving code.)
This commit is contained in:
Dan Winship
2023-01-15 10:02:04 -05:00
parent d9c371a2c4
commit fe49e3933d
4 changed files with 431 additions and 380 deletions

View File

@@ -78,37 +78,6 @@ func BuildPortsToEndpointsMap(endpoints *v1.Endpoints) map[string][]string {
return portsToEndpoints
}
// ContainsIPv4Loopback returns true if the input is empty or one of the CIDR contains an IPv4 loopback address.
func ContainsIPv4Loopback(cidrStrings []string) bool {
if len(cidrStrings) == 0 {
return true
}
// RFC 5735 127.0.0.0/8 - This block is assigned for use as the Internet host loopback address
ipv4LoopbackStart := netutils.ParseIPSloppy("127.0.0.0")
for _, cidr := range cidrStrings {
if IsZeroCIDR(cidr) {
return true
}
ip, ipnet, err := netutils.ParseCIDRSloppy(cidr)
if err != nil {
continue
}
if netutils.IsIPv6CIDR(ipnet) {
continue
}
if ip.IsLoopback() {
return true
}
if ipnet.Contains(ipv4LoopbackStart) {
return true
}
}
return false
}
// IsZeroCIDR checks whether the input CIDR string is either
// the IPv4 or IPv6 zero CIDR
func IsZeroCIDR(cidr string) bool {
@@ -228,70 +197,6 @@ func ShouldSkipService(service *v1.Service) bool {
return false
}
// GetNodeAddresses return all matched node IP addresses based on given cidr slice.
// Some callers, e.g. IPVS proxier, need concrete IPs, not ranges, which is why this exists.
// NetworkInterfacer is injected for test purpose.
// We expect the cidrs passed in is already validated.
// Given an empty input `[]`, it will return `0.0.0.0/0` and `::/0` directly.
// If multiple cidrs is given, it will return the minimal IP sets, e.g. given input `[1.2.0.0/16, 0.0.0.0/0]`, it will
// only return `0.0.0.0/0`.
// NOTE: GetNodeAddresses only accepts CIDRs, if you want concrete IPs, e.g. 1.2.3.4, then the input should be 1.2.3.4/32.
func GetNodeAddresses(cidrs []string, nw NetworkInterfacer) (sets.String, error) {
uniqueAddressList := sets.NewString()
if len(cidrs) == 0 {
uniqueAddressList.Insert(IPv4ZeroCIDR)
uniqueAddressList.Insert(IPv6ZeroCIDR)
return uniqueAddressList, nil
}
// First round of iteration to pick out `0.0.0.0/0` or `::/0` for the sake of excluding non-zero IPs.
for _, cidr := range cidrs {
if IsZeroCIDR(cidr) {
uniqueAddressList.Insert(cidr)
}
}
addrs, err := nw.InterfaceAddrs()
if err != nil {
return nil, fmt.Errorf("error listing all interfaceAddrs from host, error: %v", err)
}
// Second round of iteration to parse IPs based on cidr.
for _, cidr := range cidrs {
if IsZeroCIDR(cidr) {
continue
}
_, ipNet, _ := netutils.ParseCIDRSloppy(cidr)
for _, addr := range addrs {
var ip net.IP
// nw.InterfaceAddrs may return net.IPAddr or net.IPNet on windows, and it will return net.IPNet on linux.
switch v := addr.(type) {
case *net.IPAddr:
ip = v.IP
case *net.IPNet:
ip = v.IP
default:
continue
}
if ipNet.Contains(ip) {
if netutils.IsIPv6(ip) && !uniqueAddressList.Has(IPv6ZeroCIDR) {
uniqueAddressList.Insert(ip.String())
}
if !netutils.IsIPv6(ip) && !uniqueAddressList.Has(IPv4ZeroCIDR) {
uniqueAddressList.Insert(ip.String())
}
}
}
}
if uniqueAddressList.Len() == 0 {
return nil, fmt.Errorf("no addresses found for cidrs %v", cidrs)
}
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 {