[Spice-devel] RFC: spice vdagent protocol documentation

Hans de Goede hdegoede at redhat.com
Wed Sep 1 07:22:31 PDT 2010


Hi All,

This is a first draft version / a first attempt to document the
spice vdagent protocol. This is meant to eventually go to the wiki.

Question where on the wiki should I put this?

spice vdagent protocol
-----------------------

For certain features to work spice requires that the guest os is running
the spice agent (vdagent). This document describes how vdagent communicates
with the spice server and client.


1. vdagent virtio serial port
-----------------------------

All vdagent communications on the guest side run over a single pipe which
gets presented to the guest os as a virtio serial port. Under windows this
virtio serial port is identified by the following guid:
const GUID GUID_VIOSERIAL_PORT =
     {0x6fde7521, 0x1b65, 0x48ae, 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26}

Under Linux this virtio serial port has the following name:
/dev/virtio-ports/com.redhat.spice.0


2. vdagent data chunks / ports
------------------------------

The vdagent is connect through the virtio serial port (vdagent channel) with
the spice server but it can receive messages from / send messages to both
the spice server and the spice client. To make this possible all messages on
the vdagent channel are prefixed with a VDIChunkHeader:
typedef struct SPICE_ATTR_PACKED VDIChunkHeader {
     uint32_t port;
     uint32_t size;
} VDIChunkHeader;

Where size is the size of the VDAgentMessage being send / received including
the variable data part, iow it is sizeof(VDAgentMessage) + variable_data_len,
and port is one of:
enum {
     VDP_CLIENT_PORT = 1,
     VDP_SERVER_PORT,
};

When the vdagent receives messages port indicates where the message came from.
When sending messages port indicates the intended receiver. When a message is
a reply / ack of a received message port should have the same value as it had
in the received message the message being send is a reply to.

When the spice server receives a message it removes the chunk header and
then depending on the port in the chunk header, forwards it to the client,
handles it itself, or if the port is not a valid value logs an error and
drops the message.

Note currently there are no messages from the agent which are meant for the
server so all messages send by the agent with a port of VDP_SERVER_PORT get
dropped silently.


3. vdagent message struct
-------------------------

Messages send / received by the agent are encapsulated in the VDAgentMessage
struct:
typedef struct SPICE_ATTR_PACKED VDAgentMessage {
     uint32_t protocol;
     uint32_t type;
     uint64_t opaque;
     uint32_t size;
     uint8_t data[0];
} VDAgentMessage;

Where protocol is always VD_AGENT_PROTOCOL.

Type is a value from the following enum:
enum {
     VD_AGENT_MOUSE_STATE = 1,
     VD_AGENT_MONITORS_CONFIG,
     VD_AGENT_REPLY,
     VD_AGENT_CLIPBOARD,
     VD_AGENT_DISPLAY_CONFIG,
     VD_AGENT_ANNOUNCE_CAPABILITIES,
     VD_AGENT_END_MESSAGE,
};

Opaque is a place holder for message types which only need to pass a single
integer as message data, for message types which have more data it is
always set to 0.

Size is the size of the variable length data. Note that the size of the
complete message in the channel is
sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + variable_data_len

Data is the start of the variable length data, the contents of this depends
on the message types, for most messages it is a message type specific
struct such as VDAgentMouseState. Note that data is declared as a 0 sized
array meaning that it does not take up any size in the struct, it is simply
there to be able to easily determine the start address of the data.


4. vdagent messages
-------------------

4.1 VD_AGENT_MOUSE_STATE

Spice supports two mouse modes, server and client.

In server mode the the QEMU ps/2 mouse emulation is used for sending mouse
state to the guest. Upon user click inside the Spice client window, the client
mouse is captured and the client sends mouse moves as delta coordinates.

In client mode mouse coordinates are send as absolute values to the guest,
this requires using either usb table emulation, or sending them to the
vdagent which will them notify the guest os of the mouse position (and of
button clicks).

The VD_AGENT_MOUSE_STATE message contains mouse state updates send by the
spice server when the mouse is in client mode. The variable data of these
messages consists of the following structure:

typedef struct SPICE_ATTR_PACKED VDAgentMouseState {
     uint32_t x;
     uint32_t y;
     uint32_t buttons;
     uint8_t display_id;
} VDAgentMouseState;

Note these messages are send by the spice server, not by the spice client as
the server does all the mouse handling (like switching between client and
server mode as the vdagent connects / disconnects).

4.2 VD_AGENT_MONITORS_CONFIG

This message gets send by the client to the agent when the client is run
in fullscreen auto configuration mode. This message contains information
about the monitors attached to the client machine. Upon receiving this
message the agent should reconfigure the output(s) of the qxl vga devices
in the guest to match those in the message in as far as possible. For
example if the client has more outputs then there are configured in the
vm the outputs which are present should be configured to match what is
in the message.

The variable data of these messages consists of the following structure:

typedef struct SPICE_ATTR_PACKED VDAgentMonitorsConfig {
     uint32_t num_of_monitors;
     uint32_t flags;
     VDAgentMonConfig monitors[0];
} VDAgentMonitorsConfig;

Followed by num_of_monitors times the following structure:

typedef struct SPICE_ATTR_PACKED VDAgentMonConfig {
     uint32_t height;
     uint32_t width;
     uint32_t depth;
     int32_t x;
     int32_t y;
} VDAgentMonConfig;

When the agent is done configuring the outputs it should send back in
VD_AGENT_REPLY message with a type set to VD_AGENT_MONITORS_CONFIG
and error set to VD_AGENT_SUCCESS or VD_AGENT_ERROR to indicate success
resp. error in configuring the outputs.

4.3 VD_AGENT_REPLY

This message gets send by the vdagent to the spice client to signal
it is done handling a VD_AGENT_MONITORS_CONFIG or VD_AGENT_DISPLAY_CONFIG,
and if it succeeded or not:

typedef struct SPICE_ATTR_PACKED VDAgentReply {
     uint32_t type;
     uint32_t error;
} VDAgentReply;

enum {
     VD_AGENT_SUCCESS = 1,
     VD_AGENT_ERROR,
};

4.4 VD_AGENT_CLIPBOARD

Still in flux

4.5 VD_AGENT_DISPLAY_CONFIG

This message gets send by the spice client to the vdagent to notify it of
any special performance related settings. The client can ask the vdagent
to disable various features of the guest os like font anti aliasing to improve
performance. vdagent should do a best effort here, esp. as most settings
are rather windows centric and should return a success status using
VD_AGENT_REPLY unless something really went wrong.

typedef struct SPICE_ATTR_PACKED VDAgentDisplayConfig {
     uint32_t flags;
     uint32_t depth;
} VDAgentDisplayConfig;

enum {
     VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_WALLPAPER = (1 << 0),
     VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_FONT_SMOOTH = (1 << 1),
     VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_ANIMATION = (1 << 2),
     VD_AGENT_DISPLAY_CONFIG_FLAG_SET_COLOR_DEPTH = (1 << 3),
};

4.6 VD_AGENT_ANNOUNCE_CAPABILITIES

This message can (and should) be send by both the client and the vdagent,
it announces which messages / capabilities (one capability can encompass
multiple messages) the sending side may send and/or knows how to handle
when received. The purpose of this message is to allow different client
and vdagent versions to work together:

typedef struct SPICE_ATTR_PACKED VDAgentAnnounceCapabilities {
     uint32_t  request;
     uint32_t caps[0];
} VDAgentAnnounceCapabilities;

The request field is a boolean which indicates if the receiver of the
message should send back an VD_AGENT_ANNOUNCE_CAPABILITIES message as
the sender wants to know its capabilities too. It should be true when
initiating a capabilities exchange, and set to false when sending an
announce capabilities as a reply to a received one.

The caps member of the struct is the beginning of a variable length array
holding the capabilities bit, the length of this array can be determined
using the VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE macro on the VDAgentMessage
msg size member. The indexes for the different capabilities are in an enum
defining VD_AGENT_CAP_ constants and there are VD_AGENT_HAS_CAPABILITY
and VD_AGENT_SET_CAPABILITY macros to test / set the capability bits
in the array.

Regards,

Hans


More information about the Spice-devel mailing list