get ips from loopback interfaces

This commit is contained in:
Antonio Ojea 2020-11-14 22:11:41 +01:00
parent 078d2e65b5
commit 432e74d245
2 changed files with 59 additions and 2 deletions

View File

@ -266,6 +266,36 @@ func getIPFromInterface(intfName string, forFamily AddressFamily, nw networkInte
return nil, nil
}
// getIPFromLoopbackInterface gets the IPs on a loopback interface and returns a global unicast address, if any.
// The loopback interface must be up, the IP must in the family requested, and the IP must be a global unicast address.
func getIPFromLoopbackInterface(forFamily AddressFamily, nw networkInterfacer) (net.IP, error) {
intfs, err := nw.Interfaces()
if err != nil {
return nil, err
}
for _, intf := range intfs {
if !isInterfaceUp(&intf) {
continue
}
if intf.Flags&(net.FlagLoopback) != 0 {
addrs, err := nw.Addrs(&intf)
if err != nil {
return nil, err
}
klog.V(4).Infof("Interface %q has %d addresses :%v.", intf.Name, len(addrs), addrs)
matchingIP, err := getMatchingGlobalIP(addrs, forFamily)
if err != nil {
return nil, err
}
if matchingIP != nil {
klog.V(4).Infof("Found valid IPv%d address %v for interface %q.", int(forFamily), matchingIP, intf.Name)
return matchingIP, nil
}
}
}
return nil, nil
}
// 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 {
@ -414,8 +444,8 @@ func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer, addressF
}
// In case of network setups where default routes are present, but network
// interfaces use only link-local addresses (e.g. as described in RFC5549).
// the global IP is assigned to the loopback interface
loopbackIP, err := getIPFromInterface(LoopbackInterfaceName, family, nw)
// the global IP is assigned to the loopback interface, and we should use it
loopbackIP, err := getIPFromLoopbackInterface(family, nw)
if err != nil {
return nil, err
}

View File

@ -579,6 +579,33 @@ func TestGetIPFromInterface(t *testing.T) {
}
}
func TestGetIPFromLoopbackInterface(t *testing.T) {
testCases := []struct {
tcase string
family AddressFamily
nw networkInterfacer
expected net.IP
errStrFrag string
}{
{"ipv4", familyIPv4, linkLocalLoopbackNetworkInterface{}, net.ParseIP("10.1.1.1"), ""},
{"ipv6", familyIPv6, linkLocalLoopbackNetworkInterface{}, net.ParseIP("fd00:1:1::1"), ""},
{"no global ipv4", familyIPv4, loopbackNetworkInterface{}, nil, ""},
{"no global ipv6", familyIPv6, loopbackNetworkInterface{}, nil, ""},
}
for _, tc := range testCases {
ip, err := getIPFromLoopbackInterface(tc.family, tc.nw)
if err != nil {
if !strings.Contains(err.Error(), tc.errStrFrag) {
t.Errorf("case[%s]: Error string %q does not contain %q", tc.tcase, err, tc.errStrFrag)
}
} else if tc.errStrFrag != "" {
t.Errorf("case[%s]: Error %q expected, but seen %v", tc.tcase, tc.errStrFrag, err)
} else if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestChooseHostInterfaceFromRoute(t *testing.T) {
testCases := []struct {
tcase string