mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-04 02:56:18 +00:00
network: Add support for ipvlan
Support ipvlan interfaces by setting up tc redirect rules. Fixes #591 Signed-off-by: Archana Shinde <archana.m.shinde@intel.com>
This commit is contained in:
parent
c7a9e454ac
commit
0acbbf0651
@ -47,6 +47,9 @@ const (
|
|||||||
|
|
||||||
// TapEndpointType is tap network interface.
|
// TapEndpointType is tap network interface.
|
||||||
TapEndpointType EndpointType = "tap"
|
TapEndpointType EndpointType = "tap"
|
||||||
|
|
||||||
|
// IPVlanEndpointType is ipvlan network interface.
|
||||||
|
IPVlanEndpointType EndpointType = "ipvlan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set sets an endpoint type based on the input string.
|
// Set sets an endpoint type based on the input string.
|
||||||
@ -70,6 +73,9 @@ func (endpointType *EndpointType) Set(value string) error {
|
|||||||
case "tap":
|
case "tap":
|
||||||
*endpointType = TapEndpointType
|
*endpointType = TapEndpointType
|
||||||
return nil
|
return nil
|
||||||
|
case "ipvlan":
|
||||||
|
*endpointType = IPVlanEndpointType
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown endpoint type %s", value)
|
return fmt.Errorf("Unknown endpoint type %s", value)
|
||||||
}
|
}
|
||||||
@ -90,6 +96,8 @@ func (endpointType *EndpointType) String() string {
|
|||||||
return string(MacvtapEndpointType)
|
return string(MacvtapEndpointType)
|
||||||
case TapEndpointType:
|
case TapEndpointType:
|
||||||
return string(TapEndpointType)
|
return string(TapEndpointType)
|
||||||
|
case IPVlanEndpointType:
|
||||||
|
return string(IPVlanEndpointType)
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
120
virtcontainers/ipvlan_endpoint.go
Normal file
120
virtcontainers/ipvlan_endpoint.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPVlanEndpoint represents a ipvlan endpoint that is bridged to the VM
|
||||||
|
type IPVlanEndpoint struct {
|
||||||
|
NetPair NetworkInterfacePair
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createIPVlanNetworkEndpoint(idx int, ifName string) (*IPVlanEndpoint, error) {
|
||||||
|
if idx < 0 {
|
||||||
|
return &IPVlanEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use tc filtering for ipvlan, since the other inter networking models will
|
||||||
|
// not work for ipvlan.
|
||||||
|
interworkingModel := NetXConnectTCFilterModel
|
||||||
|
netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &IPVlanEndpoint{
|
||||||
|
NetPair: netPair,
|
||||||
|
EndpointType: IPVlanEndpointType,
|
||||||
|
}
|
||||||
|
if ifName != "" {
|
||||||
|
endpoint.NetPair.VirtIface.Name = ifName
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns properties of the interface.
|
||||||
|
func (endpoint *IPVlanEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the veth interface in the network pair.
|
||||||
|
func (endpoint *IPVlanEndpoint) Name() string {
|
||||||
|
return endpoint.NetPair.VirtIface.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// HardwareAddr returns the mac address that is assigned to the tap interface
|
||||||
|
// in th network pair.
|
||||||
|
func (endpoint *IPVlanEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.NetPair.TAPIface.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type identifies the endpoint as a virtual endpoint.
|
||||||
|
func (endpoint *IPVlanEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties for the endpoint.
|
||||||
|
func (endpoint *IPVlanEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *IPVlanEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *IPVlanEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *IPVlanEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return &endpoint.NetPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for virtual endpoint bridges the network pair and adds the
|
||||||
|
// tap interface of the network pair to the hypervisor.
|
||||||
|
func (endpoint *IPVlanEndpoint) Attach(h hypervisor) error {
|
||||||
|
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error bridging virtual ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.addDevice(endpoint, netDev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach for the virtual endpoint tears down the tap and bridge
|
||||||
|
// created for the veth interface.
|
||||||
|
func (endpoint *IPVlanEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
||||||
|
// The network namespace would have been deleted at this point
|
||||||
|
// if it has not been created by virtcontainers.
|
||||||
|
if !netNsCreated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
return xconnectVMNetwork(endpoint, false, 0, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for physical endpoint not supported yet
|
||||||
|
func (endpoint *IPVlanEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("IPVlanEndpoint does not support Hot attach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for physical endpoint not supported yet
|
||||||
|
func (endpoint *IPVlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
return fmt.Errorf("IPVlanEndpoint does not support Hot detach")
|
||||||
|
}
|
50
virtcontainers/ipvlan_endpoint_test.go
Normal file
50
virtcontainers/ipvlan_endpoint_test.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateIPVlanEndpoint(t *testing.T) {
|
||||||
|
macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x04}
|
||||||
|
|
||||||
|
expected := &IPVlanEndpoint{
|
||||||
|
NetPair: NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
|
ID: "uniqueTestID-5",
|
||||||
|
Name: "br5_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap5_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VirtIface: NetworkInterface{
|
||||||
|
Name: "eth5",
|
||||||
|
HardAddr: macAddr.String(),
|
||||||
|
},
|
||||||
|
|
||||||
|
NetInterworkingModel: NetXConnectTCFilterModel,
|
||||||
|
},
|
||||||
|
EndpointType: IPVlanEndpointType,
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := createIPVlanNetworkEndpoint(5, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the resulting ID will be random - so let's overwrite to test the rest of the flow
|
||||||
|
result.NetPair.ID = "uniqueTestID-5"
|
||||||
|
|
||||||
|
// the resulting mac address will be random - so lets overwrite it
|
||||||
|
result.NetPair.VirtIface.HardAddr = macAddr.String()
|
||||||
|
|
||||||
|
if reflect.DeepEqual(result, expected) == false {
|
||||||
|
t.Fatalf("\nGot: %+v, \n\nExpected: %+v", result, expected)
|
||||||
|
}
|
||||||
|
}
|
@ -454,6 +454,8 @@ func getLinkForEndpoint(endpoint Endpoint, netHandle *netlink.Handle) (netlink.L
|
|||||||
link = &netlink.Veth{}
|
link = &netlink.Veth{}
|
||||||
case *BridgedMacvlanEndpoint:
|
case *BridgedMacvlanEndpoint:
|
||||||
link = &netlink.Macvlan{}
|
link = &netlink.Macvlan{}
|
||||||
|
case *IPVlanEndpoint:
|
||||||
|
link = &netlink.IPVlan{}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unexpected endpointType %s", ep.Type())
|
return nil, fmt.Errorf("Unexpected endpointType %s", ep.Type())
|
||||||
}
|
}
|
||||||
@ -488,6 +490,10 @@ func getLinkByName(netHandle *netlink.Handle, name string, expectedLink netlink.
|
|||||||
if l, ok := link.(*netlink.Macvlan); ok {
|
if l, ok := link.(*netlink.Macvlan); ok {
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
case (&netlink.IPVlan{}).Type():
|
||||||
|
if l, ok := link.(*netlink.IPVlan); ok {
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported link type %s", expectedLink.Type())
|
return nil, fmt.Errorf("Unsupported link type %s", expectedLink.Type())
|
||||||
}
|
}
|
||||||
@ -1405,6 +1411,8 @@ func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (E
|
|||||||
endpoint, err = createTapNetworkEndpoint(idx, netInfo.Iface.Name)
|
endpoint, err = createTapNetworkEndpoint(idx, netInfo.Iface.Name)
|
||||||
} else if netInfo.Iface.Type == "veth" {
|
} else if netInfo.Iface.Type == "veth" {
|
||||||
endpoint, err = createVethNetworkEndpoint(idx, netInfo.Iface.Name, model)
|
endpoint, err = createVethNetworkEndpoint(idx, netInfo.Iface.Name, model)
|
||||||
|
} else if netInfo.Iface.Type == "ipvlan" {
|
||||||
|
endpoint, err = createIPVlanNetworkEndpoint(idx, netInfo.Iface.Name)
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Unsupported network interface")
|
return nil, fmt.Errorf("Unsupported network interface")
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ func networkModelToQemuType(model NetInterworkingModel) govmmQemu.NetDeviceType
|
|||||||
|
|
||||||
func (q *qemuArchBase) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) []govmmQemu.Device {
|
func (q *qemuArchBase) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) []govmmQemu.Device {
|
||||||
switch ep := endpoint.(type) {
|
switch ep := endpoint.(type) {
|
||||||
case *VethEndpoint, *BridgedMacvlanEndpoint:
|
case *VethEndpoint, *BridgedMacvlanEndpoint, *IPVlanEndpoint:
|
||||||
netPair := ep.NetworkPair()
|
netPair := ep.NetworkPair()
|
||||||
devices = append(devices,
|
devices = append(devices,
|
||||||
govmmQemu.NetDevice{
|
govmmQemu.NetDevice{
|
||||||
|
Loading…
Reference in New Issue
Block a user