Skip to content
Kei Kamikawa edited this page Nov 2, 2022 · 4 revisions

(Virtio) Socket configure services and other communication endpoints in your virtual machine. Host computers make services available using ports, which identify the type of service and the protocol to use when transmitting data. Use this object to specify the ports available to your guest operating system, and to register handlers to manage the communication on those ports. To enable socket device communication support in Linux, configure the Linux guest kernel to enable the CONFIG_VIRTIO_VSOCKETS support.

Overview

Use a vz.VirtioSocketDeviceConfiguration to implement port-based communication between the guest operating system and the host computer. When you add this object to the socketDevices property of your vz.VirtualMachineConfiguration, the virtual machine provides a corresponding vz.VirtioSocketDevice to use to configure the ports. Add only one vz.VirtioSocketDeviceConfiguration to your virtual machine’s configuration.

The example below shows the creation of a vz.VirtioSocketDeviceConfiguration:

socketDevice, err := vz.NewVirtioSocketDeviceConfiguration()
if err != nil {
	return nil, err
}
config.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{
	socketDevice,
})

Once the configuration is complete and your virtual machine is created, the socket device is available. The virtual machine creates it and stores it in the socketDevices property. You can obtain the socket device with the following code:

socketDevices := vm.SocketDevices()
if len(socketDevices) != 1 {
	log.Fatalf("want the number of socket devices is 1 but got %d", len(socketDevices))
}
socketDevice := socketDevices[0]

Connect from guest to host

To connect the guest to the host, the socat is used here. socat supports the VSOCK family required for this communication, which is very useful as it can behave both as a client and as a server.

In this example, echo server is served using socketDevice to wait for connections from guests:

listener, err := socketDevice.Listen(4321)
if err != nil {
	return err
}
defer listener.Close()

log.Println("host is waiting on:", listener.Addr()) // host is waiting on: 2:4321

go func() {
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("failed to accept connection: %v", err)
			return
		}
		go func() {
			defer conn.Close()
			_, err := io.Copy(conn, conn)
			if err != nil {
				log.Println("error in copy: ", err)
			}

		}()
	}
}()

Send messages as a guest with socat as the client. If successful, the message sent will be returned.

$ echo Hello, World from guest! | socat - VSOCK-CONNECT:2:4321
Hello, World from guest!

Connecting from host to guest

In this example, a socket connection is made from the host to the guest, and messages are exchanged such that the guest returns messages written by the host.

Start the echo server using socat in the guest first:

$ socat PIPE VSOCK-LISTEN:6543,fork

The guest served on port 6543. Next, The example below demonstrates to connect from the virtual machine to the coping port:

conn, err := socketDevice.Connect(6543)
if err != nil {
	return err
}
defer conn.Close()

_, err = conn.Write([]byte("Hello, World from Host!"))
if err != nil {
	return err
}

reply := make([]byte, 40)
n, err := conn.Read(reply)
if err != nil {
	return err
}

log.Println(string(reply[:n])) // Hello, World from Host!