mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-04 02:56:18 +00:00
network: Refactor network.go
Split endpoint implementations into their own file. Fixes #799 Signed-off-by: Archana Shinde <archana.m.shinde@intel.com>
This commit is contained in:
parent
7fb2706667
commit
adcd9106f9
116
virtcontainers/bridgedmacvlan_endpoint.go
Normal file
116
virtcontainers/bridgedmacvlan_endpoint.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM
|
||||||
|
type BridgedMacvlanEndpoint struct {
|
||||||
|
NetPair NetworkInterfacePair
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBridgedMacvlanNetworkEndpoint(idx int, ifName string, interworkingModel NetInterworkingModel) (*BridgedMacvlanEndpoint, error) {
|
||||||
|
if idx < 0 {
|
||||||
|
return &BridgedMacvlanEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &BridgedMacvlanEndpoint{
|
||||||
|
NetPair: netPair,
|
||||||
|
EndpointType: BridgedMacvlanEndpointType,
|
||||||
|
}
|
||||||
|
if ifName != "" {
|
||||||
|
endpoint.NetPair.VirtIface.Name = ifName
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns properties of the interface.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the veth interface in the network pair.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) 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 *BridgedMacvlanEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.NetPair.TAPIface.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type identifies the endpoint as a virtual endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties for the endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) 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 *BridgedMacvlanEndpoint) Attach(h hypervisor) error {
|
||||||
|
networkLogger().Info("Attaching macvlan endpoint")
|
||||||
|
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 *BridgedMacvlanEndpoint) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
networkLogger().Info("Detaching virtual endpoint")
|
||||||
|
|
||||||
|
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
//return xconnectVMNetwork(&(endpoint.NetPair), false, 0, false, endpoint.EndpointType)
|
||||||
|
return xconnectVMNetwork(endpoint, false, 0, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for physical endpoint not supported yet
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot attach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for physical endpoint not supported yet
|
||||||
|
func (endpoint *BridgedMacvlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot detach")
|
||||||
|
}
|
87
virtcontainers/endpoint.go
Normal file
87
virtcontainers/endpoint.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Endpoint represents a physical or virtual network interface.
|
||||||
|
type Endpoint interface {
|
||||||
|
Properties() NetworkInfo
|
||||||
|
Name() string
|
||||||
|
HardwareAddr() string
|
||||||
|
Type() EndpointType
|
||||||
|
PciAddr() string
|
||||||
|
NetworkPair() *NetworkInterfacePair
|
||||||
|
|
||||||
|
SetProperties(NetworkInfo)
|
||||||
|
Attach(hypervisor) error
|
||||||
|
Detach(netNsCreated bool, netNsPath string) error
|
||||||
|
HotAttach(h hypervisor) error
|
||||||
|
HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointType identifies the type of the network endpoint.
|
||||||
|
type EndpointType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PhysicalEndpointType is the physical network interface.
|
||||||
|
PhysicalEndpointType EndpointType = "physical"
|
||||||
|
|
||||||
|
// VirtualEndpointType is the virtual network interface.
|
||||||
|
VirtualEndpointType EndpointType = "virtual"
|
||||||
|
|
||||||
|
// VhostUserEndpointType is the vhostuser network interface.
|
||||||
|
VhostUserEndpointType EndpointType = "vhost-user"
|
||||||
|
|
||||||
|
// BridgedMacvlanEndpointType is macvlan network interface.
|
||||||
|
BridgedMacvlanEndpointType EndpointType = "macvlan"
|
||||||
|
|
||||||
|
// MacvtapEndpointType is macvtap network interface.
|
||||||
|
MacvtapEndpointType EndpointType = "macvtap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set sets an endpoint type based on the input string.
|
||||||
|
func (endpointType *EndpointType) Set(value string) error {
|
||||||
|
switch value {
|
||||||
|
case "physical":
|
||||||
|
*endpointType = PhysicalEndpointType
|
||||||
|
return nil
|
||||||
|
case "virtual":
|
||||||
|
*endpointType = VirtualEndpointType
|
||||||
|
return nil
|
||||||
|
case "vhost-user":
|
||||||
|
*endpointType = VhostUserEndpointType
|
||||||
|
return nil
|
||||||
|
case "macvlan":
|
||||||
|
*endpointType = BridgedMacvlanEndpointType
|
||||||
|
return nil
|
||||||
|
case "macvtap":
|
||||||
|
*endpointType = MacvtapEndpointType
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown endpoint type %s", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String converts an endpoint type to a string.
|
||||||
|
func (endpointType *EndpointType) String() string {
|
||||||
|
switch *endpointType {
|
||||||
|
case PhysicalEndpointType:
|
||||||
|
return string(PhysicalEndpointType)
|
||||||
|
case VirtualEndpointType:
|
||||||
|
return string(VirtualEndpointType)
|
||||||
|
case VhostUserEndpointType:
|
||||||
|
return string(VhostUserEndpointType)
|
||||||
|
case BridgedMacvlanEndpointType:
|
||||||
|
return string(BridgedMacvlanEndpointType)
|
||||||
|
case MacvtapEndpointType:
|
||||||
|
return string(MacvtapEndpointType)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
101
virtcontainers/macvtap_endpoint.go
Normal file
101
virtcontainers/macvtap_endpoint.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MacvtapEndpoint represents a macvtap endpoint
|
||||||
|
type MacvtapEndpoint struct {
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
VMFds []*os.File
|
||||||
|
VhostFds []*os.File
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMacvtapNetworkEndpoint(netInfo NetworkInfo) (*MacvtapEndpoint, error) {
|
||||||
|
endpoint := &MacvtapEndpoint{
|
||||||
|
EndpointType: MacvtapEndpointType,
|
||||||
|
EndpointProperties: netInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns the properties of the macvtap interface.
|
||||||
|
func (endpoint *MacvtapEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// HardwareAddr returns the mac address of the macvtap network interface.
|
||||||
|
func (endpoint *MacvtapEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.EndpointProperties.Iface.HardwareAddr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the macvtap interface.
|
||||||
|
func (endpoint *MacvtapEndpoint) Name() string {
|
||||||
|
return endpoint.EndpointProperties.Iface.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type indentifies the endpoint as a macvtap endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties of the macvtap endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for macvtap endpoint passes macvtap device to the hypervisor.
|
||||||
|
func (endpoint *MacvtapEndpoint) Attach(h hypervisor) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "macvtap").Info("Attaching endpoint")
|
||||||
|
var err error
|
||||||
|
|
||||||
|
endpoint.VMFds, err = createMacvtapFds(endpoint.EndpointProperties.Iface.Index, int(h.hypervisorConfig().NumVCPUs))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not setup macvtap fds %s: %s", endpoint.EndpointProperties.Iface.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !h.hypervisorConfig().DisableVhostNet {
|
||||||
|
vhostFds, err := createVhostFds(int(h.hypervisorConfig().NumVCPUs))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not setup vhost fds %s : %s", endpoint.EndpointProperties.Iface.Name, err)
|
||||||
|
}
|
||||||
|
endpoint.VhostFds = vhostFds
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.addDevice(endpoint, netDev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach for macvtap endpoint does nothing.
|
||||||
|
func (endpoint *MacvtapEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "macvtap").Info("Detaching endpoint")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for macvtap endpoint not supported yet
|
||||||
|
func (endpoint *MacvtapEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("MacvtapEndpoint does not support Hot attach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for macvtap endpoint not supported yet
|
||||||
|
func (endpoint *MacvtapEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
return fmt.Errorf("MacvtapEndpoint does not support Hot detach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return nil
|
||||||
|
}
|
@ -7,29 +7,22 @@ package virtcontainers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
cryptoRand "crypto/rand"
|
cryptoRand "crypto/rand"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/safchain/ethtool"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/kata-containers/agent/protocols/grpc"
|
"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"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/utils"
|
"github.com/kata-containers/runtime/virtcontainers/utils"
|
||||||
)
|
)
|
||||||
@ -148,548 +141,10 @@ type NetworkConfig struct {
|
|||||||
InterworkingModel NetInterworkingModel
|
InterworkingModel NetInterworkingModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Endpoint represents a physical or virtual network interface.
|
|
||||||
type Endpoint interface {
|
|
||||||
Properties() NetworkInfo
|
|
||||||
Name() string
|
|
||||||
HardwareAddr() string
|
|
||||||
Type() EndpointType
|
|
||||||
PciAddr() string
|
|
||||||
NetworkPair() *NetworkInterfacePair
|
|
||||||
|
|
||||||
SetProperties(NetworkInfo)
|
|
||||||
Attach(hypervisor) error
|
|
||||||
Detach(netNsCreated bool, netNsPath string) error
|
|
||||||
HotAttach(h hypervisor) error
|
|
||||||
HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// VirtualEndpoint gathers a network pair and its properties.
|
|
||||||
type VirtualEndpoint struct {
|
|
||||||
NetPair NetworkInterfacePair
|
|
||||||
EndpointProperties NetworkInfo
|
|
||||||
Physical bool
|
|
||||||
EndpointType EndpointType
|
|
||||||
PCIAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// PhysicalEndpoint gathers a physical network interface and its properties
|
|
||||||
type PhysicalEndpoint struct {
|
|
||||||
IfaceName string
|
|
||||||
HardAddr string
|
|
||||||
EndpointProperties NetworkInfo
|
|
||||||
EndpointType EndpointType
|
|
||||||
BDF string
|
|
||||||
Driver string
|
|
||||||
VendorDeviceID string
|
|
||||||
PCIAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// VhostUserEndpoint represents a vhost-user socket based network interface
|
|
||||||
type VhostUserEndpoint struct {
|
|
||||||
// Path to the vhost-user socket on the host system
|
|
||||||
SocketPath string
|
|
||||||
// MAC address of the interface
|
|
||||||
HardAddr string
|
|
||||||
IfaceName string
|
|
||||||
EndpointProperties NetworkInfo
|
|
||||||
EndpointType EndpointType
|
|
||||||
PCIAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM
|
|
||||||
type BridgedMacvlanEndpoint struct {
|
|
||||||
NetPair NetworkInterfacePair
|
|
||||||
EndpointProperties NetworkInfo
|
|
||||||
EndpointType EndpointType
|
|
||||||
PCIAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MacvtapEndpoint represents a macvtap endpoint
|
|
||||||
type MacvtapEndpoint struct {
|
|
||||||
EndpointProperties NetworkInfo
|
|
||||||
EndpointType EndpointType
|
|
||||||
VMFds []*os.File
|
|
||||||
VhostFds []*os.File
|
|
||||||
PCIAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties returns properties for the veth interface in the network pair.
|
|
||||||
func (endpoint *VirtualEndpoint) Properties() NetworkInfo {
|
|
||||||
return endpoint.EndpointProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns name of the veth interface in the network pair.
|
|
||||||
func (endpoint *VirtualEndpoint) 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 *VirtualEndpoint) HardwareAddr() string {
|
|
||||||
return endpoint.NetPair.TAPIface.HardAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type identifies the endpoint as a virtual endpoint.
|
|
||||||
func (endpoint *VirtualEndpoint) Type() EndpointType {
|
|
||||||
return endpoint.EndpointType
|
|
||||||
}
|
|
||||||
|
|
||||||
// PciAddr returns the PCI address of the endpoint.
|
|
||||||
func (endpoint *VirtualEndpoint) PciAddr() string {
|
|
||||||
return endpoint.PCIAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
|
||||||
func (endpoint *VirtualEndpoint) NetworkPair() *NetworkInterfacePair {
|
|
||||||
return &endpoint.NetPair
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProperties sets the properties for the endpoint.
|
|
||||||
func (endpoint *VirtualEndpoint) SetProperties(properties NetworkInfo) {
|
|
||||||
endpoint.EndpointProperties = properties
|
|
||||||
}
|
|
||||||
|
|
||||||
func networkLogger() *logrus.Entry {
|
func networkLogger() *logrus.Entry {
|
||||||
return virtLog.WithField("subsystem", "network")
|
return virtLog.WithField("subsystem", "network")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach for virtual endpoint bridges the network pair and adds the
|
|
||||||
// tap interface of the network pair to the hypervisor.
|
|
||||||
func (endpoint *VirtualEndpoint) Attach(h hypervisor) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "virtual").Info("Attaching endpoint")
|
|
||||||
|
|
||||||
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
|
||||||
networkLogger().WithError(err).Error("Error bridging virtual endpoint")
|
|
||||||
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 *VirtualEndpoint) 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
|
|
||||||
}
|
|
||||||
|
|
||||||
networkLogger().WithField("endpoint-type", "virtual").Info("Detaching endpoint")
|
|
||||||
|
|
||||||
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
|
||||||
return xconnectVMNetwork(endpoint, false, 0, false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotAttach for the virtual endpoint uses hot plug device
|
|
||||||
func (endpoint *VirtualEndpoint) HotAttach(h hypervisor) error {
|
|
||||||
networkLogger().Info("Hot attaching virtual endpoint")
|
|
||||||
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
|
||||||
networkLogger().WithError(err).Error("Error bridging virtual ep")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := h.hotplugAddDevice(endpoint, netDev); err != nil {
|
|
||||||
networkLogger().WithError(err).Error("Error attach virtual ep")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotDetach for the virtual endpoint uses hot pull device
|
|
||||||
func (endpoint *VirtualEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
|
||||||
if !netNsCreated {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
networkLogger().Info("Hot detaching virtual endpoint")
|
|
||||||
if err := doNetNS(netNsPath, func(_ ns.NetNS) error {
|
|
||||||
return xconnectVMNetwork(endpoint, false, 0, h.hypervisorConfig().DisableVhostNet)
|
|
||||||
}); err != nil {
|
|
||||||
networkLogger().WithError(err).Warn("Error un-bridging virtual ep")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := h.hotplugRemoveDevice(endpoint, netDev); err != nil {
|
|
||||||
networkLogger().WithError(err).Error("Error detach virtual ep")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties returns the properties of the interface.
|
|
||||||
func (endpoint *VhostUserEndpoint) Properties() NetworkInfo {
|
|
||||||
return endpoint.EndpointProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns name of the interface.
|
|
||||||
func (endpoint *VhostUserEndpoint) Name() string {
|
|
||||||
return endpoint.IfaceName
|
|
||||||
}
|
|
||||||
|
|
||||||
// HardwareAddr returns the mac address of the vhostuser network interface
|
|
||||||
func (endpoint *VhostUserEndpoint) HardwareAddr() string {
|
|
||||||
return endpoint.HardAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type indentifies the endpoint as a vhostuser endpoint.
|
|
||||||
func (endpoint *VhostUserEndpoint) Type() EndpointType {
|
|
||||||
return endpoint.EndpointType
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProperties sets the properties of the endpoint.
|
|
||||||
func (endpoint *VhostUserEndpoint) SetProperties(properties NetworkInfo) {
|
|
||||||
endpoint.EndpointProperties = properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// PciAddr returns the PCI address of the endpoint.
|
|
||||||
func (endpoint *VhostUserEndpoint) PciAddr() string {
|
|
||||||
return endpoint.PCIAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
|
||||||
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach for vhostuser endpoint
|
|
||||||
func (endpoint *VhostUserEndpoint) Attach(h hypervisor) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "vhostuser").Info("Attaching endpoint")
|
|
||||||
|
|
||||||
// Generate a unique ID to be used for hypervisor commandline fields
|
|
||||||
randBytes, err := utils.GenerateRandomBytes(8)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
id := hex.EncodeToString(randBytes)
|
|
||||||
|
|
||||||
d := config.VhostUserDeviceAttrs{
|
|
||||||
DevID: id,
|
|
||||||
SocketPath: endpoint.SocketPath,
|
|
||||||
MacAddress: endpoint.HardAddr,
|
|
||||||
Type: config.VhostUserNet,
|
|
||||||
}
|
|
||||||
|
|
||||||
return h.addDevice(d, vhostuserDev)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detach for vhostuser endpoint
|
|
||||||
func (endpoint *VhostUserEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "vhostuser").Info("Detaching endpoint")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotAttach for vhostuser endpoint not supported yet
|
|
||||||
func (endpoint *VhostUserEndpoint) HotAttach(h hypervisor) error {
|
|
||||||
return fmt.Errorf("VhostUserEndpoint does not support Hot attach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotDetach for vhostuser endpoint not supported yet
|
|
||||||
func (endpoint *VhostUserEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
|
||||||
return fmt.Errorf("VhostUserEndpoint does not support Hot detach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a vhostuser endpoint
|
|
||||||
func createVhostUserEndpoint(netInfo NetworkInfo, socket string) (*VhostUserEndpoint, error) {
|
|
||||||
|
|
||||||
vhostUserEndpoint := &VhostUserEndpoint{
|
|
||||||
SocketPath: socket,
|
|
||||||
HardAddr: netInfo.Iface.HardwareAddr.String(),
|
|
||||||
IfaceName: netInfo.Iface.Name,
|
|
||||||
EndpointType: VhostUserEndpointType,
|
|
||||||
}
|
|
||||||
return vhostUserEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties returns the properties of the physical interface.
|
|
||||||
func (endpoint *PhysicalEndpoint) Properties() NetworkInfo {
|
|
||||||
return endpoint.EndpointProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// HardwareAddr returns the mac address of the physical network interface.
|
|
||||||
func (endpoint *PhysicalEndpoint) HardwareAddr() string {
|
|
||||||
return endpoint.HardAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns name of the physical interface.
|
|
||||||
func (endpoint *PhysicalEndpoint) Name() string {
|
|
||||||
return endpoint.IfaceName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type indentifies the endpoint as a physical endpoint.
|
|
||||||
func (endpoint *PhysicalEndpoint) Type() EndpointType {
|
|
||||||
return endpoint.EndpointType
|
|
||||||
}
|
|
||||||
|
|
||||||
// PciAddr returns the PCI address of the endpoint.
|
|
||||||
func (endpoint *PhysicalEndpoint) PciAddr() string {
|
|
||||||
return endpoint.PCIAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProperties sets the properties of the physical endpoint.
|
|
||||||
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
|
||||||
endpoint.EndpointProperties = properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
|
||||||
func (endpoint *PhysicalEndpoint) NetworkPair() *NetworkInterfacePair {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach for physical endpoint binds the physical network interface to
|
|
||||||
// vfio-pci and adds device to the hypervisor with vfio-passthrough.
|
|
||||||
func (endpoint *PhysicalEndpoint) Attach(h hypervisor) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "physical").Info("Attaching endpoint")
|
|
||||||
|
|
||||||
// Unbind physical interface from host driver and bind to vfio
|
|
||||||
// so that it can be passed to qemu.
|
|
||||||
if err := bindNICToVFIO(endpoint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use device manager as general device management entrance
|
|
||||||
d := config.VFIODev{
|
|
||||||
BDF: endpoint.BDF,
|
|
||||||
}
|
|
||||||
|
|
||||||
return h.addDevice(d, vfioDev)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detach for physical endpoint unbinds the physical network interface from vfio-pci
|
|
||||||
// and binds it back to the saved host driver.
|
|
||||||
func (endpoint *PhysicalEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
|
||||||
// Bind back the physical network interface to host.
|
|
||||||
// We need to do this even if a new network namespace has not
|
|
||||||
// been created by virtcontainers.
|
|
||||||
networkLogger().WithField("endpoint-type", "physical").Info("Detaching endpoint")
|
|
||||||
|
|
||||||
// We do not need to enter the network namespace to bind back the
|
|
||||||
// physical interface to host driver.
|
|
||||||
return bindNICToHost(endpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotAttach for physical endpoint not supported yet
|
|
||||||
func (endpoint *PhysicalEndpoint) HotAttach(h hypervisor) error {
|
|
||||||
return fmt.Errorf("PhysicalEndpoint does not support Hot attach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotDetach for physical endpoint not supported yet
|
|
||||||
func (endpoint *PhysicalEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
|
||||||
return fmt.Errorf("PhysicalEndpoint does not support Hot detach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Macvlan
|
|
||||||
|
|
||||||
// Properties returns properties of the interface.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) Properties() NetworkInfo {
|
|
||||||
return endpoint.EndpointProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns name of the veth interface in the network pair.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) 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 *BridgedMacvlanEndpoint) HardwareAddr() string {
|
|
||||||
return endpoint.NetPair.TAPIface.HardAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type identifies the endpoint as a virtual endpoint.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) Type() EndpointType {
|
|
||||||
return endpoint.EndpointType
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProperties sets the properties for the endpoint.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) SetProperties(properties NetworkInfo) {
|
|
||||||
endpoint.EndpointProperties = properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// PciAddr returns the PCI address of the endpoint.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) PciAddr() string {
|
|
||||||
return endpoint.PCIAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) 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 *BridgedMacvlanEndpoint) Attach(h hypervisor) error {
|
|
||||||
networkLogger().Info("Attaching macvlan endpoint")
|
|
||||||
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 *BridgedMacvlanEndpoint) 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
|
|
||||||
}
|
|
||||||
|
|
||||||
networkLogger().Info("Detaching virtual endpoint")
|
|
||||||
|
|
||||||
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
|
||||||
//return xconnectVMNetwork(&(endpoint.NetPair), false, 0, false, endpoint.EndpointType)
|
|
||||||
return xconnectVMNetwork(endpoint, false, 0, false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotAttach for physical endpoint not supported yet
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) HotAttach(h hypervisor) error {
|
|
||||||
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot attach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotDetach for physical endpoint not supported yet
|
|
||||||
func (endpoint *BridgedMacvlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
|
||||||
return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot detach")
|
|
||||||
}
|
|
||||||
|
|
||||||
//Macvtap
|
|
||||||
|
|
||||||
// Properties returns the properties of the macvtap interface.
|
|
||||||
func (endpoint *MacvtapEndpoint) Properties() NetworkInfo {
|
|
||||||
return endpoint.EndpointProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// HardwareAddr returns the mac address of the macvtap network interface.
|
|
||||||
func (endpoint *MacvtapEndpoint) HardwareAddr() string {
|
|
||||||
return endpoint.EndpointProperties.Iface.HardwareAddr.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns name of the macvtap interface.
|
|
||||||
func (endpoint *MacvtapEndpoint) Name() string {
|
|
||||||
return endpoint.EndpointProperties.Iface.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type indentifies the endpoint as a macvtap endpoint.
|
|
||||||
func (endpoint *MacvtapEndpoint) Type() EndpointType {
|
|
||||||
return endpoint.EndpointType
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProperties sets the properties of the macvtap endpoint.
|
|
||||||
func (endpoint *MacvtapEndpoint) SetProperties(properties NetworkInfo) {
|
|
||||||
endpoint.EndpointProperties = properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach for macvtap endpoint passes macvtap device to the hypervisor.
|
|
||||||
func (endpoint *MacvtapEndpoint) Attach(h hypervisor) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "macvtap").Info("Attaching endpoint")
|
|
||||||
var err error
|
|
||||||
|
|
||||||
endpoint.VMFds, err = createMacvtapFds(endpoint.EndpointProperties.Iface.Index, int(h.hypervisorConfig().NumVCPUs))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not setup macvtap fds %s: %s", endpoint.EndpointProperties.Iface.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !h.hypervisorConfig().DisableVhostNet {
|
|
||||||
vhostFds, err := createVhostFds(int(h.hypervisorConfig().NumVCPUs))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not setup vhost fds %s : %s", endpoint.EndpointProperties.Iface.Name, err)
|
|
||||||
}
|
|
||||||
endpoint.VhostFds = vhostFds
|
|
||||||
}
|
|
||||||
|
|
||||||
return h.addDevice(endpoint, netDev)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detach for macvtap endpoint does nothing.
|
|
||||||
func (endpoint *MacvtapEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
|
||||||
networkLogger().WithField("endpoint-type", "macvtap").Info("Detaching endpoint")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotAttach for macvtap endpoint not supported yet
|
|
||||||
func (endpoint *MacvtapEndpoint) HotAttach(h hypervisor) error {
|
|
||||||
return fmt.Errorf("MacvtapEndpoint does not support Hot attach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HotDetach for macvtap endpoint not supported yet
|
|
||||||
func (endpoint *MacvtapEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
|
||||||
return fmt.Errorf("MacvtapEndpoint does not support Hot detach")
|
|
||||||
}
|
|
||||||
|
|
||||||
// PciAddr returns the PCI address of the endpoint.
|
|
||||||
func (endpoint *MacvtapEndpoint) PciAddr() string {
|
|
||||||
return endpoint.PCIAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkPair returns the network pair of the endpoint.
|
|
||||||
func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EndpointType identifies the type of the network endpoint.
|
|
||||||
type EndpointType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// PhysicalEndpointType is the physical network interface.
|
|
||||||
PhysicalEndpointType EndpointType = "physical"
|
|
||||||
|
|
||||||
// VirtualEndpointType is the virtual network interface.
|
|
||||||
VirtualEndpointType EndpointType = "virtual"
|
|
||||||
|
|
||||||
// VhostUserEndpointType is the vhostuser network interface.
|
|
||||||
VhostUserEndpointType EndpointType = "vhost-user"
|
|
||||||
|
|
||||||
// BridgedMacvlanEndpointType is macvlan network interface.
|
|
||||||
BridgedMacvlanEndpointType EndpointType = "macvlan"
|
|
||||||
|
|
||||||
// MacvtapEndpointType is macvtap network interface.
|
|
||||||
MacvtapEndpointType EndpointType = "macvtap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set sets an endpoint type based on the input string.
|
|
||||||
func (endpointType *EndpointType) Set(value string) error {
|
|
||||||
switch value {
|
|
||||||
case "physical":
|
|
||||||
*endpointType = PhysicalEndpointType
|
|
||||||
return nil
|
|
||||||
case "virtual":
|
|
||||||
*endpointType = VirtualEndpointType
|
|
||||||
return nil
|
|
||||||
case "vhost-user":
|
|
||||||
*endpointType = VhostUserEndpointType
|
|
||||||
return nil
|
|
||||||
case "macvlan":
|
|
||||||
*endpointType = BridgedMacvlanEndpointType
|
|
||||||
return nil
|
|
||||||
case "macvtap":
|
|
||||||
*endpointType = MacvtapEndpointType
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Unknown endpoint type %s", value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// String converts an endpoint type to a string.
|
|
||||||
func (endpointType *EndpointType) String() string {
|
|
||||||
switch *endpointType {
|
|
||||||
case PhysicalEndpointType:
|
|
||||||
return string(PhysicalEndpointType)
|
|
||||||
case VirtualEndpointType:
|
|
||||||
return string(VirtualEndpointType)
|
|
||||||
case VhostUserEndpointType:
|
|
||||||
return string(VhostUserEndpointType)
|
|
||||||
case BridgedMacvlanEndpointType:
|
|
||||||
return string(BridgedMacvlanEndpointType)
|
|
||||||
case MacvtapEndpointType:
|
|
||||||
return string(MacvtapEndpointType)
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkNamespace contains all data related to its network namespace.
|
// NetworkNamespace contains all data related to its network namespace.
|
||||||
type NetworkNamespace struct {
|
type NetworkNamespace struct {
|
||||||
NetNsPath string
|
NetNsPath string
|
||||||
@ -1411,60 +866,6 @@ func deleteNetNS(netNSPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVirtualNetworkEndpoint(idx int, ifName string, interworkingModel NetInterworkingModel) (*VirtualEndpoint, error) {
|
|
||||||
if idx < 0 {
|
|
||||||
return &VirtualEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint := &VirtualEndpoint{
|
|
||||||
// TODO This is too specific. We may need to create multiple
|
|
||||||
// end point types here and then decide how to connect them
|
|
||||||
// at the time of hypervisor attach and not here
|
|
||||||
NetPair: netPair,
|
|
||||||
EndpointType: VirtualEndpointType,
|
|
||||||
}
|
|
||||||
if ifName != "" {
|
|
||||||
endpoint.NetPair.VirtIface.Name = ifName
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createMacvtapNetworkEndpoint(netInfo NetworkInfo) (*MacvtapEndpoint, error) {
|
|
||||||
endpoint := &MacvtapEndpoint{
|
|
||||||
EndpointType: MacvtapEndpointType,
|
|
||||||
EndpointProperties: netInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createBridgedMacvlanNetworkEndpoint(idx int, ifName string, interworkingModel NetInterworkingModel) (*BridgedMacvlanEndpoint, error) {
|
|
||||||
if idx < 0 {
|
|
||||||
return &BridgedMacvlanEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint := &BridgedMacvlanEndpoint{
|
|
||||||
NetPair: netPair,
|
|
||||||
EndpointType: BridgedMacvlanEndpointType,
|
|
||||||
}
|
|
||||||
if ifName != "" {
|
|
||||||
endpoint.NetPair.VirtIface.Name = ifName
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) {
|
func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) {
|
||||||
|
|
||||||
if networkNS.NetNsPath == "" {
|
if networkNS.NetNsPath == "" {
|
||||||
@ -1723,132 +1124,6 @@ func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (E
|
|||||||
return endpoint, err
|
return endpoint, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// isPhysicalIface checks if an interface is a physical device.
|
|
||||||
// We use ethtool here to not rely on device sysfs inside the network namespace.
|
|
||||||
func isPhysicalIface(ifaceName string) (bool, error) {
|
|
||||||
if ifaceName == "lo" {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ethHandle, err := ethtool.NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bus, err := ethHandle.BusInfo(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a pci bus format
|
|
||||||
tokens := strings.Split(bus, ":")
|
|
||||||
if len(tokens) != 3 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var sysPCIDevicesPath = "/sys/bus/pci/devices"
|
|
||||||
|
|
||||||
func createPhysicalEndpoint(netInfo NetworkInfo) (*PhysicalEndpoint, error) {
|
|
||||||
// Get ethtool handle to derive driver and bus
|
|
||||||
ethHandle, err := ethtool.NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get BDF
|
|
||||||
bdf, err := ethHandle.BusInfo(netInfo.Iface.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Driver
|
|
||||||
driver, err := ethHandle.DriverName(netInfo.Iface.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get vendor and device id from pci space (sys/bus/pci/devices/$bdf)
|
|
||||||
|
|
||||||
ifaceDevicePath := filepath.Join(sysPCIDevicesPath, bdf, "device")
|
|
||||||
contents, err := ioutil.ReadFile(ifaceDevicePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceID := strings.TrimSpace(string(contents))
|
|
||||||
|
|
||||||
// Vendor id
|
|
||||||
ifaceVendorPath := filepath.Join(sysPCIDevicesPath, bdf, "vendor")
|
|
||||||
contents, err = ioutil.ReadFile(ifaceVendorPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vendorID := strings.TrimSpace(string(contents))
|
|
||||||
vendorDeviceID := fmt.Sprintf("%s %s", vendorID, deviceID)
|
|
||||||
vendorDeviceID = strings.TrimSpace(vendorDeviceID)
|
|
||||||
|
|
||||||
physicalEndpoint := &PhysicalEndpoint{
|
|
||||||
IfaceName: netInfo.Iface.Name,
|
|
||||||
HardAddr: netInfo.Iface.HardwareAddr.String(),
|
|
||||||
VendorDeviceID: vendorDeviceID,
|
|
||||||
EndpointType: PhysicalEndpointType,
|
|
||||||
Driver: driver,
|
|
||||||
BDF: bdf,
|
|
||||||
}
|
|
||||||
|
|
||||||
return physicalEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bindNICToVFIO(endpoint *PhysicalEndpoint) error {
|
|
||||||
return drivers.BindDevicetoVFIO(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func bindNICToHost(endpoint *PhysicalEndpoint) error {
|
|
||||||
return drivers.BindDevicetoHost(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Long term, this should be made more configurable. For now matching path
|
|
||||||
// provided by CNM VPP and OVS-DPDK plugins, available at github.com/clearcontainers/vpp and
|
|
||||||
// github.com/clearcontainers/ovsdpdk. The plugins create the socket on the host system
|
|
||||||
// using this path.
|
|
||||||
const hostSocketSearchPath = "/tmp/vhostuser_%s/vhu.sock"
|
|
||||||
|
|
||||||
// findVhostUserNetSocketPath checks if an interface is a dummy placeholder
|
|
||||||
// for a vhost-user socket, and if it is it returns the path to the socket
|
|
||||||
func findVhostUserNetSocketPath(netInfo NetworkInfo) (string, error) {
|
|
||||||
if netInfo.Iface.Name == "lo" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for socket file existence at known location.
|
|
||||||
for _, addr := range netInfo.Addrs {
|
|
||||||
socketPath := fmt.Sprintf(hostSocketSearchPath, addr.IPNet.IP)
|
|
||||||
if _, err := os.Stat(socketPath); err == nil {
|
|
||||||
return socketPath, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// vhostUserSocketPath returns the path of the socket discovered. This discovery
|
|
||||||
// will vary depending on the type of vhost-user socket.
|
|
||||||
// Today only VhostUserNetDevice is supported.
|
|
||||||
func vhostUserSocketPath(info interface{}) (string, error) {
|
|
||||||
|
|
||||||
switch v := info.(type) {
|
|
||||||
case NetworkInfo:
|
|
||||||
return findVhostUserNetSocketPath(v)
|
|
||||||
default:
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// network is the virtcontainers network interface.
|
// network is the virtcontainers network interface.
|
||||||
// Container network plugins are used to setup virtual network
|
// Container network plugins are used to setup virtual network
|
||||||
// between VM netns and the host network physical interface.
|
// between VM netns and the host network physical interface.
|
||||||
|
194
virtcontainers/physical_endpoint.go
Normal file
194
virtcontainers/physical_endpoint.go
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/device/drivers"
|
||||||
|
"github.com/safchain/ethtool"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PhysicalEndpoint gathers a physical network interface and its properties
|
||||||
|
type PhysicalEndpoint struct {
|
||||||
|
IfaceName string
|
||||||
|
HardAddr string
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
BDF string
|
||||||
|
Driver string
|
||||||
|
VendorDeviceID string
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns the properties of the physical interface.
|
||||||
|
func (endpoint *PhysicalEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// HardwareAddr returns the mac address of the physical network interface.
|
||||||
|
func (endpoint *PhysicalEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the physical interface.
|
||||||
|
func (endpoint *PhysicalEndpoint) Name() string {
|
||||||
|
return endpoint.IfaceName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type indentifies the endpoint as a physical endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties of the physical endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *PhysicalEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for physical endpoint binds the physical network interface to
|
||||||
|
// vfio-pci and adds device to the hypervisor with vfio-passthrough.
|
||||||
|
func (endpoint *PhysicalEndpoint) Attach(h hypervisor) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "physical").Info("Attaching endpoint")
|
||||||
|
|
||||||
|
// Unbind physical interface from host driver and bind to vfio
|
||||||
|
// so that it can be passed to qemu.
|
||||||
|
if err := bindNICToVFIO(endpoint); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use device manager as general device management entrance
|
||||||
|
d := config.VFIODev{
|
||||||
|
BDF: endpoint.BDF,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.addDevice(d, vfioDev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach for physical endpoint unbinds the physical network interface from vfio-pci
|
||||||
|
// and binds it back to the saved host driver.
|
||||||
|
func (endpoint *PhysicalEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
||||||
|
// Bind back the physical network interface to host.
|
||||||
|
// We need to do this even if a new network namespace has not
|
||||||
|
// been created by virtcontainers.
|
||||||
|
networkLogger().WithField("endpoint-type", "physical").Info("Detaching endpoint")
|
||||||
|
|
||||||
|
// We do not need to enter the network namespace to bind back the
|
||||||
|
// physical interface to host driver.
|
||||||
|
return bindNICToHost(endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for physical endpoint not supported yet
|
||||||
|
func (endpoint *PhysicalEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("PhysicalEndpoint does not support Hot attach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for physical endpoint not supported yet
|
||||||
|
func (endpoint *PhysicalEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
return fmt.Errorf("PhysicalEndpoint does not support Hot detach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// isPhysicalIface checks if an interface is a physical device.
|
||||||
|
// We use ethtool here to not rely on device sysfs inside the network namespace.
|
||||||
|
func isPhysicalIface(ifaceName string) (bool, error) {
|
||||||
|
if ifaceName == "lo" {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandle, err := ethtool.NewEthtool()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bus, err := ethHandle.BusInfo(ifaceName)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a pci bus format
|
||||||
|
tokens := strings.Split(bus, ":")
|
||||||
|
if len(tokens) != 3 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var sysPCIDevicesPath = "/sys/bus/pci/devices"
|
||||||
|
|
||||||
|
func createPhysicalEndpoint(netInfo NetworkInfo) (*PhysicalEndpoint, error) {
|
||||||
|
// Get ethtool handle to derive driver and bus
|
||||||
|
ethHandle, err := ethtool.NewEthtool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get BDF
|
||||||
|
bdf, err := ethHandle.BusInfo(netInfo.Iface.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Driver
|
||||||
|
driver, err := ethHandle.DriverName(netInfo.Iface.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get vendor and device id from pci space (sys/bus/pci/devices/$bdf)
|
||||||
|
|
||||||
|
ifaceDevicePath := filepath.Join(sysPCIDevicesPath, bdf, "device")
|
||||||
|
contents, err := ioutil.ReadFile(ifaceDevicePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceID := strings.TrimSpace(string(contents))
|
||||||
|
|
||||||
|
// Vendor id
|
||||||
|
ifaceVendorPath := filepath.Join(sysPCIDevicesPath, bdf, "vendor")
|
||||||
|
contents, err = ioutil.ReadFile(ifaceVendorPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
vendorID := strings.TrimSpace(string(contents))
|
||||||
|
vendorDeviceID := fmt.Sprintf("%s %s", vendorID, deviceID)
|
||||||
|
vendorDeviceID = strings.TrimSpace(vendorDeviceID)
|
||||||
|
|
||||||
|
physicalEndpoint := &PhysicalEndpoint{
|
||||||
|
IfaceName: netInfo.Iface.Name,
|
||||||
|
HardAddr: netInfo.Iface.HardwareAddr.String(),
|
||||||
|
VendorDeviceID: vendorDeviceID,
|
||||||
|
EndpointType: PhysicalEndpointType,
|
||||||
|
Driver: driver,
|
||||||
|
BDF: bdf,
|
||||||
|
}
|
||||||
|
|
||||||
|
return physicalEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindNICToVFIO(endpoint *PhysicalEndpoint) error {
|
||||||
|
return drivers.BindDevicetoVFIO(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindNICToHost(endpoint *PhysicalEndpoint) error {
|
||||||
|
return drivers.BindDevicetoHost(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID)
|
||||||
|
}
|
149
virtcontainers/vhostuser_endpoint.go
Normal file
149
virtcontainers/vhostuser_endpoint.go
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/device/config"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Long term, this should be made more configurable. For now matching path
|
||||||
|
// provided by CNM VPP and OVS-DPDK plugins, available at github.com/clearcontainers/vpp and
|
||||||
|
// github.com/clearcontainers/ovsdpdk. The plugins create the socket on the host system
|
||||||
|
// using this path.
|
||||||
|
const hostSocketSearchPath = "/tmp/vhostuser_%s/vhu.sock"
|
||||||
|
|
||||||
|
// VhostUserEndpoint represents a vhost-user socket based network interface
|
||||||
|
type VhostUserEndpoint struct {
|
||||||
|
// Path to the vhost-user socket on the host system
|
||||||
|
SocketPath string
|
||||||
|
// MAC address of the interface
|
||||||
|
HardAddr string
|
||||||
|
IfaceName string
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
EndpointType EndpointType
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns the properties of the interface.
|
||||||
|
func (endpoint *VhostUserEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the interface.
|
||||||
|
func (endpoint *VhostUserEndpoint) Name() string {
|
||||||
|
return endpoint.IfaceName
|
||||||
|
}
|
||||||
|
|
||||||
|
// HardwareAddr returns the mac address of the vhostuser network interface
|
||||||
|
func (endpoint *VhostUserEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type indentifies the endpoint as a vhostuser endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties of the endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for vhostuser endpoint
|
||||||
|
func (endpoint *VhostUserEndpoint) Attach(h hypervisor) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "vhostuser").Info("Attaching endpoint")
|
||||||
|
|
||||||
|
// Generate a unique ID to be used for hypervisor commandline fields
|
||||||
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
id := hex.EncodeToString(randBytes)
|
||||||
|
|
||||||
|
d := config.VhostUserDeviceAttrs{
|
||||||
|
DevID: id,
|
||||||
|
SocketPath: endpoint.SocketPath,
|
||||||
|
MacAddress: endpoint.HardAddr,
|
||||||
|
Type: config.VhostUserNet,
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.addDevice(d, vhostuserDev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach for vhostuser endpoint
|
||||||
|
func (endpoint *VhostUserEndpoint) Detach(netNsCreated bool, netNsPath string) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "vhostuser").Info("Detaching endpoint")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for vhostuser endpoint not supported yet
|
||||||
|
func (endpoint *VhostUserEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
return fmt.Errorf("VhostUserEndpoint does not support Hot attach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for vhostuser endpoint not supported yet
|
||||||
|
func (endpoint *VhostUserEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
return fmt.Errorf("VhostUserEndpoint does not support Hot detach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a vhostuser endpoint
|
||||||
|
func createVhostUserEndpoint(netInfo NetworkInfo, socket string) (*VhostUserEndpoint, error) {
|
||||||
|
|
||||||
|
vhostUserEndpoint := &VhostUserEndpoint{
|
||||||
|
SocketPath: socket,
|
||||||
|
HardAddr: netInfo.Iface.HardwareAddr.String(),
|
||||||
|
IfaceName: netInfo.Iface.Name,
|
||||||
|
EndpointType: VhostUserEndpointType,
|
||||||
|
}
|
||||||
|
return vhostUserEndpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// findVhostUserNetSocketPath checks if an interface is a dummy placeholder
|
||||||
|
// for a vhost-user socket, and if it is it returns the path to the socket
|
||||||
|
func findVhostUserNetSocketPath(netInfo NetworkInfo) (string, error) {
|
||||||
|
if netInfo.Iface.Name == "lo" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for socket file existence at known location.
|
||||||
|
for _, addr := range netInfo.Addrs {
|
||||||
|
socketPath := fmt.Sprintf(hostSocketSearchPath, addr.IPNet.IP)
|
||||||
|
if _, err := os.Stat(socketPath); err == nil {
|
||||||
|
return socketPath, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// vhostUserSocketPath returns the path of the socket discovered. This discovery
|
||||||
|
// will vary depending on the type of vhost-user socket.
|
||||||
|
// Today only VhostUserNetDevice is supported.
|
||||||
|
func vhostUserSocketPath(info interface{}) (string, error) {
|
||||||
|
|
||||||
|
switch v := info.(type) {
|
||||||
|
case NetworkInfo:
|
||||||
|
return findVhostUserNetSocketPath(v)
|
||||||
|
default:
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
144
virtcontainers/virtual_endpoint.go
Normal file
144
virtcontainers/virtual_endpoint.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VirtualEndpoint gathers a network pair and its properties.
|
||||||
|
type VirtualEndpoint struct {
|
||||||
|
NetPair NetworkInterfacePair
|
||||||
|
EndpointProperties NetworkInfo
|
||||||
|
Physical bool
|
||||||
|
EndpointType EndpointType
|
||||||
|
PCIAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createVirtualNetworkEndpoint(idx int, ifName string, interworkingModel NetInterworkingModel) (*VirtualEndpoint, error) {
|
||||||
|
if idx < 0 {
|
||||||
|
return &VirtualEndpoint{}, fmt.Errorf("invalid network endpoint index: %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
netPair, err := createNetworkInterfacePair(idx, ifName, interworkingModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &VirtualEndpoint{
|
||||||
|
// TODO This is too specific. We may need to create multiple
|
||||||
|
// end point types here and then decide how to connect them
|
||||||
|
// at the time of hypervisor attach and not here
|
||||||
|
NetPair: netPair,
|
||||||
|
EndpointType: VirtualEndpointType,
|
||||||
|
}
|
||||||
|
if ifName != "" {
|
||||||
|
endpoint.NetPair.VirtIface.Name = ifName
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties returns properties for the veth interface in the network pair.
|
||||||
|
func (endpoint *VirtualEndpoint) Properties() NetworkInfo {
|
||||||
|
return endpoint.EndpointProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns name of the veth interface in the network pair.
|
||||||
|
func (endpoint *VirtualEndpoint) 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 *VirtualEndpoint) HardwareAddr() string {
|
||||||
|
return endpoint.NetPair.TAPIface.HardAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type identifies the endpoint as a virtual endpoint.
|
||||||
|
func (endpoint *VirtualEndpoint) Type() EndpointType {
|
||||||
|
return endpoint.EndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
// PciAddr returns the PCI address of the endpoint.
|
||||||
|
func (endpoint *VirtualEndpoint) PciAddr() string {
|
||||||
|
return endpoint.PCIAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkPair returns the network pair of the endpoint.
|
||||||
|
func (endpoint *VirtualEndpoint) NetworkPair() *NetworkInterfacePair {
|
||||||
|
return &endpoint.NetPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperties sets the properties for the endpoint.
|
||||||
|
func (endpoint *VirtualEndpoint) SetProperties(properties NetworkInfo) {
|
||||||
|
endpoint.EndpointProperties = properties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach for virtual endpoint bridges the network pair and adds the
|
||||||
|
// tap interface of the network pair to the hypervisor.
|
||||||
|
func (endpoint *VirtualEndpoint) Attach(h hypervisor) error {
|
||||||
|
networkLogger().WithField("endpoint-type", "virtual").Info("Attaching endpoint")
|
||||||
|
|
||||||
|
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error bridging virtual endpoint")
|
||||||
|
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 *VirtualEndpoint) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
networkLogger().WithField("endpoint-type", "virtual").Info("Detaching endpoint")
|
||||||
|
|
||||||
|
return doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
return xconnectVMNetwork(endpoint, false, 0, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotAttach for the virtual endpoint uses hot plug device
|
||||||
|
func (endpoint *VirtualEndpoint) HotAttach(h hypervisor) error {
|
||||||
|
networkLogger().Info("Hot attaching virtual endpoint")
|
||||||
|
if err := xconnectVMNetwork(endpoint, true, h.hypervisorConfig().NumVCPUs, h.hypervisorConfig().DisableVhostNet); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error bridging virtual ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.hotplugAddDevice(endpoint, netDev); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error attach virtual ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HotDetach for the virtual endpoint uses hot pull device
|
||||||
|
func (endpoint *VirtualEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
|
||||||
|
if !netNsCreated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
networkLogger().Info("Hot detaching virtual endpoint")
|
||||||
|
if err := doNetNS(netNsPath, func(_ ns.NetNS) error {
|
||||||
|
return xconnectVMNetwork(endpoint, false, 0, h.hypervisorConfig().DisableVhostNet)
|
||||||
|
}); err != nil {
|
||||||
|
networkLogger().WithError(err).Warn("Error un-bridging virtual ep")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.hotplugRemoveDevice(endpoint, netDev); err != nil {
|
||||||
|
networkLogger().WithError(err).Error("Error detach virtual ep")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user