From patchwork Thu Feb 28 15:31:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Coquelin X-Patchwork-Id: 50643 X-Patchwork-Delegate: maxime.coquelin@redhat.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 129324C8D; Thu, 28 Feb 2019 16:31:48 +0100 (CET) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by dpdk.org (Postfix) with ESMTP id 040D74C8D for ; Thu, 28 Feb 2019 16:31:45 +0100 (CET) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 50C0B2A108C; Thu, 28 Feb 2019 15:31:45 +0000 (UTC) Received: from localhost.localdomain (ovpn-112-64.ams2.redhat.com [10.36.112.64]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7EE885C1B5; Thu, 28 Feb 2019 15:31:42 +0000 (UTC) From: Maxime Coquelin To: dev@dpdk.org, changpeng.liu@intel.com, tiwei.bie@intel.com, i.maximets@samsung.com Cc: Maxime Coquelin Date: Thu, 28 Feb 2019 16:31:33 +0100 Message-Id: <20190228153134.31865-2-maxime.coquelin@redhat.com> In-Reply-To: <20190228153134.31865-1-maxime.coquelin@redhat.com> References: <20190228153134.31865-1-maxime.coquelin@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 28 Feb 2019 15:31:45 +0000 (UTC) Subject: [dpdk-dev] [RFC v2 1/2] vhost: add API to set protocol features flags X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" rte_vhost_driver_set_protocol_features API is to be used by external backends to advertize vhost-user protocol features it supports. It has to be called after rte_vhost_driver_register() and before rte_vhost_driver_start(). Example of usage to advertize VHOST_USER_PROTOCOL_F_FOOBAR protocol feature: const char *path = "/tmp/vhost-user"; uint64_t protocol_features; rte_vhost_driver_register(path, 0); rte_vhost_driver_get_protocol_features(path, &protocol_features); protocol_features |= VHOST_USER_PROTOCOL_F_FOOBAR; rte_vhost_driver_set_protocol_features(path, protocol_features); rte_vhost_driver_start(path); Signed-off-by: Maxime Coquelin Tested-by: Darek Stojaczyk --- lib/librte_vhost/rte_vhost.h | 14 ++++++++++++++ lib/librte_vhost/rte_vhost_version.map | 1 + lib/librte_vhost/socket.c | 14 ++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h index 2753670a2..c9c392975 100644 --- a/lib/librte_vhost/rte_vhost.h +++ b/lib/librte_vhost/rte_vhost.h @@ -405,6 +405,20 @@ int rte_vhost_driver_disable_features(const char *path, uint64_t features); */ int rte_vhost_driver_get_features(const char *path, uint64_t *features); +/** + * Set the protocol feature bits before feature negotiation. + * + * @param path + * The vhost-user socket file path + * @param protocol_features + * Supported protocol features + * @return + * 0 on success, -1 on failure + */ +int __rte_experimental +rte_vhost_driver_set_protocol_features(const char *path, + uint64_t protocol_features); + /** * Get the protocol feature bits before feature negotiation. * diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map index 8a3bc19e0..5f1d4a75c 100644 --- a/lib/librte_vhost/rte_vhost_version.map +++ b/lib/librte_vhost/rte_vhost_version.map @@ -86,4 +86,5 @@ EXPERIMENTAL { rte_vhost_host_notifier_ctrl; rte_vdpa_relay_vring_used; rte_vhost_extern_callback_register; + rte_vhost_driver_set_protocol_features; }; diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c index 9883b0491..3da9de62c 100644 --- a/lib/librte_vhost/socket.c +++ b/lib/librte_vhost/socket.c @@ -707,6 +707,20 @@ rte_vhost_driver_get_features(const char *path, uint64_t *features) return ret; } +int +rte_vhost_driver_set_protocol_features(const char *path, + uint64_t protocol_features) +{ + struct vhost_user_socket *vsocket; + + pthread_mutex_lock(&vhost_user.mutex); + vsocket = find_vhost_user_socket(path); + if (vsocket) + vsocket->protocol_features = protocol_features; + pthread_mutex_unlock(&vhost_user.mutex); + return vsocket ? 0 : -1; +} + int rte_vhost_driver_get_protocol_features(const char *path, uint64_t *protocol_features) From patchwork Thu Feb 28 15:31:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Coquelin X-Patchwork-Id: 50644 X-Patchwork-Delegate: maxime.coquelin@redhat.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 55B324C93; Thu, 28 Feb 2019 16:31:52 +0100 (CET) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by dpdk.org (Postfix) with ESMTP id 50EC34C91 for ; Thu, 28 Feb 2019 16:31:50 +0100 (CET) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AE0B9308C775; Thu, 28 Feb 2019 15:31:49 +0000 (UTC) Received: from localhost.localdomain (ovpn-112-64.ams2.redhat.com [10.36.112.64]) by smtp.corp.redhat.com (Postfix) with ESMTP id A9B775C1B5; Thu, 28 Feb 2019 15:31:45 +0000 (UTC) From: Maxime Coquelin To: dev@dpdk.org, changpeng.liu@intel.com, tiwei.bie@intel.com, i.maximets@samsung.com Cc: Maxime Coquelin Date: Thu, 28 Feb 2019 16:31:34 +0100 Message-Id: <20190228153134.31865-3-maxime.coquelin@redhat.com> In-Reply-To: <20190228153134.31865-1-maxime.coquelin@redhat.com> References: <20190228153134.31865-1-maxime.coquelin@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Thu, 28 Feb 2019 15:31:49 +0000 (UTC) Subject: [dpdk-dev] [RFC v2 2/2] vhost: support requests only handled by external backend X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" External backends may have specific requests to handle, and so we don't want the vhost-user lib to handle these requests as errors. This patch also changes the experimental API by introducing RTE_VHOST_MSG_RESULT_NOT_HANDLED so that vhost-user lib can report an error if a message is handled neither by the vhost-user library nor by the external backend. The logic changes a bit so that if the callback returns with ERR, OK or REPLY, it is considered the message is handled by the external backend so it won't be handled by the vhost-user library. It is still possible for an external backend to listen to requests that have to be handled by the vhost-user library like SET_MEM_TABLE, but the callback have to return NOT_HANDLED in that case. Suggested-by: Ilya Maximets Signed-off-by: Maxime Coquelin Tested-by: Darek Stojaczyk --- lib/librte_vhost/rte_vhost.h | 16 +++++--- lib/librte_vhost/vhost_user.c | 75 +++++++++++++++++++++++------------ 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h index c9c392975..b1c5a0908 100644 --- a/lib/librte_vhost/rte_vhost.h +++ b/lib/librte_vhost/rte_vhost.h @@ -121,6 +121,8 @@ enum rte_vhost_msg_result { RTE_VHOST_MSG_RESULT_OK = 0, /* Message handling successful and reply prepared */ RTE_VHOST_MSG_RESULT_REPLY = 1, + /* Message not handled */ + RTE_VHOST_MSG_RESULT_NOT_HANDLED, }; /** @@ -135,11 +137,13 @@ enum rte_vhost_msg_result { * If the handler requires skipping the master message handling, this variable * shall be written 1, otherwise 0. * @return - * VH_RESULT_OK on success, VH_RESULT_REPLY on success with reply, - * VH_RESULT_ERR on failure + * RTE_VHOST_MSG_RESULT_OK on success, + * RTE_VHOST_MSG_RESULT_REPLY on success with reply, + * RTE_VHOST_MSG_RESULT_ERR on failure, + * RTE_VHOST_MSG_RESULT_NOT_HANDLED if message was not handled. */ typedef enum rte_vhost_msg_result (*rte_vhost_msg_pre_handle)(int vid, - void *msg, uint32_t *skip_master); + void *msg); /** * Function prototype for the vhost backend to handler specific vhost user @@ -150,8 +154,10 @@ typedef enum rte_vhost_msg_result (*rte_vhost_msg_pre_handle)(int vid, * @param msg * Message pointer. * @return - * VH_RESULT_OK on success, VH_RESULT_REPLY on success with reply, - * VH_RESULT_ERR on failure + * RTE_VHOST_MSG_RESULT_OK on success, + * RTE_VHOST_MSG_RESULT_REPLY on success with reply, + * RTE_VHOST_MSG_RESULT_ERR on failure, + * RTE_VHOST_MSG_RESULT_NOT_HANDLED if message was not handled. */ typedef enum rte_vhost_msg_result (*rte_vhost_msg_post_handle)(int vid, void *msg); diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 36c0c676d..ca9167f1d 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -1906,7 +1906,7 @@ vhost_user_msg_handler(int vid, int fd) int did = -1; int ret; int unlock_required = 0; - uint32_t skip_master = 0; + bool handled; int request; dev = get_device(vid); @@ -1924,27 +1924,29 @@ vhost_user_msg_handler(int vid, int fd) } ret = read_vhost_message(fd, &msg); - if (ret <= 0 || msg.request.master >= VHOST_USER_MAX) { + if (ret <= 0) { if (ret < 0) RTE_LOG(ERR, VHOST_CONFIG, "vhost read message failed\n"); - else if (ret == 0) + else RTE_LOG(INFO, VHOST_CONFIG, "vhost peer closed\n"); - else - RTE_LOG(ERR, VHOST_CONFIG, - "vhost read incorrect message\n"); return -1; } ret = 0; - if (msg.request.master != VHOST_USER_IOTLB_MSG) - RTE_LOG(INFO, VHOST_CONFIG, "read message %s\n", - vhost_message_str[msg.request.master]); - else - RTE_LOG(DEBUG, VHOST_CONFIG, "read message %s\n", - vhost_message_str[msg.request.master]); + request = msg.request.master; + if (request < VHOST_USER_MAX && vhost_message_str[request]) { + if (request != VHOST_USER_IOTLB_MSG) + RTE_LOG(INFO, VHOST_CONFIG, "read message %s\n", + vhost_message_str[request]); + else + RTE_LOG(DEBUG, VHOST_CONFIG, "read message %s\n", + vhost_message_str[request]); + } else { + RTE_LOG(INFO, VHOST_CONFIG, "External request %d\n", request); + } ret = vhost_user_check_and_alloc_queue_pair(dev, &msg); if (ret < 0) { @@ -1960,7 +1962,7 @@ vhost_user_msg_handler(int vid, int fd) * inactive, so it is safe. Otherwise taking the access_lock * would cause a dead lock. */ - switch (msg.request.master) { + switch (request) { case VHOST_USER_SET_FEATURES: case VHOST_USER_SET_PROTOCOL_FEATURES: case VHOST_USER_SET_OWNER: @@ -1985,19 +1987,23 @@ vhost_user_msg_handler(int vid, int fd) } + handled = false; if (dev->extern_ops.pre_msg_handle) { ret = (*dev->extern_ops.pre_msg_handle)(dev->vid, - (void *)&msg, &skip_master); - if (ret == RTE_VHOST_MSG_RESULT_ERR) - goto skip_to_reply; - else if (ret == RTE_VHOST_MSG_RESULT_REPLY) + (void *)&msg); + switch (ret) { + case RTE_VHOST_MSG_RESULT_REPLY: send_vhost_reply(fd, &msg); - - if (skip_master) + case RTE_VHOST_MSG_RESULT_ERR: + case RTE_VHOST_MSG_RESULT_OK: + handled = true; goto skip_to_post_handle; + case RTE_VHOST_MSG_RESULT_NOT_HANDLED: + default: + break; + } } - request = msg.request.master; if (request > VHOST_USER_NONE && request < VHOST_USER_MAX) { if (!vhost_message_handlers[request]) goto skip_to_post_handle; @@ -2008,17 +2014,22 @@ vhost_user_msg_handler(int vid, int fd) RTE_LOG(ERR, VHOST_CONFIG, "Processing %s failed.\n", vhost_message_str[request]); + handled = true; break; case RTE_VHOST_MSG_RESULT_OK: RTE_LOG(DEBUG, VHOST_CONFIG, "Processing %s succeeded.\n", vhost_message_str[request]); + handled = true; break; case RTE_VHOST_MSG_RESULT_REPLY: RTE_LOG(DEBUG, VHOST_CONFIG, "Processing %s succeeded and needs reply.\n", vhost_message_str[request]); send_vhost_reply(fd, &msg); + handled = true; + break; + default: break; } } else { @@ -2030,18 +2041,30 @@ vhost_user_msg_handler(int vid, int fd) skip_to_post_handle: if (ret != RTE_VHOST_MSG_RESULT_ERR && dev->extern_ops.post_msg_handle) { - ret = (*dev->extern_ops.post_msg_handle)( - dev->vid, (void *)&msg); - if (ret == RTE_VHOST_MSG_RESULT_ERR) - goto skip_to_reply; - else if (ret == RTE_VHOST_MSG_RESULT_REPLY) + ret = (*dev->extern_ops.post_msg_handle)(dev->vid, + (void *)&msg); + switch (ret) { + case RTE_VHOST_MSG_RESULT_REPLY: send_vhost_reply(fd, &msg); + case RTE_VHOST_MSG_RESULT_ERR: + case RTE_VHOST_MSG_RESULT_OK: + handled = true; + case RTE_VHOST_MSG_RESULT_NOT_HANDLED: + default: + break; + } } -skip_to_reply: if (unlock_required) vhost_user_unlock_all_queue_pairs(dev); + /* If message was not handled at this stage, treat it as an error */ + if (!handled) { + RTE_LOG(ERR, VHOST_CONFIG, + "vhost message (req: %d) was not handled.\n", request); + ret = RTE_VHOST_MSG_RESULT_ERR; + } + /* * If the request required a reply that was already sent, * this optional reply-ack won't be sent as the