gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/vhostuser_endpoint.go (about)

     1  // Copyright (c) 2018 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"encoding/hex"
    10  	"fmt"
    11  	"os"
    12  
    13  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    14  	persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api"
    15  	"github.com/kata-containers/runtime/virtcontainers/utils"
    16  )
    17  
    18  // Long term, this should be made more configurable.  For now matching path
    19  // provided by CNM VPP and OVS-DPDK plugins, available at github.com/clearcontainers/vpp and
    20  // github.com/clearcontainers/ovsdpdk.  The plugins create the socket on the host system
    21  // using this path.
    22  const hostSocketSearchPath = "/tmp/vhostuser_%s/vhu.sock"
    23  
    24  // VhostUserEndpoint represents a vhost-user socket based network interface
    25  type VhostUserEndpoint struct {
    26  	// Path to the vhost-user socket on the host system
    27  	SocketPath string
    28  	// MAC address of the interface
    29  	HardAddr           string
    30  	IfaceName          string
    31  	EndpointProperties NetworkInfo
    32  	EndpointType       EndpointType
    33  	PCIAddr            string
    34  }
    35  
    36  // Properties returns the properties of the interface.
    37  func (endpoint *VhostUserEndpoint) Properties() NetworkInfo {
    38  	return endpoint.EndpointProperties
    39  }
    40  
    41  // Name returns name of the interface.
    42  func (endpoint *VhostUserEndpoint) Name() string {
    43  	return endpoint.IfaceName
    44  }
    45  
    46  // HardwareAddr returns the mac address of the vhostuser network interface
    47  func (endpoint *VhostUserEndpoint) HardwareAddr() string {
    48  	return endpoint.HardAddr
    49  }
    50  
    51  // Type indentifies the endpoint as a vhostuser endpoint.
    52  func (endpoint *VhostUserEndpoint) Type() EndpointType {
    53  	return endpoint.EndpointType
    54  }
    55  
    56  // SetProperties sets the properties of the endpoint.
    57  func (endpoint *VhostUserEndpoint) SetProperties(properties NetworkInfo) {
    58  	endpoint.EndpointProperties = properties
    59  }
    60  
    61  // PciAddr returns the PCI address of the endpoint.
    62  func (endpoint *VhostUserEndpoint) PciAddr() string {
    63  	return endpoint.PCIAddr
    64  }
    65  
    66  // SetPciAddr sets the PCI address of the endpoint.
    67  func (endpoint *VhostUserEndpoint) SetPciAddr(pciAddr string) {
    68  	endpoint.PCIAddr = pciAddr
    69  }
    70  
    71  // NetworkPair returns the network pair of the endpoint.
    72  func (endpoint *VhostUserEndpoint) NetworkPair() *NetworkInterfacePair {
    73  	return nil
    74  }
    75  
    76  // Attach for vhostuser endpoint
    77  func (endpoint *VhostUserEndpoint) Attach(h hypervisor) error {
    78  	// Generate a unique ID to be used for hypervisor commandline fields
    79  	randBytes, err := utils.GenerateRandomBytes(8)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	id := hex.EncodeToString(randBytes)
    84  
    85  	d := config.VhostUserDeviceAttrs{
    86  		DevID:      id,
    87  		SocketPath: endpoint.SocketPath,
    88  		MacAddress: endpoint.HardAddr,
    89  		Type:       config.VhostUserNet,
    90  	}
    91  
    92  	return h.addDevice(d, vhostuserDev)
    93  }
    94  
    95  // Detach for vhostuser endpoint
    96  func (endpoint *VhostUserEndpoint) Detach(netNsCreated bool, netNsPath string) error {
    97  	return nil
    98  }
    99  
   100  // HotAttach for vhostuser endpoint not supported yet
   101  func (endpoint *VhostUserEndpoint) HotAttach(h hypervisor) error {
   102  	return fmt.Errorf("VhostUserEndpoint does not support Hot attach")
   103  }
   104  
   105  // HotDetach for vhostuser endpoint not supported yet
   106  func (endpoint *VhostUserEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error {
   107  	return fmt.Errorf("VhostUserEndpoint does not support Hot detach")
   108  }
   109  
   110  // Create a vhostuser endpoint
   111  func createVhostUserEndpoint(netInfo NetworkInfo, socket string) (*VhostUserEndpoint, error) {
   112  
   113  	vhostUserEndpoint := &VhostUserEndpoint{
   114  		SocketPath:   socket,
   115  		HardAddr:     netInfo.Iface.HardwareAddr.String(),
   116  		IfaceName:    netInfo.Iface.Name,
   117  		EndpointType: VhostUserEndpointType,
   118  	}
   119  	return vhostUserEndpoint, nil
   120  }
   121  
   122  // findVhostUserNetSocketPath checks if an interface is a dummy placeholder
   123  // for a vhost-user socket, and if it is it returns the path to the socket
   124  func findVhostUserNetSocketPath(netInfo NetworkInfo) (string, error) {
   125  	if netInfo.Iface.Name == "lo" {
   126  		return "", nil
   127  	}
   128  
   129  	// check for socket file existence at known location.
   130  	for _, addr := range netInfo.Addrs {
   131  		socketPath := fmt.Sprintf(hostSocketSearchPath, addr.IPNet.IP)
   132  		if _, err := os.Stat(socketPath); err == nil {
   133  			return socketPath, nil
   134  		}
   135  	}
   136  
   137  	return "", nil
   138  }
   139  
   140  // vhostUserSocketPath returns the path of the socket discovered.  This discovery
   141  // will vary depending on the type of vhost-user socket.
   142  //  Today only VhostUserNetDevice is supported.
   143  func vhostUserSocketPath(info interface{}) (string, error) {
   144  
   145  	switch v := info.(type) {
   146  	case NetworkInfo:
   147  		return findVhostUserNetSocketPath(v)
   148  	default:
   149  		return "", nil
   150  	}
   151  
   152  }
   153  
   154  func (endpoint *VhostUserEndpoint) save() persistapi.NetworkEndpoint {
   155  	return persistapi.NetworkEndpoint{
   156  		Type: string(endpoint.Type()),
   157  		VhostUser: &persistapi.VhostUserEndpoint{
   158  			IfaceName: endpoint.IfaceName,
   159  			PCIAddr:   endpoint.PCIAddr,
   160  		},
   161  	}
   162  }
   163  
   164  func (endpoint *VhostUserEndpoint) load(s persistapi.NetworkEndpoint) {
   165  	endpoint.EndpointType = VhostUserEndpointType
   166  
   167  	if s.VhostUser != nil {
   168  		endpoint.IfaceName = s.VhostUser.IfaceName
   169  		endpoint.PCIAddr = s.VhostUser.PCIAddr
   170  	}
   171  }