mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-18 01:13:56 +00:00
Merge pull request #733 from caoruidong/qemu-ns
cli: add configuration option to use or not use host netns
This commit is contained in:
commit
5a8b738818
@ -108,6 +108,7 @@ type proxy struct {
|
|||||||
type runtime struct {
|
type runtime struct {
|
||||||
Debug bool `toml:"enable_debug"`
|
Debug bool `toml:"enable_debug"`
|
||||||
Tracing bool `toml:"enable_tracing"`
|
Tracing bool `toml:"enable_tracing"`
|
||||||
|
DisableNewNetNs bool `toml:"disable_new_netns"`
|
||||||
InterNetworkModel string `toml:"internetworking_model"`
|
InterNetworkModel string `toml:"internetworking_model"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,9 +599,7 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
|||||||
kataLog.Logger.Level = originalLoggerLevel
|
kataLog.Logger.Level = originalLoggerLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
if tomlConf.Runtime.Tracing {
|
tracing = tomlConf.Runtime.Tracing
|
||||||
tracing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if tomlConf.Runtime.InterNetworkModel != "" {
|
if tomlConf.Runtime.InterNetworkModel != "" {
|
||||||
err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel)
|
err = config.InterNetworkModel.SetModel(tomlConf.Runtime.InterNetworkModel)
|
||||||
@ -626,6 +625,11 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
|||||||
return "", config, err
|
return "", config, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.DisableNewNetNs = tomlConf.Runtime.DisableNewNetNs
|
||||||
|
if err := checkNetNsConfig(config); err != nil {
|
||||||
|
return "", config, err
|
||||||
|
}
|
||||||
|
|
||||||
// use no proxy if HypervisorConfig.UseVSock is true
|
// use no proxy if HypervisorConfig.UseVSock is true
|
||||||
if config.HypervisorConfig.UseVSock {
|
if config.HypervisorConfig.UseVSock {
|
||||||
kataLog.Info("VSOCK supported, configure to not use proxy")
|
kataLog.Info("VSOCK supported, configure to not use proxy")
|
||||||
@ -640,6 +644,20 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
|
|||||||
return resolved, config, nil
|
return resolved, config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkNetNsConfig performs sanity checks on disable_new_netns config.
|
||||||
|
// Because it is an expert option and conflicts with some other common configs.
|
||||||
|
func checkNetNsConfig(config oci.RuntimeConfig) error {
|
||||||
|
if config.DisableNewNetNs {
|
||||||
|
if config.NetmonConfig.Enable {
|
||||||
|
return fmt.Errorf("config disable_new_netns conflicts with enable_netmon")
|
||||||
|
}
|
||||||
|
if config.InterNetworkModel != vc.NetXConnectNoneModel {
|
||||||
|
return fmt.Errorf("config disable_new_netns only works with 'none' internetworking_model")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// checkHypervisorConfig performs basic "sanity checks" on the hypervisor
|
// checkHypervisorConfig performs basic "sanity checks" on the hypervisor
|
||||||
// config.
|
// config.
|
||||||
func checkHypervisorConfig(config vc.HypervisorConfig) error {
|
func checkHypervisorConfig(config vc.HypervisorConfig) error {
|
||||||
|
@ -230,9 +230,23 @@ path = "@NETMONPATH@"
|
|||||||
# - macvtap
|
# - macvtap
|
||||||
# Used when the Container network interface can be bridged using
|
# Used when the Container network interface can be bridged using
|
||||||
# macvtap.
|
# macvtap.
|
||||||
|
#
|
||||||
|
# - none
|
||||||
|
# Used when customize network. Only creates a tap device. No veth pair.
|
||||||
|
#
|
||||||
internetworking_model="@DEFNETWORKMODEL@"
|
internetworking_model="@DEFNETWORKMODEL@"
|
||||||
|
|
||||||
# If enabled, the runtime will create opentracing.io traces and spans.
|
# If enabled, the runtime will create opentracing.io traces and spans.
|
||||||
# (See https://www.jaegertracing.io/docs/getting-started).
|
# (See https://www.jaegertracing.io/docs/getting-started).
|
||||||
# (default: disabled)
|
# (default: disabled)
|
||||||
#enable_tracing = true
|
#enable_tracing = true
|
||||||
|
|
||||||
|
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
|
||||||
|
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
|
||||||
|
# `disable_new_netns` conflicts with `enable_netmon`
|
||||||
|
# `disable_new_netns` conflicts with `internetworking_model=bridged` and `internetworking_model=macvtap`. It works only
|
||||||
|
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
|
||||||
|
# (like OVS) directly.
|
||||||
|
# If you are using docker, `disable_new_netns` only works with `docker run --net=none`
|
||||||
|
# (default: false)
|
||||||
|
#disable_new_netns = true
|
||||||
|
@ -42,7 +42,7 @@ type testRuntimeConfig struct {
|
|||||||
LogPath string
|
LogPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus bool) string {
|
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus, disableNewNetNs bool) string {
|
||||||
return `
|
return `
|
||||||
# Runtime configuration file
|
# Runtime configuration file
|
||||||
|
|
||||||
@ -77,7 +77,8 @@ func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath
|
|||||||
enable_debug = ` + strconv.FormatBool(netmonDebug) + `
|
enable_debug = ` + strconv.FormatBool(netmonDebug) + `
|
||||||
|
|
||||||
[runtime]
|
[runtime]
|
||||||
enable_debug = ` + strconv.FormatBool(runtimeDebug)
|
enable_debug = ` + strconv.FormatBool(runtimeDebug) + `
|
||||||
|
disable_new_netns= ` + strconv.FormatBool(disableNewNetNs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createConfig(configPath string, fileData string) error {
|
func createConfig(configPath string, fileData string) error {
|
||||||
@ -116,8 +117,9 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
blockDeviceDriver := "virtio-scsi"
|
blockDeviceDriver := "virtio-scsi"
|
||||||
enableIOThreads := true
|
enableIOThreads := true
|
||||||
hotplugVFIOOnRootBus := true
|
hotplugVFIOOnRootBus := true
|
||||||
|
disableNewNetNs := false
|
||||||
|
|
||||||
runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus)
|
runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus, disableNewNetNs)
|
||||||
|
|
||||||
configPath := path.Join(dir, "runtime.toml")
|
configPath := path.Join(dir, "runtime.toml")
|
||||||
err = createConfig(configPath, runtimeConfigFileData)
|
err = createConfig(configPath, runtimeConfigFileData)
|
||||||
@ -193,6 +195,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
ShimConfig: shimConfig,
|
ShimConfig: shimConfig,
|
||||||
|
|
||||||
NetmonConfig: netmonConfig,
|
NetmonConfig: netmonConfig,
|
||||||
|
DisableNewNetNs: disableNewNetNs,
|
||||||
}
|
}
|
||||||
|
|
||||||
config = testRuntimeConfig{
|
config = testRuntimeConfig{
|
||||||
@ -1455,3 +1458,23 @@ func TestCheckHypervisorConfig(t *testing.T) {
|
|||||||
kataLog.Logger.Out = savedOut
|
kataLog.Logger.Out = savedOut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckNetNsConfig(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
config := oci.RuntimeConfig{
|
||||||
|
DisableNewNetNs: true,
|
||||||
|
NetmonConfig: vc.NetmonConfig{
|
||||||
|
Enable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := checkNetNsConfig(config)
|
||||||
|
assert.Error(err)
|
||||||
|
|
||||||
|
config = oci.RuntimeConfig{
|
||||||
|
DisableNewNetNs: true,
|
||||||
|
InterNetworkModel: vc.NetXConnectDefaultModel,
|
||||||
|
}
|
||||||
|
err = checkNetNsConfig(config)
|
||||||
|
assert.Error(err)
|
||||||
|
}
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
//
|
//
|
||||||
// XXX: Increment for every change to the output format
|
// XXX: Increment for every change to the output format
|
||||||
// (meaning any change to the EnvInfo type).
|
// (meaning any change to the EnvInfo type).
|
||||||
const formatVersion = "1.0.18"
|
const formatVersion = "1.0.19"
|
||||||
|
|
||||||
// MetaInfo stores information on the format of the output itself
|
// MetaInfo stores information on the format of the output itself
|
||||||
type MetaInfo struct {
|
type MetaInfo struct {
|
||||||
@ -65,6 +65,7 @@ type RuntimeInfo struct {
|
|||||||
Version RuntimeVersionInfo
|
Version RuntimeVersionInfo
|
||||||
Config RuntimeConfigInfo
|
Config RuntimeConfigInfo
|
||||||
Debug bool
|
Debug bool
|
||||||
|
DisableNewNetNs bool
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ func getRuntimeInfo(configFile string, config oci.RuntimeConfig) RuntimeInfo {
|
|||||||
Version: runtimeVersion,
|
Version: runtimeVersion,
|
||||||
Config: runtimeConfig,
|
Config: runtimeConfig,
|
||||||
Path: runtimePath,
|
Path: runtimePath,
|
||||||
|
DisableNewNetNs: config.DisableNewNetNs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
|
|||||||
blockStorageDriver := "virtio-scsi"
|
blockStorageDriver := "virtio-scsi"
|
||||||
enableIOThreads := true
|
enableIOThreads := true
|
||||||
hotplugVFIOOnRootBus := true
|
hotplugVFIOOnRootBus := true
|
||||||
|
disableNewNetNs := false
|
||||||
|
|
||||||
// override
|
// override
|
||||||
defaultProxyPath = proxyPath
|
defaultProxyPath = proxyPath
|
||||||
@ -121,6 +122,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
|
|||||||
blockStorageDriver,
|
blockStorageDriver,
|
||||||
enableIOThreads,
|
enableIOThreads,
|
||||||
hotplugVFIOOnRootBus,
|
hotplugVFIOOnRootBus,
|
||||||
|
disableNewNetNs,
|
||||||
)
|
)
|
||||||
|
|
||||||
configFile = path.Join(prefixDir, "runtime.toml")
|
configFile = path.Join(prefixDir, "runtime.toml")
|
||||||
@ -295,6 +297,7 @@ func getExpectedRuntimeDetails(config oci.RuntimeConfig, configFile string) Runt
|
|||||||
},
|
},
|
||||||
Path: runtimePath,
|
Path: runtimePath,
|
||||||
Debug: config.Debug,
|
Debug: config.Debug,
|
||||||
|
DisableNewNetNs: config.DisableNewNetNs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +336,11 @@ func hostNetworkingRequested(configNetNs string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupNetworkNamespace(config *vc.NetworkConfig) error {
|
func setupNetworkNamespace(config *vc.NetworkConfig) error {
|
||||||
|
if config.DisableNewNetNs {
|
||||||
|
kataLog.Info("DisableNewNetNs is on, shim and hypervisor are running in the host netns")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if config.NetNSPath == "" {
|
if config.NetNSPath == "" {
|
||||||
n, err := ns.NewNS()
|
n, err := ns.NewNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -217,4 +217,9 @@ func TestSetupNetworkNamespace(t *testing.T) {
|
|||||||
n.Close()
|
n.Close()
|
||||||
unix.Unmount(config.NetNSPath, unix.MNT_DETACH)
|
unix.Unmount(config.NetNSPath, unix.MNT_DETACH)
|
||||||
os.RemoveAll(config.NetNSPath)
|
os.RemoveAll(config.NetNSPath)
|
||||||
|
|
||||||
|
// Config with DisableNewNetNs
|
||||||
|
config = &vc.NetworkConfig{DisableNewNetNs: true}
|
||||||
|
err = setupNetworkNamespace(config)
|
||||||
|
assert.NoError(err)
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,11 @@ func (endpoint *BridgedMacvlanEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *BridgedMacvlanEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *BridgedMacvlanEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return &endpoint.NetPair
|
return &endpoint.NetPair
|
||||||
|
@ -16,15 +16,17 @@ func TestCreateBridgedMacvlanEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
expected := &BridgedMacvlanEndpoint{
|
expected := &BridgedMacvlanEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
ID: "uniqueTestID-4",
|
ID: "uniqueTestID-4",
|
||||||
Name: "br4_kata",
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: BridgedMacvlanEndpointType,
|
EndpointType: BridgedMacvlanEndpointType,
|
||||||
|
@ -7,7 +7,6 @@ package virtcontainers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
@ -35,10 +34,6 @@ func (n *defNetwork) run(networkNSPath string, cb func() error) error {
|
|||||||
span, _ := n.trace(context.Background(), "run")
|
span, _ := n.trace(context.Background(), "run")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
if networkNSPath == "" {
|
|
||||||
return fmt.Errorf("networkNSPath cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return doNetNS(networkNSPath, func(_ ns.NetNS) error {
|
return doNetNS(networkNSPath, func(_ ns.NetNS) error {
|
||||||
return cb()
|
return cb()
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,7 @@ type Endpoint interface {
|
|||||||
NetworkPair() *NetworkInterfacePair
|
NetworkPair() *NetworkInterfacePair
|
||||||
|
|
||||||
SetProperties(NetworkInfo)
|
SetProperties(NetworkInfo)
|
||||||
|
SetPciAddr(string)
|
||||||
Attach(hypervisor) error
|
Attach(hypervisor) error
|
||||||
Detach(netNsCreated bool, netNsPath string) error
|
Detach(netNsCreated bool, netNsPath string) error
|
||||||
HotAttach(h hypervisor) error
|
HotAttach(h hypervisor) error
|
||||||
@ -43,6 +44,9 @@ const (
|
|||||||
|
|
||||||
// MacvtapEndpointType is macvtap network interface.
|
// MacvtapEndpointType is macvtap network interface.
|
||||||
MacvtapEndpointType EndpointType = "macvtap"
|
MacvtapEndpointType EndpointType = "macvtap"
|
||||||
|
|
||||||
|
// TapEndpointType is tap network interface.
|
||||||
|
TapEndpointType EndpointType = "tap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set sets an endpoint type based on the input string.
|
// Set sets an endpoint type based on the input string.
|
||||||
@ -63,6 +67,9 @@ func (endpointType *EndpointType) Set(value string) error {
|
|||||||
case "macvtap":
|
case "macvtap":
|
||||||
*endpointType = MacvtapEndpointType
|
*endpointType = MacvtapEndpointType
|
||||||
return nil
|
return nil
|
||||||
|
case "tap":
|
||||||
|
*endpointType = TapEndpointType
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown endpoint type %s", value)
|
return fmt.Errorf("Unknown endpoint type %s", value)
|
||||||
}
|
}
|
||||||
@ -81,6 +88,8 @@ func (endpointType *EndpointType) String() string {
|
|||||||
return string(BridgedMacvlanEndpointType)
|
return string(BridgedMacvlanEndpointType)
|
||||||
case MacvtapEndpointType:
|
case MacvtapEndpointType:
|
||||||
return string(MacvtapEndpointType)
|
return string(MacvtapEndpointType)
|
||||||
|
case TapEndpointType:
|
||||||
|
return string(TapEndpointType)
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,11 @@ func (endpoint *MacvtapEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return nil
|
return nil
|
||||||
|
@ -51,6 +51,9 @@ const (
|
|||||||
// This will be used for vethtap, macvtap, ipvtap
|
// This will be used for vethtap, macvtap, ipvtap
|
||||||
NetXConnectEnlightenedModel
|
NetXConnectEnlightenedModel
|
||||||
|
|
||||||
|
// NetXConnectNoneModel can be used when the VM is in the host network namespace
|
||||||
|
NetXConnectNoneModel
|
||||||
|
|
||||||
// NetXConnectInvalidModel is the last item to check valid values by IsValid()
|
// NetXConnectInvalidModel is the last item to check valid values by IsValid()
|
||||||
NetXConnectInvalidModel
|
NetXConnectInvalidModel
|
||||||
)
|
)
|
||||||
@ -75,6 +78,9 @@ func (n *NetInterworkingModel) SetModel(modelName string) error {
|
|||||||
case "enlightened":
|
case "enlightened":
|
||||||
*n = NetXConnectEnlightenedModel
|
*n = NetXConnectEnlightenedModel
|
||||||
return nil
|
return nil
|
||||||
|
case "none":
|
||||||
|
*n = NetXConnectNoneModel
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Unknown type %s", modelName)
|
return fmt.Errorf("Unknown type %s", modelName)
|
||||||
}
|
}
|
||||||
@ -122,21 +128,27 @@ type NetworkInterface struct {
|
|||||||
Addrs []netlink.Addr
|
Addrs []netlink.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
|
// TapInterface defines a tap interface
|
||||||
type NetworkInterfacePair struct {
|
type TapInterface struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
VirtIface NetworkInterface
|
|
||||||
TAPIface NetworkInterface
|
TAPIface NetworkInterface
|
||||||
NetInterworkingModel
|
|
||||||
VMFds []*os.File
|
VMFds []*os.File
|
||||||
VhostFds []*os.File
|
VhostFds []*os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetworkInterfacePair defines a pair between VM and virtual network interfaces.
|
||||||
|
type NetworkInterfacePair struct {
|
||||||
|
TapInterface
|
||||||
|
VirtIface NetworkInterface
|
||||||
|
NetInterworkingModel
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkConfig is the network configuration related to a network.
|
// NetworkConfig is the network configuration related to a network.
|
||||||
type NetworkConfig struct {
|
type NetworkConfig struct {
|
||||||
NetNSPath string
|
NetNSPath string
|
||||||
NetNsCreated bool
|
NetNsCreated bool
|
||||||
|
DisableNewNetNs bool
|
||||||
NetmonConfig NetmonConfig
|
NetmonConfig NetmonConfig
|
||||||
InterworkingModel NetInterworkingModel
|
InterworkingModel NetInterworkingModel
|
||||||
}
|
}
|
||||||
@ -194,6 +206,96 @@ func (n NetworkNamespace) MarshalJSON() ([]byte, error) {
|
|||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateEndpoints(typedEndpoints []TypedJSONEndpoint) ([]Endpoint, error) {
|
||||||
|
var endpoints []Endpoint
|
||||||
|
|
||||||
|
for _, e := range typedEndpoints {
|
||||||
|
switch e.Type {
|
||||||
|
case PhysicalEndpointType:
|
||||||
|
var endpoint PhysicalEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "physical",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
case VethEndpointType:
|
||||||
|
var endpoint VethEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "virtual",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
case VhostUserEndpointType:
|
||||||
|
var endpoint VhostUserEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "vhostuser",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
case BridgedMacvlanEndpointType:
|
||||||
|
var endpoint BridgedMacvlanEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "macvlan",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
case MacvtapEndpointType:
|
||||||
|
var endpoint MacvtapEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "macvtap",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
case TapEndpointType:
|
||||||
|
var endpoint TapEndpoint
|
||||||
|
err := json.Unmarshal(e.Data, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, &endpoint)
|
||||||
|
networkLogger().WithFields(logrus.Fields{
|
||||||
|
"endpoint": endpoint,
|
||||||
|
"endpoint-type": "tap",
|
||||||
|
}).Info("endpoint unmarshalled")
|
||||||
|
|
||||||
|
default:
|
||||||
|
networkLogger().WithField("endpoint-type", e.Type).Error("Ignoring unknown endpoint type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endpoints, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON is the custom NetworkNamespace unmarshalling routine.
|
// UnmarshalJSON is the custom NetworkNamespace unmarshalling routine.
|
||||||
// This is needed for unmarshalling the Endpoints interfaces array.
|
// This is needed for unmarshalling the Endpoints interfaces array.
|
||||||
func (n *NetworkNamespace) UnmarshalJSON(b []byte) error {
|
func (n *NetworkNamespace) UnmarshalJSON(b []byte) error {
|
||||||
@ -214,81 +316,11 @@ func (n *NetworkNamespace) UnmarshalJSON(b []byte) error {
|
|||||||
if err := json.Unmarshal([]byte(string(s.Endpoints)), &typedEndpoints); err != nil {
|
if err := json.Unmarshal([]byte(string(s.Endpoints)), &typedEndpoints); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
endpoints, err := generateEndpoints(typedEndpoints)
|
||||||
var endpoints []Endpoint
|
|
||||||
|
|
||||||
for _, e := range typedEndpoints {
|
|
||||||
switch e.Type {
|
|
||||||
case PhysicalEndpointType:
|
|
||||||
var endpoint PhysicalEndpoint
|
|
||||||
err := json.Unmarshal(e.Data, &endpoint)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints = append(endpoints, &endpoint)
|
|
||||||
networkLogger().WithFields(logrus.Fields{
|
|
||||||
"endpoint": endpoint,
|
|
||||||
"endpoint-type": "physical",
|
|
||||||
}).Info("endpoint unmarshalled")
|
|
||||||
|
|
||||||
case VethEndpointType:
|
|
||||||
var endpoint VethEndpoint
|
|
||||||
err := json.Unmarshal(e.Data, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints = append(endpoints, &endpoint)
|
|
||||||
networkLogger().WithFields(logrus.Fields{
|
|
||||||
"endpoint": endpoint,
|
|
||||||
"endpoint-type": "virtual",
|
|
||||||
}).Info("endpoint unmarshalled")
|
|
||||||
|
|
||||||
case VhostUserEndpointType:
|
|
||||||
var endpoint VhostUserEndpoint
|
|
||||||
err := json.Unmarshal(e.Data, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints = append(endpoints, &endpoint)
|
|
||||||
networkLogger().WithFields(logrus.Fields{
|
|
||||||
"endpoint": endpoint,
|
|
||||||
"endpoint-type": "vhostuser",
|
|
||||||
}).Info("endpoint unmarshalled")
|
|
||||||
|
|
||||||
case BridgedMacvlanEndpointType:
|
|
||||||
var endpoint BridgedMacvlanEndpoint
|
|
||||||
err := json.Unmarshal(e.Data, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints = append(endpoints, &endpoint)
|
|
||||||
networkLogger().WithFields(logrus.Fields{
|
|
||||||
"endpoint": endpoint,
|
|
||||||
"endpoint-type": "macvlan",
|
|
||||||
}).Info("endpoint unmarshalled")
|
|
||||||
|
|
||||||
case MacvtapEndpointType:
|
|
||||||
var endpoint MacvtapEndpoint
|
|
||||||
err := json.Unmarshal(e.Data, &endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints = append(endpoints, &endpoint)
|
|
||||||
networkLogger().WithFields(logrus.Fields{
|
|
||||||
"endpoint": endpoint,
|
|
||||||
"endpoint-type": "macvtap",
|
|
||||||
}).Info("endpoint unmarshalled")
|
|
||||||
|
|
||||||
default:
|
|
||||||
networkLogger().WithField("endpoint-type", e.Type).Error("Ignoring unknown endpoint type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(*n).Endpoints = endpoints
|
(*n).Endpoints = endpoints
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -825,6 +857,13 @@ func createNetNS() (string, error) {
|
|||||||
// into runtime.LockOSThread(), meaning it won't be executed in a
|
// into runtime.LockOSThread(), meaning it won't be executed in a
|
||||||
// different thread than the one expected by the caller.
|
// different thread than the one expected by the caller.
|
||||||
func doNetNS(netNSPath string, cb func(ns.NetNS) error) error {
|
func doNetNS(netNSPath string, cb func(ns.NetNS) error) error {
|
||||||
|
// if netNSPath is empty, the callback function will be run in the current network namespace.
|
||||||
|
// So skip the whole function, just call cb(). cb() needs a NetNS as arg but ignored, give it a fake one.
|
||||||
|
if netNSPath == "" {
|
||||||
|
var netNs ns.NetNS
|
||||||
|
return cb(netNs)
|
||||||
|
}
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
defer runtime.UnlockOSThread()
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
@ -964,15 +1003,17 @@ func createNetworkInterfacePair(idx int, ifName string, interworkingModel NetInt
|
|||||||
}
|
}
|
||||||
|
|
||||||
netPair := NetworkInterfacePair{
|
netPair := NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
ID: uniqueID,
|
ID: uniqueID,
|
||||||
Name: fmt.Sprintf("br%d_kata", idx),
|
Name: fmt.Sprintf("br%d_kata", idx),
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: fmt.Sprintf("tap%d_kata", idx),
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: fmt.Sprintf("eth%d", idx),
|
Name: fmt.Sprintf("eth%d", idx),
|
||||||
HardAddr: randomMacAddr,
|
HardAddr: randomMacAddr,
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: fmt.Sprintf("tap%d_kata", idx),
|
|
||||||
},
|
|
||||||
NetInterworkingModel: interworkingModel,
|
NetInterworkingModel: interworkingModel,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,6 +1159,9 @@ func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (E
|
|||||||
} else if netInfo.Iface.Type == "macvtap" {
|
} else if netInfo.Iface.Type == "macvtap" {
|
||||||
networkLogger().Infof("macvtap interface found")
|
networkLogger().Infof("macvtap interface found")
|
||||||
endpoint, err = createMacvtapNetworkEndpoint(netInfo)
|
endpoint, err = createMacvtapNetworkEndpoint(netInfo)
|
||||||
|
} else if netInfo.Iface.Type == "tap" {
|
||||||
|
networkLogger().Info("tap interface found")
|
||||||
|
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 {
|
} else {
|
||||||
|
@ -216,6 +216,7 @@ func TestNetInterworkingModelSetModel(t *testing.T) {
|
|||||||
{"bridged Model", "bridged", false},
|
{"bridged Model", "bridged", false},
|
||||||
{"macvtap Model", "macvtap", false},
|
{"macvtap Model", "macvtap", false},
|
||||||
{"enlightened Model", "enlightened", false},
|
{"enlightened Model", "enlightened", false},
|
||||||
|
{"none Model", "none", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -53,6 +53,11 @@ func (endpoint *PhysicalEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// SetProperties sets the properties of the physical endpoint.
|
// SetProperties sets the properties of the physical endpoint.
|
||||||
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
endpoint.EndpointProperties = properties
|
endpoint.EndpointProperties = properties
|
||||||
|
@ -121,6 +121,9 @@ type RuntimeConfig struct {
|
|||||||
InterNetworkModel vc.NetInterworkingModel
|
InterNetworkModel vc.NetInterworkingModel
|
||||||
FactoryConfig FactoryConfig
|
FactoryConfig FactoryConfig
|
||||||
Debug bool
|
Debug bool
|
||||||
|
|
||||||
|
//Determines if create a netns for hypervisor process
|
||||||
|
DisableNewNetNs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddKernelParam allows the addition of new kernel parameters to an existing
|
// AddKernelParam allows the addition of new kernel parameters to an existing
|
||||||
@ -326,6 +329,7 @@ func networkConfig(ocispec CompatOCISpec, config RuntimeConfig) (vc.NetworkConfi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
netConf.InterworkingModel = config.InterNetworkModel
|
netConf.InterworkingModel = config.InterNetworkModel
|
||||||
|
netConf.DisableNewNetNs = config.DisableNewNetNs
|
||||||
|
|
||||||
netConf.NetmonConfig = vc.NetmonConfig{
|
netConf.NetmonConfig = vc.NetmonConfig{
|
||||||
Path: config.NetmonConfig.Path,
|
Path: config.NetmonConfig.Path,
|
||||||
|
@ -838,66 +838,83 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) hotplugMacvtap(drive *VethEndpoint) error {
|
func (q *qemu) hotAddNetDevice(name, hardAddr string, VMFds, VhostFds []*os.File) error {
|
||||||
var (
|
var (
|
||||||
VMFdNames []string
|
VMFdNames []string
|
||||||
VhostFdNames []string
|
VhostFdNames []string
|
||||||
)
|
)
|
||||||
for i, VMFd := range drive.NetPair.VMFds {
|
for i, VMFd := range VMFds {
|
||||||
fdName := fmt.Sprintf("fd%d", i)
|
fdName := fmt.Sprintf("fd%d", i)
|
||||||
err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VMFd)
|
if err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VMFd); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
VMFdNames = append(VMFdNames, fdName)
|
VMFdNames = append(VMFdNames, fdName)
|
||||||
}
|
}
|
||||||
for i, VhostFd := range drive.NetPair.VhostFds {
|
for i, VhostFd := range VhostFds {
|
||||||
fdName := fmt.Sprintf("vhostfd%d", i)
|
fdName := fmt.Sprintf("vhostfd%d", i)
|
||||||
err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VhostFd)
|
if err := q.qmpMonitorCh.qmp.ExecuteGetFD(q.qmpMonitorCh.ctx, fdName, VhostFd); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
VhostFdNames = append(VhostFdNames, fdName)
|
VhostFdNames = append(VhostFdNames, fdName)
|
||||||
}
|
}
|
||||||
return q.qmpMonitorCh.qmp.ExecuteNetdevAddByFds(q.qmpMonitorCh.ctx, "tap", drive.NetPair.Name, VMFdNames, VhostFdNames)
|
return q.qmpMonitorCh.qmp.ExecuteNetdevAddByFds(q.qmpMonitorCh.ctx, "tap", name, VMFdNames, VhostFdNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) hotplugNetDevice(drive *VethEndpoint, op operation) error {
|
func (q *qemu) hotplugNetDevice(endpoint Endpoint, op operation) error {
|
||||||
err := q.qmpSetup()
|
err := q.qmpSetup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
devID := "virtio-" + drive.NetPair.ID
|
var tap TapInterface
|
||||||
|
|
||||||
if op == addDevice {
|
if op == addDevice {
|
||||||
switch drive.NetPair.NetInterworkingModel {
|
switch endpoint.Type() {
|
||||||
case NetXConnectBridgedModel:
|
case VethEndpointType:
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteNetdevAdd(q.qmpMonitorCh.ctx, "tap", drive.NetPair.Name, drive.NetPair.TAPIface.Name, "no", "no", int(q.config.NumVCPUs)); err != nil {
|
drive := endpoint.(*VethEndpoint)
|
||||||
return err
|
tap = drive.NetPair.TapInterface
|
||||||
}
|
case TapEndpointType:
|
||||||
case NetXConnectMacVtapModel:
|
drive := endpoint.(*TapEndpoint)
|
||||||
if err := q.hotplugMacvtap(drive); err != nil {
|
tap = drive.TapInterface
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("this net interworking model is not supported")
|
return fmt.Errorf("this endpoint is not supported")
|
||||||
}
|
}
|
||||||
addr, bridge, err := q.addDeviceToBridge(drive.NetPair.ID)
|
|
||||||
|
if err = q.hotAddNetDevice(tap.Name, endpoint.HardwareAddr(), tap.VMFds, tap.VhostFds); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, bridge, err := q.addDeviceToBridge(tap.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
drive.PCIAddr = fmt.Sprintf("%02x/%s", bridge.Addr, addr)
|
pciAddr := fmt.Sprintf("%02x/%s", bridge.Addr, addr)
|
||||||
if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, drive.NetPair.Name, devID, drive.NetPair.TAPIface.HardAddr, addr, bridge.ID, romFile, int(q.config.NumVCPUs)); err != nil {
|
endpoint.SetPciAddr(pciAddr)
|
||||||
|
|
||||||
|
devID := "virtio-" + tap.ID
|
||||||
|
if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, tap.Name, devID, endpoint.HardwareAddr(), addr, bridge.ID, romFile, int(q.config.NumVCPUs)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := q.removeDeviceFromBridge(drive.NetPair.ID); err != nil {
|
switch endpoint.Type() {
|
||||||
|
case VethEndpointType:
|
||||||
|
drive := endpoint.(*VethEndpoint)
|
||||||
|
tap = drive.NetPair.TapInterface
|
||||||
|
case TapEndpointType:
|
||||||
|
drive := endpoint.(*TapEndpoint)
|
||||||
|
tap = drive.TapInterface
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("this endpoint is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.removeDeviceFromBridge(tap.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devID := "virtio-" + tap.ID
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil {
|
if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := q.qmpMonitorCh.qmp.ExecuteNetdevDel(q.qmpMonitorCh.ctx, drive.NetPair.Name); err != nil {
|
if err := q.qmpMonitorCh.qmp.ExecuteNetdevDel(q.qmpMonitorCh.ctx, tap.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -919,7 +936,7 @@ func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operati
|
|||||||
memdev := devInfo.(*memoryDevice)
|
memdev := devInfo.(*memoryDevice)
|
||||||
return q.hotplugMemory(memdev, op)
|
return q.hotplugMemory(memdev, op)
|
||||||
case netDev:
|
case netDev:
|
||||||
device := devInfo.(*VethEndpoint)
|
device := devInfo.(Endpoint)
|
||||||
return nil, q.hotplugNetDevice(device, op)
|
return nil, q.hotplugNetDevice(device, op)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("cannot hotplug device: unsupported device type '%v'", devType)
|
return nil, fmt.Errorf("cannot hotplug device: unsupported device type '%v'", devType)
|
||||||
|
@ -443,15 +443,17 @@ func TestQemuArchBaseAppendNetwork(t *testing.T) {
|
|||||||
|
|
||||||
macvlanEp := &BridgedMacvlanEndpoint{
|
macvlanEp := &BridgedMacvlanEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
ID: "uniqueTestID-4",
|
ID: "uniqueTestID-4",
|
||||||
Name: "br4_kata",
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: BridgedMacvlanEndpointType,
|
EndpointType: BridgedMacvlanEndpointType,
|
||||||
|
@ -1021,6 +1021,10 @@ func (s *Sandbox) startNetworkMonitor() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sandbox) createNetwork() error {
|
func (s *Sandbox) createNetwork() error {
|
||||||
|
if s.config.NetworkConfig.DisableNewNetNs {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
span, _ := s.trace("createNetwork")
|
span, _ := s.trace("createNetwork")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
@ -1089,6 +1093,13 @@ func (s *Sandbox) generateNetInfo(inf *grpc.Interface) (NetworkInfo, error) {
|
|||||||
addrs = append(addrs, *netlinkAddr)
|
addrs = append(addrs, *netlinkAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ifaceType string
|
||||||
|
if s.config.NetworkConfig.InterworkingModel == NetXConnectNoneModel {
|
||||||
|
ifaceType = "tap"
|
||||||
|
} else {
|
||||||
|
ifaceType = "veth"
|
||||||
|
}
|
||||||
|
|
||||||
return NetworkInfo{
|
return NetworkInfo{
|
||||||
Iface: NetlinkIface{
|
Iface: NetlinkIface{
|
||||||
LinkAttrs: netlink.LinkAttrs{
|
LinkAttrs: netlink.LinkAttrs{
|
||||||
@ -1096,7 +1107,7 @@ func (s *Sandbox) generateNetInfo(inf *grpc.Interface) (NetworkInfo, error) {
|
|||||||
HardwareAddr: hw,
|
HardwareAddr: hw,
|
||||||
MTU: int(inf.Mtu),
|
MTU: int(inf.Mtu),
|
||||||
},
|
},
|
||||||
Type: "",
|
Type: ifaceType,
|
||||||
},
|
},
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
}, nil
|
}, nil
|
||||||
@ -1142,6 +1153,9 @@ func (s *Sandbox) RemoveInterface(inf *grpc.Interface) (*grpc.Interface, error)
|
|||||||
return inf, err
|
return inf, err
|
||||||
}
|
}
|
||||||
s.networkNS.Endpoints = append(s.networkNS.Endpoints[:i], s.networkNS.Endpoints[i+1:]...)
|
s.networkNS.Endpoints = append(s.networkNS.Endpoints[:i], s.networkNS.Endpoints[i+1:]...)
|
||||||
|
if err := s.storage.storeSandboxNetwork(s.id, s.networkNS); err != nil {
|
||||||
|
return inf, err
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
189
virtcontainers/tap_endpoint.go
Normal file
189
virtcontainers/tap_endpoint.go
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
// Copyright (c) 2018 Huawei Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TapEndpoint represents just a tap endpoint
|
||||||
|
type TapEndpoint struct {
|
||||||
|
TapInterface TapInterface
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns the properties of the tap interface.
|
||||||
|
func (endpoint *TapEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the tap interface in the network pair.
|
||||||
|
func (endpoint *TapEndpoint) Name() string {
|
||||||
|
return endpoint.TapInterface.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// HardwareAddr returns the mac address that is assigned to the tap interface
|
||||||
|
func (endpoint *TapEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.TapInterface.TAPIface.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type identifies the endpoint as a tap endpoint.
|
||||||
|
func (endpoint *TapEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *TapEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *TapEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *TapEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties for the endpoint.
|
||||||
|
func (endpoint *TapEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for tap endpoint adds the tap interface to the hypervisor.
|
||||||
|
func (endpoint *TapEndpoint) Attach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("TapEndpoint does not support Attach, if you're using docker please use --net none")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach for the tap endpoint tears down the tap
|
||||||
|
func (endpoint *TapEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
||||||
|
if !netNsCreated && netNsPath != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
networkLogger().WithField("endpoint-type", TapEndpointType).Info("Detaching endpoint")
|
||||||
|
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
return unTapNetwork(endpoint.TapInterface.TAPIface.Name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for the tap endpoint uses hot plug device
|
||||||
|
func (endpoint *TapEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
networkLogger().Info("Hot attaching tap endpoint")
|
||||||
|
if err := tapNetwork(endpoint, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error bridging tap ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.hotplugAddDevice(endpoint, netDev); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error attach tap ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for the tap endpoint uses hot pull device
|
||||||
|
func (endpoint *TapEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
networkLogger().Info("Hot detaching tap endpoint")
|
||||||
|
if err := doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
return unTapNetwork(endpoint.TapInterface.TAPIface.Name)
|
||||||
|
}); err != nil {
|
||||||
|
networkLogger().WithError(err).Warn("Error un-bridging tap ep")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.hotplugRemoveDevice(endpoint, netDev); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error detach tap ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTapNetworkEndpoint(idx int, ifName string) (*TapEndpoint, error) {
|
||||||
|
if idx < 0 {
|
||||||
|
return &TapEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
||||||
|
}
|
||||||
|
uniqueID := uuid.Generate().String()
|
||||||
|
|
||||||
|
endpoint := &TapEndpoint{
|
||||||
|
TapInterface: TapInterface{
|
||||||
|
ID: uniqueID,
|
||||||
|
Name: fmt.Sprintf("eth%d", idx),
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: fmt.Sprintf("tap%d_kata", idx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EndpointType: TapEndpointType,
|
||||||
|
}
|
||||||
|
if ifName != "" {
|
||||||
|
endpoint.TapInterface.Name = ifName
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func tapNetwork(endpoint *TapEndpoint, numCPUs uint32, disableVhostNet bool) error {
|
||||||
|
netHandle, err := netlink.NewHandle()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer netHandle.Delete()
|
||||||
|
|
||||||
|
tapLink, fds, err := createLink(netHandle, endpoint.TapInterface.TAPIface.Name, &netlink.Tuntap{}, int(numCPUs))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not create TAP interface: %s", err)
|
||||||
|
}
|
||||||
|
endpoint.TapInterface.VMFds = fds
|
||||||
|
if !disableVhostNet {
|
||||||
|
vhostFds, err := createVhostFds(int(numCPUs))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not setup vhost fds %s : %s", endpoint.TapInterface.Name, err)
|
||||||
|
}
|
||||||
|
endpoint.TapInterface.VhostFds = vhostFds
|
||||||
|
}
|
||||||
|
linkAttrs := endpoint.Properties().Iface.LinkAttrs
|
||||||
|
|
||||||
|
// Save the MAC address to the TAP so that it can later be used
|
||||||
|
// to build the QMP command line. This MAC address has to be
|
||||||
|
// the one inside the VM in order to avoid any firewall issues. The
|
||||||
|
// bridge created by the network plugin on the host actually expects
|
||||||
|
// to see traffic from this MAC address and not another one.
|
||||||
|
endpoint.TapInterface.TAPIface.HardAddr = linkAttrs.HardwareAddr.String()
|
||||||
|
if err := netHandle.LinkSetMTU(tapLink, linkAttrs.MTU); err != nil {
|
||||||
|
return fmt.Errorf("Could not set TAP MTU %d: %s", linkAttrs.MTU, err)
|
||||||
|
}
|
||||||
|
if err := netHandle.LinkSetUp(tapLink); err != nil {
|
||||||
|
return fmt.Errorf("Could not enable TAP %s: %s", endpoint.TapInterface.Name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unTapNetwork(name string) error {
|
||||||
|
netHandle, err := netlink.NewHandle()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer netHandle.Delete()
|
||||||
|
tapLink, err := getLinkByName(netHandle, name, &netlink.Tuntap{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not get TAP interface: %s", err)
|
||||||
|
}
|
||||||
|
if err := netHandle.LinkSetDown(tapLink); err != nil {
|
||||||
|
return fmt.Errorf("Could not disable TAP %s: %s", name, err)
|
||||||
|
}
|
||||||
|
if err := netHandle.LinkDel(tapLink); err != nil {
|
||||||
|
return fmt.Errorf("Could not remove TAP %s: %s", name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -70,6 +70,11 @@ func (endpoint *VethEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *VethEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *VethEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *VethEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return &endpoint.NetPair
|
return &endpoint.NetPair
|
||||||
|
@ -16,15 +16,17 @@ func TestCreateVethNetworkEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
expected := &VethEndpoint{
|
expected := &VethEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
ID: "uniqueTestID-4",
|
ID: "uniqueTestID-4",
|
||||||
Name: "br4_kata",
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth4",
|
Name: "eth4",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: VethEndpointType,
|
EndpointType: VethEndpointType,
|
||||||
@ -51,15 +53,17 @@ func TestCreateVethNetworkEndpointChooseIfaceName(t *testing.T) {
|
|||||||
|
|
||||||
expected := &VethEndpoint{
|
expected := &VethEndpoint{
|
||||||
NetPair: NetworkInterfacePair{
|
NetPair: NetworkInterfacePair{
|
||||||
|
TapInterface: TapInterface{
|
||||||
ID: "uniqueTestID-4",
|
ID: "uniqueTestID-4",
|
||||||
Name: "br4_kata",
|
Name: "br4_kata",
|
||||||
|
TAPIface: NetworkInterface{
|
||||||
|
Name: "tap4_kata",
|
||||||
|
},
|
||||||
|
},
|
||||||
VirtIface: NetworkInterface{
|
VirtIface: NetworkInterface{
|
||||||
Name: "eth1",
|
Name: "eth1",
|
||||||
HardAddr: macAddr.String(),
|
HardAddr: macAddr.String(),
|
||||||
},
|
},
|
||||||
TAPIface: NetworkInterface{
|
|
||||||
Name: "tap4_kata",
|
|
||||||
},
|
|
||||||
NetInterworkingModel: DefaultNetInterworkingModel,
|
NetInterworkingModel: DefaultNetInterworkingModel,
|
||||||
},
|
},
|
||||||
EndpointType: VethEndpointType,
|
EndpointType: VethEndpointType,
|
||||||
|
@ -62,6 +62,11 @@ func (endpoint *VhostUserEndpoint) PciAddr() string {
|
|||||||
return endpoint.PCIAddr
|
return endpoint.PCIAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPciAddr sets the PCI address of the endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) SetPciAddr(pciAddr string) {
|
||||||
|
endpoint.PCIAddr = pciAddr
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user