Skip to contentSkip to conversation

vhost: support inflight share memory protocol feature

PATCH Superseded JinYu 2 participants 4 messages Aug 6, 2019 – Aug 26, 2019 1 message not in the archive Arm/Amlogic Meson SoC support

v5 of 11 Superseded Latest is v11 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): 20190731204050.40633

JinYu

author
#1 lore raw

v5 cover vhost: support inflight share memory protocol feature

This patches introduces two new messages VHOST_USER_GET_INFLIGHT_FD and VHOST_USER_SET_INFLIGHT_FD to support transferring a shared buffer between qemu and backend.
Now It can both support split and packed ring. The example code show how these API work. The test has passed.

How to test the example:
1, Qemu need two patches.
https://patchwork.kernel.org/patch/10766813/
https://patchwork.kernel.org/patch/10861411/
it also needs some manual modifications:
we should confirm that before we send get inflight we have already sent the set features but it seems Qemu didn't do like this. So we manually revise this, we can add below code in vhost_dev_get_inflight

    int r;

    r = vhost_dev_set_features(dev, dev->log_enabled);
    if (r < 0) {
        return -errno;
    }

before get_inflight_fd.
2, Guest OS version >= 5.0
3, run the example
4, run the qemu with vhost-user-blk-pci.
eg:

        -chardev socket,id=spdk_vhost_blk0,reconnect=1,path=xxxx\
        -device vhost-user-blk-pci,ring_packed=on,chardev=spdk_vhost_blk0,num-queues=1\

5, run fio in the guest
6, kill the example(vhost-user backend) and run again. 7, the fio in the guest should continue run without errors.

JinYu (2):
vhost: support inflight share memory protocol feature
vhost: add vhost-user-blk example which support inflight

 examples/vhost_blk/Makefile            |   67 ++
 examples/vhost_blk/blk.c               |  125 +++
 examples/vhost_blk/blk_spec.h          |   95 ++
 examples/vhost_blk/meson.build         |   20 +
 examples/vhost_blk/vhost_blk.c         | 1313 ++++++++++++++++++++++++
 examples/vhost_blk/vhost_blk.h         |  116 +++
 examples/vhost_blk/vhost_blk_compat.c  |  195 ++++
 lib/librte_vhost/rte_vhost.h           |  255 ++++-
 lib/librte_vhost/rte_vhost_version.map |   12 +
 lib/librte_vhost/vhost.c               |  396 ++++++-
 lib/librte_vhost/vhost.h               |   61 +-
 lib/librte_vhost/vhost_user.c          |  437 +++++++-
 lib/librte_vhost/vhost_user.h          |   13 +-
 13 files changed, 3059 insertions(+), 46 deletions(-)
 create mode 100644 examples/vhost_blk/Makefile
 create mode 100644 examples/vhost_blk/blk.c
 create mode 100644 examples/vhost_blk/blk_spec.h
 create mode 100644 examples/vhost_blk/meson.build
 create mode 100644 examples/vhost_blk/vhost_blk.c
 create mode 100644 examples/vhost_blk/vhost_blk.h
 create mode 100644 examples/vhost_blk/vhost_blk_compat.c
Signature · 1 line
2.17.2
author
#2 lore raw

PATCH v5 1/2 vhost: support inflight share memory protocol feature

This patch introduces two new messages VHOST_USER_GET_INFLIGHT_FD and VHOST_USER_SET_INFLIGHT_FD to support transferring a shared buffer between qemu and backend.

Firstly, qemu uses VHOST_USER_GET_INFLIGHT_FD to get the shared buffer from backend. Then qemu should send it back through VHOST_USER_SET_INFLIGHT_FD each time we start vhost-user.

This shared buffer is used to process inflight I/O when backend reconnect.

---
v1 - specify the APIs are split-ring only
v2 - fix APIs and judge split or packed
v3 - Add rte_vhost_ prefix and fix one issue.
v4 - add the packed ring support
v5 - revise get_vring_base func depend on Tiwei's suggestion

---
 lib/librte_vhost/rte_vhost.h           | 255 ++++++++++++++-
 lib/librte_vhost/rte_vhost_version.map |  12 +
 lib/librte_vhost/vhost.c               | 396 +++++++++++++++++++++-
 lib/librte_vhost/vhost.h               |  61 ++--
 lib/librte_vhost/vhost_user.c          | 437 ++++++++++++++++++++++++-
 lib/librte_vhost/vhost_user.h          |  13 +-
 6 files changed, 1128 insertions(+), 46 deletions(-)
lib/librte_vhost/rte_vhost.h +249 -6
index 0226b3eff..3f01429b1 100644
@@ -11,6 +11,7 @@
  */
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/eventfd.h>
 
 #include <rte_memory.h>
@@ -71,6 +72,10 @@ extern "C" {
 #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11
 #endif
 
+#ifndef VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
+#define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12
+#endif
+
 /** Indicate whether protocol features negotiation is supported. */
 #ifndef VHOST_USER_F_PROTOCOL_FEATURES
 #define VHOST_USER_F_PROTOCOL_FEATURES	30
@@ -98,10 +103,92 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[];
 };
 
+struct inflight_desc_packed {
+	uint8_t inflight;
+	uint8_t padding;
+	uint16_t next;
+	uint16_t last;
+	uint16_t num;
+	uint64_t counter;
+	uint16_t id;
+	uint16_t flags;
+	uint32_t len;
+	uint64_t addr;
+};
+
+struct inflight_info_packed {
+	uint64_t features;
+	uint16_t version;
+	uint16_t desc_num;
+	uint16_t free_head;
+	uint16_t old_free_head;
+	uint16_t used_idx;
+	uint16_t old_used_idx;
+	uint8_t used_wrap_counter;
+	uint8_t old_used_wrap_counter;
+	uint8_t padding[7];
+	struct inflight_desc_packed desc[0];
+};
+
+struct rte_vhost_resubmit_desc {
+	uint16_t index;
+	uint64_t counter;
+};
+
+struct rte_vhost_resubmit_info {
+	struct rte_vhost_resubmit_desc	*resubmit_list;
+	uint16_t resubmit_num;
+};
+
+struct rte_vhost_ring_inflight {
+	union {
+		struct inflight_info_split *inflight_split;
+		struct inflight_info_packed *inflight_packed;
+	};
+
+	struct rte_vhost_resubmit_info *resubmit_inflight;
+};
+
+/*
+ * Declare below packed ring defines unconditionally
+ * as Kernel header might use different names.
+ */
+#ifndef VIRTIO_F_RING_PACKED
+#define VIRTIO_F_RING_PACKED 34
+
+#define VRING_DESC_F_AVAIL	(1ULL << 7)
+#define VRING_DESC_F_USED	(1ULL << 15)
+
+struct vring_packed_desc {
+	uint64_t addr;
+	uint32_t len;
+	uint16_t id;
+	uint16_t flags;
+};
+
+#define VRING_EVENT_F_ENABLE 0x0
+#define VRING_EVENT_F_DISABLE 0x1
+#define VRING_EVENT_F_DESC 0x2
+struct vring_packed_desc_event {
+	uint16_t off_wrap;
+	uint16_t flags;
+};
+#endif
+
 struct rte_vhost_vring {
-	struct vring_desc	*desc;
-	struct vring_avail	*avail;
-	struct vring_used	*used;
+	union {
+		struct vring_desc	*desc;
+		struct vring_packed_desc *desc_packed;
+	};
+	union {
+		struct vring_avail	*avail;
+		struct vring_packed_desc_event *driver_event;
+	};
+	union {
+		struct vring_used	*used;
+		struct vring_packed_desc_event *device_event;
+	};
+
 	uint64_t		log_guest_addr;
 
 	/** Deprecated, use rte_vhost_vring_call() instead. */
@@ -603,6 +690,33 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
  */
 int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
 
+/**
+ * Get vq is packed
+ *
+ * @param vid
+ *  vhost device ID
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_vq_is_packed(int vid);
+
+/**
+ * Get guest inflight vring info, including inflight ring and resubmit list.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested inflight vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_get_vhost_ring_inflight(int vid, uint16_t vring_idx,
+	struct rte_vhost_ring_inflight *vring);
+
 /**
  * Get guest vring info, including the vring address, vring size, etc.
  *
@@ -616,7 +730,7 @@ int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
  *  0 on success, -1 on failure
  */
 int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
-			      struct rte_vhost_vring *vring);
+	struct rte_vhost_vring *vring);
 
 /**
  * Notify the guest that used descriptors have been added to the vring.  This
@@ -631,6 +745,112 @@ int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
  */
 int rte_vhost_vring_call(int vid, uint16_t vring_idx);
 
+/**
+ * set split inflight descriptor.
+ *
+ * This function save descriptors that has been comsumed in available
+ * ring
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_inflight_desc_split(int vid, uint16_t vring_idx,
+	uint16_t idx);
+
+/**
+ * set packed inflight descriptor and get corresponding inflight entry
+ *
+ * This function save descriptors that has been comsumed
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_inflight_desc_packed(int vid, uint16_t vring_idx,
+	uint16_t head, uint16_t last, uint16_t *inflight_entry);
+
+/**
+ * save the head of list that the last batch of used descriptors.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  descriptor entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_last_inflight_io_split(int vid,
+	uint16_t vring_idx, uint16_t idx);
+
+/**
+ * update the inflight free_head, used_idx and used_wrap_counter.
+ *
+ * This function will update status first before updating descriptors
+ * to used
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_last_inflight_io_packed(int vid,
+	uint16_t vring_idx, uint16_t head);
+
+/**
+ * clear the split inflight status.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param last_used_idx
+ *  last used idx of used ring
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_clr_inflight_desc_split(int vid, uint16_t vring_idx,
+	uint16_t last_used_idx, uint16_t idx);
+
+/**
+ * clear the packed inflight status.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param head
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_clr_inflight_desc_packed(int vid, uint16_t vring_idx,
+	uint16_t head);
+
 /**
  * Get vhost RX queue avail count.
  *
@@ -656,7 +876,8 @@ uint32_t rte_vhost_rx_queue_count(int vid, uint16_t qid);
  *  0 on success, -1 on failure
  */
 int __rte_experimental
-rte_vhost_get_log_base(int vid, uint64_t *log_base, uint64_t *log_size);
+rte_vhost_get_log_base(int vid, uint64_t *log_base,
+	uint64_t *log_size);
 
 /**
  * Get last_avail/used_idx of the vhost virtqueue
@@ -676,6 +897,28 @@ int __rte_experimental
 rte_vhost_get_vring_base(int vid, uint16_t queue_id,
 		uint16_t *last_avail_idx, uint16_t *last_used_idx);
 
+/**
+ * Get last_avail/last_used of the vhost virtqueue
+ *
+ * This function is designed for the reconnection and it's specific for
+ * the packed ring as we can get the two parameters from the inflight
+ * queueregion
+ *
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  vhost queue index
+ * @param last_avail_idx
+ *  vhost last_avail_idx to get
+ * @param last_used_idx
+ *  vhost last_used_idx to get
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_get_vring_base_from_inflight(int vid,
+	uint16_t queue_id, uint16_t *last_avail_idx, uint16_t *last_used_idx);
+
 /**
  * Set last_avail/used_idx of the vhost virtqueue
  *
@@ -692,7 +935,7 @@ rte_vhost_get_vring_base(int vid, uint16_t queue_id,
  */
 int __rte_experimental
 rte_vhost_set_vring_base(int vid, uint16_t queue_id,
-		uint16_t last_avail_idx, uint16_t last_used_idx);
+	uint16_t last_avail_idx, uint16_t last_used_idx);
 
 /**
  * Register external message handling callbacks
lib/librte_vhost/rte_vhost_version.map +12 -0
index 5f1d4a75c..99f1134ea 100644
@@ -87,4 +87,16 @@ EXPERIMENTAL {
 	rte_vdpa_relay_vring_used;
 	rte_vhost_extern_callback_register;
 	rte_vhost_driver_set_protocol_features;
+	rte_vhost_set_inflight_desc_split;
+	rte_vhost_clr_inflight_desc_split;
+	rte_vhost_set_last_inflight_io_split;
+	rte_vhost_get_vhost_ring_inflight;
+	rte_vhost_vq_is_packed;
+	rte_vhost_set_inflight_desc_packed;
+	rte_vhost_clr_inflight_desc_packed;
+	rte_vhost_set_last_inflight_io_packed;
+	rte_vhost_get_vring_base_counter;
+	rte_vhost_get_vring_base_from_inflight;
+	rte_vhost_get_vring_base_counter_from_inflight;
+	rte_vhost_set_vring_base_counter;
 };
lib/librte_vhost/vhost.c +387 -9

450 lines not on this page · raw message

lib/librte_vhost/vhost.h +32 -29

97 lines not on this page · raw message

lib/librte_vhost/vhost_user.c +436 -1

497 lines not on this page · raw message

lib/librte_vhost/vhost_user.h +12 -1
index 2a650fe4b..99a773910 100644
@@ -54,7 +54,9 @@ typedef enum VhostUserRequest {
 	VHOST_USER_POSTCOPY_ADVISE = 28,
 	VHOST_USER_POSTCOPY_LISTEN = 29,
 	VHOST_USER_POSTCOPY_END = 30,
-	VHOST_USER_MAX = 31
+	VHOST_USER_GET_INFLIGHT_FD = 31,
+	VHOST_USER_SET_INFLIGHT_FD = 32,
+	VHOST_USER_MAX = 33
 } VhostUserRequest;
 
 typedef enum VhostUserSlaveRequest {
@@ -112,6 +114,13 @@ typedef struct VhostUserVringArea {
 	uint64_t offset;
 } VhostUserVringArea;
 
+typedef struct VhostUserInflight {
+	uint64_t mmap_size;
+	uint64_t mmap_offset;
+	uint16_t num_queues;
+	uint16_t queue_size;
+} VhostUserInflight;
+
 typedef struct VhostUserMsg {
 	union {
 		uint32_t master; /* a VhostUserRequest value */
@@ -131,6 +140,7 @@ typedef struct VhostUserMsg {
 		struct vhost_vring_addr addr;
 		VhostUserMemory memory;
 		VhostUserLog    log;
+		VhostUserInflight inflight;
 		struct vhost_iotlb_msg iotlb;
 		VhostUserCryptoSessionParam crypto_session;
 		VhostUserVringArea area;
@@ -148,6 +158,7 @@ typedef struct VhostUserMsg {
 /* vhost_user.c */
 int vhost_user_msg_handler(int vid, int fd);
 int vhost_user_iotlb_miss(struct virtio_net *dev, uint64_t iova, uint8_t perm);
+void *inflight_mem_alloc(const char *name, size_t size, int *fd);
 
 /* socket.c */
 int read_fd_message(int sockfd, char *buf, int buflen, int *fds, int max_fds,
Signature · 1 line
2.17.2
#3 lore raw
Quoted 8 lines · JinYu

This patch introduces two new messages VHOST_USER_GET_INFLIGHT_FD and VHOST_USER_SET_INFLIGHT_FD to support transferring a shared buffer between qemu and backend.

Firstly, qemu uses VHOST_USER_GET_INFLIGHT_FD to get the shared buffer from backend. Then qemu should send it back through VHOST_USER_SET_INFLIGHT_FD each time we start vhost-user.

Quoted 7 lines

This shared buffer is used to process inflight I/O when backend reconnect.

s/JinYu/Jin Yu/

Quoted 6 lines

---
v1 - specify the APIs are split-ring only
v2 - fix APIs and judge split or packed
v3 - Add rte_vhost_ prefix and fix one issue.
v4 - add the packed ring support
v5 - revise get_vring_base func depend on Tiwei's suggestion

Quoted 8 lines
---
 lib/librte_vhost/rte_vhost.h           | 255 ++++++++++++++-
 lib/librte_vhost/rte_vhost_version.map |  12 +
 lib/librte_vhost/vhost.c               | 396 +++++++++++++++++++++-
 lib/librte_vhost/vhost.h               |  61 ++--
 lib/librte_vhost/vhost_user.c          | 437 ++++++++++++++++++++++++-
 lib/librte_vhost/vhost_user.h          |  13 +-
 6 files changed, 1128 insertions(+), 46 deletions(-)

This patch is too big, please divide it into small patches. E.g. rte_vhost_vq_is_packed() can be introduced in a separate patch.

Quoted 30 lines
lib/librte_vhost/rte_vhost.h +7 -0
index 0226b3eff..3f01429b1 100644
@@ -11,6 +11,7 @@
  */
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/eventfd.h>
 
 #include <rte_memory.h>
@@ -71,6 +72,10 @@ extern "C" {
 #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11
 #endif
 
+#ifndef VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
+#define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12
+#endif
+
 /** Indicate whether protocol features negotiation is supported. */
 #ifndef VHOST_USER_F_PROTOCOL_FEATURES
 #define VHOST_USER_F_PROTOCOL_FEATURES	30
@@ -98,10 +103,92 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[];
 };
 
+struct inflight_desc_packed {
+	uint8_t inflight;

lib/librte_vhost/rte_vhost.h struct rte_vhost_memory { · line 117

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +10 -0
+	uint8_t padding;
+	uint16_t next;
+	uint16_t last;
+	uint16_t num;
+	uint64_t counter;
+	uint16_t id;
+	uint16_t flags;
+	uint32_t len;
+	uint64_t addr;
+};

Why struct inflight_desc_split doesn't have to be part of vhost API but struct inflight_desc_packed has to be?

Quoted 18 lines
lib/librte_vhost/rte_vhost.h +18 -0
+
+struct inflight_info_packed {
+	uint64_t features;
+	uint16_t version;
+	uint16_t desc_num;
+	uint16_t free_head;
+	uint16_t old_free_head;
+	uint16_t used_idx;
+	uint16_t old_used_idx;
+	uint8_t used_wrap_counter;
+	uint8_t old_used_wrap_counter;
+	uint8_t padding[7];
+	struct inflight_desc_packed desc[0];
+};
+
+struct rte_vhost_resubmit_desc {
+	uint16_t index;
+	uint64_t counter;

lib/librte_vhost/rte_vhost.h struct rte_vhost_memory { · line 145

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +10 -0
+};
+
+struct rte_vhost_resubmit_info {
+	struct rte_vhost_resubmit_desc	*resubmit_list;
+	uint16_t resubmit_num;
+};
+
+struct rte_vhost_ring_inflight {
+	union {
+		struct inflight_info_split *inflight_split;

struct inflight_info_split is used but not declared.

Quoted 5 lines
lib/librte_vhost/rte_vhost.h +5 -0
+		struct inflight_info_packed *inflight_packed;
+	};
+
+	struct rte_vhost_resubmit_info *resubmit_inflight;
+};

lib/librte_vhost/rte_vhost.h struct rte_vhost_memory { · line 160

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +10 -0
+
+/*
+ * Declare below packed ring defines unconditionally
+ * as Kernel header might use different names.
+ */
+#ifndef VIRTIO_F_RING_PACKED
+#define VIRTIO_F_RING_PACKED 34
+
+#define VRING_DESC_F_AVAIL	(1ULL << 7)
+#define VRING_DESC_F_USED	(1ULL << 15)

You shouldn't put above macros under VIRTIO_F_RING_PACKED as kernel doesn't define them. And the build will be broken when kernel defines VIRTIO_F_RING_PACKED.

Besides, it seems not a good idea to make them parts of vhost API.

Quoted 5 lines
lib/librte_vhost/rte_vhost.h +5 -0
+
+struct vring_packed_desc {
+	uint64_t addr;
+	uint32_t len;
+	uint16_t id;

lib/librte_vhost/rte_vhost.h struct rte_vhost_memory { · line 175

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +10 -0
+	uint16_t flags;
+};
+
+#define VRING_EVENT_F_ENABLE 0x0
+#define VRING_EVENT_F_DISABLE 0x1
+#define VRING_EVENT_F_DESC 0x2
+struct vring_packed_desc_event {
+	uint16_t off_wrap;
+	uint16_t flags;
+};

You just need to declare instead of defining vring_packed_desc/vring_packed_desc_event in vhost header.

Quoted 23 lines
lib/librte_vhost/rte_vhost.h +15 -3
+#endif
+
 struct rte_vhost_vring {
-	struct vring_desc	*desc;
-	struct vring_avail	*avail;
-	struct vring_used	*used;
+	union {
+		struct vring_desc	*desc;
+		struct vring_packed_desc *desc_packed;
+	};
+	union {
+		struct vring_avail	*avail;
+		struct vring_packed_desc_event *driver_event;
+	};
+	union {
+		struct vring_used	*used;
+		struct vring_packed_desc_event *device_event;
+	};
+
 	uint64_t		log_guest_addr;
 
 	/** Deprecated, use rte_vhost_vring_call() instead. */

lib/librte_vhost/rte_vhost.h uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id, · line 699

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +7 -0
@@ -603,6 +690,33 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
  */
 int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
 
+/**
+ * Get vq is packed
+ *
+ * @param vid
+ *  vhost device ID
+ * @return
+ *  0 on success, -1 on failure

Return value should be true or false.

Quoted 7 lines
lib/librte_vhost/rte_vhost.h +7 -0
+ */
+int __rte_experimental
+rte_vhost_vq_is_packed(int vid);
+
+/**
+ * Get guest inflight vring info, including inflight ring and resubmit list.
+ *

lib/librte_vhost/rte_vhost.h uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id, · line 716

Quoted 10 lines
lib/librte_vhost/rte_vhost.h +10 -0
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested inflight vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental

You should put the __rte_experimental tag at the beginning. See this for more details:
http://git.dpdk.org/dpdk/commit/lib/librte_vhost?id=18218713bf4248c4c6b97a12231e7d59b8a86865

Quoted 16 lines
lib/librte_vhost/rte_vhost.h +4 -1
+rte_vhost_get_vhost_ring_inflight(int vid, uint16_t vring_idx,
+	struct rte_vhost_ring_inflight *vring);
+
 /**
  * Get guest vring info, including the vring address, vring size, etc.
  *
@@ -616,7 +730,7 @@ int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
  *  0 on success, -1 on failure
  */
 int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
-			      struct rte_vhost_vring *vring);
+	struct rte_vhost_vring *vring);
 
 /**
  * Notify the guest that used descriptors have been added to the vring.  This

lib/librte_vhost/rte_vhost.h int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx, · line 749

Quoted 5 lines
lib/librte_vhost/rte_vhost.h +2 -0
@@ -631,6 +745,112 @@ int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
  */
 int rte_vhost_vring_call(int vid, uint16_t vring_idx);
 
+/**
+ * set split inflight descriptor.

Please capitalize the first letter consistently.

Quoted 108 lines
lib/librte_vhost/rte_vhost.h +104 -0
+ *
+ * This function save descriptors that has been comsumed in available
+ * ring
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_inflight_desc_split(int vid, uint16_t vring_idx,
+	uint16_t idx);
+
+/**
+ * set packed inflight descriptor and get corresponding inflight entry
+ *
+ * This function save descriptors that has been comsumed
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_inflight_desc_packed(int vid, uint16_t vring_idx,
+	uint16_t head, uint16_t last, uint16_t *inflight_entry);
+
+/**
+ * save the head of list that the last batch of used descriptors.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  descriptor entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_last_inflight_io_split(int vid,
+	uint16_t vring_idx, uint16_t idx);
+
+/**
+ * update the inflight free_head, used_idx and used_wrap_counter.
+ *
+ * This function will update status first before updating descriptors
+ * to used
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_set_last_inflight_io_packed(int vid,
+	uint16_t vring_idx, uint16_t head);
+
+/**
+ * clear the split inflight status.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param last_used_idx
+ *  last used idx of used ring
+ * @param idx
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_clr_inflight_desc_split(int vid, uint16_t vring_idx,
+	uint16_t last_used_idx, uint16_t idx);
+
+/**
+ * clear the packed inflight status.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param head
+ *  inflight entry index
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_clr_inflight_desc_packed(int vid, uint16_t vring_idx,
+	uint16_t head);
+
 /**
  * Get vhost RX queue avail count.
  *

lib/librte_vhost/rte_vhost.h uint32_t rte_vhost_rx_queue_count(int vid, uint16_t qid); · line 880

Quoted 6 lines
lib/librte_vhost/rte_vhost.h +2 -1
@@ -656,7 +876,8 @@ uint32_t rte_vhost_rx_queue_count(int vid, uint16_t qid);
  *  0 on success, -1 on failure
  */
 int __rte_experimental
-rte_vhost_get_log_base(int vid, uint64_t *log_base, uint64_t *log_size);
+rte_vhost_get_log_base(int vid, uint64_t *log_base,
+	uint64_t *log_size);

This change isn't necessary.

Quoted 80 lines
lib/librte_vhost/rte_vhost.h +23 -1
 /**
  * Get last_avail/used_idx of the vhost virtqueue
@@ -676,6 +897,28 @@ int __rte_experimental
 rte_vhost_get_vring_base(int vid, uint16_t queue_id,
 		uint16_t *last_avail_idx, uint16_t *last_used_idx);
 
+/**
+ * Get last_avail/last_used of the vhost virtqueue
+ *
+ * This function is designed for the reconnection and it's specific for
+ * the packed ring as we can get the two parameters from the inflight
+ * queueregion
+ *
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  vhost queue index
+ * @param last_avail_idx
+ *  vhost last_avail_idx to get
+ * @param last_used_idx
+ *  vhost last_used_idx to get
+ * @return
+ *  0 on success, -1 on failure
+ */
+int __rte_experimental
+rte_vhost_get_vring_base_from_inflight(int vid,
+	uint16_t queue_id, uint16_t *last_avail_idx, uint16_t *last_used_idx);
+
 /**
  * Set last_avail/used_idx of the vhost virtqueue
  *
@@ -692,7 +935,7 @@ rte_vhost_get_vring_base(int vid, uint16_t queue_id,
  */
 int __rte_experimental
 rte_vhost_set_vring_base(int vid, uint16_t queue_id,
-		uint16_t last_avail_idx, uint16_t last_used_idx);
+	uint16_t last_avail_idx, uint16_t last_used_idx);
 
 /**
  * Register external message handling callbacks
lib/librte_vhost/rte_vhost_version.map +16 -2
index 5f1d4a75c..99f1134ea 100644
@@ -87,4 +87,16 @@ EXPERIMENTAL {
 	rte_vdpa_relay_vring_used;
 	rte_vhost_extern_callback_register;
 	rte_vhost_driver_set_protocol_features;
+	rte_vhost_set_inflight_desc_split;
+	rte_vhost_clr_inflight_desc_split;
+	rte_vhost_set_last_inflight_io_split;
+	rte_vhost_get_vhost_ring_inflight;
+	rte_vhost_vq_is_packed;
+	rte_vhost_set_inflight_desc_packed;
+	rte_vhost_clr_inflight_desc_packed;
+	rte_vhost_set_last_inflight_io_packed;
+	rte_vhost_get_vring_base_counter;
+	rte_vhost_get_vring_base_from_inflight;
+	rte_vhost_get_vring_base_counter_from_inflight;
+	rte_vhost_set_vring_base_counter;
 };
@@ -939,13 +1270,48 @@ int rte_vhost_get_log_base(int vid, uint64_t *log_base,
 int rte_vhost_get_vring_base(int vid, uint16_t queue_id,
 		uint16_t *last_avail_idx, uint16_t *last_used_idx)
 {
+	struct vhost_virtqueue *vq;
 	struct virtio_net *dev = get_device(vid);
 
 	if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
 		return -1;
 
-	*last_avail_idx = dev->virtqueue[queue_id]->last_avail_idx;
-	*last_used_idx = dev->virtqueue[queue_id]->last_used_idx;
+	vq = dev->virtqueue[queue_id];
+	if (!vq)
+		return -1;

lib/librte_vhost/rte_vhost_version.map int rte_vhost_get_log_base(int vid, uint64_t *log_base, · line 1291

Quoted 10 lines
lib/librte_vhost/rte_vhost_version.map +10 -0
+
+	if (vq_is_packed(dev)) {
+		*last_avail_idx = (vq->avail_wrap_counter << 15) |
+					vq->last_avail_idx;
+		*last_used_idx = (vq->used_wrap_counter << 15) |
+					vq->last_used_idx;
+	} else {
+		*last_avail_idx = vq->last_avail_idx;
+		*last_used_idx = vq->last_used_idx;
+	}

This should be a fix. Without this change, the user of this API can't use packed ring properly.

Please do this in a separate patch, add a fixes line and Cc stable.

Quoted 41 lines
lib/librte_vhost/rte_vhost_version.map +27 -2
+
+	return 0;
+}
+
+int rte_vhost_get_vring_base_from_inflight(int vid,
+	uint16_t queue_id, uint16_t *last_avail_idx, uint16_t *last_used_idx)
+{
+	struct inflight_info_packed *inflight_info;
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
+		return -1;
+
+	if (!vq_is_packed(dev))
+		return -1;
+
+	inflight_info = dev->virtqueue[queue_id]->inflight_packed;
+	if (!inflight_info)
+		return -1;
+
+	*last_avail_idx = (inflight_info->old_used_wrap_counter << 15) |
+				inflight_info->old_used_idx;
+	*last_used_idx = *last_avail_idx;
 
 	return 0;
 }
@@ -953,13 +1319,25 @@ int rte_vhost_get_vring_base(int vid, uint16_t queue_id,
 int rte_vhost_set_vring_base(int vid, uint16_t queue_id,
 		uint16_t last_avail_idx, uint16_t last_used_idx)
 {
+	struct vhost_virtqueue *vq;
 	struct virtio_net *dev = get_device(vid);
 
 	if (!dev)
 		return -1;
 
-	dev->virtqueue[queue_id]->last_avail_idx = last_avail_idx;
-	dev->virtqueue[queue_id]->last_used_idx = last_used_idx;
+	vq = dev->virtqueue[queue_id];
+	if (!vq)
+		return -1;

lib/librte_vhost/rte_vhost_version.map int rte_vhost_get_vring_base(int vid, uint16_t queue_id, · line 1340

Quoted 10 lines
lib/librte_vhost/rte_vhost_version.map +10 -0
+
+	if (vq_is_packed(dev)) {
+		vq->last_avail_idx = last_avail_idx & 0x7fff;
+		vq->avail_wrap_counter = !!(last_avail_idx & (1 << 15));
+		vq->last_used_idx = last_used_idx & 0x7fff;
+		vq->used_wrap_counter = !!(last_used_idx & (1 << 15));
+	} else {
+		vq->last_avail_idx = last_avail_idx;
+		vq->last_used_idx = last_used_idx;
+	}

Ditto.

Quoted 27 lines
lib/librte_vhost/rte_vhost_version.map +0 -0
 	return 0;
 }
lib/librte_vhost/vhost.h +16 -0
index 884befa85..e9d0b983d 100644
@@ -88,6 +88,22 @@ struct vring_used_elem_packed {
 	uint32_t count;
 };
 
+struct inflight_desc_split {
+	uint8_t		inflight;
+	uint8_t		padding[5];
+	uint16_t	next;
+	uint64_t	counter;
+};
+
+struct inflight_info_split {
+	uint64_t		features;
+	uint16_t		version;
+	uint16_t		desc_num;
+	uint16_t		last_inflight_io;
+	uint16_t		used_idx;
+	struct inflight_desc_split desc[0];
+};
+
author
#4 lore raw

PATCH v5 2/2 vhost: add vhost-user-blk example which support inflight

In reply to JinYu

A vhost-user-blk example that support inflight feature. It uses the new APIs that introduced in the first patch, so It can show how there APIs work to support inflight feature.

---
V1 - add the case.
V2 - add the rte_vhost prefix.
V3 - add packed ring support

---
 examples/vhost_blk/Makefile           |   67 ++
 examples/vhost_blk/blk.c              |  125 +++
 examples/vhost_blk/blk_spec.h         |   95 ++
 examples/vhost_blk/meson.build        |   20 +
 examples/vhost_blk/vhost_blk.c        | 1313 +++++++++++++++++++++++++
 examples/vhost_blk/vhost_blk.h        |  116 +++
 examples/vhost_blk/vhost_blk_compat.c |  195 ++++
 7 files changed, 1931 insertions(+)
 create mode 100644 examples/vhost_blk/Makefile
 create mode 100644 examples/vhost_blk/blk.c
 create mode 100644 examples/vhost_blk/blk_spec.h
 create mode 100644 examples/vhost_blk/meson.build
 create mode 100644 examples/vhost_blk/vhost_blk.c
 create mode 100644 examples/vhost_blk/vhost_blk.h
 create mode 100644 examples/vhost_blk/vhost_blk_compat.c
examples/vhost_blk/Makefile new file +67 -0
new file mode 100644
index 000000000..52e9befd8
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2017 Intel Corporation
+
+# binary name
+APP = vhost-blk
+
+# all source are stored in SRCS-y
+SRCS-y := blk.c vhost_blk.c vhost_blk_compat.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+	ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+	ln -sf $(APP)-static build/$(APP)
+
+CFLAGS += -D_FILE_OFFSET_BITS=64
+LDFLAGS += -pthread
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+	@mkdir -p $@
+
+.PHONY: clean
+clean:
+	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+	test -d build && rmdir -p build || true
+
+else # Build using legacy build system
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, detect a build directory, by looking for a path with a .config
+RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config)))))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUX),y)
+$(info This application can only operate in a linux environment, \
+please change the definition of the RTE_TARGET environment variable)
+all:
+else
+
+CFLAGS += -D_FILE_OFFSET_BITS=64
+CFLAGS += -O2
+#CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
+endif
examples/vhost_blk/blk.c new file +125 -0

125 lines not on this page · raw message

examples/vhost_blk/blk_spec.h new file +95 -0

95 lines not on this page · raw message

examples/vhost_blk/meson.build new file +20 -0
new file mode 100644
index 000000000..028aa4f62
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+if not is_linux
+	build = false
+endif
+
+if not cc.has_header('linux/virtio_blk.h')
+	build = false
+endif
+
+deps += 'vhost'
+sources = files(
+	'blk.c', 'vhost_blk.c', 'vhost_blk_compat.c'
+)
examples/vhost_blk/vhost_blk.c new file +1313 -0

1,313 lines not on this page · raw message

examples/vhost_blk/vhost_blk.h new file +116 -0

116 lines not on this page · raw message

examples/vhost_blk/vhost_blk_compat.c new file +195 -0

195 lines not on this page · raw message

Signature · 1 line
2.17.2