diff --git a/network.go b/network.go index 21f4a9e66..4717ebaed 100644 --- a/network.go +++ b/network.go @@ -114,7 +114,7 @@ func updateLink(netHandle *netlink.Handle, link netlink.Link, iface *types.Inter } // As a first step, clear out any existing addresses associated with the link: - linkIPs, err := netlink.AddrList(link, netlink.FAMILY_V4) + linkIPs, err := netlink.AddrList(link, netlink.FAMILY_ALL) if err != nil { return grpcStatus.Errorf(codes.Internal, "Could not check initial addresses for the link: %v", err) } @@ -297,7 +297,7 @@ func getInterface(netHandle *netlink.Handle, link netlink.Link) (*types.Interfac ifc.Mtu = uint64(linkAttrs.MTU) ifc.HwAddr = linkAttrs.HardwareAddr.String() - addrs, err := netHandle.AddrList(link, netlink.FAMILY_V4) + addrs, err := netHandle.AddrList(link, netlink.FAMILY_ALL) if err != nil { agentLog.WithError(err).Error("getInterface() failed") return nil, err @@ -308,6 +308,11 @@ func getInterface(netHandle *netlink.Handle, link netlink.Link) (*types.Interfac Address: addr.IP.String(), Mask: fmt.Sprintf("%d", netMask), } + if addr.IP.To4() != nil { + m.Family = types.IPFamily_v4 + } else { + m.Family = types.IPFamily_v6 + } ifc.IPAddresses = append(ifc.IPAddresses, &m) } diff --git a/network_test.go b/network_test.go index 108494dc2..97a80450a 100644 --- a/network_test.go +++ b/network_test.go @@ -254,7 +254,14 @@ func TestListInterfaces(t *testing.T) { Address: "192.168.0.101", Mask: "24", } + ipv4addr := types.IPAddress{ + Family: 1, + Address: "2001:db8:1::242:ac11:5", + Mask: "64", + } + ifc.IPAddresses = append(ifc.IPAddresses, &ip) + ifc.IPAddresses = append(ifc.IPAddresses, &ipv4addr) netHandle, _ := netlink.NewHandle() defer netHandle.Delete() // create a dummy link that we can test update on @@ -275,8 +282,25 @@ func TestListInterfaces(t *testing.T) { // results, err := s.listInterfaces(nil) assert.Nil(err, "Expected to list all interfaces") - assert.True(reflect.DeepEqual(results.Interfaces[1], &ifc), - "Interface listed didn't match: got %+v, expecting %+v", results.Interfaces[1], &ifc) + + resifc := results.Interfaces[1] + assert.Equal(resifc.Name, ifc.Name) + assert.Equal(resifc.Mtu, ifc.Mtu) + assert.Equal(resifc.HwAddr, ifc.HwAddr) + + for i, ip := range ifc.IPAddresses { + assert.True(reflect.DeepEqual(resifc.IPAddresses[i], ip), + "Interface address didn't match: got %+v, expecting %+v", resifc.IPAddresses[i], ip) + } + + // An ipv6 link local address is created by default, using the mac address. + // Check if the additional address is indeed an ipv6 link local address. + if len(resifc.IPAddresses) > len(ifc.IPAddresses) { + ipAddr := resifc.IPAddresses[2] + assert.Equal(ipAddr.Family, types.IPFamily_v6) + ip := net.ParseIP(ipAddr.Address) + assert.True(ip.IsLinkLocalUnicast()) + } } func TestListRoutes(t *testing.T) { @@ -353,6 +377,73 @@ func TestListRoutes(t *testing.T) { "Route listed didn't match: got %+v, expecting %+v", results.Routes[1], inputRoutesSimple[1]) } +func TestListRoutesWithIPV6(t *testing.T) { + tearDown := setupNetworkTest(t) + defer tearDown() + + assert := assert.New(t) + + s := sandbox{} + + // create a dummy link which we'll play with + macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x48} + link := &netlink.Dummy{ + LinkAttrs: netlink.LinkAttrs{ + MTU: 1500, + TxQLen: -1, + Name: "ifc-name", + HardwareAddr: macAddr, + }, + } + netHandle, _ := netlink.NewHandle() + defer netHandle.Delete() + + netHandle.LinkAdd(link) + if err := netHandle.LinkSetUp(link); err != nil { + t.Fatal(err) + } + netlinkAddr, _ := netlink.ParseAddr("192.168.0.2/16") + netHandle.AddrAdd(link, netlinkAddr) + + netlinkAddrV6, _ := netlink.ParseAddr("2001:db8:1::242:ac11:2/64") + netHandle.AddrAdd(link, netlinkAddrV6) + + //Test a simple route setup: + inputRoutesSimple := []*types.Route{ + {Dest: "", Gateway: "192.168.0.1", Source: "", Scope: 0, Device: "ifc-name"}, + {Dest: "", Gateway: "2001:db8:1::1", Source: "", Scope: 0, Device: "ifc-name"}, + } + + expectedRoutes := []*types.Route{ + {Dest: "", Gateway: "192.168.0.1", Source: "", Scope: 0, Device: "ifc-name"}, + // This route is auto-added by kernel, and we no longer delete kernel proto routes + {Dest: "192.168.0.0/16", Gateway: "", Source: "192.168.0.2", Scope: 253, Device: "ifc-name"}, + {Dest: "2001:db8:1::/64", Gateway: "", Source: "", Scope: 0, Device: "ifc-name"}, + {Dest: "fe80::/64", Gateway: "", Source: "", Scope: 0, Device: "ifc-name"}, + {Dest: "", Gateway: "2001:db8:1::1", Source: "", Scope: 0, Device: "ifc-name"}, + } + + testRoutes := &pb.Routes{ + Routes: inputRoutesSimple, + } + + _, err := s.updateRoutes(netHandle, testRoutes) + assert.Nil(err) + results, err := s.listRoutes(nil) + assert.Nil(err, "Expected to list all routes") + + assert.True(reflect.DeepEqual(results.Routes[0], expectedRoutes[0]), + "Route listed didn't match: got %+v, expecting %+v", results.Routes[0], expectedRoutes[0]) + assert.True(reflect.DeepEqual(results.Routes[1], expectedRoutes[1]), + "Route listed didn't match: got %+v, expecting %+v", results.Routes[1], expectedRoutes[1]) + assert.True(reflect.DeepEqual(results.Routes[2], expectedRoutes[2]), + "Route listed didn't match: got %+v, expecting %+v", results.Routes[2], expectedRoutes[2]) + assert.True(reflect.DeepEqual(results.Routes[3], expectedRoutes[3]), + "Route listed didn't match: got %+v, expecting %+v", results.Routes[3], expectedRoutes[3]) + assert.True(reflect.DeepEqual(results.Routes[4], expectedRoutes[4]), + "Route listed didn't match: got %+v, expecting %+v", results.Routes[4], expectedRoutes[4]) +} + func TestListRoutesWithTwoInterfacesSameSubnet(t *testing.T) { tearDown := setupNetworkTest(t) defer tearDown()