mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Merge pull request #115244 from danwinship/nodeport-addresses-1
clean up kube-proxy nodeport address handling (part 1)
This commit is contained in:
commit
f212d42086
116
pkg/proxy/util/nodeport_addresses.go
Normal file
116
pkg/proxy/util/nodeport_addresses.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
netutils "k8s.io/utils/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
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
|
||||||
|
}
|
325
pkg/proxy/util/nodeport_addresses_test.go
Normal file
325
pkg/proxy/util/nodeport_addresses_test.go
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
fake "k8s.io/kubernetes/pkg/proxy/util/testing"
|
||||||
|
netutils "k8s.io/utils/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InterfaceAddrsPair struct {
|
||||||
|
itf net.Interface
|
||||||
|
addrs []net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNodeAddresses(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
cidrs []string
|
||||||
|
itfAddrsPairs []InterfaceAddrsPair
|
||||||
|
expected sets.String
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "IPv4 single",
|
||||||
|
cidrs: []string{"10.20.30.0/24"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("100.200.201.1"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("10.20.30.51"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 zero CIDR",
|
||||||
|
cidrs: []string{"0.0.0.0/0"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("0.0.0.0/0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv6 multiple",
|
||||||
|
cidrs: []string{"2001:db8::/64", "::1/128"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(64, 128)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("2001:db8::1", "::1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv6 zero CIDR",
|
||||||
|
cidrs: []string{"::/0"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(64, 128)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("::/0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 localhost exact",
|
||||||
|
cidrs: []string{"127.0.0.1/32"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("127.0.0.1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 localhost subnet",
|
||||||
|
cidrs: []string{"127.0.0.0/8"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.1.1"), Mask: net.CIDRMask(8, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("127.0.1.1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 multiple",
|
||||||
|
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("100.200.201.1"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("10.20.30.51", "100.200.201.1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 multiple, no match",
|
||||||
|
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("192.168.1.2"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty list, IPv4 addrs",
|
||||||
|
cidrs: []string{},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("192.168.1.2"), Mask: net.CIDRMask(24, 32)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty list, IPv6 addrs",
|
||||||
|
cidrs: []string{},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(64, 128)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IPv4 redundant CIDRs",
|
||||||
|
cidrs: []string{"1.2.3.0/24", "0.0.0.0/0"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("0.0.0.0/0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dual-stack, redundant IPv4",
|
||||||
|
cidrs: []string{"0.0.0.0/0", "1.2.3.0/24", "2001:db8::1/128"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)},
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(64, 128)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)},
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("0.0.0.0/0", "2001:db8::1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dual-stack, redundant IPv6",
|
||||||
|
cidrs: []string{"::/0", "1.2.3.0/24", "2001:db8::1/128"},
|
||||||
|
itfAddrsPairs: []InterfaceAddrsPair{
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)},
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(64, 128)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||||
|
addrs: []net.Addr{
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)},
|
||||||
|
&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: sets.NewString("::/0", "1.2.3.4"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
nw := fake.NewFakeNetwork()
|
||||||
|
for _, pair := range tc.itfAddrsPairs {
|
||||||
|
nw.AddInterfaceAddr(&pair.itf, pair.addrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
addrList, err := GetNodeAddresses(tc.cidrs, nw)
|
||||||
|
// The fake InterfaceAddrs() never returns an error, so the only
|
||||||
|
// error GetNodeAddresses will return is "no addresses found".
|
||||||
|
if err != nil && tc.expected != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !addrList.Equal(tc.expected) {
|
||||||
|
t.Errorf("unexpected mismatch, expected: %v, got: %v", tc.expected, addrList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContainsIPv4Loopback(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cidrStrings []string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all zeros ipv4",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "0.0.0.0/0"},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all zeros ipv4 and invalid cidr",
|
||||||
|
cidrStrings: []string{"invalid.cidr", "192.168.0.0/16", "fd00:1:d::/64", "0.0.0.0/0"},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all zeros ipv6",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "::/0"},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ipv4 loopback",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "127.0.0.0/8"},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ipv6 loopback",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "::1/128"},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ipv4 loopback smaller range",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "127.0.2.0/28"},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ipv4 loopback within larger range",
|
||||||
|
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "64.0.0.0/2"},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non loop loopback",
|
||||||
|
cidrStrings: []string{"128.0.2.0/28", "224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64"},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid cidr",
|
||||||
|
cidrStrings: []string{"invalid.ip/invalid.mask"},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := ContainsIPv4Loopback(tt.cidrStrings); got != tt.want {
|
||||||
|
t.Errorf("ContainsIPv4Loopback() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -78,37 +78,6 @@ func BuildPortsToEndpointsMap(endpoints *v1.Endpoints) map[string][]string {
|
|||||||
return portsToEndpoints
|
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
|
// IsZeroCIDR checks whether the input CIDR string is either
|
||||||
// the IPv4 or IPv6 zero CIDR
|
// the IPv4 or IPv6 zero CIDR
|
||||||
func IsZeroCIDR(cidr string) bool {
|
func IsZeroCIDR(cidr string) bool {
|
||||||
@ -228,70 +197,6 @@ func ShouldSkipService(service *v1.Service) bool {
|
|||||||
return false
|
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.
|
// AddressSet validates the addresses in the slice using the "isValid" function.
|
||||||
// Addresses that pass the validation are returned as a string Set.
|
// Addresses that pass the validation are returned as a string Set.
|
||||||
func AddressSet(isValid func(ip net.IP) bool, addrs []net.Addr) sets.String {
|
func AddressSet(isValid func(ip net.IP) bool, addrs []net.Addr) sets.String {
|
||||||
|
@ -18,7 +18,6 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -28,7 +27,6 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
fake "k8s.io/kubernetes/pkg/proxy/util/testing"
|
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -399,224 +397,6 @@ func (t *testResolver) LookupIPAddr(_ context.Context, address string) ([]net.IP
|
|||||||
return t.addrs, t.err
|
return t.addrs, t.err
|
||||||
}
|
}
|
||||||
|
|
||||||
type InterfaceAddrsPair struct {
|
|
||||||
itf net.Interface
|
|
||||||
addrs []net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetNodeAddresses(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
cidrs []string
|
|
||||||
nw *fake.FakeNetwork
|
|
||||||
itfAddrsPairs []InterfaceAddrsPair
|
|
||||||
expected sets.String
|
|
||||||
expectedErr error
|
|
||||||
}{
|
|
||||||
{ // case 0
|
|
||||||
cidrs: []string{"10.20.30.0/24"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("100.200.201.1"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("10.20.30.51"),
|
|
||||||
},
|
|
||||||
{ // case 1
|
|
||||||
cidrs: []string{"0.0.0.0/0"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("0.0.0.0/0"),
|
|
||||||
},
|
|
||||||
{ // case 2
|
|
||||||
cidrs: []string{"2001:db8::/32", "::1/128"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(32, 128)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("2001:db8::1", "::1"),
|
|
||||||
},
|
|
||||||
{ // case 3
|
|
||||||
cidrs: []string{"::/0"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(32, 128)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("::/0"),
|
|
||||||
},
|
|
||||||
{ // case 4
|
|
||||||
cidrs: []string{"127.0.0.1/32"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("127.0.0.1"),
|
|
||||||
},
|
|
||||||
{ // case 5
|
|
||||||
cidrs: []string{"127.0.0.0/8"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.1.1"), Mask: net.CIDRMask(8, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("127.0.1.1"),
|
|
||||||
},
|
|
||||||
{ // case 6
|
|
||||||
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("10.20.30.51"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("100.200.201.1"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("10.20.30.51", "100.200.201.1"),
|
|
||||||
},
|
|
||||||
{ // case 7
|
|
||||||
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("192.168.1.2"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: nil,
|
|
||||||
expectedErr: fmt.Errorf("no addresses found for cidrs %v", []string{"10.20.30.0/24", "100.200.201.0/24"}),
|
|
||||||
},
|
|
||||||
{ // case 8
|
|
||||||
cidrs: []string{},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("192.168.1.2"), Mask: net.CIDRMask(24, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("127.0.0.1"), Mask: net.CIDRMask(8, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
|
||||||
},
|
|
||||||
{ // case 9
|
|
||||||
cidrs: []string{},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("2001:db8::1"), Mask: net.CIDRMask(32, 128)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
|
||||||
},
|
|
||||||
{ // case 9
|
|
||||||
cidrs: []string{"1.2.3.0/24", "0.0.0.0/0"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("0.0.0.0/0"),
|
|
||||||
},
|
|
||||||
{ // case 10
|
|
||||||
cidrs: []string{"0.0.0.0/0", "1.2.3.0/24", "::1/128"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("0.0.0.0/0", "::1"),
|
|
||||||
},
|
|
||||||
{ // case 11
|
|
||||||
cidrs: []string{"::/0", "1.2.3.0/24", "::1/128"},
|
|
||||||
nw: fake.NewFakeNetwork(),
|
|
||||||
itfAddrsPairs: []InterfaceAddrsPair{
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("1.2.3.4"), Mask: net.CIDRMask(30, 32)}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
|
||||||
addrs: []net.Addr{&net.IPNet{IP: netutils.ParseIPSloppy("::1"), Mask: net.CIDRMask(128, 128)}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: sets.NewString("::/0", "1.2.3.4"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range testCases {
|
|
||||||
for _, pair := range testCases[i].itfAddrsPairs {
|
|
||||||
testCases[i].nw.AddInterfaceAddr(&pair.itf, pair.addrs)
|
|
||||||
}
|
|
||||||
addrList, err := GetNodeAddresses(testCases[i].cidrs, testCases[i].nw)
|
|
||||||
if !reflect.DeepEqual(err, testCases[i].expectedErr) {
|
|
||||||
t.Errorf("case [%d], unexpected error: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !addrList.Equal(testCases[i].expected) {
|
|
||||||
t.Errorf("case [%d], unexpected mismatch, expected: %v, got: %v", i, testCases[i].expected, addrList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendPortIfNeeded(t *testing.T) {
|
func TestAppendPortIfNeeded(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -1405,71 +1185,6 @@ func TestAddressSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainsIPv4Loopback(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
cidrStrings []string
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "empty",
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "all zeros ipv4",
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "0.0.0.0/0"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "all zeros ipv4 and invalid cidr",
|
|
||||||
cidrStrings: []string{"invalid.cidr", "192.168.0.0/16", "fd00:1:d::/64", "0.0.0.0/0"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "all zeros ipv6", // interpret all zeros equal for IPv4 and IPv6 as Golang stdlib
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "::/0"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ipv4 loopback",
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "127.0.0.0/8"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ipv6 loopback",
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "::1/128"},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ipv4 loopback smaller range",
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "127.0.2.0/28"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ipv4 loopback within larger range",
|
|
||||||
cidrStrings: []string{"224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64", "64.0.0.0/2"},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "non loop loopback",
|
|
||||||
cidrStrings: []string{"128.0.2.0/28", "224.0.0.0/24", "192.168.0.0/16", "fd00:1:d::/64"},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid cidr",
|
|
||||||
cidrStrings: []string{"invalid.ip/invalid.mask"},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := ContainsIPv4Loopback(tt.cidrStrings); got != tt.want {
|
|
||||||
t.Errorf("ContainLoopback() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsZeroCIDR(t *testing.T) {
|
func TestIsZeroCIDR(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
Loading…
Reference in New Issue
Block a user