diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go index cffbc7f24f..4c90ebcea9 100644 --- a/virtcontainers/kata_agent.go +++ b/virtcontainers/kata_agent.go @@ -381,95 +381,6 @@ func (k *kataAgent) exec(sandbox *Sandbox, c Container, cmd Cmd) (*Process, erro k.state.URL, cmd, []ns.NSType{}, enterNSList) } -func (k *kataAgent) generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) { - span, _ := k.trace("generateInterfacesAndRoutes") - defer span.Finish() - - if networkNS.NetNsPath == "" { - return nil, nil, nil - } - - var routes []*grpc.Route - var ifaces []*grpc.Interface - - for _, endpoint := range networkNS.Endpoints { - - var ipAddresses []*grpc.IPAddress - for _, addr := range endpoint.Properties().Addrs { - // Skip IPv6 because not supported - if addr.IP.To4() == nil { - // Skip IPv6 because not supported - k.Logger().WithFields(logrus.Fields{ - "unsupported-address-type": "ipv6", - "address": addr, - }).Warn("unsupported address") - continue - } - // Skip localhost interface - if addr.IP.IsLoopback() { - continue - } - netMask, _ := addr.Mask.Size() - ipAddress := grpc.IPAddress{ - Family: grpc.IPFamily_v4, - Address: addr.IP.String(), - Mask: fmt.Sprintf("%d", netMask), - } - ipAddresses = append(ipAddresses, &ipAddress) - } - ifc := grpc.Interface{ - IPAddresses: ipAddresses, - Device: endpoint.Name(), - Name: endpoint.Name(), - Mtu: uint64(endpoint.Properties().Iface.MTU), - HwAddr: endpoint.HardwareAddr(), - } - - ifaces = append(ifaces, &ifc) - - for _, route := range endpoint.Properties().Routes { - var r grpc.Route - - if route.Dst != nil { - r.Dest = route.Dst.String() - - if route.Dst.IP.To4() == nil { - // Skip IPv6 because not supported - k.Logger().WithFields(logrus.Fields{ - "unsupported-route-type": "ipv6", - "destination": r.Dest, - }).Warn("unsupported route") - continue - } - } - - if route.Gw != nil { - gateway := route.Gw.String() - - if route.Gw.To4() == nil { - // Skip IPv6 because is is not supported - k.Logger().WithFields(logrus.Fields{ - "unsupported-route-type": "ipv6", - "gateway": gateway, - }).Warn("unsupported route") - continue - } - r.Gateway = gateway - } - - if route.Src != nil { - r.Source = route.Src.String() - } - - r.Device = endpoint.Name() - r.Scope = uint32(route.Scope) - routes = append(routes, &r) - - } - } - return ifaces, routes, nil -} - func (k *kataAgent) updateInterface(ifc *grpc.Interface) (*grpc.Interface, error) { // send update interface request ifcReq := &grpc.UpdateInterfaceRequest{ @@ -623,7 +534,7 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error { // // Setup network interfaces and routes // - interfaces, routes, err := k.generateInterfacesAndRoutes(sandbox.networkNS) + interfaces, routes, err := generateInterfacesAndRoutes(sandbox.networkNS) if err != nil { return err } diff --git a/virtcontainers/kata_agent_test.go b/virtcontainers/kata_agent_test.go index cc908d9e14..3f21d6df2f 100644 --- a/virtcontainers/kata_agent_test.go +++ b/virtcontainers/kata_agent_test.go @@ -20,7 +20,6 @@ import ( gpb "github.com/gogo/protobuf/types" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" - "github.com/vishvananda/netlink" "golang.org/x/net/context" "google.golang.org/grpc" @@ -339,100 +338,6 @@ func TestKataAgentSendReq(t *testing.T) { assert.Nil(err) } -func TestGenerateInterfacesAndRoutes(t *testing.T) { - - impl := &gRPCProxy{} - - proxy := mock.ProxyGRPCMock{ - GRPCImplementer: impl, - GRPCRegister: gRPCRegister, - } - - sockDir, err := testGenerateKataProxySockDir() - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(sockDir) - - testKataProxyURL := fmt.Sprintf(testKataProxyURLTempl, sockDir) - if err := proxy.Start(testKataProxyURL); err != nil { - t.Fatal(err) - } - defer proxy.Stop() - - k := &kataAgent{ - state: KataAgentState{ - URL: testKataProxyURL, - }, - } - - // - //Create a couple of addresses - // - address1 := &net.IPNet{IP: net.IPv4(172, 17, 0, 2), Mask: net.CIDRMask(16, 32)} - address2 := &net.IPNet{IP: net.IPv4(182, 17, 0, 2), Mask: net.CIDRMask(16, 32)} - - addrs := []netlink.Addr{ - {IPNet: address1, Label: "phyaddr1"}, - {IPNet: address2, Label: "phyaddr2"}, - } - - // Create a couple of routes: - dst2 := &net.IPNet{IP: net.IPv4(172, 17, 0, 0), Mask: net.CIDRMask(16, 32)} - src2 := net.IPv4(172, 17, 0, 2) - gw2 := net.IPv4(172, 17, 0, 1) - - routes := []netlink.Route{ - {LinkIndex: 329, Dst: nil, Src: nil, Gw: net.IPv4(172, 17, 0, 1), Scope: netlink.Scope(254)}, - {LinkIndex: 329, Dst: dst2, Src: src2, Gw: gw2}, - } - - networkInfo := NetworkInfo{ - Iface: NetlinkIface{ - LinkAttrs: netlink.LinkAttrs{MTU: 1500}, - Type: "", - }, - Addrs: addrs, - Routes: routes, - } - - ep0 := &PhysicalEndpoint{ - IfaceName: "eth0", - HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(), - EndpointProperties: networkInfo, - } - - endpoints := []Endpoint{ep0} - - nns := NetworkNamespace{NetNsPath: "foobar", NetNsCreated: true, Endpoints: endpoints} - - resInterfaces, resRoutes, err := k.generateInterfacesAndRoutes(nns) - - // - // Build expected results: - // - expectedAddresses := []*pb.IPAddress{ - {Family: 0, Address: "172.17.0.2", Mask: "16"}, - {Family: 0, Address: "182.17.0.2", Mask: "16"}, - } - - expectedInterfaces := []*pb.Interface{ - {Device: "eth0", Name: "eth0", IPAddresses: expectedAddresses, Mtu: 1500, HwAddr: "02:00:ca:fe:00:04"}, - } - - expectedRoutes := []*pb.Route{ - {Dest: "", Gateway: "172.17.0.1", Device: "eth0", Source: "", Scope: uint32(254)}, - {Dest: "172.17.0.0/16", Gateway: "172.17.0.1", Device: "eth0", Source: "172.17.0.2"}, - } - - assert.Nil(t, err, "unexpected failure when calling generateKataInterfacesAndRoutes") - assert.True(t, reflect.DeepEqual(resInterfaces, expectedInterfaces), - "Interfaces returned didn't match: got %+v, expecting %+v", resInterfaces, expectedInterfaces) - assert.True(t, reflect.DeepEqual(resRoutes, expectedRoutes), - "Routes returned didn't match: got %+v, expecting %+v", resRoutes, expectedRoutes) - -} - func TestHandleEphemeralStorage(t *testing.T) { k := kataAgent{} var ociMounts []specs.Mount diff --git a/virtcontainers/network.go b/virtcontainers/network.go index 92602b2d90..8768ffa377 100644 --- a/virtcontainers/network.go +++ b/virtcontainers/network.go @@ -27,6 +27,7 @@ import ( "github.com/vishvananda/netns" "golang.org/x/sys/unix" + "github.com/kata-containers/agent/protocols/grpc" "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/drivers" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid" @@ -1340,6 +1341,93 @@ func createVirtualNetworkEndpoint(idx int, ifName string, interworkingModel NetI return endpoint, nil } +func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) { + + if networkNS.NetNsPath == "" { + return nil, nil, nil + } + + var routes []*grpc.Route + var ifaces []*grpc.Interface + + for _, endpoint := range networkNS.Endpoints { + + var ipAddresses []*grpc.IPAddress + for _, addr := range endpoint.Properties().Addrs { + // Skip IPv6 because not supported + if addr.IP.To4() == nil { + // Skip IPv6 because not supported + networkLogger().WithFields(logrus.Fields{ + "unsupported-address-type": "ipv6", + "address": addr, + }).Warn("unsupported address") + continue + } + // Skip localhost interface + if addr.IP.IsLoopback() { + continue + } + netMask, _ := addr.Mask.Size() + ipAddress := grpc.IPAddress{ + Family: grpc.IPFamily_v4, + Address: addr.IP.String(), + Mask: fmt.Sprintf("%d", netMask), + } + ipAddresses = append(ipAddresses, &ipAddress) + } + ifc := grpc.Interface{ + IPAddresses: ipAddresses, + Device: endpoint.Name(), + Name: endpoint.Name(), + Mtu: uint64(endpoint.Properties().Iface.MTU), + HwAddr: endpoint.HardwareAddr(), + } + + ifaces = append(ifaces, &ifc) + + for _, route := range endpoint.Properties().Routes { + var r grpc.Route + + if route.Dst != nil { + r.Dest = route.Dst.String() + + if route.Dst.IP.To4() == nil { + // Skip IPv6 because not supported + networkLogger().WithFields(logrus.Fields{ + "unsupported-route-type": "ipv6", + "destination": r.Dest, + }).Warn("unsupported route") + continue + } + } + + if route.Gw != nil { + gateway := route.Gw.String() + + if route.Gw.To4() == nil { + // Skip IPv6 because is is not supported + networkLogger().WithFields(logrus.Fields{ + "unsupported-route-type": "ipv6", + "gateway": gateway, + }).Warn("unsupported route") + continue + } + r.Gateway = gateway + } + + if route.Src != nil { + r.Source = route.Src.String() + } + + r.Device = endpoint.Name() + r.Scope = uint32(route.Scope) + routes = append(routes, &r) + + } + } + return ifaces, routes, nil +} + func networkInfoFromLink(handle *netlink.Handle, link netlink.Link) (NetworkInfo, error) { addrs, err := handle.AddrList(link, netlink.FAMILY_ALL) if err != nil { diff --git a/virtcontainers/network_test.go b/virtcontainers/network_test.go index ce1ddaf08b..ab4789b4a6 100644 --- a/virtcontainers/network_test.go +++ b/virtcontainers/network_test.go @@ -16,6 +16,7 @@ import ( "testing" "github.com/containernetworking/plugins/pkg/ns" + "github.com/kata-containers/agent/protocols/grpc" "github.com/stretchr/testify/assert" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" @@ -614,3 +615,71 @@ func TestHostNetworkingRequested(t *testing.T) { syscall.Unmount(tmpFile, 0) } + +func TestGenerateInterfacesAndRoutes(t *testing.T) { + // + //Create a couple of addresses + // + address1 := &net.IPNet{IP: net.IPv4(172, 17, 0, 2), Mask: net.CIDRMask(16, 32)} + address2 := &net.IPNet{IP: net.IPv4(182, 17, 0, 2), Mask: net.CIDRMask(16, 32)} + + addrs := []netlink.Addr{ + {IPNet: address1, Label: "phyaddr1"}, + {IPNet: address2, Label: "phyaddr2"}, + } + + // Create a couple of routes: + dst2 := &net.IPNet{IP: net.IPv4(172, 17, 0, 0), Mask: net.CIDRMask(16, 32)} + src2 := net.IPv4(172, 17, 0, 2) + gw2 := net.IPv4(172, 17, 0, 1) + + routes := []netlink.Route{ + {LinkIndex: 329, Dst: nil, Src: nil, Gw: net.IPv4(172, 17, 0, 1), Scope: netlink.Scope(254)}, + {LinkIndex: 329, Dst: dst2, Src: src2, Gw: gw2}, + } + + networkInfo := NetworkInfo{ + Iface: NetlinkIface{ + LinkAttrs: netlink.LinkAttrs{MTU: 1500}, + Type: "", + }, + Addrs: addrs, + Routes: routes, + } + + ep0 := &PhysicalEndpoint{ + IfaceName: "eth0", + HardAddr: net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(), + EndpointProperties: networkInfo, + } + + endpoints := []Endpoint{ep0} + + nns := NetworkNamespace{NetNsPath: "foobar", NetNsCreated: true, Endpoints: endpoints} + + resInterfaces, resRoutes, err := generateInterfacesAndRoutes(nns) + + // + // Build expected results: + // + expectedAddresses := []*grpc.IPAddress{ + {Family: 0, Address: "172.17.0.2", Mask: "16"}, + {Family: 0, Address: "182.17.0.2", Mask: "16"}, + } + + expectedInterfaces := []*grpc.Interface{ + {Device: "eth0", Name: "eth0", IPAddresses: expectedAddresses, Mtu: 1500, HwAddr: "02:00:ca:fe:00:04"}, + } + + expectedRoutes := []*grpc.Route{ + {Dest: "", Gateway: "172.17.0.1", Device: "eth0", Source: "", Scope: uint32(254)}, + {Dest: "172.17.0.0/16", Gateway: "172.17.0.1", Device: "eth0", Source: "172.17.0.2"}, + } + + assert.Nil(t, err, "unexpected failure when calling generateKataInterfacesAndRoutes") + assert.True(t, reflect.DeepEqual(resInterfaces, expectedInterfaces), + "Interfaces returned didn't match: got %+v, expecting %+v", resInterfaces, expectedInterfaces) + assert.True(t, reflect.DeepEqual(resRoutes, expectedRoutes), + "Routes returned didn't match: got %+v, expecting %+v", resRoutes, expectedRoutes) + +}