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 }