Re: [dpdk-dev] [PATCH 25/40] net/virtio: add Virtio-user features ops
From: Adrian Moreno <hidden>
Date: 2021-01-13 13:43:28
Hi Chenbo On 1/6/21 12:54 PM, Xia, Chenbo wrote:
Hi Maxime,quoted
-----Original Message----- From: Maxime Coquelin <redacted> Sent: Monday, December 21, 2020 5:14 AM To: dev@dpdk.org; Xia, Chenbo <redacted>; olivier.matz@6wind.com; amorenoz@redhat.com; david.marchand@redhat.com Cc: Maxime Coquelin <redacted> Subject: [PATCH 25/40] net/virtio: add Virtio-user features ops This patch introduce new callbacks for gettings/introduce/introducesquoted
and setting Virtio features, and implements them for the different backend types. Signed-off-by: Maxime Coquelin <redacted> --- drivers/net/virtio/virtio_user/vhost.h | 2 + drivers/net/virtio/virtio_user/vhost_kernel.c | 150 +++++++++--------- .../net/virtio/virtio_user/vhost_kernel_tap.c | 23 +++ .../net/virtio/virtio_user/vhost_kernel_tap.h | 1 + drivers/net/virtio/virtio_user/vhost_user.c | 63 +++++++- drivers/net/virtio/virtio_user/vhost_vdpa.c | 38 +++-- .../net/virtio/virtio_user/virtio_user_dev.c | 5 +- drivers/net/virtio/virtio_user_ethdev.c | 3 +- 8 files changed, 188 insertions(+), 97 deletions(-)diff --git a/drivers/net/virtio/virtio_user/vhost.hb/drivers/net/virtio/virtio_user/vhost.h index 8e819ecfb8..16978e27ed 100644--- a/drivers/net/virtio/virtio_user/vhost.h +++ b/drivers/net/virtio/virtio_user/vhost.h@@ -102,6 +102,8 @@ struct virtio_user_dev; struct virtio_user_backend_ops { int (*setup)(struct virtio_user_dev *dev); int (*set_owner)(struct virtio_user_dev *dev); + int (*get_features)(struct virtio_user_dev *dev, uint64_t *features); + int (*set_features)(struct virtio_user_dev *dev, uint64_t features); int (*send_request)(struct virtio_user_dev *dev, enum vhost_user_request req, void *arg);diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.cb/drivers/net/virtio/virtio_user/vhost_kernel.c index b79dcad179..f44df8ef1f 100644--- a/drivers/net/virtio/virtio_user/vhost_kernel.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel.c@@ -38,6 +38,28 @@ struct vhost_memory_kernel { #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file) #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, structvhost_vring_file) +/* with below features, vhost kernel does not need to do the checksum and TSO, + * these info will be passed to virtio_user through virtio net header. + */ +#define VHOST_KERNEL_GUEST_OFFLOADS_MASK \ + ((1ULL << VIRTIO_NET_F_GUEST_CSUM) | \ + (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ + (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ + (1ULL << VIRTIO_NET_F_GUEST_UFO)) + +/* with below features, when flows from virtio_user to vhost kernel + * (1) if flows goes up through the kernel networking stack, it does not need + * to verify checksum, which can save CPU cycles; + * (2) if flows goes through a Linux bridge and outside from an interface + * (kernel driver), checksum and TSO will be done by GSO in kernel or even + * offloaded into real physical device. + */ +#define VHOST_KERNEL_HOST_OFFLOADS_MASK \ + ((1ULL << VIRTIO_NET_F_HOST_TSO4) | \ + (1ULL << VIRTIO_NET_F_HOST_TSO6) | \ + (1ULL << VIRTIO_NET_F_CSUM)) + static uint64_t max_regions = 64; static void@@ -77,10 +99,57 @@ vhost_kernel_set_owner(struct virtio_user_dev *dev) return vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_OWNER, NULL); } +static int +vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) +{ + int ret; + unsigned int tap_features; + + ret = vhost_kernel_ioctl(dev->vhostfds[0], VHOST_GET_FEATURES, features); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to get features"); + return -1; + } + + ret = tap_support_features(&tap_features); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to get TAP features)");should delete ')' after 'features'?quoted
+ return -1; + } + + /* with tap as the backend, all these features are supported + * but not claimed by vhost-net, so we add them back when + * reporting to upper layer. + */<snip>quoted
.dma_map = vhost_vdpa_dma_map,diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.cb/drivers/net/virtio/virtio_user/virtio_user_dev.c index f8e4581951..0a85d058a8 100644--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c@@ -141,7 +141,7 @@ virtio_user_dev_set_features(struct virtio_user_dev *dev) /* Strip VIRTIO_NET_F_CTRL_VQ, as devices do not really need to know */ features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ); features &= ~(1ull << VIRTIO_NET_F_STATUS); - ret = dev->ops->send_request(dev, VHOST_USER_SET_FEATURES, &features); + ret = dev->ops->set_features(dev, features);I noticed that virtio_user_dev_set_features is called by virtio_user_set_status. The former may fail but the latter will ignore the failure. So this will happen: setting features already failed but virtio-user still continue to do things. IMHO, this is not very good (similar things may happen for virtio_user_start_device). What do you think?
You're right. Although set_status(features_ok) should be followed by get_status() to check if device has set feature_ok bit, the problem is that set_status is called on device initialization, which would happen even when the vhost backed is not yet connected (server-mode). Failing there would tear down the ethdev which would make the future "hotplug" fail. Hopefully this will all be fixed by Maxime's refactoring :) So +1 to reconsider improving error propagation here.
Thanks, Chenboquoted
if (ret < 0) goto error; PMD_DRV_LOG(INFO, "set features: %" PRIx64, features);@@ -488,8 +488,7 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char*path, int queues, return -1; } - if (dev->ops->send_request(dev, VHOST_USER_GET_FEATURES, - &dev->device_features) < 0) { + if (dev->ops->get_features(dev, &dev->device_features) < 0) { PMD_INIT_LOG(ERR, "get_features failed: %s", strerror(errno)); return -1;diff --git a/drivers/net/virtio/virtio_user_ethdev.cb/drivers/net/virtio/virtio_user_ethdev.c index 283f5c7a36..4d2635c8aa 100644--- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c@@ -85,8 +85,7 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev) virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); - if (dev->ops->send_request(dev, VHOST_USER_GET_FEATURES, - &dev->device_features) < 0) { + if (dev->ops->get_features(dev, &dev->device_features) < 0) { PMD_INIT_LOG(ERR, "get_features failed: %s", strerror(errno)); return -1; --2.29.2
-- Adrián Moreno