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