summaryrefslogtreecommitdiff
path: root/vendor/k8s.io/apimachinery/pkg/util/net/interface.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/apimachinery/pkg/util/net/interface.go')
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/net/interface.go73
1 files changed, 57 insertions, 16 deletions
diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/interface.go b/vendor/k8s.io/apimachinery/pkg/util/net/interface.go
index daf5d2496..836494d57 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/net/interface.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/net/interface.go
@@ -36,6 +36,18 @@ const (
familyIPv6 AddressFamily = 6
)
+type AddressFamilyPreference []AddressFamily
+
+var (
+ preferIPv4 = AddressFamilyPreference{familyIPv4, familyIPv6}
+ preferIPv6 = AddressFamilyPreference{familyIPv6, familyIPv4}
+)
+
+const (
+ // LoopbackInterfaceName is the default name of the loopback interface
+ LoopbackInterfaceName = "lo"
+)
+
const (
ipv4RouteFile = "/proc/net/route"
ipv6RouteFile = "/proc/net/ipv6_route"
@@ -53,7 +65,7 @@ type RouteFile struct {
parse func(input io.Reader) ([]Route, error)
}
-// noRoutesError can be returned by ChooseBindAddress() in case of no routes
+// noRoutesError can be returned in case of no routes
type noRoutesError struct {
message string
}
@@ -254,7 +266,7 @@ func getIPFromInterface(intfName string, forFamily AddressFamily, nw networkInte
return nil, nil
}
-// memberOF tells if the IP is of the desired family. Used for checking interface addresses.
+// memberOf tells if the IP is of the desired family. Used for checking interface addresses.
func memberOf(ip net.IP, family AddressFamily) bool {
if ip.To4() != nil {
return family == familyIPv4
@@ -265,8 +277,8 @@ func memberOf(ip net.IP, family AddressFamily) bool {
// chooseIPFromHostInterfaces looks at all system interfaces, trying to find one that is up that
// has a global unicast address (non-loopback, non-link local, non-point2point), and returns the IP.
-// Searches for IPv4 addresses, and then IPv6 addresses.
-func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
+// addressFamilies determines whether it prefers IPv4 or IPv6
+func chooseIPFromHostInterfaces(nw networkInterfacer, addressFamilies AddressFamilyPreference) (net.IP, error) {
intfs, err := nw.Interfaces()
if err != nil {
return nil, err
@@ -274,7 +286,7 @@ func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
if len(intfs) == 0 {
return nil, fmt.Errorf("no interfaces found on host.")
}
- for _, family := range []AddressFamily{familyIPv4, familyIPv6} {
+ for _, family := range addressFamilies {
klog.V(4).Infof("Looking for system interface with a global IPv%d address", uint(family))
for _, intf := range intfs {
if !isInterfaceUp(&intf) {
@@ -321,15 +333,19 @@ func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
// IP of the interface with a gateway on it (with priority given to IPv4). For a node
// with no internet connection, it returns error.
func ChooseHostInterface() (net.IP, error) {
+ return chooseHostInterface(preferIPv4)
+}
+
+func chooseHostInterface(addressFamilies AddressFamilyPreference) (net.IP, error) {
var nw networkInterfacer = networkInterface{}
if _, err := os.Stat(ipv4RouteFile); os.IsNotExist(err) {
- return chooseIPFromHostInterfaces(nw)
+ return chooseIPFromHostInterfaces(nw, addressFamilies)
}
routes, err := getAllDefaultRoutes()
if err != nil {
return nil, err
}
- return chooseHostInterfaceFromRoute(routes, nw)
+ return chooseHostInterfaceFromRoute(routes, nw, addressFamilies)
}
// networkInterfacer defines an interface for several net library functions. Production
@@ -377,10 +393,10 @@ func getAllDefaultRoutes() ([]Route, error) {
}
// chooseHostInterfaceFromRoute cycles through each default route provided, looking for a
-// global IP address from the interface for the route. Will first look all each IPv4 route for
-// an IPv4 IP, and then will look at each IPv6 route for an IPv6 IP.
-func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer) (net.IP, error) {
- for _, family := range []AddressFamily{familyIPv4, familyIPv6} {
+// global IP address from the interface for the route. addressFamilies determines whether it
+// prefers IPv4 or IPv6
+func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer, addressFamilies AddressFamilyPreference) (net.IP, error) {
+ for _, family := range addressFamilies {
klog.V(4).Infof("Looking for default routes with IPv%d addresses", uint(family))
for _, route := range routes {
if route.Family != family {
@@ -401,12 +417,19 @@ func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer) (net.IP,
return nil, fmt.Errorf("unable to select an IP from default routes.")
}
-// If bind-address is usable, return it directly
-// If bind-address is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
-// interface.
-func ChooseBindAddress(bindAddress net.IP) (net.IP, error) {
+// ResolveBindAddress returns the IP address of a daemon, based on the given bindAddress:
+// If bindAddress is unset, it returns the host's default IP, as with ChooseHostInterface().
+// If bindAddress is unspecified or loopback, it returns the default IP of the same
+// address family as bindAddress.
+// Otherwise, it just returns bindAddress.
+func ResolveBindAddress(bindAddress net.IP) (net.IP, error) {
+ addressFamilies := preferIPv4
+ if bindAddress != nil && memberOf(bindAddress, familyIPv6) {
+ addressFamilies = preferIPv6
+ }
+
if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
- hostIP, err := ChooseHostInterface()
+ hostIP, err := chooseHostInterface(addressFamilies)
if err != nil {
return nil, err
}
@@ -414,3 +437,21 @@ func ChooseBindAddress(bindAddress net.IP) (net.IP, error) {
}
return bindAddress, nil
}
+
+// ChooseBindAddressForInterface choose a global IP for a specific interface, with priority given to IPv4.
+// This is required in case of network setups where default routes are present, but network
+// interfaces use only link-local addresses (e.g. as described in RFC5549).
+// e.g when using BGP to announce a host IP over link-local ip addresses and this ip address is attached to the lo interface.
+func ChooseBindAddressForInterface(intfName string) (net.IP, error) {
+ var nw networkInterfacer = networkInterface{}
+ for _, family := range preferIPv4 {
+ ip, err := getIPFromInterface(intfName, family, nw)
+ if err != nil {
+ return nil, err
+ }
+ if ip != nil {
+ return ip, nil
+ }
+ }
+ return nil, fmt.Errorf("unable to select an IP from %s network interface", intfName)
+}