Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
virtcontainers: support vhost and physical endpoints in AddInterface
Browse files Browse the repository at this point in the history
Support to hotplug vhost and physical endpoints by AddInterface API

Fixes #758

Signed-off-by: Ruidong Cao <[email protected]>
  • Loading branch information
caoruidong committed Sep 21, 2018
1 parent 611158a commit ec87dca
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 37 deletions.
96 changes: 61 additions & 35 deletions virtcontainers/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ type Endpoint interface {
Name() string
HardwareAddr() string
Type() EndpointType
PciAddr() string

SetProperties(NetworkInfo)
Attach(hypervisor) error
Expand All @@ -178,6 +179,7 @@ type PhysicalEndpoint struct {
BDF string
Driver string
VendorDeviceID string
PCIAddr string
}

// VhostUserEndpoint represents a vhost-user socket based network interface
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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) {
Expand Down
5 changes: 3 additions & 2 deletions virtcontainers/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
}

Expand Down

0 comments on commit ec87dca

Please sign in to comment.