CC'ing MarcAndre and Michael S Tsirkin. On Fri, Jun 24, 2016 at 1:47 PM, Prerna Saxena <saxenap....@gmail.com> wrote:
> From: Prerna Saxena <prerna.sax...@nutanix.com> > > Signed-off-by: Prerna Saxena <prerna.sax...@nutanix.com> > --- > docs/specs/vhost-user.txt | 36 +++++++++++ > hw/virtio/vhost-user.c | 153 > +++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 186 insertions(+), 3 deletions(-) > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt > index 777c49c..e5388b2 100644 > --- a/docs/specs/vhost-user.txt > +++ b/docs/specs/vhost-user.txt > @@ -37,6 +37,7 @@ consists of 3 header fields and a payload: > * Flags: 32-bit bit field: > - Lower 2 bits are the version (currently 0x01) > - Bit 2 is the reply flag - needs to be sent on each reply from the > slave > + - Bit 3 is the need_response flag - see > VHOST_USER_PROTOCOL_F_REPLY_ACK for details. > * Size - 32-bit size of the payload > > > @@ -126,6 +127,8 @@ the ones that do: > * VHOST_GET_VRING_BASE > * VHOST_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD) > > +[ Also see the section on REPLY_ACK protocol extension] > + > There are several messages that the master sends with file descriptors > passed > in the ancillary data: > > @@ -254,6 +257,7 @@ Protocol features > #define VHOST_USER_PROTOCOL_F_MQ 0 > #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 > #define VHOST_USER_PROTOCOL_F_RARP 2 > +#define VHOST_USER_PROTOCOL_F_REPLY_ACK 3 > > Message types > ------------- > @@ -464,3 +468,35 @@ Message types > is present in VHOST_USER_GET_PROTOCOL_FEATURES. > The first 6 bytes of the payload contain the mac address of the > guest to > allow the vhost user backend to construct and broadcast the fake > RARP. > + > +VHOST_USER_PROTOCOL_F_REPLY_ACK: > +-------------------------------- > +The original vhost-user specification only demands responses for certain > +commands. This differs from the vhost protocol implementation where > commands > +are sent over an ioctl() call and block until the client has completed. > Not > +receiving a response for commands like VHOST_SET_MEM_TABLE makes the > sender > +unable to tell when the client has finished (re)mapping the GPA, or > whether it > +has failed altogether. > + > +With this protocol extension negotiated, the sender can set the newly > +introduced "need_response" [Bit 3] flag to any command. This indicates > that > +the client MUST to respond with a Payload VhostUserMsg indicating success > or > +failure. The payload should be set to zero on success or non-zero on > failure. > +In other words, response must be in the following format : > +------------------------------------ > +| request | flags | size | payload | > +------------------------------------ > + > + * Request: 32-bit type of the original request which is being responded > to. > + * Flags: 32-bit bit field: (VHOST_USER_VERSION | VHOST_USER_REPLY_MASK) > + * Size: size of the payload ( see below) > + * Payload : a u64 integer, where a non-zero value indicates a failure. > + > +Note that as per the original vhost-user protocol, the following four > messages anyway > +require distinct responses from the vhost-user client process : > + * VHOST_GET_FEATURES > + * VHOST_GET_PROTOCOL_FEATURES > + * VHOST_GET_VRING_BASE > + * VHOST_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD) > +For these message types, the presence of VHOST_USER_PROTOCOL_F_REPLY_ACK > or > +need_response bit being set brings no behaviourial change. > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c > index 495e09f..f01ebb4 100644 > --- a/hw/virtio/vhost-user.c > +++ b/hw/virtio/vhost-user.c > @@ -31,6 +31,7 @@ enum VhostUserProtocolFeature { > VHOST_USER_PROTOCOL_F_MQ = 0, > VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, > VHOST_USER_PROTOCOL_F_RARP = 2, > + VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, > > VHOST_USER_PROTOCOL_F_MAX > }; > @@ -82,8 +83,9 @@ typedef struct VhostUserLog { > typedef struct VhostUserMsg { > VhostUserRequest request; > > -#define VHOST_USER_VERSION_MASK (0x3) > -#define VHOST_USER_REPLY_MASK (0x1<<2) > +#define VHOST_USER_VERSION_MASK (0x3) > +#define VHOST_USER_REPLY_MASK (0x1 << 2) > +#define VHOST_USER_NEED_RESPONSE_MASK (0x1 << 3) > uint32_t flags; > uint32_t size; /* the following payload size */ > union { > @@ -239,10 +241,17 @@ static int vhost_user_set_mem_table(struct vhost_dev > *dev, > int fds[VHOST_MEMORY_MAX_NREGIONS]; > int i, fd; > size_t fd_num = 0; > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > VhostUserMsg msg = { > .request = VHOST_USER_SET_MEM_TABLE, > .flags = VHOST_USER_VERSION, > }; > + VhostUserRequest request = msg.request; > + > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > > for (i = 0; i < dev->mem->nregions; ++i) { > struct vhost_memory_region *reg = dev->mem->regions + i; > @@ -277,6 +286,20 @@ static int vhost_user_set_mem_table(struct vhost_dev > *dev, > > vhost_user_write(dev, &msg, fds, fd_num); > > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > + > return 0; > } > > @@ -289,9 +312,29 @@ static int vhost_user_set_vring_addr(struct vhost_dev > *dev, > .payload.addr = *addr, > .size = sizeof(msg.payload.addr), > }; > + VhostUserRequest request = msg.request; > + > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > vhost_user_write(dev, &msg, NULL, 0); > > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > return 0; > } > > @@ -313,8 +356,28 @@ static int vhost_set_vring(struct vhost_dev *dev, > .size = sizeof(msg.payload.state), > }; > > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > + > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > + > vhost_user_write(dev, &msg, NULL, 0); > > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %lu received %lu", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > return 0; > } > > @@ -395,6 +458,13 @@ static int vhost_set_vring_file(struct vhost_dev *dev, > .size = sizeof(msg.payload.u64), > }; > > + bool reply_Supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > + > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > + > if (ioeventfd_enabled() && file->fd > 0) { > fds[fd_num++] = file->fd; > } else { > @@ -403,6 +473,20 @@ static int vhost_set_vring_file(struct vhost_dev *dev, > > vhost_user_write(dev, &msg, fds, fd_num); > > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > + > return 0; > } > > @@ -489,8 +573,30 @@ static int vhost_user_set_owner(struct vhost_dev *dev) > .flags = VHOST_USER_VERSION, > }; > > + VhostUserRequest request = msg.request; > + > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > + > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > + > vhost_user_write(dev, &msg, NULL, 0); > > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > return 0; > } > > @@ -500,9 +606,30 @@ static int vhost_user_reset_device(struct vhost_dev > *dev) > .request = VHOST_USER_RESET_OWNER, > .flags = VHOST_USER_VERSION, > }; > + VhostUserRequest request = msg.request; > + > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > + > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > > vhost_user_write(dev, &msg, NULL, 0); > > + if (reply_suported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } > return 0; > } > > @@ -589,9 +716,15 @@ static int vhost_user_migration_done(struct vhost_dev > *dev, char* mac_addr) > { > VhostUserMsg msg = { 0 }; > int err; > + VhostUserRequest request = msg.request; > + bool reply_supported = virtio_has_feature(dev->protocol_features, > + VHOST_USER_PROTOCOL_F_REPLY_ACK); > > assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); > > + if (reply_supported) { > + msg.flags |= VHOST_USER_NEED_RESPONSE_MASK; > + } > /* If guest supports GUEST_ANNOUNCE do nothing */ > if (virtio_has_feature(dev->acked_features, > VIRTIO_NET_F_GUEST_ANNOUNCE)) { > return 0; > @@ -606,7 +739,21 @@ static int vhost_user_migration_done(struct vhost_dev > *dev, char* mac_addr) > msg.size = sizeof(msg.payload.u64); > > err = vhost_user_write(dev, &msg, NULL, 0); > - return err; > + if (reply_supported) { > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request != request) { > + error_report("Received unexpected msg type." > + "Expected %d received %d", > + request, msg.request); > + return -1; > + } > + return msg.payload.u64 ? -1 : 0; > + } else { > + return err; > + } > } > return -1; > } > -- > 1.8.1.2 > >