virtcontainers: support vhost and physical endpoints in AddInterface

Support to hotplug vhost and physical endpoints by AddInterface API

Fixes #758

Signed-off-by: Ruidong Cao <caoruidong@huawei.com>
This commit is contained in:
Ruidong Cao 2018-09-20 00:19:37 +08:00
parent 611158ac54
commit ec87dca2d8
2 changed files with 64 additions and 37 deletions

View File

@ -152,6 +152,7 @@ type Endpoint interface {
Name() string
HardwareAddr() string
Type() EndpointType
PciAddr() string
SetProperties(NetworkInfo)
Attach(hypervisor) error
@ -178,6 +179,7 @@ type PhysicalEndpoint struct {
BDF string
Driver string
VendorDeviceID string
PCIAddr string
}
// VhostUserEndpoint represents a vhost-user socket based network interface
@ -189,6 +191,7 @@ type VhostUserEndpoint struct {
IfaceName string
EndpointProperties NetworkInfo
EndpointType EndpointType
PCIAddr string
}
// Properties returns properties for the veth interface in the network pair.
@ -212,6 +215,11 @@ func (endpoint *VirtualEndpoint) Type() EndpointType {
return endpoint.EndpointType
}
// PciAddr returns the PCI address of the endpoint.
func (endpoint *VirtualEndpoint) PciAddr() string {
return endpoint.PCIAddr
}
// SetProperties sets the properties for the endpoint.
func (endpoint *VirtualEndpoint) SetProperties(properties NetworkInfo) {
endpoint.EndpointProperties = properties
@ -309,6 +317,11 @@ 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
}
// Attach for vhostuser endpoint
func (endpoint *VhostUserEndpoint) Attach(h hypervisor) error {
networkLogger().WithField("endpoint-type", "vhostuser").Info("Attaching endpoint")
@ -378,6 +391,11 @@ 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
@ -1302,7 +1320,10 @@ func createEndpointsFromScan(networkNSPath string, config NetworkConfig) ([]Endp
idx := 0
for _, link := range linkList {
var endpoint Endpoint
var (
endpoint Endpoint
errCreate error
)
netInfo, err := networkInfoFromLink(netlinkHandle, link)
if err != nil {
@ -1323,40 +1344,8 @@ func createEndpointsFromScan(networkNSPath string, config NetworkConfig) ([]Endp
}
if err := doNetNS(networkNSPath, func(_ ns.NetNS) error {
// TODO: This is the incoming interface
// based on the incoming interface we should create
// an appropriate EndPoint based on interface type
// This should be a switch
// Check if interface is a physical interface. Do not create
// tap interface/bridge if it is.
isPhysical, err := isPhysicalIface(netInfo.Iface.Name)
if err != nil {
return err
}
if isPhysical {
networkLogger().WithField("interface", netInfo.Iface.Name).Info("Physical network interface found")
endpoint, err = createPhysicalEndpoint(netInfo)
} else {
var socketPath string
// Check if this is a dummy interface which has a vhost-user socket associated with it
socketPath, err = vhostUserSocketPath(netInfo)
if err != nil {
return err
}
if socketPath != "" {
networkLogger().WithField("interface", netInfo.Iface.Name).Info("VhostUser network interface found")
endpoint, err = createVhostUserEndpoint(netInfo, socketPath)
} else {
endpoint, err = createVirtualNetworkEndpoint(idx, netInfo.Iface.Name, config.InterworkingModel)
}
}
return err
endpoint, errCreate = createEndpoint(netInfo, idx, config.InterworkingModel)
return errCreate
}); err != nil {
return []Endpoint{}, err
}
@ -1370,6 +1359,43 @@ func createEndpointsFromScan(networkNSPath string, config NetworkConfig) ([]Endp
return endpoints, nil
}
func createEndpoint(netInfo NetworkInfo, idx int, model NetInterworkingModel) (Endpoint, error) {
var endpoint Endpoint
// TODO: This is the incoming interface
// based on the incoming interface we should create
// an appropriate EndPoint based on interface type
// This should be a switch
// Check if interface is a physical interface. Do not create
// tap interface/bridge if it is.
isPhysical, err := isPhysicalIface(netInfo.Iface.Name)
if err != nil {
return nil, err
}
if isPhysical {
networkLogger().WithField("interface", netInfo.Iface.Name).Info("Physical network interface found")
endpoint, err = createPhysicalEndpoint(netInfo)
} else {
var socketPath string
// Check if this is a dummy interface which has a vhost-user socket associated with it
socketPath, err = vhostUserSocketPath(netInfo)
if err != nil {
return nil, err
}
if socketPath != "" {
networkLogger().WithField("interface", netInfo.Iface.Name).Info("VhostUser network interface found")
endpoint, err = createVhostUserEndpoint(netInfo, socketPath)
} else {
endpoint, err = createVirtualNetworkEndpoint(idx, netInfo.Iface.Name, model)
}
}
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) {

View File

@ -1105,10 +1105,11 @@ func (s *Sandbox) AddInterface(inf *grpc.Interface) (*grpc.Interface, error) {
return nil, err
}
endpoint, err := createVirtualNetworkEndpoint(len(s.networkNS.Endpoints), inf.Name, s.config.NetworkConfig.InterworkingModel)
endpoint, err := createEndpoint(netInfo, len(s.networkNS.Endpoints), s.config.NetworkConfig.InterworkingModel)
if err != nil {
return nil, err
}
endpoint.SetProperties(netInfo)
if err := doNetNS(s.networkNS.NetNsPath, func(_ ns.NetNS) error {
return endpoint.HotAttach(s.hypervisor)
@ -1123,7 +1124,7 @@ func (s *Sandbox) AddInterface(inf *grpc.Interface) (*grpc.Interface, error) {
}
// Add network for vm
inf.PciAddr = endpoint.PCIAddr
inf.PciAddr = endpoint.PciAddr()
return s.agent.updateInterface(inf)
}