From: Marc-André Lureau
The bridge can now be interrupted with ctrl-c. Once the slave channel is
up, it will request a shutdown, and wait for success reply to exit.
Signed-off-by: Marc-André Lureau
---
tests/vhost-user-bridge.c | 102 --
1 file changed, 99 insertions(+), 3 deletions(-)
diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
index 42450a6..ea123be 100644
--- a/tests/vhost-user-bridge.c
+++ b/tests/vhost-user-bridge.c
@@ -135,6 +135,9 @@ dispatcher_wait(Dispatcher *dispr, uint32_t timeout)
int rc = select(dispr->max_sock + 1, &fdset, 0, 0, &tv);
if (rc == -1) {
+if (errno == EINTR) {
+return 0;
+}
vubr_die("select");
}
@@ -186,6 +189,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_SLAVE_CHANNEL = 3,
VHOST_USER_PROTOCOL_F_MAX
};
@@ -213,9 +217,16 @@ typedef enum VhostUserRequest {
VHOST_USER_GET_QUEUE_NUM = 17,
VHOST_USER_SET_VRING_ENABLE = 18,
VHOST_USER_SEND_RARP = 19,
+VHOST_USER_SET_SLAVE_FD = 20,
VHOST_USER_MAX
} VhostUserRequest;
+typedef enum VhostUserSlaveRequest {
+VHOST_USER_SLAVE_NONE = 0,
+VHOST_USER_SLAVE_SHUTDOWN = 1,
+VHOST_USER_SLAVE_MAX
+} VhostUserSlaveRequest;
+
typedef struct VhostUserMemoryRegion {
uint64_t guest_phys_addr;
uint64_t memory_size;
@@ -288,6 +299,8 @@ typedef struct VubrDev {
int ready;
uint64_t features;
int hdrlen;
+int slave_fd;
+bool shutdown_requested;
} VubrDev;
static const char *vubr_request_str[] = {
@@ -311,7 +324,14 @@ static const char *vubr_request_str[] = {
[VHOST_USER_GET_QUEUE_NUM] = "VHOST_USER_GET_QUEUE_NUM",
[VHOST_USER_SET_VRING_ENABLE] = "VHOST_USER_SET_VRING_ENABLE",
[VHOST_USER_SEND_RARP] = "VHOST_USER_SEND_RARP",
-[VHOST_USER_MAX]= "VHOST_USER_MAX",
+[VHOST_USER_SET_SLAVE_FD] = "VHOST_USER_SET_SLAVE_FD",
+[VHOST_USER_MAX]= "VHOST_USER_MAX"
+};
+
+static const char *vubr_slave_request_str[] = {
+[VHOST_USER_SLAVE_NONE] = "VHOST_USER_SLAVE_NONE",
+[VHOST_USER_SLAVE_SHUTDOWN] = "VHOST_USER_SLAVE_SHUTDOWN",
+[VHOST_USER_SLAVE_MAX] = "VHOST_USER_SLAVE_MAX"
};
static void
@@ -638,7 +658,7 @@ vubr_process_desc(VubrDev *dev, VubrVirtq *vq)
size_t buf_size = 4096;
uint8_t buf[4096];
-DPRINT("Chunks: ");
+DPRINT("Chunks: aidx:%d ", a_index);
i = d_index;
do {
void *chunk_start = (void *)(uintptr_t)gpa_to_va(dev, desc[i].addr);
@@ -1063,7 +1083,9 @@ vubr_set_vring_err_exec(VubrDev *dev, VhostUserMsg *vmsg)
static int
vubr_get_protocol_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
{
-vmsg->payload.u64 = 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
+vmsg->payload.u64 =
+1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD |
+1ULL << VHOST_USER_PROTOCOL_F_SLAVE_CHANNEL;
DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
vmsg->size = sizeof(vmsg->payload.u64);
@@ -1105,6 +1127,46 @@ vubr_send_rarp_exec(VubrDev *dev, VhostUserMsg *vmsg)
return 0;
}
+static void
+vubr_handle_slave_reply(VhostUserMsg *vmsg)
+{
+DPRINT(
+"== Vhost slave reply from QEMU
==\n");
+DPRINT("Request: %s (%d)\n", vubr_slave_request_str[vmsg->request],
+ vmsg->request);
+DPRINT("Flags: 0x%x\n", vmsg->flags);
+DPRINT("Size:%d\n", vmsg->size);
+
+switch (vmsg->request) {
+case VHOST_USER_SLAVE_SHUTDOWN:
+DPRINT("Shutdown success: 0x%016"PRIx64"\n", vmsg->payload.u64);
+if (vmsg->payload.u64 == 0) {
+exit(0);
+}
+default:
+DPRINT("Invalid slave reply");
+};
+}
+
+static void
+slave_receive_cb(int sock, void *ctx)
+{
+VhostUserMsg vmsg;
+
+vubr_message_read(sock, &vmsg);
+vubr_handle_slave_reply(&vmsg);
+}
+
+static int
+vubr_set_slave_fd_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+assert(vmsg->fd_num == 1);
+dev->slave_fd = vmsg->fds[0];
+DPRINT("Got slave_fd: %d\n", vmsg->fds[0]);
+dispatcher_add(&dev->dispatcher, dev->slave_fd, dev, slave_receive_cb);
+return 0;
+}
+
static int
vubr_execute_request(VubrDev *dev, VhostUserMsg *vmsg)
{
@@ -1166,6 +1228,8 @@ vubr_execute_request(VubrDev *dev, VhostUserMsg *vmsg)
return vubr_set_vring_enable_exec(dev, vmsg);
case VHOST_USER_SEND_RARP:
return vubr_send_rarp_exec(dev, vmsg);
+case VHOST_USER_SET_SLAVE_FD:
+return vubr_set_slave_fd_exec(dev, vmsg);
case VHOST_USER_MAX:
assert(vmsg->request != VHOST_USER_MAX);
@@ -1226,6 +1290,7 @@ vubr_new(const char *path)
};
}
+dev->slave_fd = -1;
/* Init log */
dev->log_call_fd = -1;
dev->