*** vhost support inflight share memory protocol feature ***
A message that is not in the archive (sent off-list or not yet received): 20190715202858.49624
v4 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.
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 | 122 +++ examples/vhost_blk/blk_spec.h | 95 +++ examples/vhost_blk/meson.build | 20 + examples/vhost_blk/vhost_blk.c | 1054 ++++++++++++++++++++++++ examples/vhost_blk/vhost_blk.h | 114 +++ examples/vhost_blk/vhost_blk_compat.c | 193 +++++ lib/librte_vhost/rte_vhost.h | 301 ++++++- lib/librte_vhost/rte_vhost_version.map | 12 + lib/librte_vhost/vhost.c | 398 ++++++++- lib/librte_vhost/vhost.h | 54 +- lib/librte_vhost/vhost_user.c | 418 +++++++++- lib/librte_vhost/vhost_user.h | 13 +- 13 files changed, 2832 insertions(+), 29 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
PATCH v4 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
--- lib/librte_vhost/rte_vhost.h | 301 +++++++++++++++++- lib/librte_vhost/rte_vhost_version.map | 12 + lib/librte_vhost/vhost.c | 398 ++++++++++++++++++++++- lib/librte_vhost/vhost.h | 54 ++-- lib/librte_vhost/vhost_user.c | 418 ++++++++++++++++++++++++- lib/librte_vhost/vhost_user.h | 13 +- 6 files changed, 1167 insertions(+), 29 deletions(-)
lib/librte_vhost/rte_vhost.h +297 -4
@@ -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,85 @@ 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; +}; + +struct vring_packed_desc { +uint64_t addr; +uint32_t len; +uint16_t id; +uint16_t flags; +}; + +struct vring_split_desc { +uint64_t addr; +uint32_t len; +uint16_t flags; +uint16_t next; +}; + +struct vring_packed_desc_event { +uint16_t off_wrap; +uint16_t flags; +}; +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 +683,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 +723,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 +738,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. *
@@ -676,6 +889,68 @@ 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 avail_wrap_counter/used_wrap_counter of the vhost virtqueue +* +* @param vid +* vhost device ID +* @param queue_id +* vhost queue index +* @param avail_wrap_counter +* vhost avail_wrap_counter to get +* @param used_wrap_counter +* vhost used_wrap_counter to get +* @return +* 0 on success, -1 on failure +*/ +int __rte_experimental +rte_vhost_get_vring_base_counter (int vid,uint16_t queue_id, +bool *avail_wrap_counter,bool *used_wrap_counter); + +/** +* 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); + +/** +* Get avail_wrap_counter/used_wrap_counter 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 avail_wrap_counter +* vhost avail_wrap_counter to get +* @param used_wrap_counter +* vhost used_wrap_counter to get +* @return +* 0 on success, -1 on failure +*/ +int __rte_experimental +rte_vhost_get_vring_base_counter_from_inflight (int vid, +uint16_t queue_id,bool *avail_wrap_counter,bool *used_wrap_counter); +/** * Set last_avail/used_idx of the vhost virtqueue *
@@ -694,6 +969,24 @@ int __rte_experimental rte_vhost_set_vring_base(int vid, uint16_t queue_id, uint16_t last_avail_idx, uint16_t last_used_idx); +/** +* Set avail_wrap_counter/used_wrap_counter of the vhost virtqueue +* +* @param vid +* vhost device ID +* @param queue_id +* vhost queue index +* @param avail_wrap_counter +* avail_wrap_counter to set +* @param used_wrap_counter +* used_wrap_counter to set +* @return +* 0 on success, -1 on failure +*/ +int __rte_experimental +rte_vhost_set_vring_base_counter (int vid,uint16_t queue_id, +bool avail_wrap_counter,bool used_wrap_counter); +/** * Register external message handling callbacks *
lib/librte_vhost/rte_vhost_version.map +12 -0
@@ -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 +393 -5
442 lines not on this page · raw message
lib/librte_vhost/vhost.h +36 -18
96 lines not on this page · raw message
lib/librte_vhost/vhost_user.c +417 -1
478 lines not on this page · raw message
lib/librte_vhost/vhost_user.h +12 -1
@@ -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
PATCH v4 2/2 vhost: Add vhost-user-blk example which support inflight
In reply to JinYuA 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 | 122 +++ examples/vhost_blk/blk_spec.h | 95 +++ examples/vhost_blk/meson.build | 20 + examples/vhost_blk/vhost_blk.c | 1054 +++++++++++++++++++++++++ examples/vhost_blk/vhost_blk.h | 114 +++ examples/vhost_blk/vhost_blk_compat.c | 193 +++++ 7 files changed, 1665 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
@@ -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 +122 -0
122 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
@@ -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 +1054 -0
1,054 lines not on this page · raw message
examples/vhost_blk/vhost_blk.h new file +114 -0
114 lines not on this page · raw message
examples/vhost_blk/vhost_blk_compat.c new file +193 -0
193 lines not on this page · raw message
Signature · 1 line
2.17.2